summaryrefslogtreecommitdiff
path: root/internal/array.h
diff options
context:
space:
mode:
Diffstat (limited to 'internal/array.h')
-rw-r--r--internal/array.h84
1 files changed, 61 insertions, 23 deletions
diff --git a/internal/array.h b/internal/array.h
index 97b707f271..a2cd06f2e3 100644
--- a/internal/array.h
+++ b/internal/array.h
@@ -1,7 +1,6 @@
#ifndef INTERNAL_ARRAY_H /*-*-C-*-vi:se ft=c:*/
#define INTERNAL_ARRAY_H
/**
- * @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
@@ -19,29 +18,31 @@
# define ARRAY_DEBUG (0+RUBY_DEBUG)
#endif
-#define RARRAY_PTR_IN_USE_FLAG FL_USER14
+#define RARRAY_SHARED_FLAG ELTS_SHARED
+#define RARRAY_SHARED_ROOT_FLAG FL_USER12
+#define RARRAY_PTR_IN_USE_FLAG FL_USER14
/* array.c */
+VALUE rb_ary_hash_values(long len, const VALUE *elements);
VALUE rb_ary_last(int, const VALUE *, VALUE);
void rb_ary_set_len(VALUE, long);
void rb_ary_delete_same(VALUE, VALUE);
-VALUE rb_ary_tmp_new_fill(long capa);
+VALUE rb_ary_hidden_new_fill(long capa);
VALUE rb_ary_at(VALUE, VALUE);
size_t rb_ary_memsize(VALUE);
VALUE rb_to_array_type(VALUE obj);
VALUE rb_to_array(VALUE obj);
void rb_ary_cancel_sharing(VALUE ary);
+size_t rb_ary_size_as_embedded(VALUE ary);
+void rb_ary_make_embedded(VALUE ary);
+bool rb_ary_embeddable_p(VALUE ary);
+VALUE rb_ary_diff(VALUE ary1, VALUE ary2);
+VALUE rb_ary_compact_bang(VALUE ary);
+RUBY_EXTERN VALUE rb_cArray_empty_frozen;
static inline VALUE rb_ary_entry_internal(VALUE ary, long offset);
static inline bool ARY_PTR_USING_P(VALUE ary);
-static inline void RARY_TRANSIENT_SET(VALUE ary);
-static inline void RARY_TRANSIENT_UNSET(VALUE ary);
-RUBY_SYMBOL_EXPORT_BEGIN
-/* array.c (export) */
-RUBY_SYMBOL_EXPORT_END
-
-MJIT_SYMBOL_EXPORT_BEGIN
VALUE rb_ary_tmp_new_from_values(VALUE, long, const VALUE *);
VALUE rb_check_to_array(VALUE ary);
VALUE rb_ary_behead(VALUE, long);
@@ -49,13 +50,13 @@ VALUE rb_ary_aref1(VALUE ary, VALUE i);
struct rb_execution_context_struct;
VALUE rb_ec_ary_new_from_values(struct rb_execution_context_struct *ec, long n, const VALUE *elts);
-MJIT_SYMBOL_EXPORT_END
+// YJIT needs this function to never allocate and never raise
static inline VALUE
rb_ary_entry_internal(VALUE ary, long offset)
{
long len = RARRAY_LEN(ary);
- const VALUE *ptr = RARRAY_CONST_PTR_TRANSIENT(ary);
+ const VALUE *ptr = RARRAY_CONST_PTR(ary);
if (len == 0) return Qnil;
if (offset < 0) {
offset += len;
@@ -73,20 +74,48 @@ ARY_PTR_USING_P(VALUE ary)
return FL_TEST_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
}
-static inline void
-RARY_TRANSIENT_SET(VALUE ary)
+RBIMPL_ATTR_MAYBE_UNUSED()
+static inline int
+ary_should_not_be_shared_and_embedded(VALUE ary)
{
-#if USE_TRANSIENT_HEAP
- FL_SET_RAW(ary, RARRAY_TRANSIENT_FLAG);
-#endif
+ return !FL_ALL_RAW(ary, RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG);
}
-static inline void
-RARY_TRANSIENT_UNSET(VALUE ary)
+static inline bool
+ARY_SHARED_P(VALUE ary)
{
-#if USE_TRANSIENT_HEAP
- FL_UNSET_RAW(ary, RARRAY_TRANSIENT_FLAG);
-#endif
+ assert(RB_TYPE_P(ary, T_ARRAY));
+ assert(ary_should_not_be_shared_and_embedded(ary));
+ return FL_TEST_RAW(ary, RARRAY_SHARED_FLAG);
+}
+
+static inline bool
+ARY_EMBED_P(VALUE ary)
+{
+ assert(RB_TYPE_P(ary, T_ARRAY));
+ assert(ary_should_not_be_shared_and_embedded(ary));
+ return FL_TEST_RAW(ary, RARRAY_EMBED_FLAG);
+}
+
+static inline VALUE
+ARY_SHARED_ROOT(VALUE ary)
+{
+ assert(ARY_SHARED_P(ary));
+ return RARRAY(ary)->as.heap.aux.shared_root;
+}
+
+static inline bool
+ARY_SHARED_ROOT_P(VALUE ary)
+{
+ assert(RB_TYPE_P(ary, T_ARRAY));
+ return FL_TEST_RAW(ary, RARRAY_SHARED_ROOT_FLAG);
+}
+
+static inline long
+ARY_SHARED_ROOT_REFCNT(VALUE ary)
+{
+ assert(ARY_SHARED_ROOT_P(ary));
+ return RARRAY(ary)->as.heap.aux.capa;
}
#undef rb_ary_new_from_args
@@ -109,9 +138,18 @@ RBIMPL_ATTR_ARTIFICIAL()
static inline VALUE
RARRAY_AREF(VALUE ary, long i)
{
+ VALUE val;
RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
- return RARRAY_CONST_PTR_TRANSIENT(ary)[i];
+ RUBY_ASSERT(i < RARRAY_LEN(ary));
+
+ RBIMPL_WARNING_PUSH();
+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ == 13
+ RBIMPL_WARNING_IGNORED(-Warray-bounds);
+#endif
+ val = RARRAY_CONST_PTR(ary)[i];
+ RBIMPL_WARNING_POP();
+ return val;
}
#endif /* INTERNAL_ARRAY_H */
-rw-r--r--ext/-test-/bignum/bigzero.c26
-rw-r--r--ext/-test-/bignum/depend1141
-rw-r--r--ext/-test-/bignum/div.c35
-rw-r--r--ext/-test-/bignum/extconf.rb3
-rw-r--r--ext/-test-/bignum/init.c11
-rw-r--r--ext/-test-/bignum/intpack.c87
-rw-r--r--ext/-test-/bignum/mul.c65
-rw-r--r--ext/-test-/bignum/str2big.c38
-rw-r--r--ext/-test-/box/yay1/extconf.rb1
-rw-r--r--ext/-test-/box/yay1/yay1.c28
-rw-r--r--ext/-test-/box/yay1/yay1.def3
-rw-r--r--ext/-test-/box/yay1/yay1.h4
-rw-r--r--ext/-test-/box/yay2/extconf.rb1
-rw-r--r--ext/-test-/box/yay2/yay2.c28
-rw-r--r--ext/-test-/box/yay2/yay2.def3
-rw-r--r--ext/-test-/box/yay2/yay2.h4
-rw-r--r--ext/-test-/bug-14834/bug-14834.c39
-rw-r--r--ext/-test-/bug-14834/depend163
-rw-r--r--ext/-test-/bug-14834/extconf.rb2
-rw-r--r--ext/-test-/bug-3571/bug.c23
-rw-r--r--ext/-test-/bug-3571/depend163
-rw-r--r--ext/-test-/bug-3571/extconf.rb2
-rw-r--r--ext/-test-/bug-5832/bug.c14
-rw-r--r--ext/-test-/bug-5832/depend163
-rw-r--r--ext/-test-/bug-5832/extconf.rb2
-rw-r--r--ext/-test-/bug_reporter/bug_reporter.c24
-rw-r--r--ext/-test-/bug_reporter/depend163
-rw-r--r--ext/-test-/bug_reporter/extconf.rb2
-rw-r--r--ext/-test-/class/class2name.c14
-rw-r--r--ext/-test-/class/depend323
-rw-r--r--ext/-test-/class/extconf.rb3
-rw-r--r--ext/-test-/class/init.c12
-rw-r--r--ext/-test-/cxxanyargs/cxxanyargs.cpp935
-rw-r--r--ext/-test-/cxxanyargs/depend13
-rw-r--r--ext/-test-/cxxanyargs/extconf.rb46
-rw-r--r--ext/-test-/cxxanyargs/failure.cpp13
-rw-r--r--ext/-test-/cxxanyargs/failurem1.cpp13
-rw-r--r--ext/-test-/debug/depend485
-rw-r--r--ext/-test-/debug/extconf.rb3
-rw-r--r--ext/-test-/debug/init.c11
-rw-r--r--ext/-test-/debug/inspector.c32
-rw-r--r--ext/-test-/debug/profile_frames.c65
-rw-r--r--ext/-test-/dln/empty/depend163
-rw-r--r--ext/-test-/dln/empty/empty.c6
-rw-r--r--ext/-test-/dln/empty/extconf.rb2
-rw-r--r--ext/-test-/econv/append.c17
-rw-r--r--ext/-test-/econv/depend336
-rw-r--r--ext/-test-/econv/extconf.rb3
-rw-r--r--ext/-test-/econv/init.c11
-rw-r--r--ext/-test-/ensure_and_callcc/depend163
-rw-r--r--ext/-test-/ensure_and_callcc/ensure_and_callcc.c58
-rw-r--r--ext/-test-/ensure_and_callcc/extconf.rb5
-rw-r--r--ext/-test-/enumerator_kw/depend163
-rw-r--r--ext/-test-/enumerator_kw/enumerator_kw.c22
-rw-r--r--ext/-test-/enumerator_kw/extconf.rb1
-rw-r--r--ext/-test-/eval/depend162
-rw-r--r--ext/-test-/eval/eval.c13
-rw-r--r--ext/-test-/eval/extconf.rb2
-rw-r--r--ext/-test-/exception/dataerror.c31
-rw-r--r--ext/-test-/exception/depend657
-rw-r--r--ext/-test-/exception/enc_raise.c15
-rw-r--r--ext/-test-/exception/ensured.c39
-rw-r--r--ext/-test-/exception/extconf.rb3
-rw-r--r--ext/-test-/exception/init.c11
-rw-r--r--ext/-test-/fatal/depend486
-rw-r--r--ext/-test-/fatal/extconf.rb3
-rw-r--r--ext/-test-/fatal/init.c10
-rw-r--r--ext/-test-/fatal/invalid.c22
-rw-r--r--ext/-test-/fatal/rb_fatal.c19
-rw-r--r--ext/-test-/file/depend682
-rw-r--r--ext/-test-/file/extconf.rb18
-rw-r--r--ext/-test-/file/fs.c111
-rw-r--r--ext/-test-/file/init.c11
-rw-r--r--ext/-test-/file/newline_conv.c73
-rw-r--r--ext/-test-/file/stat.c27
-rw-r--r--ext/-test-/float/depend328
-rw-r--r--ext/-test-/float/extconf.rb3
-rw-r--r--ext/-test-/float/init.c11
-rw-r--r--ext/-test-/float/nextafter.c36
-rw-r--r--ext/-test-/funcall/depend163
-rw-r--r--ext/-test-/funcall/extconf.rb3
-rw-r--r--ext/-test-/funcall/funcall.c72
-rw-r--r--ext/-test-/gvl/call_without_gvl/call_without_gvl.c78
-rw-r--r--ext/-test-/gvl/call_without_gvl/depend163
-rw-r--r--ext/-test-/gvl/call_without_gvl/extconf.rb2
-rw-r--r--ext/-test-/hash/delete.c16
-rw-r--r--ext/-test-/hash/depend324
-rw-r--r--ext/-test-/hash/extconf.rb3
-rw-r--r--ext/-test-/hash/init.c11
-rw-r--r--ext/-test-/integer/core_ext.c36
-rw-r--r--ext/-test-/integer/depend496
-rw-r--r--ext/-test-/integer/extconf.rb3
-rw-r--r--ext/-test-/integer/init.c11
-rw-r--r--ext/-test-/integer/my_integer.c20
-rw-r--r--ext/-test-/iseq_load/depend163
-rw-r--r--ext/-test-/iseq_load/extconf.rb2
-rw-r--r--ext/-test-/iseq_load/iseq_load.c21
-rw-r--r--ext/-test-/iter/break.c25
-rw-r--r--ext/-test-/iter/depend485
-rw-r--r--ext/-test-/iter/extconf.rb3
-rw-r--r--ext/-test-/iter/init.c11
-rw-r--r--ext/-test-/iter/yield.c16
-rw-r--r--ext/-test-/load/dot.dot/depend163
-rw-r--r--ext/-test-/load/dot.dot/dot.dot.c3
-rw-r--r--ext/-test-/load/dot.dot/extconf.rb2
-rw-r--r--ext/-test-/load/protect/depend163
-rw-r--r--ext/-test-/load/protect/extconf.rb1
-rw-r--r--ext/-test-/load/protect/protect.c19
-rw-r--r--ext/-test-/load/resolve_symbol_resolver/depend163
-rw-r--r--ext/-test-/load/resolve_symbol_resolver/extconf.rb1
-rw-r--r--ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c56
-rw-r--r--ext/-test-/load/resolve_symbol_target/depend164
-rw-r--r--ext/-test-/load/resolve_symbol_target/extconf.rb1
-rw-r--r--ext/-test-/load/resolve_symbol_target/resolve_symbol_target.c15
-rw-r--r--ext/-test-/load/resolve_symbol_target/resolve_symbol_target.h4
-rw-r--r--ext/-test-/load/stringify_symbols/depend164
-rw-r--r--ext/-test-/load/stringify_symbols/extconf.rb1
-rw-r--r--ext/-test-/load/stringify_symbols/stringify_symbols.c29
-rw-r--r--ext/-test-/load/stringify_target/depend164
-rw-r--r--ext/-test-/load/stringify_target/extconf.rb1
-rw-r--r--ext/-test-/load/stringify_target/stringify_target.c15
-rw-r--r--ext/-test-/load/stringify_target/stringify_target.h4
-rw-r--r--ext/-test-/marshal/compat/depend163
-rw-r--r--ext/-test-/marshal/compat/extconf.rb2
-rw-r--r--ext/-test-/marshal/compat/usrcompat.c32
-rw-r--r--ext/-test-/marshal/internal_ivar/depend163
-rw-r--r--ext/-test-/marshal/internal_ivar/extconf.rb2
-rw-r--r--ext/-test-/marshal/internal_ivar/internal_ivar.c54
-rw-r--r--ext/-test-/marshal/usr/depend163
-rw-r--r--ext/-test-/marshal/usr/extconf.rb2
-rw-r--r--ext/-test-/marshal/usr/usrmarshal.c50
-rw-r--r--ext/-test-/memory_status/depend162
-rw-r--r--ext/-test-/memory_status/extconf.rb12
-rw-r--r--ext/-test-/memory_status/memory_status.c80
-rw-r--r--ext/-test-/memory_view/depend164
-rw-r--r--ext/-test-/memory_view/extconf.rb5
-rw-r--r--ext/-test-/memory_view/memory_view.c450
-rw-r--r--ext/-test-/method/arity.c22
-rw-r--r--ext/-test-/method/depend324
-rw-r--r--ext/-test-/method/extconf.rb3
-rw-r--r--ext/-test-/method/init.c11
-rw-r--r--ext/-test-/notimplement/bug.c18
-rw-r--r--ext/-test-/notimplement/depend163
-rw-r--r--ext/-test-/notimplement/extconf.rb2
-rw-r--r--ext/-test-/num2int/depend163
-rw-r--r--ext/-test-/num2int/extconf.rb2
-rw-r--r--ext/-test-/num2int/num2int.c136
-rw-r--r--ext/-test-/path_to_class/depend163
-rw-r--r--ext/-test-/path_to_class/extconf.rb7
-rw-r--r--ext/-test-/path_to_class/path_to_class.c15
-rw-r--r--ext/-test-/popen_deadlock/depend164
-rw-r--r--ext/-test-/popen_deadlock/extconf.rb6
-rw-r--r--ext/-test-/popen_deadlock/infinite_loop_dlsym.c50
-rw-r--r--ext/-test-/postponed_job/depend164
-rw-r--r--ext/-test-/postponed_job/extconf.rb2
-rw-r--r--ext/-test-/postponed_job/postponed_job.c151
-rw-r--r--ext/-test-/printf/depend175
-rw-r--r--ext/-test-/printf/extconf.rb2
-rw-r--r--ext/-test-/printf/printf.c109
-rw-r--r--ext/-test-/proc/depend485
-rw-r--r--ext/-test-/proc/extconf.rb3
-rw-r--r--ext/-test-/proc/init.c11
-rw-r--r--ext/-test-/proc/receiver.c21
-rw-r--r--ext/-test-/proc/super.c27
-rw-r--r--ext/-test-/public_header_warnings/extconf.rb28
-rw-r--r--ext/-test-/random/bad_version.c135
-rw-r--r--ext/-test-/random/depend485
-rw-r--r--ext/-test-/random/extconf.rb3
-rw-r--r--ext/-test-/random/init.c11
-rw-r--r--ext/-test-/random/loop.c120
-rw-r--r--ext/-test-/rational/depend183
-rw-r--r--ext/-test-/rational/extconf.rb8
-rw-r--r--ext/-test-/rational/rat.c48
-rw-r--r--ext/-test-/rb_call_super_kw/depend163
-rw-r--r--ext/-test-/rb_call_super_kw/extconf.rb1
-rw-r--r--ext/-test-/rb_call_super_kw/rb_call_super_kw.c15
-rw-r--r--ext/-test-/recursion/depend163
-rw-r--r--ext/-test-/recursion/extconf.rb3
-rw-r--r--ext/-test-/recursion/recursion.c28
-rw-r--r--ext/-test-/regexp/depend325
-rw-r--r--ext/-test-/regexp/extconf.rb3
-rw-r--r--ext/-test-/regexp/init.c11
-rw-r--r--ext/-test-/regexp/parse_depth_limit.c23
-rw-r--r--ext/-test-/sanitizers/depend162
-rw-r--r--ext/-test-/sanitizers/extconf.rb2
-rw-r--r--ext/-test-/sanitizers/sanitizers.c36
-rw-r--r--ext/-test-/scan_args/depend163
-rw-r--r--ext/-test-/scan_args/extconf.rb1
-rw-r--r--ext/-test-/scan_args/scan_args.c305
-rw-r--r--ext/-test-/scheduler/extconf.rb2
-rw-r--r--ext/-test-/scheduler/scheduler.c92
-rw-r--r--ext/-test-/st/foreach/depend163
-rw-r--r--ext/-test-/st/foreach/extconf.rb2
-rw-r--r--ext/-test-/st/foreach/foreach.c163
-rw-r--r--ext/-test-/st/numhash/depend163
-rw-r--r--ext/-test-/st/numhash/extconf.rb2
-rw-r--r--ext/-test-/st/numhash/numhash.c137
-rw-r--r--ext/-test-/st/update/depend163
-rw-r--r--ext/-test-/st/update/extconf.rb2
-rw-r--r--ext/-test-/st/update/update.c34
-rw-r--r--ext/-test-/stack/depend179
-rw-r--r--ext/-test-/stack/extconf.rb3
-rw-r--r--ext/-test-/stack/stack.c35
-rw-r--r--ext/-test-/string/capacity.c18
-rw-r--r--ext/-test-/string/coderange.c47
-rw-r--r--ext/-test-/string/cstr.c147
-rw-r--r--ext/-test-/string/depend3030
-rw-r--r--ext/-test-/string/ellipsize.c13
-rw-r--r--ext/-test-/string/enc_associate.c22
-rw-r--r--ext/-test-/string/enc_dummy.c15
-rw-r--r--ext/-test-/string/enc_str_buf_cat.c28
-rw-r--r--ext/-test-/string/extconf.rb3
-rw-r--r--ext/-test-/string/fstring.c38
-rw-r--r--ext/-test-/string/init.c11
-rw-r--r--ext/-test-/string/modify.c22
-rw-r--r--ext/-test-/string/new.c21
-rw-r--r--ext/-test-/string/nofree.c13
-rw-r--r--ext/-test-/string/normalize.c17
-rw-r--r--ext/-test-/string/qsort.c61
-rw-r--r--ext/-test-/string/rb_interned_str.c14
-rw-r--r--ext/-test-/string/rb_str_dup.c35
-rw-r--r--ext/-test-/string/set_len.c32
-rw-r--r--ext/-test-/struct/data.c13
-rw-r--r--ext/-test-/struct/depend807
-rw-r--r--ext/-test-/struct/duplicate.c24
-rw-r--r--ext/-test-/struct/extconf.rb3
-rw-r--r--ext/-test-/struct/init.c11
-rw-r--r--ext/-test-/struct/len.c13
-rw-r--r--ext/-test-/struct/member.c18
-rw-r--r--ext/-test-/symbol/depend324
-rw-r--r--ext/-test-/symbol/extconf.rb4
-rw-r--r--ext/-test-/symbol/init.c39
-rw-r--r--ext/-test-/symbol/type.c78
-rw-r--r--ext/-test-/thread/id/depend163
-rw-r--r--ext/-test-/thread/id/extconf.rb3
-rw-r--r--ext/-test-/thread/id/id.c15
-rw-r--r--ext/-test-/thread/instrumentation/depend165
-rw-r--r--ext/-test-/thread/instrumentation/extconf.rb2
-rw-r--r--ext/-test-/thread/instrumentation/instrumentation.c218
-rw-r--r--ext/-test-/thread/lock_native_thread/depend163
-rw-r--r--ext/-test-/thread/lock_native_thread/extconf.rb2
-rw-r--r--ext/-test-/thread/lock_native_thread/lock_native_thread.c50
-rw-r--r--ext/-test-/time/depend490
-rw-r--r--ext/-test-/time/extconf.rb3
-rw-r--r--ext/-test-/time/init.c11
-rw-r--r--ext/-test-/time/new.c34
-rw-r--r--ext/-test-/tracepoint/depend324
-rw-r--r--ext/-test-/tracepoint/extconf.rb2
-rw-r--r--ext/-test-/tracepoint/gc_hook.c89
-rw-r--r--ext/-test-/tracepoint/tracepoint.c98
-rw-r--r--ext/-test-/typeddata/depend163
-rw-r--r--ext/-test-/typeddata/extconf.rb2
-rw-r--r--ext/-test-/typeddata/typeddata.c44
-rw-r--r--ext/-test-/vm/at_exit.c44
-rw-r--r--ext/-test-/vm/depend163
-rw-r--r--ext/-test-/vm/extconf.rb1
-rw-r--r--ext/-test-/wait/depend175
-rw-r--r--ext/-test-/wait/extconf.rb2
-rw-r--r--ext/-test-/wait/wait.c39
-rw-r--r--ext/-test-/win32/console/attribute.c69
-rw-r--r--ext/-test-/win32/console/depend1
-rw-r--r--ext/-test-/win32/console/extconf.rb5
-rw-r--r--ext/-test-/win32/console/init.c11
-rw-r--r--ext/-test-/win32/dln/depend9
-rw-r--r--ext/-test-/win32/dln/dlntest.c17
-rw-r--r--ext/-test-/win32/dln/extconf.rb34
-rw-r--r--ext/-test-/win32/dln/libdlntest.c4
-rw-r--r--ext/-test-/win32/dln/libdlntest.def2
-rw-r--r--ext/-test-/win32/fd_setsize/depend1
-rw-r--r--ext/-test-/win32/fd_setsize/extconf.rb4
-rw-r--r--ext/-test-/win32/fd_setsize/fd_setsize.c55
-rw-r--r--ext/.cvsignore2
-rw-r--r--ext/.document82
-rw-r--r--ext/Setup37
-rw-r--r--ext/Setup.atheos36
-rw-r--r--ext/Setup.dj33
-rw-r--r--ext/Setup.emx33
-rw-r--r--ext/Setup.nt36
-rw-r--r--ext/Setup.x6833
-rw-r--r--ext/Win32API/.cvsignore3
-rw-r--r--ext/Win32API/Win32API.c215
-rw-r--r--ext/Win32API/depend1
-rw-r--r--ext/Win32API/extconf.rb6
-rw-r--r--ext/Win32API/getch.rb5
-rw-r--r--ext/Win32API/lib/win32/registry.rb831
-rw-r--r--ext/Win32API/lib/win32/resolv.rb366
-rw-r--r--ext/Win32API/point.rb18
-rw-r--r--ext/bigdecimal/.cvsignore3
-rw-r--r--ext/bigdecimal/README60
-rw-r--r--ext/bigdecimal/bigdecimal.c4689
-rw-r--r--ext/bigdecimal/bigdecimal.def2
-rw-r--r--ext/bigdecimal/bigdecimal.h216
-rw-r--r--ext/bigdecimal/bigdecimal_en.html797
-rw-r--r--ext/bigdecimal/bigdecimal_ja.html798
-rw-r--r--ext/bigdecimal/depend1
-rw-r--r--ext/bigdecimal/extconf.rb2
-rw-r--r--ext/bigdecimal/lib/bigdecimal/jacobian.rb85
-rw-r--r--ext/bigdecimal/lib/bigdecimal/ludcmp.rb84
-rw-r--r--ext/bigdecimal/lib/bigdecimal/math.rb235
-rw-r--r--ext/bigdecimal/lib/bigdecimal/newton.rb77
-rw-r--r--ext/bigdecimal/lib/bigdecimal/util.rb65
-rw-r--r--ext/bigdecimal/sample/linear.rb71
-rw-r--r--ext/bigdecimal/sample/nlsolve.rb38
-rw-r--r--ext/bigdecimal/sample/pi.rb20
-rw-r--r--ext/cgi/escape/depend175
-rw-r--r--ext/cgi/escape/escape.c487
-rw-r--r--ext/cgi/escape/extconf.rb7
-rw-r--r--ext/continuation/continuation.c13
-rw-r--r--ext/continuation/depend162
-rw-r--r--ext/continuation/extconf.rb4
-rw-r--r--ext/coverage/coverage.c710
-rw-r--r--ext/coverage/depend210
-rw-r--r--ext/coverage/extconf.rb5
-rw-r--r--ext/coverage/lib/coverage.rb19
-rw-r--r--ext/curses/.cvsignore3
-rw-r--r--ext/curses/curses.c2102
-rw-r--r--ext/curses/depend1
-rw-r--r--ext/curses/extconf.rb31
-rw-r--r--ext/curses/hello.rb30
-rw-r--r--ext/curses/mouse.rb53
-rw-r--r--ext/curses/rain.rb76
-rw-r--r--ext/curses/view.rb91
-rw-r--r--ext/curses/view2.rb115
-rw-r--r--ext/date/date.gemspec36
-rw-r--r--ext/date/date_core.c10258
-rw-r--r--ext/date/date_parse.c3086
-rw-r--r--ext/date/date_strftime.c638
-rw-r--r--ext/date/date_strptime.c704
-rw-r--r--ext/date/date_tmx.h56
-rw-r--r--ext/date/depend692
-rw-r--r--ext/date/extconf.rb13
-rw-r--r--ext/date/lib/date.rb70
-rw-r--r--ext/date/prereq.mk19
-rw-r--r--ext/date/update-abbr52
-rw-r--r--ext/date/zonetab.h1564
-rw-r--r--ext/date/zonetab.list330
-rw-r--r--ext/dbm/.cvsignore3
-rw-r--r--ext/dbm/dbm.c816
-rw-r--r--ext/dbm/depend1
-rw-r--r--ext/dbm/extconf.rb61
-rw-r--r--ext/digest/.cvsignore3
-rw-r--r--ext/digest/.document3
-rw-r--r--ext/digest/bubblebabble/bubblebabble.c146
-rw-r--r--ext/digest/bubblebabble/depend164
-rw-r--r--ext/digest/bubblebabble/extconf.rb4
-rw-r--r--ext/digest/defs.h36
-rw-r--r--ext/digest/depend166
-rw-r--r--ext/digest/digest.c909
-rw-r--r--ext/digest/digest.gemspec44
-rw-r--r--ext/digest/digest.h100
-rw-r--r--ext/digest/digest.txt113
-rw-r--r--ext/digest/digest.txt.ja111
-rw-r--r--ext/digest/digest_conf.rb19
-rw-r--r--ext/digest/extconf.rb5
-rw-r--r--ext/digest/lib/digest.rb123
-rw-r--r--ext/digest/lib/digest/loader.rb3
-rw-r--r--ext/digest/lib/digest/version.rb6
-rw-r--r--ext/digest/lib/md5.rb14
-rw-r--r--ext/digest/lib/sha1.rb14
-rw-r--r--ext/digest/md5/.cvsignore3
-rw-r--r--ext/digest/md5/depend339
-rw-r--r--ext/digest/md5/extconf.rb20
-rw-r--r--ext/digest/md5/md5.c42
-rw-r--r--ext/digest/md5/md5.h13
-rw-r--r--ext/digest/md5/md5cc.h27
-rw-r--r--ext/digest/md5/md5init.c60
-rw-r--r--ext/digest/md5/md5ossl.c30
-rw-r--r--ext/digest/md5/md5ossl.h12
-rw-r--r--ext/digest/rmd160/.cvsignore3
-rw-r--r--ext/digest/rmd160/depend340
-rw-r--r--ext/digest/rmd160/extconf.rb21
-rw-r--r--ext/digest/rmd160/rmd160.c25
-rw-r--r--ext/digest/rmd160/rmd160.h22
-rw-r--r--ext/digest/rmd160/rmd160hl.c96
-rw-r--r--ext/digest/rmd160/rmd160init.c62
-rw-r--r--ext/digest/rmd160/rmd160ossl.c45
-rw-r--r--ext/digest/rmd160/rmd160ossl.h21
-rw-r--r--ext/digest/sha1/.cvsignore3
-rw-r--r--ext/digest/sha1/depend341
-rw-r--r--ext/digest/sha1/extconf.rb19
-rw-r--r--ext/digest/sha1/sha1.c38
-rw-r--r--ext/digest/sha1/sha1.h25
-rw-r--r--ext/digest/sha1/sha1cc.h22
-rw-r--r--ext/digest/sha1/sha1hl.c102
-rw-r--r--ext/digest/sha1/sha1init.c64
-rw-r--r--ext/digest/sha1/sha1ossl.c45
-rw-r--r--ext/digest/sha1/sha1ossl.h17
-rw-r--r--ext/digest/sha2/.cvsignore3
-rw-r--r--ext/digest/sha2/depend339
-rw-r--r--ext/digest/sha2/extconf.rb22
-rw-r--r--ext/digest/sha2/lib/sha2.rb142
-rw-r--r--ext/digest/sha2/lib/sha2/loader.rb3
-rw-r--r--ext/digest/sha2/sha2.c318
-rw-r--r--ext/digest/sha2/sha2.h194
-rw-r--r--ext/digest/sha2/sha2cc.h70
-rw-r--r--ext/digest/sha2/sha2hl.c252
-rw-r--r--ext/digest/sha2/sha2init.c79
-rw-r--r--ext/digest/test.sh33
-rw-r--r--ext/dl/.cvsignore8
-rw-r--r--ext/dl/depend46
-rw-r--r--ext/dl/dl.c728
-rw-r--r--ext/dl/dl.def59
-rw-r--r--ext/dl/dl.h313
-rw-r--r--ext/dl/doc/dl.txt266
-rw-r--r--ext/dl/extconf.rb193
-rw-r--r--ext/dl/h2rb500
-rw-r--r--ext/dl/handle.c215
-rw-r--r--ext/dl/install.rb49
-rw-r--r--ext/dl/lib/dl/import.rb225
-rw-r--r--ext/dl/lib/dl/struct.rb149
-rw-r--r--ext/dl/lib/dl/types.rb245
-rw-r--r--ext/dl/lib/dl/win32.rb25
-rw-r--r--ext/dl/mkcall.rb62
-rw-r--r--ext/dl/mkcallback.rb53
-rw-r--r--ext/dl/mkcbtable.rb18
-rw-r--r--ext/dl/ptr.c1067
-rw-r--r--ext/dl/sample/c++sample.C35
-rw-r--r--ext/dl/sample/c++sample.rb60
-rw-r--r--ext/dl/sample/drives.rb70
-rw-r--r--ext/dl/sample/getch.rb5
-rw-r--r--ext/dl/sample/libc.rb69
-rw-r--r--ext/dl/sample/msgbox.rb19
-rw-r--r--ext/dl/sample/msgbox2.rb18
-rw-r--r--ext/dl/sample/stream.rb87
-rw-r--r--ext/dl/sym.c992
-rw-r--r--ext/dl/test/libtest.def28
-rw-r--r--ext/dl/test/test.c247
-rw-r--r--ext/dl/test/test.rb306
-rw-r--r--ext/dl/type.rb115
-rw-r--r--ext/enumerator/.cvsignore2
-rw-r--r--ext/enumerator/enumerator.c298
-rw-r--r--ext/enumerator/enumerator.txt102
-rw-r--r--ext/enumerator/extconf.rb2
-rw-r--r--ext/erb/escape/escape.c114
-rw-r--r--ext/erb/escape/extconf.rb9
-rw-r--r--ext/etc/.cvsignore3
-rw-r--r--ext/etc/.document2
-rw-r--r--ext/etc/depend183
-rw-r--r--ext/etc/etc.c1193
-rw-r--r--ext/etc/etc.gemspec44
-rw-r--r--ext/etc/etc.txt72
-rw-r--r--ext/etc/etc.txt.ja72
-rw-r--r--ext/etc/extconf.rb60
-rw-r--r--ext/etc/mkconstants.rb352
-rwxr-xr-x[-rw-r--r--]ext/extmk.rb782
-rw-r--r--ext/fcntl/.cvsignore3
-rw-r--r--ext/fcntl/depend164
-rw-r--r--ext/fcntl/extconf.rb1
-rw-r--r--ext/fcntl/fcntl.c255
-rw-r--r--ext/fcntl/fcntl.gemspec32
-rw-r--r--ext/gdbm/.cvsignore3
-rw-r--r--ext/gdbm/README1
-rw-r--r--ext/gdbm/depend1
-rw-r--r--ext/gdbm/extconf.rb7
-rw-r--r--ext/gdbm/gdbm.c1022
-rw-r--r--ext/iconv/.cvsignore5
-rw-r--r--ext/iconv/charset_alias.rb103
-rw-r--r--ext/iconv/depend2
-rw-r--r--ext/iconv/extconf.rb51
-rw-r--r--ext/iconv/iconv.c910
-rw-r--r--ext/io/console/.document2
-rwxr-xr-xext/io/console/buildgem.sh5
-rw-r--r--ext/io/console/console.c2019
-rw-r--r--ext/io/console/depend199
-rw-r--r--ext/io/console/extconf.rb61
-rw-r--r--ext/io/console/io-console.gemspec53
-rw-r--r--ext/io/console/lib/console/size.rb23
-rw-r--r--ext/io/console/win32_vk.chksum1
-rw-r--r--ext/io/console/win32_vk.inc1390
-rw-r--r--ext/io/console/win32_vk.list166
-rw-r--r--ext/io/nonblock/depend176
-rw-r--r--ext/io/nonblock/extconf.rb16
-rw-r--r--ext/io/nonblock/io-nonblock.gemspec25
-rw-r--r--ext/io/nonblock/nonblock.c210
-rw-r--r--ext/io/wait/.cvsignore2
-rw-r--r--ext/io/wait/depend176
-rw-r--r--ext/io/wait/extconf.rb17
-rw-r--r--ext/io/wait/io-wait.gemspec39
-rw-r--r--ext/io/wait/lib/nonblock.rb23
-rw-r--r--ext/io/wait/wait.c111
-rw-r--r--ext/json/depend2
-rw-r--r--ext/json/extconf.rb3
-rw-r--r--ext/json/fbuffer/fbuffer.h260
-rw-r--r--ext/json/generator/depend186
-rw-r--r--ext/json/generator/extconf.rb19
-rw-r--r--ext/json/generator/generator.c1997
-rw-r--r--ext/json/json.gemspec62
-rw-r--r--ext/json/json.h134
-rw-r--r--ext/json/lib/json.rb675
-rw-r--r--ext/json/lib/json/add/bigdecimal.rb58
-rw-r--r--ext/json/lib/json/add/complex.rb51
-rw-r--r--ext/json/lib/json/add/core.rb13
-rw-r--r--ext/json/lib/json/add/date.rb54
-rw-r--r--ext/json/lib/json/add/date_time.rb67
-rw-r--r--ext/json/lib/json/add/exception.rb49
-rw-r--r--ext/json/lib/json/add/ostruct.rb54
-rw-r--r--ext/json/lib/json/add/range.rb54
-rw-r--r--ext/json/lib/json/add/rational.rb49
-rw-r--r--ext/json/lib/json/add/regexp.rb48
-rw-r--r--ext/json/lib/json/add/set.rb48
-rw-r--r--ext/json/lib/json/add/string.rb35
-rw-r--r--ext/json/lib/json/add/struct.rb52
-rw-r--r--ext/json/lib/json/add/symbol.rb52
-rw-r--r--ext/json/lib/json/add/time.rb52
-rw-r--r--ext/json/lib/json/common.rb1173
-rw-r--r--ext/json/lib/json/ext.rb45
-rw-r--r--ext/json/lib/json/ext/generator/state.rb103
-rw-r--r--ext/json/lib/json/generic_object.rb67
-rw-r--r--ext/json/lib/json/version.rb5
-rw-r--r--ext/json/parser/depend182
-rw-r--r--ext/json/parser/extconf.rb21
-rw-r--r--ext/json/parser/parser.c2038
-rw-r--r--ext/json/simd/conf.rb24
-rw-r--r--ext/json/simd/simd.h208
-rw-r--r--ext/json/vendor/fpconv.c480
-rw-r--r--ext/json/vendor/jeaiii-ltoa.h267
-rw-r--r--ext/json/vendor/ryu.h819
-rw-r--r--ext/nkf/.cvsignore3
-rw-r--r--ext/nkf/depend1
-rw-r--r--ext/nkf/extconf.rb2
-rw-r--r--ext/nkf/lib/kconv.rb367
-rw-r--r--ext/nkf/nkf-utf8/config.h88
-rw-r--r--ext/nkf/nkf-utf8/nkf.c5633
-rw-r--r--ext/nkf/nkf-utf8/utf8tbl.c8500
-rw-r--r--ext/nkf/nkf-utf8/utf8tbl.h34
-rw-r--r--ext/nkf/nkf.c654
-rw-r--r--ext/objspace/depend642
-rw-r--r--ext/objspace/extconf.rb4
-rw-r--r--ext/objspace/lib/objspace.rb135
-rw-r--r--ext/objspace/lib/objspace/trace.rb45
-rw-r--r--ext/objspace/object_tracing.c607
-rw-r--r--ext/objspace/objspace.c868
-rw-r--r--ext/objspace/objspace.h20
-rw-r--r--ext/objspace/objspace_dump.c932
-rw-r--r--ext/openssl/.cvsignore5
-rw-r--r--ext/openssl/History.md1007
-rw-r--r--ext/openssl/depend6507
-rw-r--r--ext/openssl/extconf.rb248
-rw-r--r--ext/openssl/lib/net/ftptls.rb43
-rw-r--r--ext/openssl/lib/net/telnets.rb248
-rw-r--r--ext/openssl/lib/openssl.rb41
-rw-r--r--ext/openssl/lib/openssl/bn.rb47
-rw-r--r--ext/openssl/lib/openssl/buffering.rb380
-rw-r--r--ext/openssl/lib/openssl/cipher.rb81
-rw-r--r--ext/openssl/lib/openssl/digest.rb102
-rw-r--r--ext/openssl/lib/openssl/hmac.rb78
-rw-r--r--ext/openssl/lib/openssl/marshal.rb30
-rw-r--r--ext/openssl/lib/openssl/pkcs5.rb22
-rw-r--r--ext/openssl/lib/openssl/pkey.rb493
-rw-r--r--ext/openssl/lib/openssl/ssl.rb495
-rw-r--r--ext/openssl/lib/openssl/version.rb6
-rw-r--r--ext/openssl/lib/openssl/x509.rb298
-rw-r--r--ext/openssl/openssl.gemspec28
-rw-r--r--ext/openssl/openssl_missing.c345
-rw-r--r--ext/openssl/openssl_missing.h139
-rw-r--r--ext/openssl/ossl.c1266
-rw-r--r--ext/openssl/ossl.h224
-rw-r--r--ext/openssl/ossl_asn1.c1960
-rw-r--r--ext/openssl/ossl_asn1.h51
-rw-r--r--ext/openssl/ossl_bio.c67
-rw-r--r--ext/openssl/ossl_bio.h11
-rw-r--r--ext/openssl/ossl_bn.c1438
-rw-r--r--ext/openssl/ossl_bn.h17
-rw-r--r--ext/openssl/ossl_cipher.c1065
-rw-r--r--ext/openssl/ossl_cipher.h21
-rw-r--r--ext/openssl/ossl_config.c647
-rw-r--r--ext/openssl/ossl_config.h18
-rw-r--r--ext/openssl/ossl_digest.c497
-rw-r--r--ext/openssl/ossl_digest.h20
-rw-r--r--ext/openssl/ossl_engine.c391
-rw-r--r--ext/openssl/ossl_engine.h8
-rw-r--r--ext/openssl/ossl_hmac.c318
-rw-r--r--ext/openssl/ossl_hmac.h8
-rw-r--r--ext/openssl/ossl_kdf.c376
-rw-r--r--ext/openssl/ossl_kdf.h6
-rw-r--r--ext/openssl/ossl_ns_spki.c305
-rw-r--r--ext/openssl/ossl_ns_spki.h10
-rw-r--r--ext/openssl/ossl_ocsp.c1742
-rw-r--r--ext/openssl/ossl_ocsp.h12
-rw-r--r--ext/openssl/ossl_pkcs12.c267
-rw-r--r--ext/openssl/ossl_pkcs12.h10
-rw-r--r--ext/openssl/ossl_pkcs7.c757
-rw-r--r--ext/openssl/ossl_pkcs7.h13
-rw-r--r--ext/openssl/ossl_pkey.c1762
-rw-r--r--ext/openssl/ossl_pkey.h226
-rw-r--r--ext/openssl/ossl_pkey_dh.c640
-rw-r--r--ext/openssl/ossl_pkey_dsa.c590
-rw-r--r--ext/openssl/ossl_pkey_ec.c1655
-rw-r--r--ext/openssl/ossl_pkey_rsa.c844
-rw-r--r--ext/openssl/ossl_provider.c204
-rw-r--r--ext/openssl/ossl_provider.h5
-rw-r--r--ext/openssl/ossl_rand.c189
-rw-r--r--ext/openssl/ossl_rand.h9
-rw-r--r--ext/openssl/ossl_ssl.c3461
-rw-r--r--ext/openssl/ossl_ssl.h25
-rw-r--r--ext/openssl/ossl_ssl_session.c327
-rw-r--r--ext/openssl/ossl_ts.c1554
-rw-r--r--ext/openssl/ossl_ts.h16
-rw-r--r--ext/openssl/ossl_version.h16
-rw-r--r--ext/openssl/ossl_x509.c165
-rw-r--r--ext/openssl/ossl_x509.h62
-rw-r--r--ext/openssl/ossl_x509attr.c285
-rw-r--r--ext/openssl/ossl_x509cert.c819
-rw-r--r--ext/openssl/ossl_x509crl.c381
-rw-r--r--ext/openssl/ossl_x509ext.c350
-rw-r--r--ext/openssl/ossl_x509name.c479
-rw-r--r--ext/openssl/ossl_x509req.c317
-rw-r--r--ext/openssl/ossl_x509revoked.c202
-rw-r--r--ext/openssl/ossl_x509store.c829
-rw-r--r--ext/openssl/ruby_missing.h18
-rw-r--r--ext/psych/.gitignore1
-rw-r--r--ext/psych/depend906
-rw-r--r--ext/psych/extconf.rb56
-rw-r--r--ext/psych/lib/psych.rb794
-rw-r--r--ext/psych/lib/psych/class_loader.rb105
-rw-r--r--ext/psych/lib/psych/coder.rb95
-rw-r--r--ext/psych/lib/psych/core_ext.rb36
-rw-r--r--ext/psych/lib/psych/exception.rb28
-rw-r--r--ext/psych/lib/psych/handler.rb255
-rw-r--r--ext/psych/lib/psych/handlers/document_stream.rb23
-rw-r--r--ext/psych/lib/psych/handlers/recorder.rb40
-rw-r--r--ext/psych/lib/psych/json/ruby_events.rb20
-rw-r--r--ext/psych/lib/psych/json/stream.rb17
-rw-r--r--ext/psych/lib/psych/json/tree_builder.rb13
-rw-r--r--ext/psych/lib/psych/json/yaml_events.rb30
-rw-r--r--ext/psych/lib/psych/nodes.rb78
-rw-r--r--ext/psych/lib/psych/nodes/alias.rb21
-rw-r--r--ext/psych/lib/psych/nodes/document.rb63
-rw-r--r--ext/psych/lib/psych/nodes/mapping.rb59
-rw-r--r--ext/psych/lib/psych/nodes/node.rb76
-rw-r--r--ext/psych/lib/psych/nodes/scalar.rb70
-rw-r--r--ext/psych/lib/psych/nodes/sequence.rb84
-rw-r--r--ext/psych/lib/psych/nodes/stream.rb40
-rw-r--r--ext/psych/lib/psych/omap.rb5
-rw-r--r--ext/psych/lib/psych/parser.rb65
-rw-r--r--ext/psych/lib/psych/scalar_scanner.rb142
-rw-r--r--ext/psych/lib/psych/set.rb5
-rw-r--r--ext/psych/lib/psych/stream.rb38
-rw-r--r--ext/psych/lib/psych/streaming.rb28
-rw-r--r--ext/psych/lib/psych/syntax_error.rb22
-rw-r--r--ext/psych/lib/psych/tree_builder.rb137
-rw-r--r--ext/psych/lib/psych/versions.rb10
-rw-r--r--ext/psych/lib/psych/visitors.rb7
-rw-r--r--ext/psych/lib/psych/visitors/depth_first.rb27
-rw-r--r--ext/psych/lib/psych/visitors/emitter.rb52
-rw-r--r--ext/psych/lib/psych/visitors/json_tree.rb25
-rw-r--r--ext/psych/lib/psych/visitors/to_ruby.rb479
-rw-r--r--ext/psych/lib/psych/visitors/visitor.rb34
-rw-r--r--ext/psych/lib/psych/visitors/yaml_tree.rb626
-rw-r--r--ext/psych/lib/psych/y.rb10
-rw-r--r--ext/psych/psych.c36
-rw-r--r--ext/psych/psych.gemspec82
-rw-r--r--ext/psych/psych.h17
-rw-r--r--ext/psych/psych_emitter.c589
-rw-r--r--ext/psych/psych_emitter.h8
-rw-r--r--ext/psych/psych_parser.c575
-rw-r--r--ext/psych/psych_parser.h6
-rw-r--r--ext/psych/psych_to_ruby.c42
-rw-r--r--ext/psych/psych_to_ruby.h8
-rw-r--r--ext/psych/psych_yaml_tree.c11
-rw-r--r--ext/psych/psych_yaml_tree.h8
-rw-r--r--ext/pty/.cvsignore3
-rw-r--r--ext/pty/README65
-rw-r--r--ext/pty/README.expect22
-rw-r--r--ext/pty/README.expect.ja21
-rw-r--r--ext/pty/README.ja89
-rw-r--r--ext/pty/depend189
-rw-r--r--ext/pty/expect_sample.rb55
-rw-r--r--ext/pty/extconf.rb21
-rw-r--r--ext/pty/lib/expect.rb45
-rw-r--r--ext/pty/pty.c1045
-rw-r--r--ext/pty/script.rb37
-rw-r--r--ext/pty/shl.rb92
-rw-r--r--ext/racc/cparse/.cvsignore3
-rw-r--r--ext/racc/cparse/cparse.c832
-rw-r--r--ext/racc/cparse/depend1
-rw-r--r--ext/racc/cparse/extconf.rb4
-rw-r--r--ext/rbconfig/sizeof/depend337
-rw-r--r--ext/rbconfig/sizeof/extconf.rb36
-rw-r--r--ext/readline/.cvsignore3
-rw-r--r--ext/readline/README62
-rw-r--r--ext/readline/README.ja63
-rw-r--r--ext/readline/depend1
-rw-r--r--ext/readline/extconf.rb63
-rw-r--r--ext/readline/readline.c820
-rw-r--r--ext/ripper/README29
-rw-r--r--ext/ripper/depend841
-rw-r--r--ext/ripper/eventids2.c303
-rw-r--r--ext/ripper/eventids2.h8
-rw-r--r--ext/ripper/extconf.rb18
-rw-r--r--ext/ripper/lib/ripper.rb74
-rw-r--r--ext/ripper/lib/ripper/core.rb74
-rw-r--r--ext/ripper/lib/ripper/filter.rb86
-rw-r--r--ext/ripper/lib/ripper/lexer.rb379
-rw-r--r--ext/ripper/lib/ripper/sexp.rb187
-rw-r--r--ext/ripper/ripper_init.c.tmpl680
-rw-r--r--ext/ripper/ripper_init.h6
-rw-r--r--ext/ripper/tools/dsl.rb181
-rw-r--r--ext/ripper/tools/generate-param-macros.rb15
-rw-r--r--ext/ripper/tools/generate.rb194
-rw-r--r--ext/ripper/tools/preproc.rb124
-rw-r--r--ext/ripper/tools/strip.rb12
-rw-r--r--ext/rubyvm/depend2
-rw-r--r--ext/rubyvm/extconf.rb1
-rw-r--r--ext/rubyvm/lib/forwardable/impl.rb16
-rw-r--r--ext/sdbm/.cvsignore3
-rw-r--r--ext/sdbm/_sdbm.c973
-rw-r--r--ext/sdbm/depend2
-rw-r--r--ext/sdbm/extconf.rb3
-rw-r--r--ext/sdbm/init.c788
-rw-r--r--ext/sdbm/sdbm.h84
-rw-r--r--ext/socket/.cvsignore3
-rw-r--r--ext/socket/.document17
-rw-r--r--ext/socket/addrinfo.h79
-rw-r--r--ext/socket/ancdata.c1742
-rw-r--r--ext/socket/basicsocket.c792
-rw-r--r--ext/socket/constants.c144
-rw-r--r--ext/socket/depend3257
-rw-r--r--ext/socket/extconf.rb739
-rw-r--r--ext/socket/getaddrinfo.c981
-rw-r--r--ext/socket/getnameinfo.c285
-rw-r--r--ext/socket/ifaddr.c480
-rw-r--r--ext/socket/init.c842
-rw-r--r--ext/socket/ipsocket.c1640
-rw-r--r--ext/socket/lib/socket.rb1816
-rw-r--r--ext/socket/mkconstants.rb854
-rw-r--r--ext/socket/option.c1477
-rw-r--r--ext/socket/raddrinfo.c3274
-rw-r--r--ext/socket/rubysocket.h514
-rw-r--r--ext/socket/socket.c5377
-rw-r--r--ext/socket/sockport.h84
-rw-r--r--ext/socket/sockssocket.c75
-rw-r--r--ext/socket/tcpserver.c140
-rw-r--r--ext/socket/tcpsocket.c144
-rw-r--r--ext/socket/udpsocket.c247
-rw-r--r--ext/socket/unixserver.c121
-rw-r--r--ext/socket/unixsocket.c598
-rw-r--r--ext/stringio/.cvsignore3
-rw-r--r--ext/stringio/.document1
-rw-r--r--ext/stringio/README19
-rw-r--r--ext/stringio/README.md10
-rw-r--r--ext/stringio/depend179
-rw-r--r--ext/stringio/extconf.rb9
-rw-r--r--ext/stringio/stringio.c1910
-rw-r--r--ext/stringio/stringio.gemspec46
-rw-r--r--ext/strscan/.cvsignore3
-rw-r--r--ext/strscan/depend178
-rw-r--r--ext/strscan/extconf.rb14
-rw-r--r--ext/strscan/lib/strscan.rb20
-rw-r--r--ext/strscan/lib/strscan/strscan.rb55
-rw-r--r--ext/strscan/strscan.c2312
-rw-r--r--ext/strscan/strscan.gemspec49
-rw-r--r--ext/syck/.cvsignore3
-rw-r--r--ext/syck/bytecode.c1166
-rw-r--r--ext/syck/depend12
-rw-r--r--ext/syck/emitter.c1242
-rw-r--r--ext/syck/extconf.rb5
-rw-r--r--ext/syck/gram.c1894
-rw-r--r--ext/syck/gram.h79
-rw-r--r--ext/syck/handler.c174
-rw-r--r--ext/syck/implicit.c2990
-rw-r--r--ext/syck/node.c408
-rw-r--r--ext/syck/rubyext.c2367
-rw-r--r--ext/syck/syck.c504
-rw-r--r--ext/syck/syck.h456
-rw-r--r--ext/syck/token.c2725
-rw-r--r--ext/syck/yaml2byte.c257
-rw-r--r--ext/syck/yamlbyte.h170
-rw-r--r--ext/syslog/.cvsignore3
-rw-r--r--ext/syslog/depend2
-rw-r--r--ext/syslog/extconf.rb10
-rw-r--r--ext/syslog/syslog.c394
-rw-r--r--ext/syslog/syslog.txt121
-rw-r--r--ext/syslog/test.rb164
-rw-r--r--ext/tk/.cvsignore3
-rw-r--r--ext/tk/ChangeLog.tkextlib858
-rw-r--r--ext/tk/MANUAL_tcltklib.eng445
-rw-r--r--ext/tk/MANUAL_tcltklib.eucj557
-rw-r--r--ext/tk/README.1st22
-rw-r--r--ext/tk/README.ActiveTcl49
-rw-r--r--ext/tk/README.fork34
-rw-r--r--ext/tk/README.macosx-aqua67
-rw-r--r--ext/tk/README.tcltklib72
-rw-r--r--ext/tk/depend2
-rw-r--r--ext/tk/extconf.rb309
-rw-r--r--ext/tk/lib/README30
-rw-r--r--ext/tk/lib/multi-tk.rb3233
-rw-r--r--ext/tk/lib/remote-tk.rb526
-rw-r--r--ext/tk/lib/tcltk.rb367
-rw-r--r--ext/tk/lib/tk.rb4615
-rw-r--r--ext/tk/lib/tk/after.rb6
-rw-r--r--ext/tk/lib/tk/autoload.rb196
-rw-r--r--ext/tk/lib/tk/bgerror.rb29
-rw-r--r--ext/tk/lib/tk/bindtag.rb81
-rw-r--r--ext/tk/lib/tk/button.rb27
-rw-r--r--ext/tk/lib/tk/canvas.rb759
-rw-r--r--ext/tk/lib/tk/canvastag.rb375
-rw-r--r--ext/tk/lib/tk/checkbutton.rb25
-rw-r--r--ext/tk/lib/tk/clipboard.rb75
-rw-r--r--ext/tk/lib/tk/clock.rb71
-rw-r--r--ext/tk/lib/tk/composite.rb394
-rw-r--r--ext/tk/lib/tk/console.rb52
-rw-r--r--ext/tk/lib/tk/dialog.rb326
-rw-r--r--ext/tk/lib/tk/encodedstr.rb111
-rw-r--r--ext/tk/lib/tk/entry.rb117
-rw-r--r--ext/tk/lib/tk/event.rb488
-rw-r--r--ext/tk/lib/tk/font.rb1762
-rw-r--r--ext/tk/lib/tk/frame.rb128
-rw-r--r--ext/tk/lib/tk/grid.rb220
-rw-r--r--ext/tk/lib/tk/image.rb237
-rw-r--r--ext/tk/lib/tk/itemconfig.rb1056
-rw-r--r--ext/tk/lib/tk/itemfont.rb300
-rw-r--r--ext/tk/lib/tk/kinput.rb71
-rw-r--r--ext/tk/lib/tk/label.rb18
-rw-r--r--ext/tk/lib/tk/labelframe.rb25
-rw-r--r--ext/tk/lib/tk/listbox.rb279
-rw-r--r--ext/tk/lib/tk/macpkg.rb73
-rw-r--r--ext/tk/lib/tk/menu.rb632
-rw-r--r--ext/tk/lib/tk/menubar.rb131
-rw-r--r--ext/tk/lib/tk/menuspec.rb269
-rw-r--r--ext/tk/lib/tk/message.rb19
-rw-r--r--ext/tk/lib/tk/mngfocus.rb33
-rw-r--r--ext/tk/lib/tk/msgcat.rb292
-rw-r--r--ext/tk/lib/tk/namespace.rb500
-rw-r--r--ext/tk/lib/tk/optiondb.rb371
-rw-r--r--ext/tk/lib/tk/optionobj.rb212
-rw-r--r--ext/tk/lib/tk/pack.rb90
-rw-r--r--ext/tk/lib/tk/package.rb139
-rw-r--r--ext/tk/lib/tk/palette.rb55
-rw-r--r--ext/tk/lib/tk/panedwindow.rb232
-rw-r--r--ext/tk/lib/tk/place.rb128
-rw-r--r--ext/tk/lib/tk/radiobutton.rb66
-rw-r--r--ext/tk/lib/tk/root.rb108
-rw-r--r--ext/tk/lib/tk/scale.rb86
-rw-r--r--ext/tk/lib/tk/scrollable.rb79
-rw-r--r--ext/tk/lib/tk/scrollbar.rb124
-rw-r--r--ext/tk/lib/tk/scrollbox.rb36
-rw-r--r--ext/tk/lib/tk/selection.rb86
-rw-r--r--ext/tk/lib/tk/spinbox.rb99
-rw-r--r--ext/tk/lib/tk/tagfont.rb43
-rw-r--r--ext/tk/lib/tk/text.rb1550
-rw-r--r--ext/tk/lib/tk/textimage.rb82
-rw-r--r--ext/tk/lib/tk/textmark.rb166
-rw-r--r--ext/tk/lib/tk/texttag.rb279
-rw-r--r--ext/tk/lib/tk/textwindow.rb149
-rw-r--r--ext/tk/lib/tk/timer.rb634
-rw-r--r--ext/tk/lib/tk/toplevel.rb257
-rw-r--r--ext/tk/lib/tk/txtwin_abst.rb39
-rw-r--r--ext/tk/lib/tk/validation.rb376
-rw-r--r--ext/tk/lib/tk/variable.rb1651
-rw-r--r--ext/tk/lib/tk/virtevent.rb106
-rw-r--r--ext/tk/lib/tk/winfo.rb392
-rw-r--r--ext/tk/lib/tk/winpkg.rb143
-rw-r--r--ext/tk/lib/tk/wm.rb360
-rw-r--r--ext/tk/lib/tk/xim.rb122
-rw-r--r--ext/tk/lib/tkafter.rb4
-rw-r--r--ext/tk/lib/tkbgerror.rb4
-rw-r--r--ext/tk/lib/tkcanvas.rb4
-rw-r--r--ext/tk/lib/tkclass.rb47
-rw-r--r--ext/tk/lib/tkconsole.rb4
-rw-r--r--ext/tk/lib/tkdialog.rb4
-rw-r--r--ext/tk/lib/tkentry.rb4
-rw-r--r--ext/tk/lib/tkextlib/ICONS.rb13
-rw-r--r--ext/tk/lib/tkextlib/ICONS/icons.rb129
-rw-r--r--ext/tk/lib/tkextlib/ICONS/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/SUPPORT_STATUS196
-rw-r--r--ext/tk/lib/tkextlib/blt.rb187
-rw-r--r--ext/tk/lib/tkextlib/blt/barchart.rb79
-rw-r--r--ext/tk/lib/tkextlib/blt/bitmap.rb99
-rw-r--r--ext/tk/lib/tkextlib/blt/busy.rb82
-rw-r--r--ext/tk/lib/tkextlib/blt/component.rb1835
-rw-r--r--ext/tk/lib/tkextlib/blt/container.rb28
-rw-r--r--ext/tk/lib/tkextlib/blt/cutbuffer.rb23
-rw-r--r--ext/tk/lib/tkextlib/blt/dragdrop.rb214
-rw-r--r--ext/tk/lib/tkextlib/blt/eps.rb32
-rw-r--r--ext/tk/lib/tkextlib/blt/graph.rb67
-rw-r--r--ext/tk/lib/tkextlib/blt/htext.rb110
-rw-r--r--ext/tk/lib/tkextlib/blt/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/blt/spline.rb23
-rw-r--r--ext/tk/lib/tkextlib/blt/stripchart.rb74
-rw-r--r--ext/tk/lib/tkextlib/blt/table.rb344
-rw-r--r--ext/tk/lib/tkextlib/blt/tabnotebook.rb21
-rw-r--r--ext/tk/lib/tkextlib/blt/tabset.rb401
-rw-r--r--ext/tk/lib/tkextlib/blt/ted.rb62
-rw-r--r--ext/tk/lib/tkextlib/blt/tile.rb21
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/button.rb16
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/checkbutton.rb17
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/frame.rb16
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/label.rb16
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/radiobutton.rb17
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/scrollbar.rb16
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/toplevel.rb16
-rw-r--r--ext/tk/lib/tkextlib/blt/tree.rb923
-rw-r--r--ext/tk/lib/tkextlib/blt/treeview.rb1146
-rw-r--r--ext/tk/lib/tkextlib/blt/unix_dnd.rb129
-rw-r--r--ext/tk/lib/tkextlib/blt/vector.rb243
-rw-r--r--ext/tk/lib/tkextlib/blt/watch.rb142
-rw-r--r--ext/tk/lib/tkextlib/blt/win_printer.rb61
-rw-r--r--ext/tk/lib/tkextlib/blt/winop.rb107
-rw-r--r--ext/tk/lib/tkextlib/bwidget.rb151
-rw-r--r--ext/tk/lib/tkextlib/bwidget/arrowbutton.rb21
-rw-r--r--ext/tk/lib/tkextlib/bwidget/bitmap.rb21
-rw-r--r--ext/tk/lib/tkextlib/bwidget/button.rb31
-rw-r--r--ext/tk/lib/tkextlib/bwidget/buttonbox.rb78
-rw-r--r--ext/tk/lib/tkextlib/bwidget/combobox.rb45
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dialog.rb157
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dragsite.rb31
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dropsite.rb39
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dynamichelp.rb56
-rw-r--r--ext/tk/lib/tkextlib/bwidget/entry.rb43
-rw-r--r--ext/tk/lib/tkextlib/bwidget/label.rb41
-rw-r--r--ext/tk/lib/tkextlib/bwidget/labelentry.rb80
-rw-r--r--ext/tk/lib/tkextlib/bwidget/labelframe.rb46
-rw-r--r--ext/tk/lib/tkextlib/bwidget/listbox.rb339
-rw-r--r--ext/tk/lib/tkextlib/bwidget/mainframe.rb92
-rw-r--r--ext/tk/lib/tkextlib/bwidget/messagedlg.rb178
-rw-r--r--ext/tk/lib/tkextlib/bwidget/notebook.rb148
-rw-r--r--ext/tk/lib/tkextlib/bwidget/pagesmanager.rb61
-rw-r--r--ext/tk/lib/tkextlib/bwidget/panedwindow.rb31
-rw-r--r--ext/tk/lib/tkextlib/bwidget/panelframe.rb51
-rw-r--r--ext/tk/lib/tkextlib/bwidget/passwddlg.rb44
-rw-r--r--ext/tk/lib/tkextlib/bwidget/progressbar.rb20
-rw-r--r--ext/tk/lib/tkextlib/bwidget/progressdlg.rb54
-rw-r--r--ext/tk/lib/tkextlib/bwidget/scrollableframe.rb34
-rw-r--r--ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb32
-rw-r--r--ext/tk/lib/tkextlib/bwidget/scrollview.rb25
-rw-r--r--ext/tk/lib/tkextlib/bwidget/selectcolor.rb45
-rw-r--r--ext/tk/lib/tkextlib/bwidget/selectfont.rb85
-rw-r--r--ext/tk/lib/tkextlib/bwidget/separator.rb20
-rw-r--r--ext/tk/lib/tkextlib/bwidget/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/spinbox.rb98
-rw-r--r--ext/tk/lib/tkextlib/bwidget/statusbar.rb46
-rw-r--r--ext/tk/lib/tkextlib/bwidget/titleframe.rb27
-rw-r--r--ext/tk/lib/tkextlib/bwidget/tree.rb434
-rw-r--r--ext/tk/lib/tkextlib/bwidget/widget.rb113
-rw-r--r--ext/tk/lib/tkextlib/itcl.rb13
-rw-r--r--ext/tk/lib/tkextlib/itcl/incr_tcl.rb172
-rw-r--r--ext/tk/lib/tkextlib/itcl/setup.rb13
-rw-r--r--ext/tk/lib/tkextlib/itk.rb13
-rw-r--r--ext/tk/lib/tkextlib/itk/incr_tk.rb428
-rw-r--r--ext/tk/lib/tkextlib/itk/setup.rb13
-rw-r--r--ext/tk/lib/tkextlib/iwidgets.rb94
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/buttonbox.rb119
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/calendar.rb106
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb53
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb38
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/checkbox.rb116
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/combobox.rb104
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/dateentry.rb20
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/datefield.rb58
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/dialog.rb20
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/dialogshell.rb119
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb50
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/entryfield.rb166
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/extbutton.rb40
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb46
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb33
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/feedback.rb35
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb46
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb33
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/finddialog.rb42
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/hierarchy.rb309
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb50
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/labeledframe.rb39
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb45
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/mainwindow.rb67
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/menubar.rb210
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/messagebox.rb91
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/messagedialog.rb20
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/notebook.rb168
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/optionmenu.rb92
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/panedwindow.rb132
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/promptdialog.rb131
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/pushbutton.rb35
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/radiobox.rb116
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scopedobject.rb24
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb347
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb59
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb58
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb207
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb538
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb20
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/selectionbox.rb102
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb92
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/shell.rb38
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/spindate.rb48
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/spinint.rb30
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/spinner.rb150
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/spintime.rb48
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb169
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/tabset.rb99
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/timeentry.rb25
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/timefield.rb58
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/toolbar.rb112
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/watch.rb56
-rwxr-xr-xext/tk/lib/tkextlib/pkg_checker.rb184
-rw-r--r--ext/tk/lib/tkextlib/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tcllib.rb90
-rw-r--r--ext/tk/lib/tkextlib/tcllib/README135
-rw-r--r--ext/tk/lib/tkextlib/tcllib/autoscroll.rb158
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ctext.rb160
-rw-r--r--ext/tk/lib/tkextlib/tcllib/cursor.rb97
-rw-r--r--ext/tk/lib/tkextlib/tcllib/datefield.rb57
-rw-r--r--ext/tk/lib/tkextlib/tcllib/dialog.rb84
-rw-r--r--ext/tk/lib/tkextlib/tcllib/getstring.rb131
-rw-r--r--ext/tk/lib/tkextlib/tcllib/history.rb73
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ico.rb114
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ip_entry.rb66
-rw-r--r--ext/tk/lib/tkextlib/tcllib/panelframe.rb72
-rw-r--r--ext/tk/lib/tkextlib/tcllib/plotchart.rb865
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ruler.rb65
-rw-r--r--ext/tk/lib/tkextlib/tcllib/screenruler.rb68
-rw-r--r--ext/tk/lib/tkextlib/tcllib/scrollwin.rb61
-rw-r--r--ext/tk/lib/tkextlib/tcllib/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tcllib/style.rb61
-rw-r--r--ext/tk/lib/tkextlib/tcllib/superframe.rb51
-rw-r--r--ext/tk/lib/tkextlib/tcllib/swaplist.rb147
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tablelist.rb27
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tablelist_core.rb770
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb25
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tkpiechart.rb308
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tooltip.rb95
-rw-r--r--ext/tk/lib/tkextlib/tcllib/widget.rb48
-rw-r--r--ext/tk/lib/tkextlib/tclx.rb13
-rw-r--r--ext/tk/lib/tkextlib/tclx/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tclx/tclx.rb74
-rw-r--r--ext/tk/lib/tkextlib/tile.rb225
-rw-r--r--ext/tk/lib/tkextlib/tile/dialog.rb84
-rw-r--r--ext/tk/lib/tkextlib/tile/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tile/style.rb103
-rw-r--r--ext/tk/lib/tkextlib/tile/tbutton.rb30
-rw-r--r--ext/tk/lib/tkextlib/tile/tcheckbutton.rb32
-rw-r--r--ext/tk/lib/tkextlib/tile/tcombobox.rb55
-rw-r--r--ext/tk/lib/tkextlib/tile/tentry.rb40
-rw-r--r--ext/tk/lib/tkextlib/tile/tframe.rb30
-rw-r--r--ext/tk/lib/tkextlib/tile/tlabel.rb30
-rw-r--r--ext/tk/lib/tkextlib/tile/tlabelframe.rb30
-rw-r--r--ext/tk/lib/tkextlib/tile/tmenubutton.rb30
-rw-r--r--ext/tk/lib/tkextlib/tile/tnotebook.rb110
-rw-r--r--ext/tk/lib/tkextlib/tile/tpaned.rb188
-rw-r--r--ext/tk/lib/tkextlib/tile/tprogressbar.rb53
-rw-r--r--ext/tk/lib/tkextlib/tile/tradiobutton.rb32
-rw-r--r--ext/tk/lib/tkextlib/tile/treeview.rb280
-rw-r--r--ext/tk/lib/tkextlib/tile/tscale.rb50
-rw-r--r--ext/tk/lib/tkextlib/tile/tscrollbar.rb30
-rw-r--r--ext/tk/lib/tkextlib/tile/tseparator.rb30
-rw-r--r--ext/tk/lib/tkextlib/tile/tsquare.rb30
-rw-r--r--ext/tk/lib/tkextlib/tkDND.rb18
-rw-r--r--ext/tk/lib/tkextlib/tkDND/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tkDND/shape.rb123
-rw-r--r--ext/tk/lib/tkextlib/tkDND/tkdnd.rb164
-rw-r--r--ext/tk/lib/tkextlib/tkHTML.rb13
-rw-r--r--ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb444
-rw-r--r--ext/tk/lib/tkextlib/tkHTML/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tkimg.rb36
-rw-r--r--ext/tk/lib/tkextlib/tkimg/README26
-rw-r--r--ext/tk/lib/tkextlib/tkimg/bmp.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/gif.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/ico.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/jpeg.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/pcx.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/pixmap.rb44
-rw-r--r--ext/tk/lib/tkextlib/tkimg/png.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/ppm.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/ps.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tkimg/sgi.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/sun.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/tga.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/tiff.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/window.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/xbm.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/xpm.rb33
-rw-r--r--ext/tk/lib/tkextlib/tktable.rb14
-rw-r--r--ext/tk/lib/tkextlib/tktable/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tktable/tktable.rb839
-rw-r--r--ext/tk/lib/tkextlib/tktrans.rb14
-rw-r--r--ext/tk/lib/tkextlib/tktrans/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tktrans/tktrans.rb64
-rw-r--r--ext/tk/lib/tkextlib/treectrl.rb13
-rw-r--r--ext/tk/lib/tkextlib/treectrl/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/treectrl/tktreectrl.rb2311
-rw-r--r--ext/tk/lib/tkextlib/trofs.rb13
-rw-r--r--ext/tk/lib/tkextlib/trofs/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/trofs/trofs.rb51
-rw-r--r--ext/tk/lib/tkextlib/vu.rb48
-rw-r--r--ext/tk/lib/tkextlib/vu/bargraph.rb61
-rw-r--r--ext/tk/lib/tkextlib/vu/charts.rb53
-rw-r--r--ext/tk/lib/tkextlib/vu/dial.rb102
-rw-r--r--ext/tk/lib/tkextlib/vu/pie.rb235
-rw-r--r--ext/tk/lib/tkextlib/vu/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/vu/spinbox.rb22
-rw-r--r--ext/tk/lib/tkextlib/winico.rb14
-rw-r--r--ext/tk/lib/tkextlib/winico/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/winico/winico.rb189
-rw-r--r--ext/tk/lib/tkfont.rb4
-rw-r--r--ext/tk/lib/tkmacpkg.rb4
-rw-r--r--ext/tk/lib/tkmenubar.rb4
-rw-r--r--ext/tk/lib/tkmngfocus.rb4
-rw-r--r--ext/tk/lib/tkpalette.rb4
-rw-r--r--ext/tk/lib/tkscrollbox.rb4
-rw-r--r--ext/tk/lib/tktext.rb4
-rw-r--r--ext/tk/lib/tkvirtevent.rb4
-rw-r--r--ext/tk/lib/tkwinpkg.rb4
-rw-r--r--ext/tk/old-README.tcltklib.eucj159
-rw-r--r--ext/tk/sample/24hr_clock.rb286
-rw-r--r--ext/tk/sample/binding_sample.rb87
-rw-r--r--ext/tk/sample/bindtag_sample.rb127
-rw-r--r--ext/tk/sample/binstr_usage.rb39
-rw-r--r--ext/tk/sample/btn_with_frame.rb20
-rw-r--r--ext/tk/sample/cd_timer.rb81
-rw-r--r--ext/tk/sample/cmd_res_test.rb17
-rw-r--r--ext/tk/sample/cmd_resource5
-rw-r--r--ext/tk/sample/demos-en/ChangeLog64
-rw-r--r--ext/tk/sample/demos-en/ChangeLog.prev9
-rw-r--r--ext/tk/sample/demos-en/README138
-rw-r--r--ext/tk/sample/demos-en/README.1st18
-rw-r--r--ext/tk/sample/demos-en/README.tkencoding29
-rw-r--r--ext/tk/sample/demos-en/anilabel.rb172
-rw-r--r--ext/tk/sample/demos-en/aniwave.rb115
-rw-r--r--ext/tk/sample/demos-en/arrow.rb239
-rw-r--r--ext/tk/sample/demos-en/bind.rb128
-rw-r--r--ext/tk/sample/demos-en/bitmap.rb73
-rw-r--r--ext/tk/sample/demos-en/browse163
-rw-r--r--ext/tk/sample/demos-en/browse282
-rw-r--r--ext/tk/sample/demos-en/button.rb84
-rw-r--r--ext/tk/sample/demos-en/check.rb70
-rw-r--r--ext/tk/sample/demos-en/check2.rb107
-rw-r--r--ext/tk/sample/demos-en/clrpick.rb77
-rw-r--r--ext/tk/sample/demos-en/colors.rb148
-rw-r--r--ext/tk/sample/demos-en/cscroll.rb134
-rw-r--r--ext/tk/sample/demos-en/ctext.rb186
-rw-r--r--ext/tk/sample/demos-en/dialog1.rb38
-rw-r--r--ext/tk/sample/demos-en/dialog2.rb41
-rw-r--r--ext/tk/sample/demos-en/doc.org/README7
-rw-r--r--ext/tk/sample/demos-en/doc.org/README.JP14
-rw-r--r--ext/tk/sample/demos-en/doc.org/README.tk8046
-rw-r--r--ext/tk/sample/demos-en/doc.org/license.terms39
-rw-r--r--ext/tk/sample/demos-en/doc.org/license.terms.tk8039
-rw-r--r--ext/tk/sample/demos-en/entry1.rb56
-rw-r--r--ext/tk/sample/demos-en/entry2.rb91
-rw-r--r--ext/tk/sample/demos-en/entry3.rb200
-rw-r--r--ext/tk/sample/demos-en/filebox.rb97
-rw-r--r--ext/tk/sample/demos-en/floor.rb1721
-rw-r--r--ext/tk/sample/demos-en/floor2.rb1720
-rw-r--r--ext/tk/sample/demos-en/form.rb62
-rw-r--r--ext/tk/sample/demos-en/goldberg.rb1999
-rw-r--r--ext/tk/sample/demos-en/hello14
-rw-r--r--ext/tk/sample/demos-en/hscale.rb74
-rw-r--r--ext/tk/sample/demos-en/icon.rb99
-rw-r--r--ext/tk/sample/demos-en/image1.rb60
-rw-r--r--ext/tk/sample/demos-en/image2.rb105
-rw-r--r--ext/tk/sample/demos-en/image3.rb122
-rw-r--r--ext/tk/sample/demos-en/items.rb374
-rw-r--r--ext/tk/sample/demos-en/ixset333
-rw-r--r--ext/tk/sample/demos-en/ixset2367
-rw-r--r--ext/tk/sample/demos-en/label.rb69
-rw-r--r--ext/tk/sample/demos-en/labelframe.rb93
-rw-r--r--ext/tk/sample/demos-en/menu.rb194
-rw-r--r--ext/tk/sample/demos-en/menu84.rb213
-rw-r--r--ext/tk/sample/demos-en/menubu.rb235
-rw-r--r--ext/tk/sample/demos-en/msgbox.rb88
-rw-r--r--ext/tk/sample/demos-en/paned1.rb45
-rw-r--r--ext/tk/sample/demos-en/paned2.rb92
-rw-r--r--ext/tk/sample/demos-en/patch_1.1c193
-rw-r--r--ext/tk/sample/demos-en/pendulum.rb223
-rw-r--r--ext/tk/sample/demos-en/plot.rb122
-rw-r--r--ext/tk/sample/demos-en/puzzle.rb120
-rw-r--r--ext/tk/sample/demos-en/radio.rb84
-rw-r--r--ext/tk/sample/demos-en/radio2.rb106
-rw-r--r--ext/tk/sample/demos-en/radio3.rb114
-rw-r--r--ext/tk/sample/demos-en/rmt268
-rw-r--r--ext/tk/sample/demos-en/rolodex320
-rw-r--r--ext/tk/sample/demos-en/rolodex-j323
-rw-r--r--ext/tk/sample/demos-en/ruler.rb203
-rw-r--r--ext/tk/sample/demos-en/sayings.rb104
-rw-r--r--ext/tk/sample/demos-en/search.rb180
-rw-r--r--ext/tk/sample/demos-en/spin.rb63
-rw-r--r--ext/tk/sample/demos-en/square81
-rw-r--r--ext/tk/sample/demos-en/states.rb78
-rw-r--r--ext/tk/sample/demos-en/style.rb211
-rw-r--r--ext/tk/sample/demos-en/tcolor526
-rw-r--r--ext/tk/sample/demos-en/text.rb126
-rw-r--r--ext/tk/sample/demos-en/timer136
-rw-r--r--ext/tk/sample/demos-en/tkencoding.rb42
-rw-r--r--ext/tk/sample/demos-en/twind.rb285
-rw-r--r--ext/tk/sample/demos-en/twind2.rb382
-rw-r--r--ext/tk/sample/demos-en/unicodeout.rb112
-rw-r--r--ext/tk/sample/demos-en/vscale.rb78
-rw-r--r--ext/tk/sample/demos-en/widget944
-rw-r--r--ext/tk/sample/demos-jp/README54
-rw-r--r--ext/tk/sample/demos-jp/README.1st20
-rw-r--r--ext/tk/sample/demos-jp/anilabel.rb174
-rw-r--r--ext/tk/sample/demos-jp/aniwave.rb116
-rw-r--r--ext/tk/sample/demos-jp/arrow.rb236
-rw-r--r--ext/tk/sample/demos-jp/bind.rb125
-rw-r--r--ext/tk/sample/demos-jp/bitmap.rb71
-rw-r--r--ext/tk/sample/demos-jp/browse163
-rw-r--r--ext/tk/sample/demos-jp/browse282
-rw-r--r--ext/tk/sample/demos-jp/button.rb81
-rw-r--r--ext/tk/sample/demos-jp/check.rb67
-rw-r--r--ext/tk/sample/demos-jp/check2.rb107
-rw-r--r--ext/tk/sample/demos-jp/clrpick.rb75
-rw-r--r--ext/tk/sample/demos-jp/colors.rb144
-rw-r--r--ext/tk/sample/demos-jp/cscroll.rb131
-rw-r--r--ext/tk/sample/demos-jp/ctext.rb182
-rw-r--r--ext/tk/sample/demos-jp/dialog1.rb38
-rw-r--r--ext/tk/sample/demos-jp/dialog2.rb42
-rw-r--r--ext/tk/sample/demos-jp/doc.org/README7
-rw-r--r--ext/tk/sample/demos-jp/doc.org/README.JP14
-rw-r--r--ext/tk/sample/demos-jp/doc.org/README.tk8046
-rw-r--r--ext/tk/sample/demos-jp/doc.org/license.terms39
-rw-r--r--ext/tk/sample/demos-jp/doc.org/license.terms.tk8039
-rw-r--r--ext/tk/sample/demos-jp/entry1.rb57
-rw-r--r--ext/tk/sample/demos-jp/entry2.rb88
-rw-r--r--ext/tk/sample/demos-jp/entry3.rb204
-rw-r--r--ext/tk/sample/demos-jp/filebox.rb96
-rw-r--r--ext/tk/sample/demos-jp/floor.rb1718
-rw-r--r--ext/tk/sample/demos-jp/floor2.rb1716
-rw-r--r--ext/tk/sample/demos-jp/form.rb63
-rw-r--r--ext/tk/sample/demos-jp/goldberg.rb2003
-rw-r--r--ext/tk/sample/demos-jp/hello9
-rw-r--r--ext/tk/sample/demos-jp/hscale.rb77
-rw-r--r--ext/tk/sample/demos-jp/icon.rb96
-rw-r--r--ext/tk/sample/demos-jp/image1.rb58
-rw-r--r--ext/tk/sample/demos-jp/image2.rb102
-rw-r--r--ext/tk/sample/demos-jp/image3.rb123
-rw-r--r--ext/tk/sample/demos-jp/items.rb371
-rw-r--r--ext/tk/sample/demos-jp/ixset333
-rw-r--r--ext/tk/sample/demos-jp/ixset2368
-rw-r--r--ext/tk/sample/demos-jp/label.rb65
-rw-r--r--ext/tk/sample/demos-jp/labelframe.rb98
-rw-r--r--ext/tk/sample/demos-jp/menu.rb196
-rw-r--r--ext/tk/sample/demos-jp/menu84.rb210
-rw-r--r--ext/tk/sample/demos-jp/menu8x.rb230
-rw-r--r--ext/tk/sample/demos-jp/menubu.rb235
-rw-r--r--ext/tk/sample/demos-jp/msgbox.rb86
-rw-r--r--ext/tk/sample/demos-jp/paned1.rb48
-rw-r--r--ext/tk/sample/demos-jp/paned2.rb96
-rw-r--r--ext/tk/sample/demos-jp/pendulum.rb224
-rw-r--r--ext/tk/sample/demos-jp/plot.rb119
-rw-r--r--ext/tk/sample/demos-jp/puzzle.rb116
-rw-r--r--ext/tk/sample/demos-jp/radio.rb81
-rw-r--r--ext/tk/sample/demos-jp/radio2.rb107
-rw-r--r--ext/tk/sample/demos-jp/radio3.rb114
-rw-r--r--ext/tk/sample/demos-jp/rmt268
-rw-r--r--ext/tk/sample/demos-jp/rolodex320
-rw-r--r--ext/tk/sample/demos-jp/rolodex-j299
-rw-r--r--ext/tk/sample/demos-jp/ruler.rb200
-rw-r--r--ext/tk/sample/demos-jp/sayings.rb100
-rw-r--r--ext/tk/sample/demos-jp/search.rb176
-rw-r--r--ext/tk/sample/demos-jp/spin.rb67
-rw-r--r--ext/tk/sample/demos-jp/square81
-rw-r--r--ext/tk/sample/demos-jp/states.rb71
-rw-r--r--ext/tk/sample/demos-jp/style.rb248
-rw-r--r--ext/tk/sample/demos-jp/tcolor533
-rw-r--r--ext/tk/sample/demos-jp/text.rb117
-rw-r--r--ext/tk/sample/demos-jp/timer136
-rw-r--r--ext/tk/sample/demos-jp/twind.rb285
-rw-r--r--ext/tk/sample/demos-jp/twind2.rb381
-rw-r--r--ext/tk/sample/demos-jp/unicodeout.rb115
-rw-r--r--ext/tk/sample/demos-jp/vscale.rb78
-rw-r--r--ext/tk/sample/demos-jp/widget973
-rw-r--r--ext/tk/sample/encstr_usage.rb29
-rw-r--r--ext/tk/sample/images/earth.gifbin51712 -> 0 bytes-rw-r--r--ext/tk/sample/images/earthris.gifbin6343 -> 0 bytes-rw-r--r--ext/tk/sample/images/face.xbm173
-rw-r--r--ext/tk/sample/images/flagdown.xbm27
-rw-r--r--ext/tk/sample/images/flagup.xbm27
-rw-r--r--ext/tk/sample/images/gray25.xbm6
-rw-r--r--ext/tk/sample/images/grey.256
-rw-r--r--ext/tk/sample/images/grey.56
-rw-r--r--ext/tk/sample/images/letters.xbm27
-rw-r--r--ext/tk/sample/images/noletter.xbm27
-rw-r--r--ext/tk/sample/images/pattern.xbm6
-rw-r--r--ext/tk/sample/images/tcllogo.gifbin2341 -> 0 bytes-rw-r--r--ext/tk/sample/images/teapot.ppm56
-rw-r--r--ext/tk/sample/irbtk.rb30
-rw-r--r--ext/tk/sample/iso2022-kr.txt2
-rw-r--r--ext/tk/sample/menubar1.rb51
-rw-r--r--ext/tk/sample/menubar2.rb56
-rw-r--r--ext/tk/sample/msgs_rb/README3
-rw-r--r--ext/tk/sample/msgs_rb/cs.msg84
-rw-r--r--ext/tk/sample/msgs_rb/de.msg88
-rw-r--r--ext/tk/sample/msgs_rb/el.msg98
-rw-r--r--ext/tk/sample/msgs_rb/en.msg83
-rw-r--r--ext/tk/sample/msgs_rb/en_gb.msg7
-rw-r--r--ext/tk/sample/msgs_rb/eo.msg87
-rw-r--r--ext/tk/sample/msgs_rb/es.msg84
-rw-r--r--ext/tk/sample/msgs_rb/fr.msg84
-rw-r--r--ext/tk/sample/msgs_rb/it.msg84
-rw-r--r--ext/tk/sample/msgs_rb/ja.msg13
-rw-r--r--ext/tk/sample/msgs_rb/nl.msg123
-rw-r--r--ext/tk/sample/msgs_rb/pl.msg87
-rw-r--r--ext/tk/sample/msgs_rb/ru.msg87
-rw-r--r--ext/tk/sample/msgs_rb2/README5
-rw-r--r--ext/tk/sample/msgs_rb2/de.msg88
-rw-r--r--ext/tk/sample/msgs_rb2/ja.msg85
-rw-r--r--ext/tk/sample/msgs_tk/README4
-rw-r--r--ext/tk/sample/msgs_tk/cs.msg84
-rw-r--r--ext/tk/sample/msgs_tk/de.msg88
-rw-r--r--ext/tk/sample/msgs_tk/el.msg103
-rw-r--r--ext/tk/sample/msgs_tk/en.msg83
-rw-r--r--ext/tk/sample/msgs_tk/en_gb.msg7
-rw-r--r--ext/tk/sample/msgs_tk/eo.msg87
-rw-r--r--ext/tk/sample/msgs_tk/es.msg84
-rw-r--r--ext/tk/sample/msgs_tk/fr.msg84
-rw-r--r--ext/tk/sample/msgs_tk/it.msg84
-rw-r--r--ext/tk/sample/msgs_tk/ja.msg13
-rw-r--r--ext/tk/sample/msgs_tk/license.terms39
-rw-r--r--ext/tk/sample/msgs_tk/nl.msg123
-rw-r--r--ext/tk/sample/msgs_tk/pl.msg87
-rw-r--r--ext/tk/sample/msgs_tk/ru.msg87
-rw-r--r--ext/tk/sample/multi-ip_sample.rb102
-rw-r--r--ext/tk/sample/multi-ip_sample2.rb29
-rw-r--r--ext/tk/sample/optobj_sample.rb67
-rw-r--r--ext/tk/sample/propagate.rb30
-rw-r--r--ext/tk/sample/remote-ip_sample.rb33
-rw-r--r--ext/tk/sample/remote-ip_sample2.rb56
-rw-r--r--ext/tk/sample/resource.en13
-rw-r--r--ext/tk/sample/resource.ja13
-rw-r--r--ext/tk/sample/safe-tk.rb115
-rw-r--r--ext/tk/sample/scrollframe.rb237
-rw-r--r--ext/tk/sample/tcltklib/batsu.gifbin538 -> 0 bytes-rw-r--r--ext/tk/sample/tcltklib/lines0.tcl42
-rw-r--r--ext/tk/sample/tcltklib/lines1.rb50
-rw-r--r--ext/tk/sample/tcltklib/lines2.rb54
-rw-r--r--ext/tk/sample/tcltklib/lines3.rb54
-rw-r--r--ext/tk/sample/tcltklib/lines4.rb54
-rw-r--r--ext/tk/sample/tcltklib/maru.gifbin481 -> 0 bytes-rw-r--r--ext/tk/sample/tcltklib/safeTk.rb22
-rw-r--r--ext/tk/sample/tcltklib/sample0.rb39
-rw-r--r--ext/tk/sample/tcltklib/sample1.rb634
-rw-r--r--ext/tk/sample/tcltklib/sample2.rb451
-rw-r--r--ext/tk/sample/tkalignbox.rb225
-rw-r--r--ext/tk/sample/tkballoonhelp.rb194
-rw-r--r--ext/tk/sample/tkbiff.rb155
-rw-r--r--ext/tk/sample/tkbrowse.rb79
-rw-r--r--ext/tk/sample/tkcombobox.rb426
-rw-r--r--ext/tk/sample/tkdialog.rb61
-rw-r--r--ext/tk/sample/tkextlib/ICONS/Orig_LICENSE.txt61
-rw-r--r--ext/tk/sample/tkextlib/ICONS/tkIcons195
-rw-r--r--ext/tk/sample/tkextlib/ICONS/tkIcons-sample.kde658
-rw-r--r--ext/tk/sample/tkextlib/ICONS/tkIcons.kde195
-rw-r--r--ext/tk/sample/tkextlib/ICONS/viewIcons.rb329
-rw-r--r--ext/tk/sample/tkextlib/blt/barchart5.rb101
-rw-r--r--ext/tk/sample/tkextlib/blt/calendar.rb117
-rw-r--r--ext/tk/sample/tkextlib/blt/graph6.rb2222
-rw-r--r--ext/tk/sample/tkextlib/blt/graph7.rb40
-rw-r--r--ext/tk/sample/tkextlib/blt/graph7a.rb63
-rw-r--r--ext/tk/sample/tkextlib/blt/graph7b.rb41
-rw-r--r--ext/tk/sample/tkextlib/blt/graph7c.rb45
-rw-r--r--ext/tk/sample/tkextlib/blt/images/buckskin.gifbin7561 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/blt/images/chalk.gifbin4378 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/blt/images/qv100.t.gifbin2694 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/blt/images/rain.gifbin3785 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/blt/images/sample.gifbin186103 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/blt/pareto.rb90
-rw-r--r--ext/tk/sample/tkextlib/blt/plot1.rb9
-rw-r--r--ext/tk/sample/tkextlib/blt/plot1b.rb10
-rw-r--r--ext/tk/sample/tkextlib/blt/readme.txt2
-rw-r--r--ext/tk/sample/tkextlib/blt/scripts/stipples.rb156
-rw-r--r--ext/tk/sample/tkextlib/blt/winop1.rb40
-rw-r--r--ext/tk/sample/tkextlib/blt/winop2.rb28
-rw-r--r--ext/tk/sample/tkextlib/bwidget/Orig_LICENSE.txt53
-rw-r--r--ext/tk/sample/tkextlib/bwidget/basic.rb198
-rw-r--r--ext/tk/sample/tkextlib/bwidget/bwidget.xbm46
-rw-r--r--ext/tk/sample/tkextlib/bwidget/demo.rb243
-rw-r--r--ext/tk/sample/tkextlib/bwidget/dnd.rb46
-rw-r--r--ext/tk/sample/tkextlib/bwidget/manager.rb150
-rw-r--r--ext/tk/sample/tkextlib/bwidget/select.rb82
-rw-r--r--ext/tk/sample/tkextlib/bwidget/tmpldlg.rb221
-rw-r--r--ext/tk/sample/tkextlib/bwidget/tree.rb289
-rw-r--r--ext/tk/sample/tkextlib/bwidget/x1.xbm2258
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/Orig_LICENSE.txt42
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/box.xbm14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/clear.gifbin279 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/close.gifbin249 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/copy.gifbin269 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/cut.gifbin179 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/exit.gifbin396 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/find.gifbin386 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/help.gifbin591 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/line.xbm14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/mag.gifbin183 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/new.gifbin212 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/open.gifbin258 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/oval.xbm14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/paste.gifbin376 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/points.xbm14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/poly.gifbin141 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/print.gifbin263 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/ruler.gifbin174 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/save.gifbin270 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/select.gifbin124 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/text.xbm14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/buttonbox.rb22
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/calendar.rb10
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/canvasprintbox.rb8
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/canvasprintdialog.rb8
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/checkbox.rb12
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/combobox.rb32
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/dateentry.rb7
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/datefield.rb8
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/dialog.rb20
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/dialogshell.rb14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/disjointlistbox.rb16
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/entryfield-1.rb39
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/entryfield-2.rb40
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/entryfield-3.rb40
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/extbutton.rb20
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/extfileselectionbox.rb8
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/extfileselectiondialog.rb29
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/feedback.rb10
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/fileselectionbox.rb8
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/fileselectiondialog.rb28
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/finddialog.rb15
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/hierarchy.rb25
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/hyperhelp.rb14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/labeledframe.rb14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/labeledwidget.rb13
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/mainwindow.rb64
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/menubar.rb124
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/menubar2.rb44
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/messagebox1.rb19
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/messagebox2.rb19
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/messagedialog.rb44
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/notebook.rb30
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/notebook2.rb30
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/optionmenu.rb14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/panedwindow.rb22
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/panedwindow2.rb22
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/promptdialog.rb17
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/pushbutton.rb9
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/radiobox.rb13
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/scrolledcanvas.rb13
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/scrolledframe.rb18
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/scrolledhtml.rb15
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/scrolledlistbox.rb22
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/scrolledtext.rb11
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/selectionbox.rb19
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/selectiondialog.rb12
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/shell.rb17
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/spindate.rb7
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/spinint.rb10
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/spinner.rb33
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/spintime.rb7
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/tabnotebook.rb26
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/tabnotebook2.rb30
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/tabset.rb34
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/timeentry.rb7
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/timefield.rb8
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/toolbar.rb152
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/watch.rb18
-rw-r--r--ext/tk/sample/tkextlib/tcllib/Orig_LICENSE.txt46
-rw-r--r--ext/tk/sample/tkextlib/tcllib/datefield.rb29
-rw-r--r--ext/tk/sample/tkextlib/tcllib/plotdemos1.rb158
-rw-r--r--ext/tk/sample/tkextlib/tcllib/plotdemos2.rb71
-rw-r--r--ext/tk/sample/tkextlib/tcllib/plotdemos3.rb83
-rw-r--r--ext/tk/sample/tkextlib/tcllib/xyplot.rb17
-rw-r--r--ext/tk/sample/tkextlib/tile/Orig_LICENSE.txt30
-rw-r--r--ext/tk/sample/tkextlib/tile/demo.rb972
-rw-r--r--ext/tk/sample/tkextlib/tile/iconlib.tcl110
-rw-r--r--ext/tk/sample/tkextlib/tile/readme.txt2
-rw-r--r--ext/tk/sample/tkextlib/tile/repeater.tcl117
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue.tcl149
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown-h.gifbin315 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown-p.gifbin312 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown.gifbin313 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft-h.gifbin329 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft-p.gifbin327 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft.gifbin323 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright-h.gifbin330 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright-p.gifbin327 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright.gifbin324 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup-h.gifbin309 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup-p.gifbin313 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup.gifbin314 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/button-h.gifbin696 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/button-n.gifbin770 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/button-n.xcfbin1942 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/button-p.gifbin769 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/check-hc.gifbin254 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/check-hu.gifbin234 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/check-nc.gifbin249 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/check-nu.gifbin229 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-hc.gifbin1098 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-hu.gifbin626 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-nc.gifbin389 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-nu.gifbin401 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-thumb-p.gifbin343 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-thumb.gifbin316 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-vthumb-p.gifbin333 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-vthumb.gifbin308 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/slider-p.gifbin182 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/slider.gifbin182 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/vslider-p.gifbin183 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/vslider.gifbin283 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/pkgIndex.tcl6
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik.tcl194
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowdown-n.gifbin273 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowdown-p.gifbin258 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowleft-n.gifbin292 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowleft-p.gifbin272 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowright-n.gifbin274 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowright-p.gifbin258 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowup-n.gifbin286 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowup-p.gifbin271 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-d.gifbin1266 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-h.gifbin896 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-n.gifbin881 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-p.gifbin625 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-s.gifbin859 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/check-c.gifbin434 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/check-u.gifbin423 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hsb-n.gifbin401 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hsb-p.gifbin395 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hslider-n.gifbin592 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-a.gifbin1116 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-arrow-n.gifbin61 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-d.gifbin1057 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-n.gifbin1095 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/radio-c.gifbin695 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/radio-u.gifbin686 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tab-n.gifbin383 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tab-p.gifbin878 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-a.gifbin907 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-n.gifbin238 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-p.gifbin927 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vsb-n.gifbin405 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vsb-p.gifbin399 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vslider-n.gifbin587 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/pkgIndex.tcl15
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc.rb200
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc.tcl163
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-h.gifbin522 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-n.gifbin554 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-p.gifbin548 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-hc.gifbin281 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-hu.gifbin273 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-nc.gifbin303 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-nu.gifbin294 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-hc.gifbin652 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-hu.gifbin644 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-nc.gifbin632 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-nu.gifbin621 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/pkgIndex.tcl15
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/pkgIndex.tcl16
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik.tcl125
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowdown-n.gifbin362 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowdown-p.gifbin250 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowleft-n.gifbin378 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowleft-p.gifbin267 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowright-n.gifbin379 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowright-p.gifbin266 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowup-n.gifbin363 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowup-p.gifbin251 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-h.gifbin439 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-n.gifbin443 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-p.gifbin302 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-hc.gifbin169 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-hu.gifbin170 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-nc.gifbin235 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-nu.gifbin226 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-pc.gifbin169 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/hsb-n.gifbin269 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/hslider-n.gifbin342 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-hc.gifbin178 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-hu.gifbin179 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-nc.gifbin236 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-nu.gifbin178 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-pc.gifbin178 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/vsb-n.gifbin366 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/vslider-n.gifbin336 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/toolbutton.tcl152
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/Orig_COPYRIGHT.txt12
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/README12
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/hv.rb313
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image1bin8995 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image10bin3095 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image11bin1425 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image12bin2468 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image13bin4073 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image14bin53 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image2bin42 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image3bin3473 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image4bin1988 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image5bin973 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image6bin2184 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image7bin2022 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image8bin1186 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image9bin139 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/index.html115
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image1bin1966 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image10bin255 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image11bin590 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image12bin254 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image13bin493 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image14bin195 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image15bin68 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image16bin157 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image17bin81 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image18bin545 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image19bin53 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image2bin49 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image20bin533 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image21bin564 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image22bin81 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image23bin539 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image24bin151 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image25bin453 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image26bin520 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image27bin565 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image28bin416 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image29bin121 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image3bin10835 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image30bin663 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image31bin78 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image32bin556 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image33bin598 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image34bin496 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image35bin724 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image36bin404 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image37bin124 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image38bin8330 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image39bin369 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image4bin268 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image5bin492 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image6bin246 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image7bin551 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image8bin497 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image9bin492 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/index.html433
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image1bin113 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image10bin5088 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image11bin4485 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image12bin3579 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image13bin5119 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image14bin3603 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image2bin74 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image3bin681 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image4bin3056 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image5bin2297 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image6bin79 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image7bin1613 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image8bin864 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image9bin2379 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/index.html2787
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image1bin42 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image2bin14343 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image3bin17750 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image4bin61 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image5bin201 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image6bin214 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image7bin149 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image8bin203 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image9bin1504 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/index.html768
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/ss.rb436
-rw-r--r--ext/tk/sample/tkextlib/tkimg/demo.rb1478
-rw-r--r--ext/tk/sample/tkextlib/tkimg/license_terms_of_Img_extension41
-rw-r--r--ext/tk/sample/tkextlib/tkimg/readme.txt3
-rw-r--r--ext/tk/sample/tkextlib/tktable/Orig_LICENSE.txt52
-rw-r--r--ext/tk/sample/tkextlib/tktable/basic.rb60
-rw-r--r--ext/tk/sample/tkextlib/tktable/buttons.rb76
-rw-r--r--ext/tk/sample/tkextlib/tktable/command.rb89
-rw-r--r--ext/tk/sample/tkextlib/tktable/debug.rb101
-rw-r--r--ext/tk/sample/tkextlib/tktable/dynarows.rb99
-rw-r--r--ext/tk/sample/tkextlib/tktable/maxsize.rb67
-rw-r--r--ext/tk/sample/tkextlib/tktable/spreadsheet.rb137
-rwxr-xr-xext/tk/sample/tkextlib/tktable/tcllogo.gifbin2341 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/tktable/valid.rb88
-rw-r--r--ext/tk/sample/tkextlib/treectrl/bitmaps.rb76
-rw-r--r--ext/tk/sample/tkextlib/treectrl/demo.rb1310
-rw-r--r--ext/tk/sample/tkextlib/treectrl/explorer.rb430
-rw-r--r--ext/tk/sample/tkextlib/treectrl/help.rb404
-rw-r--r--ext/tk/sample/tkextlib/treectrl/imovie.rb130
-rw-r--r--ext/tk/sample/tkextlib/treectrl/layout.rb159
-rw-r--r--ext/tk/sample/tkextlib/treectrl/mailwasher.rb269
-rw-r--r--ext/tk/sample/tkextlib/treectrl/outlook-folders.rb124
-rw-r--r--ext/tk/sample/tkextlib/treectrl/outlook-newgroup.rb448
-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/big-dll.gifbin437 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/big-exe.gifbin368 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/big-file.gifbin466 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/big-folder.gifbin459 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/big-txt.gifbin392 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/checked.gifbin78 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/file.gifbin279 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/folder-closed.gifbin111 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/folder-open.gifbin120 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/help-book-closed.gifbin115 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/help-book-open.gifbin128 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/help-page.gifbin132 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-01.gifbin5406 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-02.gifbin5912 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-03.gifbin4696 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-04.gifbin5783 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-05.gifbin3238 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-06.gifbin3509 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-07.gifbin2091 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-check-off.gifbin70 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-check-on.gifbin76 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-print.gifbin124 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-radio-off.gifbin68 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-radio-on.gifbin71 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-search.gifbin114 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-security.gifbin108 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/mac-collapse.gifbin275 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/mac-expand.gifbin277 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-arrow.gifbin73 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-clip.gifbin73 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-deleted.gifbin138 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-draft.gifbin134 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-folder.gifbin133 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-group.gifbin144 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-inbox.gifbin133 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-local.gifbin146 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-main.gifbin174 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-outbox.gifbin136 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-read-2.gifbin343 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-read.gifbin304 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-sent.gifbin132 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-server.gifbin163 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-unread.gifbin303 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-watch.gifbin98 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/sky.gifbin6454 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/small-dll.gifbin311 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/small-exe.gifbin115 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/small-file.gifbin338 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/small-folder.gifbin307 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/small-txt.gifbin302 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/unchecked.gifbin72 -> 0 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/random.rb508
-rw-r--r--ext/tk/sample/tkextlib/treectrl/readme.txt2
-rw-r--r--ext/tk/sample/tkextlib/treectrl/www-options.rb303
-rw-r--r--ext/tk/sample/tkextlib/vu/Orig_LICENSE.txt51
-rw-r--r--ext/tk/sample/tkextlib/vu/README.txt50
-rw-r--r--ext/tk/sample/tkextlib/vu/canvItems.rb90
-rw-r--r--ext/tk/sample/tkextlib/vu/canvSticker.rb82
-rw-r--r--ext/tk/sample/tkextlib/vu/canvSticker2.rb99
-rw-r--r--ext/tk/sample/tkextlib/vu/dial_demo.rb113
-rw-r--r--ext/tk/sample/tkextlib/vu/m128_000.xbm174
-rw-r--r--ext/tk/sample/tkextlib/vu/oscilloscope.rb68
-rw-r--r--ext/tk/sample/tkextlib/vu/pie.rb56
-rw-r--r--ext/tk/sample/tkextlib/vu/vu_demo.rb67
-rw-r--r--ext/tk/sample/tkfrom.rb132
-rw-r--r--ext/tk/sample/tkhello.rb10
-rw-r--r--ext/tk/sample/tkline.rb47
-rw-r--r--ext/tk/sample/tkmenubutton.rb135
-rw-r--r--ext/tk/sample/tkmsgcat-load_rb.rb102
-rw-r--r--ext/tk/sample/tkmsgcat-load_rb2.rb102
-rw-r--r--ext/tk/sample/tkmsgcat-load_tk.rb118
-rw-r--r--ext/tk/sample/tkmulticolumnlist.rb743
-rw-r--r--ext/tk/sample/tkmultilistbox.rb654
-rw-r--r--ext/tk/sample/tkmultilistframe.rb940
-rw-r--r--ext/tk/sample/tkoptdb-safeTk.rb73
-rw-r--r--ext/tk/sample/tkoptdb.rb106
-rw-r--r--ext/tk/sample/tkrttimer.rb68
-rw-r--r--ext/tk/sample/tktextframe.rb162
-rw-r--r--ext/tk/sample/tktextio.rb603
-rw-r--r--ext/tk/sample/tktimer.rb50
-rw-r--r--ext/tk/sample/tktimer2.rb47
-rw-r--r--ext/tk/sample/tktimer3.rb59
-rw-r--r--ext/tk/sample/tktree.rb103
-rw-r--r--ext/tk/sample/tktree.tcl305
-rw-r--r--ext/tk/stubs.c516
-rw-r--r--ext/tk/stubs.h33
-rw-r--r--ext/tk/tcltklib.c8140
-rw-r--r--ext/tk/tkutil/.cvsignore3
-rw-r--r--ext/tk/tkutil/depend1
-rw-r--r--ext/tk/tkutil/extconf.rb4
-rw-r--r--ext/tk/tkutil/tkutil.c1639
-rw-r--r--ext/win32/depend2
-rw-r--r--ext/win32/extconf.rb4
-rw-r--r--ext/win32/lib/win32/resolv.rb107
-rw-r--r--ext/win32/resolv/depend17
-rw-r--r--ext/win32/resolv/extconf.rb7
-rw-r--r--ext/win32/resolv/resolv.c261
-rw-r--r--ext/win32ole/.cvsignore4
-rw-r--r--ext/win32ole/depend1
-rw-r--r--ext/win32ole/doc/win32ole.rd294
-rw-r--r--ext/win32ole/extconf.rb41
-rw-r--r--ext/win32ole/lib/win32ole/property.rb16
-rw-r--r--ext/win32ole/sample/excel1.rb22
-rw-r--r--ext/win32ole/sample/excel2.rb30
-rw-r--r--ext/win32ole/sample/excel3.rb13
-rw-r--r--ext/win32ole/sample/ie.rb11
-rw-r--r--ext/win32ole/sample/ieconst.rb32
-rw-r--r--ext/win32ole/sample/ienavi.rb40
-rw-r--r--ext/win32ole/sample/oledirs.rb23
-rw-r--r--ext/win32ole/sample/olegen.rb348
-rw-r--r--ext/win32ole/sample/xml.rb7306
-rw-r--r--ext/win32ole/tests/oleserver.rb10
-rw-r--r--ext/win32ole/tests/testNIL2VTEMPTY.rb28
-rw-r--r--ext/win32ole/tests/testOLEEVENT.rb91
-rw-r--r--ext/win32ole/tests/testOLEMETHOD.rb92
-rw-r--r--ext/win32ole/tests/testOLEPARAM.rb65
-rw-r--r--ext/win32ole/tests/testOLETYPE.rb96
-rw-r--r--ext/win32ole/tests/testOLEVARIABLE.rb49
-rw-r--r--ext/win32ole/tests/testVARIANT.rb32
-rw-r--r--ext/win32ole/tests/testWIN32OLE.rb372
-rw-r--r--ext/win32ole/tests/test_ole_methods.rb36
-rw-r--r--ext/win32ole/tests/test_propertyputref.rb19
-rw-r--r--ext/win32ole/tests/test_word.rb37
-rw-r--r--ext/win32ole/tests/testall.rb15
-rw-r--r--ext/win32ole/win32ole.c6249
-rw-r--r--ext/zlib/.cvsignore3
-rw-r--r--ext/zlib/.gitignore1
-rw-r--r--ext/zlib/depend177
-rw-r--r--ext/zlib/doc/zlib.rd911
-rw-r--r--ext/zlib/extconf.rb105
-rw-r--r--ext/zlib/zlib.c3740
-rw-r--r--ext/zlib/zlib.gemspec31
1835 files changed, 139042 insertions, 222443 deletions
diff --git a/ext/-test-/RUBY_ALIGNOF/c.c b/ext/-test-/RUBY_ALIGNOF/c.c
new file mode 100644
index 0000000000..7a9f7cb498
--- /dev/null
+++ b/ext/-test-/RUBY_ALIGNOF/c.c
@@ -0,0 +1,15 @@
+#include "ruby.h"
+#include <stddef.h>
+
+struct T {
+ char _;
+ double t;
+};
+
+RBIMPL_STATIC_ASSERT(RUBY_ALIGNOF, RUBY_ALIGNOF(double) == offsetof(struct T, t));
+
+void
+Init_RUBY_ALIGNOF(void)
+{
+ // Windows linker mandates this symbol to exist.
+}
diff --git a/ext/-test-/RUBY_ALIGNOF/cpp.cpp b/ext/-test-/RUBY_ALIGNOF/cpp.cpp
new file mode 100644
index 0000000000..ed76d49b9f
--- /dev/null
+++ b/ext/-test-/RUBY_ALIGNOF/cpp.cpp
@@ -0,0 +1,9 @@
+#include "ruby.h"
+#include <cstddef>
+
+struct T {
+ char _;
+ double t;
+};
+
+RBIMPL_STATIC_ASSERT(RUBY_ALIGNOF, RUBY_ALIGNOF(double) == offsetof(T, t));
diff --git a/ext/-test-/RUBY_ALIGNOF/depend b/ext/-test-/RUBY_ALIGNOF/depend
new file mode 100644
index 0000000000..103d20b33c
--- /dev/null
+++ b/ext/-test-/RUBY_ALIGNOF/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+c.o: $(RUBY_EXTCONF_H)
+c.o: $(arch_hdrdir)/ruby/config.h
+c.o: $(hdrdir)/ruby.h
+c.o: $(hdrdir)/ruby/assert.h
+c.o: $(hdrdir)/ruby/backward.h
+c.o: $(hdrdir)/ruby/backward/2/assume.h
+c.o: $(hdrdir)/ruby/backward/2/attributes.h
+c.o: $(hdrdir)/ruby/backward/2/bool.h
+c.o: $(hdrdir)/ruby/backward/2/inttypes.h
+c.o: $(hdrdir)/ruby/backward/2/limits.h
+c.o: $(hdrdir)/ruby/backward/2/long_long.h
+c.o: $(hdrdir)/ruby/backward/2/stdalign.h
+c.o: $(hdrdir)/ruby/backward/2/stdarg.h
+c.o: $(hdrdir)/ruby/defines.h
+c.o: $(hdrdir)/ruby/intern.h
+c.o: $(hdrdir)/ruby/internal/abi.h
+c.o: $(hdrdir)/ruby/internal/anyargs.h
+c.o: $(hdrdir)/ruby/internal/arithmetic.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+c.o: $(hdrdir)/ruby/internal/assume.h
+c.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+c.o: $(hdrdir)/ruby/internal/attr/artificial.h
+c.o: $(hdrdir)/ruby/internal/attr/cold.h
+c.o: $(hdrdir)/ruby/internal/attr/const.h
+c.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+c.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+c.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+c.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+c.o: $(hdrdir)/ruby/internal/attr/error.h
+c.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+c.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+c.o: $(hdrdir)/ruby/internal/attr/format.h
+c.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+c.o: $(hdrdir)/ruby/internal/attr/noalias.h
+c.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+c.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+c.o: $(hdrdir)/ruby/internal/attr/noinline.h
+c.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+c.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+c.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+c.o: $(hdrdir)/ruby/internal/attr/pure.h
+c.o: $(hdrdir)/ruby/internal/attr/restrict.h
+c.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+c.o: $(hdrdir)/ruby/internal/attr/warning.h
+c.o: $(hdrdir)/ruby/internal/attr/weakref.h
+c.o: $(hdrdir)/ruby/internal/cast.h
+c.o: $(hdrdir)/ruby/internal/compiler_is.h
+c.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+c.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+c.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+c.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+c.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+c.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+c.o: $(hdrdir)/ruby/internal/compiler_since.h
+c.o: $(hdrdir)/ruby/internal/config.h
+c.o: $(hdrdir)/ruby/internal/constant_p.h
+c.o: $(hdrdir)/ruby/internal/core.h
+c.o: $(hdrdir)/ruby/internal/core/rarray.h
+c.o: $(hdrdir)/ruby/internal/core/rbasic.h
+c.o: $(hdrdir)/ruby/internal/core/rbignum.h
+c.o: $(hdrdir)/ruby/internal/core/rclass.h
+c.o: $(hdrdir)/ruby/internal/core/rdata.h
+c.o: $(hdrdir)/ruby/internal/core/rfile.h
+c.o: $(hdrdir)/ruby/internal/core/rhash.h
+c.o: $(hdrdir)/ruby/internal/core/robject.h
+c.o: $(hdrdir)/ruby/internal/core/rregexp.h
+c.o: $(hdrdir)/ruby/internal/core/rstring.h
+c.o: $(hdrdir)/ruby/internal/core/rstruct.h
+c.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+c.o: $(hdrdir)/ruby/internal/ctype.h
+c.o: $(hdrdir)/ruby/internal/dllexport.h
+c.o: $(hdrdir)/ruby/internal/dosish.h
+c.o: $(hdrdir)/ruby/internal/error.h
+c.o: $(hdrdir)/ruby/internal/eval.h
+c.o: $(hdrdir)/ruby/internal/event.h
+c.o: $(hdrdir)/ruby/internal/fl_type.h
+c.o: $(hdrdir)/ruby/internal/gc.h
+c.o: $(hdrdir)/ruby/internal/glob.h
+c.o: $(hdrdir)/ruby/internal/globals.h
+c.o: $(hdrdir)/ruby/internal/has/attribute.h
+c.o: $(hdrdir)/ruby/internal/has/builtin.h
+c.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+c.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+c.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+c.o: $(hdrdir)/ruby/internal/has/extension.h
+c.o: $(hdrdir)/ruby/internal/has/feature.h
+c.o: $(hdrdir)/ruby/internal/has/warning.h
+c.o: $(hdrdir)/ruby/internal/intern/array.h
+c.o: $(hdrdir)/ruby/internal/intern/bignum.h
+c.o: $(hdrdir)/ruby/internal/intern/class.h
+c.o: $(hdrdir)/ruby/internal/intern/compar.h
+c.o: $(hdrdir)/ruby/internal/intern/complex.h
+c.o: $(hdrdir)/ruby/internal/intern/cont.h
+c.o: $(hdrdir)/ruby/internal/intern/dir.h
+c.o: $(hdrdir)/ruby/internal/intern/enum.h
+c.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+c.o: $(hdrdir)/ruby/internal/intern/error.h
+c.o: $(hdrdir)/ruby/internal/intern/eval.h
+c.o: $(hdrdir)/ruby/internal/intern/file.h
+c.o: $(hdrdir)/ruby/internal/intern/hash.h
+c.o: $(hdrdir)/ruby/internal/intern/io.h
+c.o: $(hdrdir)/ruby/internal/intern/load.h
+c.o: $(hdrdir)/ruby/internal/intern/marshal.h
+c.o: $(hdrdir)/ruby/internal/intern/numeric.h
+c.o: $(hdrdir)/ruby/internal/intern/object.h
+c.o: $(hdrdir)/ruby/internal/intern/parse.h
+c.o: $(hdrdir)/ruby/internal/intern/proc.h
+c.o: $(hdrdir)/ruby/internal/intern/process.h
+c.o: $(hdrdir)/ruby/internal/intern/random.h
+c.o: $(hdrdir)/ruby/internal/intern/range.h
+c.o: $(hdrdir)/ruby/internal/intern/rational.h
+c.o: $(hdrdir)/ruby/internal/intern/re.h
+c.o: $(hdrdir)/ruby/internal/intern/ruby.h
+c.o: $(hdrdir)/ruby/internal/intern/select.h
+c.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+c.o: $(hdrdir)/ruby/internal/intern/set.h
+c.o: $(hdrdir)/ruby/internal/intern/signal.h
+c.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+c.o: $(hdrdir)/ruby/internal/intern/string.h
+c.o: $(hdrdir)/ruby/internal/intern/struct.h
+c.o: $(hdrdir)/ruby/internal/intern/thread.h
+c.o: $(hdrdir)/ruby/internal/intern/time.h
+c.o: $(hdrdir)/ruby/internal/intern/variable.h
+c.o: $(hdrdir)/ruby/internal/intern/vm.h
+c.o: $(hdrdir)/ruby/internal/interpreter.h
+c.o: $(hdrdir)/ruby/internal/iterator.h
+c.o: $(hdrdir)/ruby/internal/memory.h
+c.o: $(hdrdir)/ruby/internal/method.h
+c.o: $(hdrdir)/ruby/internal/module.h
+c.o: $(hdrdir)/ruby/internal/newobj.h
+c.o: $(hdrdir)/ruby/internal/scan_args.h
+c.o: $(hdrdir)/ruby/internal/special_consts.h
+c.o: $(hdrdir)/ruby/internal/static_assert.h
+c.o: $(hdrdir)/ruby/internal/stdalign.h
+c.o: $(hdrdir)/ruby/internal/stdbool.h
+c.o: $(hdrdir)/ruby/internal/stdckdint.h
+c.o: $(hdrdir)/ruby/internal/symbol.h
+c.o: $(hdrdir)/ruby/internal/value.h
+c.o: $(hdrdir)/ruby/internal/value_type.h
+c.o: $(hdrdir)/ruby/internal/variable.h
+c.o: $(hdrdir)/ruby/internal/warning_push.h
+c.o: $(hdrdir)/ruby/internal/xmalloc.h
+c.o: $(hdrdir)/ruby/missing.h
+c.o: $(hdrdir)/ruby/ruby.h
+c.o: $(hdrdir)/ruby/st.h
+c.o: $(hdrdir)/ruby/subst.h
+c.o: c.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/RUBY_ALIGNOF/extconf.rb b/ext/-test-/RUBY_ALIGNOF/extconf.rb
new file mode 100644
index 0000000000..98a370e987
--- /dev/null
+++ b/ext/-test-/RUBY_ALIGNOF/extconf.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: false
+$objs = %W"c.#$OBJEXT"
+
+$objs << "cpp.#$OBJEXT" if MakeMakefile['C++'].have_devel?
+
+create_makefile("-test-/RUBY_ALIGNOF")
diff --git a/ext/-test-/abi/abi.c b/ext/-test-/abi/abi.c
new file mode 100644
index 0000000000..923e0f67b8
--- /dev/null
+++ b/ext/-test-/abi/abi.c
@@ -0,0 +1,11 @@
+#include <limits.h>
+
+unsigned long long
+ruby_abi_version(void)
+{
+ return ULONG_MAX;
+}
+
+void
+Init_abi(void)
+{}
diff --git a/ext/-test-/abi/depend b/ext/-test-/abi/depend
new file mode 100644
index 0000000000..716a7b1356
--- /dev/null
+++ b/ext/-test-/abi/depend
@@ -0,0 +1,3 @@
+# AUTOGENERATED DEPENDENCIES START
+abi.o: abi.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/abi/extconf.rb b/ext/-test-/abi/extconf.rb
new file mode 100644
index 0000000000..3b090b7553
--- /dev/null
+++ b/ext/-test-/abi/extconf.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: false
+return unless RUBY_PATCHLEVEL < 0
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/arith_seq/beg_len_step/beg_len_step.c b/ext/-test-/arith_seq/beg_len_step/beg_len_step.c
new file mode 100644
index 0000000000..40c8cbee82
--- /dev/null
+++ b/ext/-test-/arith_seq/beg_len_step/beg_len_step.c
@@ -0,0 +1,19 @@
+#include "ruby/ruby.h"
+
+static VALUE
+arith_seq_s_beg_len_step(VALUE mod, VALUE obj, VALUE len, VALUE err)
+{
+ VALUE r;
+ long beg, len2, step;
+
+ r = rb_arithmetic_sequence_beg_len_step(obj, &beg, &len2, &step, NUM2LONG(len), NUM2INT(err));
+
+ return rb_ary_new_from_args(4, r, LONG2NUM(beg), LONG2NUM(len2), LONG2NUM(step));
+}
+
+void
+Init_beg_len_step(void)
+{
+ VALUE cArithSeq = rb_path2class("Enumerator::ArithmeticSequence");
+ rb_define_singleton_method(cArithSeq, "__beg_len_step__", arith_seq_s_beg_len_step, 3);
+}
diff --git a/ext/-test-/arith_seq/beg_len_step/depend b/ext/-test-/arith_seq/beg_len_step/depend
new file mode 100644
index 0000000000..098c8ff1f0
--- /dev/null
+++ b/ext/-test-/arith_seq/beg_len_step/depend
@@ -0,0 +1,162 @@
+# AUTOGENERATED DEPENDENCIES START
+beg_len_step.o: $(RUBY_EXTCONF_H)
+beg_len_step.o: $(arch_hdrdir)/ruby/config.h
+beg_len_step.o: $(hdrdir)/ruby/assert.h
+beg_len_step.o: $(hdrdir)/ruby/backward.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/assume.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/attributes.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/bool.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/inttypes.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/limits.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/long_long.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/stdalign.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/stdarg.h
+beg_len_step.o: $(hdrdir)/ruby/defines.h
+beg_len_step.o: $(hdrdir)/ruby/intern.h
+beg_len_step.o: $(hdrdir)/ruby/internal/abi.h
+beg_len_step.o: $(hdrdir)/ruby/internal/anyargs.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/assume.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/artificial.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/cold.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/const.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/error.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/format.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/noalias.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/noinline.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/pure.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/restrict.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/warning.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/weakref.h
+beg_len_step.o: $(hdrdir)/ruby/internal/cast.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_since.h
+beg_len_step.o: $(hdrdir)/ruby/internal/config.h
+beg_len_step.o: $(hdrdir)/ruby/internal/constant_p.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rarray.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rbasic.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rbignum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rclass.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rdata.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rfile.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rhash.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/robject.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rregexp.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rstring.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rstruct.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+beg_len_step.o: $(hdrdir)/ruby/internal/ctype.h
+beg_len_step.o: $(hdrdir)/ruby/internal/dllexport.h
+beg_len_step.o: $(hdrdir)/ruby/internal/dosish.h
+beg_len_step.o: $(hdrdir)/ruby/internal/error.h
+beg_len_step.o: $(hdrdir)/ruby/internal/eval.h
+beg_len_step.o: $(hdrdir)/ruby/internal/event.h
+beg_len_step.o: $(hdrdir)/ruby/internal/fl_type.h
+beg_len_step.o: $(hdrdir)/ruby/internal/gc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/glob.h
+beg_len_step.o: $(hdrdir)/ruby/internal/globals.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/attribute.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/builtin.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/extension.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/feature.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/warning.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/array.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/bignum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/class.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/compar.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/complex.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/cont.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/dir.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/enum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/error.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/eval.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/file.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/hash.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/io.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/load.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/marshal.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/numeric.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/object.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/parse.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/proc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/process.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/random.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/range.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/rational.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/re.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/ruby.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/select.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/set.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/signal.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/string.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/struct.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/thread.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/time.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/variable.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/vm.h
+beg_len_step.o: $(hdrdir)/ruby/internal/interpreter.h
+beg_len_step.o: $(hdrdir)/ruby/internal/iterator.h
+beg_len_step.o: $(hdrdir)/ruby/internal/memory.h
+beg_len_step.o: $(hdrdir)/ruby/internal/method.h
+beg_len_step.o: $(hdrdir)/ruby/internal/module.h
+beg_len_step.o: $(hdrdir)/ruby/internal/newobj.h
+beg_len_step.o: $(hdrdir)/ruby/internal/scan_args.h
+beg_len_step.o: $(hdrdir)/ruby/internal/special_consts.h
+beg_len_step.o: $(hdrdir)/ruby/internal/static_assert.h
+beg_len_step.o: $(hdrdir)/ruby/internal/stdalign.h
+beg_len_step.o: $(hdrdir)/ruby/internal/stdbool.h
+beg_len_step.o: $(hdrdir)/ruby/internal/stdckdint.h
+beg_len_step.o: $(hdrdir)/ruby/internal/symbol.h
+beg_len_step.o: $(hdrdir)/ruby/internal/value.h
+beg_len_step.o: $(hdrdir)/ruby/internal/value_type.h
+beg_len_step.o: $(hdrdir)/ruby/internal/variable.h
+beg_len_step.o: $(hdrdir)/ruby/internal/warning_push.h
+beg_len_step.o: $(hdrdir)/ruby/internal/xmalloc.h
+beg_len_step.o: $(hdrdir)/ruby/missing.h
+beg_len_step.o: $(hdrdir)/ruby/ruby.h
+beg_len_step.o: $(hdrdir)/ruby/st.h
+beg_len_step.o: $(hdrdir)/ruby/subst.h
+beg_len_step.o: beg_len_step.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/arith_seq/beg_len_step/extconf.rb b/ext/-test-/arith_seq/beg_len_step/extconf.rb
new file mode 100644
index 0000000000..e72b3ad01f
--- /dev/null
+++ b/ext/-test-/arith_seq/beg_len_step/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/arith_seq/beg_len_step")
diff --git a/ext/-test-/arith_seq/extract/depend b/ext/-test-/arith_seq/extract/depend
new file mode 100644
index 0000000000..5c07cea4b4
--- /dev/null
+++ b/ext/-test-/arith_seq/extract/depend
@@ -0,0 +1,162 @@
+# AUTOGENERATED DEPENDENCIES START
+extract.o: $(RUBY_EXTCONF_H)
+extract.o: $(arch_hdrdir)/ruby/config.h
+extract.o: $(hdrdir)/ruby/assert.h
+extract.o: $(hdrdir)/ruby/backward.h
+extract.o: $(hdrdir)/ruby/backward/2/assume.h
+extract.o: $(hdrdir)/ruby/backward/2/attributes.h
+extract.o: $(hdrdir)/ruby/backward/2/bool.h
+extract.o: $(hdrdir)/ruby/backward/2/inttypes.h
+extract.o: $(hdrdir)/ruby/backward/2/limits.h
+extract.o: $(hdrdir)/ruby/backward/2/long_long.h
+extract.o: $(hdrdir)/ruby/backward/2/stdalign.h
+extract.o: $(hdrdir)/ruby/backward/2/stdarg.h
+extract.o: $(hdrdir)/ruby/defines.h
+extract.o: $(hdrdir)/ruby/intern.h
+extract.o: $(hdrdir)/ruby/internal/abi.h
+extract.o: $(hdrdir)/ruby/internal/anyargs.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+extract.o: $(hdrdir)/ruby/internal/assume.h
+extract.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+extract.o: $(hdrdir)/ruby/internal/attr/artificial.h
+extract.o: $(hdrdir)/ruby/internal/attr/cold.h
+extract.o: $(hdrdir)/ruby/internal/attr/const.h
+extract.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+extract.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+extract.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+extract.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+extract.o: $(hdrdir)/ruby/internal/attr/error.h
+extract.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+extract.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+extract.o: $(hdrdir)/ruby/internal/attr/format.h
+extract.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+extract.o: $(hdrdir)/ruby/internal/attr/noalias.h
+extract.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+extract.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+extract.o: $(hdrdir)/ruby/internal/attr/noinline.h
+extract.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+extract.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+extract.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+extract.o: $(hdrdir)/ruby/internal/attr/pure.h
+extract.o: $(hdrdir)/ruby/internal/attr/restrict.h
+extract.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+extract.o: $(hdrdir)/ruby/internal/attr/warning.h
+extract.o: $(hdrdir)/ruby/internal/attr/weakref.h
+extract.o: $(hdrdir)/ruby/internal/cast.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+extract.o: $(hdrdir)/ruby/internal/compiler_since.h
+extract.o: $(hdrdir)/ruby/internal/config.h
+extract.o: $(hdrdir)/ruby/internal/constant_p.h
+extract.o: $(hdrdir)/ruby/internal/core.h
+extract.o: $(hdrdir)/ruby/internal/core/rarray.h
+extract.o: $(hdrdir)/ruby/internal/core/rbasic.h
+extract.o: $(hdrdir)/ruby/internal/core/rbignum.h
+extract.o: $(hdrdir)/ruby/internal/core/rclass.h
+extract.o: $(hdrdir)/ruby/internal/core/rdata.h
+extract.o: $(hdrdir)/ruby/internal/core/rfile.h
+extract.o: $(hdrdir)/ruby/internal/core/rhash.h
+extract.o: $(hdrdir)/ruby/internal/core/robject.h
+extract.o: $(hdrdir)/ruby/internal/core/rregexp.h
+extract.o: $(hdrdir)/ruby/internal/core/rstring.h
+extract.o: $(hdrdir)/ruby/internal/core/rstruct.h
+extract.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+extract.o: $(hdrdir)/ruby/internal/ctype.h
+extract.o: $(hdrdir)/ruby/internal/dllexport.h
+extract.o: $(hdrdir)/ruby/internal/dosish.h
+extract.o: $(hdrdir)/ruby/internal/error.h
+extract.o: $(hdrdir)/ruby/internal/eval.h
+extract.o: $(hdrdir)/ruby/internal/event.h
+extract.o: $(hdrdir)/ruby/internal/fl_type.h
+extract.o: $(hdrdir)/ruby/internal/gc.h
+extract.o: $(hdrdir)/ruby/internal/glob.h
+extract.o: $(hdrdir)/ruby/internal/globals.h
+extract.o: $(hdrdir)/ruby/internal/has/attribute.h
+extract.o: $(hdrdir)/ruby/internal/has/builtin.h
+extract.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+extract.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+extract.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+extract.o: $(hdrdir)/ruby/internal/has/extension.h
+extract.o: $(hdrdir)/ruby/internal/has/feature.h
+extract.o: $(hdrdir)/ruby/internal/has/warning.h
+extract.o: $(hdrdir)/ruby/internal/intern/array.h
+extract.o: $(hdrdir)/ruby/internal/intern/bignum.h
+extract.o: $(hdrdir)/ruby/internal/intern/class.h
+extract.o: $(hdrdir)/ruby/internal/intern/compar.h
+extract.o: $(hdrdir)/ruby/internal/intern/complex.h
+extract.o: $(hdrdir)/ruby/internal/intern/cont.h
+extract.o: $(hdrdir)/ruby/internal/intern/dir.h
+extract.o: $(hdrdir)/ruby/internal/intern/enum.h
+extract.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+extract.o: $(hdrdir)/ruby/internal/intern/error.h
+extract.o: $(hdrdir)/ruby/internal/intern/eval.h
+extract.o: $(hdrdir)/ruby/internal/intern/file.h
+extract.o: $(hdrdir)/ruby/internal/intern/hash.h
+extract.o: $(hdrdir)/ruby/internal/intern/io.h
+extract.o: $(hdrdir)/ruby/internal/intern/load.h
+extract.o: $(hdrdir)/ruby/internal/intern/marshal.h
+extract.o: $(hdrdir)/ruby/internal/intern/numeric.h
+extract.o: $(hdrdir)/ruby/internal/intern/object.h
+extract.o: $(hdrdir)/ruby/internal/intern/parse.h
+extract.o: $(hdrdir)/ruby/internal/intern/proc.h
+extract.o: $(hdrdir)/ruby/internal/intern/process.h
+extract.o: $(hdrdir)/ruby/internal/intern/random.h
+extract.o: $(hdrdir)/ruby/internal/intern/range.h
+extract.o: $(hdrdir)/ruby/internal/intern/rational.h
+extract.o: $(hdrdir)/ruby/internal/intern/re.h
+extract.o: $(hdrdir)/ruby/internal/intern/ruby.h
+extract.o: $(hdrdir)/ruby/internal/intern/select.h
+extract.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+extract.o: $(hdrdir)/ruby/internal/intern/set.h
+extract.o: $(hdrdir)/ruby/internal/intern/signal.h
+extract.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+extract.o: $(hdrdir)/ruby/internal/intern/string.h
+extract.o: $(hdrdir)/ruby/internal/intern/struct.h
+extract.o: $(hdrdir)/ruby/internal/intern/thread.h
+extract.o: $(hdrdir)/ruby/internal/intern/time.h
+extract.o: $(hdrdir)/ruby/internal/intern/variable.h
+extract.o: $(hdrdir)/ruby/internal/intern/vm.h
+extract.o: $(hdrdir)/ruby/internal/interpreter.h
+extract.o: $(hdrdir)/ruby/internal/iterator.h
+extract.o: $(hdrdir)/ruby/internal/memory.h
+extract.o: $(hdrdir)/ruby/internal/method.h
+extract.o: $(hdrdir)/ruby/internal/module.h
+extract.o: $(hdrdir)/ruby/internal/newobj.h
+extract.o: $(hdrdir)/ruby/internal/scan_args.h
+extract.o: $(hdrdir)/ruby/internal/special_consts.h
+extract.o: $(hdrdir)/ruby/internal/static_assert.h
+extract.o: $(hdrdir)/ruby/internal/stdalign.h
+extract.o: $(hdrdir)/ruby/internal/stdbool.h
+extract.o: $(hdrdir)/ruby/internal/stdckdint.h
+extract.o: $(hdrdir)/ruby/internal/symbol.h
+extract.o: $(hdrdir)/ruby/internal/value.h
+extract.o: $(hdrdir)/ruby/internal/value_type.h
+extract.o: $(hdrdir)/ruby/internal/variable.h
+extract.o: $(hdrdir)/ruby/internal/warning_push.h
+extract.o: $(hdrdir)/ruby/internal/xmalloc.h
+extract.o: $(hdrdir)/ruby/missing.h
+extract.o: $(hdrdir)/ruby/ruby.h
+extract.o: $(hdrdir)/ruby/st.h
+extract.o: $(hdrdir)/ruby/subst.h
+extract.o: extract.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/arith_seq/extract/extconf.rb b/ext/-test-/arith_seq/extract/extconf.rb
new file mode 100644
index 0000000000..9c368bf50e
--- /dev/null
+++ b/ext/-test-/arith_seq/extract/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/arith_seq/extract")
diff --git a/ext/-test-/arith_seq/extract/extract.c b/ext/-test-/arith_seq/extract/extract.c
new file mode 100644
index 0000000000..93b89c239a
--- /dev/null
+++ b/ext/-test-/arith_seq/extract/extract.c
@@ -0,0 +1,27 @@
+#include "ruby/ruby.h"
+
+static VALUE
+arith_seq_s_extract(VALUE mod, VALUE obj)
+{
+ rb_arithmetic_sequence_components_t x;
+ VALUE ret;
+ int r;
+
+ r = rb_arithmetic_sequence_extract(obj, &x);
+
+ ret = rb_ary_new2(5);
+ rb_ary_store(ret, 0, r ? x.begin : Qnil);
+ rb_ary_store(ret, 1, r ? x.end : Qnil);
+ rb_ary_store(ret, 2, r ? x.step : Qnil);
+ rb_ary_store(ret, 3, r ? INT2FIX(x.exclude_end) : Qnil);
+ rb_ary_store(ret, 4, INT2FIX(r));
+
+ return ret;
+}
+
+void
+Init_extract(void)
+{
+ VALUE cArithSeq = rb_path2class("Enumerator::ArithmeticSequence");
+ rb_define_singleton_method(cArithSeq, "__extract__", arith_seq_s_extract, 1);
+}
diff --git a/ext/-test-/array/concat/depend b/ext/-test-/array/concat/depend
new file mode 100644
index 0000000000..8edf45465f
--- /dev/null
+++ b/ext/-test-/array/concat/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+to_ary_concat.o: $(RUBY_EXTCONF_H)
+to_ary_concat.o: $(arch_hdrdir)/ruby/config.h
+to_ary_concat.o: $(hdrdir)/ruby.h
+to_ary_concat.o: $(hdrdir)/ruby/assert.h
+to_ary_concat.o: $(hdrdir)/ruby/backward.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/assume.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/attributes.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/bool.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/limits.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/long_long.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/stdarg.h
+to_ary_concat.o: $(hdrdir)/ruby/defines.h
+to_ary_concat.o: $(hdrdir)/ruby/intern.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/abi.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/anyargs.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/assume.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/artificial.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/cold.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/const.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/error.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/format.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/noalias.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/noinline.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/pure.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/restrict.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/warning.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/weakref.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/cast.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_since.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/config.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/constant_p.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rarray.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rbasic.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rbignum.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rclass.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rdata.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rfile.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rhash.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/robject.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rregexp.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rstring.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rstruct.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/ctype.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/dllexport.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/dosish.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/error.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/eval.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/event.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/fl_type.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/gc.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/glob.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/globals.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/attribute.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/builtin.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/extension.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/feature.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/warning.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/array.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/bignum.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/class.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/compar.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/complex.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/cont.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/dir.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/enum.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/error.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/eval.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/file.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/hash.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/io.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/load.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/marshal.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/numeric.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/object.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/parse.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/proc.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/process.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/random.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/range.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/rational.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/re.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/ruby.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/select.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/set.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/signal.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/string.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/struct.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/thread.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/time.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/variable.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/vm.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/interpreter.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/iterator.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/memory.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/method.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/module.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/newobj.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/scan_args.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/special_consts.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/static_assert.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/stdalign.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/stdbool.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/stdckdint.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/symbol.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/value.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/value_type.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/variable.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/warning_push.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/xmalloc.h
+to_ary_concat.o: $(hdrdir)/ruby/missing.h
+to_ary_concat.o: $(hdrdir)/ruby/ruby.h
+to_ary_concat.o: $(hdrdir)/ruby/st.h
+to_ary_concat.o: $(hdrdir)/ruby/subst.h
+to_ary_concat.o: to_ary_concat.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/array/concat/extconf.rb b/ext/-test-/array/concat/extconf.rb
new file mode 100644
index 0000000000..cdd79126c9
--- /dev/null
+++ b/ext/-test-/array/concat/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/array/to_ary_concat")
diff --git a/ext/-test-/array/concat/to_ary_concat.c b/ext/-test-/array/concat/to_ary_concat.c
new file mode 100644
index 0000000000..07a96d3907
--- /dev/null
+++ b/ext/-test-/array/concat/to_ary_concat.c
@@ -0,0 +1,38 @@
+#include "ruby.h"
+
+// Bar
+
+typedef struct {
+ int dummy;
+} Bar;
+
+static rb_data_type_t Bar_type = {
+ "Bar",
+ {NULL, RUBY_TYPED_DEFAULT_FREE, NULL },
+};
+
+static VALUE
+Bar_alloc(VALUE klass)
+{
+ return TypedData_Wrap_Struct(klass, &Bar_type, NULL);
+}
+
+static VALUE
+Bar_to_ary(VALUE _self)
+{
+ VALUE ary = rb_ary_new2(2);
+ VALUE foo = rb_ary_new2(0);
+ rb_ary_push(ary, foo);
+ rb_ary_push(ary, foo);
+ rb_ary_push(ary, foo);
+ return ary;
+}
+
+void
+Init_to_ary_concat(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE bar = rb_define_class_under(mBug, "Bar", rb_cObject);
+ rb_define_alloc_func(bar, Bar_alloc);
+ rb_define_method(bar, "to_ary", Bar_to_ary, 0);
+}
diff --git a/ext/-test-/array/resize/depend b/ext/-test-/array/resize/depend
new file mode 100644
index 0000000000..e6a228b43d
--- /dev/null
+++ b/ext/-test-/array/resize/depend
@@ -0,0 +1,162 @@
+# AUTOGENERATED DEPENDENCIES START
+resize.o: $(RUBY_EXTCONF_H)
+resize.o: $(arch_hdrdir)/ruby/config.h
+resize.o: $(hdrdir)/ruby/assert.h
+resize.o: $(hdrdir)/ruby/backward.h
+resize.o: $(hdrdir)/ruby/backward/2/assume.h
+resize.o: $(hdrdir)/ruby/backward/2/attributes.h
+resize.o: $(hdrdir)/ruby/backward/2/bool.h
+resize.o: $(hdrdir)/ruby/backward/2/inttypes.h
+resize.o: $(hdrdir)/ruby/backward/2/limits.h
+resize.o: $(hdrdir)/ruby/backward/2/long_long.h
+resize.o: $(hdrdir)/ruby/backward/2/stdalign.h
+resize.o: $(hdrdir)/ruby/backward/2/stdarg.h
+resize.o: $(hdrdir)/ruby/defines.h
+resize.o: $(hdrdir)/ruby/intern.h
+resize.o: $(hdrdir)/ruby/internal/abi.h
+resize.o: $(hdrdir)/ruby/internal/anyargs.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+resize.o: $(hdrdir)/ruby/internal/assume.h
+resize.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+resize.o: $(hdrdir)/ruby/internal/attr/artificial.h
+resize.o: $(hdrdir)/ruby/internal/attr/cold.h
+resize.o: $(hdrdir)/ruby/internal/attr/const.h
+resize.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+resize.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+resize.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+resize.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+resize.o: $(hdrdir)/ruby/internal/attr/error.h
+resize.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+resize.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+resize.o: $(hdrdir)/ruby/internal/attr/format.h
+resize.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+resize.o: $(hdrdir)/ruby/internal/attr/noalias.h
+resize.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+resize.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+resize.o: $(hdrdir)/ruby/internal/attr/noinline.h
+resize.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+resize.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+resize.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+resize.o: $(hdrdir)/ruby/internal/attr/pure.h
+resize.o: $(hdrdir)/ruby/internal/attr/restrict.h
+resize.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+resize.o: $(hdrdir)/ruby/internal/attr/warning.h
+resize.o: $(hdrdir)/ruby/internal/attr/weakref.h
+resize.o: $(hdrdir)/ruby/internal/cast.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+resize.o: $(hdrdir)/ruby/internal/compiler_since.h
+resize.o: $(hdrdir)/ruby/internal/config.h
+resize.o: $(hdrdir)/ruby/internal/constant_p.h
+resize.o: $(hdrdir)/ruby/internal/core.h
+resize.o: $(hdrdir)/ruby/internal/core/rarray.h
+resize.o: $(hdrdir)/ruby/internal/core/rbasic.h
+resize.o: $(hdrdir)/ruby/internal/core/rbignum.h
+resize.o: $(hdrdir)/ruby/internal/core/rclass.h
+resize.o: $(hdrdir)/ruby/internal/core/rdata.h
+resize.o: $(hdrdir)/ruby/internal/core/rfile.h
+resize.o: $(hdrdir)/ruby/internal/core/rhash.h
+resize.o: $(hdrdir)/ruby/internal/core/robject.h
+resize.o: $(hdrdir)/ruby/internal/core/rregexp.h
+resize.o: $(hdrdir)/ruby/internal/core/rstring.h
+resize.o: $(hdrdir)/ruby/internal/core/rstruct.h
+resize.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+resize.o: $(hdrdir)/ruby/internal/ctype.h
+resize.o: $(hdrdir)/ruby/internal/dllexport.h
+resize.o: $(hdrdir)/ruby/internal/dosish.h
+resize.o: $(hdrdir)/ruby/internal/error.h
+resize.o: $(hdrdir)/ruby/internal/eval.h
+resize.o: $(hdrdir)/ruby/internal/event.h
+resize.o: $(hdrdir)/ruby/internal/fl_type.h
+resize.o: $(hdrdir)/ruby/internal/gc.h
+resize.o: $(hdrdir)/ruby/internal/glob.h
+resize.o: $(hdrdir)/ruby/internal/globals.h
+resize.o: $(hdrdir)/ruby/internal/has/attribute.h
+resize.o: $(hdrdir)/ruby/internal/has/builtin.h
+resize.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+resize.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+resize.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+resize.o: $(hdrdir)/ruby/internal/has/extension.h
+resize.o: $(hdrdir)/ruby/internal/has/feature.h
+resize.o: $(hdrdir)/ruby/internal/has/warning.h
+resize.o: $(hdrdir)/ruby/internal/intern/array.h
+resize.o: $(hdrdir)/ruby/internal/intern/bignum.h
+resize.o: $(hdrdir)/ruby/internal/intern/class.h
+resize.o: $(hdrdir)/ruby/internal/intern/compar.h
+resize.o: $(hdrdir)/ruby/internal/intern/complex.h
+resize.o: $(hdrdir)/ruby/internal/intern/cont.h
+resize.o: $(hdrdir)/ruby/internal/intern/dir.h
+resize.o: $(hdrdir)/ruby/internal/intern/enum.h
+resize.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+resize.o: $(hdrdir)/ruby/internal/intern/error.h
+resize.o: $(hdrdir)/ruby/internal/intern/eval.h
+resize.o: $(hdrdir)/ruby/internal/intern/file.h
+resize.o: $(hdrdir)/ruby/internal/intern/hash.h
+resize.o: $(hdrdir)/ruby/internal/intern/io.h
+resize.o: $(hdrdir)/ruby/internal/intern/load.h
+resize.o: $(hdrdir)/ruby/internal/intern/marshal.h
+resize.o: $(hdrdir)/ruby/internal/intern/numeric.h
+resize.o: $(hdrdir)/ruby/internal/intern/object.h
+resize.o: $(hdrdir)/ruby/internal/intern/parse.h
+resize.o: $(hdrdir)/ruby/internal/intern/proc.h
+resize.o: $(hdrdir)/ruby/internal/intern/process.h
+resize.o: $(hdrdir)/ruby/internal/intern/random.h
+resize.o: $(hdrdir)/ruby/internal/intern/range.h
+resize.o: $(hdrdir)/ruby/internal/intern/rational.h
+resize.o: $(hdrdir)/ruby/internal/intern/re.h
+resize.o: $(hdrdir)/ruby/internal/intern/ruby.h
+resize.o: $(hdrdir)/ruby/internal/intern/select.h
+resize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+resize.o: $(hdrdir)/ruby/internal/intern/set.h
+resize.o: $(hdrdir)/ruby/internal/intern/signal.h
+resize.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+resize.o: $(hdrdir)/ruby/internal/intern/string.h
+resize.o: $(hdrdir)/ruby/internal/intern/struct.h
+resize.o: $(hdrdir)/ruby/internal/intern/thread.h
+resize.o: $(hdrdir)/ruby/internal/intern/time.h
+resize.o: $(hdrdir)/ruby/internal/intern/variable.h
+resize.o: $(hdrdir)/ruby/internal/intern/vm.h
+resize.o: $(hdrdir)/ruby/internal/interpreter.h
+resize.o: $(hdrdir)/ruby/internal/iterator.h
+resize.o: $(hdrdir)/ruby/internal/memory.h
+resize.o: $(hdrdir)/ruby/internal/method.h
+resize.o: $(hdrdir)/ruby/internal/module.h
+resize.o: $(hdrdir)/ruby/internal/newobj.h
+resize.o: $(hdrdir)/ruby/internal/scan_args.h
+resize.o: $(hdrdir)/ruby/internal/special_consts.h
+resize.o: $(hdrdir)/ruby/internal/static_assert.h
+resize.o: $(hdrdir)/ruby/internal/stdalign.h
+resize.o: $(hdrdir)/ruby/internal/stdbool.h
+resize.o: $(hdrdir)/ruby/internal/stdckdint.h
+resize.o: $(hdrdir)/ruby/internal/symbol.h
+resize.o: $(hdrdir)/ruby/internal/value.h
+resize.o: $(hdrdir)/ruby/internal/value_type.h
+resize.o: $(hdrdir)/ruby/internal/variable.h
+resize.o: $(hdrdir)/ruby/internal/warning_push.h
+resize.o: $(hdrdir)/ruby/internal/xmalloc.h
+resize.o: $(hdrdir)/ruby/missing.h
+resize.o: $(hdrdir)/ruby/ruby.h
+resize.o: $(hdrdir)/ruby/st.h
+resize.o: $(hdrdir)/ruby/subst.h
+resize.o: resize.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/array/resize/extconf.rb b/ext/-test-/array/resize/extconf.rb
new file mode 100644
index 0000000000..bc827e1170
--- /dev/null
+++ b/ext/-test-/array/resize/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/array/resize")
diff --git a/ext/-test-/array/resize/resize.c b/ext/-test-/array/resize/resize.c
new file mode 100644
index 0000000000..cfe910ebed
--- /dev/null
+++ b/ext/-test-/array/resize/resize.c
@@ -0,0 +1,16 @@
+#include "ruby/ruby.h"
+
+static VALUE
+ary_resize(VALUE klass, VALUE ary, VALUE len)
+{
+ rb_ary_resize(ary, NUM2LONG(len));
+ return ary;
+}
+
+void
+Init_resize(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "Array", rb_cObject);
+ rb_define_singleton_method(klass, "__resize__", ary_resize, 2);
+}
diff --git a/ext/-test-/auto_ext.rb b/ext/-test-/auto_ext.rb
new file mode 100644
index 0000000000..58c49c177b
--- /dev/null
+++ b/ext/-test-/auto_ext.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: false
+def auto_ext(feat = $0[%r[/ext/(-test-/.*)/extconf.rb\z], 1], inc: false)
+ $INCFLAGS << " -I$(topdir) -I$(top_srcdir)" if inc
+ $srcs = Dir[File.join($srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
+ inits = $srcs.map {|s| File.basename(s, ".*")}
+ inits.delete("init")
+ inits.map! {|s|"X(#{s})"}
+ $defs << "-DTEST_INIT_FUNCS(X)=\"#{inits.join(' ')}\""
+ create_header
+ create_makefile(feat)
+end
diff --git a/ext/-test-/bignum/big2str.c b/ext/-test-/bignum/big2str.c
new file mode 100644
index 0000000000..255e8ad729
--- /dev/null
+++ b/ext/-test-/bignum/big2str.c
@@ -0,0 +1,53 @@
+#include "internal/bignum.h"
+
+static VALUE
+big(VALUE x)
+{
+ if (FIXNUM_P(x))
+ return rb_int2big(FIX2LONG(x));
+ if (RB_TYPE_P(x, T_BIGNUM))
+ return x;
+ rb_raise(rb_eTypeError, "can't convert %s to Bignum",
+ rb_obj_classname(x));
+}
+
+static VALUE
+big2str_generic(VALUE klass, VALUE x, VALUE vbase)
+{
+ int base = NUM2INT(vbase);
+ if (base < 2 || 36 < base)
+ rb_raise(rb_eArgError, "invalid radix %d", base);
+ return rb_big2str_generic(big(x), base);
+}
+
+#define POW2_P(x) (((x)&((x)-1))==0)
+
+static VALUE
+big2str_poweroftwo(VALUE klass, VALUE x, VALUE vbase)
+{
+ int base = NUM2INT(vbase);
+ if (base < 2 || 36 < base || !POW2_P(base))
+ rb_raise(rb_eArgError, "invalid radix %d", base);
+ return rb_big2str_poweroftwo(big(x), base);
+}
+
+#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
+static VALUE
+big2str_gmp(VALUE klass, VALUE x, VALUE vbase)
+{
+ int base = NUM2INT(vbase);
+ if (base < 2 || 36 < base)
+ rb_raise(rb_eArgError, "invalid radix %d", base);
+ return rb_big2str_gmp(big(x), base);
+}
+#else
+#define big2str_gmp rb_f_notimplement
+#endif
+
+void
+Init_big2str(VALUE klass)
+{
+ rb_define_singleton_method(klass, "big2str_generic", big2str_generic, 2);
+ rb_define_singleton_method(klass, "big2str_poweroftwo", big2str_poweroftwo, 2);
+ rb_define_singleton_method(klass, "big2str_gmp", big2str_gmp, 2);
+}
diff --git a/ext/-test-/bignum/bigzero.c b/ext/-test-/bignum/bigzero.c
new file mode 100644
index 0000000000..e2bfebcd3e
--- /dev/null
+++ b/ext/-test-/bignum/bigzero.c
@@ -0,0 +1,26 @@
+#include "internal/bignum.h"
+
+static VALUE
+bug_big_zero(VALUE self, VALUE length)
+{
+ long len = NUM2ULONG(length);
+ VALUE z = rb_big_new(len, 1);
+ MEMZERO(BIGNUM_DIGITS(z), BDIGIT, len);
+ return z;
+}
+
+static VALUE
+bug_big_negzero(VALUE self, VALUE length)
+{
+ long len = NUM2ULONG(length);
+ VALUE z = rb_big_new(len, 0);
+ MEMZERO(BIGNUM_DIGITS(z), BDIGIT, len);
+ return z;
+}
+
+void
+Init_bigzero(VALUE klass)
+{
+ rb_define_singleton_method(klass, "zero", bug_big_zero, 1);
+ rb_define_singleton_method(klass, "negzero", bug_big_negzero, 1);
+}
diff --git a/ext/-test-/bignum/depend b/ext/-test-/bignum/depend
new file mode 100644
index 0000000000..82972f1032
--- /dev/null
+++ b/ext/-test-/bignum/depend
@@ -0,0 +1,1141 @@
+# AUTOGENERATED DEPENDENCIES START
+big2str.o: $(RUBY_EXTCONF_H)
+big2str.o: $(arch_hdrdir)/ruby/config.h
+big2str.o: $(hdrdir)/ruby/assert.h
+big2str.o: $(hdrdir)/ruby/backward.h
+big2str.o: $(hdrdir)/ruby/backward/2/assume.h
+big2str.o: $(hdrdir)/ruby/backward/2/attributes.h
+big2str.o: $(hdrdir)/ruby/backward/2/bool.h
+big2str.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+big2str.o: $(hdrdir)/ruby/backward/2/inttypes.h
+big2str.o: $(hdrdir)/ruby/backward/2/limits.h
+big2str.o: $(hdrdir)/ruby/backward/2/long_long.h
+big2str.o: $(hdrdir)/ruby/backward/2/stdalign.h
+big2str.o: $(hdrdir)/ruby/backward/2/stdarg.h
+big2str.o: $(hdrdir)/ruby/defines.h
+big2str.o: $(hdrdir)/ruby/intern.h
+big2str.o: $(hdrdir)/ruby/internal/abi.h
+big2str.o: $(hdrdir)/ruby/internal/anyargs.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+big2str.o: $(hdrdir)/ruby/internal/assume.h
+big2str.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+big2str.o: $(hdrdir)/ruby/internal/attr/artificial.h
+big2str.o: $(hdrdir)/ruby/internal/attr/cold.h
+big2str.o: $(hdrdir)/ruby/internal/attr/const.h
+big2str.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+big2str.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+big2str.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+big2str.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+big2str.o: $(hdrdir)/ruby/internal/attr/error.h
+big2str.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+big2str.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+big2str.o: $(hdrdir)/ruby/internal/attr/format.h
+big2str.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+big2str.o: $(hdrdir)/ruby/internal/attr/noalias.h
+big2str.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+big2str.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+big2str.o: $(hdrdir)/ruby/internal/attr/noinline.h
+big2str.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+big2str.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+big2str.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+big2str.o: $(hdrdir)/ruby/internal/attr/pure.h
+big2str.o: $(hdrdir)/ruby/internal/attr/restrict.h
+big2str.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+big2str.o: $(hdrdir)/ruby/internal/attr/warning.h
+big2str.o: $(hdrdir)/ruby/internal/attr/weakref.h
+big2str.o: $(hdrdir)/ruby/internal/cast.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_since.h
+big2str.o: $(hdrdir)/ruby/internal/config.h
+big2str.o: $(hdrdir)/ruby/internal/constant_p.h
+big2str.o: $(hdrdir)/ruby/internal/core.h
+big2str.o: $(hdrdir)/ruby/internal/core/rarray.h
+big2str.o: $(hdrdir)/ruby/internal/core/rbasic.h
+big2str.o: $(hdrdir)/ruby/internal/core/rbignum.h
+big2str.o: $(hdrdir)/ruby/internal/core/rclass.h
+big2str.o: $(hdrdir)/ruby/internal/core/rdata.h
+big2str.o: $(hdrdir)/ruby/internal/core/rfile.h
+big2str.o: $(hdrdir)/ruby/internal/core/rhash.h
+big2str.o: $(hdrdir)/ruby/internal/core/robject.h
+big2str.o: $(hdrdir)/ruby/internal/core/rregexp.h
+big2str.o: $(hdrdir)/ruby/internal/core/rstring.h
+big2str.o: $(hdrdir)/ruby/internal/core/rstruct.h
+big2str.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+big2str.o: $(hdrdir)/ruby/internal/ctype.h
+big2str.o: $(hdrdir)/ruby/internal/dllexport.h
+big2str.o: $(hdrdir)/ruby/internal/dosish.h
+big2str.o: $(hdrdir)/ruby/internal/error.h
+big2str.o: $(hdrdir)/ruby/internal/eval.h
+big2str.o: $(hdrdir)/ruby/internal/event.h
+big2str.o: $(hdrdir)/ruby/internal/fl_type.h
+big2str.o: $(hdrdir)/ruby/internal/gc.h
+big2str.o: $(hdrdir)/ruby/internal/glob.h
+big2str.o: $(hdrdir)/ruby/internal/globals.h
+big2str.o: $(hdrdir)/ruby/internal/has/attribute.h
+big2str.o: $(hdrdir)/ruby/internal/has/builtin.h
+big2str.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+big2str.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+big2str.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+big2str.o: $(hdrdir)/ruby/internal/has/extension.h
+big2str.o: $(hdrdir)/ruby/internal/has/feature.h
+big2str.o: $(hdrdir)/ruby/internal/has/warning.h
+big2str.o: $(hdrdir)/ruby/internal/intern/array.h
+big2str.o: $(hdrdir)/ruby/internal/intern/bignum.h
+big2str.o: $(hdrdir)/ruby/internal/intern/class.h
+big2str.o: $(hdrdir)/ruby/internal/intern/compar.h
+big2str.o: $(hdrdir)/ruby/internal/intern/complex.h
+big2str.o: $(hdrdir)/ruby/internal/intern/cont.h
+big2str.o: $(hdrdir)/ruby/internal/intern/dir.h
+big2str.o: $(hdrdir)/ruby/internal/intern/enum.h
+big2str.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+big2str.o: $(hdrdir)/ruby/internal/intern/error.h
+big2str.o: $(hdrdir)/ruby/internal/intern/eval.h
+big2str.o: $(hdrdir)/ruby/internal/intern/file.h
+big2str.o: $(hdrdir)/ruby/internal/intern/hash.h
+big2str.o: $(hdrdir)/ruby/internal/intern/io.h
+big2str.o: $(hdrdir)/ruby/internal/intern/load.h
+big2str.o: $(hdrdir)/ruby/internal/intern/marshal.h
+big2str.o: $(hdrdir)/ruby/internal/intern/numeric.h
+big2str.o: $(hdrdir)/ruby/internal/intern/object.h
+big2str.o: $(hdrdir)/ruby/internal/intern/parse.h
+big2str.o: $(hdrdir)/ruby/internal/intern/proc.h
+big2str.o: $(hdrdir)/ruby/internal/intern/process.h
+big2str.o: $(hdrdir)/ruby/internal/intern/random.h
+big2str.o: $(hdrdir)/ruby/internal/intern/range.h
+big2str.o: $(hdrdir)/ruby/internal/intern/rational.h
+big2str.o: $(hdrdir)/ruby/internal/intern/re.h
+big2str.o: $(hdrdir)/ruby/internal/intern/ruby.h
+big2str.o: $(hdrdir)/ruby/internal/intern/select.h
+big2str.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+big2str.o: $(hdrdir)/ruby/internal/intern/set.h
+big2str.o: $(hdrdir)/ruby/internal/intern/signal.h
+big2str.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+big2str.o: $(hdrdir)/ruby/internal/intern/string.h
+big2str.o: $(hdrdir)/ruby/internal/intern/struct.h
+big2str.o: $(hdrdir)/ruby/internal/intern/thread.h
+big2str.o: $(hdrdir)/ruby/internal/intern/time.h
+big2str.o: $(hdrdir)/ruby/internal/intern/variable.h
+big2str.o: $(hdrdir)/ruby/internal/intern/vm.h
+big2str.o: $(hdrdir)/ruby/internal/interpreter.h
+big2str.o: $(hdrdir)/ruby/internal/iterator.h
+big2str.o: $(hdrdir)/ruby/internal/memory.h
+big2str.o: $(hdrdir)/ruby/internal/method.h
+big2str.o: $(hdrdir)/ruby/internal/module.h
+big2str.o: $(hdrdir)/ruby/internal/newobj.h
+big2str.o: $(hdrdir)/ruby/internal/scan_args.h
+big2str.o: $(hdrdir)/ruby/internal/special_consts.h
+big2str.o: $(hdrdir)/ruby/internal/static_assert.h
+big2str.o: $(hdrdir)/ruby/internal/stdalign.h
+big2str.o: $(hdrdir)/ruby/internal/stdbool.h
+big2str.o: $(hdrdir)/ruby/internal/stdckdint.h
+big2str.o: $(hdrdir)/ruby/internal/symbol.h
+big2str.o: $(hdrdir)/ruby/internal/value.h
+big2str.o: $(hdrdir)/ruby/internal/value_type.h
+big2str.o: $(hdrdir)/ruby/internal/variable.h
+big2str.o: $(hdrdir)/ruby/internal/warning_push.h
+big2str.o: $(hdrdir)/ruby/internal/xmalloc.h
+big2str.o: $(hdrdir)/ruby/missing.h
+big2str.o: $(hdrdir)/ruby/ruby.h
+big2str.o: $(hdrdir)/ruby/st.h
+big2str.o: $(hdrdir)/ruby/subst.h
+big2str.o: $(top_srcdir)/internal/bignum.h
+big2str.o: $(top_srcdir)/internal/compilers.h
+big2str.o: big2str.c
+bigzero.o: $(RUBY_EXTCONF_H)
+bigzero.o: $(arch_hdrdir)/ruby/config.h
+bigzero.o: $(hdrdir)/ruby/assert.h
+bigzero.o: $(hdrdir)/ruby/backward.h
+bigzero.o: $(hdrdir)/ruby/backward/2/assume.h
+bigzero.o: $(hdrdir)/ruby/backward/2/attributes.h
+bigzero.o: $(hdrdir)/ruby/backward/2/bool.h
+bigzero.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+bigzero.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bigzero.o: $(hdrdir)/ruby/backward/2/limits.h
+bigzero.o: $(hdrdir)/ruby/backward/2/long_long.h
+bigzero.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bigzero.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bigzero.o: $(hdrdir)/ruby/defines.h
+bigzero.o: $(hdrdir)/ruby/intern.h
+bigzero.o: $(hdrdir)/ruby/internal/abi.h
+bigzero.o: $(hdrdir)/ruby/internal/anyargs.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bigzero.o: $(hdrdir)/ruby/internal/assume.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/cold.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/const.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/error.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/format.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/pure.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/warning.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bigzero.o: $(hdrdir)/ruby/internal/cast.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_since.h
+bigzero.o: $(hdrdir)/ruby/internal/config.h
+bigzero.o: $(hdrdir)/ruby/internal/constant_p.h
+bigzero.o: $(hdrdir)/ruby/internal/core.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rarray.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rclass.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rdata.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rfile.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rhash.h
+bigzero.o: $(hdrdir)/ruby/internal/core/robject.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rstring.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bigzero.o: $(hdrdir)/ruby/internal/ctype.h
+bigzero.o: $(hdrdir)/ruby/internal/dllexport.h
+bigzero.o: $(hdrdir)/ruby/internal/dosish.h
+bigzero.o: $(hdrdir)/ruby/internal/error.h
+bigzero.o: $(hdrdir)/ruby/internal/eval.h
+bigzero.o: $(hdrdir)/ruby/internal/event.h
+bigzero.o: $(hdrdir)/ruby/internal/fl_type.h
+bigzero.o: $(hdrdir)/ruby/internal/gc.h
+bigzero.o: $(hdrdir)/ruby/internal/glob.h
+bigzero.o: $(hdrdir)/ruby/internal/globals.h
+bigzero.o: $(hdrdir)/ruby/internal/has/attribute.h
+bigzero.o: $(hdrdir)/ruby/internal/has/builtin.h
+bigzero.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bigzero.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bigzero.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bigzero.o: $(hdrdir)/ruby/internal/has/extension.h
+bigzero.o: $(hdrdir)/ruby/internal/has/feature.h
+bigzero.o: $(hdrdir)/ruby/internal/has/warning.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/array.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/class.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/compar.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/complex.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/cont.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/dir.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/enum.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/error.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/eval.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/file.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/hash.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/io.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/load.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/object.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/parse.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/proc.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/process.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/random.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/range.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/rational.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/re.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/select.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/set.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/signal.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/string.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/struct.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/thread.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/time.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/variable.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/vm.h
+bigzero.o: $(hdrdir)/ruby/internal/interpreter.h
+bigzero.o: $(hdrdir)/ruby/internal/iterator.h
+bigzero.o: $(hdrdir)/ruby/internal/memory.h
+bigzero.o: $(hdrdir)/ruby/internal/method.h
+bigzero.o: $(hdrdir)/ruby/internal/module.h
+bigzero.o: $(hdrdir)/ruby/internal/newobj.h
+bigzero.o: $(hdrdir)/ruby/internal/scan_args.h
+bigzero.o: $(hdrdir)/ruby/internal/special_consts.h
+bigzero.o: $(hdrdir)/ruby/internal/static_assert.h
+bigzero.o: $(hdrdir)/ruby/internal/stdalign.h
+bigzero.o: $(hdrdir)/ruby/internal/stdbool.h
+bigzero.o: $(hdrdir)/ruby/internal/stdckdint.h
+bigzero.o: $(hdrdir)/ruby/internal/symbol.h
+bigzero.o: $(hdrdir)/ruby/internal/value.h
+bigzero.o: $(hdrdir)/ruby/internal/value_type.h
+bigzero.o: $(hdrdir)/ruby/internal/variable.h
+bigzero.o: $(hdrdir)/ruby/internal/warning_push.h
+bigzero.o: $(hdrdir)/ruby/internal/xmalloc.h
+bigzero.o: $(hdrdir)/ruby/missing.h
+bigzero.o: $(hdrdir)/ruby/ruby.h
+bigzero.o: $(hdrdir)/ruby/st.h
+bigzero.o: $(hdrdir)/ruby/subst.h
+bigzero.o: $(top_srcdir)/internal/bignum.h
+bigzero.o: $(top_srcdir)/internal/compilers.h
+bigzero.o: bigzero.c
+div.o: $(RUBY_EXTCONF_H)
+div.o: $(arch_hdrdir)/ruby/config.h
+div.o: $(hdrdir)/ruby/assert.h
+div.o: $(hdrdir)/ruby/backward.h
+div.o: $(hdrdir)/ruby/backward/2/assume.h
+div.o: $(hdrdir)/ruby/backward/2/attributes.h
+div.o: $(hdrdir)/ruby/backward/2/bool.h
+div.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+div.o: $(hdrdir)/ruby/backward/2/inttypes.h
+div.o: $(hdrdir)/ruby/backward/2/limits.h
+div.o: $(hdrdir)/ruby/backward/2/long_long.h
+div.o: $(hdrdir)/ruby/backward/2/stdalign.h
+div.o: $(hdrdir)/ruby/backward/2/stdarg.h
+div.o: $(hdrdir)/ruby/defines.h
+div.o: $(hdrdir)/ruby/intern.h
+div.o: $(hdrdir)/ruby/internal/abi.h
+div.o: $(hdrdir)/ruby/internal/anyargs.h
+div.o: $(hdrdir)/ruby/internal/arithmetic.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+div.o: $(hdrdir)/ruby/internal/assume.h
+div.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+div.o: $(hdrdir)/ruby/internal/attr/artificial.h
+div.o: $(hdrdir)/ruby/internal/attr/cold.h
+div.o: $(hdrdir)/ruby/internal/attr/const.h
+div.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+div.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+div.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+div.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+div.o: $(hdrdir)/ruby/internal/attr/error.h
+div.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+div.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+div.o: $(hdrdir)/ruby/internal/attr/format.h
+div.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+div.o: $(hdrdir)/ruby/internal/attr/noalias.h
+div.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+div.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+div.o: $(hdrdir)/ruby/internal/attr/noinline.h
+div.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+div.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+div.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+div.o: $(hdrdir)/ruby/internal/attr/pure.h
+div.o: $(hdrdir)/ruby/internal/attr/restrict.h
+div.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+div.o: $(hdrdir)/ruby/internal/attr/warning.h
+div.o: $(hdrdir)/ruby/internal/attr/weakref.h
+div.o: $(hdrdir)/ruby/internal/cast.h
+div.o: $(hdrdir)/ruby/internal/compiler_is.h
+div.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+div.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+div.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+div.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+div.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+div.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+div.o: $(hdrdir)/ruby/internal/compiler_since.h
+div.o: $(hdrdir)/ruby/internal/config.h
+div.o: $(hdrdir)/ruby/internal/constant_p.h
+div.o: $(hdrdir)/ruby/internal/core.h
+div.o: $(hdrdir)/ruby/internal/core/rarray.h
+div.o: $(hdrdir)/ruby/internal/core/rbasic.h
+div.o: $(hdrdir)/ruby/internal/core/rbignum.h
+div.o: $(hdrdir)/ruby/internal/core/rclass.h
+div.o: $(hdrdir)/ruby/internal/core/rdata.h
+div.o: $(hdrdir)/ruby/internal/core/rfile.h
+div.o: $(hdrdir)/ruby/internal/core/rhash.h
+div.o: $(hdrdir)/ruby/internal/core/robject.h
+div.o: $(hdrdir)/ruby/internal/core/rregexp.h
+div.o: $(hdrdir)/ruby/internal/core/rstring.h
+div.o: $(hdrdir)/ruby/internal/core/rstruct.h
+div.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+div.o: $(hdrdir)/ruby/internal/ctype.h
+div.o: $(hdrdir)/ruby/internal/dllexport.h
+div.o: $(hdrdir)/ruby/internal/dosish.h
+div.o: $(hdrdir)/ruby/internal/error.h
+div.o: $(hdrdir)/ruby/internal/eval.h
+div.o: $(hdrdir)/ruby/internal/event.h
+div.o: $(hdrdir)/ruby/internal/fl_type.h
+div.o: $(hdrdir)/ruby/internal/gc.h
+div.o: $(hdrdir)/ruby/internal/glob.h
+div.o: $(hdrdir)/ruby/internal/globals.h
+div.o: $(hdrdir)/ruby/internal/has/attribute.h
+div.o: $(hdrdir)/ruby/internal/has/builtin.h
+div.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+div.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+div.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+div.o: $(hdrdir)/ruby/internal/has/extension.h
+div.o: $(hdrdir)/ruby/internal/has/feature.h
+div.o: $(hdrdir)/ruby/internal/has/warning.h
+div.o: $(hdrdir)/ruby/internal/intern/array.h
+div.o: $(hdrdir)/ruby/internal/intern/bignum.h
+div.o: $(hdrdir)/ruby/internal/intern/class.h
+div.o: $(hdrdir)/ruby/internal/intern/compar.h
+div.o: $(hdrdir)/ruby/internal/intern/complex.h
+div.o: $(hdrdir)/ruby/internal/intern/cont.h
+div.o: $(hdrdir)/ruby/internal/intern/dir.h
+div.o: $(hdrdir)/ruby/internal/intern/enum.h
+div.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+div.o: $(hdrdir)/ruby/internal/intern/error.h
+div.o: $(hdrdir)/ruby/internal/intern/eval.h
+div.o: $(hdrdir)/ruby/internal/intern/file.h
+div.o: $(hdrdir)/ruby/internal/intern/hash.h
+div.o: $(hdrdir)/ruby/internal/intern/io.h
+div.o: $(hdrdir)/ruby/internal/intern/load.h
+div.o: $(hdrdir)/ruby/internal/intern/marshal.h
+div.o: $(hdrdir)/ruby/internal/intern/numeric.h
+div.o: $(hdrdir)/ruby/internal/intern/object.h
+div.o: $(hdrdir)/ruby/internal/intern/parse.h
+div.o: $(hdrdir)/ruby/internal/intern/proc.h
+div.o: $(hdrdir)/ruby/internal/intern/process.h
+div.o: $(hdrdir)/ruby/internal/intern/random.h
+div.o: $(hdrdir)/ruby/internal/intern/range.h
+div.o: $(hdrdir)/ruby/internal/intern/rational.h
+div.o: $(hdrdir)/ruby/internal/intern/re.h
+div.o: $(hdrdir)/ruby/internal/intern/ruby.h
+div.o: $(hdrdir)/ruby/internal/intern/select.h
+div.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+div.o: $(hdrdir)/ruby/internal/intern/set.h
+div.o: $(hdrdir)/ruby/internal/intern/signal.h
+div.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+div.o: $(hdrdir)/ruby/internal/intern/string.h
+div.o: $(hdrdir)/ruby/internal/intern/struct.h
+div.o: $(hdrdir)/ruby/internal/intern/thread.h
+div.o: $(hdrdir)/ruby/internal/intern/time.h
+div.o: $(hdrdir)/ruby/internal/intern/variable.h
+div.o: $(hdrdir)/ruby/internal/intern/vm.h
+div.o: $(hdrdir)/ruby/internal/interpreter.h
+div.o: $(hdrdir)/ruby/internal/iterator.h
+div.o: $(hdrdir)/ruby/internal/memory.h
+div.o: $(hdrdir)/ruby/internal/method.h
+div.o: $(hdrdir)/ruby/internal/module.h
+div.o: $(hdrdir)/ruby/internal/newobj.h
+div.o: $(hdrdir)/ruby/internal/scan_args.h
+div.o: $(hdrdir)/ruby/internal/special_consts.h
+div.o: $(hdrdir)/ruby/internal/static_assert.h
+div.o: $(hdrdir)/ruby/internal/stdalign.h
+div.o: $(hdrdir)/ruby/internal/stdbool.h
+div.o: $(hdrdir)/ruby/internal/stdckdint.h
+div.o: $(hdrdir)/ruby/internal/symbol.h
+div.o: $(hdrdir)/ruby/internal/value.h
+div.o: $(hdrdir)/ruby/internal/value_type.h
+div.o: $(hdrdir)/ruby/internal/variable.h
+div.o: $(hdrdir)/ruby/internal/warning_push.h
+div.o: $(hdrdir)/ruby/internal/xmalloc.h
+div.o: $(hdrdir)/ruby/missing.h
+div.o: $(hdrdir)/ruby/ruby.h
+div.o: $(hdrdir)/ruby/st.h
+div.o: $(hdrdir)/ruby/subst.h
+div.o: $(top_srcdir)/internal/bignum.h
+div.o: $(top_srcdir)/internal/compilers.h
+div.o: div.c
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+intpack.o: $(RUBY_EXTCONF_H)
+intpack.o: $(arch_hdrdir)/ruby/config.h
+intpack.o: $(hdrdir)/ruby/assert.h
+intpack.o: $(hdrdir)/ruby/backward.h
+intpack.o: $(hdrdir)/ruby/backward/2/assume.h
+intpack.o: $(hdrdir)/ruby/backward/2/attributes.h
+intpack.o: $(hdrdir)/ruby/backward/2/bool.h
+intpack.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+intpack.o: $(hdrdir)/ruby/backward/2/inttypes.h
+intpack.o: $(hdrdir)/ruby/backward/2/limits.h
+intpack.o: $(hdrdir)/ruby/backward/2/long_long.h
+intpack.o: $(hdrdir)/ruby/backward/2/stdalign.h
+intpack.o: $(hdrdir)/ruby/backward/2/stdarg.h
+intpack.o: $(hdrdir)/ruby/defines.h
+intpack.o: $(hdrdir)/ruby/intern.h
+intpack.o: $(hdrdir)/ruby/internal/abi.h
+intpack.o: $(hdrdir)/ruby/internal/anyargs.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+intpack.o: $(hdrdir)/ruby/internal/assume.h
+intpack.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+intpack.o: $(hdrdir)/ruby/internal/attr/artificial.h
+intpack.o: $(hdrdir)/ruby/internal/attr/cold.h
+intpack.o: $(hdrdir)/ruby/internal/attr/const.h
+intpack.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+intpack.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+intpack.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+intpack.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+intpack.o: $(hdrdir)/ruby/internal/attr/error.h
+intpack.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+intpack.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+intpack.o: $(hdrdir)/ruby/internal/attr/format.h
+intpack.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+intpack.o: $(hdrdir)/ruby/internal/attr/noalias.h
+intpack.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+intpack.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+intpack.o: $(hdrdir)/ruby/internal/attr/noinline.h
+intpack.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+intpack.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+intpack.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+intpack.o: $(hdrdir)/ruby/internal/attr/pure.h
+intpack.o: $(hdrdir)/ruby/internal/attr/restrict.h
+intpack.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+intpack.o: $(hdrdir)/ruby/internal/attr/warning.h
+intpack.o: $(hdrdir)/ruby/internal/attr/weakref.h
+intpack.o: $(hdrdir)/ruby/internal/cast.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_since.h
+intpack.o: $(hdrdir)/ruby/internal/config.h
+intpack.o: $(hdrdir)/ruby/internal/constant_p.h
+intpack.o: $(hdrdir)/ruby/internal/core.h
+intpack.o: $(hdrdir)/ruby/internal/core/rarray.h
+intpack.o: $(hdrdir)/ruby/internal/core/rbasic.h
+intpack.o: $(hdrdir)/ruby/internal/core/rbignum.h
+intpack.o: $(hdrdir)/ruby/internal/core/rclass.h
+intpack.o: $(hdrdir)/ruby/internal/core/rdata.h
+intpack.o: $(hdrdir)/ruby/internal/core/rfile.h
+intpack.o: $(hdrdir)/ruby/internal/core/rhash.h
+intpack.o: $(hdrdir)/ruby/internal/core/robject.h
+intpack.o: $(hdrdir)/ruby/internal/core/rregexp.h
+intpack.o: $(hdrdir)/ruby/internal/core/rstring.h
+intpack.o: $(hdrdir)/ruby/internal/core/rstruct.h
+intpack.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+intpack.o: $(hdrdir)/ruby/internal/ctype.h
+intpack.o: $(hdrdir)/ruby/internal/dllexport.h
+intpack.o: $(hdrdir)/ruby/internal/dosish.h
+intpack.o: $(hdrdir)/ruby/internal/error.h
+intpack.o: $(hdrdir)/ruby/internal/eval.h
+intpack.o: $(hdrdir)/ruby/internal/event.h
+intpack.o: $(hdrdir)/ruby/internal/fl_type.h
+intpack.o: $(hdrdir)/ruby/internal/gc.h
+intpack.o: $(hdrdir)/ruby/internal/glob.h
+intpack.o: $(hdrdir)/ruby/internal/globals.h
+intpack.o: $(hdrdir)/ruby/internal/has/attribute.h
+intpack.o: $(hdrdir)/ruby/internal/has/builtin.h
+intpack.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+intpack.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+intpack.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+intpack.o: $(hdrdir)/ruby/internal/has/extension.h
+intpack.o: $(hdrdir)/ruby/internal/has/feature.h
+intpack.o: $(hdrdir)/ruby/internal/has/warning.h
+intpack.o: $(hdrdir)/ruby/internal/intern/array.h
+intpack.o: $(hdrdir)/ruby/internal/intern/bignum.h
+intpack.o: $(hdrdir)/ruby/internal/intern/class.h
+intpack.o: $(hdrdir)/ruby/internal/intern/compar.h
+intpack.o: $(hdrdir)/ruby/internal/intern/complex.h
+intpack.o: $(hdrdir)/ruby/internal/intern/cont.h
+intpack.o: $(hdrdir)/ruby/internal/intern/dir.h
+intpack.o: $(hdrdir)/ruby/internal/intern/enum.h
+intpack.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+intpack.o: $(hdrdir)/ruby/internal/intern/error.h
+intpack.o: $(hdrdir)/ruby/internal/intern/eval.h
+intpack.o: $(hdrdir)/ruby/internal/intern/file.h
+intpack.o: $(hdrdir)/ruby/internal/intern/hash.h
+intpack.o: $(hdrdir)/ruby/internal/intern/io.h
+intpack.o: $(hdrdir)/ruby/internal/intern/load.h
+intpack.o: $(hdrdir)/ruby/internal/intern/marshal.h
+intpack.o: $(hdrdir)/ruby/internal/intern/numeric.h
+intpack.o: $(hdrdir)/ruby/internal/intern/object.h
+intpack.o: $(hdrdir)/ruby/internal/intern/parse.h
+intpack.o: $(hdrdir)/ruby/internal/intern/proc.h
+intpack.o: $(hdrdir)/ruby/internal/intern/process.h
+intpack.o: $(hdrdir)/ruby/internal/intern/random.h
+intpack.o: $(hdrdir)/ruby/internal/intern/range.h
+intpack.o: $(hdrdir)/ruby/internal/intern/rational.h
+intpack.o: $(hdrdir)/ruby/internal/intern/re.h
+intpack.o: $(hdrdir)/ruby/internal/intern/ruby.h
+intpack.o: $(hdrdir)/ruby/internal/intern/select.h
+intpack.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+intpack.o: $(hdrdir)/ruby/internal/intern/set.h
+intpack.o: $(hdrdir)/ruby/internal/intern/signal.h
+intpack.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+intpack.o: $(hdrdir)/ruby/internal/intern/string.h
+intpack.o: $(hdrdir)/ruby/internal/intern/struct.h
+intpack.o: $(hdrdir)/ruby/internal/intern/thread.h
+intpack.o: $(hdrdir)/ruby/internal/intern/time.h
+intpack.o: $(hdrdir)/ruby/internal/intern/variable.h
+intpack.o: $(hdrdir)/ruby/internal/intern/vm.h
+intpack.o: $(hdrdir)/ruby/internal/interpreter.h
+intpack.o: $(hdrdir)/ruby/internal/iterator.h
+intpack.o: $(hdrdir)/ruby/internal/memory.h
+intpack.o: $(hdrdir)/ruby/internal/method.h
+intpack.o: $(hdrdir)/ruby/internal/module.h
+intpack.o: $(hdrdir)/ruby/internal/newobj.h
+intpack.o: $(hdrdir)/ruby/internal/scan_args.h
+intpack.o: $(hdrdir)/ruby/internal/special_consts.h
+intpack.o: $(hdrdir)/ruby/internal/static_assert.h
+intpack.o: $(hdrdir)/ruby/internal/stdalign.h
+intpack.o: $(hdrdir)/ruby/internal/stdbool.h
+intpack.o: $(hdrdir)/ruby/internal/stdckdint.h
+intpack.o: $(hdrdir)/ruby/internal/symbol.h
+intpack.o: $(hdrdir)/ruby/internal/value.h
+intpack.o: $(hdrdir)/ruby/internal/value_type.h
+intpack.o: $(hdrdir)/ruby/internal/variable.h
+intpack.o: $(hdrdir)/ruby/internal/warning_push.h
+intpack.o: $(hdrdir)/ruby/internal/xmalloc.h
+intpack.o: $(hdrdir)/ruby/missing.h
+intpack.o: $(hdrdir)/ruby/ruby.h
+intpack.o: $(hdrdir)/ruby/st.h
+intpack.o: $(hdrdir)/ruby/subst.h
+intpack.o: $(top_srcdir)/internal/bignum.h
+intpack.o: $(top_srcdir)/internal/compilers.h
+intpack.o: intpack.c
+mul.o: $(RUBY_EXTCONF_H)
+mul.o: $(arch_hdrdir)/ruby/config.h
+mul.o: $(hdrdir)/ruby/assert.h
+mul.o: $(hdrdir)/ruby/backward.h
+mul.o: $(hdrdir)/ruby/backward/2/assume.h
+mul.o: $(hdrdir)/ruby/backward/2/attributes.h
+mul.o: $(hdrdir)/ruby/backward/2/bool.h
+mul.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+mul.o: $(hdrdir)/ruby/backward/2/inttypes.h
+mul.o: $(hdrdir)/ruby/backward/2/limits.h
+mul.o: $(hdrdir)/ruby/backward/2/long_long.h
+mul.o: $(hdrdir)/ruby/backward/2/stdalign.h
+mul.o: $(hdrdir)/ruby/backward/2/stdarg.h
+mul.o: $(hdrdir)/ruby/defines.h
+mul.o: $(hdrdir)/ruby/intern.h
+mul.o: $(hdrdir)/ruby/internal/abi.h
+mul.o: $(hdrdir)/ruby/internal/anyargs.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+mul.o: $(hdrdir)/ruby/internal/assume.h
+mul.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+mul.o: $(hdrdir)/ruby/internal/attr/artificial.h
+mul.o: $(hdrdir)/ruby/internal/attr/cold.h
+mul.o: $(hdrdir)/ruby/internal/attr/const.h
+mul.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+mul.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+mul.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+mul.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+mul.o: $(hdrdir)/ruby/internal/attr/error.h
+mul.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+mul.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+mul.o: $(hdrdir)/ruby/internal/attr/format.h
+mul.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+mul.o: $(hdrdir)/ruby/internal/attr/noalias.h
+mul.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+mul.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+mul.o: $(hdrdir)/ruby/internal/attr/noinline.h
+mul.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+mul.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+mul.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+mul.o: $(hdrdir)/ruby/internal/attr/pure.h
+mul.o: $(hdrdir)/ruby/internal/attr/restrict.h
+mul.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+mul.o: $(hdrdir)/ruby/internal/attr/warning.h
+mul.o: $(hdrdir)/ruby/internal/attr/weakref.h
+mul.o: $(hdrdir)/ruby/internal/cast.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+mul.o: $(hdrdir)/ruby/internal/compiler_since.h
+mul.o: $(hdrdir)/ruby/internal/config.h
+mul.o: $(hdrdir)/ruby/internal/constant_p.h
+mul.o: $(hdrdir)/ruby/internal/core.h
+mul.o: $(hdrdir)/ruby/internal/core/rarray.h
+mul.o: $(hdrdir)/ruby/internal/core/rbasic.h
+mul.o: $(hdrdir)/ruby/internal/core/rbignum.h
+mul.o: $(hdrdir)/ruby/internal/core/rclass.h
+mul.o: $(hdrdir)/ruby/internal/core/rdata.h
+mul.o: $(hdrdir)/ruby/internal/core/rfile.h
+mul.o: $(hdrdir)/ruby/internal/core/rhash.h
+mul.o: $(hdrdir)/ruby/internal/core/robject.h
+mul.o: $(hdrdir)/ruby/internal/core/rregexp.h
+mul.o: $(hdrdir)/ruby/internal/core/rstring.h
+mul.o: $(hdrdir)/ruby/internal/core/rstruct.h
+mul.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+mul.o: $(hdrdir)/ruby/internal/ctype.h
+mul.o: $(hdrdir)/ruby/internal/dllexport.h
+mul.o: $(hdrdir)/ruby/internal/dosish.h
+mul.o: $(hdrdir)/ruby/internal/error.h
+mul.o: $(hdrdir)/ruby/internal/eval.h
+mul.o: $(hdrdir)/ruby/internal/event.h
+mul.o: $(hdrdir)/ruby/internal/fl_type.h
+mul.o: $(hdrdir)/ruby/internal/gc.h
+mul.o: $(hdrdir)/ruby/internal/glob.h
+mul.o: $(hdrdir)/ruby/internal/globals.h
+mul.o: $(hdrdir)/ruby/internal/has/attribute.h
+mul.o: $(hdrdir)/ruby/internal/has/builtin.h
+mul.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+mul.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+mul.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+mul.o: $(hdrdir)/ruby/internal/has/extension.h
+mul.o: $(hdrdir)/ruby/internal/has/feature.h
+mul.o: $(hdrdir)/ruby/internal/has/warning.h
+mul.o: $(hdrdir)/ruby/internal/intern/array.h
+mul.o: $(hdrdir)/ruby/internal/intern/bignum.h
+mul.o: $(hdrdir)/ruby/internal/intern/class.h
+mul.o: $(hdrdir)/ruby/internal/intern/compar.h
+mul.o: $(hdrdir)/ruby/internal/intern/complex.h
+mul.o: $(hdrdir)/ruby/internal/intern/cont.h
+mul.o: $(hdrdir)/ruby/internal/intern/dir.h
+mul.o: $(hdrdir)/ruby/internal/intern/enum.h
+mul.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+mul.o: $(hdrdir)/ruby/internal/intern/error.h
+mul.o: $(hdrdir)/ruby/internal/intern/eval.h
+mul.o: $(hdrdir)/ruby/internal/intern/file.h
+mul.o: $(hdrdir)/ruby/internal/intern/hash.h
+mul.o: $(hdrdir)/ruby/internal/intern/io.h
+mul.o: $(hdrdir)/ruby/internal/intern/load.h
+mul.o: $(hdrdir)/ruby/internal/intern/marshal.h
+mul.o: $(hdrdir)/ruby/internal/intern/numeric.h
+mul.o: $(hdrdir)/ruby/internal/intern/object.h
+mul.o: $(hdrdir)/ruby/internal/intern/parse.h
+mul.o: $(hdrdir)/ruby/internal/intern/proc.h
+mul.o: $(hdrdir)/ruby/internal/intern/process.h
+mul.o: $(hdrdir)/ruby/internal/intern/random.h
+mul.o: $(hdrdir)/ruby/internal/intern/range.h
+mul.o: $(hdrdir)/ruby/internal/intern/rational.h
+mul.o: $(hdrdir)/ruby/internal/intern/re.h
+mul.o: $(hdrdir)/ruby/internal/intern/ruby.h
+mul.o: $(hdrdir)/ruby/internal/intern/select.h
+mul.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+mul.o: $(hdrdir)/ruby/internal/intern/set.h
+mul.o: $(hdrdir)/ruby/internal/intern/signal.h
+mul.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+mul.o: $(hdrdir)/ruby/internal/intern/string.h
+mul.o: $(hdrdir)/ruby/internal/intern/struct.h
+mul.o: $(hdrdir)/ruby/internal/intern/thread.h
+mul.o: $(hdrdir)/ruby/internal/intern/time.h
+mul.o: $(hdrdir)/ruby/internal/intern/variable.h
+mul.o: $(hdrdir)/ruby/internal/intern/vm.h
+mul.o: $(hdrdir)/ruby/internal/interpreter.h
+mul.o: $(hdrdir)/ruby/internal/iterator.h
+mul.o: $(hdrdir)/ruby/internal/memory.h
+mul.o: $(hdrdir)/ruby/internal/method.h
+mul.o: $(hdrdir)/ruby/internal/module.h
+mul.o: $(hdrdir)/ruby/internal/newobj.h
+mul.o: $(hdrdir)/ruby/internal/scan_args.h
+mul.o: $(hdrdir)/ruby/internal/special_consts.h
+mul.o: $(hdrdir)/ruby/internal/static_assert.h
+mul.o: $(hdrdir)/ruby/internal/stdalign.h
+mul.o: $(hdrdir)/ruby/internal/stdbool.h
+mul.o: $(hdrdir)/ruby/internal/stdckdint.h
+mul.o: $(hdrdir)/ruby/internal/symbol.h
+mul.o: $(hdrdir)/ruby/internal/value.h
+mul.o: $(hdrdir)/ruby/internal/value_type.h
+mul.o: $(hdrdir)/ruby/internal/variable.h
+mul.o: $(hdrdir)/ruby/internal/warning_push.h
+mul.o: $(hdrdir)/ruby/internal/xmalloc.h
+mul.o: $(hdrdir)/ruby/missing.h
+mul.o: $(hdrdir)/ruby/ruby.h
+mul.o: $(hdrdir)/ruby/st.h
+mul.o: $(hdrdir)/ruby/subst.h
+mul.o: $(top_srcdir)/internal/bignum.h
+mul.o: $(top_srcdir)/internal/compilers.h
+mul.o: mul.c
+str2big.o: $(RUBY_EXTCONF_H)
+str2big.o: $(arch_hdrdir)/ruby/config.h
+str2big.o: $(hdrdir)/ruby/assert.h
+str2big.o: $(hdrdir)/ruby/backward.h
+str2big.o: $(hdrdir)/ruby/backward/2/assume.h
+str2big.o: $(hdrdir)/ruby/backward/2/attributes.h
+str2big.o: $(hdrdir)/ruby/backward/2/bool.h
+str2big.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+str2big.o: $(hdrdir)/ruby/backward/2/inttypes.h
+str2big.o: $(hdrdir)/ruby/backward/2/limits.h
+str2big.o: $(hdrdir)/ruby/backward/2/long_long.h
+str2big.o: $(hdrdir)/ruby/backward/2/stdalign.h
+str2big.o: $(hdrdir)/ruby/backward/2/stdarg.h
+str2big.o: $(hdrdir)/ruby/defines.h
+str2big.o: $(hdrdir)/ruby/intern.h
+str2big.o: $(hdrdir)/ruby/internal/abi.h
+str2big.o: $(hdrdir)/ruby/internal/anyargs.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+str2big.o: $(hdrdir)/ruby/internal/assume.h
+str2big.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+str2big.o: $(hdrdir)/ruby/internal/attr/artificial.h
+str2big.o: $(hdrdir)/ruby/internal/attr/cold.h
+str2big.o: $(hdrdir)/ruby/internal/attr/const.h
+str2big.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+str2big.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+str2big.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+str2big.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+str2big.o: $(hdrdir)/ruby/internal/attr/error.h
+str2big.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+str2big.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+str2big.o: $(hdrdir)/ruby/internal/attr/format.h
+str2big.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+str2big.o: $(hdrdir)/ruby/internal/attr/noalias.h
+str2big.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+str2big.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+str2big.o: $(hdrdir)/ruby/internal/attr/noinline.h
+str2big.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+str2big.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+str2big.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+str2big.o: $(hdrdir)/ruby/internal/attr/pure.h
+str2big.o: $(hdrdir)/ruby/internal/attr/restrict.h
+str2big.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+str2big.o: $(hdrdir)/ruby/internal/attr/warning.h
+str2big.o: $(hdrdir)/ruby/internal/attr/weakref.h
+str2big.o: $(hdrdir)/ruby/internal/cast.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_since.h
+str2big.o: $(hdrdir)/ruby/internal/config.h
+str2big.o: $(hdrdir)/ruby/internal/constant_p.h
+str2big.o: $(hdrdir)/ruby/internal/core.h
+str2big.o: $(hdrdir)/ruby/internal/core/rarray.h
+str2big.o: $(hdrdir)/ruby/internal/core/rbasic.h
+str2big.o: $(hdrdir)/ruby/internal/core/rbignum.h
+str2big.o: $(hdrdir)/ruby/internal/core/rclass.h
+str2big.o: $(hdrdir)/ruby/internal/core/rdata.h
+str2big.o: $(hdrdir)/ruby/internal/core/rfile.h
+str2big.o: $(hdrdir)/ruby/internal/core/rhash.h
+str2big.o: $(hdrdir)/ruby/internal/core/robject.h
+str2big.o: $(hdrdir)/ruby/internal/core/rregexp.h
+str2big.o: $(hdrdir)/ruby/internal/core/rstring.h
+str2big.o: $(hdrdir)/ruby/internal/core/rstruct.h
+str2big.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+str2big.o: $(hdrdir)/ruby/internal/ctype.h
+str2big.o: $(hdrdir)/ruby/internal/dllexport.h
+str2big.o: $(hdrdir)/ruby/internal/dosish.h
+str2big.o: $(hdrdir)/ruby/internal/error.h
+str2big.o: $(hdrdir)/ruby/internal/eval.h
+str2big.o: $(hdrdir)/ruby/internal/event.h
+str2big.o: $(hdrdir)/ruby/internal/fl_type.h
+str2big.o: $(hdrdir)/ruby/internal/gc.h
+str2big.o: $(hdrdir)/ruby/internal/glob.h
+str2big.o: $(hdrdir)/ruby/internal/globals.h
+str2big.o: $(hdrdir)/ruby/internal/has/attribute.h
+str2big.o: $(hdrdir)/ruby/internal/has/builtin.h
+str2big.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+str2big.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+str2big.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+str2big.o: $(hdrdir)/ruby/internal/has/extension.h
+str2big.o: $(hdrdir)/ruby/internal/has/feature.h
+str2big.o: $(hdrdir)/ruby/internal/has/warning.h
+str2big.o: $(hdrdir)/ruby/internal/intern/array.h
+str2big.o: $(hdrdir)/ruby/internal/intern/bignum.h
+str2big.o: $(hdrdir)/ruby/internal/intern/class.h
+str2big.o: $(hdrdir)/ruby/internal/intern/compar.h
+str2big.o: $(hdrdir)/ruby/internal/intern/complex.h
+str2big.o: $(hdrdir)/ruby/internal/intern/cont.h
+str2big.o: $(hdrdir)/ruby/internal/intern/dir.h
+str2big.o: $(hdrdir)/ruby/internal/intern/enum.h
+str2big.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+str2big.o: $(hdrdir)/ruby/internal/intern/error.h
+str2big.o: $(hdrdir)/ruby/internal/intern/eval.h
+str2big.o: $(hdrdir)/ruby/internal/intern/file.h
+str2big.o: $(hdrdir)/ruby/internal/intern/hash.h
+str2big.o: $(hdrdir)/ruby/internal/intern/io.h
+str2big.o: $(hdrdir)/ruby/internal/intern/load.h
+str2big.o: $(hdrdir)/ruby/internal/intern/marshal.h
+str2big.o: $(hdrdir)/ruby/internal/intern/numeric.h
+str2big.o: $(hdrdir)/ruby/internal/intern/object.h
+str2big.o: $(hdrdir)/ruby/internal/intern/parse.h
+str2big.o: $(hdrdir)/ruby/internal/intern/proc.h
+str2big.o: $(hdrdir)/ruby/internal/intern/process.h
+str2big.o: $(hdrdir)/ruby/internal/intern/random.h
+str2big.o: $(hdrdir)/ruby/internal/intern/range.h
+str2big.o: $(hdrdir)/ruby/internal/intern/rational.h
+str2big.o: $(hdrdir)/ruby/internal/intern/re.h
+str2big.o: $(hdrdir)/ruby/internal/intern/ruby.h
+str2big.o: $(hdrdir)/ruby/internal/intern/select.h
+str2big.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+str2big.o: $(hdrdir)/ruby/internal/intern/set.h
+str2big.o: $(hdrdir)/ruby/internal/intern/signal.h
+str2big.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+str2big.o: $(hdrdir)/ruby/internal/intern/string.h
+str2big.o: $(hdrdir)/ruby/internal/intern/struct.h
+str2big.o: $(hdrdir)/ruby/internal/intern/thread.h
+str2big.o: $(hdrdir)/ruby/internal/intern/time.h
+str2big.o: $(hdrdir)/ruby/internal/intern/variable.h
+str2big.o: $(hdrdir)/ruby/internal/intern/vm.h
+str2big.o: $(hdrdir)/ruby/internal/interpreter.h
+str2big.o: $(hdrdir)/ruby/internal/iterator.h
+str2big.o: $(hdrdir)/ruby/internal/memory.h
+str2big.o: $(hdrdir)/ruby/internal/method.h
+str2big.o: $(hdrdir)/ruby/internal/module.h
+str2big.o: $(hdrdir)/ruby/internal/newobj.h
+str2big.o: $(hdrdir)/ruby/internal/scan_args.h
+str2big.o: $(hdrdir)/ruby/internal/special_consts.h
+str2big.o: $(hdrdir)/ruby/internal/static_assert.h
+str2big.o: $(hdrdir)/ruby/internal/stdalign.h
+str2big.o: $(hdrdir)/ruby/internal/stdbool.h
+str2big.o: $(hdrdir)/ruby/internal/stdckdint.h
+str2big.o: $(hdrdir)/ruby/internal/symbol.h
+str2big.o: $(hdrdir)/ruby/internal/value.h
+str2big.o: $(hdrdir)/ruby/internal/value_type.h
+str2big.o: $(hdrdir)/ruby/internal/variable.h
+str2big.o: $(hdrdir)/ruby/internal/warning_push.h
+str2big.o: $(hdrdir)/ruby/internal/xmalloc.h
+str2big.o: $(hdrdir)/ruby/missing.h
+str2big.o: $(hdrdir)/ruby/ruby.h
+str2big.o: $(hdrdir)/ruby/st.h
+str2big.o: $(hdrdir)/ruby/subst.h
+str2big.o: $(top_srcdir)/internal/bignum.h
+str2big.o: $(top_srcdir)/internal/compilers.h
+str2big.o: str2big.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/bignum/div.c b/ext/-test-/bignum/div.c
new file mode 100644
index 0000000000..85ee0677fa
--- /dev/null
+++ b/ext/-test-/bignum/div.c
@@ -0,0 +1,35 @@
+#include "internal/bignum.h"
+
+static VALUE
+big(VALUE x)
+{
+ if (FIXNUM_P(x))
+ return rb_int2big(FIX2LONG(x));
+ if (RB_TYPE_P(x, T_BIGNUM))
+ return x;
+ rb_raise(rb_eTypeError, "can't convert %s to Bignum",
+ rb_obj_classname(x));
+}
+
+static VALUE
+divrem_normal(VALUE klass, VALUE x, VALUE y)
+{
+ return rb_big_norm(rb_big_divrem_normal(big(x), big(y)));
+}
+
+#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
+static VALUE
+divrem_gmp(VALUE klass, VALUE x, VALUE y)
+{
+ return rb_big_norm(rb_big_divrem_gmp(big(x), big(y)));
+}
+#else
+#define divrem_gmp rb_f_notimplement
+#endif
+
+void
+Init_div(VALUE klass)
+{
+ rb_define_singleton_method(klass, "big_divrem_normal", divrem_normal, 2);
+ rb_define_singleton_method(klass, "big_divrem_gmp", divrem_gmp, 2);
+}
diff --git a/ext/-test-/bignum/extconf.rb b/ext/-test-/bignum/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/bignum/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/bignum/init.c b/ext/-test-/bignum/init.c
new file mode 100644
index 0000000000..82a159bf1d
--- /dev/null
+++ b/ext/-test-/bignum/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_bignum(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "Bignum", rb_cString);
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/bignum/intpack.c b/ext/-test-/bignum/intpack.c
new file mode 100644
index 0000000000..d5591505e5
--- /dev/null
+++ b/ext/-test-/bignum/intpack.c
@@ -0,0 +1,87 @@
+#include "internal/bignum.h"
+
+static VALUE
+rb_integer_pack_raw_m(VALUE klass, VALUE val, VALUE buf, VALUE numwords_arg, VALUE wordsize_arg, VALUE nails, VALUE flags)
+{
+ int sign;
+ size_t numwords = 0;
+ size_t wordsize = NUM2SIZET(wordsize_arg);
+
+ StringValue(buf);
+ rb_str_modify(buf);
+ sign = rb_integer_pack(val,
+ RSTRING_PTR(buf), NUM2SIZET(numwords_arg),
+ NUM2SIZET(wordsize_arg), NUM2SIZET(nails), NUM2INT(flags));
+
+ return rb_ary_new_from_args(2, INT2NUM(sign), rb_str_new(RSTRING_PTR(buf), wordsize * numwords));
+}
+
+static VALUE
+rb_integer_pack_m(VALUE klass, VALUE val, VALUE numwords_arg, VALUE wordsize_arg, VALUE nails, VALUE flags)
+{
+ int sign;
+ size_t numwords = NUM2SIZET(numwords_arg);
+ size_t wordsize = NUM2SIZET(wordsize_arg);
+ VALUE buf;
+
+ if (numwords != 0 && wordsize != 0 && LONG_MAX / wordsize < numwords)
+ rb_raise(rb_eArgError, "too big numwords * wordsize");
+ buf = rb_str_new(NULL, numwords * wordsize);
+ sign = rb_integer_pack(val,
+ RSTRING_PTR(buf), numwords,
+ wordsize, NUM2SIZET(nails), NUM2INT(flags));
+
+ return rb_assoc_new(INT2NUM(sign), buf);
+}
+
+static VALUE
+rb_integer_unpack_m(VALUE klass, VALUE buf, VALUE numwords, VALUE wordsize, VALUE nails, VALUE flags)
+{
+ StringValue(buf);
+
+ return rb_integer_unpack(RSTRING_PTR(buf),
+ NUM2SIZET(numwords), NUM2SIZET(wordsize),
+ NUM2SIZET(nails), NUM2INT(flags));
+}
+
+static VALUE
+rb_integer_test_numbits_2comp_without_sign(VALUE klass, VALUE val)
+{
+ size_t size;
+ int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val);
+ size = rb_absint_numwords(val, 1, NULL) - (neg && rb_absint_singlebit_p(val));
+ return SIZET2NUM(size);
+}
+
+static VALUE
+rb_integer_test_numbytes_2comp_with_sign(VALUE klass, VALUE val)
+{
+ int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val);
+ int nlz_bits;
+ size_t size = rb_absint_size(val, &nlz_bits);
+ if (nlz_bits == 0 && !(neg && rb_absint_singlebit_p(val)))
+ size++;
+ return SIZET2NUM(size);
+}
+
+void
+Init_intpack(VALUE klass)
+{
+ rb_define_singleton_method(klass, "test_pack_raw", rb_integer_pack_raw_m, 6);
+ rb_define_singleton_method(klass, "test_pack", rb_integer_pack_m, 5);
+ rb_define_singleton_method(klass, "test_unpack", rb_integer_unpack_m, 5);
+ rb_define_const(klass, "INTEGER_PACK_MSWORD_FIRST", INT2NUM(INTEGER_PACK_MSWORD_FIRST));
+ rb_define_const(klass, "INTEGER_PACK_LSWORD_FIRST", INT2NUM(INTEGER_PACK_LSWORD_FIRST));
+ rb_define_const(klass, "INTEGER_PACK_MSBYTE_FIRST", INT2NUM(INTEGER_PACK_MSBYTE_FIRST));
+ rb_define_const(klass, "INTEGER_PACK_LSBYTE_FIRST", INT2NUM(INTEGER_PACK_LSBYTE_FIRST));
+ rb_define_const(klass, "INTEGER_PACK_NATIVE_BYTE_ORDER", INT2NUM(INTEGER_PACK_NATIVE_BYTE_ORDER));
+ rb_define_const(klass, "INTEGER_PACK_2COMP", INT2NUM(INTEGER_PACK_2COMP));
+ rb_define_const(klass, "INTEGER_PACK_LITTLE_ENDIAN", INT2NUM(INTEGER_PACK_LITTLE_ENDIAN));
+ rb_define_const(klass, "INTEGER_PACK_BIG_ENDIAN", INT2NUM(INTEGER_PACK_BIG_ENDIAN));
+ rb_define_const(klass, "INTEGER_PACK_FORCE_BIGNUM", INT2NUM(INTEGER_PACK_FORCE_BIGNUM));
+ rb_define_const(klass, "INTEGER_PACK_NEGATIVE", INT2NUM(INTEGER_PACK_NEGATIVE));
+ rb_define_const(klass, "INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION", INT2NUM(INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION));
+
+ rb_define_singleton_method(klass, "test_numbits_2comp_without_sign", rb_integer_test_numbits_2comp_without_sign, 1);
+ rb_define_singleton_method(klass, "test_numbytes_2comp_with_sign", rb_integer_test_numbytes_2comp_with_sign, 1);
+}
diff --git a/ext/-test-/bignum/mul.c b/ext/-test-/bignum/mul.c
new file mode 100644
index 0000000000..05ba103c44
--- /dev/null
+++ b/ext/-test-/bignum/mul.c
@@ -0,0 +1,65 @@
+#include "internal/bignum.h"
+
+static VALUE
+big(VALUE x)
+{
+ if (FIXNUM_P(x))
+ return rb_int2big(FIX2LONG(x));
+ if (RB_TYPE_P(x, T_BIGNUM))
+ return x;
+ rb_raise(rb_eTypeError, "can't convert %s to Bignum",
+ rb_obj_classname(x));
+}
+
+static VALUE
+mul_normal(VALUE klass, VALUE x, VALUE y)
+{
+ return rb_big_norm(rb_big_mul_normal(big(x), big(y)));
+}
+
+static VALUE
+sq_fast(VALUE klass, VALUE x)
+{
+ return rb_big_norm(rb_big_sq_fast(big(x)));
+}
+
+static VALUE
+mul_balance(VALUE klass, VALUE x, VALUE y)
+{
+ return rb_big_norm(rb_big_mul_balance(big(x), big(y)));
+}
+
+static VALUE
+mul_karatsuba(VALUE klass, VALUE x, VALUE y)
+{
+ return rb_big_norm(rb_big_mul_karatsuba(big(x), big(y)));
+}
+
+static VALUE
+mul_toom3(VALUE klass, VALUE x, VALUE y)
+{
+ return rb_big_norm(rb_big_mul_toom3(big(x), big(y)));
+}
+
+#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
+static VALUE
+mul_gmp(VALUE klass, VALUE x, VALUE y)
+{
+ return rb_big_norm(rb_big_mul_gmp(big(x), big(y)));
+}
+#else
+#define mul_gmp rb_f_notimplement
+#endif
+
+void
+Init_mul(VALUE klass)
+{
+ rb_define_const(klass, "SIZEOF_BDIGIT", INT2NUM(SIZEOF_BDIGIT));
+ rb_define_const(klass, "BITSPERDIG", INT2NUM(SIZEOF_BDIGIT * CHAR_BIT));
+ rb_define_singleton_method(klass, "big_mul_normal", mul_normal, 2);
+ rb_define_singleton_method(klass, "big_sq_fast", sq_fast, 1);
+ rb_define_singleton_method(klass, "big_mul_balance", mul_balance, 2);
+ rb_define_singleton_method(klass, "big_mul_karatsuba", mul_karatsuba, 2);
+ rb_define_singleton_method(klass, "big_mul_toom3", mul_toom3, 2);
+ rb_define_singleton_method(klass, "big_mul_gmp", mul_gmp, 2);
+}
diff --git a/ext/-test-/bignum/str2big.c b/ext/-test-/bignum/str2big.c
new file mode 100644
index 0000000000..337cf8fb6d
--- /dev/null
+++ b/ext/-test-/bignum/str2big.c
@@ -0,0 +1,38 @@
+#include "internal/bignum.h"
+
+static VALUE
+str2big_poweroftwo(VALUE klass, VALUE str, VALUE vbase, VALUE badcheck)
+{
+ return rb_str2big_poweroftwo(str, NUM2INT(vbase), RTEST(badcheck));
+}
+
+static VALUE
+str2big_normal(VALUE klass, VALUE str, VALUE vbase, VALUE badcheck)
+{
+ return rb_str2big_normal(str, NUM2INT(vbase), RTEST(badcheck));
+}
+
+static VALUE
+str2big_karatsuba(VALUE klass, VALUE str, VALUE vbase, VALUE badcheck)
+{
+ return rb_str2big_karatsuba(str, NUM2INT(vbase), RTEST(badcheck));
+}
+
+#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
+static VALUE
+str2big_gmp(VALUE klass, VALUE str, VALUE vbase, VALUE badcheck)
+{
+ return rb_str2big_gmp(str, NUM2INT(vbase), RTEST(badcheck));
+}
+#else
+#define str2big_gmp rb_f_notimplement
+#endif
+
+void
+Init_str2big(VALUE klass)
+{
+ rb_define_singleton_method(klass, "str2big_poweroftwo", str2big_poweroftwo, 3);
+ rb_define_singleton_method(klass, "str2big_normal", str2big_normal, 3);
+ rb_define_singleton_method(klass, "str2big_karatsuba", str2big_karatsuba, 3);
+ rb_define_singleton_method(klass, "str2big_gmp", str2big_gmp, 3);
+}
diff --git a/ext/-test-/box/yay1/extconf.rb b/ext/-test-/box/yay1/extconf.rb
new file mode 100644
index 0000000000..54387cedf1
--- /dev/null
+++ b/ext/-test-/box/yay1/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/box/yay1')
diff --git a/ext/-test-/box/yay1/yay1.c b/ext/-test-/box/yay1/yay1.c
new file mode 100644
index 0000000000..564a221c8c
--- /dev/null
+++ b/ext/-test-/box/yay1/yay1.c
@@ -0,0 +1,28 @@
+#include "yay1.h"
+
+VALUE
+yay_value(void)
+{
+ return rb_str_new_cstr("yay");
+}
+
+static VALUE
+yay1_f_version(VALUE klass)
+{
+ return rb_str_new_cstr("1.0.0");
+}
+
+static VALUE
+yay1_yay(VALUE klass)
+{
+ return yay_value();
+}
+
+void
+Init_yay1(void)
+{
+ VALUE mod = rb_define_module("Yay");
+ rb_define_const(mod, "VERSION", rb_str_new_cstr("1.0.0"));
+ rb_define_singleton_method(mod, "version", yay1_f_version, 0);
+ rb_define_singleton_method(mod, "yay", yay1_yay, 0);
+}
diff --git a/ext/-test-/box/yay1/yay1.def b/ext/-test-/box/yay1/yay1.def
new file mode 100644
index 0000000000..510fbe7017
--- /dev/null
+++ b/ext/-test-/box/yay1/yay1.def
@@ -0,0 +1,3 @@
+EXPORTS
+ Init_yay1
+ yay_value
diff --git a/ext/-test-/box/yay1/yay1.h b/ext/-test-/box/yay1/yay1.h
new file mode 100644
index 0000000000..c4dade928a
--- /dev/null
+++ b/ext/-test-/box/yay1/yay1.h
@@ -0,0 +1,4 @@
+#include <ruby.h>
+#include "ruby/internal/dllexport.h"
+
+RUBY_FUNC_EXPORTED VALUE yay_value(void);
diff --git a/ext/-test-/box/yay2/extconf.rb b/ext/-test-/box/yay2/extconf.rb
new file mode 100644
index 0000000000..850ef3edc9
--- /dev/null
+++ b/ext/-test-/box/yay2/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/box/yay2')
diff --git a/ext/-test-/box/yay2/yay2.c b/ext/-test-/box/yay2/yay2.c
new file mode 100644
index 0000000000..b632ae8495
--- /dev/null
+++ b/ext/-test-/box/yay2/yay2.c
@@ -0,0 +1,28 @@
+#include "yay2.h"
+
+VALUE
+yay_value(void)
+{
+ return rb_str_new_cstr("yaaay");
+}
+
+static VALUE
+yay2_f_version(VALUE klass)
+{
+ return rb_str_new_cstr("2.0.0");
+}
+
+static VALUE
+yay2_yay(VALUE klass)
+{
+ return yay_value();
+}
+
+void
+Init_yay2(void)
+{
+ VALUE mod = rb_define_module("Yay");
+ rb_define_const(mod, "VERSION", rb_str_new_cstr("2.0.0"));
+ rb_define_singleton_method(mod, "version", yay2_f_version, 0);
+ rb_define_singleton_method(mod, "yay", yay2_yay, 0);
+}
diff --git a/ext/-test-/box/yay2/yay2.def b/ext/-test-/box/yay2/yay2.def
new file mode 100644
index 0000000000..163fc44c04
--- /dev/null
+++ b/ext/-test-/box/yay2/yay2.def
@@ -0,0 +1,3 @@
+EXPORTS
+ Init_yay2
+ yay_value
diff --git a/ext/-test-/box/yay2/yay2.h b/ext/-test-/box/yay2/yay2.h
new file mode 100644
index 0000000000..c4dade928a
--- /dev/null
+++ b/ext/-test-/box/yay2/yay2.h
@@ -0,0 +1,4 @@
+#include <ruby.h>
+#include "ruby/internal/dllexport.h"
+
+RUBY_FUNC_EXPORTED VALUE yay_value(void);
diff --git a/ext/-test-/bug-14834/bug-14834.c b/ext/-test-/bug-14834/bug-14834.c
new file mode 100644
index 0000000000..af2070d303
--- /dev/null
+++ b/ext/-test-/bug-14834/bug-14834.c
@@ -0,0 +1,39 @@
+#include <ruby/ruby.h>
+#include <ruby/debug.h>
+
+#ifndef MAYBE_UNUSED
+# define MAYBE_UNUSED(x) x
+#endif
+
+static NOINLINE(VALUE f(VALUE));
+static NOINLINE(void g(VALUE, void*));
+extern NOINLINE(void Init_bug_14834(void));
+
+void
+Init_bug_14834(void)
+{
+ VALUE q = rb_define_module("Bug");
+ rb_define_module_function(q, "bug_14834", f, 0);
+}
+
+VALUE
+f(VALUE q)
+{
+ int w[] = { 0, 1024 };
+ VALUE e = rb_tracepoint_new(Qnil, RUBY_INTERNAL_EVENT_NEWOBJ, g, w);
+
+ rb_tracepoint_enable(e);
+ return rb_ensure(rb_yield, q, rb_tracepoint_disable, e);
+}
+
+void
+g(MAYBE_UNUSED(VALUE q), void* w)
+{
+ const int *e = (const int *)w;
+ const int r = *e++;
+ const int t = *e++;
+ VALUE *y = ALLOCA_N(VALUE, t);
+ int *u = ALLOCA_N(int, t);
+
+ rb_profile_frames(r, t, y, u);
+}
diff --git a/ext/-test-/bug-14834/depend b/ext/-test-/bug-14834/depend
new file mode 100644
index 0000000000..f83939d559
--- /dev/null
+++ b/ext/-test-/bug-14834/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+bug-14834.o: $(RUBY_EXTCONF_H)
+bug-14834.o: $(arch_hdrdir)/ruby/config.h
+bug-14834.o: $(hdrdir)/ruby/assert.h
+bug-14834.o: $(hdrdir)/ruby/backward.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/assume.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/bool.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/limits.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bug-14834.o: $(hdrdir)/ruby/debug.h
+bug-14834.o: $(hdrdir)/ruby/defines.h
+bug-14834.o: $(hdrdir)/ruby/intern.h
+bug-14834.o: $(hdrdir)/ruby/internal/abi.h
+bug-14834.o: $(hdrdir)/ruby/internal/anyargs.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/assume.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/cold.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/const.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/error.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/format.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/pure.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/warning.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bug-14834.o: $(hdrdir)/ruby/internal/cast.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_since.h
+bug-14834.o: $(hdrdir)/ruby/internal/config.h
+bug-14834.o: $(hdrdir)/ruby/internal/constant_p.h
+bug-14834.o: $(hdrdir)/ruby/internal/core.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rarray.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rclass.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rdata.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rfile.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rhash.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/robject.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rstring.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bug-14834.o: $(hdrdir)/ruby/internal/ctype.h
+bug-14834.o: $(hdrdir)/ruby/internal/dllexport.h
+bug-14834.o: $(hdrdir)/ruby/internal/dosish.h
+bug-14834.o: $(hdrdir)/ruby/internal/error.h
+bug-14834.o: $(hdrdir)/ruby/internal/eval.h
+bug-14834.o: $(hdrdir)/ruby/internal/event.h
+bug-14834.o: $(hdrdir)/ruby/internal/fl_type.h
+bug-14834.o: $(hdrdir)/ruby/internal/gc.h
+bug-14834.o: $(hdrdir)/ruby/internal/glob.h
+bug-14834.o: $(hdrdir)/ruby/internal/globals.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/attribute.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/builtin.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/extension.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/feature.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/warning.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/array.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/class.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/compar.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/complex.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/cont.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/dir.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/enum.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/error.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/eval.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/file.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/hash.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/io.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/load.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/object.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/parse.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/proc.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/process.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/random.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/range.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/rational.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/re.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/select.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/set.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/signal.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/string.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/struct.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/thread.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/time.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/variable.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/vm.h
+bug-14834.o: $(hdrdir)/ruby/internal/interpreter.h
+bug-14834.o: $(hdrdir)/ruby/internal/iterator.h
+bug-14834.o: $(hdrdir)/ruby/internal/memory.h
+bug-14834.o: $(hdrdir)/ruby/internal/method.h
+bug-14834.o: $(hdrdir)/ruby/internal/module.h
+bug-14834.o: $(hdrdir)/ruby/internal/newobj.h
+bug-14834.o: $(hdrdir)/ruby/internal/scan_args.h
+bug-14834.o: $(hdrdir)/ruby/internal/special_consts.h
+bug-14834.o: $(hdrdir)/ruby/internal/static_assert.h
+bug-14834.o: $(hdrdir)/ruby/internal/stdalign.h
+bug-14834.o: $(hdrdir)/ruby/internal/stdbool.h
+bug-14834.o: $(hdrdir)/ruby/internal/stdckdint.h
+bug-14834.o: $(hdrdir)/ruby/internal/symbol.h
+bug-14834.o: $(hdrdir)/ruby/internal/value.h
+bug-14834.o: $(hdrdir)/ruby/internal/value_type.h
+bug-14834.o: $(hdrdir)/ruby/internal/variable.h
+bug-14834.o: $(hdrdir)/ruby/internal/warning_push.h
+bug-14834.o: $(hdrdir)/ruby/internal/xmalloc.h
+bug-14834.o: $(hdrdir)/ruby/missing.h
+bug-14834.o: $(hdrdir)/ruby/ruby.h
+bug-14834.o: $(hdrdir)/ruby/st.h
+bug-14834.o: $(hdrdir)/ruby/subst.h
+bug-14834.o: bug-14834.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/bug-14834/extconf.rb b/ext/-test-/bug-14834/extconf.rb
new file mode 100644
index 0000000000..e8f3f1f437
--- /dev/null
+++ b/ext/-test-/bug-14834/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: true
+create_makefile("-test-/bug_14834")
diff --git a/ext/-test-/bug-3571/bug.c b/ext/-test-/bug-3571/bug.c
new file mode 100644
index 0000000000..dd3c85cd79
--- /dev/null
+++ b/ext/-test-/bug-3571/bug.c
@@ -0,0 +1,23 @@
+#include <ruby.h>
+
+static VALUE
+bug_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
+{
+ rb_notimplement();
+ return ID2SYM(rb_frame_this_func());
+}
+
+static VALUE
+bug_start(VALUE self)
+{
+ VALUE ary = rb_ary_new3(1, Qnil);
+ rb_block_call(ary, rb_intern("map"), 0, 0, bug_i, self);
+ return ary;
+}
+
+void
+Init_bug_3571(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ rb_define_module_function(mBug, "start", bug_start, 0);
+}
diff --git a/ext/-test-/bug-3571/depend b/ext/-test-/bug-3571/depend
new file mode 100644
index 0000000000..69c970b6f2
--- /dev/null
+++ b/ext/-test-/bug-3571/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+bug.o: $(RUBY_EXTCONF_H)
+bug.o: $(arch_hdrdir)/ruby/config.h
+bug.o: $(hdrdir)/ruby.h
+bug.o: $(hdrdir)/ruby/assert.h
+bug.o: $(hdrdir)/ruby/backward.h
+bug.o: $(hdrdir)/ruby/backward/2/assume.h
+bug.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug.o: $(hdrdir)/ruby/backward/2/bool.h
+bug.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug.o: $(hdrdir)/ruby/backward/2/limits.h
+bug.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bug.o: $(hdrdir)/ruby/defines.h
+bug.o: $(hdrdir)/ruby/intern.h
+bug.o: $(hdrdir)/ruby/internal/abi.h
+bug.o: $(hdrdir)/ruby/internal/anyargs.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bug.o: $(hdrdir)/ruby/internal/assume.h
+bug.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bug.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bug.o: $(hdrdir)/ruby/internal/attr/cold.h
+bug.o: $(hdrdir)/ruby/internal/attr/const.h
+bug.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bug.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bug.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bug.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bug.o: $(hdrdir)/ruby/internal/attr/error.h
+bug.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bug.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bug.o: $(hdrdir)/ruby/internal/attr/format.h
+bug.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bug.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bug.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bug.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bug.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bug.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bug.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bug.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+bug.o: $(hdrdir)/ruby/internal/attr/pure.h
+bug.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bug.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bug.o: $(hdrdir)/ruby/internal/attr/warning.h
+bug.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bug.o: $(hdrdir)/ruby/internal/cast.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bug.o: $(hdrdir)/ruby/internal/compiler_since.h
+bug.o: $(hdrdir)/ruby/internal/config.h
+bug.o: $(hdrdir)/ruby/internal/constant_p.h
+bug.o: $(hdrdir)/ruby/internal/core.h
+bug.o: $(hdrdir)/ruby/internal/core/rarray.h
+bug.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bug.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bug.o: $(hdrdir)/ruby/internal/core/rclass.h
+bug.o: $(hdrdir)/ruby/internal/core/rdata.h
+bug.o: $(hdrdir)/ruby/internal/core/rfile.h
+bug.o: $(hdrdir)/ruby/internal/core/rhash.h
+bug.o: $(hdrdir)/ruby/internal/core/robject.h
+bug.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bug.o: $(hdrdir)/ruby/internal/core/rstring.h
+bug.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bug.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bug.o: $(hdrdir)/ruby/internal/ctype.h
+bug.o: $(hdrdir)/ruby/internal/dllexport.h
+bug.o: $(hdrdir)/ruby/internal/dosish.h
+bug.o: $(hdrdir)/ruby/internal/error.h
+bug.o: $(hdrdir)/ruby/internal/eval.h
+bug.o: $(hdrdir)/ruby/internal/event.h
+bug.o: $(hdrdir)/ruby/internal/fl_type.h
+bug.o: $(hdrdir)/ruby/internal/gc.h
+bug.o: $(hdrdir)/ruby/internal/glob.h
+bug.o: $(hdrdir)/ruby/internal/globals.h
+bug.o: $(hdrdir)/ruby/internal/has/attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/builtin.h
+bug.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/extension.h
+bug.o: $(hdrdir)/ruby/internal/has/feature.h
+bug.o: $(hdrdir)/ruby/internal/has/warning.h
+bug.o: $(hdrdir)/ruby/internal/intern/array.h
+bug.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bug.o: $(hdrdir)/ruby/internal/intern/class.h
+bug.o: $(hdrdir)/ruby/internal/intern/compar.h
+bug.o: $(hdrdir)/ruby/internal/intern/complex.h
+bug.o: $(hdrdir)/ruby/internal/intern/cont.h
+bug.o: $(hdrdir)/ruby/internal/intern/dir.h
+bug.o: $(hdrdir)/ruby/internal/intern/enum.h
+bug.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bug.o: $(hdrdir)/ruby/internal/intern/error.h
+bug.o: $(hdrdir)/ruby/internal/intern/eval.h
+bug.o: $(hdrdir)/ruby/internal/intern/file.h
+bug.o: $(hdrdir)/ruby/internal/intern/hash.h
+bug.o: $(hdrdir)/ruby/internal/intern/io.h
+bug.o: $(hdrdir)/ruby/internal/intern/load.h
+bug.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bug.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bug.o: $(hdrdir)/ruby/internal/intern/object.h
+bug.o: $(hdrdir)/ruby/internal/intern/parse.h
+bug.o: $(hdrdir)/ruby/internal/intern/proc.h
+bug.o: $(hdrdir)/ruby/internal/intern/process.h
+bug.o: $(hdrdir)/ruby/internal/intern/random.h
+bug.o: $(hdrdir)/ruby/internal/intern/range.h
+bug.o: $(hdrdir)/ruby/internal/intern/rational.h
+bug.o: $(hdrdir)/ruby/internal/intern/re.h
+bug.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bug.o: $(hdrdir)/ruby/internal/intern/select.h
+bug.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug.o: $(hdrdir)/ruby/internal/intern/set.h
+bug.o: $(hdrdir)/ruby/internal/intern/signal.h
+bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bug.o: $(hdrdir)/ruby/internal/intern/string.h
+bug.o: $(hdrdir)/ruby/internal/intern/struct.h
+bug.o: $(hdrdir)/ruby/internal/intern/thread.h
+bug.o: $(hdrdir)/ruby/internal/intern/time.h
+bug.o: $(hdrdir)/ruby/internal/intern/variable.h
+bug.o: $(hdrdir)/ruby/internal/intern/vm.h
+bug.o: $(hdrdir)/ruby/internal/interpreter.h
+bug.o: $(hdrdir)/ruby/internal/iterator.h
+bug.o: $(hdrdir)/ruby/internal/memory.h
+bug.o: $(hdrdir)/ruby/internal/method.h
+bug.o: $(hdrdir)/ruby/internal/module.h
+bug.o: $(hdrdir)/ruby/internal/newobj.h
+bug.o: $(hdrdir)/ruby/internal/scan_args.h
+bug.o: $(hdrdir)/ruby/internal/special_consts.h
+bug.o: $(hdrdir)/ruby/internal/static_assert.h
+bug.o: $(hdrdir)/ruby/internal/stdalign.h
+bug.o: $(hdrdir)/ruby/internal/stdbool.h
+bug.o: $(hdrdir)/ruby/internal/stdckdint.h
+bug.o: $(hdrdir)/ruby/internal/symbol.h
+bug.o: $(hdrdir)/ruby/internal/value.h
+bug.o: $(hdrdir)/ruby/internal/value_type.h
+bug.o: $(hdrdir)/ruby/internal/variable.h
+bug.o: $(hdrdir)/ruby/internal/warning_push.h
+bug.o: $(hdrdir)/ruby/internal/xmalloc.h
+bug.o: $(hdrdir)/ruby/missing.h
+bug.o: $(hdrdir)/ruby/ruby.h
+bug.o: $(hdrdir)/ruby/st.h
+bug.o: $(hdrdir)/ruby/subst.h
+bug.o: bug.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/bug-3571/extconf.rb b/ext/-test-/bug-3571/extconf.rb
new file mode 100644
index 0000000000..7e76ebded6
--- /dev/null
+++ b/ext/-test-/bug-3571/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/bug_3571")
diff --git a/ext/-test-/bug-5832/bug.c b/ext/-test-/bug-5832/bug.c
new file mode 100644
index 0000000000..a2c3965640
--- /dev/null
+++ b/ext/-test-/bug-5832/bug.c
@@ -0,0 +1,14 @@
+#include <ruby.h>
+
+static VALUE
+bug_funcall_callback(VALUE self, VALUE obj)
+{
+ return rb_funcall(obj, rb_intern("callback"), 0);
+}
+
+void
+Init_bug_5832(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ rb_define_module_function(mBug, "funcall_callback", bug_funcall_callback, 1);
+}
diff --git a/ext/-test-/bug-5832/depend b/ext/-test-/bug-5832/depend
new file mode 100644
index 0000000000..69c970b6f2
--- /dev/null
+++ b/ext/-test-/bug-5832/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+bug.o: $(RUBY_EXTCONF_H)
+bug.o: $(arch_hdrdir)/ruby/config.h
+bug.o: $(hdrdir)/ruby.h
+bug.o: $(hdrdir)/ruby/assert.h
+bug.o: $(hdrdir)/ruby/backward.h
+bug.o: $(hdrdir)/ruby/backward/2/assume.h
+bug.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug.o: $(hdrdir)/ruby/backward/2/bool.h
+bug.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug.o: $(hdrdir)/ruby/backward/2/limits.h
+bug.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bug.o: $(hdrdir)/ruby/defines.h
+bug.o: $(hdrdir)/ruby/intern.h
+bug.o: $(hdrdir)/ruby/internal/abi.h
+bug.o: $(hdrdir)/ruby/internal/anyargs.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bug.o: $(hdrdir)/ruby/internal/assume.h
+bug.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bug.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bug.o: $(hdrdir)/ruby/internal/attr/cold.h
+bug.o: $(hdrdir)/ruby/internal/attr/const.h
+bug.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bug.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bug.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bug.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bug.o: $(hdrdir)/ruby/internal/attr/error.h
+bug.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bug.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bug.o: $(hdrdir)/ruby/internal/attr/format.h
+bug.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bug.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bug.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bug.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bug.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bug.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bug.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bug.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+bug.o: $(hdrdir)/ruby/internal/attr/pure.h
+bug.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bug.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bug.o: $(hdrdir)/ruby/internal/attr/warning.h
+bug.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bug.o: $(hdrdir)/ruby/internal/cast.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bug.o: $(hdrdir)/ruby/internal/compiler_since.h
+bug.o: $(hdrdir)/ruby/internal/config.h
+bug.o: $(hdrdir)/ruby/internal/constant_p.h
+bug.o: $(hdrdir)/ruby/internal/core.h
+bug.o: $(hdrdir)/ruby/internal/core/rarray.h
+bug.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bug.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bug.o: $(hdrdir)/ruby/internal/core/rclass.h
+bug.o: $(hdrdir)/ruby/internal/core/rdata.h
+bug.o: $(hdrdir)/ruby/internal/core/rfile.h
+bug.o: $(hdrdir)/ruby/internal/core/rhash.h
+bug.o: $(hdrdir)/ruby/internal/core/robject.h
+bug.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bug.o: $(hdrdir)/ruby/internal/core/rstring.h
+bug.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bug.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bug.o: $(hdrdir)/ruby/internal/ctype.h
+bug.o: $(hdrdir)/ruby/internal/dllexport.h
+bug.o: $(hdrdir)/ruby/internal/dosish.h
+bug.o: $(hdrdir)/ruby/internal/error.h
+bug.o: $(hdrdir)/ruby/internal/eval.h
+bug.o: $(hdrdir)/ruby/internal/event.h
+bug.o: $(hdrdir)/ruby/internal/fl_type.h
+bug.o: $(hdrdir)/ruby/internal/gc.h
+bug.o: $(hdrdir)/ruby/internal/glob.h
+bug.o: $(hdrdir)/ruby/internal/globals.h
+bug.o: $(hdrdir)/ruby/internal/has/attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/builtin.h
+bug.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/extension.h
+bug.o: $(hdrdir)/ruby/internal/has/feature.h
+bug.o: $(hdrdir)/ruby/internal/has/warning.h
+bug.o: $(hdrdir)/ruby/internal/intern/array.h
+bug.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bug.o: $(hdrdir)/ruby/internal/intern/class.h
+bug.o: $(hdrdir)/ruby/internal/intern/compar.h
+bug.o: $(hdrdir)/ruby/internal/intern/complex.h
+bug.o: $(hdrdir)/ruby/internal/intern/cont.h
+bug.o: $(hdrdir)/ruby/internal/intern/dir.h
+bug.o: $(hdrdir)/ruby/internal/intern/enum.h
+bug.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bug.o: $(hdrdir)/ruby/internal/intern/error.h
+bug.o: $(hdrdir)/ruby/internal/intern/eval.h
+bug.o: $(hdrdir)/ruby/internal/intern/file.h
+bug.o: $(hdrdir)/ruby/internal/intern/hash.h
+bug.o: $(hdrdir)/ruby/internal/intern/io.h
+bug.o: $(hdrdir)/ruby/internal/intern/load.h
+bug.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bug.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bug.o: $(hdrdir)/ruby/internal/intern/object.h
+bug.o: $(hdrdir)/ruby/internal/intern/parse.h
+bug.o: $(hdrdir)/ruby/internal/intern/proc.h
+bug.o: $(hdrdir)/ruby/internal/intern/process.h
+bug.o: $(hdrdir)/ruby/internal/intern/random.h
+bug.o: $(hdrdir)/ruby/internal/intern/range.h
+bug.o: $(hdrdir)/ruby/internal/intern/rational.h
+bug.o: $(hdrdir)/ruby/internal/intern/re.h
+bug.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bug.o: $(hdrdir)/ruby/internal/intern/select.h
+bug.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug.o: $(hdrdir)/ruby/internal/intern/set.h
+bug.o: $(hdrdir)/ruby/internal/intern/signal.h
+bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bug.o: $(hdrdir)/ruby/internal/intern/string.h
+bug.o: $(hdrdir)/ruby/internal/intern/struct.h
+bug.o: $(hdrdir)/ruby/internal/intern/thread.h
+bug.o: $(hdrdir)/ruby/internal/intern/time.h
+bug.o: $(hdrdir)/ruby/internal/intern/variable.h
+bug.o: $(hdrdir)/ruby/internal/intern/vm.h
+bug.o: $(hdrdir)/ruby/internal/interpreter.h
+bug.o: $(hdrdir)/ruby/internal/iterator.h
+bug.o: $(hdrdir)/ruby/internal/memory.h
+bug.o: $(hdrdir)/ruby/internal/method.h
+bug.o: $(hdrdir)/ruby/internal/module.h
+bug.o: $(hdrdir)/ruby/internal/newobj.h
+bug.o: $(hdrdir)/ruby/internal/scan_args.h
+bug.o: $(hdrdir)/ruby/internal/special_consts.h
+bug.o: $(hdrdir)/ruby/internal/static_assert.h
+bug.o: $(hdrdir)/ruby/internal/stdalign.h
+bug.o: $(hdrdir)/ruby/internal/stdbool.h
+bug.o: $(hdrdir)/ruby/internal/stdckdint.h
+bug.o: $(hdrdir)/ruby/internal/symbol.h
+bug.o: $(hdrdir)/ruby/internal/value.h
+bug.o: $(hdrdir)/ruby/internal/value_type.h
+bug.o: $(hdrdir)/ruby/internal/variable.h
+bug.o: $(hdrdir)/ruby/internal/warning_push.h
+bug.o: $(hdrdir)/ruby/internal/xmalloc.h
+bug.o: $(hdrdir)/ruby/missing.h
+bug.o: $(hdrdir)/ruby/ruby.h
+bug.o: $(hdrdir)/ruby/st.h
+bug.o: $(hdrdir)/ruby/subst.h
+bug.o: bug.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/bug-5832/extconf.rb b/ext/-test-/bug-5832/extconf.rb
new file mode 100644
index 0000000000..b8452b4f8f
--- /dev/null
+++ b/ext/-test-/bug-5832/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/bug_5832")
diff --git a/ext/-test-/bug_reporter/bug_reporter.c b/ext/-test-/bug_reporter/bug_reporter.c
new file mode 100644
index 0000000000..e9ea9e3db0
--- /dev/null
+++ b/ext/-test-/bug_reporter/bug_reporter.c
@@ -0,0 +1,24 @@
+#include <ruby.h>
+#include <stdio.h>
+
+int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);
+
+static void
+sample_bug_reporter(FILE *out, void *ptr)
+{
+ int n = (int)(uintptr_t)ptr;
+ fprintf(out, "Sample bug reporter: %d\n", n);
+}
+
+static VALUE
+register_sample_bug_reporter(VALUE self, VALUE obj)
+{
+ rb_bug_reporter_add(sample_bug_reporter, (void *)(uintptr_t)NUM2INT(obj));
+ return Qnil;
+}
+
+void
+Init_bug_reporter(void)
+{
+ rb_define_global_function("register_sample_bug_reporter", register_sample_bug_reporter, 1);
+}
diff --git a/ext/-test-/bug_reporter/depend b/ext/-test-/bug_reporter/depend
new file mode 100644
index 0000000000..e9993c3295
--- /dev/null
+++ b/ext/-test-/bug_reporter/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+bug_reporter.o: $(RUBY_EXTCONF_H)
+bug_reporter.o: $(arch_hdrdir)/ruby/config.h
+bug_reporter.o: $(hdrdir)/ruby.h
+bug_reporter.o: $(hdrdir)/ruby/assert.h
+bug_reporter.o: $(hdrdir)/ruby/backward.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/assume.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/bool.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/limits.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bug_reporter.o: $(hdrdir)/ruby/defines.h
+bug_reporter.o: $(hdrdir)/ruby/intern.h
+bug_reporter.o: $(hdrdir)/ruby/internal/abi.h
+bug_reporter.o: $(hdrdir)/ruby/internal/anyargs.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/assume.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/cold.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/const.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/error.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/format.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/pure.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/warning.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bug_reporter.o: $(hdrdir)/ruby/internal/cast.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_since.h
+bug_reporter.o: $(hdrdir)/ruby/internal/config.h
+bug_reporter.o: $(hdrdir)/ruby/internal/constant_p.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rarray.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rclass.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rdata.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rfile.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rhash.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/robject.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rstring.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bug_reporter.o: $(hdrdir)/ruby/internal/ctype.h
+bug_reporter.o: $(hdrdir)/ruby/internal/dllexport.h
+bug_reporter.o: $(hdrdir)/ruby/internal/dosish.h
+bug_reporter.o: $(hdrdir)/ruby/internal/error.h
+bug_reporter.o: $(hdrdir)/ruby/internal/eval.h
+bug_reporter.o: $(hdrdir)/ruby/internal/event.h
+bug_reporter.o: $(hdrdir)/ruby/internal/fl_type.h
+bug_reporter.o: $(hdrdir)/ruby/internal/gc.h
+bug_reporter.o: $(hdrdir)/ruby/internal/glob.h
+bug_reporter.o: $(hdrdir)/ruby/internal/globals.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/attribute.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/builtin.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/extension.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/feature.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/warning.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/array.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/class.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/compar.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/complex.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/cont.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/dir.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/enum.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/error.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/eval.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/file.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/hash.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/io.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/load.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/object.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/parse.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/proc.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/process.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/random.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/range.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/rational.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/re.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/select.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/set.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/signal.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/string.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/struct.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/thread.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/time.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/variable.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/vm.h
+bug_reporter.o: $(hdrdir)/ruby/internal/interpreter.h
+bug_reporter.o: $(hdrdir)/ruby/internal/iterator.h
+bug_reporter.o: $(hdrdir)/ruby/internal/memory.h
+bug_reporter.o: $(hdrdir)/ruby/internal/method.h
+bug_reporter.o: $(hdrdir)/ruby/internal/module.h
+bug_reporter.o: $(hdrdir)/ruby/internal/newobj.h
+bug_reporter.o: $(hdrdir)/ruby/internal/scan_args.h
+bug_reporter.o: $(hdrdir)/ruby/internal/special_consts.h
+bug_reporter.o: $(hdrdir)/ruby/internal/static_assert.h
+bug_reporter.o: $(hdrdir)/ruby/internal/stdalign.h
+bug_reporter.o: $(hdrdir)/ruby/internal/stdbool.h
+bug_reporter.o: $(hdrdir)/ruby/internal/stdckdint.h
+bug_reporter.o: $(hdrdir)/ruby/internal/symbol.h
+bug_reporter.o: $(hdrdir)/ruby/internal/value.h
+bug_reporter.o: $(hdrdir)/ruby/internal/value_type.h
+bug_reporter.o: $(hdrdir)/ruby/internal/variable.h
+bug_reporter.o: $(hdrdir)/ruby/internal/warning_push.h
+bug_reporter.o: $(hdrdir)/ruby/internal/xmalloc.h
+bug_reporter.o: $(hdrdir)/ruby/missing.h
+bug_reporter.o: $(hdrdir)/ruby/ruby.h
+bug_reporter.o: $(hdrdir)/ruby/st.h
+bug_reporter.o: $(hdrdir)/ruby/subst.h
+bug_reporter.o: bug_reporter.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/bug_reporter/extconf.rb b/ext/-test-/bug_reporter/extconf.rb
new file mode 100644
index 0000000000..d9d49bb23e
--- /dev/null
+++ b/ext/-test-/bug_reporter/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/bug_reporter")
diff --git a/ext/-test-/class/class2name.c b/ext/-test-/class/class2name.c
new file mode 100644
index 0000000000..c48df6fb2a
--- /dev/null
+++ b/ext/-test-/class/class2name.c
@@ -0,0 +1,14 @@
+#include <ruby/ruby.h>
+
+static VALUE
+class2name(VALUE self, VALUE klass)
+{
+ const char *name = rb_class2name(klass);
+ return name ? rb_str_new_cstr(name) : Qnil;
+}
+
+void
+Init_class2name(VALUE klass)
+{
+ rb_define_singleton_method(klass, "class2name", class2name, 1);
+}
diff --git a/ext/-test-/class/depend b/ext/-test-/class/depend
new file mode 100644
index 0000000000..557206cefb
--- /dev/null
+++ b/ext/-test-/class/depend
@@ -0,0 +1,323 @@
+# AUTOGENERATED DEPENDENCIES START
+class2name.o: $(RUBY_EXTCONF_H)
+class2name.o: $(arch_hdrdir)/ruby/config.h
+class2name.o: $(hdrdir)/ruby/assert.h
+class2name.o: $(hdrdir)/ruby/backward.h
+class2name.o: $(hdrdir)/ruby/backward/2/assume.h
+class2name.o: $(hdrdir)/ruby/backward/2/attributes.h
+class2name.o: $(hdrdir)/ruby/backward/2/bool.h
+class2name.o: $(hdrdir)/ruby/backward/2/inttypes.h
+class2name.o: $(hdrdir)/ruby/backward/2/limits.h
+class2name.o: $(hdrdir)/ruby/backward/2/long_long.h
+class2name.o: $(hdrdir)/ruby/backward/2/stdalign.h
+class2name.o: $(hdrdir)/ruby/backward/2/stdarg.h
+class2name.o: $(hdrdir)/ruby/defines.h
+class2name.o: $(hdrdir)/ruby/intern.h
+class2name.o: $(hdrdir)/ruby/internal/abi.h
+class2name.o: $(hdrdir)/ruby/internal/anyargs.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+class2name.o: $(hdrdir)/ruby/internal/assume.h
+class2name.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+class2name.o: $(hdrdir)/ruby/internal/attr/artificial.h
+class2name.o: $(hdrdir)/ruby/internal/attr/cold.h
+class2name.o: $(hdrdir)/ruby/internal/attr/const.h
+class2name.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+class2name.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+class2name.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+class2name.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+class2name.o: $(hdrdir)/ruby/internal/attr/error.h
+class2name.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+class2name.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+class2name.o: $(hdrdir)/ruby/internal/attr/format.h
+class2name.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+class2name.o: $(hdrdir)/ruby/internal/attr/noalias.h
+class2name.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+class2name.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+class2name.o: $(hdrdir)/ruby/internal/attr/noinline.h
+class2name.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+class2name.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+class2name.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+class2name.o: $(hdrdir)/ruby/internal/attr/pure.h
+class2name.o: $(hdrdir)/ruby/internal/attr/restrict.h
+class2name.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+class2name.o: $(hdrdir)/ruby/internal/attr/warning.h
+class2name.o: $(hdrdir)/ruby/internal/attr/weakref.h
+class2name.o: $(hdrdir)/ruby/internal/cast.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_since.h
+class2name.o: $(hdrdir)/ruby/internal/config.h
+class2name.o: $(hdrdir)/ruby/internal/constant_p.h
+class2name.o: $(hdrdir)/ruby/internal/core.h
+class2name.o: $(hdrdir)/ruby/internal/core/rarray.h
+class2name.o: $(hdrdir)/ruby/internal/core/rbasic.h
+class2name.o: $(hdrdir)/ruby/internal/core/rbignum.h
+class2name.o: $(hdrdir)/ruby/internal/core/rclass.h
+class2name.o: $(hdrdir)/ruby/internal/core/rdata.h
+class2name.o: $(hdrdir)/ruby/internal/core/rfile.h
+class2name.o: $(hdrdir)/ruby/internal/core/rhash.h
+class2name.o: $(hdrdir)/ruby/internal/core/robject.h
+class2name.o: $(hdrdir)/ruby/internal/core/rregexp.h
+class2name.o: $(hdrdir)/ruby/internal/core/rstring.h
+class2name.o: $(hdrdir)/ruby/internal/core/rstruct.h
+class2name.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+class2name.o: $(hdrdir)/ruby/internal/ctype.h
+class2name.o: $(hdrdir)/ruby/internal/dllexport.h
+class2name.o: $(hdrdir)/ruby/internal/dosish.h
+class2name.o: $(hdrdir)/ruby/internal/error.h
+class2name.o: $(hdrdir)/ruby/internal/eval.h
+class2name.o: $(hdrdir)/ruby/internal/event.h
+class2name.o: $(hdrdir)/ruby/internal/fl_type.h
+class2name.o: $(hdrdir)/ruby/internal/gc.h
+class2name.o: $(hdrdir)/ruby/internal/glob.h
+class2name.o: $(hdrdir)/ruby/internal/globals.h
+class2name.o: $(hdrdir)/ruby/internal/has/attribute.h
+class2name.o: $(hdrdir)/ruby/internal/has/builtin.h
+class2name.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+class2name.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+class2name.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+class2name.o: $(hdrdir)/ruby/internal/has/extension.h
+class2name.o: $(hdrdir)/ruby/internal/has/feature.h
+class2name.o: $(hdrdir)/ruby/internal/has/warning.h
+class2name.o: $(hdrdir)/ruby/internal/intern/array.h
+class2name.o: $(hdrdir)/ruby/internal/intern/bignum.h
+class2name.o: $(hdrdir)/ruby/internal/intern/class.h
+class2name.o: $(hdrdir)/ruby/internal/intern/compar.h
+class2name.o: $(hdrdir)/ruby/internal/intern/complex.h
+class2name.o: $(hdrdir)/ruby/internal/intern/cont.h
+class2name.o: $(hdrdir)/ruby/internal/intern/dir.h
+class2name.o: $(hdrdir)/ruby/internal/intern/enum.h
+class2name.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+class2name.o: $(hdrdir)/ruby/internal/intern/error.h
+class2name.o: $(hdrdir)/ruby/internal/intern/eval.h
+class2name.o: $(hdrdir)/ruby/internal/intern/file.h
+class2name.o: $(hdrdir)/ruby/internal/intern/hash.h
+class2name.o: $(hdrdir)/ruby/internal/intern/io.h
+class2name.o: $(hdrdir)/ruby/internal/intern/load.h
+class2name.o: $(hdrdir)/ruby/internal/intern/marshal.h
+class2name.o: $(hdrdir)/ruby/internal/intern/numeric.h
+class2name.o: $(hdrdir)/ruby/internal/intern/object.h
+class2name.o: $(hdrdir)/ruby/internal/intern/parse.h
+class2name.o: $(hdrdir)/ruby/internal/intern/proc.h
+class2name.o: $(hdrdir)/ruby/internal/intern/process.h
+class2name.o: $(hdrdir)/ruby/internal/intern/random.h
+class2name.o: $(hdrdir)/ruby/internal/intern/range.h
+class2name.o: $(hdrdir)/ruby/internal/intern/rational.h
+class2name.o: $(hdrdir)/ruby/internal/intern/re.h
+class2name.o: $(hdrdir)/ruby/internal/intern/ruby.h
+class2name.o: $(hdrdir)/ruby/internal/intern/select.h
+class2name.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+class2name.o: $(hdrdir)/ruby/internal/intern/set.h
+class2name.o: $(hdrdir)/ruby/internal/intern/signal.h
+class2name.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+class2name.o: $(hdrdir)/ruby/internal/intern/string.h
+class2name.o: $(hdrdir)/ruby/internal/intern/struct.h
+class2name.o: $(hdrdir)/ruby/internal/intern/thread.h
+class2name.o: $(hdrdir)/ruby/internal/intern/time.h
+class2name.o: $(hdrdir)/ruby/internal/intern/variable.h
+class2name.o: $(hdrdir)/ruby/internal/intern/vm.h
+class2name.o: $(hdrdir)/ruby/internal/interpreter.h
+class2name.o: $(hdrdir)/ruby/internal/iterator.h
+class2name.o: $(hdrdir)/ruby/internal/memory.h
+class2name.o: $(hdrdir)/ruby/internal/method.h
+class2name.o: $(hdrdir)/ruby/internal/module.h
+class2name.o: $(hdrdir)/ruby/internal/newobj.h
+class2name.o: $(hdrdir)/ruby/internal/scan_args.h
+class2name.o: $(hdrdir)/ruby/internal/special_consts.h
+class2name.o: $(hdrdir)/ruby/internal/static_assert.h
+class2name.o: $(hdrdir)/ruby/internal/stdalign.h
+class2name.o: $(hdrdir)/ruby/internal/stdbool.h
+class2name.o: $(hdrdir)/ruby/internal/stdckdint.h
+class2name.o: $(hdrdir)/ruby/internal/symbol.h
+class2name.o: $(hdrdir)/ruby/internal/value.h
+class2name.o: $(hdrdir)/ruby/internal/value_type.h
+class2name.o: $(hdrdir)/ruby/internal/variable.h
+class2name.o: $(hdrdir)/ruby/internal/warning_push.h
+class2name.o: $(hdrdir)/ruby/internal/xmalloc.h
+class2name.o: $(hdrdir)/ruby/missing.h
+class2name.o: $(hdrdir)/ruby/ruby.h
+class2name.o: $(hdrdir)/ruby/st.h
+class2name.o: $(hdrdir)/ruby/subst.h
+class2name.o: class2name.c
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/class/extconf.rb b/ext/-test-/class/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/class/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/class/init.c b/ext/-test-/class/init.c
new file mode 100644
index 0000000000..108ff7525c
--- /dev/null
+++ b/ext/-test-/class/init.c
@@ -0,0 +1,12 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE mod); Init_##n(mod);}
+
+void
+Init_class(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE mod = rb_define_module_under(mBug, "Class");
+ rb_define_class_under(mod, "TestClassDefinedInC", rb_cObject);
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/cxxanyargs/cxxanyargs.cpp b/ext/-test-/cxxanyargs/cxxanyargs.cpp
new file mode 100644
index 0000000000..c7df7f9038
--- /dev/null
+++ b/ext/-test-/cxxanyargs/cxxanyargs.cpp
@@ -0,0 +1,935 @@
+#include <ruby/ruby.h>
+
+#if 0 // Warnings expected, should just suppress them
+
+#elif defined(_MSC_VER)
+#pragma warning(disable : 4996)
+
+#elif defined(__INTEL_COMPILER)
+#pragma warning(disable : 1786)
+
+#elif defined(__clang__)
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#elif defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+#elif defined(__SUNPRO_CC)
+#pragma error_messages (off,symdeprecated)
+
+#else
+// :FIXME: improve here for your compiler.
+
+#endif
+
+namespace test_rb_define_virtual_variable {
+ VALUE
+ getter(ID, VALUE *data)
+ {
+ return *data;
+ }
+
+ void
+ setter(VALUE val, ID, VALUE *data)
+ {
+ *data = val;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ rb_define_virtual_variable("test",
+ RUBY_METHOD_FUNC(getter),
+ reinterpret_cast<void(*)(ANYARGS)>(setter)); // old
+ rb_define_virtual_variable("test", getter, setter); // new
+
+#ifdef HAVE_NULLPTR
+ rb_define_virtual_variable("test", nullptr, reinterpret_cast<void(*)(ANYARGS)>(setter));
+ rb_define_virtual_variable("test", nullptr, setter);
+
+ rb_define_virtual_variable("test", RUBY_METHOD_FUNC(getter), nullptr);
+ rb_define_virtual_variable("test", getter, nullptr);
+
+ // It doesn't make any sense for both function pointers be nullptr at
+ // the same time.
+#endif
+
+ return self;
+ }
+}
+
+struct test_rb_define_hooked_variable {
+ static VALUE v;
+
+ static VALUE
+ getter(ID, VALUE *data)
+ {
+ return *data;
+ }
+
+ static void
+ setter(VALUE val, ID, VALUE *data)
+ {
+ *data = val;
+ }
+
+ static VALUE
+ test(VALUE self)
+ {
+ rb_define_hooked_variable("test", &v,
+ RUBY_METHOD_FUNC(getter),
+ reinterpret_cast<void(*)(ANYARGS)>(setter)); // old
+ rb_define_hooked_variable("test", &v, getter, setter); // new
+
+#ifdef HAVE_NULLPTR
+ rb_define_hooked_variable("test", &v, nullptr, reinterpret_cast<void(*)(ANYARGS)>(setter));
+ rb_define_hooked_variable("test", &v, nullptr, setter);
+
+ rb_define_hooked_variable("test", &v, RUBY_METHOD_FUNC(getter), nullptr);
+ rb_define_hooked_variable("test", &v, getter, nullptr);
+
+ // It doesn't make any sense for both function pointers be nullptr at
+ // the same time.
+#endif
+
+ return self;
+ }
+};
+VALUE test_rb_define_hooked_variable::v = Qundef;
+
+namespace test_rb_block_call {
+ VALUE
+ block(RB_BLOCK_CALL_FUNC_ARGLIST(arg, param))
+ {
+ return rb_funcall(arg, rb_intern("=="), 1, param);
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ const ID mid = rb_intern("each");
+ const VALUE argv[] = { Qundef };
+
+#ifdef HAVE_NULLPTR
+ rb_block_call(self, mid, 0, argv, nullptr, self);
+#endif
+
+ rb_block_call(self, mid, 0, argv, RUBY_METHOD_FUNC(block), self); // old
+ return rb_block_call(self, mid, 0, argv, block, self); // new
+ }
+}
+
+namespace test_rb_rescue {
+ VALUE
+ begin(VALUE arg)
+ {
+ return arg;
+ }
+
+ VALUE
+ rescue(VALUE arg, VALUE exc)
+ {
+ return exc;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+#ifdef HAVE_NULLPTR
+ rb_rescue(RUBY_METHOD_FUNC(begin), self, nullptr, self);
+ rb_rescue(begin, self, nullptr, self);
+#endif
+
+ rb_rescue(RUBY_METHOD_FUNC(begin), self, RUBY_METHOD_FUNC(rescue), self); // old
+ return rb_rescue(begin, self, rescue, self); // new
+ }
+}
+
+namespace test_rb_rescue2 {
+ VALUE
+ begin(VALUE arg)
+ {
+ return arg;
+ }
+
+ VALUE
+ rescue(VALUE arg, VALUE exc)
+ {
+ return exc;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+#ifdef HAVE_NULLPTR
+ rb_rescue2(RUBY_METHOD_FUNC(begin), self, nullptr, self, rb_eStandardError, rb_eFatal, (VALUE)0);
+ rb_rescue2(begin, self, nullptr, self, rb_eStandardError, rb_eFatal, (VALUE)0);
+#endif
+
+ rb_rescue2(RUBY_METHOD_FUNC(begin), self, RUBY_METHOD_FUNC(rescue), self,
+ rb_eStandardError, rb_eFatal, (VALUE)0); // old
+ return rb_rescue2(begin, self, rescue, self, rb_eStandardError, rb_eFatal, (VALUE)0); // new
+ }
+}
+
+namespace test_rb_ensure {
+ VALUE
+ begin(VALUE arg)
+ {
+ return arg;
+ }
+
+ VALUE
+ ensure(VALUE arg)
+ {
+ return arg;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+#ifdef HAVE_NULLPTR
+ rb_ensure(RUBY_METHOD_FUNC(begin), self, nullptr, self);
+ rb_ensure(begin, self, nullptr, self);
+#endif
+
+ rb_ensure(RUBY_METHOD_FUNC(begin), self, RUBY_METHOD_FUNC(ensure), self); // old
+ return rb_ensure(begin, self, ensure, self); // new
+ }
+}
+
+namespace test_rb_catch {
+ VALUE
+ catcher(RB_BLOCK_CALL_FUNC_ARGLIST(arg, param))
+ {
+ return arg;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ static const char *zero = 0;
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a catcher.
+#endif
+
+ rb_catch(zero, RUBY_METHOD_FUNC(catcher), self); // old
+ return rb_catch(zero, catcher, self); // new
+ }
+}
+
+namespace test_rb_catch_obj {
+ VALUE
+ catcher(RB_BLOCK_CALL_FUNC_ARGLIST(arg, param))
+ {
+ return arg;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a catcher.
+#endif
+
+ rb_catch_obj(self, RUBY_METHOD_FUNC(catcher), self); // old
+ return rb_catch_obj(self, catcher, self); // new
+ }
+}
+
+namespace test_rb_fiber_new {
+ VALUE
+ fiber(RB_BLOCK_CALL_FUNC_ARGLIST(arg, param))
+ {
+ return arg;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a fiber.
+#endif
+
+ rb_fiber_new(RUBY_METHOD_FUNC(fiber), self); // old
+ return rb_fiber_new(fiber, self); // new
+ }
+}
+
+namespace test_rb_proc_new {
+ VALUE
+ proc(RB_BLOCK_CALL_FUNC_ARGLIST(arg, param))
+ {
+ return arg;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a proc.
+#endif
+
+ rb_fiber_new(RUBY_METHOD_FUNC(proc), self); // old
+ return rb_fiber_new(proc, self); // new
+ }
+}
+
+struct test_rb_thread_create {
+ static VALUE v;
+
+ static VALUE
+ thread(void *ptr)
+ {
+ const VALUE *w = reinterpret_cast<const VALUE*>(ptr);
+ return *w;
+ }
+
+ static VALUE
+ test(VALUE self)
+ {
+ v = self;
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a thread.
+#endif
+
+ rb_thread_create(RUBY_METHOD_FUNC(thread), &v); // old
+ return rb_thread_create(thread, &v); // new
+ }
+};
+VALUE test_rb_thread_create::v = Qundef;
+
+namespace test_st_foreach {
+ static int
+ iter(st_data_t, st_data_t, st_data_t)
+ {
+ return ST_CONTINUE;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ st_data_t data = 0;
+ st_table *st = st_init_numtable();
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as an iterator.
+#endif
+
+ st_foreach(st, reinterpret_cast<int(*)(ANYARGS)>(iter), data); // old
+ st_foreach(st, iter, data); // new
+ return self;
+ }
+}
+
+namespace test_st_foreach_check {
+ static int
+ iter(st_data_t, st_data_t, st_data_t, int x)
+ {
+ return x ? ST_STOP : ST_CONTINUE;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ st_data_t data = 0;
+ st_table *st = st_init_numtable();
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as an iterator.
+#endif
+
+ st_foreach_check(st, reinterpret_cast<int(*)(ANYARGS)>(iter), data, data); // old
+ st_foreach_check(st, iter, data, data); // new
+ return self;
+ }
+}
+
+namespace test_st_foreach_safe {
+ static int
+ iter(st_data_t, st_data_t, st_data_t)
+ {
+ return ST_CONTINUE;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ st_data_t data = 0;
+ st_table *st = st_init_numtable();
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as an iterator.
+#endif
+
+ st_foreach_safe(st, reinterpret_cast<int(*)(ANYARGS)>(iter), data); // old
+ st_foreach_safe(st, iter, data); // new
+ return self;
+ }
+}
+
+namespace test_rb_hash_foreach {
+ static int
+ iter(VALUE, VALUE, VALUE)
+ {
+ return ST_CONTINUE;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ VALUE h = rb_hash_new();
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as an iterator.
+#endif
+
+ rb_hash_foreach(h, reinterpret_cast<int(*)(ANYARGS)>(iter), self); // old
+ rb_hash_foreach(h, iter, self); // new
+ return self;
+ }
+}
+
+namespace test_rb_ivar_foreach {
+ static int
+ iter(VALUE, VALUE, VALUE)
+ {
+ return ST_CONTINUE;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as an iterator.
+#endif
+
+ rb_ivar_foreach(self, reinterpret_cast<int(*)(ANYARGS)>(iter), self); // old
+ rb_ivar_foreach(self, iter, self); // new
+ return self;
+ }
+}
+
+namespace test_rb_define_method {
+ static VALUE
+ m1(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ m2(VALUE, VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ ma(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mv(int, VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ // No cast
+ rb_define_method(self, "m1", m1, 1);
+ rb_define_method(self, "m2", m2, 2);
+ rb_define_method(self, "ma", ma, -2);
+ rb_define_method(self, "mv", mv, -1);
+ rb_define_method(self, "mc", mc, -1);
+
+ // Cast by RUBY_METHOD_FUNC
+ rb_define_method(self, "m1", RUBY_METHOD_FUNC(m1), 1);
+ rb_define_method(self, "m2", RUBY_METHOD_FUNC(m2), 2);
+ rb_define_method(self, "ma", RUBY_METHOD_FUNC(ma), -2);
+ rb_define_method(self, "mv", RUBY_METHOD_FUNC(mv), -1);
+ rb_define_method(self, "mc", RUBY_METHOD_FUNC(mc), -1);
+
+ // Explicit cast instead of RUBY_METHOD_FUNC
+ rb_define_method(self, "m1", (VALUE (*)(...))(m1), 1);
+ rb_define_method(self, "m2", (VALUE (*)(...))(m2), 2);
+ rb_define_method(self, "ma", (VALUE (*)(...))(ma), -2);
+ rb_define_method(self, "mv", (VALUE (*)(...))(mv), -1);
+ rb_define_method(self, "mc", (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_method(self, "m1", rb_f_notimplement, 1);
+ rb_define_method(self, "m2", rb_f_notimplement, 2);
+ rb_define_method(self, "ma", rb_f_notimplement, -2);
+ rb_define_method(self, "mv", rb_f_notimplement, -1);
+ rb_define_method(self, "mc", rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
+
+ return self;
+ }
+}
+
+namespace test_rb_define_method_id {
+ static VALUE
+ m1(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ m2(VALUE, VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ ma(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mv(int, VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ // No cast
+ rb_define_method_id(self, rb_intern("m1"), m1, 1);
+ rb_define_method_id(self, rb_intern("m2"), m2, 2);
+ rb_define_method_id(self, rb_intern("ma"), ma, -2);
+ rb_define_method_id(self, rb_intern("mv"), mv, -1);
+ rb_define_method_id(self, rb_intern("mc"), mc, -1);
+
+ // Cast by RUBY_METHOD_FUNC
+ rb_define_method_id(self, rb_intern("m1"), RUBY_METHOD_FUNC(m1), 1);
+ rb_define_method_id(self, rb_intern("m2"), RUBY_METHOD_FUNC(m2), 2);
+ rb_define_method_id(self, rb_intern("ma"), RUBY_METHOD_FUNC(ma), -2);
+ rb_define_method_id(self, rb_intern("mv"), RUBY_METHOD_FUNC(mv), -1);
+ rb_define_method_id(self, rb_intern("mc"), RUBY_METHOD_FUNC(mc), -1);
+
+ // Explicit cast instead of RUBY_METHOD_FUNC
+ rb_define_method_id(self, rb_intern("m1"), (VALUE (*)(...))(m1), 1);
+ rb_define_method_id(self, rb_intern("m2"), (VALUE (*)(...))(m2), 2);
+ rb_define_method_id(self, rb_intern("ma"), (VALUE (*)(...))(ma), -2);
+ rb_define_method_id(self, rb_intern("mv"), (VALUE (*)(...))(mv), -1);
+ rb_define_method_id(self, rb_intern("mc"), (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_method_id(self, rb_intern("m1"), rb_f_notimplement, 1);
+ rb_define_method_id(self, rb_intern("m2"), rb_f_notimplement, 2);
+ rb_define_method_id(self, rb_intern("ma"), rb_f_notimplement, -2);
+ rb_define_method_id(self, rb_intern("mv"), rb_f_notimplement, -1);
+ rb_define_method_id(self, rb_intern("mc"), rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
+
+ return self;
+ }
+}
+
+namespace test_rb_define_module_function {
+ static VALUE
+ m1(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ m2(VALUE, VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ ma(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mv(int, VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ // No cast
+ rb_define_module_function(self, "m1", m1, 1);
+ rb_define_module_function(self, "m2", m2, 2);
+ rb_define_module_function(self, "ma", ma, -2);
+ rb_define_module_function(self, "mv", mv, -1);
+ rb_define_module_function(self, "mc", mc, -1);
+
+ // Cast by RUBY_METHOD_FUNC
+ rb_define_module_function(self, "m1", RUBY_METHOD_FUNC(m1), 1);
+ rb_define_module_function(self, "m2", RUBY_METHOD_FUNC(m2), 2);
+ rb_define_module_function(self, "ma", RUBY_METHOD_FUNC(ma), -2);
+ rb_define_module_function(self, "mv", RUBY_METHOD_FUNC(mv), -1);
+ rb_define_module_function(self, "mc", RUBY_METHOD_FUNC(mc), -1);
+
+ // Explicit cast instead of RUBY_METHOD_FUNC
+ rb_define_module_function(self, "m1", (VALUE (*)(...))(m1), 1);
+ rb_define_module_function(self, "m2", (VALUE (*)(...))(m2), 2);
+ rb_define_module_function(self, "ma", (VALUE (*)(...))(ma), -2);
+ rb_define_module_function(self, "mv", (VALUE (*)(...))(mv), -1);
+ rb_define_module_function(self, "mc", (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_module_function(self, "m1", rb_f_notimplement, 1);
+ rb_define_module_function(self, "m2", rb_f_notimplement, 2);
+ rb_define_module_function(self, "ma", rb_f_notimplement, -2);
+ rb_define_module_function(self, "mv", rb_f_notimplement, -1);
+ rb_define_module_function(self, "mc", rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
+
+ return self;
+ }
+}
+
+namespace test_rb_define_singleton_method {
+ static VALUE
+ m1(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ m2(VALUE, VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ ma(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mv(int, VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ // No cast
+ rb_define_singleton_method(self, "m1", m1, 1);
+ rb_define_singleton_method(self, "m2", m2, 2);
+ rb_define_singleton_method(self, "ma", ma, -2);
+ rb_define_singleton_method(self, "mv", mv, -1);
+ rb_define_singleton_method(self, "mc", mc, -1);
+
+ // Cast by RUBY_METHOD_FUNC
+ rb_define_singleton_method(self, "m1", RUBY_METHOD_FUNC(m1), 1);
+ rb_define_singleton_method(self, "m2", RUBY_METHOD_FUNC(m2), 2);
+ rb_define_singleton_method(self, "ma", RUBY_METHOD_FUNC(ma), -2);
+ rb_define_singleton_method(self, "mv", RUBY_METHOD_FUNC(mv), -1);
+ rb_define_singleton_method(self, "mc", RUBY_METHOD_FUNC(mc), -1);
+
+ // Explicit cast instead of RUBY_METHOD_FUNC
+ rb_define_singleton_method(self, "m1", (VALUE (*)(...))(m1), 1);
+ rb_define_singleton_method(self, "m2", (VALUE (*)(...))(m2), 2);
+ rb_define_singleton_method(self, "ma", (VALUE (*)(...))(ma), -2);
+ rb_define_singleton_method(self, "mv", (VALUE (*)(...))(mv), -1);
+ rb_define_singleton_method(self, "mc", (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_singleton_method(self, "m1", rb_f_notimplement, 1);
+ rb_define_singleton_method(self, "m2", rb_f_notimplement, 2);
+ rb_define_singleton_method(self, "ma", rb_f_notimplement, -2);
+ rb_define_singleton_method(self, "mv", rb_f_notimplement, -1);
+ rb_define_singleton_method(self, "mc", rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
+
+ return self;
+ }
+}
+
+namespace test_rb_define_protected_method {
+ static VALUE
+ m1(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ m2(VALUE, VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ ma(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mv(int, VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ // No cast
+ rb_define_protected_method(self, "m1", m1, 1);
+ rb_define_protected_method(self, "m2", m2, 2);
+ rb_define_protected_method(self, "ma", ma, -2);
+ rb_define_protected_method(self, "mv", mv, -1);
+ rb_define_protected_method(self, "mc", mc, -1);
+
+ // Cast by RUBY_METHOD_FUNC
+ rb_define_protected_method(self, "m1", RUBY_METHOD_FUNC(m1), 1);
+ rb_define_protected_method(self, "m2", RUBY_METHOD_FUNC(m2), 2);
+ rb_define_protected_method(self, "ma", RUBY_METHOD_FUNC(ma), -2);
+ rb_define_protected_method(self, "mv", RUBY_METHOD_FUNC(mv), -1);
+ rb_define_protected_method(self, "mc", RUBY_METHOD_FUNC(mc), -1);
+
+ // Explicit cast instead of RUBY_METHOD_FUNC
+ rb_define_protected_method(self, "m1", (VALUE (*)(...))(m1), 1);
+ rb_define_protected_method(self, "m2", (VALUE (*)(...))(m2), 2);
+ rb_define_protected_method(self, "ma", (VALUE (*)(...))(ma), -2);
+ rb_define_protected_method(self, "mv", (VALUE (*)(...))(mv), -1);
+ rb_define_protected_method(self, "mc", (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_protected_method(self, "m1", rb_f_notimplement, 1);
+ rb_define_protected_method(self, "m2", rb_f_notimplement, 2);
+ rb_define_protected_method(self, "ma", rb_f_notimplement, -2);
+ rb_define_protected_method(self, "mv", rb_f_notimplement, -1);
+ rb_define_protected_method(self, "mc", rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
+
+ return self;
+ }
+}
+
+namespace test_rb_define_private_method {
+ static VALUE
+ m1(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ m2(VALUE, VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ ma(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mv(int, VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ // No cast
+ rb_define_private_method(self, "m1", m1, 1);
+ rb_define_private_method(self, "m2", m2, 2);
+ rb_define_private_method(self, "ma", ma, -2);
+ rb_define_private_method(self, "mv", mv, -1);
+ rb_define_private_method(self, "mc", mc, -1);
+
+ // Cast by RUBY_METHOD_FUNC
+ rb_define_private_method(self, "m1", RUBY_METHOD_FUNC(m1), 1);
+ rb_define_private_method(self, "m2", RUBY_METHOD_FUNC(m2), 2);
+ rb_define_private_method(self, "ma", RUBY_METHOD_FUNC(ma), -2);
+ rb_define_private_method(self, "mv", RUBY_METHOD_FUNC(mv), -1);
+ rb_define_private_method(self, "mc", RUBY_METHOD_FUNC(mc), -1);
+
+ // Explicit cast instead of RUBY_METHOD_FUNC
+ rb_define_private_method(self, "m1", (VALUE (*)(...))(m1), 1);
+ rb_define_private_method(self, "m2", (VALUE (*)(...))(m2), 2);
+ rb_define_private_method(self, "ma", (VALUE (*)(...))(ma), -2);
+ rb_define_private_method(self, "mv", (VALUE (*)(...))(mv), -1);
+ rb_define_private_method(self, "mc", (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_private_method(self, "m1", rb_f_notimplement, 1);
+ rb_define_private_method(self, "m2", rb_f_notimplement, 2);
+ rb_define_private_method(self, "ma", rb_f_notimplement, -2);
+ rb_define_private_method(self, "mv", rb_f_notimplement, -1);
+ rb_define_private_method(self, "mc", rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
+
+ return self;
+ }
+}
+
+namespace test_rb_define_global_function {
+ static VALUE
+ m1(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ m2(VALUE, VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ ma(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mv(int, VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ // No cast
+ rb_define_global_function("m1", m1, 1);
+ rb_define_global_function("m2", m2, 2);
+ rb_define_global_function("ma", ma, -2);
+ rb_define_global_function("mv", mv, -1);
+ rb_define_global_function("mc", mc, -1);
+
+ // Cast by RUBY_METHOD_FUNC
+ rb_define_global_function("m1", RUBY_METHOD_FUNC(m1), 1);
+ rb_define_global_function("m2", RUBY_METHOD_FUNC(m2), 2);
+ rb_define_global_function("ma", RUBY_METHOD_FUNC(ma), -2);
+ rb_define_global_function("mv", RUBY_METHOD_FUNC(mv), -1);
+ rb_define_global_function("mc", RUBY_METHOD_FUNC(mc), -1);
+
+ // Explicit cast instead of RUBY_METHOD_FUNC
+ rb_define_global_function("m1", (VALUE (*)(...))(m1), 1);
+ rb_define_global_function("m2", (VALUE (*)(...))(m2), 2);
+ rb_define_global_function("ma", (VALUE (*)(...))(ma), -2);
+ rb_define_global_function("mv", (VALUE (*)(...))(mv), -1);
+ rb_define_global_function("mc", (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_global_function("m1", rb_f_notimplement, 1);
+ rb_define_global_function("m2", rb_f_notimplement, 2);
+ rb_define_global_function("ma", rb_f_notimplement, -2);
+ rb_define_global_function("mv", rb_f_notimplement, -1);
+ rb_define_global_function("mc", rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
+
+ return self;
+ }
+}
+
+extern "C" void
+Init_cxxanyargs(void)
+{
+ VALUE b = rb_define_module("Bug");
+#define test(sym) \
+ rb_define_module_function(b, #sym, RUBY_METHOD_FUNC(test_ ## sym::test), 0)
+
+ test(rb_define_virtual_variable);
+ test(rb_define_hooked_variable);
+ test(rb_block_call);
+ test(rb_rescue);
+ test(rb_rescue2);
+ test(rb_ensure);
+ test(rb_catch);
+ test(rb_catch_obj);
+ test(rb_fiber_new);
+ test(rb_proc_new);
+ test(rb_thread_create);
+ test(st_foreach);
+ test(st_foreach_check);
+ test(st_foreach_safe);
+ test(rb_hash_foreach);
+ test(rb_ivar_foreach);
+ test(rb_define_method);
+ test(rb_define_method_id);
+ test(rb_define_module_function);
+ test(rb_define_singleton_method);
+ test(rb_define_protected_method);
+ test(rb_define_private_method);
+ test(rb_define_global_function);
+}
diff --git a/ext/-test-/cxxanyargs/depend b/ext/-test-/cxxanyargs/depend
new file mode 100644
index 0000000000..fc3d8e45d9
--- /dev/null
+++ b/ext/-test-/cxxanyargs/depend
@@ -0,0 +1,13 @@
+$(TARGET_SO) $(STATIC_LIB): $(FAILURES:.cpp=.failed)
+
+.SUFFIXES: .failed
+
+.cpp.failed:
+ $(Q)$(RUBY) -rfileutils \
+ -e "t = ARGV.shift" \
+ -e "err = IO.popen(ARGV, err:[:child, :out], &:read)" \
+ -e "abort err unless /rb_define_method/ =~ err.b" \
+ -e "File.write(t, err)" $@ $(MAKE) $(*F).o
+
+# AUTOGENERATED DEPENDENCIES START
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/cxxanyargs/extconf.rb b/ext/-test-/cxxanyargs/extconf.rb
new file mode 100644
index 0000000000..9749f42068
--- /dev/null
+++ b/ext/-test-/cxxanyargs/extconf.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: false
+
+cxx = MakeMakefile["C++"]
+
+# #### have_devel hack ####
+# cxx.try_compile tries to detect compilers, but the try_compile below is
+# trying to detect a compiler in a different way. We need to prevent the
+# default detection routine.
+
+cxx.instance_variable_set(:'@have_devel', true)
+
+ok = cxx.try_link(<<~'begin', "") do |x|
+ #include "ruby/config.h"
+
+ #ifdef RUBY_ALTERNATIVE_MALLOC_HEADER
+ # include RUBY_ALTERNATIVE_MALLOC_HEADER
+ #endif
+
+ namespace {
+ typedef int conftest1[SIZEOF_LONG == sizeof(long) ? 1 : -1];
+ typedef int conftest2[SIZEOF_VOIDP == sizeof(void*) ? 1 : -1];
+ }
+
+ int
+ main(int argc, const char** argv)
+ {
+ return !!argv[argc];
+ }
+begin
+ # We are wiping ruby.h from the source because that header file is the
+ # subject we are going to test in this extension library.
+ x.sub! %<#include "ruby.h">, ''
+end
+
+cxx.instance_variable_set(:'@have_devel', ok)
+
+if ok
+ $srcs = %w[cxxanyargs.cpp]
+ failures = Dir.glob($srcdir + "/failure*.cpp").map {|n| File.basename(n)}
+ $cleanfiles << "$(FAILURES:.cpp=.failed)"
+ create_makefile("-test-/cxxanyargs") do |mk|
+ mk << "FAILURES #{['=', failures].join(' ')}\n"
+ mk << ".IGNORE: $(FAILURES:.cpp=.o)\n" unless $mswin
+ mk
+ end
+end
diff --git a/ext/-test-/cxxanyargs/failure.cpp b/ext/-test-/cxxanyargs/failure.cpp
new file mode 100644
index 0000000000..039beb1633
--- /dev/null
+++ b/ext/-test-/cxxanyargs/failure.cpp
@@ -0,0 +1,13 @@
+#include <ruby/ruby.h>
+
+static VALUE
+func_arg1(VALUE self, VALUE arg1)
+{
+ return arg1;
+}
+
+extern "C" void
+Init_failure(void)
+{
+ rb_define_method(rb_cObject, "arg1", func_arg1, 0);
+}
diff --git a/ext/-test-/cxxanyargs/failurem1.cpp b/ext/-test-/cxxanyargs/failurem1.cpp
new file mode 100644
index 0000000000..e58a0f4e0d
--- /dev/null
+++ b/ext/-test-/cxxanyargs/failurem1.cpp
@@ -0,0 +1,13 @@
+#include <ruby/ruby.h>
+
+static VALUE
+func_argm1(int argc, VALUE *argv, VALUE self)
+{
+ return argc > 0 ? argv[0] : Qnil;
+}
+
+extern "C" void
+Init_failure(void)
+{
+ rb_define_method(rb_cObject, "argm1", func_argm1, 0);
+}
diff --git a/ext/-test-/debug/depend b/ext/-test-/debug/depend
new file mode 100644
index 0000000000..4ae0378ef2
--- /dev/null
+++ b/ext/-test-/debug/depend
@@ -0,0 +1,485 @@
+# AUTOGENERATED DEPENDENCIES START
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+inspector.o: $(RUBY_EXTCONF_H)
+inspector.o: $(arch_hdrdir)/ruby/config.h
+inspector.o: $(hdrdir)/ruby/assert.h
+inspector.o: $(hdrdir)/ruby/backward.h
+inspector.o: $(hdrdir)/ruby/backward/2/assume.h
+inspector.o: $(hdrdir)/ruby/backward/2/attributes.h
+inspector.o: $(hdrdir)/ruby/backward/2/bool.h
+inspector.o: $(hdrdir)/ruby/backward/2/inttypes.h
+inspector.o: $(hdrdir)/ruby/backward/2/limits.h
+inspector.o: $(hdrdir)/ruby/backward/2/long_long.h
+inspector.o: $(hdrdir)/ruby/backward/2/stdalign.h
+inspector.o: $(hdrdir)/ruby/backward/2/stdarg.h
+inspector.o: $(hdrdir)/ruby/debug.h
+inspector.o: $(hdrdir)/ruby/defines.h
+inspector.o: $(hdrdir)/ruby/intern.h
+inspector.o: $(hdrdir)/ruby/internal/abi.h
+inspector.o: $(hdrdir)/ruby/internal/anyargs.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+inspector.o: $(hdrdir)/ruby/internal/assume.h
+inspector.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+inspector.o: $(hdrdir)/ruby/internal/attr/artificial.h
+inspector.o: $(hdrdir)/ruby/internal/attr/cold.h
+inspector.o: $(hdrdir)/ruby/internal/attr/const.h
+inspector.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+inspector.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+inspector.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+inspector.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+inspector.o: $(hdrdir)/ruby/internal/attr/error.h
+inspector.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+inspector.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+inspector.o: $(hdrdir)/ruby/internal/attr/format.h
+inspector.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+inspector.o: $(hdrdir)/ruby/internal/attr/noalias.h
+inspector.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+inspector.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+inspector.o: $(hdrdir)/ruby/internal/attr/noinline.h
+inspector.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+inspector.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+inspector.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+inspector.o: $(hdrdir)/ruby/internal/attr/pure.h
+inspector.o: $(hdrdir)/ruby/internal/attr/restrict.h
+inspector.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+inspector.o: $(hdrdir)/ruby/internal/attr/warning.h
+inspector.o: $(hdrdir)/ruby/internal/attr/weakref.h
+inspector.o: $(hdrdir)/ruby/internal/cast.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_since.h
+inspector.o: $(hdrdir)/ruby/internal/config.h
+inspector.o: $(hdrdir)/ruby/internal/constant_p.h
+inspector.o: $(hdrdir)/ruby/internal/core.h
+inspector.o: $(hdrdir)/ruby/internal/core/rarray.h
+inspector.o: $(hdrdir)/ruby/internal/core/rbasic.h
+inspector.o: $(hdrdir)/ruby/internal/core/rbignum.h
+inspector.o: $(hdrdir)/ruby/internal/core/rclass.h
+inspector.o: $(hdrdir)/ruby/internal/core/rdata.h
+inspector.o: $(hdrdir)/ruby/internal/core/rfile.h
+inspector.o: $(hdrdir)/ruby/internal/core/rhash.h
+inspector.o: $(hdrdir)/ruby/internal/core/robject.h
+inspector.o: $(hdrdir)/ruby/internal/core/rregexp.h
+inspector.o: $(hdrdir)/ruby/internal/core/rstring.h
+inspector.o: $(hdrdir)/ruby/internal/core/rstruct.h
+inspector.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+inspector.o: $(hdrdir)/ruby/internal/ctype.h
+inspector.o: $(hdrdir)/ruby/internal/dllexport.h
+inspector.o: $(hdrdir)/ruby/internal/dosish.h
+inspector.o: $(hdrdir)/ruby/internal/error.h
+inspector.o: $(hdrdir)/ruby/internal/eval.h
+inspector.o: $(hdrdir)/ruby/internal/event.h
+inspector.o: $(hdrdir)/ruby/internal/fl_type.h
+inspector.o: $(hdrdir)/ruby/internal/gc.h
+inspector.o: $(hdrdir)/ruby/internal/glob.h
+inspector.o: $(hdrdir)/ruby/internal/globals.h
+inspector.o: $(hdrdir)/ruby/internal/has/attribute.h
+inspector.o: $(hdrdir)/ruby/internal/has/builtin.h
+inspector.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+inspector.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+inspector.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+inspector.o: $(hdrdir)/ruby/internal/has/extension.h
+inspector.o: $(hdrdir)/ruby/internal/has/feature.h
+inspector.o: $(hdrdir)/ruby/internal/has/warning.h
+inspector.o: $(hdrdir)/ruby/internal/intern/array.h
+inspector.o: $(hdrdir)/ruby/internal/intern/bignum.h
+inspector.o: $(hdrdir)/ruby/internal/intern/class.h
+inspector.o: $(hdrdir)/ruby/internal/intern/compar.h
+inspector.o: $(hdrdir)/ruby/internal/intern/complex.h
+inspector.o: $(hdrdir)/ruby/internal/intern/cont.h
+inspector.o: $(hdrdir)/ruby/internal/intern/dir.h
+inspector.o: $(hdrdir)/ruby/internal/intern/enum.h
+inspector.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+inspector.o: $(hdrdir)/ruby/internal/intern/error.h
+inspector.o: $(hdrdir)/ruby/internal/intern/eval.h
+inspector.o: $(hdrdir)/ruby/internal/intern/file.h
+inspector.o: $(hdrdir)/ruby/internal/intern/hash.h
+inspector.o: $(hdrdir)/ruby/internal/intern/io.h
+inspector.o: $(hdrdir)/ruby/internal/intern/load.h
+inspector.o: $(hdrdir)/ruby/internal/intern/marshal.h
+inspector.o: $(hdrdir)/ruby/internal/intern/numeric.h
+inspector.o: $(hdrdir)/ruby/internal/intern/object.h
+inspector.o: $(hdrdir)/ruby/internal/intern/parse.h
+inspector.o: $(hdrdir)/ruby/internal/intern/proc.h
+inspector.o: $(hdrdir)/ruby/internal/intern/process.h
+inspector.o: $(hdrdir)/ruby/internal/intern/random.h
+inspector.o: $(hdrdir)/ruby/internal/intern/range.h
+inspector.o: $(hdrdir)/ruby/internal/intern/rational.h
+inspector.o: $(hdrdir)/ruby/internal/intern/re.h
+inspector.o: $(hdrdir)/ruby/internal/intern/ruby.h
+inspector.o: $(hdrdir)/ruby/internal/intern/select.h
+inspector.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+inspector.o: $(hdrdir)/ruby/internal/intern/set.h
+inspector.o: $(hdrdir)/ruby/internal/intern/signal.h
+inspector.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+inspector.o: $(hdrdir)/ruby/internal/intern/string.h
+inspector.o: $(hdrdir)/ruby/internal/intern/struct.h
+inspector.o: $(hdrdir)/ruby/internal/intern/thread.h
+inspector.o: $(hdrdir)/ruby/internal/intern/time.h
+inspector.o: $(hdrdir)/ruby/internal/intern/variable.h
+inspector.o: $(hdrdir)/ruby/internal/intern/vm.h
+inspector.o: $(hdrdir)/ruby/internal/interpreter.h
+inspector.o: $(hdrdir)/ruby/internal/iterator.h
+inspector.o: $(hdrdir)/ruby/internal/memory.h
+inspector.o: $(hdrdir)/ruby/internal/method.h
+inspector.o: $(hdrdir)/ruby/internal/module.h
+inspector.o: $(hdrdir)/ruby/internal/newobj.h
+inspector.o: $(hdrdir)/ruby/internal/scan_args.h
+inspector.o: $(hdrdir)/ruby/internal/special_consts.h
+inspector.o: $(hdrdir)/ruby/internal/static_assert.h
+inspector.o: $(hdrdir)/ruby/internal/stdalign.h
+inspector.o: $(hdrdir)/ruby/internal/stdbool.h
+inspector.o: $(hdrdir)/ruby/internal/stdckdint.h
+inspector.o: $(hdrdir)/ruby/internal/symbol.h
+inspector.o: $(hdrdir)/ruby/internal/value.h
+inspector.o: $(hdrdir)/ruby/internal/value_type.h
+inspector.o: $(hdrdir)/ruby/internal/variable.h
+inspector.o: $(hdrdir)/ruby/internal/warning_push.h
+inspector.o: $(hdrdir)/ruby/internal/xmalloc.h
+inspector.o: $(hdrdir)/ruby/missing.h
+inspector.o: $(hdrdir)/ruby/ruby.h
+inspector.o: $(hdrdir)/ruby/st.h
+inspector.o: $(hdrdir)/ruby/subst.h
+inspector.o: inspector.c
+profile_frames.o: $(RUBY_EXTCONF_H)
+profile_frames.o: $(arch_hdrdir)/ruby/config.h
+profile_frames.o: $(hdrdir)/ruby/assert.h
+profile_frames.o: $(hdrdir)/ruby/backward.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/assume.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/attributes.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/bool.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/inttypes.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/limits.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/long_long.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/stdalign.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/stdarg.h
+profile_frames.o: $(hdrdir)/ruby/debug.h
+profile_frames.o: $(hdrdir)/ruby/defines.h
+profile_frames.o: $(hdrdir)/ruby/intern.h
+profile_frames.o: $(hdrdir)/ruby/internal/abi.h
+profile_frames.o: $(hdrdir)/ruby/internal/anyargs.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/assume.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/artificial.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/cold.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/const.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/error.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/format.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/noalias.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/noinline.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/pure.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/restrict.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/warning.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/weakref.h
+profile_frames.o: $(hdrdir)/ruby/internal/cast.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_since.h
+profile_frames.o: $(hdrdir)/ruby/internal/config.h
+profile_frames.o: $(hdrdir)/ruby/internal/constant_p.h
+profile_frames.o: $(hdrdir)/ruby/internal/core.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rarray.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rbasic.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rbignum.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rclass.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rdata.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rfile.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rhash.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/robject.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rregexp.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rstring.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rstruct.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+profile_frames.o: $(hdrdir)/ruby/internal/ctype.h
+profile_frames.o: $(hdrdir)/ruby/internal/dllexport.h
+profile_frames.o: $(hdrdir)/ruby/internal/dosish.h
+profile_frames.o: $(hdrdir)/ruby/internal/error.h
+profile_frames.o: $(hdrdir)/ruby/internal/eval.h
+profile_frames.o: $(hdrdir)/ruby/internal/event.h
+profile_frames.o: $(hdrdir)/ruby/internal/fl_type.h
+profile_frames.o: $(hdrdir)/ruby/internal/gc.h
+profile_frames.o: $(hdrdir)/ruby/internal/glob.h
+profile_frames.o: $(hdrdir)/ruby/internal/globals.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/attribute.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/builtin.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/extension.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/feature.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/warning.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/array.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/bignum.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/class.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/compar.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/complex.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/cont.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/dir.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/enum.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/error.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/eval.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/file.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/hash.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/io.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/load.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/marshal.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/numeric.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/object.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/parse.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/proc.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/process.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/random.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/range.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/rational.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/re.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/ruby.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/select.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/set.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/signal.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/string.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/struct.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/thread.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/time.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/variable.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/vm.h
+profile_frames.o: $(hdrdir)/ruby/internal/interpreter.h
+profile_frames.o: $(hdrdir)/ruby/internal/iterator.h
+profile_frames.o: $(hdrdir)/ruby/internal/memory.h
+profile_frames.o: $(hdrdir)/ruby/internal/method.h
+profile_frames.o: $(hdrdir)/ruby/internal/module.h
+profile_frames.o: $(hdrdir)/ruby/internal/newobj.h
+profile_frames.o: $(hdrdir)/ruby/internal/scan_args.h
+profile_frames.o: $(hdrdir)/ruby/internal/special_consts.h
+profile_frames.o: $(hdrdir)/ruby/internal/static_assert.h
+profile_frames.o: $(hdrdir)/ruby/internal/stdalign.h
+profile_frames.o: $(hdrdir)/ruby/internal/stdbool.h
+profile_frames.o: $(hdrdir)/ruby/internal/stdckdint.h
+profile_frames.o: $(hdrdir)/ruby/internal/symbol.h
+profile_frames.o: $(hdrdir)/ruby/internal/value.h
+profile_frames.o: $(hdrdir)/ruby/internal/value_type.h
+profile_frames.o: $(hdrdir)/ruby/internal/variable.h
+profile_frames.o: $(hdrdir)/ruby/internal/warning_push.h
+profile_frames.o: $(hdrdir)/ruby/internal/xmalloc.h
+profile_frames.o: $(hdrdir)/ruby/missing.h
+profile_frames.o: $(hdrdir)/ruby/ruby.h
+profile_frames.o: $(hdrdir)/ruby/st.h
+profile_frames.o: $(hdrdir)/ruby/subst.h
+profile_frames.o: profile_frames.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/debug/extconf.rb b/ext/-test-/debug/extconf.rb
new file mode 100644
index 0000000000..ca51178a18
--- /dev/null
+++ b/ext/-test-/debug/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext
diff --git a/ext/-test-/debug/init.c b/ext/-test-/debug/init.c
new file mode 100644
index 0000000000..fe3979cbc5
--- /dev/null
+++ b/ext/-test-/debug/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_debug(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_module_under(mBug, "Debug");
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/debug/inspector.c b/ext/-test-/debug/inspector.c
new file mode 100644
index 0000000000..25f9d894d3
--- /dev/null
+++ b/ext/-test-/debug/inspector.c
@@ -0,0 +1,32 @@
+#include "ruby/ruby.h"
+#include "ruby/debug.h"
+
+static VALUE
+callback(const rb_debug_inspector_t *dbg_context, void *data)
+{
+ VALUE locs = rb_debug_inspector_backtrace_locations(dbg_context);
+ long i, len = RARRAY_LEN(locs);
+ VALUE binds = rb_ary_new();
+ for (i = 0; i < len; ++i) {
+ VALUE entry = rb_ary_new();
+ rb_ary_push(binds, entry);
+ rb_ary_push(entry, rb_debug_inspector_frame_self_get(dbg_context, i));
+ rb_ary_push(entry, rb_debug_inspector_frame_binding_get(dbg_context, i));
+ rb_ary_push(entry, rb_debug_inspector_frame_class_get(dbg_context, i));
+ rb_ary_push(entry, rb_debug_inspector_frame_iseq_get(dbg_context, i));
+ rb_ary_push(entry, rb_ary_entry(locs, i));
+ }
+ return binds;
+}
+
+static VALUE
+debug_inspector(VALUE self)
+{
+ return rb_debug_inspector_open(callback, NULL);
+}
+
+void
+Init_inspector(VALUE klass)
+{
+ rb_define_module_function(klass, "inspector", debug_inspector, 0);
+}
diff --git a/ext/-test-/debug/profile_frames.c b/ext/-test-/debug/profile_frames.c
new file mode 100644
index 0000000000..f9a77a5a78
--- /dev/null
+++ b/ext/-test-/debug/profile_frames.c
@@ -0,0 +1,65 @@
+#include "ruby/ruby.h"
+#include "ruby/debug.h"
+
+#define MAX_BUF_SIZE 0x100
+
+static VALUE
+profile_frames(VALUE self, VALUE start_v, VALUE num_v)
+{
+ int i, collected_size;
+ int start = NUM2INT(start_v);
+ int buff_size = NUM2INT(num_v);
+ VALUE buff[MAX_BUF_SIZE];
+ int lines[MAX_BUF_SIZE];
+ VALUE result = rb_ary_new();
+
+ if (buff_size > MAX_BUF_SIZE) rb_raise(rb_eRuntimeError, "too long buff_size");
+
+ collected_size = rb_profile_frames(start, buff_size, buff, lines);
+
+ for (i=0; i<collected_size; i++) {
+ VALUE ary = rb_ary_new();
+ rb_ary_push(ary, rb_profile_frame_path(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_absolute_path(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_label(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_base_label(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_full_label(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_first_lineno(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_classpath(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_singleton_method_p(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_method_name(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_qualified_method_name(buff[i]));
+ rb_ary_push(ary, INT2NUM(lines[i]));
+
+ rb_ary_push(result, ary);
+ }
+
+ return result;
+}
+
+static VALUE
+profile_thread_frames(VALUE self, VALUE thread, VALUE start_v, VALUE num_v)
+{
+ int i, collected_size;
+ int start = NUM2INT(start_v);
+ int buff_size = NUM2INT(num_v);
+ VALUE buff[MAX_BUF_SIZE];
+ int lines[MAX_BUF_SIZE];
+ VALUE result = rb_ary_new();
+
+ if (buff_size > MAX_BUF_SIZE) rb_raise(rb_eRuntimeError, "too long buff_size");
+
+ collected_size = rb_profile_thread_frames(thread, start, buff_size, buff, lines);
+ for (i=0; i<collected_size; i++) {
+ rb_ary_push(result, rb_profile_frame_full_label(buff[i]));
+ }
+
+ return result;
+}
+
+void
+Init_profile_frames(VALUE klass)
+{
+ rb_define_module_function(klass, "profile_frames", profile_frames, 2);
+ rb_define_module_function(klass, "profile_thread_frames", profile_thread_frames, 3);
+}
diff --git a/ext/-test-/dln/empty/depend b/ext/-test-/dln/empty/depend
new file mode 100644
index 0000000000..58f1508598
--- /dev/null
+++ b/ext/-test-/dln/empty/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+empty.o: $(RUBY_EXTCONF_H)
+empty.o: $(arch_hdrdir)/ruby/config.h
+empty.o: $(hdrdir)/ruby.h
+empty.o: $(hdrdir)/ruby/assert.h
+empty.o: $(hdrdir)/ruby/backward.h
+empty.o: $(hdrdir)/ruby/backward/2/assume.h
+empty.o: $(hdrdir)/ruby/backward/2/attributes.h
+empty.o: $(hdrdir)/ruby/backward/2/bool.h
+empty.o: $(hdrdir)/ruby/backward/2/inttypes.h
+empty.o: $(hdrdir)/ruby/backward/2/limits.h
+empty.o: $(hdrdir)/ruby/backward/2/long_long.h
+empty.o: $(hdrdir)/ruby/backward/2/stdalign.h
+empty.o: $(hdrdir)/ruby/backward/2/stdarg.h
+empty.o: $(hdrdir)/ruby/defines.h
+empty.o: $(hdrdir)/ruby/intern.h
+empty.o: $(hdrdir)/ruby/internal/abi.h
+empty.o: $(hdrdir)/ruby/internal/anyargs.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+empty.o: $(hdrdir)/ruby/internal/assume.h
+empty.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+empty.o: $(hdrdir)/ruby/internal/attr/artificial.h
+empty.o: $(hdrdir)/ruby/internal/attr/cold.h
+empty.o: $(hdrdir)/ruby/internal/attr/const.h
+empty.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+empty.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+empty.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+empty.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+empty.o: $(hdrdir)/ruby/internal/attr/error.h
+empty.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+empty.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+empty.o: $(hdrdir)/ruby/internal/attr/format.h
+empty.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+empty.o: $(hdrdir)/ruby/internal/attr/noalias.h
+empty.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+empty.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+empty.o: $(hdrdir)/ruby/internal/attr/noinline.h
+empty.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+empty.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+empty.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+empty.o: $(hdrdir)/ruby/internal/attr/pure.h
+empty.o: $(hdrdir)/ruby/internal/attr/restrict.h
+empty.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+empty.o: $(hdrdir)/ruby/internal/attr/warning.h
+empty.o: $(hdrdir)/ruby/internal/attr/weakref.h
+empty.o: $(hdrdir)/ruby/internal/cast.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+empty.o: $(hdrdir)/ruby/internal/compiler_since.h
+empty.o: $(hdrdir)/ruby/internal/config.h
+empty.o: $(hdrdir)/ruby/internal/constant_p.h
+empty.o: $(hdrdir)/ruby/internal/core.h
+empty.o: $(hdrdir)/ruby/internal/core/rarray.h
+empty.o: $(hdrdir)/ruby/internal/core/rbasic.h
+empty.o: $(hdrdir)/ruby/internal/core/rbignum.h
+empty.o: $(hdrdir)/ruby/internal/core/rclass.h
+empty.o: $(hdrdir)/ruby/internal/core/rdata.h
+empty.o: $(hdrdir)/ruby/internal/core/rfile.h
+empty.o: $(hdrdir)/ruby/internal/core/rhash.h
+empty.o: $(hdrdir)/ruby/internal/core/robject.h
+empty.o: $(hdrdir)/ruby/internal/core/rregexp.h
+empty.o: $(hdrdir)/ruby/internal/core/rstring.h
+empty.o: $(hdrdir)/ruby/internal/core/rstruct.h
+empty.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+empty.o: $(hdrdir)/ruby/internal/ctype.h
+empty.o: $(hdrdir)/ruby/internal/dllexport.h
+empty.o: $(hdrdir)/ruby/internal/dosish.h
+empty.o: $(hdrdir)/ruby/internal/error.h
+empty.o: $(hdrdir)/ruby/internal/eval.h
+empty.o: $(hdrdir)/ruby/internal/event.h
+empty.o: $(hdrdir)/ruby/internal/fl_type.h
+empty.o: $(hdrdir)/ruby/internal/gc.h
+empty.o: $(hdrdir)/ruby/internal/glob.h
+empty.o: $(hdrdir)/ruby/internal/globals.h
+empty.o: $(hdrdir)/ruby/internal/has/attribute.h
+empty.o: $(hdrdir)/ruby/internal/has/builtin.h
+empty.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+empty.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+empty.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+empty.o: $(hdrdir)/ruby/internal/has/extension.h
+empty.o: $(hdrdir)/ruby/internal/has/feature.h
+empty.o: $(hdrdir)/ruby/internal/has/warning.h
+empty.o: $(hdrdir)/ruby/internal/intern/array.h
+empty.o: $(hdrdir)/ruby/internal/intern/bignum.h
+empty.o: $(hdrdir)/ruby/internal/intern/class.h
+empty.o: $(hdrdir)/ruby/internal/intern/compar.h
+empty.o: $(hdrdir)/ruby/internal/intern/complex.h
+empty.o: $(hdrdir)/ruby/internal/intern/cont.h
+empty.o: $(hdrdir)/ruby/internal/intern/dir.h
+empty.o: $(hdrdir)/ruby/internal/intern/enum.h
+empty.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+empty.o: $(hdrdir)/ruby/internal/intern/error.h
+empty.o: $(hdrdir)/ruby/internal/intern/eval.h
+empty.o: $(hdrdir)/ruby/internal/intern/file.h
+empty.o: $(hdrdir)/ruby/internal/intern/hash.h
+empty.o: $(hdrdir)/ruby/internal/intern/io.h
+empty.o: $(hdrdir)/ruby/internal/intern/load.h
+empty.o: $(hdrdir)/ruby/internal/intern/marshal.h
+empty.o: $(hdrdir)/ruby/internal/intern/numeric.h
+empty.o: $(hdrdir)/ruby/internal/intern/object.h
+empty.o: $(hdrdir)/ruby/internal/intern/parse.h
+empty.o: $(hdrdir)/ruby/internal/intern/proc.h
+empty.o: $(hdrdir)/ruby/internal/intern/process.h
+empty.o: $(hdrdir)/ruby/internal/intern/random.h
+empty.o: $(hdrdir)/ruby/internal/intern/range.h
+empty.o: $(hdrdir)/ruby/internal/intern/rational.h
+empty.o: $(hdrdir)/ruby/internal/intern/re.h
+empty.o: $(hdrdir)/ruby/internal/intern/ruby.h
+empty.o: $(hdrdir)/ruby/internal/intern/select.h
+empty.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+empty.o: $(hdrdir)/ruby/internal/intern/set.h
+empty.o: $(hdrdir)/ruby/internal/intern/signal.h
+empty.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+empty.o: $(hdrdir)/ruby/internal/intern/string.h
+empty.o: $(hdrdir)/ruby/internal/intern/struct.h
+empty.o: $(hdrdir)/ruby/internal/intern/thread.h
+empty.o: $(hdrdir)/ruby/internal/intern/time.h
+empty.o: $(hdrdir)/ruby/internal/intern/variable.h
+empty.o: $(hdrdir)/ruby/internal/intern/vm.h
+empty.o: $(hdrdir)/ruby/internal/interpreter.h
+empty.o: $(hdrdir)/ruby/internal/iterator.h
+empty.o: $(hdrdir)/ruby/internal/memory.h
+empty.o: $(hdrdir)/ruby/internal/method.h
+empty.o: $(hdrdir)/ruby/internal/module.h
+empty.o: $(hdrdir)/ruby/internal/newobj.h
+empty.o: $(hdrdir)/ruby/internal/scan_args.h
+empty.o: $(hdrdir)/ruby/internal/special_consts.h
+empty.o: $(hdrdir)/ruby/internal/static_assert.h
+empty.o: $(hdrdir)/ruby/internal/stdalign.h
+empty.o: $(hdrdir)/ruby/internal/stdbool.h
+empty.o: $(hdrdir)/ruby/internal/stdckdint.h
+empty.o: $(hdrdir)/ruby/internal/symbol.h
+empty.o: $(hdrdir)/ruby/internal/value.h
+empty.o: $(hdrdir)/ruby/internal/value_type.h
+empty.o: $(hdrdir)/ruby/internal/variable.h
+empty.o: $(hdrdir)/ruby/internal/warning_push.h
+empty.o: $(hdrdir)/ruby/internal/xmalloc.h
+empty.o: $(hdrdir)/ruby/missing.h
+empty.o: $(hdrdir)/ruby/ruby.h
+empty.o: $(hdrdir)/ruby/st.h
+empty.o: $(hdrdir)/ruby/subst.h
+empty.o: empty.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/dln/empty/empty.c b/ext/-test-/dln/empty/empty.c
new file mode 100644
index 0000000000..2b4fd42cd2
--- /dev/null
+++ b/ext/-test-/dln/empty/empty.c
@@ -0,0 +1,6 @@
+#include "ruby.h"
+
+void
+Init_empty(void)
+{
+}
diff --git a/ext/-test-/dln/empty/extconf.rb b/ext/-test-/dln/empty/extconf.rb
new file mode 100644
index 0000000000..20310b6dde
--- /dev/null
+++ b/ext/-test-/dln/empty/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/dln/empty")
diff --git a/ext/-test-/econv/append.c b/ext/-test-/econv/append.c
new file mode 100644
index 0000000000..eb473c47a3
--- /dev/null
+++ b/ext/-test-/econv/append.c
@@ -0,0 +1,17 @@
+#include "ruby/ruby.h"
+#include "ruby/encoding.h"
+
+static VALUE
+econv_append(VALUE self, VALUE src, VALUE dst)
+{
+ rb_econv_t *ec = DATA_PTR(self);
+ StringValue(src);
+ StringValue(dst);
+ return rb_econv_str_append(ec, src, dst, 0);
+}
+
+void
+Init_econv_append(VALUE klass)
+{
+ rb_define_method(klass, "append", econv_append, 2);
+}
diff --git a/ext/-test-/econv/depend b/ext/-test-/econv/depend
new file mode 100644
index 0000000000..3a5bc9c659
--- /dev/null
+++ b/ext/-test-/econv/depend
@@ -0,0 +1,336 @@
+# AUTOGENERATED DEPENDENCIES START
+append.o: $(RUBY_EXTCONF_H)
+append.o: $(arch_hdrdir)/ruby/config.h
+append.o: $(hdrdir)/ruby.h
+append.o: $(hdrdir)/ruby/assert.h
+append.o: $(hdrdir)/ruby/backward.h
+append.o: $(hdrdir)/ruby/backward/2/assume.h
+append.o: $(hdrdir)/ruby/backward/2/attributes.h
+append.o: $(hdrdir)/ruby/backward/2/bool.h
+append.o: $(hdrdir)/ruby/backward/2/inttypes.h
+append.o: $(hdrdir)/ruby/backward/2/limits.h
+append.o: $(hdrdir)/ruby/backward/2/long_long.h
+append.o: $(hdrdir)/ruby/backward/2/stdalign.h
+append.o: $(hdrdir)/ruby/backward/2/stdarg.h
+append.o: $(hdrdir)/ruby/defines.h
+append.o: $(hdrdir)/ruby/encoding.h
+append.o: $(hdrdir)/ruby/intern.h
+append.o: $(hdrdir)/ruby/internal/abi.h
+append.o: $(hdrdir)/ruby/internal/anyargs.h
+append.o: $(hdrdir)/ruby/internal/arithmetic.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+append.o: $(hdrdir)/ruby/internal/assume.h
+append.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+append.o: $(hdrdir)/ruby/internal/attr/artificial.h
+append.o: $(hdrdir)/ruby/internal/attr/cold.h
+append.o: $(hdrdir)/ruby/internal/attr/const.h
+append.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+append.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+append.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+append.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+append.o: $(hdrdir)/ruby/internal/attr/error.h
+append.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+append.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+append.o: $(hdrdir)/ruby/internal/attr/format.h
+append.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+append.o: $(hdrdir)/ruby/internal/attr/noalias.h
+append.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+append.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+append.o: $(hdrdir)/ruby/internal/attr/noinline.h
+append.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+append.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+append.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+append.o: $(hdrdir)/ruby/internal/attr/pure.h
+append.o: $(hdrdir)/ruby/internal/attr/restrict.h
+append.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+append.o: $(hdrdir)/ruby/internal/attr/warning.h
+append.o: $(hdrdir)/ruby/internal/attr/weakref.h
+append.o: $(hdrdir)/ruby/internal/cast.h
+append.o: $(hdrdir)/ruby/internal/compiler_is.h
+append.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+append.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+append.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+append.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+append.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+append.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+append.o: $(hdrdir)/ruby/internal/compiler_since.h
+append.o: $(hdrdir)/ruby/internal/config.h
+append.o: $(hdrdir)/ruby/internal/constant_p.h
+append.o: $(hdrdir)/ruby/internal/core.h
+append.o: $(hdrdir)/ruby/internal/core/rarray.h
+append.o: $(hdrdir)/ruby/internal/core/rbasic.h
+append.o: $(hdrdir)/ruby/internal/core/rbignum.h
+append.o: $(hdrdir)/ruby/internal/core/rclass.h
+append.o: $(hdrdir)/ruby/internal/core/rdata.h
+append.o: $(hdrdir)/ruby/internal/core/rfile.h
+append.o: $(hdrdir)/ruby/internal/core/rhash.h
+append.o: $(hdrdir)/ruby/internal/core/robject.h
+append.o: $(hdrdir)/ruby/internal/core/rregexp.h
+append.o: $(hdrdir)/ruby/internal/core/rstring.h
+append.o: $(hdrdir)/ruby/internal/core/rstruct.h
+append.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+append.o: $(hdrdir)/ruby/internal/ctype.h
+append.o: $(hdrdir)/ruby/internal/dllexport.h
+append.o: $(hdrdir)/ruby/internal/dosish.h
+append.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+append.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+append.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+append.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+append.o: $(hdrdir)/ruby/internal/encoding/re.h
+append.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+append.o: $(hdrdir)/ruby/internal/encoding/string.h
+append.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+append.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+append.o: $(hdrdir)/ruby/internal/error.h
+append.o: $(hdrdir)/ruby/internal/eval.h
+append.o: $(hdrdir)/ruby/internal/event.h
+append.o: $(hdrdir)/ruby/internal/fl_type.h
+append.o: $(hdrdir)/ruby/internal/gc.h
+append.o: $(hdrdir)/ruby/internal/glob.h
+append.o: $(hdrdir)/ruby/internal/globals.h
+append.o: $(hdrdir)/ruby/internal/has/attribute.h
+append.o: $(hdrdir)/ruby/internal/has/builtin.h
+append.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+append.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+append.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+append.o: $(hdrdir)/ruby/internal/has/extension.h
+append.o: $(hdrdir)/ruby/internal/has/feature.h
+append.o: $(hdrdir)/ruby/internal/has/warning.h
+append.o: $(hdrdir)/ruby/internal/intern/array.h
+append.o: $(hdrdir)/ruby/internal/intern/bignum.h
+append.o: $(hdrdir)/ruby/internal/intern/class.h
+append.o: $(hdrdir)/ruby/internal/intern/compar.h
+append.o: $(hdrdir)/ruby/internal/intern/complex.h
+append.o: $(hdrdir)/ruby/internal/intern/cont.h
+append.o: $(hdrdir)/ruby/internal/intern/dir.h
+append.o: $(hdrdir)/ruby/internal/intern/enum.h
+append.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+append.o: $(hdrdir)/ruby/internal/intern/error.h
+append.o: $(hdrdir)/ruby/internal/intern/eval.h
+append.o: $(hdrdir)/ruby/internal/intern/file.h
+append.o: $(hdrdir)/ruby/internal/intern/hash.h
+append.o: $(hdrdir)/ruby/internal/intern/io.h
+append.o: $(hdrdir)/ruby/internal/intern/load.h
+append.o: $(hdrdir)/ruby/internal/intern/marshal.h
+append.o: $(hdrdir)/ruby/internal/intern/numeric.h
+append.o: $(hdrdir)/ruby/internal/intern/object.h
+append.o: $(hdrdir)/ruby/internal/intern/parse.h
+append.o: $(hdrdir)/ruby/internal/intern/proc.h
+append.o: $(hdrdir)/ruby/internal/intern/process.h
+append.o: $(hdrdir)/ruby/internal/intern/random.h
+append.o: $(hdrdir)/ruby/internal/intern/range.h
+append.o: $(hdrdir)/ruby/internal/intern/rational.h
+append.o: $(hdrdir)/ruby/internal/intern/re.h
+append.o: $(hdrdir)/ruby/internal/intern/ruby.h
+append.o: $(hdrdir)/ruby/internal/intern/select.h
+append.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+append.o: $(hdrdir)/ruby/internal/intern/set.h
+append.o: $(hdrdir)/ruby/internal/intern/signal.h
+append.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+append.o: $(hdrdir)/ruby/internal/intern/string.h
+append.o: $(hdrdir)/ruby/internal/intern/struct.h
+append.o: $(hdrdir)/ruby/internal/intern/thread.h
+append.o: $(hdrdir)/ruby/internal/intern/time.h
+append.o: $(hdrdir)/ruby/internal/intern/variable.h
+append.o: $(hdrdir)/ruby/internal/intern/vm.h
+append.o: $(hdrdir)/ruby/internal/interpreter.h
+append.o: $(hdrdir)/ruby/internal/iterator.h
+append.o: $(hdrdir)/ruby/internal/memory.h
+append.o: $(hdrdir)/ruby/internal/method.h
+append.o: $(hdrdir)/ruby/internal/module.h
+append.o: $(hdrdir)/ruby/internal/newobj.h
+append.o: $(hdrdir)/ruby/internal/scan_args.h
+append.o: $(hdrdir)/ruby/internal/special_consts.h
+append.o: $(hdrdir)/ruby/internal/static_assert.h
+append.o: $(hdrdir)/ruby/internal/stdalign.h
+append.o: $(hdrdir)/ruby/internal/stdbool.h
+append.o: $(hdrdir)/ruby/internal/stdckdint.h
+append.o: $(hdrdir)/ruby/internal/symbol.h
+append.o: $(hdrdir)/ruby/internal/value.h
+append.o: $(hdrdir)/ruby/internal/value_type.h
+append.o: $(hdrdir)/ruby/internal/variable.h
+append.o: $(hdrdir)/ruby/internal/warning_push.h
+append.o: $(hdrdir)/ruby/internal/xmalloc.h
+append.o: $(hdrdir)/ruby/missing.h
+append.o: $(hdrdir)/ruby/onigmo.h
+append.o: $(hdrdir)/ruby/oniguruma.h
+append.o: $(hdrdir)/ruby/ruby.h
+append.o: $(hdrdir)/ruby/st.h
+append.o: $(hdrdir)/ruby/subst.h
+append.o: append.c
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/econv/extconf.rb b/ext/-test-/econv/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/econv/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/econv/init.c b/ext/-test-/econv/init.c
new file mode 100644
index 0000000000..9772ebe71c
--- /dev/null
+++ b/ext/-test-/econv/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_econv_##n(VALUE klass); Init_econv_##n(klass);}
+
+void
+Init_econv(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "EConv", rb_path2class("Encoding::Converter"));
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/ensure_and_callcc/depend b/ext/-test-/ensure_and_callcc/depend
new file mode 100644
index 0000000000..54431847a6
--- /dev/null
+++ b/ext/-test-/ensure_and_callcc/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+ensure_and_callcc.o: $(RUBY_EXTCONF_H)
+ensure_and_callcc.o: $(arch_hdrdir)/ruby/config.h
+ensure_and_callcc.o: $(hdrdir)/ruby.h
+ensure_and_callcc.o: $(hdrdir)/ruby/assert.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/assume.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/attributes.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/bool.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/limits.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/long_long.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ensure_and_callcc.o: $(hdrdir)/ruby/defines.h
+ensure_and_callcc.o: $(hdrdir)/ruby/intern.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/abi.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/anyargs.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/assume.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/cold.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/const.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/error.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/format.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/pure.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/warning.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/cast.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_since.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/config.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/constant_p.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rarray.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rclass.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rdata.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rfile.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rhash.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/robject.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rstring.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/ctype.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/dllexport.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/dosish.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/error.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/eval.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/event.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/fl_type.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/gc.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/glob.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/globals.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/attribute.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/builtin.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/extension.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/feature.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/warning.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/array.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/class.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/compar.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/complex.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/cont.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/dir.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/enum.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/error.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/eval.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/file.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/hash.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/io.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/load.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/object.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/parse.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/proc.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/process.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/random.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/range.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/rational.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/re.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/select.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/set.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/signal.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/string.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/struct.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/thread.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/time.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/variable.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/vm.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/interpreter.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/iterator.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/memory.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/method.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/module.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/newobj.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/scan_args.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/special_consts.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/static_assert.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/stdalign.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/stdbool.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/stdckdint.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/symbol.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/value.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/value_type.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/variable.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/warning_push.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/xmalloc.h
+ensure_and_callcc.o: $(hdrdir)/ruby/missing.h
+ensure_and_callcc.o: $(hdrdir)/ruby/ruby.h
+ensure_and_callcc.o: $(hdrdir)/ruby/st.h
+ensure_and_callcc.o: $(hdrdir)/ruby/subst.h
+ensure_and_callcc.o: ensure_and_callcc.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/ensure_and_callcc/ensure_and_callcc.c b/ext/-test-/ensure_and_callcc/ensure_and_callcc.c
new file mode 100644
index 0000000000..1a92de69c3
--- /dev/null
+++ b/ext/-test-/ensure_and_callcc/ensure_and_callcc.c
@@ -0,0 +1,58 @@
+#include "ruby.h"
+
+static VALUE rb_mEnsureAndCallcc;
+
+struct require_data {
+ VALUE obj;
+ VALUE fname;
+};
+
+static VALUE
+call_require(VALUE arg)
+{
+ struct require_data *data = (struct require_data *)arg;
+ rb_f_require(data->obj, data->fname);
+ return Qnil;
+}
+
+static VALUE
+call_ensure(VALUE _)
+{
+ VALUE v = rb_iv_get(rb_mEnsureAndCallcc, "@ensure_called");
+ int called = FIX2INT(v) + 1;
+ rb_iv_set(rb_mEnsureAndCallcc, "@ensure_called", INT2FIX(called));
+ return Qnil;
+}
+
+static VALUE
+require_with_ensure(VALUE self, VALUE fname)
+{
+ struct require_data data = {
+ .obj = self,
+ .fname = fname
+ };
+ return rb_ensure(call_require, (VALUE)&data, call_ensure, Qnil);
+}
+
+static VALUE
+ensure_called(VALUE self)
+{
+ return rb_iv_get(rb_mEnsureAndCallcc, "@ensure_called");
+}
+
+static VALUE
+reset(VALUE self)
+{
+ rb_iv_set(rb_mEnsureAndCallcc, "@ensure_called", INT2FIX(0));
+ return Qnil;
+}
+
+void
+Init_ensure_and_callcc(void)
+{
+ rb_mEnsureAndCallcc = rb_define_module("EnsureAndCallcc");
+ rb_iv_set(rb_mEnsureAndCallcc, "@ensure_called", INT2FIX(0));
+ rb_define_singleton_method(rb_mEnsureAndCallcc, "reset", reset, 0);
+ rb_define_singleton_method(rb_mEnsureAndCallcc, "ensure_called", ensure_called, 0);
+ rb_define_singleton_method(rb_mEnsureAndCallcc, "require_with_ensure", require_with_ensure, 1);
+}
diff --git a/ext/-test-/ensure_and_callcc/extconf.rb b/ext/-test-/ensure_and_callcc/extconf.rb
new file mode 100644
index 0000000000..123b80b8d0
--- /dev/null
+++ b/ext/-test-/ensure_and_callcc/extconf.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: false
+require "mkmf"
+
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/enumerator_kw/depend b/ext/-test-/enumerator_kw/depend
new file mode 100644
index 0000000000..b6d2f0a998
--- /dev/null
+++ b/ext/-test-/enumerator_kw/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+enumerator_kw.o: $(RUBY_EXTCONF_H)
+enumerator_kw.o: $(arch_hdrdir)/ruby/config.h
+enumerator_kw.o: $(hdrdir)/ruby.h
+enumerator_kw.o: $(hdrdir)/ruby/assert.h
+enumerator_kw.o: $(hdrdir)/ruby/backward.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/assume.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/attributes.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/bool.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/inttypes.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/limits.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/long_long.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/stdalign.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/stdarg.h
+enumerator_kw.o: $(hdrdir)/ruby/defines.h
+enumerator_kw.o: $(hdrdir)/ruby/intern.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/abi.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/anyargs.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/assume.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/artificial.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/cold.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/const.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/error.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/format.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/noalias.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/noinline.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/pure.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/restrict.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/warning.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/weakref.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/cast.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_since.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/config.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/constant_p.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rarray.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rbasic.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rbignum.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rclass.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rdata.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rfile.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rhash.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/robject.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rregexp.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rstring.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rstruct.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/ctype.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/dllexport.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/dosish.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/error.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/eval.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/event.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/fl_type.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/gc.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/glob.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/globals.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/attribute.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/builtin.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/extension.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/feature.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/warning.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/array.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/bignum.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/class.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/compar.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/complex.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/cont.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/dir.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/enum.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/error.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/eval.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/file.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/hash.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/io.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/load.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/marshal.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/numeric.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/object.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/parse.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/proc.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/process.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/random.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/range.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/rational.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/re.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/ruby.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/select.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/set.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/signal.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/string.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/struct.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/thread.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/time.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/variable.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/vm.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/interpreter.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/iterator.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/memory.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/method.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/module.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/newobj.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/scan_args.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/special_consts.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/static_assert.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/stdalign.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/stdbool.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/stdckdint.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/symbol.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/value.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/value_type.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/variable.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/warning_push.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/xmalloc.h
+enumerator_kw.o: $(hdrdir)/ruby/missing.h
+enumerator_kw.o: $(hdrdir)/ruby/ruby.h
+enumerator_kw.o: $(hdrdir)/ruby/st.h
+enumerator_kw.o: $(hdrdir)/ruby/subst.h
+enumerator_kw.o: enumerator_kw.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/enumerator_kw/enumerator_kw.c b/ext/-test-/enumerator_kw/enumerator_kw.c
new file mode 100644
index 0000000000..9104c51869
--- /dev/null
+++ b/ext/-test-/enumerator_kw/enumerator_kw.c
@@ -0,0 +1,22 @@
+#include <ruby.h>
+
+static VALUE
+enumerator_kw(int argc, VALUE *argv, VALUE self)
+{
+ VALUE opt, enum_args[4];
+ enum_args[0] = Qnil;
+ enum_args[1] = Qnil;
+ rb_scan_args(argc, argv, "01*:", enum_args, enum_args+1, &opt);
+ enum_args[3] = self;
+ enum_args[2] = opt;
+ RETURN_SIZED_ENUMERATOR_KW(self, 4, enum_args, 0, RB_NO_KEYWORDS);
+ return rb_yield_values_kw(4, enum_args, RB_NO_KEYWORDS);
+}
+
+void
+Init_enumerator_kw(void)
+{
+ VALUE module = rb_define_module("Bug");
+ module = rb_define_module_under(module, "EnumeratorKw");
+ rb_define_method(module, "m", enumerator_kw, -1);
+}
diff --git a/ext/-test-/enumerator_kw/extconf.rb b/ext/-test-/enumerator_kw/extconf.rb
new file mode 100644
index 0000000000..ab2be73fa8
--- /dev/null
+++ b/ext/-test-/enumerator_kw/extconf.rb
@@ -0,0 +1 @@
+create_makefile("-test-/enumerator_kw")
diff --git a/ext/-test-/eval/depend b/ext/-test-/eval/depend
new file mode 100644
index 0000000000..03a1c7d7ef
--- /dev/null
+++ b/ext/-test-/eval/depend
@@ -0,0 +1,162 @@
+# AUTOGENERATED DEPENDENCIES START
+eval.o: $(RUBY_EXTCONF_H)
+eval.o: $(arch_hdrdir)/ruby/config.h
+eval.o: $(hdrdir)/ruby/assert.h
+eval.o: $(hdrdir)/ruby/backward.h
+eval.o: $(hdrdir)/ruby/backward/2/assume.h
+eval.o: $(hdrdir)/ruby/backward/2/attributes.h
+eval.o: $(hdrdir)/ruby/backward/2/bool.h
+eval.o: $(hdrdir)/ruby/backward/2/inttypes.h
+eval.o: $(hdrdir)/ruby/backward/2/limits.h
+eval.o: $(hdrdir)/ruby/backward/2/long_long.h
+eval.o: $(hdrdir)/ruby/backward/2/stdalign.h
+eval.o: $(hdrdir)/ruby/backward/2/stdarg.h
+eval.o: $(hdrdir)/ruby/defines.h
+eval.o: $(hdrdir)/ruby/intern.h
+eval.o: $(hdrdir)/ruby/internal/abi.h
+eval.o: $(hdrdir)/ruby/internal/anyargs.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+eval.o: $(hdrdir)/ruby/internal/assume.h
+eval.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+eval.o: $(hdrdir)/ruby/internal/attr/artificial.h
+eval.o: $(hdrdir)/ruby/internal/attr/cold.h
+eval.o: $(hdrdir)/ruby/internal/attr/const.h
+eval.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+eval.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+eval.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+eval.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+eval.o: $(hdrdir)/ruby/internal/attr/error.h
+eval.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+eval.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+eval.o: $(hdrdir)/ruby/internal/attr/format.h
+eval.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+eval.o: $(hdrdir)/ruby/internal/attr/noalias.h
+eval.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+eval.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+eval.o: $(hdrdir)/ruby/internal/attr/noinline.h
+eval.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+eval.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+eval.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+eval.o: $(hdrdir)/ruby/internal/attr/pure.h
+eval.o: $(hdrdir)/ruby/internal/attr/restrict.h
+eval.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+eval.o: $(hdrdir)/ruby/internal/attr/warning.h
+eval.o: $(hdrdir)/ruby/internal/attr/weakref.h
+eval.o: $(hdrdir)/ruby/internal/cast.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+eval.o: $(hdrdir)/ruby/internal/compiler_since.h
+eval.o: $(hdrdir)/ruby/internal/config.h
+eval.o: $(hdrdir)/ruby/internal/constant_p.h
+eval.o: $(hdrdir)/ruby/internal/core.h
+eval.o: $(hdrdir)/ruby/internal/core/rarray.h
+eval.o: $(hdrdir)/ruby/internal/core/rbasic.h
+eval.o: $(hdrdir)/ruby/internal/core/rbignum.h
+eval.o: $(hdrdir)/ruby/internal/core/rclass.h
+eval.o: $(hdrdir)/ruby/internal/core/rdata.h
+eval.o: $(hdrdir)/ruby/internal/core/rfile.h
+eval.o: $(hdrdir)/ruby/internal/core/rhash.h
+eval.o: $(hdrdir)/ruby/internal/core/robject.h
+eval.o: $(hdrdir)/ruby/internal/core/rregexp.h
+eval.o: $(hdrdir)/ruby/internal/core/rstring.h
+eval.o: $(hdrdir)/ruby/internal/core/rstruct.h
+eval.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+eval.o: $(hdrdir)/ruby/internal/ctype.h
+eval.o: $(hdrdir)/ruby/internal/dllexport.h
+eval.o: $(hdrdir)/ruby/internal/dosish.h
+eval.o: $(hdrdir)/ruby/internal/error.h
+eval.o: $(hdrdir)/ruby/internal/eval.h
+eval.o: $(hdrdir)/ruby/internal/event.h
+eval.o: $(hdrdir)/ruby/internal/fl_type.h
+eval.o: $(hdrdir)/ruby/internal/gc.h
+eval.o: $(hdrdir)/ruby/internal/glob.h
+eval.o: $(hdrdir)/ruby/internal/globals.h
+eval.o: $(hdrdir)/ruby/internal/has/attribute.h
+eval.o: $(hdrdir)/ruby/internal/has/builtin.h
+eval.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+eval.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+eval.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+eval.o: $(hdrdir)/ruby/internal/has/extension.h
+eval.o: $(hdrdir)/ruby/internal/has/feature.h
+eval.o: $(hdrdir)/ruby/internal/has/warning.h
+eval.o: $(hdrdir)/ruby/internal/intern/array.h
+eval.o: $(hdrdir)/ruby/internal/intern/bignum.h
+eval.o: $(hdrdir)/ruby/internal/intern/class.h
+eval.o: $(hdrdir)/ruby/internal/intern/compar.h
+eval.o: $(hdrdir)/ruby/internal/intern/complex.h
+eval.o: $(hdrdir)/ruby/internal/intern/cont.h
+eval.o: $(hdrdir)/ruby/internal/intern/dir.h
+eval.o: $(hdrdir)/ruby/internal/intern/enum.h
+eval.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+eval.o: $(hdrdir)/ruby/internal/intern/error.h
+eval.o: $(hdrdir)/ruby/internal/intern/eval.h
+eval.o: $(hdrdir)/ruby/internal/intern/file.h
+eval.o: $(hdrdir)/ruby/internal/intern/hash.h
+eval.o: $(hdrdir)/ruby/internal/intern/io.h
+eval.o: $(hdrdir)/ruby/internal/intern/load.h
+eval.o: $(hdrdir)/ruby/internal/intern/marshal.h
+eval.o: $(hdrdir)/ruby/internal/intern/numeric.h
+eval.o: $(hdrdir)/ruby/internal/intern/object.h
+eval.o: $(hdrdir)/ruby/internal/intern/parse.h
+eval.o: $(hdrdir)/ruby/internal/intern/proc.h
+eval.o: $(hdrdir)/ruby/internal/intern/process.h
+eval.o: $(hdrdir)/ruby/internal/intern/random.h
+eval.o: $(hdrdir)/ruby/internal/intern/range.h
+eval.o: $(hdrdir)/ruby/internal/intern/rational.h
+eval.o: $(hdrdir)/ruby/internal/intern/re.h
+eval.o: $(hdrdir)/ruby/internal/intern/ruby.h
+eval.o: $(hdrdir)/ruby/internal/intern/select.h
+eval.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+eval.o: $(hdrdir)/ruby/internal/intern/set.h
+eval.o: $(hdrdir)/ruby/internal/intern/signal.h
+eval.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+eval.o: $(hdrdir)/ruby/internal/intern/string.h
+eval.o: $(hdrdir)/ruby/internal/intern/struct.h
+eval.o: $(hdrdir)/ruby/internal/intern/thread.h
+eval.o: $(hdrdir)/ruby/internal/intern/time.h
+eval.o: $(hdrdir)/ruby/internal/intern/variable.h
+eval.o: $(hdrdir)/ruby/internal/intern/vm.h
+eval.o: $(hdrdir)/ruby/internal/interpreter.h
+eval.o: $(hdrdir)/ruby/internal/iterator.h
+eval.o: $(hdrdir)/ruby/internal/memory.h
+eval.o: $(hdrdir)/ruby/internal/method.h
+eval.o: $(hdrdir)/ruby/internal/module.h
+eval.o: $(hdrdir)/ruby/internal/newobj.h
+eval.o: $(hdrdir)/ruby/internal/scan_args.h
+eval.o: $(hdrdir)/ruby/internal/special_consts.h
+eval.o: $(hdrdir)/ruby/internal/static_assert.h
+eval.o: $(hdrdir)/ruby/internal/stdalign.h
+eval.o: $(hdrdir)/ruby/internal/stdbool.h
+eval.o: $(hdrdir)/ruby/internal/stdckdint.h
+eval.o: $(hdrdir)/ruby/internal/symbol.h
+eval.o: $(hdrdir)/ruby/internal/value.h
+eval.o: $(hdrdir)/ruby/internal/value_type.h
+eval.o: $(hdrdir)/ruby/internal/variable.h
+eval.o: $(hdrdir)/ruby/internal/warning_push.h
+eval.o: $(hdrdir)/ruby/internal/xmalloc.h
+eval.o: $(hdrdir)/ruby/missing.h
+eval.o: $(hdrdir)/ruby/ruby.h
+eval.o: $(hdrdir)/ruby/st.h
+eval.o: $(hdrdir)/ruby/subst.h
+eval.o: eval.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/eval/eval.c b/ext/-test-/eval/eval.c
new file mode 100644
index 0000000000..983468fc34
--- /dev/null
+++ b/ext/-test-/eval/eval.c
@@ -0,0 +1,13 @@
+#include "ruby/ruby.h"
+
+static VALUE
+eval_string(VALUE self, VALUE str)
+{
+ return rb_eval_string(StringValueCStr(str));
+}
+
+void
+Init_eval(void)
+{
+ rb_define_global_function("rb_eval_string", eval_string, 1);
+}
diff --git a/ext/-test-/eval/extconf.rb b/ext/-test-/eval/extconf.rb
new file mode 100644
index 0000000000..cdbf6a8597
--- /dev/null
+++ b/ext/-test-/eval/extconf.rb
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile('-test-/eval')
diff --git a/ext/-test-/exception/dataerror.c b/ext/-test-/exception/dataerror.c
new file mode 100644
index 0000000000..d8beba8aa4
--- /dev/null
+++ b/ext/-test-/exception/dataerror.c
@@ -0,0 +1,31 @@
+#include <ruby/ruby.h>
+
+static void
+dataerror_mark(void *ptr)
+{
+ rb_gc_mark((VALUE)ptr);
+}
+
+static void
+dataerror_free(void *ptr)
+{
+}
+
+static const rb_data_type_t dataerror_type = {
+ "Bug #9167",
+ {dataerror_mark, dataerror_free},
+};
+
+static VALUE
+dataerror_alloc(VALUE klass)
+{
+ VALUE n = rb_str_new_cstr("[Bug #9167] error");
+ return TypedData_Wrap_Struct(klass, &dataerror_type, (void *)n);
+}
+
+void
+Init_dataerror(VALUE klass)
+{
+ VALUE rb_eDataErr = rb_define_class_under(klass, "DataError", rb_eStandardError);
+ rb_define_alloc_func(rb_eDataErr, dataerror_alloc);
+}
diff --git a/ext/-test-/exception/depend b/ext/-test-/exception/depend
new file mode 100644
index 0000000000..690e5ad377
--- /dev/null
+++ b/ext/-test-/exception/depend
@@ -0,0 +1,657 @@
+# AUTOGENERATED DEPENDENCIES START
+dataerror.o: $(RUBY_EXTCONF_H)
+dataerror.o: $(arch_hdrdir)/ruby/config.h
+dataerror.o: $(hdrdir)/ruby/assert.h
+dataerror.o: $(hdrdir)/ruby/backward.h
+dataerror.o: $(hdrdir)/ruby/backward/2/assume.h
+dataerror.o: $(hdrdir)/ruby/backward/2/attributes.h
+dataerror.o: $(hdrdir)/ruby/backward/2/bool.h
+dataerror.o: $(hdrdir)/ruby/backward/2/inttypes.h
+dataerror.o: $(hdrdir)/ruby/backward/2/limits.h
+dataerror.o: $(hdrdir)/ruby/backward/2/long_long.h
+dataerror.o: $(hdrdir)/ruby/backward/2/stdalign.h
+dataerror.o: $(hdrdir)/ruby/backward/2/stdarg.h
+dataerror.o: $(hdrdir)/ruby/defines.h
+dataerror.o: $(hdrdir)/ruby/intern.h
+dataerror.o: $(hdrdir)/ruby/internal/abi.h
+dataerror.o: $(hdrdir)/ruby/internal/anyargs.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+dataerror.o: $(hdrdir)/ruby/internal/assume.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/artificial.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/cold.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/const.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/error.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/format.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/noalias.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/noinline.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/pure.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/restrict.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/warning.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/weakref.h
+dataerror.o: $(hdrdir)/ruby/internal/cast.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_since.h
+dataerror.o: $(hdrdir)/ruby/internal/config.h
+dataerror.o: $(hdrdir)/ruby/internal/constant_p.h
+dataerror.o: $(hdrdir)/ruby/internal/core.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rarray.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rbasic.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rbignum.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rclass.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rdata.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rfile.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rhash.h
+dataerror.o: $(hdrdir)/ruby/internal/core/robject.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rregexp.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rstring.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rstruct.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+dataerror.o: $(hdrdir)/ruby/internal/ctype.h
+dataerror.o: $(hdrdir)/ruby/internal/dllexport.h
+dataerror.o: $(hdrdir)/ruby/internal/dosish.h
+dataerror.o: $(hdrdir)/ruby/internal/error.h
+dataerror.o: $(hdrdir)/ruby/internal/eval.h
+dataerror.o: $(hdrdir)/ruby/internal/event.h
+dataerror.o: $(hdrdir)/ruby/internal/fl_type.h
+dataerror.o: $(hdrdir)/ruby/internal/gc.h
+dataerror.o: $(hdrdir)/ruby/internal/glob.h
+dataerror.o: $(hdrdir)/ruby/internal/globals.h
+dataerror.o: $(hdrdir)/ruby/internal/has/attribute.h
+dataerror.o: $(hdrdir)/ruby/internal/has/builtin.h
+dataerror.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+dataerror.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+dataerror.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+dataerror.o: $(hdrdir)/ruby/internal/has/extension.h
+dataerror.o: $(hdrdir)/ruby/internal/has/feature.h
+dataerror.o: $(hdrdir)/ruby/internal/has/warning.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/array.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/bignum.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/class.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/compar.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/complex.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/cont.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/dir.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/enum.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/error.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/eval.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/file.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/hash.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/io.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/load.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/marshal.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/numeric.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/object.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/parse.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/proc.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/process.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/random.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/range.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/rational.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/re.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/ruby.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/select.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/set.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/signal.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/string.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/struct.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/thread.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/time.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/variable.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/vm.h
+dataerror.o: $(hdrdir)/ruby/internal/interpreter.h
+dataerror.o: $(hdrdir)/ruby/internal/iterator.h
+dataerror.o: $(hdrdir)/ruby/internal/memory.h
+dataerror.o: $(hdrdir)/ruby/internal/method.h
+dataerror.o: $(hdrdir)/ruby/internal/module.h
+dataerror.o: $(hdrdir)/ruby/internal/newobj.h
+dataerror.o: $(hdrdir)/ruby/internal/scan_args.h
+dataerror.o: $(hdrdir)/ruby/internal/special_consts.h
+dataerror.o: $(hdrdir)/ruby/internal/static_assert.h
+dataerror.o: $(hdrdir)/ruby/internal/stdalign.h
+dataerror.o: $(hdrdir)/ruby/internal/stdbool.h
+dataerror.o: $(hdrdir)/ruby/internal/stdckdint.h
+dataerror.o: $(hdrdir)/ruby/internal/symbol.h
+dataerror.o: $(hdrdir)/ruby/internal/value.h
+dataerror.o: $(hdrdir)/ruby/internal/value_type.h
+dataerror.o: $(hdrdir)/ruby/internal/variable.h
+dataerror.o: $(hdrdir)/ruby/internal/warning_push.h
+dataerror.o: $(hdrdir)/ruby/internal/xmalloc.h
+dataerror.o: $(hdrdir)/ruby/missing.h
+dataerror.o: $(hdrdir)/ruby/ruby.h
+dataerror.o: $(hdrdir)/ruby/st.h
+dataerror.o: $(hdrdir)/ruby/subst.h
+dataerror.o: dataerror.c
+enc_raise.o: $(RUBY_EXTCONF_H)
+enc_raise.o: $(arch_hdrdir)/ruby/config.h
+enc_raise.o: $(hdrdir)/ruby.h
+enc_raise.o: $(hdrdir)/ruby/assert.h
+enc_raise.o: $(hdrdir)/ruby/backward.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/assume.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/attributes.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/bool.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/inttypes.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/limits.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/long_long.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/stdalign.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/stdarg.h
+enc_raise.o: $(hdrdir)/ruby/defines.h
+enc_raise.o: $(hdrdir)/ruby/encoding.h
+enc_raise.o: $(hdrdir)/ruby/intern.h
+enc_raise.o: $(hdrdir)/ruby/internal/abi.h
+enc_raise.o: $(hdrdir)/ruby/internal/anyargs.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/assume.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/artificial.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/cold.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/const.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/error.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/format.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/noalias.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/noinline.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/pure.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/restrict.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/warning.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/weakref.h
+enc_raise.o: $(hdrdir)/ruby/internal/cast.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_since.h
+enc_raise.o: $(hdrdir)/ruby/internal/config.h
+enc_raise.o: $(hdrdir)/ruby/internal/constant_p.h
+enc_raise.o: $(hdrdir)/ruby/internal/core.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rarray.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rbasic.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rbignum.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rclass.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rdata.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rfile.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rhash.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/robject.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rregexp.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rstring.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rstruct.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+enc_raise.o: $(hdrdir)/ruby/internal/ctype.h
+enc_raise.o: $(hdrdir)/ruby/internal/dllexport.h
+enc_raise.o: $(hdrdir)/ruby/internal/dosish.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/re.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/string.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+enc_raise.o: $(hdrdir)/ruby/internal/error.h
+enc_raise.o: $(hdrdir)/ruby/internal/eval.h
+enc_raise.o: $(hdrdir)/ruby/internal/event.h
+enc_raise.o: $(hdrdir)/ruby/internal/fl_type.h
+enc_raise.o: $(hdrdir)/ruby/internal/gc.h
+enc_raise.o: $(hdrdir)/ruby/internal/glob.h
+enc_raise.o: $(hdrdir)/ruby/internal/globals.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/attribute.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/builtin.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/extension.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/feature.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/warning.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/array.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/bignum.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/class.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/compar.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/complex.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/cont.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/dir.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/enum.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/error.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/eval.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/file.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/hash.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/io.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/load.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/marshal.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/numeric.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/object.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/parse.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/proc.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/process.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/random.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/range.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/rational.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/re.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/ruby.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/select.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/set.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/signal.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/string.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/struct.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/thread.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/time.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/variable.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/vm.h
+enc_raise.o: $(hdrdir)/ruby/internal/interpreter.h
+enc_raise.o: $(hdrdir)/ruby/internal/iterator.h
+enc_raise.o: $(hdrdir)/ruby/internal/memory.h
+enc_raise.o: $(hdrdir)/ruby/internal/method.h
+enc_raise.o: $(hdrdir)/ruby/internal/module.h
+enc_raise.o: $(hdrdir)/ruby/internal/newobj.h
+enc_raise.o: $(hdrdir)/ruby/internal/scan_args.h
+enc_raise.o: $(hdrdir)/ruby/internal/special_consts.h
+enc_raise.o: $(hdrdir)/ruby/internal/static_assert.h
+enc_raise.o: $(hdrdir)/ruby/internal/stdalign.h
+enc_raise.o: $(hdrdir)/ruby/internal/stdbool.h
+enc_raise.o: $(hdrdir)/ruby/internal/stdckdint.h
+enc_raise.o: $(hdrdir)/ruby/internal/symbol.h
+enc_raise.o: $(hdrdir)/ruby/internal/value.h
+enc_raise.o: $(hdrdir)/ruby/internal/value_type.h
+enc_raise.o: $(hdrdir)/ruby/internal/variable.h
+enc_raise.o: $(hdrdir)/ruby/internal/warning_push.h
+enc_raise.o: $(hdrdir)/ruby/internal/xmalloc.h
+enc_raise.o: $(hdrdir)/ruby/missing.h
+enc_raise.o: $(hdrdir)/ruby/onigmo.h
+enc_raise.o: $(hdrdir)/ruby/oniguruma.h
+enc_raise.o: $(hdrdir)/ruby/ruby.h
+enc_raise.o: $(hdrdir)/ruby/st.h
+enc_raise.o: $(hdrdir)/ruby/subst.h
+enc_raise.o: enc_raise.c
+ensured.o: $(RUBY_EXTCONF_H)
+ensured.o: $(arch_hdrdir)/ruby/config.h
+ensured.o: $(hdrdir)/ruby.h
+ensured.o: $(hdrdir)/ruby/assert.h
+ensured.o: $(hdrdir)/ruby/backward.h
+ensured.o: $(hdrdir)/ruby/backward/2/assume.h
+ensured.o: $(hdrdir)/ruby/backward/2/attributes.h
+ensured.o: $(hdrdir)/ruby/backward/2/bool.h
+ensured.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ensured.o: $(hdrdir)/ruby/backward/2/limits.h
+ensured.o: $(hdrdir)/ruby/backward/2/long_long.h
+ensured.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ensured.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ensured.o: $(hdrdir)/ruby/defines.h
+ensured.o: $(hdrdir)/ruby/intern.h
+ensured.o: $(hdrdir)/ruby/internal/abi.h
+ensured.o: $(hdrdir)/ruby/internal/anyargs.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ensured.o: $(hdrdir)/ruby/internal/assume.h
+ensured.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ensured.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ensured.o: $(hdrdir)/ruby/internal/attr/cold.h
+ensured.o: $(hdrdir)/ruby/internal/attr/const.h
+ensured.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ensured.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ensured.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ensured.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ensured.o: $(hdrdir)/ruby/internal/attr/error.h
+ensured.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ensured.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ensured.o: $(hdrdir)/ruby/internal/attr/format.h
+ensured.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ensured.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ensured.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ensured.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ensured.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ensured.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ensured.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ensured.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ensured.o: $(hdrdir)/ruby/internal/attr/pure.h
+ensured.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ensured.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ensured.o: $(hdrdir)/ruby/internal/attr/warning.h
+ensured.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ensured.o: $(hdrdir)/ruby/internal/cast.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_since.h
+ensured.o: $(hdrdir)/ruby/internal/config.h
+ensured.o: $(hdrdir)/ruby/internal/constant_p.h
+ensured.o: $(hdrdir)/ruby/internal/core.h
+ensured.o: $(hdrdir)/ruby/internal/core/rarray.h
+ensured.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ensured.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ensured.o: $(hdrdir)/ruby/internal/core/rclass.h
+ensured.o: $(hdrdir)/ruby/internal/core/rdata.h
+ensured.o: $(hdrdir)/ruby/internal/core/rfile.h
+ensured.o: $(hdrdir)/ruby/internal/core/rhash.h
+ensured.o: $(hdrdir)/ruby/internal/core/robject.h
+ensured.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ensured.o: $(hdrdir)/ruby/internal/core/rstring.h
+ensured.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ensured.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ensured.o: $(hdrdir)/ruby/internal/ctype.h
+ensured.o: $(hdrdir)/ruby/internal/dllexport.h
+ensured.o: $(hdrdir)/ruby/internal/dosish.h
+ensured.o: $(hdrdir)/ruby/internal/error.h
+ensured.o: $(hdrdir)/ruby/internal/eval.h
+ensured.o: $(hdrdir)/ruby/internal/event.h
+ensured.o: $(hdrdir)/ruby/internal/fl_type.h
+ensured.o: $(hdrdir)/ruby/internal/gc.h
+ensured.o: $(hdrdir)/ruby/internal/glob.h
+ensured.o: $(hdrdir)/ruby/internal/globals.h
+ensured.o: $(hdrdir)/ruby/internal/has/attribute.h
+ensured.o: $(hdrdir)/ruby/internal/has/builtin.h
+ensured.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ensured.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ensured.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ensured.o: $(hdrdir)/ruby/internal/has/extension.h
+ensured.o: $(hdrdir)/ruby/internal/has/feature.h
+ensured.o: $(hdrdir)/ruby/internal/has/warning.h
+ensured.o: $(hdrdir)/ruby/internal/intern/array.h
+ensured.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ensured.o: $(hdrdir)/ruby/internal/intern/class.h
+ensured.o: $(hdrdir)/ruby/internal/intern/compar.h
+ensured.o: $(hdrdir)/ruby/internal/intern/complex.h
+ensured.o: $(hdrdir)/ruby/internal/intern/cont.h
+ensured.o: $(hdrdir)/ruby/internal/intern/dir.h
+ensured.o: $(hdrdir)/ruby/internal/intern/enum.h
+ensured.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ensured.o: $(hdrdir)/ruby/internal/intern/error.h
+ensured.o: $(hdrdir)/ruby/internal/intern/eval.h
+ensured.o: $(hdrdir)/ruby/internal/intern/file.h
+ensured.o: $(hdrdir)/ruby/internal/intern/hash.h
+ensured.o: $(hdrdir)/ruby/internal/intern/io.h
+ensured.o: $(hdrdir)/ruby/internal/intern/load.h
+ensured.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ensured.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ensured.o: $(hdrdir)/ruby/internal/intern/object.h
+ensured.o: $(hdrdir)/ruby/internal/intern/parse.h
+ensured.o: $(hdrdir)/ruby/internal/intern/proc.h
+ensured.o: $(hdrdir)/ruby/internal/intern/process.h
+ensured.o: $(hdrdir)/ruby/internal/intern/random.h
+ensured.o: $(hdrdir)/ruby/internal/intern/range.h
+ensured.o: $(hdrdir)/ruby/internal/intern/rational.h
+ensured.o: $(hdrdir)/ruby/internal/intern/re.h
+ensured.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ensured.o: $(hdrdir)/ruby/internal/intern/select.h
+ensured.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ensured.o: $(hdrdir)/ruby/internal/intern/set.h
+ensured.o: $(hdrdir)/ruby/internal/intern/signal.h
+ensured.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ensured.o: $(hdrdir)/ruby/internal/intern/string.h
+ensured.o: $(hdrdir)/ruby/internal/intern/struct.h
+ensured.o: $(hdrdir)/ruby/internal/intern/thread.h
+ensured.o: $(hdrdir)/ruby/internal/intern/time.h
+ensured.o: $(hdrdir)/ruby/internal/intern/variable.h
+ensured.o: $(hdrdir)/ruby/internal/intern/vm.h
+ensured.o: $(hdrdir)/ruby/internal/interpreter.h
+ensured.o: $(hdrdir)/ruby/internal/iterator.h
+ensured.o: $(hdrdir)/ruby/internal/memory.h
+ensured.o: $(hdrdir)/ruby/internal/method.h
+ensured.o: $(hdrdir)/ruby/internal/module.h
+ensured.o: $(hdrdir)/ruby/internal/newobj.h
+ensured.o: $(hdrdir)/ruby/internal/scan_args.h
+ensured.o: $(hdrdir)/ruby/internal/special_consts.h
+ensured.o: $(hdrdir)/ruby/internal/static_assert.h
+ensured.o: $(hdrdir)/ruby/internal/stdalign.h
+ensured.o: $(hdrdir)/ruby/internal/stdbool.h
+ensured.o: $(hdrdir)/ruby/internal/stdckdint.h
+ensured.o: $(hdrdir)/ruby/internal/symbol.h
+ensured.o: $(hdrdir)/ruby/internal/value.h
+ensured.o: $(hdrdir)/ruby/internal/value_type.h
+ensured.o: $(hdrdir)/ruby/internal/variable.h
+ensured.o: $(hdrdir)/ruby/internal/warning_push.h
+ensured.o: $(hdrdir)/ruby/internal/xmalloc.h
+ensured.o: $(hdrdir)/ruby/missing.h
+ensured.o: $(hdrdir)/ruby/ruby.h
+ensured.o: $(hdrdir)/ruby/st.h
+ensured.o: $(hdrdir)/ruby/subst.h
+ensured.o: ensured.c
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/exception/enc_raise.c b/ext/-test-/exception/enc_raise.c
new file mode 100644
index 0000000000..68d7b4ebc1
--- /dev/null
+++ b/ext/-test-/exception/enc_raise.c
@@ -0,0 +1,15 @@
+#include <ruby.h>
+#include <ruby/encoding.h>
+
+static VALUE
+enc_raise(VALUE exc, VALUE encoding, VALUE mesg)
+{
+ rb_enc_raise(rb_to_encoding(encoding), exc, "%s", StringValueCStr(mesg));
+ UNREACHABLE_RETURN(Qnil);
+}
+
+void
+Init_enc_raise(VALUE klass)
+{
+ rb_define_module_function(klass, "enc_raise", enc_raise, 2);
+}
diff --git a/ext/-test-/exception/ensured.c b/ext/-test-/exception/ensured.c
new file mode 100644
index 0000000000..7dcc9b78ef
--- /dev/null
+++ b/ext/-test-/exception/ensured.c
@@ -0,0 +1,39 @@
+#include <ruby.h>
+
+static VALUE
+begin(VALUE object)
+{
+ return rb_funcall(object, rb_intern("try_method"), 0);
+}
+
+static VALUE
+ensure(VALUE object)
+{
+ return rb_funcall(object, rb_intern("ensured_method"), 0);
+}
+
+static VALUE
+ensured(VALUE module, VALUE object)
+{
+ return rb_ensure(begin, object, ensure, object);
+}
+
+static VALUE
+exc_raise(VALUE exc)
+{
+ rb_exc_raise(exc);
+ return Qnil;
+}
+
+static VALUE
+ensure_raise(VALUE module, VALUE object, VALUE exc)
+{
+ return rb_ensure(rb_yield, object, exc_raise, exc);
+}
+
+void
+Init_ensured(VALUE klass)
+{
+ rb_define_module_function(klass, "ensured", ensured, 1);
+ rb_define_module_function(klass, "ensure_raise", ensure_raise, 2);
+}
diff --git a/ext/-test-/exception/extconf.rb b/ext/-test-/exception/extconf.rb
new file mode 100644
index 0000000000..ca51178a18
--- /dev/null
+++ b/ext/-test-/exception/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext
diff --git a/ext/-test-/exception/init.c b/ext/-test-/exception/init.c
new file mode 100644
index 0000000000..853bb68f79
--- /dev/null
+++ b/ext/-test-/exception/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_exception(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "Exception", rb_eStandardError);
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/fatal/depend b/ext/-test-/fatal/depend
new file mode 100644
index 0000000000..306bc9099c
--- /dev/null
+++ b/ext/-test-/fatal/depend
@@ -0,0 +1,486 @@
+# AUTOGENERATED DEPENDENCIES START
+
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+invalid.o: $(RUBY_EXTCONF_H)
+invalid.o: $(arch_hdrdir)/ruby/config.h
+invalid.o: $(hdrdir)/ruby.h
+invalid.o: $(hdrdir)/ruby/assert.h
+invalid.o: $(hdrdir)/ruby/backward.h
+invalid.o: $(hdrdir)/ruby/backward/2/assume.h
+invalid.o: $(hdrdir)/ruby/backward/2/attributes.h
+invalid.o: $(hdrdir)/ruby/backward/2/bool.h
+invalid.o: $(hdrdir)/ruby/backward/2/inttypes.h
+invalid.o: $(hdrdir)/ruby/backward/2/limits.h
+invalid.o: $(hdrdir)/ruby/backward/2/long_long.h
+invalid.o: $(hdrdir)/ruby/backward/2/stdalign.h
+invalid.o: $(hdrdir)/ruby/backward/2/stdarg.h
+invalid.o: $(hdrdir)/ruby/defines.h
+invalid.o: $(hdrdir)/ruby/intern.h
+invalid.o: $(hdrdir)/ruby/internal/abi.h
+invalid.o: $(hdrdir)/ruby/internal/anyargs.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+invalid.o: $(hdrdir)/ruby/internal/assume.h
+invalid.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+invalid.o: $(hdrdir)/ruby/internal/attr/artificial.h
+invalid.o: $(hdrdir)/ruby/internal/attr/cold.h
+invalid.o: $(hdrdir)/ruby/internal/attr/const.h
+invalid.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+invalid.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+invalid.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+invalid.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+invalid.o: $(hdrdir)/ruby/internal/attr/error.h
+invalid.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+invalid.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+invalid.o: $(hdrdir)/ruby/internal/attr/format.h
+invalid.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+invalid.o: $(hdrdir)/ruby/internal/attr/noalias.h
+invalid.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+invalid.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+invalid.o: $(hdrdir)/ruby/internal/attr/noinline.h
+invalid.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+invalid.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+invalid.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+invalid.o: $(hdrdir)/ruby/internal/attr/pure.h
+invalid.o: $(hdrdir)/ruby/internal/attr/restrict.h
+invalid.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+invalid.o: $(hdrdir)/ruby/internal/attr/warning.h
+invalid.o: $(hdrdir)/ruby/internal/attr/weakref.h
+invalid.o: $(hdrdir)/ruby/internal/cast.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_since.h
+invalid.o: $(hdrdir)/ruby/internal/config.h
+invalid.o: $(hdrdir)/ruby/internal/constant_p.h
+invalid.o: $(hdrdir)/ruby/internal/core.h
+invalid.o: $(hdrdir)/ruby/internal/core/rarray.h
+invalid.o: $(hdrdir)/ruby/internal/core/rbasic.h
+invalid.o: $(hdrdir)/ruby/internal/core/rbignum.h
+invalid.o: $(hdrdir)/ruby/internal/core/rclass.h
+invalid.o: $(hdrdir)/ruby/internal/core/rdata.h
+invalid.o: $(hdrdir)/ruby/internal/core/rfile.h
+invalid.o: $(hdrdir)/ruby/internal/core/rhash.h
+invalid.o: $(hdrdir)/ruby/internal/core/robject.h
+invalid.o: $(hdrdir)/ruby/internal/core/rregexp.h
+invalid.o: $(hdrdir)/ruby/internal/core/rstring.h
+invalid.o: $(hdrdir)/ruby/internal/core/rstruct.h
+invalid.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+invalid.o: $(hdrdir)/ruby/internal/ctype.h
+invalid.o: $(hdrdir)/ruby/internal/dllexport.h
+invalid.o: $(hdrdir)/ruby/internal/dosish.h
+invalid.o: $(hdrdir)/ruby/internal/error.h
+invalid.o: $(hdrdir)/ruby/internal/eval.h
+invalid.o: $(hdrdir)/ruby/internal/event.h
+invalid.o: $(hdrdir)/ruby/internal/fl_type.h
+invalid.o: $(hdrdir)/ruby/internal/gc.h
+invalid.o: $(hdrdir)/ruby/internal/glob.h
+invalid.o: $(hdrdir)/ruby/internal/globals.h
+invalid.o: $(hdrdir)/ruby/internal/has/attribute.h
+invalid.o: $(hdrdir)/ruby/internal/has/builtin.h
+invalid.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+invalid.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+invalid.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+invalid.o: $(hdrdir)/ruby/internal/has/extension.h
+invalid.o: $(hdrdir)/ruby/internal/has/feature.h
+invalid.o: $(hdrdir)/ruby/internal/has/warning.h
+invalid.o: $(hdrdir)/ruby/internal/intern/array.h
+invalid.o: $(hdrdir)/ruby/internal/intern/bignum.h
+invalid.o: $(hdrdir)/ruby/internal/intern/class.h
+invalid.o: $(hdrdir)/ruby/internal/intern/compar.h
+invalid.o: $(hdrdir)/ruby/internal/intern/complex.h
+invalid.o: $(hdrdir)/ruby/internal/intern/cont.h
+invalid.o: $(hdrdir)/ruby/internal/intern/dir.h
+invalid.o: $(hdrdir)/ruby/internal/intern/enum.h
+invalid.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+invalid.o: $(hdrdir)/ruby/internal/intern/error.h
+invalid.o: $(hdrdir)/ruby/internal/intern/eval.h
+invalid.o: $(hdrdir)/ruby/internal/intern/file.h
+invalid.o: $(hdrdir)/ruby/internal/intern/hash.h
+invalid.o: $(hdrdir)/ruby/internal/intern/io.h
+invalid.o: $(hdrdir)/ruby/internal/intern/load.h
+invalid.o: $(hdrdir)/ruby/internal/intern/marshal.h
+invalid.o: $(hdrdir)/ruby/internal/intern/numeric.h
+invalid.o: $(hdrdir)/ruby/internal/intern/object.h
+invalid.o: $(hdrdir)/ruby/internal/intern/parse.h
+invalid.o: $(hdrdir)/ruby/internal/intern/proc.h
+invalid.o: $(hdrdir)/ruby/internal/intern/process.h
+invalid.o: $(hdrdir)/ruby/internal/intern/random.h
+invalid.o: $(hdrdir)/ruby/internal/intern/range.h
+invalid.o: $(hdrdir)/ruby/internal/intern/rational.h
+invalid.o: $(hdrdir)/ruby/internal/intern/re.h
+invalid.o: $(hdrdir)/ruby/internal/intern/ruby.h
+invalid.o: $(hdrdir)/ruby/internal/intern/select.h
+invalid.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+invalid.o: $(hdrdir)/ruby/internal/intern/set.h
+invalid.o: $(hdrdir)/ruby/internal/intern/signal.h
+invalid.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+invalid.o: $(hdrdir)/ruby/internal/intern/string.h
+invalid.o: $(hdrdir)/ruby/internal/intern/struct.h
+invalid.o: $(hdrdir)/ruby/internal/intern/thread.h
+invalid.o: $(hdrdir)/ruby/internal/intern/time.h
+invalid.o: $(hdrdir)/ruby/internal/intern/variable.h
+invalid.o: $(hdrdir)/ruby/internal/intern/vm.h
+invalid.o: $(hdrdir)/ruby/internal/interpreter.h
+invalid.o: $(hdrdir)/ruby/internal/iterator.h
+invalid.o: $(hdrdir)/ruby/internal/memory.h
+invalid.o: $(hdrdir)/ruby/internal/method.h
+invalid.o: $(hdrdir)/ruby/internal/module.h
+invalid.o: $(hdrdir)/ruby/internal/newobj.h
+invalid.o: $(hdrdir)/ruby/internal/scan_args.h
+invalid.o: $(hdrdir)/ruby/internal/special_consts.h
+invalid.o: $(hdrdir)/ruby/internal/static_assert.h
+invalid.o: $(hdrdir)/ruby/internal/stdalign.h
+invalid.o: $(hdrdir)/ruby/internal/stdbool.h
+invalid.o: $(hdrdir)/ruby/internal/stdckdint.h
+invalid.o: $(hdrdir)/ruby/internal/symbol.h
+invalid.o: $(hdrdir)/ruby/internal/value.h
+invalid.o: $(hdrdir)/ruby/internal/value_type.h
+invalid.o: $(hdrdir)/ruby/internal/variable.h
+invalid.o: $(hdrdir)/ruby/internal/warning_push.h
+invalid.o: $(hdrdir)/ruby/internal/xmalloc.h
+invalid.o: $(hdrdir)/ruby/missing.h
+invalid.o: $(hdrdir)/ruby/ruby.h
+invalid.o: $(hdrdir)/ruby/st.h
+invalid.o: $(hdrdir)/ruby/subst.h
+invalid.o: invalid.c
+rb_fatal.o: $(RUBY_EXTCONF_H)
+rb_fatal.o: $(arch_hdrdir)/ruby/config.h
+rb_fatal.o: $(hdrdir)/ruby.h
+rb_fatal.o: $(hdrdir)/ruby/assert.h
+rb_fatal.o: $(hdrdir)/ruby/backward.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/assume.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/attributes.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/bool.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/limits.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/long_long.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/stdarg.h
+rb_fatal.o: $(hdrdir)/ruby/defines.h
+rb_fatal.o: $(hdrdir)/ruby/intern.h
+rb_fatal.o: $(hdrdir)/ruby/internal/abi.h
+rb_fatal.o: $(hdrdir)/ruby/internal/anyargs.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/assume.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/cold.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/const.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/error.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/format.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/pure.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/warning.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rb_fatal.o: $(hdrdir)/ruby/internal/cast.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_since.h
+rb_fatal.o: $(hdrdir)/ruby/internal/config.h
+rb_fatal.o: $(hdrdir)/ruby/internal/constant_p.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rarray.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rclass.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rdata.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rfile.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rhash.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/robject.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rstring.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rb_fatal.o: $(hdrdir)/ruby/internal/ctype.h
+rb_fatal.o: $(hdrdir)/ruby/internal/dllexport.h
+rb_fatal.o: $(hdrdir)/ruby/internal/dosish.h
+rb_fatal.o: $(hdrdir)/ruby/internal/error.h
+rb_fatal.o: $(hdrdir)/ruby/internal/eval.h
+rb_fatal.o: $(hdrdir)/ruby/internal/event.h
+rb_fatal.o: $(hdrdir)/ruby/internal/fl_type.h
+rb_fatal.o: $(hdrdir)/ruby/internal/gc.h
+rb_fatal.o: $(hdrdir)/ruby/internal/glob.h
+rb_fatal.o: $(hdrdir)/ruby/internal/globals.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/attribute.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/builtin.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/extension.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/feature.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/warning.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/array.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/class.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/compar.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/complex.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/cont.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/dir.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/enum.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/error.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/eval.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/file.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/hash.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/io.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/load.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/object.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/parse.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/proc.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/process.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/random.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/range.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/rational.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/re.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/select.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/set.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/signal.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/string.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/struct.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/thread.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/time.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/variable.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/vm.h
+rb_fatal.o: $(hdrdir)/ruby/internal/interpreter.h
+rb_fatal.o: $(hdrdir)/ruby/internal/iterator.h
+rb_fatal.o: $(hdrdir)/ruby/internal/memory.h
+rb_fatal.o: $(hdrdir)/ruby/internal/method.h
+rb_fatal.o: $(hdrdir)/ruby/internal/module.h
+rb_fatal.o: $(hdrdir)/ruby/internal/newobj.h
+rb_fatal.o: $(hdrdir)/ruby/internal/scan_args.h
+rb_fatal.o: $(hdrdir)/ruby/internal/special_consts.h
+rb_fatal.o: $(hdrdir)/ruby/internal/static_assert.h
+rb_fatal.o: $(hdrdir)/ruby/internal/stdalign.h
+rb_fatal.o: $(hdrdir)/ruby/internal/stdbool.h
+rb_fatal.o: $(hdrdir)/ruby/internal/stdckdint.h
+rb_fatal.o: $(hdrdir)/ruby/internal/symbol.h
+rb_fatal.o: $(hdrdir)/ruby/internal/value.h
+rb_fatal.o: $(hdrdir)/ruby/internal/value_type.h
+rb_fatal.o: $(hdrdir)/ruby/internal/variable.h
+rb_fatal.o: $(hdrdir)/ruby/internal/warning_push.h
+rb_fatal.o: $(hdrdir)/ruby/internal/xmalloc.h
+rb_fatal.o: $(hdrdir)/ruby/missing.h
+rb_fatal.o: $(hdrdir)/ruby/ruby.h
+rb_fatal.o: $(hdrdir)/ruby/st.h
+rb_fatal.o: $(hdrdir)/ruby/subst.h
+rb_fatal.o: rb_fatal.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/fatal/extconf.rb b/ext/-test-/fatal/extconf.rb
new file mode 100644
index 0000000000..ca51178a18
--- /dev/null
+++ b/ext/-test-/fatal/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext
diff --git a/ext/-test-/fatal/init.c b/ext/-test-/fatal/init.c
new file mode 100644
index 0000000000..3b71708789
--- /dev/null
+++ b/ext/-test-/fatal/init.c
@@ -0,0 +1,10 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_fatal(void)
+{
+ VALUE klass = rb_define_module("Bug");
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/fatal/invalid.c b/ext/-test-/fatal/invalid.c
new file mode 100644
index 0000000000..6fd970b181
--- /dev/null
+++ b/ext/-test-/fatal/invalid.c
@@ -0,0 +1,22 @@
+#include <ruby.h>
+
+static VALUE
+invalid_call(VALUE obj, VALUE address)
+{
+ typedef VALUE (*func_type)(VALUE);
+
+ return (*(func_type)NUM2PTR(address))(obj);
+}
+
+static VALUE
+invalid_access(VALUE obj, VALUE address)
+{
+ return *(VALUE *)NUM2PTR(address) == obj ? Qtrue : Qfalse;
+}
+
+void
+Init_invalid(VALUE mBug)
+{
+ rb_define_singleton_method(mBug, "invalid_call", invalid_call, 1);
+ rb_define_singleton_method(mBug, "invalid_access", invalid_access, 1);
+}
diff --git a/ext/-test-/fatal/rb_fatal.c b/ext/-test-/fatal/rb_fatal.c
new file mode 100644
index 0000000000..6c7bb89628
--- /dev/null
+++ b/ext/-test-/fatal/rb_fatal.c
@@ -0,0 +1,19 @@
+#include <ruby.h>
+
+static VALUE
+ruby_fatal(VALUE obj, VALUE msg)
+{
+ const char *cmsg = NULL;
+
+ (void)obj;
+
+ cmsg = RSTRING_PTR(msg);
+ rb_fatal("%s", cmsg);
+ return 0; /* never reached */
+}
+
+void
+Init_rb_fatal(VALUE mBug)
+{
+ rb_define_singleton_method(mBug, "rb_fatal", ruby_fatal, 1);
+}
diff --git a/ext/-test-/file/depend b/ext/-test-/file/depend
new file mode 100644
index 0000000000..fe320f3d44
--- /dev/null
+++ b/ext/-test-/file/depend
@@ -0,0 +1,682 @@
+# AUTOGENERATED DEPENDENCIES START
+fs.o: $(RUBY_EXTCONF_H)
+fs.o: $(arch_hdrdir)/ruby/config.h
+fs.o: $(hdrdir)/ruby/assert.h
+fs.o: $(hdrdir)/ruby/backward.h
+fs.o: $(hdrdir)/ruby/backward/2/assume.h
+fs.o: $(hdrdir)/ruby/backward/2/attributes.h
+fs.o: $(hdrdir)/ruby/backward/2/bool.h
+fs.o: $(hdrdir)/ruby/backward/2/inttypes.h
+fs.o: $(hdrdir)/ruby/backward/2/limits.h
+fs.o: $(hdrdir)/ruby/backward/2/long_long.h
+fs.o: $(hdrdir)/ruby/backward/2/stdalign.h
+fs.o: $(hdrdir)/ruby/backward/2/stdarg.h
+fs.o: $(hdrdir)/ruby/defines.h
+fs.o: $(hdrdir)/ruby/encoding.h
+fs.o: $(hdrdir)/ruby/intern.h
+fs.o: $(hdrdir)/ruby/internal/abi.h
+fs.o: $(hdrdir)/ruby/internal/anyargs.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+fs.o: $(hdrdir)/ruby/internal/assume.h
+fs.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+fs.o: $(hdrdir)/ruby/internal/attr/artificial.h
+fs.o: $(hdrdir)/ruby/internal/attr/cold.h
+fs.o: $(hdrdir)/ruby/internal/attr/const.h
+fs.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+fs.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+fs.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+fs.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+fs.o: $(hdrdir)/ruby/internal/attr/error.h
+fs.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+fs.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+fs.o: $(hdrdir)/ruby/internal/attr/format.h
+fs.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+fs.o: $(hdrdir)/ruby/internal/attr/noalias.h
+fs.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+fs.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+fs.o: $(hdrdir)/ruby/internal/attr/noinline.h
+fs.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+fs.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+fs.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+fs.o: $(hdrdir)/ruby/internal/attr/pure.h
+fs.o: $(hdrdir)/ruby/internal/attr/restrict.h
+fs.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+fs.o: $(hdrdir)/ruby/internal/attr/warning.h
+fs.o: $(hdrdir)/ruby/internal/attr/weakref.h
+fs.o: $(hdrdir)/ruby/internal/cast.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+fs.o: $(hdrdir)/ruby/internal/compiler_since.h
+fs.o: $(hdrdir)/ruby/internal/config.h
+fs.o: $(hdrdir)/ruby/internal/constant_p.h
+fs.o: $(hdrdir)/ruby/internal/core.h
+fs.o: $(hdrdir)/ruby/internal/core/rarray.h
+fs.o: $(hdrdir)/ruby/internal/core/rbasic.h
+fs.o: $(hdrdir)/ruby/internal/core/rbignum.h
+fs.o: $(hdrdir)/ruby/internal/core/rclass.h
+fs.o: $(hdrdir)/ruby/internal/core/rdata.h
+fs.o: $(hdrdir)/ruby/internal/core/rfile.h
+fs.o: $(hdrdir)/ruby/internal/core/rhash.h
+fs.o: $(hdrdir)/ruby/internal/core/robject.h
+fs.o: $(hdrdir)/ruby/internal/core/rregexp.h
+fs.o: $(hdrdir)/ruby/internal/core/rstring.h
+fs.o: $(hdrdir)/ruby/internal/core/rstruct.h
+fs.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+fs.o: $(hdrdir)/ruby/internal/ctype.h
+fs.o: $(hdrdir)/ruby/internal/dllexport.h
+fs.o: $(hdrdir)/ruby/internal/dosish.h
+fs.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+fs.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+fs.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+fs.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+fs.o: $(hdrdir)/ruby/internal/encoding/re.h
+fs.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+fs.o: $(hdrdir)/ruby/internal/encoding/string.h
+fs.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+fs.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+fs.o: $(hdrdir)/ruby/internal/error.h
+fs.o: $(hdrdir)/ruby/internal/eval.h
+fs.o: $(hdrdir)/ruby/internal/event.h
+fs.o: $(hdrdir)/ruby/internal/fl_type.h
+fs.o: $(hdrdir)/ruby/internal/gc.h
+fs.o: $(hdrdir)/ruby/internal/glob.h
+fs.o: $(hdrdir)/ruby/internal/globals.h
+fs.o: $(hdrdir)/ruby/internal/has/attribute.h
+fs.o: $(hdrdir)/ruby/internal/has/builtin.h
+fs.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+fs.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+fs.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+fs.o: $(hdrdir)/ruby/internal/has/extension.h
+fs.o: $(hdrdir)/ruby/internal/has/feature.h
+fs.o: $(hdrdir)/ruby/internal/has/warning.h
+fs.o: $(hdrdir)/ruby/internal/intern/array.h
+fs.o: $(hdrdir)/ruby/internal/intern/bignum.h
+fs.o: $(hdrdir)/ruby/internal/intern/class.h
+fs.o: $(hdrdir)/ruby/internal/intern/compar.h
+fs.o: $(hdrdir)/ruby/internal/intern/complex.h
+fs.o: $(hdrdir)/ruby/internal/intern/cont.h
+fs.o: $(hdrdir)/ruby/internal/intern/dir.h
+fs.o: $(hdrdir)/ruby/internal/intern/enum.h
+fs.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+fs.o: $(hdrdir)/ruby/internal/intern/error.h
+fs.o: $(hdrdir)/ruby/internal/intern/eval.h
+fs.o: $(hdrdir)/ruby/internal/intern/file.h
+fs.o: $(hdrdir)/ruby/internal/intern/hash.h
+fs.o: $(hdrdir)/ruby/internal/intern/io.h
+fs.o: $(hdrdir)/ruby/internal/intern/load.h
+fs.o: $(hdrdir)/ruby/internal/intern/marshal.h
+fs.o: $(hdrdir)/ruby/internal/intern/numeric.h
+fs.o: $(hdrdir)/ruby/internal/intern/object.h
+fs.o: $(hdrdir)/ruby/internal/intern/parse.h
+fs.o: $(hdrdir)/ruby/internal/intern/proc.h
+fs.o: $(hdrdir)/ruby/internal/intern/process.h
+fs.o: $(hdrdir)/ruby/internal/intern/random.h
+fs.o: $(hdrdir)/ruby/internal/intern/range.h
+fs.o: $(hdrdir)/ruby/internal/intern/rational.h
+fs.o: $(hdrdir)/ruby/internal/intern/re.h
+fs.o: $(hdrdir)/ruby/internal/intern/ruby.h
+fs.o: $(hdrdir)/ruby/internal/intern/select.h
+fs.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+fs.o: $(hdrdir)/ruby/internal/intern/set.h
+fs.o: $(hdrdir)/ruby/internal/intern/signal.h
+fs.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+fs.o: $(hdrdir)/ruby/internal/intern/string.h
+fs.o: $(hdrdir)/ruby/internal/intern/struct.h
+fs.o: $(hdrdir)/ruby/internal/intern/thread.h
+fs.o: $(hdrdir)/ruby/internal/intern/time.h
+fs.o: $(hdrdir)/ruby/internal/intern/variable.h
+fs.o: $(hdrdir)/ruby/internal/intern/vm.h
+fs.o: $(hdrdir)/ruby/internal/interpreter.h
+fs.o: $(hdrdir)/ruby/internal/iterator.h
+fs.o: $(hdrdir)/ruby/internal/memory.h
+fs.o: $(hdrdir)/ruby/internal/method.h
+fs.o: $(hdrdir)/ruby/internal/module.h
+fs.o: $(hdrdir)/ruby/internal/newobj.h
+fs.o: $(hdrdir)/ruby/internal/scan_args.h
+fs.o: $(hdrdir)/ruby/internal/special_consts.h
+fs.o: $(hdrdir)/ruby/internal/static_assert.h
+fs.o: $(hdrdir)/ruby/internal/stdalign.h
+fs.o: $(hdrdir)/ruby/internal/stdbool.h
+fs.o: $(hdrdir)/ruby/internal/stdckdint.h
+fs.o: $(hdrdir)/ruby/internal/symbol.h
+fs.o: $(hdrdir)/ruby/internal/value.h
+fs.o: $(hdrdir)/ruby/internal/value_type.h
+fs.o: $(hdrdir)/ruby/internal/variable.h
+fs.o: $(hdrdir)/ruby/internal/warning_push.h
+fs.o: $(hdrdir)/ruby/internal/xmalloc.h
+fs.o: $(hdrdir)/ruby/io.h
+fs.o: $(hdrdir)/ruby/missing.h
+fs.o: $(hdrdir)/ruby/onigmo.h
+fs.o: $(hdrdir)/ruby/oniguruma.h
+fs.o: $(hdrdir)/ruby/ruby.h
+fs.o: $(hdrdir)/ruby/st.h
+fs.o: $(hdrdir)/ruby/subst.h
+fs.o: fs.c
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+newline_conv.o: $(RUBY_EXTCONF_H)
+newline_conv.o: $(arch_hdrdir)/ruby/config.h
+newline_conv.o: $(hdrdir)/ruby/assert.h
+newline_conv.o: $(hdrdir)/ruby/backward.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/assume.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/attributes.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/bool.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/inttypes.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/limits.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/long_long.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/stdalign.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/stdarg.h
+newline_conv.o: $(hdrdir)/ruby/defines.h
+newline_conv.o: $(hdrdir)/ruby/encoding.h
+newline_conv.o: $(hdrdir)/ruby/intern.h
+newline_conv.o: $(hdrdir)/ruby/internal/abi.h
+newline_conv.o: $(hdrdir)/ruby/internal/anyargs.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/assume.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/artificial.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/cold.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/const.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/error.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/format.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/noalias.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/noinline.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/pure.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/restrict.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/warning.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/weakref.h
+newline_conv.o: $(hdrdir)/ruby/internal/cast.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_since.h
+newline_conv.o: $(hdrdir)/ruby/internal/config.h
+newline_conv.o: $(hdrdir)/ruby/internal/constant_p.h
+newline_conv.o: $(hdrdir)/ruby/internal/core.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rarray.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rbasic.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rbignum.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rclass.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rdata.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rfile.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rhash.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/robject.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rregexp.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rstring.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rstruct.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+newline_conv.o: $(hdrdir)/ruby/internal/ctype.h
+newline_conv.o: $(hdrdir)/ruby/internal/dllexport.h
+newline_conv.o: $(hdrdir)/ruby/internal/dosish.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/re.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/string.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+newline_conv.o: $(hdrdir)/ruby/internal/error.h
+newline_conv.o: $(hdrdir)/ruby/internal/eval.h
+newline_conv.o: $(hdrdir)/ruby/internal/event.h
+newline_conv.o: $(hdrdir)/ruby/internal/fl_type.h
+newline_conv.o: $(hdrdir)/ruby/internal/gc.h
+newline_conv.o: $(hdrdir)/ruby/internal/glob.h
+newline_conv.o: $(hdrdir)/ruby/internal/globals.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/attribute.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/builtin.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/extension.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/feature.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/warning.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/array.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/bignum.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/class.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/compar.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/complex.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/cont.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/dir.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/enum.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/error.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/eval.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/file.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/hash.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/io.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/load.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/marshal.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/numeric.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/object.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/parse.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/proc.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/process.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/random.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/range.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/rational.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/re.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/ruby.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/select.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/set.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/signal.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/string.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/struct.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/thread.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/time.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/variable.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/vm.h
+newline_conv.o: $(hdrdir)/ruby/internal/interpreter.h
+newline_conv.o: $(hdrdir)/ruby/internal/iterator.h
+newline_conv.o: $(hdrdir)/ruby/internal/memory.h
+newline_conv.o: $(hdrdir)/ruby/internal/method.h
+newline_conv.o: $(hdrdir)/ruby/internal/module.h
+newline_conv.o: $(hdrdir)/ruby/internal/newobj.h
+newline_conv.o: $(hdrdir)/ruby/internal/scan_args.h
+newline_conv.o: $(hdrdir)/ruby/internal/special_consts.h
+newline_conv.o: $(hdrdir)/ruby/internal/static_assert.h
+newline_conv.o: $(hdrdir)/ruby/internal/stdalign.h
+newline_conv.o: $(hdrdir)/ruby/internal/stdbool.h
+newline_conv.o: $(hdrdir)/ruby/internal/stdckdint.h
+newline_conv.o: $(hdrdir)/ruby/internal/symbol.h
+newline_conv.o: $(hdrdir)/ruby/internal/value.h
+newline_conv.o: $(hdrdir)/ruby/internal/value_type.h
+newline_conv.o: $(hdrdir)/ruby/internal/variable.h
+newline_conv.o: $(hdrdir)/ruby/internal/warning_push.h
+newline_conv.o: $(hdrdir)/ruby/internal/xmalloc.h
+newline_conv.o: $(hdrdir)/ruby/io.h
+newline_conv.o: $(hdrdir)/ruby/missing.h
+newline_conv.o: $(hdrdir)/ruby/onigmo.h
+newline_conv.o: $(hdrdir)/ruby/oniguruma.h
+newline_conv.o: $(hdrdir)/ruby/ruby.h
+newline_conv.o: $(hdrdir)/ruby/st.h
+newline_conv.o: $(hdrdir)/ruby/subst.h
+newline_conv.o: newline_conv.c
+stat.o: $(RUBY_EXTCONF_H)
+stat.o: $(arch_hdrdir)/ruby/config.h
+stat.o: $(hdrdir)/ruby/assert.h
+stat.o: $(hdrdir)/ruby/backward.h
+stat.o: $(hdrdir)/ruby/backward/2/assume.h
+stat.o: $(hdrdir)/ruby/backward/2/attributes.h
+stat.o: $(hdrdir)/ruby/backward/2/bool.h
+stat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+stat.o: $(hdrdir)/ruby/backward/2/limits.h
+stat.o: $(hdrdir)/ruby/backward/2/long_long.h
+stat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+stat.o: $(hdrdir)/ruby/backward/2/stdarg.h
+stat.o: $(hdrdir)/ruby/defines.h
+stat.o: $(hdrdir)/ruby/encoding.h
+stat.o: $(hdrdir)/ruby/intern.h
+stat.o: $(hdrdir)/ruby/internal/abi.h
+stat.o: $(hdrdir)/ruby/internal/anyargs.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+stat.o: $(hdrdir)/ruby/internal/assume.h
+stat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+stat.o: $(hdrdir)/ruby/internal/attr/artificial.h
+stat.o: $(hdrdir)/ruby/internal/attr/cold.h
+stat.o: $(hdrdir)/ruby/internal/attr/const.h
+stat.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+stat.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+stat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+stat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+stat.o: $(hdrdir)/ruby/internal/attr/error.h
+stat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+stat.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+stat.o: $(hdrdir)/ruby/internal/attr/format.h
+stat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+stat.o: $(hdrdir)/ruby/internal/attr/noalias.h
+stat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+stat.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+stat.o: $(hdrdir)/ruby/internal/attr/noinline.h
+stat.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+stat.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+stat.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+stat.o: $(hdrdir)/ruby/internal/attr/pure.h
+stat.o: $(hdrdir)/ruby/internal/attr/restrict.h
+stat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+stat.o: $(hdrdir)/ruby/internal/attr/warning.h
+stat.o: $(hdrdir)/ruby/internal/attr/weakref.h
+stat.o: $(hdrdir)/ruby/internal/cast.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+stat.o: $(hdrdir)/ruby/internal/compiler_since.h
+stat.o: $(hdrdir)/ruby/internal/config.h
+stat.o: $(hdrdir)/ruby/internal/constant_p.h
+stat.o: $(hdrdir)/ruby/internal/core.h
+stat.o: $(hdrdir)/ruby/internal/core/rarray.h
+stat.o: $(hdrdir)/ruby/internal/core/rbasic.h
+stat.o: $(hdrdir)/ruby/internal/core/rbignum.h
+stat.o: $(hdrdir)/ruby/internal/core/rclass.h
+stat.o: $(hdrdir)/ruby/internal/core/rdata.h
+stat.o: $(hdrdir)/ruby/internal/core/rfile.h
+stat.o: $(hdrdir)/ruby/internal/core/rhash.h
+stat.o: $(hdrdir)/ruby/internal/core/robject.h
+stat.o: $(hdrdir)/ruby/internal/core/rregexp.h
+stat.o: $(hdrdir)/ruby/internal/core/rstring.h
+stat.o: $(hdrdir)/ruby/internal/core/rstruct.h
+stat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+stat.o: $(hdrdir)/ruby/internal/ctype.h
+stat.o: $(hdrdir)/ruby/internal/dllexport.h
+stat.o: $(hdrdir)/ruby/internal/dosish.h
+stat.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+stat.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+stat.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+stat.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+stat.o: $(hdrdir)/ruby/internal/encoding/re.h
+stat.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+stat.o: $(hdrdir)/ruby/internal/encoding/string.h
+stat.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+stat.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+stat.o: $(hdrdir)/ruby/internal/error.h
+stat.o: $(hdrdir)/ruby/internal/eval.h
+stat.o: $(hdrdir)/ruby/internal/event.h
+stat.o: $(hdrdir)/ruby/internal/fl_type.h
+stat.o: $(hdrdir)/ruby/internal/gc.h
+stat.o: $(hdrdir)/ruby/internal/glob.h
+stat.o: $(hdrdir)/ruby/internal/globals.h
+stat.o: $(hdrdir)/ruby/internal/has/attribute.h
+stat.o: $(hdrdir)/ruby/internal/has/builtin.h
+stat.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+stat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+stat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+stat.o: $(hdrdir)/ruby/internal/has/extension.h
+stat.o: $(hdrdir)/ruby/internal/has/feature.h
+stat.o: $(hdrdir)/ruby/internal/has/warning.h
+stat.o: $(hdrdir)/ruby/internal/intern/array.h
+stat.o: $(hdrdir)/ruby/internal/intern/bignum.h
+stat.o: $(hdrdir)/ruby/internal/intern/class.h
+stat.o: $(hdrdir)/ruby/internal/intern/compar.h
+stat.o: $(hdrdir)/ruby/internal/intern/complex.h
+stat.o: $(hdrdir)/ruby/internal/intern/cont.h
+stat.o: $(hdrdir)/ruby/internal/intern/dir.h
+stat.o: $(hdrdir)/ruby/internal/intern/enum.h
+stat.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+stat.o: $(hdrdir)/ruby/internal/intern/error.h
+stat.o: $(hdrdir)/ruby/internal/intern/eval.h
+stat.o: $(hdrdir)/ruby/internal/intern/file.h
+stat.o: $(hdrdir)/ruby/internal/intern/hash.h
+stat.o: $(hdrdir)/ruby/internal/intern/io.h
+stat.o: $(hdrdir)/ruby/internal/intern/load.h
+stat.o: $(hdrdir)/ruby/internal/intern/marshal.h
+stat.o: $(hdrdir)/ruby/internal/intern/numeric.h
+stat.o: $(hdrdir)/ruby/internal/intern/object.h
+stat.o: $(hdrdir)/ruby/internal/intern/parse.h
+stat.o: $(hdrdir)/ruby/internal/intern/proc.h
+stat.o: $(hdrdir)/ruby/internal/intern/process.h
+stat.o: $(hdrdir)/ruby/internal/intern/random.h
+stat.o: $(hdrdir)/ruby/internal/intern/range.h
+stat.o: $(hdrdir)/ruby/internal/intern/rational.h
+stat.o: $(hdrdir)/ruby/internal/intern/re.h
+stat.o: $(hdrdir)/ruby/internal/intern/ruby.h
+stat.o: $(hdrdir)/ruby/internal/intern/select.h
+stat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+stat.o: $(hdrdir)/ruby/internal/intern/set.h
+stat.o: $(hdrdir)/ruby/internal/intern/signal.h
+stat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+stat.o: $(hdrdir)/ruby/internal/intern/string.h
+stat.o: $(hdrdir)/ruby/internal/intern/struct.h
+stat.o: $(hdrdir)/ruby/internal/intern/thread.h
+stat.o: $(hdrdir)/ruby/internal/intern/time.h
+stat.o: $(hdrdir)/ruby/internal/intern/variable.h
+stat.o: $(hdrdir)/ruby/internal/intern/vm.h
+stat.o: $(hdrdir)/ruby/internal/interpreter.h
+stat.o: $(hdrdir)/ruby/internal/iterator.h
+stat.o: $(hdrdir)/ruby/internal/memory.h
+stat.o: $(hdrdir)/ruby/internal/method.h
+stat.o: $(hdrdir)/ruby/internal/module.h
+stat.o: $(hdrdir)/ruby/internal/newobj.h
+stat.o: $(hdrdir)/ruby/internal/scan_args.h
+stat.o: $(hdrdir)/ruby/internal/special_consts.h
+stat.o: $(hdrdir)/ruby/internal/static_assert.h
+stat.o: $(hdrdir)/ruby/internal/stdalign.h
+stat.o: $(hdrdir)/ruby/internal/stdbool.h
+stat.o: $(hdrdir)/ruby/internal/stdckdint.h
+stat.o: $(hdrdir)/ruby/internal/symbol.h
+stat.o: $(hdrdir)/ruby/internal/value.h
+stat.o: $(hdrdir)/ruby/internal/value_type.h
+stat.o: $(hdrdir)/ruby/internal/variable.h
+stat.o: $(hdrdir)/ruby/internal/warning_push.h
+stat.o: $(hdrdir)/ruby/internal/xmalloc.h
+stat.o: $(hdrdir)/ruby/io.h
+stat.o: $(hdrdir)/ruby/missing.h
+stat.o: $(hdrdir)/ruby/onigmo.h
+stat.o: $(hdrdir)/ruby/oniguruma.h
+stat.o: $(hdrdir)/ruby/ruby.h
+stat.o: $(hdrdir)/ruby/st.h
+stat.o: $(hdrdir)/ruby/subst.h
+stat.o: stat.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/file/extconf.rb b/ext/-test-/file/extconf.rb
new file mode 100644
index 0000000000..9027ed1c3e
--- /dev/null
+++ b/ext/-test-/file/extconf.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+
+headers = %w[sys/param.h sys/mount.h sys/vfs.h].select {|h| have_header(h)}
+if have_type("struct statfs", headers)
+ have_struct_member("struct statfs", "f_fstypename", headers)
+ have_struct_member("struct statfs", "f_type", headers)
+ have_struct_member("struct statfs", "f_flags", headers)
+end
+
+headers = %w[sys/statvfs.h].select {|h| have_header(h)}
+if have_type("struct statvfs", headers)
+ have_struct_member("struct statvfs", "f_fstypename", headers)
+ have_struct_member("struct statvfs", "f_basetype", headers)
+ have_struct_member("struct statvfs", "f_type", headers)
+end
+
+auto_ext(inc: true)
diff --git a/ext/-test-/file/fs.c b/ext/-test-/file/fs.c
new file mode 100644
index 0000000000..eb17e9768e
--- /dev/null
+++ b/ext/-test-/file/fs.c
@@ -0,0 +1,111 @@
+#include "ruby/ruby.h"
+#include "ruby/io.h"
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+
+#if defined HAVE_STRUCT_STATFS_F_FSTYPENAME
+typedef struct statfs statfs_t;
+# define STATFS(f, s) statfs((f), (s))
+# define HAVE_STRUCT_STATFS_T_F_FSTYPENAME 1
+# if defined HAVE_STRUCT_STATFS_F_TYPE
+# define HAVE_STRUCT_STATFS_T_F_TYPE 1
+# endif
+#elif defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME) /* NetBSD */
+typedef struct statvfs statfs_t;
+# define STATFS(f, s) statvfs((f), (s))
+# define HAVE_STRUCT_STATFS_T_F_FSTYPENAME 1
+# if defined HAVE_STRUCT_STATVFS_F_TYPE
+# define HAVE_STRUCT_STATFS_T_F_TYPE 1
+# endif
+#elif defined(HAVE_STRUCT_STATVFS_F_BASETYPE) /* AIX, Solaris */
+typedef struct statvfs statfs_t;
+# define STATFS(f, s) statvfs((f), (s))
+# define HAVE_STRUCT_STATFS_T_F_FSTYPENAME 1
+# define f_fstypename f_basetype
+# if defined HAVE_STRUCT_STATVFS_F_TYPE
+# define HAVE_STRUCT_STATFS_T_F_TYPE 1
+# endif
+#elif defined(HAVE_STRUCT_STATFS_F_TYPE) /* Linux */
+typedef struct statfs statfs_t;
+# define STATFS(f, s) statfs((f), (s))
+# if defined HAVE_STRUCT_STATFS_F_TYPE
+# define HAVE_STRUCT_STATFS_T_F_TYPE 1
+# endif
+#endif
+
+VALUE
+get_fsname(VALUE self, VALUE str)
+{
+#ifdef STATFS
+ statfs_t st;
+# define CSTR(s) rb_str_new_cstr(s)
+
+ FilePathValue(str);
+ str = rb_str_encode_ospath(str);
+ if (STATFS(StringValueCStr(str), &st) == -1) {
+ rb_sys_fail_str(str);
+ }
+# ifdef HAVE_STRUCT_STATFS_T_F_FSTYPENAME
+ if (st.f_fstypename[0])
+ return CSTR(st.f_fstypename);
+# endif
+# ifdef HAVE_STRUCT_STATFS_T_F_TYPE
+ switch (st.f_type) {
+ case 0x9123683E: /* BTRFS_SUPER_MAGIC */
+ return CSTR("btrfs");
+ case 0x7461636f: /* OCFS2_SUPER_MAGIC */
+ return CSTR("ocfs");
+ case 0xEF53: /* EXT2_SUPER_MAGIC EXT3_SUPER_MAGIC EXT4_SUPER_MAGIC */
+ return CSTR("ext4");
+ case 0x58465342: /* XFS_SUPER_MAGIC */
+ return CSTR("xfs");
+ case 0x01021994: /* TMPFS_MAGIC */
+ return CSTR("tmpfs");
+ }
+# endif
+#endif
+ return Qnil;
+}
+
+VALUE
+get_noatime_p(VALUE self, VALUE str)
+{
+#ifdef STATFS
+ statfs_t st;
+ FilePathValue(str);
+ str = rb_str_encode_ospath(str);
+ if (STATFS(StringValueCStr(str), &st) == -1) {
+ rb_sys_fail_str(str);
+ }
+# ifdef HAVE_STRUCT_STATFS_F_FLAGS
+# ifdef MNT_STRICTATIME
+ if (!(st.f_flags & MNT_STRICTATIME)) return Qtrue;
+# endif
+# ifdef MNT_NOATIME
+ return st.f_flags & MNT_NOATIME ? Qtrue : Qfalse;
+# elif defined(ST_NOATIME)
+ return st.f_flags & ST_NOATIME ? Qtrue : Qfalse;
+# endif
+# endif
+#endif
+ return Qnil;
+}
+
+void
+Init_fs(VALUE module)
+{
+ VALUE fs = rb_define_module_under(module, "Fs");
+ rb_define_module_function(fs, "fsname", get_fsname, 1);
+ rb_define_module_function(fs, "noatime?", get_noatime_p, 1);
+}
diff --git a/ext/-test-/file/init.c b/ext/-test-/file/init.c
new file mode 100644
index 0000000000..1117993d6c
--- /dev/null
+++ b/ext/-test-/file/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(module);}
+
+void
+Init_file(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE module = rb_define_module_under(mBug, "File");
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/file/newline_conv.c b/ext/-test-/file/newline_conv.c
new file mode 100644
index 0000000000..2ac5aef801
--- /dev/null
+++ b/ext/-test-/file/newline_conv.c
@@ -0,0 +1,73 @@
+#include "ruby/ruby.h"
+#include "ruby/io.h"
+#include <fcntl.h>
+
+static VALUE
+open_with_rb_file_open(VALUE self, VALUE filename, VALUE read_or_write, VALUE binary_or_text)
+{
+ char fmode[3] = { 0 };
+ if (rb_sym2id(read_or_write) == rb_intern("read")) {
+ fmode[0] = 'r';
+ }
+ else if (rb_sym2id(read_or_write) == rb_intern("write")) {
+ fmode[0] = 'w';
+ }
+ else {
+ rb_raise(rb_eArgError, "read_or_write param must be :read or :write");
+ }
+
+ if (rb_sym2id(binary_or_text) == rb_intern("binary")) {
+ fmode[1] = 'b';
+ }
+ else if (rb_sym2id(binary_or_text) == rb_intern("text")) {
+
+ }
+ else {
+ rb_raise(rb_eArgError, "binary_or_text param must be :binary or :text");
+ }
+
+ return rb_file_open(StringValueCStr(filename), fmode);
+}
+
+static VALUE
+open_with_rb_io_fdopen(VALUE self, VALUE filename, VALUE read_or_write, VALUE binary_or_text)
+{
+ int omode = 0;
+ if (rb_sym2id(read_or_write) == rb_intern("read")) {
+ omode |= O_RDONLY;
+ }
+ else if (rb_sym2id(read_or_write) == rb_intern("write")) {
+ omode |= O_WRONLY;
+ }
+ else {
+ rb_raise(rb_eArgError, "read_or_write param must be :read or :write");
+ }
+
+ if (rb_sym2id(binary_or_text) == rb_intern("binary")) {
+#ifdef O_BINARY
+ omode |= O_BINARY;
+#endif
+ }
+ else if (rb_sym2id(binary_or_text) == rb_intern("text")) {
+
+ }
+ else {
+ rb_raise(rb_eArgError, "binary_or_text param must be :binary or :text");
+ }
+
+ int fd = rb_cloexec_open(StringValueCStr(filename), omode, 0);
+ if (fd < 0) {
+ rb_raise(rb_eIOError, "failed to open the file");
+ }
+
+ rb_update_max_fd(fd);
+ return rb_io_fdopen(fd, omode, StringValueCStr(filename));
+}
+
+void
+Init_newline_conv(VALUE module)
+{
+ VALUE newline_conv = rb_define_module_under(module, "NewlineConv");
+ rb_define_module_function(newline_conv, "rb_file_open", open_with_rb_file_open, 3);
+ rb_define_module_function(newline_conv, "rb_io_fdopen", open_with_rb_io_fdopen, 3);
+}
diff --git a/ext/-test-/file/stat.c b/ext/-test-/file/stat.c
new file mode 100644
index 0000000000..fed5d389eb
--- /dev/null
+++ b/ext/-test-/file/stat.c
@@ -0,0 +1,27 @@
+#include "ruby/ruby.h"
+#include "ruby/io.h"
+
+static VALUE
+stat_for_fd(VALUE self, VALUE fileno)
+{
+ struct stat st;
+ if (fstat(NUM2INT(fileno), &st)) rb_sys_fail(0);
+ return rb_stat_new(&st);
+}
+
+static VALUE
+stat_for_path(VALUE self, VALUE path)
+{
+ struct stat st;
+ FilePathValue(path);
+ if (stat(RSTRING_PTR(path), &st)) rb_sys_fail(0);
+ return rb_stat_new(&st);
+}
+
+void
+Init_stat(VALUE module)
+{
+ VALUE st = rb_define_module_under(module, "Stat");
+ rb_define_module_function(st, "for_fd", stat_for_fd, 1);
+ rb_define_module_function(st, "for_path", stat_for_path, 1);
+}
diff --git a/ext/-test-/float/depend b/ext/-test-/float/depend
new file mode 100644
index 0000000000..334ed33c3b
--- /dev/null
+++ b/ext/-test-/float/depend
@@ -0,0 +1,328 @@
+# for FreeBSD make
+nextafter.o: nextafter.c $(top_srcdir)/missing/nextafter.c
+
+# AUTOGENERATED DEPENDENCIES START
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+nextafter.o: $(RUBY_EXTCONF_H)
+nextafter.o: $(arch_hdrdir)/ruby/config.h
+nextafter.o: $(hdrdir)/ruby.h
+nextafter.o: $(hdrdir)/ruby/assert.h
+nextafter.o: $(hdrdir)/ruby/backward.h
+nextafter.o: $(hdrdir)/ruby/backward/2/assume.h
+nextafter.o: $(hdrdir)/ruby/backward/2/attributes.h
+nextafter.o: $(hdrdir)/ruby/backward/2/bool.h
+nextafter.o: $(hdrdir)/ruby/backward/2/inttypes.h
+nextafter.o: $(hdrdir)/ruby/backward/2/limits.h
+nextafter.o: $(hdrdir)/ruby/backward/2/long_long.h
+nextafter.o: $(hdrdir)/ruby/backward/2/stdalign.h
+nextafter.o: $(hdrdir)/ruby/backward/2/stdarg.h
+nextafter.o: $(hdrdir)/ruby/defines.h
+nextafter.o: $(hdrdir)/ruby/intern.h
+nextafter.o: $(hdrdir)/ruby/internal/abi.h
+nextafter.o: $(hdrdir)/ruby/internal/anyargs.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+nextafter.o: $(hdrdir)/ruby/internal/assume.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/artificial.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/cold.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/const.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/error.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/format.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/noalias.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/noinline.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/pure.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/restrict.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/warning.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/weakref.h
+nextafter.o: $(hdrdir)/ruby/internal/cast.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_since.h
+nextafter.o: $(hdrdir)/ruby/internal/config.h
+nextafter.o: $(hdrdir)/ruby/internal/constant_p.h
+nextafter.o: $(hdrdir)/ruby/internal/core.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rarray.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rbasic.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rbignum.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rclass.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rdata.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rfile.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rhash.h
+nextafter.o: $(hdrdir)/ruby/internal/core/robject.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rregexp.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rstring.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rstruct.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+nextafter.o: $(hdrdir)/ruby/internal/ctype.h
+nextafter.o: $(hdrdir)/ruby/internal/dllexport.h
+nextafter.o: $(hdrdir)/ruby/internal/dosish.h
+nextafter.o: $(hdrdir)/ruby/internal/error.h
+nextafter.o: $(hdrdir)/ruby/internal/eval.h
+nextafter.o: $(hdrdir)/ruby/internal/event.h
+nextafter.o: $(hdrdir)/ruby/internal/fl_type.h
+nextafter.o: $(hdrdir)/ruby/internal/gc.h
+nextafter.o: $(hdrdir)/ruby/internal/glob.h
+nextafter.o: $(hdrdir)/ruby/internal/globals.h
+nextafter.o: $(hdrdir)/ruby/internal/has/attribute.h
+nextafter.o: $(hdrdir)/ruby/internal/has/builtin.h
+nextafter.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+nextafter.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+nextafter.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+nextafter.o: $(hdrdir)/ruby/internal/has/extension.h
+nextafter.o: $(hdrdir)/ruby/internal/has/feature.h
+nextafter.o: $(hdrdir)/ruby/internal/has/warning.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/array.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/bignum.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/class.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/compar.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/complex.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/cont.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/dir.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/enum.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/error.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/eval.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/file.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/hash.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/io.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/load.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/marshal.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/numeric.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/object.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/parse.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/proc.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/process.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/random.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/range.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/rational.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/re.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/ruby.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/select.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/set.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/signal.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/string.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/struct.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/thread.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/time.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/variable.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/vm.h
+nextafter.o: $(hdrdir)/ruby/internal/interpreter.h
+nextafter.o: $(hdrdir)/ruby/internal/iterator.h
+nextafter.o: $(hdrdir)/ruby/internal/memory.h
+nextafter.o: $(hdrdir)/ruby/internal/method.h
+nextafter.o: $(hdrdir)/ruby/internal/module.h
+nextafter.o: $(hdrdir)/ruby/internal/newobj.h
+nextafter.o: $(hdrdir)/ruby/internal/scan_args.h
+nextafter.o: $(hdrdir)/ruby/internal/special_consts.h
+nextafter.o: $(hdrdir)/ruby/internal/static_assert.h
+nextafter.o: $(hdrdir)/ruby/internal/stdalign.h
+nextafter.o: $(hdrdir)/ruby/internal/stdbool.h
+nextafter.o: $(hdrdir)/ruby/internal/stdckdint.h
+nextafter.o: $(hdrdir)/ruby/internal/symbol.h
+nextafter.o: $(hdrdir)/ruby/internal/value.h
+nextafter.o: $(hdrdir)/ruby/internal/value_type.h
+nextafter.o: $(hdrdir)/ruby/internal/variable.h
+nextafter.o: $(hdrdir)/ruby/internal/warning_push.h
+nextafter.o: $(hdrdir)/ruby/internal/xmalloc.h
+nextafter.o: $(hdrdir)/ruby/missing.h
+nextafter.o: $(hdrdir)/ruby/ruby.h
+nextafter.o: $(hdrdir)/ruby/st.h
+nextafter.o: $(hdrdir)/ruby/subst.h
+nextafter.o: $(top_srcdir)/missing/nextafter.c
+nextafter.o: nextafter.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/float/extconf.rb b/ext/-test-/float/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/float/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/float/init.c b/ext/-test-/float/init.c
new file mode 100644
index 0000000000..d962108e39
--- /dev/null
+++ b/ext/-test-/float/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_float(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "Float", rb_cObject);
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/float/nextafter.c b/ext/-test-/float/nextafter.c
new file mode 100644
index 0000000000..30fb71f520
--- /dev/null
+++ b/ext/-test-/float/nextafter.c
@@ -0,0 +1,36 @@
+#include "ruby.h"
+
+static VALUE
+system_nextafter_m(VALUE klass, VALUE vx, VALUE vy)
+{
+ double x, y, z;
+
+ x = NUM2DBL(vx);
+ y = NUM2DBL(vy);
+ z = nextafter(x, y);
+
+ return DBL2NUM(z);
+}
+
+#define nextafter missing_nextafter
+#include "../../../missing/nextafter.c"
+#undef nextafter
+
+static VALUE
+missing_nextafter_m(VALUE klass, VALUE vx, VALUE vy)
+{
+ double x, y, z;
+
+ x = NUM2DBL(vx);
+ y = NUM2DBL(vy);
+ z = missing_nextafter(x, y);
+
+ return DBL2NUM(z);
+}
+
+void
+Init_nextafter(VALUE klass)
+{
+ rb_define_singleton_method(klass, "system_nextafter", system_nextafter_m, 2);
+ rb_define_singleton_method(klass, "missing_nextafter", missing_nextafter_m, 2);
+}
diff --git a/ext/-test-/funcall/depend b/ext/-test-/funcall/depend
new file mode 100644
index 0000000000..e54370306f
--- /dev/null
+++ b/ext/-test-/funcall/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+funcall.o: $(RUBY_EXTCONF_H)
+funcall.o: $(arch_hdrdir)/ruby/config.h
+funcall.o: $(hdrdir)/ruby.h
+funcall.o: $(hdrdir)/ruby/assert.h
+funcall.o: $(hdrdir)/ruby/backward.h
+funcall.o: $(hdrdir)/ruby/backward/2/assume.h
+funcall.o: $(hdrdir)/ruby/backward/2/attributes.h
+funcall.o: $(hdrdir)/ruby/backward/2/bool.h
+funcall.o: $(hdrdir)/ruby/backward/2/inttypes.h
+funcall.o: $(hdrdir)/ruby/backward/2/limits.h
+funcall.o: $(hdrdir)/ruby/backward/2/long_long.h
+funcall.o: $(hdrdir)/ruby/backward/2/stdalign.h
+funcall.o: $(hdrdir)/ruby/backward/2/stdarg.h
+funcall.o: $(hdrdir)/ruby/defines.h
+funcall.o: $(hdrdir)/ruby/intern.h
+funcall.o: $(hdrdir)/ruby/internal/abi.h
+funcall.o: $(hdrdir)/ruby/internal/anyargs.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+funcall.o: $(hdrdir)/ruby/internal/assume.h
+funcall.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+funcall.o: $(hdrdir)/ruby/internal/attr/artificial.h
+funcall.o: $(hdrdir)/ruby/internal/attr/cold.h
+funcall.o: $(hdrdir)/ruby/internal/attr/const.h
+funcall.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+funcall.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+funcall.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+funcall.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+funcall.o: $(hdrdir)/ruby/internal/attr/error.h
+funcall.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+funcall.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+funcall.o: $(hdrdir)/ruby/internal/attr/format.h
+funcall.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+funcall.o: $(hdrdir)/ruby/internal/attr/noalias.h
+funcall.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+funcall.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+funcall.o: $(hdrdir)/ruby/internal/attr/noinline.h
+funcall.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+funcall.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+funcall.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+funcall.o: $(hdrdir)/ruby/internal/attr/pure.h
+funcall.o: $(hdrdir)/ruby/internal/attr/restrict.h
+funcall.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+funcall.o: $(hdrdir)/ruby/internal/attr/warning.h
+funcall.o: $(hdrdir)/ruby/internal/attr/weakref.h
+funcall.o: $(hdrdir)/ruby/internal/cast.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_since.h
+funcall.o: $(hdrdir)/ruby/internal/config.h
+funcall.o: $(hdrdir)/ruby/internal/constant_p.h
+funcall.o: $(hdrdir)/ruby/internal/core.h
+funcall.o: $(hdrdir)/ruby/internal/core/rarray.h
+funcall.o: $(hdrdir)/ruby/internal/core/rbasic.h
+funcall.o: $(hdrdir)/ruby/internal/core/rbignum.h
+funcall.o: $(hdrdir)/ruby/internal/core/rclass.h
+funcall.o: $(hdrdir)/ruby/internal/core/rdata.h
+funcall.o: $(hdrdir)/ruby/internal/core/rfile.h
+funcall.o: $(hdrdir)/ruby/internal/core/rhash.h
+funcall.o: $(hdrdir)/ruby/internal/core/robject.h
+funcall.o: $(hdrdir)/ruby/internal/core/rregexp.h
+funcall.o: $(hdrdir)/ruby/internal/core/rstring.h
+funcall.o: $(hdrdir)/ruby/internal/core/rstruct.h
+funcall.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+funcall.o: $(hdrdir)/ruby/internal/ctype.h
+funcall.o: $(hdrdir)/ruby/internal/dllexport.h
+funcall.o: $(hdrdir)/ruby/internal/dosish.h
+funcall.o: $(hdrdir)/ruby/internal/error.h
+funcall.o: $(hdrdir)/ruby/internal/eval.h
+funcall.o: $(hdrdir)/ruby/internal/event.h
+funcall.o: $(hdrdir)/ruby/internal/fl_type.h
+funcall.o: $(hdrdir)/ruby/internal/gc.h
+funcall.o: $(hdrdir)/ruby/internal/glob.h
+funcall.o: $(hdrdir)/ruby/internal/globals.h
+funcall.o: $(hdrdir)/ruby/internal/has/attribute.h
+funcall.o: $(hdrdir)/ruby/internal/has/builtin.h
+funcall.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+funcall.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+funcall.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+funcall.o: $(hdrdir)/ruby/internal/has/extension.h
+funcall.o: $(hdrdir)/ruby/internal/has/feature.h
+funcall.o: $(hdrdir)/ruby/internal/has/warning.h
+funcall.o: $(hdrdir)/ruby/internal/intern/array.h
+funcall.o: $(hdrdir)/ruby/internal/intern/bignum.h
+funcall.o: $(hdrdir)/ruby/internal/intern/class.h
+funcall.o: $(hdrdir)/ruby/internal/intern/compar.h
+funcall.o: $(hdrdir)/ruby/internal/intern/complex.h
+funcall.o: $(hdrdir)/ruby/internal/intern/cont.h
+funcall.o: $(hdrdir)/ruby/internal/intern/dir.h
+funcall.o: $(hdrdir)/ruby/internal/intern/enum.h
+funcall.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+funcall.o: $(hdrdir)/ruby/internal/intern/error.h
+funcall.o: $(hdrdir)/ruby/internal/intern/eval.h
+funcall.o: $(hdrdir)/ruby/internal/intern/file.h
+funcall.o: $(hdrdir)/ruby/internal/intern/hash.h
+funcall.o: $(hdrdir)/ruby/internal/intern/io.h
+funcall.o: $(hdrdir)/ruby/internal/intern/load.h
+funcall.o: $(hdrdir)/ruby/internal/intern/marshal.h
+funcall.o: $(hdrdir)/ruby/internal/intern/numeric.h
+funcall.o: $(hdrdir)/ruby/internal/intern/object.h
+funcall.o: $(hdrdir)/ruby/internal/intern/parse.h
+funcall.o: $(hdrdir)/ruby/internal/intern/proc.h
+funcall.o: $(hdrdir)/ruby/internal/intern/process.h
+funcall.o: $(hdrdir)/ruby/internal/intern/random.h
+funcall.o: $(hdrdir)/ruby/internal/intern/range.h
+funcall.o: $(hdrdir)/ruby/internal/intern/rational.h
+funcall.o: $(hdrdir)/ruby/internal/intern/re.h
+funcall.o: $(hdrdir)/ruby/internal/intern/ruby.h
+funcall.o: $(hdrdir)/ruby/internal/intern/select.h
+funcall.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+funcall.o: $(hdrdir)/ruby/internal/intern/set.h
+funcall.o: $(hdrdir)/ruby/internal/intern/signal.h
+funcall.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+funcall.o: $(hdrdir)/ruby/internal/intern/string.h
+funcall.o: $(hdrdir)/ruby/internal/intern/struct.h
+funcall.o: $(hdrdir)/ruby/internal/intern/thread.h
+funcall.o: $(hdrdir)/ruby/internal/intern/time.h
+funcall.o: $(hdrdir)/ruby/internal/intern/variable.h
+funcall.o: $(hdrdir)/ruby/internal/intern/vm.h
+funcall.o: $(hdrdir)/ruby/internal/interpreter.h
+funcall.o: $(hdrdir)/ruby/internal/iterator.h
+funcall.o: $(hdrdir)/ruby/internal/memory.h
+funcall.o: $(hdrdir)/ruby/internal/method.h
+funcall.o: $(hdrdir)/ruby/internal/module.h
+funcall.o: $(hdrdir)/ruby/internal/newobj.h
+funcall.o: $(hdrdir)/ruby/internal/scan_args.h
+funcall.o: $(hdrdir)/ruby/internal/special_consts.h
+funcall.o: $(hdrdir)/ruby/internal/static_assert.h
+funcall.o: $(hdrdir)/ruby/internal/stdalign.h
+funcall.o: $(hdrdir)/ruby/internal/stdbool.h
+funcall.o: $(hdrdir)/ruby/internal/stdckdint.h
+funcall.o: $(hdrdir)/ruby/internal/symbol.h
+funcall.o: $(hdrdir)/ruby/internal/value.h
+funcall.o: $(hdrdir)/ruby/internal/value_type.h
+funcall.o: $(hdrdir)/ruby/internal/variable.h
+funcall.o: $(hdrdir)/ruby/internal/warning_push.h
+funcall.o: $(hdrdir)/ruby/internal/xmalloc.h
+funcall.o: $(hdrdir)/ruby/missing.h
+funcall.o: $(hdrdir)/ruby/ruby.h
+funcall.o: $(hdrdir)/ruby/st.h
+funcall.o: $(hdrdir)/ruby/subst.h
+funcall.o: funcall.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/funcall/extconf.rb b/ext/-test-/funcall/extconf.rb
new file mode 100644
index 0000000000..39d6134cba
--- /dev/null
+++ b/ext/-test-/funcall/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require 'mkmf'
+create_makefile("-test-/funcall")
diff --git a/ext/-test-/funcall/funcall.c b/ext/-test-/funcall/funcall.c
new file mode 100644
index 0000000000..a68d6de255
--- /dev/null
+++ b/ext/-test-/funcall/funcall.c
@@ -0,0 +1,72 @@
+#include "ruby.h"
+
+static VALUE
+with_funcall2(int argc, VALUE *argv, VALUE self)
+{
+ return rb_funcallv(self, rb_intern("target"), argc, argv);
+}
+
+static VALUE
+with_funcall_passing_block(int argc, VALUE *argv, VALUE self)
+{
+ return rb_funcall_passing_block(self, rb_intern("target"), argc, argv);
+}
+
+static VALUE
+with_funcall_passing_block_kw(int argc, VALUE *argv, VALUE self)
+{
+ return rb_funcall_passing_block_kw(self, rb_intern("target"), argc-1, argv+1, FIX2INT(argv[0]));
+}
+
+static VALUE
+with_funcallv_public_kw(int argc, VALUE *argv, VALUE self)
+{
+ return rb_funcallv_public_kw(argv[0], SYM2ID(argv[1]), argc-3, argv+3, FIX2INT(argv[2]));
+}
+
+static VALUE
+with_yield_splat_kw(int argc, VALUE *argv, VALUE self)
+{
+ return rb_yield_splat_kw(argv[1], FIX2INT(argv[0]));
+}
+
+static VALUE
+extra_args_name(VALUE self)
+{
+ /*
+ * at least clang 5.x gets tripped by the extra 0 arg
+ * [ruby-core:85266] [Bug #14425]
+ */
+ return rb_funcall(self, rb_intern("name"), 0, 0);
+}
+
+void
+Init_funcall(void)
+{
+ VALUE cTestFuncall = rb_path2class("TestFuncall");
+ VALUE cRelay = rb_define_module_under(cTestFuncall, "Relay");
+
+ rb_define_singleton_method(cRelay,
+ "with_funcall2",
+ with_funcall2,
+ -1);
+ rb_define_singleton_method(cRelay,
+ "with_funcall_passing_block_kw",
+ with_funcall_passing_block_kw,
+ -1);
+ rb_define_singleton_method(cRelay,
+ "with_funcall_passing_block",
+ with_funcall_passing_block,
+ -1);
+ rb_define_singleton_method(cRelay,
+ "with_funcallv_public_kw",
+ with_funcallv_public_kw,
+ -1);
+ rb_define_singleton_method(cRelay,
+ "with_yield_splat_kw",
+ with_yield_splat_kw,
+ -1);
+ rb_define_singleton_method(cTestFuncall, "extra_args_name",
+ extra_args_name,
+ 0);
+}
diff --git a/ext/-test-/gvl/call_without_gvl/call_without_gvl.c b/ext/-test-/gvl/call_without_gvl/call_without_gvl.c
new file mode 100644
index 0000000000..97946e925d
--- /dev/null
+++ b/ext/-test-/gvl/call_without_gvl/call_without_gvl.c
@@ -0,0 +1,78 @@
+#include "ruby/ruby.h"
+#include "ruby/thread.h"
+
+static void*
+native_sleep_callback(void *data)
+{
+ struct timeval *timeval = data;
+ select(0, NULL, NULL, NULL, timeval);
+
+ return NULL;
+}
+
+
+static VALUE
+thread_runnable_sleep(VALUE thread, VALUE timeout)
+{
+ struct timeval timeval;
+
+ if (NIL_P(timeout)) {
+ rb_raise(rb_eArgError, "timeout must be non nil");
+ }
+
+ timeval = rb_time_interval(timeout);
+
+ rb_thread_call_without_gvl(native_sleep_callback, &timeval, RUBY_UBF_IO, NULL);
+
+ return Qnil;
+}
+
+struct loop_ctl {
+ int notify_fd;
+ volatile int stop;
+};
+
+static void *
+do_loop(void *p)
+{
+ struct loop_ctl *ctl = p;
+
+ /* tell the waiting process they can interrupt us, now */
+ ssize_t err = write(ctl->notify_fd, "", 1);
+ if (err == -1) rb_bug("write error");
+
+ while (!ctl->stop) {
+ struct timeval tv = { 0, 10000 };
+ select(0, NULL, NULL, NULL, &tv);
+ }
+ return 0;
+}
+
+static void
+stop_set(void *p)
+{
+ struct loop_ctl *ctl = p;
+
+ ctl->stop = 1;
+}
+
+static VALUE
+thread_ubf_async_safe(VALUE thread, VALUE notify_fd)
+{
+ struct loop_ctl ctl;
+
+ ctl.notify_fd = NUM2INT(notify_fd);
+ ctl.stop = 0;
+
+ rb_nogvl(do_loop, &ctl, stop_set, &ctl, RB_NOGVL_UBF_ASYNC_SAFE);
+ return Qnil;
+}
+
+void
+Init_call_without_gvl(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_module_under(mBug, "Thread");
+ rb_define_singleton_method(klass, "runnable_sleep", thread_runnable_sleep, 1);
+ rb_define_singleton_method(klass, "ubf_async_safe", thread_ubf_async_safe, 1);
+}
diff --git a/ext/-test-/gvl/call_without_gvl/depend b/ext/-test-/gvl/call_without_gvl/depend
new file mode 100644
index 0000000000..236d1e1d3b
--- /dev/null
+++ b/ext/-test-/gvl/call_without_gvl/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+call_without_gvl.o: $(RUBY_EXTCONF_H)
+call_without_gvl.o: $(arch_hdrdir)/ruby/config.h
+call_without_gvl.o: $(hdrdir)/ruby/assert.h
+call_without_gvl.o: $(hdrdir)/ruby/backward.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/assume.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/attributes.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/bool.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/inttypes.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/limits.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/long_long.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/stdalign.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/stdarg.h
+call_without_gvl.o: $(hdrdir)/ruby/defines.h
+call_without_gvl.o: $(hdrdir)/ruby/intern.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/abi.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/anyargs.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/assume.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/artificial.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/cold.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/const.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/error.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/format.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noalias.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noinline.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/pure.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/restrict.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/warning.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/weakref.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/cast.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_since.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/config.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/constant_p.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rarray.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rbasic.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rbignum.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rclass.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rdata.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rfile.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rhash.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/robject.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rregexp.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rstring.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rstruct.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/ctype.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/dllexport.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/dosish.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/error.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/eval.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/event.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/fl_type.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/gc.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/glob.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/globals.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/attribute.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/builtin.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/extension.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/feature.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/warning.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/array.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/bignum.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/class.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/compar.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/complex.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/cont.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/dir.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/enum.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/error.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/eval.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/file.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/hash.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/io.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/load.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/marshal.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/numeric.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/object.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/parse.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/proc.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/process.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/random.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/range.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/rational.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/re.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/ruby.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/select.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/set.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/signal.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/string.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/struct.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/thread.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/time.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/variable.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/vm.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/interpreter.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/iterator.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/memory.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/method.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/module.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/newobj.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/scan_args.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/special_consts.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/static_assert.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/stdalign.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/stdbool.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/stdckdint.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/symbol.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/value.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/value_type.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/variable.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/warning_push.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/xmalloc.h
+call_without_gvl.o: $(hdrdir)/ruby/missing.h
+call_without_gvl.o: $(hdrdir)/ruby/ruby.h
+call_without_gvl.o: $(hdrdir)/ruby/st.h
+call_without_gvl.o: $(hdrdir)/ruby/subst.h
+call_without_gvl.o: $(hdrdir)/ruby/thread.h
+call_without_gvl.o: call_without_gvl.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/gvl/call_without_gvl/extconf.rb b/ext/-test-/gvl/call_without_gvl/extconf.rb
new file mode 100644
index 0000000000..56181b6773
--- /dev/null
+++ b/ext/-test-/gvl/call_without_gvl/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/gvl/call_without_gvl")
diff --git a/ext/-test-/hash/delete.c b/ext/-test-/hash/delete.c
new file mode 100644
index 0000000000..10d4aec6e7
--- /dev/null
+++ b/ext/-test-/hash/delete.c
@@ -0,0 +1,16 @@
+#include "ruby.h"
+
+extern VALUE rb_hash_delete_entry(VALUE hash, VALUE key);
+
+static VALUE
+hash_delete(VALUE hash, VALUE key)
+{
+ VALUE ret = rb_hash_delete_entry(hash, key);
+ return ret == Qundef ? Qnil : rb_ary_new_from_values(1, &ret);
+}
+
+void
+Init_delete(VALUE klass)
+{
+ rb_define_method(klass, "delete!", hash_delete, 1);
+}
diff --git a/ext/-test-/hash/depend b/ext/-test-/hash/depend
new file mode 100644
index 0000000000..416b93f9de
--- /dev/null
+++ b/ext/-test-/hash/depend
@@ -0,0 +1,324 @@
+# AUTOGENERATED DEPENDENCIES START
+delete.o: $(RUBY_EXTCONF_H)
+delete.o: $(arch_hdrdir)/ruby/config.h
+delete.o: $(hdrdir)/ruby.h
+delete.o: $(hdrdir)/ruby/assert.h
+delete.o: $(hdrdir)/ruby/backward.h
+delete.o: $(hdrdir)/ruby/backward/2/assume.h
+delete.o: $(hdrdir)/ruby/backward/2/attributes.h
+delete.o: $(hdrdir)/ruby/backward/2/bool.h
+delete.o: $(hdrdir)/ruby/backward/2/inttypes.h
+delete.o: $(hdrdir)/ruby/backward/2/limits.h
+delete.o: $(hdrdir)/ruby/backward/2/long_long.h
+delete.o: $(hdrdir)/ruby/backward/2/stdalign.h
+delete.o: $(hdrdir)/ruby/backward/2/stdarg.h
+delete.o: $(hdrdir)/ruby/defines.h
+delete.o: $(hdrdir)/ruby/intern.h
+delete.o: $(hdrdir)/ruby/internal/abi.h
+delete.o: $(hdrdir)/ruby/internal/anyargs.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+delete.o: $(hdrdir)/ruby/internal/assume.h
+delete.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+delete.o: $(hdrdir)/ruby/internal/attr/artificial.h
+delete.o: $(hdrdir)/ruby/internal/attr/cold.h
+delete.o: $(hdrdir)/ruby/internal/attr/const.h
+delete.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+delete.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+delete.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+delete.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+delete.o: $(hdrdir)/ruby/internal/attr/error.h
+delete.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+delete.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+delete.o: $(hdrdir)/ruby/internal/attr/format.h
+delete.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+delete.o: $(hdrdir)/ruby/internal/attr/noalias.h
+delete.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+delete.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+delete.o: $(hdrdir)/ruby/internal/attr/noinline.h
+delete.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+delete.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+delete.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+delete.o: $(hdrdir)/ruby/internal/attr/pure.h
+delete.o: $(hdrdir)/ruby/internal/attr/restrict.h
+delete.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+delete.o: $(hdrdir)/ruby/internal/attr/warning.h
+delete.o: $(hdrdir)/ruby/internal/attr/weakref.h
+delete.o: $(hdrdir)/ruby/internal/cast.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+delete.o: $(hdrdir)/ruby/internal/compiler_since.h
+delete.o: $(hdrdir)/ruby/internal/config.h
+delete.o: $(hdrdir)/ruby/internal/constant_p.h
+delete.o: $(hdrdir)/ruby/internal/core.h
+delete.o: $(hdrdir)/ruby/internal/core/rarray.h
+delete.o: $(hdrdir)/ruby/internal/core/rbasic.h
+delete.o: $(hdrdir)/ruby/internal/core/rbignum.h
+delete.o: $(hdrdir)/ruby/internal/core/rclass.h
+delete.o: $(hdrdir)/ruby/internal/core/rdata.h
+delete.o: $(hdrdir)/ruby/internal/core/rfile.h
+delete.o: $(hdrdir)/ruby/internal/core/rhash.h
+delete.o: $(hdrdir)/ruby/internal/core/robject.h
+delete.o: $(hdrdir)/ruby/internal/core/rregexp.h
+delete.o: $(hdrdir)/ruby/internal/core/rstring.h
+delete.o: $(hdrdir)/ruby/internal/core/rstruct.h
+delete.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+delete.o: $(hdrdir)/ruby/internal/ctype.h
+delete.o: $(hdrdir)/ruby/internal/dllexport.h
+delete.o: $(hdrdir)/ruby/internal/dosish.h
+delete.o: $(hdrdir)/ruby/internal/error.h
+delete.o: $(hdrdir)/ruby/internal/eval.h
+delete.o: $(hdrdir)/ruby/internal/event.h
+delete.o: $(hdrdir)/ruby/internal/fl_type.h
+delete.o: $(hdrdir)/ruby/internal/gc.h
+delete.o: $(hdrdir)/ruby/internal/glob.h
+delete.o: $(hdrdir)/ruby/internal/globals.h
+delete.o: $(hdrdir)/ruby/internal/has/attribute.h
+delete.o: $(hdrdir)/ruby/internal/has/builtin.h
+delete.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+delete.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+delete.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+delete.o: $(hdrdir)/ruby/internal/has/extension.h
+delete.o: $(hdrdir)/ruby/internal/has/feature.h
+delete.o: $(hdrdir)/ruby/internal/has/warning.h
+delete.o: $(hdrdir)/ruby/internal/intern/array.h
+delete.o: $(hdrdir)/ruby/internal/intern/bignum.h
+delete.o: $(hdrdir)/ruby/internal/intern/class.h
+delete.o: $(hdrdir)/ruby/internal/intern/compar.h
+delete.o: $(hdrdir)/ruby/internal/intern/complex.h
+delete.o: $(hdrdir)/ruby/internal/intern/cont.h
+delete.o: $(hdrdir)/ruby/internal/intern/dir.h
+delete.o: $(hdrdir)/ruby/internal/intern/enum.h
+delete.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+delete.o: $(hdrdir)/ruby/internal/intern/error.h
+delete.o: $(hdrdir)/ruby/internal/intern/eval.h
+delete.o: $(hdrdir)/ruby/internal/intern/file.h
+delete.o: $(hdrdir)/ruby/internal/intern/hash.h
+delete.o: $(hdrdir)/ruby/internal/intern/io.h
+delete.o: $(hdrdir)/ruby/internal/intern/load.h
+delete.o: $(hdrdir)/ruby/internal/intern/marshal.h
+delete.o: $(hdrdir)/ruby/internal/intern/numeric.h
+delete.o: $(hdrdir)/ruby/internal/intern/object.h
+delete.o: $(hdrdir)/ruby/internal/intern/parse.h
+delete.o: $(hdrdir)/ruby/internal/intern/proc.h
+delete.o: $(hdrdir)/ruby/internal/intern/process.h
+delete.o: $(hdrdir)/ruby/internal/intern/random.h
+delete.o: $(hdrdir)/ruby/internal/intern/range.h
+delete.o: $(hdrdir)/ruby/internal/intern/rational.h
+delete.o: $(hdrdir)/ruby/internal/intern/re.h
+delete.o: $(hdrdir)/ruby/internal/intern/ruby.h
+delete.o: $(hdrdir)/ruby/internal/intern/select.h
+delete.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+delete.o: $(hdrdir)/ruby/internal/intern/set.h
+delete.o: $(hdrdir)/ruby/internal/intern/signal.h
+delete.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+delete.o: $(hdrdir)/ruby/internal/intern/string.h
+delete.o: $(hdrdir)/ruby/internal/intern/struct.h
+delete.o: $(hdrdir)/ruby/internal/intern/thread.h
+delete.o: $(hdrdir)/ruby/internal/intern/time.h
+delete.o: $(hdrdir)/ruby/internal/intern/variable.h
+delete.o: $(hdrdir)/ruby/internal/intern/vm.h
+delete.o: $(hdrdir)/ruby/internal/interpreter.h
+delete.o: $(hdrdir)/ruby/internal/iterator.h
+delete.o: $(hdrdir)/ruby/internal/memory.h
+delete.o: $(hdrdir)/ruby/internal/method.h
+delete.o: $(hdrdir)/ruby/internal/module.h
+delete.o: $(hdrdir)/ruby/internal/newobj.h
+delete.o: $(hdrdir)/ruby/internal/scan_args.h
+delete.o: $(hdrdir)/ruby/internal/special_consts.h
+delete.o: $(hdrdir)/ruby/internal/static_assert.h
+delete.o: $(hdrdir)/ruby/internal/stdalign.h
+delete.o: $(hdrdir)/ruby/internal/stdbool.h
+delete.o: $(hdrdir)/ruby/internal/stdckdint.h
+delete.o: $(hdrdir)/ruby/internal/symbol.h
+delete.o: $(hdrdir)/ruby/internal/value.h
+delete.o: $(hdrdir)/ruby/internal/value_type.h
+delete.o: $(hdrdir)/ruby/internal/variable.h
+delete.o: $(hdrdir)/ruby/internal/warning_push.h
+delete.o: $(hdrdir)/ruby/internal/xmalloc.h
+delete.o: $(hdrdir)/ruby/missing.h
+delete.o: $(hdrdir)/ruby/ruby.h
+delete.o: $(hdrdir)/ruby/st.h
+delete.o: $(hdrdir)/ruby/subst.h
+delete.o: delete.c
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/hash/extconf.rb b/ext/-test-/hash/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/hash/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/hash/init.c b/ext/-test-/hash/init.c
new file mode 100644
index 0000000000..9f6cbde652
--- /dev/null
+++ b/ext/-test-/hash/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_hash(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "Hash", rb_cHash);
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/integer/core_ext.c b/ext/-test-/integer/core_ext.c
new file mode 100644
index 0000000000..e364aa4b40
--- /dev/null
+++ b/ext/-test-/integer/core_ext.c
@@ -0,0 +1,36 @@
+#include "internal/numeric.h"
+
+static VALUE
+int_bignum_p(VALUE klass, VALUE self)
+{
+ return RB_TYPE_P(self, T_BIGNUM) ? Qtrue : Qfalse;
+}
+
+static VALUE
+int_fixnum_p(VALUE klass, VALUE self)
+{
+ return FIXNUM_P(self) ? Qtrue : Qfalse;
+}
+
+static VALUE
+rb_int_to_bignum(VALUE klass, VALUE x)
+{
+ if (FIXNUM_P(x))
+ x = rb_int2big(FIX2LONG(x));
+ return x;
+}
+
+static VALUE
+positive_pow(VALUE klass, VALUE x, VALUE y)
+{
+ return rb_int_positive_pow(NUM2LONG(x), NUM2ULONG(y));
+}
+
+void
+Init_core_ext(VALUE klass)
+{
+ rb_define_singleton_method(klass, "bignum?", int_bignum_p, 1);
+ rb_define_singleton_method(klass, "fixnum?", int_fixnum_p, 1);
+ rb_define_singleton_method(klass, "to_bignum", rb_int_to_bignum, 1);
+ rb_define_singleton_method(klass, "positive_pow", positive_pow, 2);
+}
diff --git a/ext/-test-/integer/depend b/ext/-test-/integer/depend
new file mode 100644
index 0000000000..d0589b5e5d
--- /dev/null
+++ b/ext/-test-/integer/depend
@@ -0,0 +1,496 @@
+# AUTOGENERATED DEPENDENCIES START
+core_ext.o: $(RUBY_EXTCONF_H)
+core_ext.o: $(arch_hdrdir)/ruby/config.h
+core_ext.o: $(hdrdir)/ruby/assert.h
+core_ext.o: $(hdrdir)/ruby/backward.h
+core_ext.o: $(hdrdir)/ruby/backward/2/assume.h
+core_ext.o: $(hdrdir)/ruby/backward/2/attributes.h
+core_ext.o: $(hdrdir)/ruby/backward/2/bool.h
+core_ext.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+core_ext.o: $(hdrdir)/ruby/backward/2/inttypes.h
+core_ext.o: $(hdrdir)/ruby/backward/2/limits.h
+core_ext.o: $(hdrdir)/ruby/backward/2/long_long.h
+core_ext.o: $(hdrdir)/ruby/backward/2/stdalign.h
+core_ext.o: $(hdrdir)/ruby/backward/2/stdarg.h
+core_ext.o: $(hdrdir)/ruby/defines.h
+core_ext.o: $(hdrdir)/ruby/intern.h
+core_ext.o: $(hdrdir)/ruby/internal/abi.h
+core_ext.o: $(hdrdir)/ruby/internal/anyargs.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+core_ext.o: $(hdrdir)/ruby/internal/assume.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/artificial.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/cold.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/const.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/error.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/format.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/noalias.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/noinline.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/pure.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/restrict.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/warning.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/weakref.h
+core_ext.o: $(hdrdir)/ruby/internal/cast.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_since.h
+core_ext.o: $(hdrdir)/ruby/internal/config.h
+core_ext.o: $(hdrdir)/ruby/internal/constant_p.h
+core_ext.o: $(hdrdir)/ruby/internal/core.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rarray.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rbasic.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rbignum.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rclass.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rdata.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rfile.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rhash.h
+core_ext.o: $(hdrdir)/ruby/internal/core/robject.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rregexp.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rstring.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rstruct.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+core_ext.o: $(hdrdir)/ruby/internal/ctype.h
+core_ext.o: $(hdrdir)/ruby/internal/dllexport.h
+core_ext.o: $(hdrdir)/ruby/internal/dosish.h
+core_ext.o: $(hdrdir)/ruby/internal/error.h
+core_ext.o: $(hdrdir)/ruby/internal/eval.h
+core_ext.o: $(hdrdir)/ruby/internal/event.h
+core_ext.o: $(hdrdir)/ruby/internal/fl_type.h
+core_ext.o: $(hdrdir)/ruby/internal/gc.h
+core_ext.o: $(hdrdir)/ruby/internal/glob.h
+core_ext.o: $(hdrdir)/ruby/internal/globals.h
+core_ext.o: $(hdrdir)/ruby/internal/has/attribute.h
+core_ext.o: $(hdrdir)/ruby/internal/has/builtin.h
+core_ext.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+core_ext.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+core_ext.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+core_ext.o: $(hdrdir)/ruby/internal/has/extension.h
+core_ext.o: $(hdrdir)/ruby/internal/has/feature.h
+core_ext.o: $(hdrdir)/ruby/internal/has/warning.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/array.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/bignum.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/class.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/compar.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/complex.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/cont.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/dir.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/enum.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/error.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/eval.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/file.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/hash.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/io.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/load.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/marshal.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/numeric.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/object.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/parse.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/proc.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/process.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/random.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/range.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/rational.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/re.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/ruby.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/select.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/set.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/signal.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/string.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/struct.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/thread.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/time.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/variable.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/vm.h
+core_ext.o: $(hdrdir)/ruby/internal/interpreter.h
+core_ext.o: $(hdrdir)/ruby/internal/iterator.h
+core_ext.o: $(hdrdir)/ruby/internal/memory.h
+core_ext.o: $(hdrdir)/ruby/internal/method.h
+core_ext.o: $(hdrdir)/ruby/internal/module.h
+core_ext.o: $(hdrdir)/ruby/internal/newobj.h
+core_ext.o: $(hdrdir)/ruby/internal/scan_args.h
+core_ext.o: $(hdrdir)/ruby/internal/special_consts.h
+core_ext.o: $(hdrdir)/ruby/internal/static_assert.h
+core_ext.o: $(hdrdir)/ruby/internal/stdalign.h
+core_ext.o: $(hdrdir)/ruby/internal/stdbool.h
+core_ext.o: $(hdrdir)/ruby/internal/stdckdint.h
+core_ext.o: $(hdrdir)/ruby/internal/symbol.h
+core_ext.o: $(hdrdir)/ruby/internal/value.h
+core_ext.o: $(hdrdir)/ruby/internal/value_type.h
+core_ext.o: $(hdrdir)/ruby/internal/variable.h
+core_ext.o: $(hdrdir)/ruby/internal/warning_push.h
+core_ext.o: $(hdrdir)/ruby/internal/xmalloc.h
+core_ext.o: $(hdrdir)/ruby/missing.h
+core_ext.o: $(hdrdir)/ruby/ruby.h
+core_ext.o: $(hdrdir)/ruby/st.h
+core_ext.o: $(hdrdir)/ruby/subst.h
+core_ext.o: $(top_srcdir)/internal.h
+core_ext.o: $(top_srcdir)/internal/basic_operators.h
+core_ext.o: $(top_srcdir)/internal/bignum.h
+core_ext.o: $(top_srcdir)/internal/bits.h
+core_ext.o: $(top_srcdir)/internal/compar.h
+core_ext.o: $(top_srcdir)/internal/compilers.h
+core_ext.o: $(top_srcdir)/internal/fixnum.h
+core_ext.o: $(top_srcdir)/internal/numeric.h
+core_ext.o: $(top_srcdir)/internal/serial.h
+core_ext.o: $(top_srcdir)/internal/static_assert.h
+core_ext.o: $(top_srcdir)/internal/vm.h
+core_ext.o: core_ext.c
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+my_integer.o: $(RUBY_EXTCONF_H)
+my_integer.o: $(arch_hdrdir)/ruby/config.h
+my_integer.o: $(hdrdir)/ruby.h
+my_integer.o: $(hdrdir)/ruby/assert.h
+my_integer.o: $(hdrdir)/ruby/backward.h
+my_integer.o: $(hdrdir)/ruby/backward/2/assume.h
+my_integer.o: $(hdrdir)/ruby/backward/2/attributes.h
+my_integer.o: $(hdrdir)/ruby/backward/2/bool.h
+my_integer.o: $(hdrdir)/ruby/backward/2/inttypes.h
+my_integer.o: $(hdrdir)/ruby/backward/2/limits.h
+my_integer.o: $(hdrdir)/ruby/backward/2/long_long.h
+my_integer.o: $(hdrdir)/ruby/backward/2/stdalign.h
+my_integer.o: $(hdrdir)/ruby/backward/2/stdarg.h
+my_integer.o: $(hdrdir)/ruby/defines.h
+my_integer.o: $(hdrdir)/ruby/intern.h
+my_integer.o: $(hdrdir)/ruby/internal/abi.h
+my_integer.o: $(hdrdir)/ruby/internal/anyargs.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+my_integer.o: $(hdrdir)/ruby/internal/assume.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/artificial.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/cold.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/const.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/error.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/format.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/noalias.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/noinline.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/pure.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/restrict.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/warning.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/weakref.h
+my_integer.o: $(hdrdir)/ruby/internal/cast.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_since.h
+my_integer.o: $(hdrdir)/ruby/internal/config.h
+my_integer.o: $(hdrdir)/ruby/internal/constant_p.h
+my_integer.o: $(hdrdir)/ruby/internal/core.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rarray.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rbasic.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rbignum.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rclass.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rdata.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rfile.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rhash.h
+my_integer.o: $(hdrdir)/ruby/internal/core/robject.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rregexp.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rstring.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rstruct.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+my_integer.o: $(hdrdir)/ruby/internal/ctype.h
+my_integer.o: $(hdrdir)/ruby/internal/dllexport.h
+my_integer.o: $(hdrdir)/ruby/internal/dosish.h
+my_integer.o: $(hdrdir)/ruby/internal/error.h
+my_integer.o: $(hdrdir)/ruby/internal/eval.h
+my_integer.o: $(hdrdir)/ruby/internal/event.h
+my_integer.o: $(hdrdir)/ruby/internal/fl_type.h
+my_integer.o: $(hdrdir)/ruby/internal/gc.h
+my_integer.o: $(hdrdir)/ruby/internal/glob.h
+my_integer.o: $(hdrdir)/ruby/internal/globals.h
+my_integer.o: $(hdrdir)/ruby/internal/has/attribute.h
+my_integer.o: $(hdrdir)/ruby/internal/has/builtin.h
+my_integer.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+my_integer.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+my_integer.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+my_integer.o: $(hdrdir)/ruby/internal/has/extension.h
+my_integer.o: $(hdrdir)/ruby/internal/has/feature.h
+my_integer.o: $(hdrdir)/ruby/internal/has/warning.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/array.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/bignum.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/class.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/compar.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/complex.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/cont.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/dir.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/enum.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/error.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/eval.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/file.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/hash.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/io.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/load.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/marshal.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/numeric.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/object.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/parse.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/proc.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/process.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/random.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/range.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/rational.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/re.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/ruby.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/select.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/set.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/signal.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/string.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/struct.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/thread.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/time.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/variable.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/vm.h
+my_integer.o: $(hdrdir)/ruby/internal/interpreter.h
+my_integer.o: $(hdrdir)/ruby/internal/iterator.h
+my_integer.o: $(hdrdir)/ruby/internal/memory.h
+my_integer.o: $(hdrdir)/ruby/internal/method.h
+my_integer.o: $(hdrdir)/ruby/internal/module.h
+my_integer.o: $(hdrdir)/ruby/internal/newobj.h
+my_integer.o: $(hdrdir)/ruby/internal/scan_args.h
+my_integer.o: $(hdrdir)/ruby/internal/special_consts.h
+my_integer.o: $(hdrdir)/ruby/internal/static_assert.h
+my_integer.o: $(hdrdir)/ruby/internal/stdalign.h
+my_integer.o: $(hdrdir)/ruby/internal/stdbool.h
+my_integer.o: $(hdrdir)/ruby/internal/stdckdint.h
+my_integer.o: $(hdrdir)/ruby/internal/symbol.h
+my_integer.o: $(hdrdir)/ruby/internal/value.h
+my_integer.o: $(hdrdir)/ruby/internal/value_type.h
+my_integer.o: $(hdrdir)/ruby/internal/variable.h
+my_integer.o: $(hdrdir)/ruby/internal/warning_push.h
+my_integer.o: $(hdrdir)/ruby/internal/xmalloc.h
+my_integer.o: $(hdrdir)/ruby/missing.h
+my_integer.o: $(hdrdir)/ruby/ruby.h
+my_integer.o: $(hdrdir)/ruby/st.h
+my_integer.o: $(hdrdir)/ruby/subst.h
+my_integer.o: my_integer.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/integer/extconf.rb b/ext/-test-/integer/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/integer/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/integer/init.c b/ext/-test-/integer/init.c
new file mode 100644
index 0000000000..fc256ea16b
--- /dev/null
+++ b/ext/-test-/integer/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_integer(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "Integer", rb_cObject);
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/integer/my_integer.c b/ext/-test-/integer/my_integer.c
new file mode 100644
index 0000000000..94f14d2765
--- /dev/null
+++ b/ext/-test-/integer/my_integer.c
@@ -0,0 +1,20 @@
+#include "ruby.h"
+
+static const rb_data_type_t my_integer_type = {
+ "MyInteger", {0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static VALUE
+my_integer_s_new(VALUE klass)
+{
+ return TypedData_Wrap_Struct(klass, &my_integer_type, 0);
+}
+
+void
+Init_my_integer(VALUE klass)
+{
+ VALUE cMyInteger;
+
+ cMyInteger = rb_define_class_under(klass, "MyInteger", rb_cInteger);
+ rb_define_singleton_method(cMyInteger, "new", my_integer_s_new, 0);
+}
diff --git a/ext/-test-/iseq_load/depend b/ext/-test-/iseq_load/depend
new file mode 100644
index 0000000000..9361ddb938
--- /dev/null
+++ b/ext/-test-/iseq_load/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+iseq_load.o: $(RUBY_EXTCONF_H)
+iseq_load.o: $(arch_hdrdir)/ruby/config.h
+iseq_load.o: $(hdrdir)/ruby.h
+iseq_load.o: $(hdrdir)/ruby/assert.h
+iseq_load.o: $(hdrdir)/ruby/backward.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/assume.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/attributes.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/bool.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/inttypes.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/limits.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/long_long.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/stdalign.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/stdarg.h
+iseq_load.o: $(hdrdir)/ruby/defines.h
+iseq_load.o: $(hdrdir)/ruby/intern.h
+iseq_load.o: $(hdrdir)/ruby/internal/abi.h
+iseq_load.o: $(hdrdir)/ruby/internal/anyargs.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/assume.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/artificial.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/cold.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/const.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/error.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/format.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/noalias.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/noinline.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/pure.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/restrict.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/warning.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/weakref.h
+iseq_load.o: $(hdrdir)/ruby/internal/cast.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_since.h
+iseq_load.o: $(hdrdir)/ruby/internal/config.h
+iseq_load.o: $(hdrdir)/ruby/internal/constant_p.h
+iseq_load.o: $(hdrdir)/ruby/internal/core.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rarray.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rbasic.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rbignum.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rclass.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rdata.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rfile.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rhash.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/robject.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rregexp.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rstring.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rstruct.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+iseq_load.o: $(hdrdir)/ruby/internal/ctype.h
+iseq_load.o: $(hdrdir)/ruby/internal/dllexport.h
+iseq_load.o: $(hdrdir)/ruby/internal/dosish.h
+iseq_load.o: $(hdrdir)/ruby/internal/error.h
+iseq_load.o: $(hdrdir)/ruby/internal/eval.h
+iseq_load.o: $(hdrdir)/ruby/internal/event.h
+iseq_load.o: $(hdrdir)/ruby/internal/fl_type.h
+iseq_load.o: $(hdrdir)/ruby/internal/gc.h
+iseq_load.o: $(hdrdir)/ruby/internal/glob.h
+iseq_load.o: $(hdrdir)/ruby/internal/globals.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/attribute.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/builtin.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/extension.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/feature.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/warning.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/array.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/bignum.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/class.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/compar.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/complex.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/cont.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/dir.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/enum.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/error.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/eval.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/file.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/hash.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/io.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/load.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/marshal.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/numeric.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/object.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/parse.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/proc.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/process.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/random.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/range.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/rational.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/re.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/ruby.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/select.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/set.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/signal.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/string.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/struct.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/thread.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/time.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/variable.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/vm.h
+iseq_load.o: $(hdrdir)/ruby/internal/interpreter.h
+iseq_load.o: $(hdrdir)/ruby/internal/iterator.h
+iseq_load.o: $(hdrdir)/ruby/internal/memory.h
+iseq_load.o: $(hdrdir)/ruby/internal/method.h
+iseq_load.o: $(hdrdir)/ruby/internal/module.h
+iseq_load.o: $(hdrdir)/ruby/internal/newobj.h
+iseq_load.o: $(hdrdir)/ruby/internal/scan_args.h
+iseq_load.o: $(hdrdir)/ruby/internal/special_consts.h
+iseq_load.o: $(hdrdir)/ruby/internal/static_assert.h
+iseq_load.o: $(hdrdir)/ruby/internal/stdalign.h
+iseq_load.o: $(hdrdir)/ruby/internal/stdbool.h
+iseq_load.o: $(hdrdir)/ruby/internal/stdckdint.h
+iseq_load.o: $(hdrdir)/ruby/internal/symbol.h
+iseq_load.o: $(hdrdir)/ruby/internal/value.h
+iseq_load.o: $(hdrdir)/ruby/internal/value_type.h
+iseq_load.o: $(hdrdir)/ruby/internal/variable.h
+iseq_load.o: $(hdrdir)/ruby/internal/warning_push.h
+iseq_load.o: $(hdrdir)/ruby/internal/xmalloc.h
+iseq_load.o: $(hdrdir)/ruby/missing.h
+iseq_load.o: $(hdrdir)/ruby/ruby.h
+iseq_load.o: $(hdrdir)/ruby/st.h
+iseq_load.o: $(hdrdir)/ruby/subst.h
+iseq_load.o: iseq_load.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/iseq_load/extconf.rb b/ext/-test-/iseq_load/extconf.rb
new file mode 100644
index 0000000000..5858870138
--- /dev/null
+++ b/ext/-test-/iseq_load/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/iseq_load")
diff --git a/ext/-test-/iseq_load/iseq_load.c b/ext/-test-/iseq_load/iseq_load.c
new file mode 100644
index 0000000000..b4b9a8aa3d
--- /dev/null
+++ b/ext/-test-/iseq_load/iseq_load.c
@@ -0,0 +1,21 @@
+#include <ruby.h>
+
+VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt);
+
+static VALUE
+iseq_load(int argc, VALUE *argv, VALUE self)
+{
+ VALUE data, opt = Qnil;
+
+ rb_scan_args(argc, argv, "11", &data, &opt);
+
+ return rb_iseq_load(data, 0, opt);
+}
+
+void
+Init_iseq_load(void)
+{
+ VALUE rb_cISeq = rb_path2class("RubyVM::InstructionSequence");
+
+ rb_define_singleton_method(rb_cISeq, "iseq_load", iseq_load, -1);
+}
diff --git a/ext/-test-/iter/break.c b/ext/-test-/iter/break.c
new file mode 100644
index 0000000000..4d43c5d0cf
--- /dev/null
+++ b/ext/-test-/iter/break.c
@@ -0,0 +1,25 @@
+#include <ruby.h>
+
+static VALUE
+iter_break(VALUE self)
+{
+ rb_iter_break();
+
+ UNREACHABLE_RETURN(Qnil);
+}
+
+static VALUE
+iter_break_value(VALUE self, VALUE val)
+{
+ rb_iter_break_value(val);
+
+ UNREACHABLE_RETURN(Qnil);
+}
+
+void
+Init_break(VALUE klass)
+{
+ VALUE breakable = rb_define_module_under(klass, "Breakable");
+ rb_define_module_function(breakable, "iter_break", iter_break, 0);
+ rb_define_module_function(breakable, "iter_break_value", iter_break_value, 1);
+}
diff --git a/ext/-test-/iter/depend b/ext/-test-/iter/depend
new file mode 100644
index 0000000000..161947382c
--- /dev/null
+++ b/ext/-test-/iter/depend
@@ -0,0 +1,485 @@
+# AUTOGENERATED DEPENDENCIES START
+break.o: $(RUBY_EXTCONF_H)
+break.o: $(arch_hdrdir)/ruby/config.h
+break.o: $(hdrdir)/ruby.h
+break.o: $(hdrdir)/ruby/assert.h
+break.o: $(hdrdir)/ruby/backward.h
+break.o: $(hdrdir)/ruby/backward/2/assume.h
+break.o: $(hdrdir)/ruby/backward/2/attributes.h
+break.o: $(hdrdir)/ruby/backward/2/bool.h
+break.o: $(hdrdir)/ruby/backward/2/inttypes.h
+break.o: $(hdrdir)/ruby/backward/2/limits.h
+break.o: $(hdrdir)/ruby/backward/2/long_long.h
+break.o: $(hdrdir)/ruby/backward/2/stdalign.h
+break.o: $(hdrdir)/ruby/backward/2/stdarg.h
+break.o: $(hdrdir)/ruby/defines.h
+break.o: $(hdrdir)/ruby/intern.h
+break.o: $(hdrdir)/ruby/internal/abi.h
+break.o: $(hdrdir)/ruby/internal/anyargs.h
+break.o: $(hdrdir)/ruby/internal/arithmetic.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+break.o: $(hdrdir)/ruby/internal/assume.h
+break.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+break.o: $(hdrdir)/ruby/internal/attr/artificial.h
+break.o: $(hdrdir)/ruby/internal/attr/cold.h
+break.o: $(hdrdir)/ruby/internal/attr/const.h
+break.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+break.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+break.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+break.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+break.o: $(hdrdir)/ruby/internal/attr/error.h
+break.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+break.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+break.o: $(hdrdir)/ruby/internal/attr/format.h
+break.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+break.o: $(hdrdir)/ruby/internal/attr/noalias.h
+break.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+break.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+break.o: $(hdrdir)/ruby/internal/attr/noinline.h
+break.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+break.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+break.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+break.o: $(hdrdir)/ruby/internal/attr/pure.h
+break.o: $(hdrdir)/ruby/internal/attr/restrict.h
+break.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+break.o: $(hdrdir)/ruby/internal/attr/warning.h
+break.o: $(hdrdir)/ruby/internal/attr/weakref.h
+break.o: $(hdrdir)/ruby/internal/cast.h
+break.o: $(hdrdir)/ruby/internal/compiler_is.h
+break.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+break.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+break.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+break.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+break.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+break.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+break.o: $(hdrdir)/ruby/internal/compiler_since.h
+break.o: $(hdrdir)/ruby/internal/config.h
+break.o: $(hdrdir)/ruby/internal/constant_p.h
+break.o: $(hdrdir)/ruby/internal/core.h
+break.o: $(hdrdir)/ruby/internal/core/rarray.h
+break.o: $(hdrdir)/ruby/internal/core/rbasic.h
+break.o: $(hdrdir)/ruby/internal/core/rbignum.h
+break.o: $(hdrdir)/ruby/internal/core/rclass.h
+break.o: $(hdrdir)/ruby/internal/core/rdata.h
+break.o: $(hdrdir)/ruby/internal/core/rfile.h
+break.o: $(hdrdir)/ruby/internal/core/rhash.h
+break.o: $(hdrdir)/ruby/internal/core/robject.h
+break.o: $(hdrdir)/ruby/internal/core/rregexp.h
+break.o: $(hdrdir)/ruby/internal/core/rstring.h
+break.o: $(hdrdir)/ruby/internal/core/rstruct.h
+break.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+break.o: $(hdrdir)/ruby/internal/ctype.h
+break.o: $(hdrdir)/ruby/internal/dllexport.h
+break.o: $(hdrdir)/ruby/internal/dosish.h
+break.o: $(hdrdir)/ruby/internal/error.h
+break.o: $(hdrdir)/ruby/internal/eval.h
+break.o: $(hdrdir)/ruby/internal/event.h
+break.o: $(hdrdir)/ruby/internal/fl_type.h
+break.o: $(hdrdir)/ruby/internal/gc.h
+break.o: $(hdrdir)/ruby/internal/glob.h
+break.o: $(hdrdir)/ruby/internal/globals.h
+break.o: $(hdrdir)/ruby/internal/has/attribute.h
+break.o: $(hdrdir)/ruby/internal/has/builtin.h
+break.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+break.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+break.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+break.o: $(hdrdir)/ruby/internal/has/extension.h
+break.o: $(hdrdir)/ruby/internal/has/feature.h
+break.o: $(hdrdir)/ruby/internal/has/warning.h
+break.o: $(hdrdir)/ruby/internal/intern/array.h
+break.o: $(hdrdir)/ruby/internal/intern/bignum.h
+break.o: $(hdrdir)/ruby/internal/intern/class.h
+break.o: $(hdrdir)/ruby/internal/intern/compar.h
+break.o: $(hdrdir)/ruby/internal/intern/complex.h
+break.o: $(hdrdir)/ruby/internal/intern/cont.h
+break.o: $(hdrdir)/ruby/internal/intern/dir.h
+break.o: $(hdrdir)/ruby/internal/intern/enum.h
+break.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+break.o: $(hdrdir)/ruby/internal/intern/error.h
+break.o: $(hdrdir)/ruby/internal/intern/eval.h
+break.o: $(hdrdir)/ruby/internal/intern/file.h
+break.o: $(hdrdir)/ruby/internal/intern/hash.h
+break.o: $(hdrdir)/ruby/internal/intern/io.h
+break.o: $(hdrdir)/ruby/internal/intern/load.h
+break.o: $(hdrdir)/ruby/internal/intern/marshal.h
+break.o: $(hdrdir)/ruby/internal/intern/numeric.h
+break.o: $(hdrdir)/ruby/internal/intern/object.h
+break.o: $(hdrdir)/ruby/internal/intern/parse.h
+break.o: $(hdrdir)/ruby/internal/intern/proc.h
+break.o: $(hdrdir)/ruby/internal/intern/process.h
+break.o: $(hdrdir)/ruby/internal/intern/random.h
+break.o: $(hdrdir)/ruby/internal/intern/range.h
+break.o: $(hdrdir)/ruby/internal/intern/rational.h
+break.o: $(hdrdir)/ruby/internal/intern/re.h
+break.o: $(hdrdir)/ruby/internal/intern/ruby.h
+break.o: $(hdrdir)/ruby/internal/intern/select.h
+break.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+break.o: $(hdrdir)/ruby/internal/intern/set.h
+break.o: $(hdrdir)/ruby/internal/intern/signal.h
+break.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+break.o: $(hdrdir)/ruby/internal/intern/string.h
+break.o: $(hdrdir)/ruby/internal/intern/struct.h
+break.o: $(hdrdir)/ruby/internal/intern/thread.h
+break.o: $(hdrdir)/ruby/internal/intern/time.h
+break.o: $(hdrdir)/ruby/internal/intern/variable.h
+break.o: $(hdrdir)/ruby/internal/intern/vm.h
+break.o: $(hdrdir)/ruby/internal/interpreter.h
+break.o: $(hdrdir)/ruby/internal/iterator.h
+break.o: $(hdrdir)/ruby/internal/memory.h
+break.o: $(hdrdir)/ruby/internal/method.h
+break.o: $(hdrdir)/ruby/internal/module.h
+break.o: $(hdrdir)/ruby/internal/newobj.h
+break.o: $(hdrdir)/ruby/internal/scan_args.h
+break.o: $(hdrdir)/ruby/internal/special_consts.h
+break.o: $(hdrdir)/ruby/internal/static_assert.h
+break.o: $(hdrdir)/ruby/internal/stdalign.h
+break.o: $(hdrdir)/ruby/internal/stdbool.h
+break.o: $(hdrdir)/ruby/internal/stdckdint.h
+break.o: $(hdrdir)/ruby/internal/symbol.h
+break.o: $(hdrdir)/ruby/internal/value.h
+break.o: $(hdrdir)/ruby/internal/value_type.h
+break.o: $(hdrdir)/ruby/internal/variable.h
+break.o: $(hdrdir)/ruby/internal/warning_push.h
+break.o: $(hdrdir)/ruby/internal/xmalloc.h
+break.o: $(hdrdir)/ruby/missing.h
+break.o: $(hdrdir)/ruby/ruby.h
+break.o: $(hdrdir)/ruby/st.h
+break.o: $(hdrdir)/ruby/subst.h
+break.o: break.c
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+yield.o: $(RUBY_EXTCONF_H)
+yield.o: $(arch_hdrdir)/ruby/config.h
+yield.o: $(hdrdir)/ruby.h
+yield.o: $(hdrdir)/ruby/assert.h
+yield.o: $(hdrdir)/ruby/backward.h
+yield.o: $(hdrdir)/ruby/backward/2/assume.h
+yield.o: $(hdrdir)/ruby/backward/2/attributes.h
+yield.o: $(hdrdir)/ruby/backward/2/bool.h
+yield.o: $(hdrdir)/ruby/backward/2/inttypes.h
+yield.o: $(hdrdir)/ruby/backward/2/limits.h
+yield.o: $(hdrdir)/ruby/backward/2/long_long.h
+yield.o: $(hdrdir)/ruby/backward/2/stdalign.h
+yield.o: $(hdrdir)/ruby/backward/2/stdarg.h
+yield.o: $(hdrdir)/ruby/defines.h
+yield.o: $(hdrdir)/ruby/intern.h
+yield.o: $(hdrdir)/ruby/internal/abi.h
+yield.o: $(hdrdir)/ruby/internal/anyargs.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+yield.o: $(hdrdir)/ruby/internal/assume.h
+yield.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+yield.o: $(hdrdir)/ruby/internal/attr/artificial.h
+yield.o: $(hdrdir)/ruby/internal/attr/cold.h
+yield.o: $(hdrdir)/ruby/internal/attr/const.h
+yield.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+yield.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+yield.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+yield.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+yield.o: $(hdrdir)/ruby/internal/attr/error.h
+yield.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+yield.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+yield.o: $(hdrdir)/ruby/internal/attr/format.h
+yield.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+yield.o: $(hdrdir)/ruby/internal/attr/noalias.h
+yield.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+yield.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+yield.o: $(hdrdir)/ruby/internal/attr/noinline.h
+yield.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+yield.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+yield.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+yield.o: $(hdrdir)/ruby/internal/attr/pure.h
+yield.o: $(hdrdir)/ruby/internal/attr/restrict.h
+yield.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+yield.o: $(hdrdir)/ruby/internal/attr/warning.h
+yield.o: $(hdrdir)/ruby/internal/attr/weakref.h
+yield.o: $(hdrdir)/ruby/internal/cast.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+yield.o: $(hdrdir)/ruby/internal/compiler_since.h
+yield.o: $(hdrdir)/ruby/internal/config.h
+yield.o: $(hdrdir)/ruby/internal/constant_p.h
+yield.o: $(hdrdir)/ruby/internal/core.h
+yield.o: $(hdrdir)/ruby/internal/core/rarray.h
+yield.o: $(hdrdir)/ruby/internal/core/rbasic.h
+yield.o: $(hdrdir)/ruby/internal/core/rbignum.h
+yield.o: $(hdrdir)/ruby/internal/core/rclass.h
+yield.o: $(hdrdir)/ruby/internal/core/rdata.h
+yield.o: $(hdrdir)/ruby/internal/core/rfile.h
+yield.o: $(hdrdir)/ruby/internal/core/rhash.h
+yield.o: $(hdrdir)/ruby/internal/core/robject.h
+yield.o: $(hdrdir)/ruby/internal/core/rregexp.h
+yield.o: $(hdrdir)/ruby/internal/core/rstring.h
+yield.o: $(hdrdir)/ruby/internal/core/rstruct.h
+yield.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+yield.o: $(hdrdir)/ruby/internal/ctype.h
+yield.o: $(hdrdir)/ruby/internal/dllexport.h
+yield.o: $(hdrdir)/ruby/internal/dosish.h
+yield.o: $(hdrdir)/ruby/internal/error.h
+yield.o: $(hdrdir)/ruby/internal/eval.h
+yield.o: $(hdrdir)/ruby/internal/event.h
+yield.o: $(hdrdir)/ruby/internal/fl_type.h
+yield.o: $(hdrdir)/ruby/internal/gc.h
+yield.o: $(hdrdir)/ruby/internal/glob.h
+yield.o: $(hdrdir)/ruby/internal/globals.h
+yield.o: $(hdrdir)/ruby/internal/has/attribute.h
+yield.o: $(hdrdir)/ruby/internal/has/builtin.h
+yield.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+yield.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+yield.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+yield.o: $(hdrdir)/ruby/internal/has/extension.h
+yield.o: $(hdrdir)/ruby/internal/has/feature.h
+yield.o: $(hdrdir)/ruby/internal/has/warning.h
+yield.o: $(hdrdir)/ruby/internal/intern/array.h
+yield.o: $(hdrdir)/ruby/internal/intern/bignum.h
+yield.o: $(hdrdir)/ruby/internal/intern/class.h
+yield.o: $(hdrdir)/ruby/internal/intern/compar.h
+yield.o: $(hdrdir)/ruby/internal/intern/complex.h
+yield.o: $(hdrdir)/ruby/internal/intern/cont.h
+yield.o: $(hdrdir)/ruby/internal/intern/dir.h
+yield.o: $(hdrdir)/ruby/internal/intern/enum.h
+yield.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+yield.o: $(hdrdir)/ruby/internal/intern/error.h
+yield.o: $(hdrdir)/ruby/internal/intern/eval.h
+yield.o: $(hdrdir)/ruby/internal/intern/file.h
+yield.o: $(hdrdir)/ruby/internal/intern/hash.h
+yield.o: $(hdrdir)/ruby/internal/intern/io.h
+yield.o: $(hdrdir)/ruby/internal/intern/load.h
+yield.o: $(hdrdir)/ruby/internal/intern/marshal.h
+yield.o: $(hdrdir)/ruby/internal/intern/numeric.h
+yield.o: $(hdrdir)/ruby/internal/intern/object.h
+yield.o: $(hdrdir)/ruby/internal/intern/parse.h
+yield.o: $(hdrdir)/ruby/internal/intern/proc.h
+yield.o: $(hdrdir)/ruby/internal/intern/process.h
+yield.o: $(hdrdir)/ruby/internal/intern/random.h
+yield.o: $(hdrdir)/ruby/internal/intern/range.h
+yield.o: $(hdrdir)/ruby/internal/intern/rational.h
+yield.o: $(hdrdir)/ruby/internal/intern/re.h
+yield.o: $(hdrdir)/ruby/internal/intern/ruby.h
+yield.o: $(hdrdir)/ruby/internal/intern/select.h
+yield.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+yield.o: $(hdrdir)/ruby/internal/intern/set.h
+yield.o: $(hdrdir)/ruby/internal/intern/signal.h
+yield.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+yield.o: $(hdrdir)/ruby/internal/intern/string.h
+yield.o: $(hdrdir)/ruby/internal/intern/struct.h
+yield.o: $(hdrdir)/ruby/internal/intern/thread.h
+yield.o: $(hdrdir)/ruby/internal/intern/time.h
+yield.o: $(hdrdir)/ruby/internal/intern/variable.h
+yield.o: $(hdrdir)/ruby/internal/intern/vm.h
+yield.o: $(hdrdir)/ruby/internal/interpreter.h
+yield.o: $(hdrdir)/ruby/internal/iterator.h
+yield.o: $(hdrdir)/ruby/internal/memory.h
+yield.o: $(hdrdir)/ruby/internal/method.h
+yield.o: $(hdrdir)/ruby/internal/module.h
+yield.o: $(hdrdir)/ruby/internal/newobj.h
+yield.o: $(hdrdir)/ruby/internal/scan_args.h
+yield.o: $(hdrdir)/ruby/internal/special_consts.h
+yield.o: $(hdrdir)/ruby/internal/static_assert.h
+yield.o: $(hdrdir)/ruby/internal/stdalign.h
+yield.o: $(hdrdir)/ruby/internal/stdbool.h
+yield.o: $(hdrdir)/ruby/internal/stdckdint.h
+yield.o: $(hdrdir)/ruby/internal/symbol.h
+yield.o: $(hdrdir)/ruby/internal/value.h
+yield.o: $(hdrdir)/ruby/internal/value_type.h
+yield.o: $(hdrdir)/ruby/internal/variable.h
+yield.o: $(hdrdir)/ruby/internal/warning_push.h
+yield.o: $(hdrdir)/ruby/internal/xmalloc.h
+yield.o: $(hdrdir)/ruby/missing.h
+yield.o: $(hdrdir)/ruby/ruby.h
+yield.o: $(hdrdir)/ruby/st.h
+yield.o: $(hdrdir)/ruby/subst.h
+yield.o: yield.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/iter/extconf.rb b/ext/-test-/iter/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/iter/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/iter/init.c b/ext/-test-/iter/init.c
new file mode 100644
index 0000000000..a074ec46a9
--- /dev/null
+++ b/ext/-test-/iter/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_iter(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_module_under(mBug, "Iter");
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/iter/yield.c b/ext/-test-/iter/yield.c
new file mode 100644
index 0000000000..0f6f3e87eb
--- /dev/null
+++ b/ext/-test-/iter/yield.c
@@ -0,0 +1,16 @@
+#include <ruby.h>
+
+static VALUE
+yield_block(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
+ return rb_block_call_kw(self, rb_to_id(argv[0]), argc-1, argv+1, rb_yield_block, 0, RB_PASS_CALLED_KEYWORDS);
+}
+
+void
+Init_yield(VALUE klass)
+{
+ VALUE yield = rb_define_module_under(klass, "Yield");
+
+ rb_define_method(yield, "yield_block", yield_block, -1);
+}
diff --git a/ext/-test-/load/dot.dot/depend b/ext/-test-/load/dot.dot/depend
new file mode 100644
index 0000000000..339837d183
--- /dev/null
+++ b/ext/-test-/load/dot.dot/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+dot.dot.o: $(RUBY_EXTCONF_H)
+dot.dot.o: $(arch_hdrdir)/ruby/config.h
+dot.dot.o: $(hdrdir)/ruby.h
+dot.dot.o: $(hdrdir)/ruby/assert.h
+dot.dot.o: $(hdrdir)/ruby/backward.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/assume.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/attributes.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/bool.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/inttypes.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/limits.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/long_long.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/stdalign.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/stdarg.h
+dot.dot.o: $(hdrdir)/ruby/defines.h
+dot.dot.o: $(hdrdir)/ruby/intern.h
+dot.dot.o: $(hdrdir)/ruby/internal/abi.h
+dot.dot.o: $(hdrdir)/ruby/internal/anyargs.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/assume.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/artificial.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/cold.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/const.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/error.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/format.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/noalias.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/noinline.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/pure.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/restrict.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/warning.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/weakref.h
+dot.dot.o: $(hdrdir)/ruby/internal/cast.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_since.h
+dot.dot.o: $(hdrdir)/ruby/internal/config.h
+dot.dot.o: $(hdrdir)/ruby/internal/constant_p.h
+dot.dot.o: $(hdrdir)/ruby/internal/core.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rarray.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rbasic.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rbignum.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rclass.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rdata.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rfile.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rhash.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/robject.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rregexp.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rstring.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rstruct.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+dot.dot.o: $(hdrdir)/ruby/internal/ctype.h
+dot.dot.o: $(hdrdir)/ruby/internal/dllexport.h
+dot.dot.o: $(hdrdir)/ruby/internal/dosish.h
+dot.dot.o: $(hdrdir)/ruby/internal/error.h
+dot.dot.o: $(hdrdir)/ruby/internal/eval.h
+dot.dot.o: $(hdrdir)/ruby/internal/event.h
+dot.dot.o: $(hdrdir)/ruby/internal/fl_type.h
+dot.dot.o: $(hdrdir)/ruby/internal/gc.h
+dot.dot.o: $(hdrdir)/ruby/internal/glob.h
+dot.dot.o: $(hdrdir)/ruby/internal/globals.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/attribute.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/builtin.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/extension.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/feature.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/warning.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/array.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/bignum.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/class.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/compar.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/complex.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/cont.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/dir.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/enum.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/error.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/eval.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/file.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/hash.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/io.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/load.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/marshal.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/numeric.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/object.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/parse.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/proc.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/process.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/random.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/range.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/rational.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/re.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/ruby.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/select.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/set.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/signal.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/string.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/struct.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/thread.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/time.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/variable.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/vm.h
+dot.dot.o: $(hdrdir)/ruby/internal/interpreter.h
+dot.dot.o: $(hdrdir)/ruby/internal/iterator.h
+dot.dot.o: $(hdrdir)/ruby/internal/memory.h
+dot.dot.o: $(hdrdir)/ruby/internal/method.h
+dot.dot.o: $(hdrdir)/ruby/internal/module.h
+dot.dot.o: $(hdrdir)/ruby/internal/newobj.h
+dot.dot.o: $(hdrdir)/ruby/internal/scan_args.h
+dot.dot.o: $(hdrdir)/ruby/internal/special_consts.h
+dot.dot.o: $(hdrdir)/ruby/internal/static_assert.h
+dot.dot.o: $(hdrdir)/ruby/internal/stdalign.h
+dot.dot.o: $(hdrdir)/ruby/internal/stdbool.h
+dot.dot.o: $(hdrdir)/ruby/internal/stdckdint.h
+dot.dot.o: $(hdrdir)/ruby/internal/symbol.h
+dot.dot.o: $(hdrdir)/ruby/internal/value.h
+dot.dot.o: $(hdrdir)/ruby/internal/value_type.h
+dot.dot.o: $(hdrdir)/ruby/internal/variable.h
+dot.dot.o: $(hdrdir)/ruby/internal/warning_push.h
+dot.dot.o: $(hdrdir)/ruby/internal/xmalloc.h
+dot.dot.o: $(hdrdir)/ruby/missing.h
+dot.dot.o: $(hdrdir)/ruby/ruby.h
+dot.dot.o: $(hdrdir)/ruby/st.h
+dot.dot.o: $(hdrdir)/ruby/subst.h
+dot.dot.o: dot.dot.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/load/dot.dot/dot.dot.c b/ext/-test-/load/dot.dot/dot.dot.c
new file mode 100644
index 0000000000..ce7563bf8d
--- /dev/null
+++ b/ext/-test-/load/dot.dot/dot.dot.c
@@ -0,0 +1,3 @@
+#include "ruby.h"
+
+void Init_dot(void) {}
diff --git a/ext/-test-/load/dot.dot/extconf.rb b/ext/-test-/load/dot.dot/extconf.rb
new file mode 100644
index 0000000000..13ebb1ffb4
--- /dev/null
+++ b/ext/-test-/load/dot.dot/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/load/dot.dot")
diff --git a/ext/-test-/load/protect/depend b/ext/-test-/load/protect/depend
new file mode 100644
index 0000000000..c76c6f88ed
--- /dev/null
+++ b/ext/-test-/load/protect/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+protect.o: $(RUBY_EXTCONF_H)
+protect.o: $(arch_hdrdir)/ruby/config.h
+protect.o: $(hdrdir)/ruby.h
+protect.o: $(hdrdir)/ruby/assert.h
+protect.o: $(hdrdir)/ruby/backward.h
+protect.o: $(hdrdir)/ruby/backward/2/assume.h
+protect.o: $(hdrdir)/ruby/backward/2/attributes.h
+protect.o: $(hdrdir)/ruby/backward/2/bool.h
+protect.o: $(hdrdir)/ruby/backward/2/inttypes.h
+protect.o: $(hdrdir)/ruby/backward/2/limits.h
+protect.o: $(hdrdir)/ruby/backward/2/long_long.h
+protect.o: $(hdrdir)/ruby/backward/2/stdalign.h
+protect.o: $(hdrdir)/ruby/backward/2/stdarg.h
+protect.o: $(hdrdir)/ruby/defines.h
+protect.o: $(hdrdir)/ruby/intern.h
+protect.o: $(hdrdir)/ruby/internal/abi.h
+protect.o: $(hdrdir)/ruby/internal/anyargs.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+protect.o: $(hdrdir)/ruby/internal/assume.h
+protect.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+protect.o: $(hdrdir)/ruby/internal/attr/artificial.h
+protect.o: $(hdrdir)/ruby/internal/attr/cold.h
+protect.o: $(hdrdir)/ruby/internal/attr/const.h
+protect.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+protect.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+protect.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+protect.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+protect.o: $(hdrdir)/ruby/internal/attr/error.h
+protect.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+protect.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+protect.o: $(hdrdir)/ruby/internal/attr/format.h
+protect.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+protect.o: $(hdrdir)/ruby/internal/attr/noalias.h
+protect.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+protect.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+protect.o: $(hdrdir)/ruby/internal/attr/noinline.h
+protect.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+protect.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+protect.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+protect.o: $(hdrdir)/ruby/internal/attr/pure.h
+protect.o: $(hdrdir)/ruby/internal/attr/restrict.h
+protect.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+protect.o: $(hdrdir)/ruby/internal/attr/warning.h
+protect.o: $(hdrdir)/ruby/internal/attr/weakref.h
+protect.o: $(hdrdir)/ruby/internal/cast.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+protect.o: $(hdrdir)/ruby/internal/compiler_since.h
+protect.o: $(hdrdir)/ruby/internal/config.h
+protect.o: $(hdrdir)/ruby/internal/constant_p.h
+protect.o: $(hdrdir)/ruby/internal/core.h
+protect.o: $(hdrdir)/ruby/internal/core/rarray.h
+protect.o: $(hdrdir)/ruby/internal/core/rbasic.h
+protect.o: $(hdrdir)/ruby/internal/core/rbignum.h
+protect.o: $(hdrdir)/ruby/internal/core/rclass.h
+protect.o: $(hdrdir)/ruby/internal/core/rdata.h
+protect.o: $(hdrdir)/ruby/internal/core/rfile.h
+protect.o: $(hdrdir)/ruby/internal/core/rhash.h
+protect.o: $(hdrdir)/ruby/internal/core/robject.h
+protect.o: $(hdrdir)/ruby/internal/core/rregexp.h
+protect.o: $(hdrdir)/ruby/internal/core/rstring.h
+protect.o: $(hdrdir)/ruby/internal/core/rstruct.h
+protect.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+protect.o: $(hdrdir)/ruby/internal/ctype.h
+protect.o: $(hdrdir)/ruby/internal/dllexport.h
+protect.o: $(hdrdir)/ruby/internal/dosish.h
+protect.o: $(hdrdir)/ruby/internal/error.h
+protect.o: $(hdrdir)/ruby/internal/eval.h
+protect.o: $(hdrdir)/ruby/internal/event.h
+protect.o: $(hdrdir)/ruby/internal/fl_type.h
+protect.o: $(hdrdir)/ruby/internal/gc.h
+protect.o: $(hdrdir)/ruby/internal/glob.h
+protect.o: $(hdrdir)/ruby/internal/globals.h
+protect.o: $(hdrdir)/ruby/internal/has/attribute.h
+protect.o: $(hdrdir)/ruby/internal/has/builtin.h
+protect.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+protect.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+protect.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+protect.o: $(hdrdir)/ruby/internal/has/extension.h
+protect.o: $(hdrdir)/ruby/internal/has/feature.h
+protect.o: $(hdrdir)/ruby/internal/has/warning.h
+protect.o: $(hdrdir)/ruby/internal/intern/array.h
+protect.o: $(hdrdir)/ruby/internal/intern/bignum.h
+protect.o: $(hdrdir)/ruby/internal/intern/class.h
+protect.o: $(hdrdir)/ruby/internal/intern/compar.h
+protect.o: $(hdrdir)/ruby/internal/intern/complex.h
+protect.o: $(hdrdir)/ruby/internal/intern/cont.h
+protect.o: $(hdrdir)/ruby/internal/intern/dir.h
+protect.o: $(hdrdir)/ruby/internal/intern/enum.h
+protect.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+protect.o: $(hdrdir)/ruby/internal/intern/error.h
+protect.o: $(hdrdir)/ruby/internal/intern/eval.h
+protect.o: $(hdrdir)/ruby/internal/intern/file.h
+protect.o: $(hdrdir)/ruby/internal/intern/hash.h
+protect.o: $(hdrdir)/ruby/internal/intern/io.h
+protect.o: $(hdrdir)/ruby/internal/intern/load.h
+protect.o: $(hdrdir)/ruby/internal/intern/marshal.h
+protect.o: $(hdrdir)/ruby/internal/intern/numeric.h
+protect.o: $(hdrdir)/ruby/internal/intern/object.h
+protect.o: $(hdrdir)/ruby/internal/intern/parse.h
+protect.o: $(hdrdir)/ruby/internal/intern/proc.h
+protect.o: $(hdrdir)/ruby/internal/intern/process.h
+protect.o: $(hdrdir)/ruby/internal/intern/random.h
+protect.o: $(hdrdir)/ruby/internal/intern/range.h
+protect.o: $(hdrdir)/ruby/internal/intern/rational.h
+protect.o: $(hdrdir)/ruby/internal/intern/re.h
+protect.o: $(hdrdir)/ruby/internal/intern/ruby.h
+protect.o: $(hdrdir)/ruby/internal/intern/select.h
+protect.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+protect.o: $(hdrdir)/ruby/internal/intern/set.h
+protect.o: $(hdrdir)/ruby/internal/intern/signal.h
+protect.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+protect.o: $(hdrdir)/ruby/internal/intern/string.h
+protect.o: $(hdrdir)/ruby/internal/intern/struct.h
+protect.o: $(hdrdir)/ruby/internal/intern/thread.h
+protect.o: $(hdrdir)/ruby/internal/intern/time.h
+protect.o: $(hdrdir)/ruby/internal/intern/variable.h
+protect.o: $(hdrdir)/ruby/internal/intern/vm.h
+protect.o: $(hdrdir)/ruby/internal/interpreter.h
+protect.o: $(hdrdir)/ruby/internal/iterator.h
+protect.o: $(hdrdir)/ruby/internal/memory.h
+protect.o: $(hdrdir)/ruby/internal/method.h
+protect.o: $(hdrdir)/ruby/internal/module.h
+protect.o: $(hdrdir)/ruby/internal/newobj.h
+protect.o: $(hdrdir)/ruby/internal/scan_args.h
+protect.o: $(hdrdir)/ruby/internal/special_consts.h
+protect.o: $(hdrdir)/ruby/internal/static_assert.h
+protect.o: $(hdrdir)/ruby/internal/stdalign.h
+protect.o: $(hdrdir)/ruby/internal/stdbool.h
+protect.o: $(hdrdir)/ruby/internal/stdckdint.h
+protect.o: $(hdrdir)/ruby/internal/symbol.h
+protect.o: $(hdrdir)/ruby/internal/value.h
+protect.o: $(hdrdir)/ruby/internal/value_type.h
+protect.o: $(hdrdir)/ruby/internal/variable.h
+protect.o: $(hdrdir)/ruby/internal/warning_push.h
+protect.o: $(hdrdir)/ruby/internal/xmalloc.h
+protect.o: $(hdrdir)/ruby/missing.h
+protect.o: $(hdrdir)/ruby/ruby.h
+protect.o: $(hdrdir)/ruby/st.h
+protect.o: $(hdrdir)/ruby/subst.h
+protect.o: protect.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/load/protect/extconf.rb b/ext/-test-/load/protect/extconf.rb
new file mode 100644
index 0000000000..83c080de9c
--- /dev/null
+++ b/ext/-test-/load/protect/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/load/protect')
diff --git a/ext/-test-/load/protect/protect.c b/ext/-test-/load/protect/protect.c
new file mode 100644
index 0000000000..ccfbbb9ea0
--- /dev/null
+++ b/ext/-test-/load/protect/protect.c
@@ -0,0 +1,19 @@
+#include <ruby.h>
+
+static VALUE
+load_protect(int argc, VALUE *argv, VALUE self)
+{
+ int state;
+ VALUE path, wrap;
+ rb_scan_args(argc, argv, "11", &path, &wrap);
+ rb_load_protect(path, RTEST(wrap), &state);
+ if (state) rb_jump_tag(state);
+ return Qnil;
+}
+
+void
+Init_protect(void)
+{
+ VALUE mod = rb_define_module("Bug");
+ rb_define_singleton_method(mod, "load_protect", load_protect, -1);
+}
diff --git a/ext/-test-/load/resolve_symbol_resolver/depend b/ext/-test-/load/resolve_symbol_resolver/depend
new file mode 100644
index 0000000000..f422898b69
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_resolver/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+resolve_symbol_resolver.o: $(RUBY_EXTCONF_H)
+resolve_symbol_resolver.o: $(arch_hdrdir)/ruby/config.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/assert.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/assume.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/attributes.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/bool.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/inttypes.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/limits.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/long_long.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/stdalign.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/stdarg.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/defines.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/intern.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/abi.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/anyargs.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/assume.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/artificial.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/cold.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/const.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/error.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/format.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/noalias.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/noinline.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/pure.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/restrict.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/warning.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/weakref.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/cast.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_since.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/config.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/constant_p.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rarray.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rbasic.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rbignum.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rclass.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rdata.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rfile.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rhash.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/robject.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rregexp.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rstring.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rstruct.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/ctype.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/dllexport.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/dosish.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/error.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/eval.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/event.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/fl_type.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/gc.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/glob.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/globals.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/attribute.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/builtin.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/extension.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/feature.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/warning.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/array.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/bignum.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/class.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/compar.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/complex.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/cont.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/dir.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/enum.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/error.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/eval.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/file.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/hash.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/io.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/load.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/marshal.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/numeric.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/object.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/parse.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/proc.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/process.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/random.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/range.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/rational.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/re.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/ruby.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/select.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/set.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/signal.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/string.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/struct.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/thread.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/time.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/variable.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/vm.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/interpreter.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/iterator.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/memory.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/method.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/module.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/newobj.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/scan_args.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/special_consts.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/static_assert.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/stdalign.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/stdbool.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/stdckdint.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/symbol.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/value.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/value_type.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/variable.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/warning_push.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/xmalloc.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/missing.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/ruby.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/st.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/subst.h
+resolve_symbol_resolver.o: resolve_symbol_resolver.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/load/resolve_symbol_resolver/extconf.rb b/ext/-test-/load/resolve_symbol_resolver/extconf.rb
new file mode 100644
index 0000000000..2299efcfd3
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_resolver/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/load/resolve_symbol_resolver')
diff --git a/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c b/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c
new file mode 100644
index 0000000000..6cc07cc1f8
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c
@@ -0,0 +1,56 @@
+#include <ruby.h>
+#include "ruby/internal/intern/load.h"
+
+typedef VALUE(*target_func)(VALUE);
+
+static target_func rst_any_method;
+
+#define resolve_func(file, name) (target_func)(uintptr_t)rb_ext_resolve_symbol(file, name)
+VALUE
+rsr_any_method(VALUE klass)
+{
+ return rst_any_method((VALUE)NULL);
+}
+
+VALUE
+rsr_try_resolve_fname(VALUE klass)
+{
+ target_func rst_something_missing =
+ resolve_func("-test-/load/resolve_symbol_missing", "rst_any_method");
+ if (rst_something_missing == NULL) {
+ // This should be done in Init_*, so the error is LoadError
+ rb_raise(rb_eLoadError, "symbol not found: missing fname");
+ }
+ return Qtrue;
+}
+
+VALUE
+rsr_try_resolve_sname(VALUE klass)
+{
+ target_func rst_something_missing =
+ resolve_func("-test-/load/resolve_symbol_target", "rst_something_missing");
+ if (rst_something_missing == NULL) {
+ // This should be done in Init_*, so the error is LoadError
+ rb_raise(rb_eLoadError, "symbol not found: missing sname");
+ }
+ return Qtrue;
+}
+
+void
+Init_resolve_symbol_resolver(void)
+{
+ /*
+ * Resolving symbols at the head of Init_ because it raises LoadError (in cases).
+ * If the module and methods are defined before raising LoadError, retrying `require "this.so"` will
+ * cause re-defining those methods (and will be warned).
+ */
+ rst_any_method = resolve_func("-test-/load/resolve_symbol_target", "rst_any_method");
+ if (rst_any_method == NULL) {
+ rb_raise(rb_eLoadError, "resolve_symbol_target is not loaded");
+ }
+
+ VALUE mod = rb_define_module("ResolveSymbolResolver");
+ rb_define_singleton_method(mod, "any_method", rsr_any_method, 0);
+ rb_define_singleton_method(mod, "try_resolve_fname", rsr_try_resolve_fname, 0);
+ rb_define_singleton_method(mod, "try_resolve_sname", rsr_try_resolve_sname, 0);
+}
diff --git a/ext/-test-/load/resolve_symbol_target/depend b/ext/-test-/load/resolve_symbol_target/depend
new file mode 100644
index 0000000000..aa0b5327be
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_target/depend
@@ -0,0 +1,164 @@
+# AUTOGENERATED DEPENDENCIES START
+resolve_symbol_target.o: $(RUBY_EXTCONF_H)
+resolve_symbol_target.o: $(arch_hdrdir)/ruby/config.h
+resolve_symbol_target.o: $(hdrdir)/ruby.h
+resolve_symbol_target.o: $(hdrdir)/ruby/assert.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/assume.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/attributes.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/bool.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/inttypes.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/limits.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/long_long.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/stdalign.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/stdarg.h
+resolve_symbol_target.o: $(hdrdir)/ruby/defines.h
+resolve_symbol_target.o: $(hdrdir)/ruby/intern.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/abi.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/anyargs.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/assume.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/artificial.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/cold.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/const.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/error.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/format.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/noalias.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/noinline.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/pure.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/restrict.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/warning.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/weakref.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/cast.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_since.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/config.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/constant_p.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rarray.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rbasic.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rbignum.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rclass.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rdata.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rfile.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rhash.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/robject.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rregexp.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rstring.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rstruct.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/ctype.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/dllexport.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/dosish.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/error.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/eval.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/event.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/fl_type.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/gc.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/glob.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/globals.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/attribute.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/builtin.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/extension.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/feature.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/warning.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/array.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/bignum.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/class.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/compar.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/complex.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/cont.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/dir.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/enum.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/error.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/eval.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/file.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/hash.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/io.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/load.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/marshal.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/numeric.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/object.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/parse.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/proc.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/process.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/random.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/range.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/rational.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/re.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/ruby.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/select.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/set.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/signal.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/string.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/struct.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/thread.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/time.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/variable.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/vm.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/interpreter.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/iterator.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/memory.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/method.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/module.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/newobj.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/scan_args.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/special_consts.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/static_assert.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/stdalign.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/stdbool.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/stdckdint.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/symbol.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/value.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/value_type.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/variable.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/warning_push.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/xmalloc.h
+resolve_symbol_target.o: $(hdrdir)/ruby/missing.h
+resolve_symbol_target.o: $(hdrdir)/ruby/ruby.h
+resolve_symbol_target.o: $(hdrdir)/ruby/st.h
+resolve_symbol_target.o: $(hdrdir)/ruby/subst.h
+resolve_symbol_target.o: resolve_symbol_target.c
+resolve_symbol_target.o: resolve_symbol_target.h
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/load/resolve_symbol_target/extconf.rb b/ext/-test-/load/resolve_symbol_target/extconf.rb
new file mode 100644
index 0000000000..b5a99ca7f1
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_target/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/load/resolve_symbol_target')
diff --git a/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.c b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.c
new file mode 100644
index 0000000000..b5bc9e8ee0
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.c
@@ -0,0 +1,15 @@
+#include <ruby.h>
+#include "resolve_symbol_target.h"
+
+VALUE
+rst_any_method(VALUE klass)
+{
+ return rb_str_new_cstr("from target");
+}
+
+void
+Init_resolve_symbol_target(void)
+{
+ VALUE mod = rb_define_module("ResolveSymbolTarget");
+ rb_define_singleton_method(mod, "any_method", rst_any_method, 0);
+}
diff --git a/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.h b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.h
new file mode 100644
index 0000000000..847dcb7dd3
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.h
@@ -0,0 +1,4 @@
+#include <ruby.h>
+#include "ruby/internal/dllexport.h"
+
+RUBY_FUNC_EXPORTED VALUE rst_any_method(VALUE);
diff --git a/ext/-test-/load/stringify_symbols/depend b/ext/-test-/load/stringify_symbols/depend
new file mode 100644
index 0000000000..2d4d79a7b7
--- /dev/null
+++ b/ext/-test-/load/stringify_symbols/depend
@@ -0,0 +1,164 @@
+# AUTOGENERATED DEPENDENCIES START
+stringify_symbols.o: $(RUBY_EXTCONF_H)
+stringify_symbols.o: $(arch_hdrdir)/ruby/config.h
+stringify_symbols.o: $(hdrdir)/ruby.h
+stringify_symbols.o: $(hdrdir)/ruby/assert.h
+stringify_symbols.o: $(hdrdir)/ruby/backward.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/assume.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/attributes.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/bool.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/inttypes.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/limits.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/long_long.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/stdalign.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/stdarg.h
+stringify_symbols.o: $(hdrdir)/ruby/defines.h
+stringify_symbols.o: $(hdrdir)/ruby/intern.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/abi.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/anyargs.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/assume.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/artificial.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/cold.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/const.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/error.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/format.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/noalias.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/noinline.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/pure.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/restrict.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/warning.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/weakref.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/cast.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_since.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/config.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/constant_p.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rarray.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rbasic.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rbignum.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rclass.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rdata.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rfile.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rhash.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/robject.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rregexp.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rstring.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rstruct.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/ctype.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/dllexport.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/dosish.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/error.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/eval.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/event.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/fl_type.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/gc.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/glob.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/globals.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/attribute.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/builtin.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/extension.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/feature.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/warning.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/array.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/bignum.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/class.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/compar.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/complex.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/cont.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/dir.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/enum.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/error.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/eval.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/file.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/hash.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/io.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/load.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/marshal.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/numeric.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/object.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/parse.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/proc.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/process.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/random.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/range.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/rational.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/re.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/ruby.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/select.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/set.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/signal.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/string.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/struct.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/thread.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/time.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/variable.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/vm.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/interpreter.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/iterator.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/memory.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/method.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/module.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/newobj.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/scan_args.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/special_consts.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/static_assert.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/stdalign.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/stdbool.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/stdckdint.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/symbol.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/value.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/value_type.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/variable.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/warning_push.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/xmalloc.h
+stringify_symbols.o: $(hdrdir)/ruby/missing.h
+stringify_symbols.o: $(hdrdir)/ruby/ruby.h
+stringify_symbols.o: $(hdrdir)/ruby/st.h
+stringify_symbols.o: $(hdrdir)/ruby/subst.h
+stringify_symbols.o: $(hdrdir)/ruby/util.h
+stringify_symbols.o: stringify_symbols.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/load/stringify_symbols/extconf.rb b/ext/-test-/load/stringify_symbols/extconf.rb
new file mode 100644
index 0000000000..ac39c15f09
--- /dev/null
+++ b/ext/-test-/load/stringify_symbols/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/load/stringify_symbols')
diff --git a/ext/-test-/load/stringify_symbols/stringify_symbols.c b/ext/-test-/load/stringify_symbols/stringify_symbols.c
new file mode 100644
index 0000000000..11a5ee3bc5
--- /dev/null
+++ b/ext/-test-/load/stringify_symbols/stringify_symbols.c
@@ -0,0 +1,29 @@
+#include <ruby.h>
+#include "ruby/internal/intern/load.h"
+#include "ruby/util.h"
+
+#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
+# define UINTPTR2NUM ULL2NUM
+#elif SIZEOF_INTPTR_T == SIZEOF_LONG
+# define UINTPTR2NUM ULONG2NUM
+#else
+# define UINTPTR2NUM UINT2NUM
+#endif
+
+static VALUE
+stringify_symbol(VALUE klass, VALUE fname, VALUE sname)
+{
+ void *ptr = rb_ext_resolve_symbol(StringValueCStr(fname), StringValueCStr(sname));
+ if (ptr == NULL) {
+ return Qnil;
+ }
+ uintptr_t uintptr = (uintptr_t)ptr;
+ return UINTPTR2NUM(uintptr);
+}
+
+void
+Init_stringify_symbols(void)
+{
+ VALUE mod = rb_define_module("StringifySymbols");
+ rb_define_singleton_method(mod, "stringify_symbol", stringify_symbol, 2);
+}
diff --git a/ext/-test-/load/stringify_target/depend b/ext/-test-/load/stringify_target/depend
new file mode 100644
index 0000000000..c66575d4e4
--- /dev/null
+++ b/ext/-test-/load/stringify_target/depend
@@ -0,0 +1,164 @@
+# AUTOGENERATED DEPENDENCIES START
+stringify_target.o: $(RUBY_EXTCONF_H)
+stringify_target.o: $(arch_hdrdir)/ruby/config.h
+stringify_target.o: $(hdrdir)/ruby.h
+stringify_target.o: $(hdrdir)/ruby/assert.h
+stringify_target.o: $(hdrdir)/ruby/backward.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/assume.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/attributes.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/bool.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/inttypes.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/limits.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/long_long.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/stdalign.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/stdarg.h
+stringify_target.o: $(hdrdir)/ruby/defines.h
+stringify_target.o: $(hdrdir)/ruby/intern.h
+stringify_target.o: $(hdrdir)/ruby/internal/abi.h
+stringify_target.o: $(hdrdir)/ruby/internal/anyargs.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/assume.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/artificial.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/cold.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/const.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/error.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/format.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/noalias.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/noinline.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/pure.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/restrict.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/warning.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/weakref.h
+stringify_target.o: $(hdrdir)/ruby/internal/cast.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_since.h
+stringify_target.o: $(hdrdir)/ruby/internal/config.h
+stringify_target.o: $(hdrdir)/ruby/internal/constant_p.h
+stringify_target.o: $(hdrdir)/ruby/internal/core.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rarray.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rbasic.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rbignum.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rclass.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rdata.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rfile.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rhash.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/robject.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rregexp.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rstring.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rstruct.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+stringify_target.o: $(hdrdir)/ruby/internal/ctype.h
+stringify_target.o: $(hdrdir)/ruby/internal/dllexport.h
+stringify_target.o: $(hdrdir)/ruby/internal/dosish.h
+stringify_target.o: $(hdrdir)/ruby/internal/error.h
+stringify_target.o: $(hdrdir)/ruby/internal/eval.h
+stringify_target.o: $(hdrdir)/ruby/internal/event.h
+stringify_target.o: $(hdrdir)/ruby/internal/fl_type.h
+stringify_target.o: $(hdrdir)/ruby/internal/gc.h
+stringify_target.o: $(hdrdir)/ruby/internal/glob.h
+stringify_target.o: $(hdrdir)/ruby/internal/globals.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/attribute.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/builtin.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/extension.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/feature.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/warning.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/array.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/bignum.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/class.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/compar.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/complex.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/cont.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/dir.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/enum.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/error.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/eval.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/file.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/hash.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/io.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/load.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/marshal.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/numeric.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/object.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/parse.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/proc.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/process.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/random.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/range.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/rational.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/re.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/ruby.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/select.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/set.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/signal.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/string.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/struct.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/thread.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/time.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/variable.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/vm.h
+stringify_target.o: $(hdrdir)/ruby/internal/interpreter.h
+stringify_target.o: $(hdrdir)/ruby/internal/iterator.h
+stringify_target.o: $(hdrdir)/ruby/internal/memory.h
+stringify_target.o: $(hdrdir)/ruby/internal/method.h
+stringify_target.o: $(hdrdir)/ruby/internal/module.h
+stringify_target.o: $(hdrdir)/ruby/internal/newobj.h
+stringify_target.o: $(hdrdir)/ruby/internal/scan_args.h
+stringify_target.o: $(hdrdir)/ruby/internal/special_consts.h
+stringify_target.o: $(hdrdir)/ruby/internal/static_assert.h
+stringify_target.o: $(hdrdir)/ruby/internal/stdalign.h
+stringify_target.o: $(hdrdir)/ruby/internal/stdbool.h
+stringify_target.o: $(hdrdir)/ruby/internal/stdckdint.h
+stringify_target.o: $(hdrdir)/ruby/internal/symbol.h
+stringify_target.o: $(hdrdir)/ruby/internal/value.h
+stringify_target.o: $(hdrdir)/ruby/internal/value_type.h
+stringify_target.o: $(hdrdir)/ruby/internal/variable.h
+stringify_target.o: $(hdrdir)/ruby/internal/warning_push.h
+stringify_target.o: $(hdrdir)/ruby/internal/xmalloc.h
+stringify_target.o: $(hdrdir)/ruby/missing.h
+stringify_target.o: $(hdrdir)/ruby/ruby.h
+stringify_target.o: $(hdrdir)/ruby/st.h
+stringify_target.o: $(hdrdir)/ruby/subst.h
+stringify_target.o: stringify_target.c
+stringify_target.o: stringify_target.h
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/load/stringify_target/extconf.rb b/ext/-test-/load/stringify_target/extconf.rb
new file mode 100644
index 0000000000..4aa201cb09
--- /dev/null
+++ b/ext/-test-/load/stringify_target/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/load/stringify_target')
diff --git a/ext/-test-/load/stringify_target/stringify_target.c b/ext/-test-/load/stringify_target/stringify_target.c
new file mode 100644
index 0000000000..ce09b8fd77
--- /dev/null
+++ b/ext/-test-/load/stringify_target/stringify_target.c
@@ -0,0 +1,15 @@
+#include <ruby.h>
+#include "stringify_target.h"
+
+VALUE
+stt_any_method(VALUE klass)
+{
+ return rb_str_new_cstr("from target");
+}
+
+void
+Init_stringify_target(void)
+{
+ VALUE mod = rb_define_module("StringifyTarget");
+ rb_define_singleton_method(mod, "any_method", stt_any_method, 0);
+}
diff --git a/ext/-test-/load/stringify_target/stringify_target.h b/ext/-test-/load/stringify_target/stringify_target.h
new file mode 100644
index 0000000000..d95fb65d7c
--- /dev/null
+++ b/ext/-test-/load/stringify_target/stringify_target.h
@@ -0,0 +1,4 @@
+#include <ruby.h>
+#include "ruby/internal/dllexport.h"
+
+RUBY_FUNC_EXPORTED VALUE stt_any_method(VALUE);
diff --git a/ext/-test-/marshal/compat/depend b/ext/-test-/marshal/compat/depend
new file mode 100644
index 0000000000..36b9235c23
--- /dev/null
+++ b/ext/-test-/marshal/compat/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+usrcompat.o: $(RUBY_EXTCONF_H)
+usrcompat.o: $(arch_hdrdir)/ruby/config.h
+usrcompat.o: $(hdrdir)/ruby.h
+usrcompat.o: $(hdrdir)/ruby/assert.h
+usrcompat.o: $(hdrdir)/ruby/backward.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/assume.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/attributes.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/bool.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/limits.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/long_long.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/stdarg.h
+usrcompat.o: $(hdrdir)/ruby/defines.h
+usrcompat.o: $(hdrdir)/ruby/intern.h
+usrcompat.o: $(hdrdir)/ruby/internal/abi.h
+usrcompat.o: $(hdrdir)/ruby/internal/anyargs.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/assume.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/artificial.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/cold.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/const.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/error.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/format.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/noalias.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/noinline.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/pure.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/restrict.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/warning.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/weakref.h
+usrcompat.o: $(hdrdir)/ruby/internal/cast.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_since.h
+usrcompat.o: $(hdrdir)/ruby/internal/config.h
+usrcompat.o: $(hdrdir)/ruby/internal/constant_p.h
+usrcompat.o: $(hdrdir)/ruby/internal/core.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rarray.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rbasic.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rbignum.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rclass.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rdata.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rfile.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rhash.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/robject.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rregexp.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rstring.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rstruct.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+usrcompat.o: $(hdrdir)/ruby/internal/ctype.h
+usrcompat.o: $(hdrdir)/ruby/internal/dllexport.h
+usrcompat.o: $(hdrdir)/ruby/internal/dosish.h
+usrcompat.o: $(hdrdir)/ruby/internal/error.h
+usrcompat.o: $(hdrdir)/ruby/internal/eval.h
+usrcompat.o: $(hdrdir)/ruby/internal/event.h
+usrcompat.o: $(hdrdir)/ruby/internal/fl_type.h
+usrcompat.o: $(hdrdir)/ruby/internal/gc.h
+usrcompat.o: $(hdrdir)/ruby/internal/glob.h
+usrcompat.o: $(hdrdir)/ruby/internal/globals.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/attribute.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/builtin.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/extension.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/feature.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/warning.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/array.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/bignum.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/class.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/compar.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/complex.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/cont.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/dir.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/enum.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/error.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/eval.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/file.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/hash.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/io.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/load.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/marshal.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/numeric.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/object.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/parse.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/proc.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/process.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/random.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/range.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/rational.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/re.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/ruby.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/select.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/set.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/signal.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/string.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/struct.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/thread.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/time.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/variable.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/vm.h
+usrcompat.o: $(hdrdir)/ruby/internal/interpreter.h
+usrcompat.o: $(hdrdir)/ruby/internal/iterator.h
+usrcompat.o: $(hdrdir)/ruby/internal/memory.h
+usrcompat.o: $(hdrdir)/ruby/internal/method.h
+usrcompat.o: $(hdrdir)/ruby/internal/module.h
+usrcompat.o: $(hdrdir)/ruby/internal/newobj.h
+usrcompat.o: $(hdrdir)/ruby/internal/scan_args.h
+usrcompat.o: $(hdrdir)/ruby/internal/special_consts.h
+usrcompat.o: $(hdrdir)/ruby/internal/static_assert.h
+usrcompat.o: $(hdrdir)/ruby/internal/stdalign.h
+usrcompat.o: $(hdrdir)/ruby/internal/stdbool.h
+usrcompat.o: $(hdrdir)/ruby/internal/stdckdint.h
+usrcompat.o: $(hdrdir)/ruby/internal/symbol.h
+usrcompat.o: $(hdrdir)/ruby/internal/value.h
+usrcompat.o: $(hdrdir)/ruby/internal/value_type.h
+usrcompat.o: $(hdrdir)/ruby/internal/variable.h
+usrcompat.o: $(hdrdir)/ruby/internal/warning_push.h
+usrcompat.o: $(hdrdir)/ruby/internal/xmalloc.h
+usrcompat.o: $(hdrdir)/ruby/missing.h
+usrcompat.o: $(hdrdir)/ruby/ruby.h
+usrcompat.o: $(hdrdir)/ruby/st.h
+usrcompat.o: $(hdrdir)/ruby/subst.h
+usrcompat.o: usrcompat.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/marshal/compat/extconf.rb b/ext/-test-/marshal/compat/extconf.rb
new file mode 100644
index 0000000000..9bf44b473a
--- /dev/null
+++ b/ext/-test-/marshal/compat/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/marshal/compat")
diff --git a/ext/-test-/marshal/compat/usrcompat.c b/ext/-test-/marshal/compat/usrcompat.c
new file mode 100644
index 0000000000..f812df5631
--- /dev/null
+++ b/ext/-test-/marshal/compat/usrcompat.c
@@ -0,0 +1,32 @@
+#include <ruby.h>
+
+static VALUE
+usr_dumper(VALUE self)
+{
+ return self;
+}
+
+static VALUE
+usr_loader(VALUE self, VALUE m)
+{
+ VALUE val = rb_ivar_get(m, rb_intern("@value"));
+ *(int *)DATA_PTR(self) = NUM2INT(val);
+ return self;
+}
+
+static VALUE
+compat_mload(VALUE self, VALUE data)
+{
+ rb_ivar_set(self, rb_intern("@value"), data);
+ return self;
+}
+
+void
+Init_compat(void)
+{
+ VALUE newclass = rb_path2class("Bug::Marshal::UsrMarshal");
+ VALUE oldclass = rb_define_class_under(newclass, "compat", rb_cObject);
+
+ rb_define_method(oldclass, "marshal_load", compat_mload, 1);
+ rb_marshal_define_compat(newclass, oldclass, usr_dumper, usr_loader);
+}
diff --git a/ext/-test-/marshal/internal_ivar/depend b/ext/-test-/marshal/internal_ivar/depend
new file mode 100644
index 0000000000..a2e093d809
--- /dev/null
+++ b/ext/-test-/marshal/internal_ivar/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+internal_ivar.o: $(RUBY_EXTCONF_H)
+internal_ivar.o: $(arch_hdrdir)/ruby/config.h
+internal_ivar.o: $(hdrdir)/ruby.h
+internal_ivar.o: $(hdrdir)/ruby/assert.h
+internal_ivar.o: $(hdrdir)/ruby/backward.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/assume.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/attributes.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/bool.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/inttypes.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/limits.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/long_long.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/stdalign.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/stdarg.h
+internal_ivar.o: $(hdrdir)/ruby/defines.h
+internal_ivar.o: $(hdrdir)/ruby/intern.h
+internal_ivar.o: $(hdrdir)/ruby/internal/abi.h
+internal_ivar.o: $(hdrdir)/ruby/internal/anyargs.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/assume.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/artificial.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/cold.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/const.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/error.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/format.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/noalias.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/noinline.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/pure.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/restrict.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/warning.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/weakref.h
+internal_ivar.o: $(hdrdir)/ruby/internal/cast.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_since.h
+internal_ivar.o: $(hdrdir)/ruby/internal/config.h
+internal_ivar.o: $(hdrdir)/ruby/internal/constant_p.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rarray.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rbasic.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rbignum.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rclass.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rdata.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rfile.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rhash.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/robject.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rregexp.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rstring.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rstruct.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+internal_ivar.o: $(hdrdir)/ruby/internal/ctype.h
+internal_ivar.o: $(hdrdir)/ruby/internal/dllexport.h
+internal_ivar.o: $(hdrdir)/ruby/internal/dosish.h
+internal_ivar.o: $(hdrdir)/ruby/internal/error.h
+internal_ivar.o: $(hdrdir)/ruby/internal/eval.h
+internal_ivar.o: $(hdrdir)/ruby/internal/event.h
+internal_ivar.o: $(hdrdir)/ruby/internal/fl_type.h
+internal_ivar.o: $(hdrdir)/ruby/internal/gc.h
+internal_ivar.o: $(hdrdir)/ruby/internal/glob.h
+internal_ivar.o: $(hdrdir)/ruby/internal/globals.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/attribute.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/builtin.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/extension.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/feature.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/warning.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/array.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/bignum.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/class.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/compar.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/complex.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/cont.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/dir.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/enum.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/error.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/eval.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/file.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/hash.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/io.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/load.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/marshal.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/numeric.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/object.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/parse.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/proc.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/process.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/random.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/range.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/rational.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/re.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/ruby.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/select.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/set.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/signal.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/string.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/struct.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/thread.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/time.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/variable.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/vm.h
+internal_ivar.o: $(hdrdir)/ruby/internal/interpreter.h
+internal_ivar.o: $(hdrdir)/ruby/internal/iterator.h
+internal_ivar.o: $(hdrdir)/ruby/internal/memory.h
+internal_ivar.o: $(hdrdir)/ruby/internal/method.h
+internal_ivar.o: $(hdrdir)/ruby/internal/module.h
+internal_ivar.o: $(hdrdir)/ruby/internal/newobj.h
+internal_ivar.o: $(hdrdir)/ruby/internal/scan_args.h
+internal_ivar.o: $(hdrdir)/ruby/internal/special_consts.h
+internal_ivar.o: $(hdrdir)/ruby/internal/static_assert.h
+internal_ivar.o: $(hdrdir)/ruby/internal/stdalign.h
+internal_ivar.o: $(hdrdir)/ruby/internal/stdbool.h
+internal_ivar.o: $(hdrdir)/ruby/internal/stdckdint.h
+internal_ivar.o: $(hdrdir)/ruby/internal/symbol.h
+internal_ivar.o: $(hdrdir)/ruby/internal/value.h
+internal_ivar.o: $(hdrdir)/ruby/internal/value_type.h
+internal_ivar.o: $(hdrdir)/ruby/internal/variable.h
+internal_ivar.o: $(hdrdir)/ruby/internal/warning_push.h
+internal_ivar.o: $(hdrdir)/ruby/internal/xmalloc.h
+internal_ivar.o: $(hdrdir)/ruby/missing.h
+internal_ivar.o: $(hdrdir)/ruby/ruby.h
+internal_ivar.o: $(hdrdir)/ruby/st.h
+internal_ivar.o: $(hdrdir)/ruby/subst.h
+internal_ivar.o: internal_ivar.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/marshal/internal_ivar/extconf.rb b/ext/-test-/marshal/internal_ivar/extconf.rb
new file mode 100644
index 0000000000..cb3f825dbd
--- /dev/null
+++ b/ext/-test-/marshal/internal_ivar/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/marshal/internal_ivar")
diff --git a/ext/-test-/marshal/internal_ivar/internal_ivar.c b/ext/-test-/marshal/internal_ivar/internal_ivar.c
new file mode 100644
index 0000000000..2e2f9cb235
--- /dev/null
+++ b/ext/-test-/marshal/internal_ivar/internal_ivar.c
@@ -0,0 +1,54 @@
+#include <ruby.h>
+
+static ID id_normal_ivar, id_internal_ivar, id_encoding_short, id_encoding_long;
+
+static VALUE
+init(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4)
+{
+ rb_ivar_set(self, id_normal_ivar, arg1);
+ rb_ivar_set(self, id_internal_ivar, arg2);
+ rb_ivar_set(self, id_encoding_short, arg3);
+ rb_ivar_set(self, id_encoding_long, arg4);
+ return self;
+}
+
+static VALUE
+get_normal(VALUE self)
+{
+ return rb_attr_get(self, id_normal_ivar);
+}
+
+static VALUE
+get_internal(VALUE self)
+{
+ return rb_attr_get(self, id_internal_ivar);
+}
+
+static VALUE
+get_encoding_short(VALUE self)
+{
+ return rb_attr_get(self, id_encoding_short);
+}
+
+static VALUE
+get_encoding_long(VALUE self)
+{
+ return rb_attr_get(self, id_encoding_long);
+}
+
+void
+Init_internal_ivar(void)
+{
+ VALUE mMarshal = rb_define_module_under(rb_define_module("Bug"), "Marshal");
+ VALUE newclass = rb_define_class_under(mMarshal, "InternalIVar", rb_cObject);
+
+ id_normal_ivar = rb_intern_const("normal");
+ id_internal_ivar = rb_intern_const("K");
+ id_encoding_short = rb_intern_const("E");
+ id_encoding_long = rb_intern_const("encoding");
+ rb_define_method(newclass, "initialize", init, 4);
+ rb_define_method(newclass, "normal", get_normal, 0);
+ rb_define_method(newclass, "internal", get_internal, 0);
+ rb_define_method(newclass, "encoding_short", get_encoding_short, 0);
+ rb_define_method(newclass, "encoding_long", get_encoding_long, 0);
+}
diff --git a/ext/-test-/marshal/usr/depend b/ext/-test-/marshal/usr/depend
new file mode 100644
index 0000000000..5ffb8c58de
--- /dev/null
+++ b/ext/-test-/marshal/usr/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+usrmarshal.o: $(RUBY_EXTCONF_H)
+usrmarshal.o: $(arch_hdrdir)/ruby/config.h
+usrmarshal.o: $(hdrdir)/ruby.h
+usrmarshal.o: $(hdrdir)/ruby/assert.h
+usrmarshal.o: $(hdrdir)/ruby/backward.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/assume.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/attributes.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/bool.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/inttypes.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/limits.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/long_long.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/stdalign.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/stdarg.h
+usrmarshal.o: $(hdrdir)/ruby/defines.h
+usrmarshal.o: $(hdrdir)/ruby/intern.h
+usrmarshal.o: $(hdrdir)/ruby/internal/abi.h
+usrmarshal.o: $(hdrdir)/ruby/internal/anyargs.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/assume.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/artificial.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/cold.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/const.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/error.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/format.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/noalias.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/noinline.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/pure.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/restrict.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/warning.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/weakref.h
+usrmarshal.o: $(hdrdir)/ruby/internal/cast.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_since.h
+usrmarshal.o: $(hdrdir)/ruby/internal/config.h
+usrmarshal.o: $(hdrdir)/ruby/internal/constant_p.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rarray.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rbasic.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rbignum.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rclass.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rdata.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rfile.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rhash.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/robject.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rregexp.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rstring.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rstruct.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+usrmarshal.o: $(hdrdir)/ruby/internal/ctype.h
+usrmarshal.o: $(hdrdir)/ruby/internal/dllexport.h
+usrmarshal.o: $(hdrdir)/ruby/internal/dosish.h
+usrmarshal.o: $(hdrdir)/ruby/internal/error.h
+usrmarshal.o: $(hdrdir)/ruby/internal/eval.h
+usrmarshal.o: $(hdrdir)/ruby/internal/event.h
+usrmarshal.o: $(hdrdir)/ruby/internal/fl_type.h
+usrmarshal.o: $(hdrdir)/ruby/internal/gc.h
+usrmarshal.o: $(hdrdir)/ruby/internal/glob.h
+usrmarshal.o: $(hdrdir)/ruby/internal/globals.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/attribute.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/builtin.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/extension.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/feature.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/warning.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/array.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/bignum.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/class.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/compar.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/complex.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/cont.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/dir.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/enum.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/error.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/eval.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/file.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/hash.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/io.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/load.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/marshal.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/numeric.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/object.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/parse.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/proc.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/process.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/random.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/range.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/rational.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/re.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/ruby.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/select.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/set.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/signal.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/string.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/struct.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/thread.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/time.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/variable.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/vm.h
+usrmarshal.o: $(hdrdir)/ruby/internal/interpreter.h
+usrmarshal.o: $(hdrdir)/ruby/internal/iterator.h
+usrmarshal.o: $(hdrdir)/ruby/internal/memory.h
+usrmarshal.o: $(hdrdir)/ruby/internal/method.h
+usrmarshal.o: $(hdrdir)/ruby/internal/module.h
+usrmarshal.o: $(hdrdir)/ruby/internal/newobj.h
+usrmarshal.o: $(hdrdir)/ruby/internal/scan_args.h
+usrmarshal.o: $(hdrdir)/ruby/internal/special_consts.h
+usrmarshal.o: $(hdrdir)/ruby/internal/static_assert.h
+usrmarshal.o: $(hdrdir)/ruby/internal/stdalign.h
+usrmarshal.o: $(hdrdir)/ruby/internal/stdbool.h
+usrmarshal.o: $(hdrdir)/ruby/internal/stdckdint.h
+usrmarshal.o: $(hdrdir)/ruby/internal/symbol.h
+usrmarshal.o: $(hdrdir)/ruby/internal/value.h
+usrmarshal.o: $(hdrdir)/ruby/internal/value_type.h
+usrmarshal.o: $(hdrdir)/ruby/internal/variable.h
+usrmarshal.o: $(hdrdir)/ruby/internal/warning_push.h
+usrmarshal.o: $(hdrdir)/ruby/internal/xmalloc.h
+usrmarshal.o: $(hdrdir)/ruby/missing.h
+usrmarshal.o: $(hdrdir)/ruby/ruby.h
+usrmarshal.o: $(hdrdir)/ruby/st.h
+usrmarshal.o: $(hdrdir)/ruby/subst.h
+usrmarshal.o: usrmarshal.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/marshal/usr/extconf.rb b/ext/-test-/marshal/usr/extconf.rb
new file mode 100644
index 0000000000..b7886b9eea
--- /dev/null
+++ b/ext/-test-/marshal/usr/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/marshal/usr")
diff --git a/ext/-test-/marshal/usr/usrmarshal.c b/ext/-test-/marshal/usr/usrmarshal.c
new file mode 100644
index 0000000000..0c9e079af2
--- /dev/null
+++ b/ext/-test-/marshal/usr/usrmarshal.c
@@ -0,0 +1,50 @@
+#include <ruby.h>
+
+static size_t
+usr_size(const void *ptr)
+{
+ return sizeof(int);
+}
+
+static const rb_data_type_t usrmarshal_type = {
+ "UsrMarshal",
+ {0, RUBY_DEFAULT_FREE, usr_size,},
+ 0, 0,
+ RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED,
+};
+
+static VALUE
+usr_alloc(VALUE klass)
+{
+ int *p;
+ return TypedData_Make_Struct(klass, int, &usrmarshal_type, p);
+}
+
+static VALUE
+usr_init(VALUE self, VALUE val)
+{
+ int *ptr = Check_TypedStruct(self, &usrmarshal_type);
+ *ptr = NUM2INT(val);
+ return self;
+}
+
+static VALUE
+usr_value(VALUE self)
+{
+ int *ptr = Check_TypedStruct(self, &usrmarshal_type);
+ int val = *ptr;
+ return INT2NUM(val);
+}
+
+void
+Init_usr(void)
+{
+ VALUE mMarshal = rb_define_module_under(rb_define_module("Bug"), "Marshal");
+ VALUE newclass = rb_define_class_under(mMarshal, "UsrMarshal", rb_cObject);
+
+ rb_define_alloc_func(newclass, usr_alloc);
+ rb_define_method(newclass, "initialize", usr_init, 1);
+ rb_define_method(newclass, "value", usr_value, 0);
+ rb_define_method(newclass, "marshal_load", usr_init, 1);
+ rb_define_method(newclass, "marshal_dump", usr_value, 0);
+}
diff --git a/ext/-test-/memory_status/depend b/ext/-test-/memory_status/depend
new file mode 100644
index 0000000000..4dd503e1bb
--- /dev/null
+++ b/ext/-test-/memory_status/depend
@@ -0,0 +1,162 @@
+# AUTOGENERATED DEPENDENCIES START
+memory_status.o: $(RUBY_EXTCONF_H)
+memory_status.o: $(arch_hdrdir)/ruby/config.h
+memory_status.o: $(hdrdir)/ruby.h
+memory_status.o: $(hdrdir)/ruby/assert.h
+memory_status.o: $(hdrdir)/ruby/backward.h
+memory_status.o: $(hdrdir)/ruby/backward/2/assume.h
+memory_status.o: $(hdrdir)/ruby/backward/2/attributes.h
+memory_status.o: $(hdrdir)/ruby/backward/2/bool.h
+memory_status.o: $(hdrdir)/ruby/backward/2/inttypes.h
+memory_status.o: $(hdrdir)/ruby/backward/2/limits.h
+memory_status.o: $(hdrdir)/ruby/backward/2/long_long.h
+memory_status.o: $(hdrdir)/ruby/backward/2/stdalign.h
+memory_status.o: $(hdrdir)/ruby/backward/2/stdarg.h
+memory_status.o: $(hdrdir)/ruby/defines.h
+memory_status.o: $(hdrdir)/ruby/intern.h
+memory_status.o: $(hdrdir)/ruby/internal/abi.h
+memory_status.o: $(hdrdir)/ruby/internal/anyargs.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+memory_status.o: $(hdrdir)/ruby/internal/assume.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/artificial.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/cold.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/const.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/error.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/format.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/noalias.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/noinline.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/pure.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/restrict.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/warning.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/weakref.h
+memory_status.o: $(hdrdir)/ruby/internal/cast.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_since.h
+memory_status.o: $(hdrdir)/ruby/internal/config.h
+memory_status.o: $(hdrdir)/ruby/internal/constant_p.h
+memory_status.o: $(hdrdir)/ruby/internal/core.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rarray.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rbasic.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rbignum.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rclass.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rdata.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rfile.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rhash.h
+memory_status.o: $(hdrdir)/ruby/internal/core/robject.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rregexp.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rstring.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rstruct.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+memory_status.o: $(hdrdir)/ruby/internal/ctype.h
+memory_status.o: $(hdrdir)/ruby/internal/dllexport.h
+memory_status.o: $(hdrdir)/ruby/internal/dosish.h
+memory_status.o: $(hdrdir)/ruby/internal/error.h
+memory_status.o: $(hdrdir)/ruby/internal/eval.h
+memory_status.o: $(hdrdir)/ruby/internal/event.h
+memory_status.o: $(hdrdir)/ruby/internal/fl_type.h
+memory_status.o: $(hdrdir)/ruby/internal/gc.h
+memory_status.o: $(hdrdir)/ruby/internal/glob.h
+memory_status.o: $(hdrdir)/ruby/internal/globals.h
+memory_status.o: $(hdrdir)/ruby/internal/has/attribute.h
+memory_status.o: $(hdrdir)/ruby/internal/has/builtin.h
+memory_status.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+memory_status.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+memory_status.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+memory_status.o: $(hdrdir)/ruby/internal/has/extension.h
+memory_status.o: $(hdrdir)/ruby/internal/has/feature.h
+memory_status.o: $(hdrdir)/ruby/internal/has/warning.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/array.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/bignum.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/class.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/compar.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/complex.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/cont.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/dir.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/enum.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/error.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/eval.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/file.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/hash.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/io.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/load.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/marshal.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/numeric.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/object.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/parse.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/proc.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/process.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/random.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/range.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/rational.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/re.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/ruby.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/select.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/signal.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/string.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/struct.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/thread.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/time.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/variable.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/vm.h
+memory_status.o: $(hdrdir)/ruby/internal/interpreter.h
+memory_status.o: $(hdrdir)/ruby/internal/iterator.h
+memory_status.o: $(hdrdir)/ruby/internal/memory.h
+memory_status.o: $(hdrdir)/ruby/internal/method.h
+memory_status.o: $(hdrdir)/ruby/internal/module.h
+memory_status.o: $(hdrdir)/ruby/internal/newobj.h
+memory_status.o: $(hdrdir)/ruby/internal/scan_args.h
+memory_status.o: $(hdrdir)/ruby/internal/special_consts.h
+memory_status.o: $(hdrdir)/ruby/internal/static_assert.h
+memory_status.o: $(hdrdir)/ruby/internal/stdalign.h
+memory_status.o: $(hdrdir)/ruby/internal/stdbool.h
+memory_status.o: $(hdrdir)/ruby/internal/stdckdint.h
+memory_status.o: $(hdrdir)/ruby/internal/symbol.h
+memory_status.o: $(hdrdir)/ruby/internal/value.h
+memory_status.o: $(hdrdir)/ruby/internal/value_type.h
+memory_status.o: $(hdrdir)/ruby/internal/variable.h
+memory_status.o: $(hdrdir)/ruby/internal/warning_push.h
+memory_status.o: $(hdrdir)/ruby/internal/xmalloc.h
+memory_status.o: $(hdrdir)/ruby/missing.h
+memory_status.o: $(hdrdir)/ruby/ruby.h
+memory_status.o: $(hdrdir)/ruby/st.h
+memory_status.o: $(hdrdir)/ruby/subst.h
+memory_status.o: memory_status.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/memory_status/extconf.rb b/ext/-test-/memory_status/extconf.rb
new file mode 100644
index 0000000000..1c1096d8f4
--- /dev/null
+++ b/ext/-test-/memory_status/extconf.rb
@@ -0,0 +1,12 @@
+case RUBY_PLATFORM
+when /darwin/
+ ok = true
+when /mswin/, /mingw/
+ func = "GetProcessMemoryInfo(0, 0, 0)"
+ hdr = "psapi.h"
+ ok = have_func(func, hdr) || have_library("psapi", func, hdr)
+end
+
+if ok
+ create_makefile("-test-/memory_status")
+end
diff --git a/ext/-test-/memory_status/memory_status.c b/ext/-test-/memory_status/memory_status.c
new file mode 100644
index 0000000000..f124c97ca1
--- /dev/null
+++ b/ext/-test-/memory_status/memory_status.c
@@ -0,0 +1,80 @@
+#include "ruby.h"
+#ifdef __APPLE__
+# include <mach/mach.h>
+# include <mach/message.h>
+# include <mach/kern_return.h>
+# include <mach/task_info.h>
+#elif defined _WIN32
+# include <psapi.h>
+#endif
+
+static VALUE cMemoryStatus;
+
+#undef HAVE_RSS
+#undef HAVE_PEAK
+
+static VALUE
+read_status(VALUE self)
+{
+ VALUE size = INT2FIX(0);
+#if defined __APPLE__
+# define HAVE_RSS 1
+ VALUE rss;
+ kern_return_t error;
+# if defined MACH_TASK_BASIC_INFO
+ const task_flavor_t flavor = MACH_TASK_BASIC_INFO;
+ mach_msg_type_number_t out_count = MACH_TASK_BASIC_INFO_COUNT;
+ mach_task_basic_info_data_t taskinfo;
+# else
+ const task_flavor_t flavor = TASK_BASIC_INFO;
+ mach_msg_type_number_t out_count = TASK_BASIC_INFO_COUNT;
+ task_basic_info_data_t taskinfo;
+# endif
+
+ taskinfo.virtual_size = 0;
+ taskinfo.resident_size = 0;
+ error = task_info(mach_task_self(), flavor,
+ (task_info_t)&taskinfo, &out_count);
+ if (error != KERN_SUCCESS) return Qnil;
+#ifndef ULL2NUM
+/* "long long" does not exist here, use size_t instead. */
+#define ULL2NUM SIZET2NUM
+#endif
+ size = ULL2NUM(taskinfo.virtual_size);
+ rss = ULL2NUM(taskinfo.resident_size);
+ rb_struct_aset(self, INT2FIX(1), rss);
+#elif defined _WIN32
+# define HAVE_RSS 1
+# define HAVE_PEAK 1
+ VALUE rss, peak;
+ PROCESS_MEMORY_COUNTERS c;
+ c.cb = sizeof(c);
+ if (!GetProcessMemoryInfo(GetCurrentProcess(), &c, c.cb))
+ return Qnil;
+ size = SIZET2NUM(c.PagefileUsage);
+ rss = SIZET2NUM(c.WorkingSetSize);
+ peak = SIZET2NUM(c.PeakWorkingSetSize);
+ rb_struct_aset(self, INT2FIX(2), peak);
+#endif
+#ifdef HAVE_RSS
+ rb_struct_aset(self, INT2FIX(1), rss);
+#endif
+ rb_struct_aset(self, INT2FIX(0), size);
+ return self;
+}
+
+void
+Init_memory_status(void)
+{
+ VALUE mMemory = rb_define_module("Memory");
+ cMemoryStatus =
+ rb_struct_define_under(mMemory, "Status", "size",
+#ifdef HAVE_RSS
+ "rss",
+#endif
+#ifdef HAVE_PEAK
+ "peak",
+#endif
+ (char *)NULL);
+ rb_define_method(cMemoryStatus, "_update", read_status, 0);
+}
diff --git a/ext/-test-/memory_view/depend b/ext/-test-/memory_view/depend
new file mode 100644
index 0000000000..a6ffd76f45
--- /dev/null
+++ b/ext/-test-/memory_view/depend
@@ -0,0 +1,164 @@
+# AUTOGENERATED DEPENDENCIES START
+memory_view.o: $(RUBY_EXTCONF_H)
+memory_view.o: $(arch_hdrdir)/ruby/config.h
+memory_view.o: $(hdrdir)/ruby.h
+memory_view.o: $(hdrdir)/ruby/assert.h
+memory_view.o: $(hdrdir)/ruby/backward.h
+memory_view.o: $(hdrdir)/ruby/backward/2/assume.h
+memory_view.o: $(hdrdir)/ruby/backward/2/attributes.h
+memory_view.o: $(hdrdir)/ruby/backward/2/bool.h
+memory_view.o: $(hdrdir)/ruby/backward/2/inttypes.h
+memory_view.o: $(hdrdir)/ruby/backward/2/limits.h
+memory_view.o: $(hdrdir)/ruby/backward/2/long_long.h
+memory_view.o: $(hdrdir)/ruby/backward/2/stdalign.h
+memory_view.o: $(hdrdir)/ruby/backward/2/stdarg.h
+memory_view.o: $(hdrdir)/ruby/defines.h
+memory_view.o: $(hdrdir)/ruby/intern.h
+memory_view.o: $(hdrdir)/ruby/internal/abi.h
+memory_view.o: $(hdrdir)/ruby/internal/anyargs.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+memory_view.o: $(hdrdir)/ruby/internal/assume.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/artificial.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/cold.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/const.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/error.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/format.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/noalias.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/noinline.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/pure.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/restrict.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/warning.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/weakref.h
+memory_view.o: $(hdrdir)/ruby/internal/cast.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_since.h
+memory_view.o: $(hdrdir)/ruby/internal/config.h
+memory_view.o: $(hdrdir)/ruby/internal/constant_p.h
+memory_view.o: $(hdrdir)/ruby/internal/core.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rarray.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rbasic.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rbignum.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rclass.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rdata.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rfile.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rhash.h
+memory_view.o: $(hdrdir)/ruby/internal/core/robject.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rregexp.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rstring.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rstruct.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+memory_view.o: $(hdrdir)/ruby/internal/ctype.h
+memory_view.o: $(hdrdir)/ruby/internal/dllexport.h
+memory_view.o: $(hdrdir)/ruby/internal/dosish.h
+memory_view.o: $(hdrdir)/ruby/internal/error.h
+memory_view.o: $(hdrdir)/ruby/internal/eval.h
+memory_view.o: $(hdrdir)/ruby/internal/event.h
+memory_view.o: $(hdrdir)/ruby/internal/fl_type.h
+memory_view.o: $(hdrdir)/ruby/internal/gc.h
+memory_view.o: $(hdrdir)/ruby/internal/glob.h
+memory_view.o: $(hdrdir)/ruby/internal/globals.h
+memory_view.o: $(hdrdir)/ruby/internal/has/attribute.h
+memory_view.o: $(hdrdir)/ruby/internal/has/builtin.h
+memory_view.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+memory_view.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+memory_view.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+memory_view.o: $(hdrdir)/ruby/internal/has/extension.h
+memory_view.o: $(hdrdir)/ruby/internal/has/feature.h
+memory_view.o: $(hdrdir)/ruby/internal/has/warning.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/array.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/bignum.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/class.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/compar.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/complex.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/cont.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/dir.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/enum.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/error.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/eval.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/file.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/hash.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/io.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/load.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/marshal.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/numeric.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/object.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/parse.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/proc.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/process.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/random.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/range.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/rational.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/re.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/ruby.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/select.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/set.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/signal.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/string.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/struct.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/thread.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/time.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/variable.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/vm.h
+memory_view.o: $(hdrdir)/ruby/internal/interpreter.h
+memory_view.o: $(hdrdir)/ruby/internal/iterator.h
+memory_view.o: $(hdrdir)/ruby/internal/memory.h
+memory_view.o: $(hdrdir)/ruby/internal/method.h
+memory_view.o: $(hdrdir)/ruby/internal/module.h
+memory_view.o: $(hdrdir)/ruby/internal/newobj.h
+memory_view.o: $(hdrdir)/ruby/internal/scan_args.h
+memory_view.o: $(hdrdir)/ruby/internal/special_consts.h
+memory_view.o: $(hdrdir)/ruby/internal/static_assert.h
+memory_view.o: $(hdrdir)/ruby/internal/stdalign.h
+memory_view.o: $(hdrdir)/ruby/internal/stdbool.h
+memory_view.o: $(hdrdir)/ruby/internal/stdckdint.h
+memory_view.o: $(hdrdir)/ruby/internal/symbol.h
+memory_view.o: $(hdrdir)/ruby/internal/value.h
+memory_view.o: $(hdrdir)/ruby/internal/value_type.h
+memory_view.o: $(hdrdir)/ruby/internal/variable.h
+memory_view.o: $(hdrdir)/ruby/internal/warning_push.h
+memory_view.o: $(hdrdir)/ruby/internal/xmalloc.h
+memory_view.o: $(hdrdir)/ruby/memory_view.h
+memory_view.o: $(hdrdir)/ruby/missing.h
+memory_view.o: $(hdrdir)/ruby/ruby.h
+memory_view.o: $(hdrdir)/ruby/st.h
+memory_view.o: $(hdrdir)/ruby/subst.h
+memory_view.o: memory_view.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/memory_view/extconf.rb b/ext/-test-/memory_view/extconf.rb
new file mode 100644
index 0000000000..123b80b8d0
--- /dev/null
+++ b/ext/-test-/memory_view/extconf.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: false
+require "mkmf"
+
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/memory_view/memory_view.c b/ext/-test-/memory_view/memory_view.c
new file mode 100644
index 0000000000..63f0beb81e
--- /dev/null
+++ b/ext/-test-/memory_view/memory_view.c
@@ -0,0 +1,450 @@
+#include "ruby.h"
+
+#ifdef HAVE_RUBY_MEMORY_VIEW_H
+#include "ruby/memory_view.h"
+
+#define STRUCT_ALIGNOF(T, result) do { \
+ (result) = RUBY_ALIGNOF(T); \
+} while(0)
+
+static ID id_str;
+static VALUE sym_format;
+static VALUE sym_native_size_p;
+static VALUE sym_offset;
+static VALUE sym_size;
+static VALUE sym_repeat;
+static VALUE sym_obj;
+static VALUE sym_byte_size;
+static VALUE sym_readonly;
+static VALUE sym_format;
+static VALUE sym_item_size;
+static VALUE sym_ndim;
+static VALUE sym_shape;
+static VALUE sym_strides;
+static VALUE sym_sub_offsets;
+static VALUE sym_endianness;
+static VALUE sym_little_endian;
+static VALUE sym_big_endian;
+
+static bool
+exportable_string_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
+{
+ VALUE str = rb_ivar_get(obj, id_str);
+ rb_memory_view_init_as_byte_array(view, obj, RSTRING_PTR(str), RSTRING_LEN(str), true);
+ return true;
+}
+
+static bool
+exportable_string_memory_view_available_p(VALUE obj)
+{
+ VALUE str = rb_ivar_get(obj, id_str);
+ return !NIL_P(str);
+}
+
+static const rb_memory_view_entry_t exportable_string_memory_view_entry = {
+ exportable_string_get_memory_view,
+ NULL,
+ exportable_string_memory_view_available_p
+};
+
+static VALUE
+memory_view_available_p(VALUE mod, VALUE obj)
+{
+ return rb_memory_view_available_p(obj) ? Qtrue : Qfalse;
+}
+
+static VALUE
+memory_view_register(VALUE mod, VALUE obj)
+{
+ return rb_memory_view_register(obj, &exportable_string_memory_view_entry) ? Qtrue : Qfalse;
+}
+
+static VALUE
+memory_view_item_size_from_format(VALUE mod, VALUE format)
+{
+ const char *c_str = NULL;
+ if (!NIL_P(format))
+ c_str = StringValueCStr(format);
+ const char *err = NULL;
+ ssize_t item_size = rb_memory_view_item_size_from_format(c_str, &err);
+ if (!err)
+ return rb_assoc_new(SSIZET2NUM(item_size), Qnil);
+ else
+ return rb_assoc_new(SSIZET2NUM(item_size), rb_str_new_cstr(err));
+}
+
+static VALUE
+memory_view_parse_item_format(VALUE mod, VALUE format)
+{
+ const char *c_str = NULL;
+ if (!NIL_P(format))
+ c_str = StringValueCStr(format);
+ const char *err = NULL;
+
+ rb_memory_view_item_component_t *members;
+ size_t n_members;
+ ssize_t item_size = rb_memory_view_parse_item_format(c_str, &members, &n_members, &err);
+
+ VALUE result = rb_ary_new_capa(3);
+ rb_ary_push(result, SSIZET2NUM(item_size));
+
+ if (!err) {
+ VALUE ary = rb_ary_new_capa((long)n_members);
+ size_t i;
+ for (i = 0; i < n_members; ++i) {
+ VALUE member = rb_hash_new();
+ rb_hash_aset(member, sym_format, rb_str_new(&members[i].format, 1));
+ rb_hash_aset(member, sym_native_size_p, members[i].native_size_p ? Qtrue : Qfalse);
+ rb_hash_aset(member, sym_endianness, members[i].little_endian_p ? sym_little_endian : sym_big_endian);
+ rb_hash_aset(member, sym_offset, SSIZET2NUM(members[i].offset));
+ rb_hash_aset(member, sym_size, SSIZET2NUM(members[i].size));
+ rb_hash_aset(member, sym_repeat, SSIZET2NUM(members[i].repeat));
+ rb_ary_push(ary, member);
+ }
+ xfree(members);
+ rb_ary_push(result, ary);
+ rb_ary_push(result, Qnil);
+ }
+ else {
+ rb_ary_push(result, Qnil); // members
+ rb_ary_push(result, rb_str_new_cstr(err));
+ }
+
+ return result;
+}
+
+static VALUE
+memory_view_get_memory_view_info(VALUE mod, VALUE obj)
+{
+ rb_memory_view_t view;
+
+ if (!rb_memory_view_get(obj, &view, 0)) {
+ return Qnil;
+ }
+
+ VALUE hash = rb_hash_new();
+ rb_hash_aset(hash, sym_obj, view.obj);
+ rb_hash_aset(hash, sym_byte_size, SSIZET2NUM(view.byte_size));
+ rb_hash_aset(hash, sym_readonly, view.readonly ? Qtrue : Qfalse);
+ rb_hash_aset(hash, sym_format, view.format ? rb_str_new_cstr(view.format) : Qnil);
+ rb_hash_aset(hash, sym_item_size, SSIZET2NUM(view.item_size));
+ rb_hash_aset(hash, sym_ndim, SSIZET2NUM(view.ndim));
+
+ if (view.shape) {
+ VALUE shape = rb_ary_new_capa(view.ndim);
+ rb_hash_aset(hash, sym_shape, shape);
+ }
+ else {
+ rb_hash_aset(hash, sym_shape, Qnil);
+ }
+
+ if (view.strides) {
+ VALUE strides = rb_ary_new_capa(view.ndim);
+ rb_hash_aset(hash, sym_strides, strides);
+ }
+ else {
+ rb_hash_aset(hash, sym_strides, Qnil);
+ }
+
+ if (view.sub_offsets) {
+ VALUE sub_offsets = rb_ary_new_capa(view.ndim);
+ rb_hash_aset(hash, sym_sub_offsets, sub_offsets);
+ }
+ else {
+ rb_hash_aset(hash, sym_sub_offsets, Qnil);
+ }
+
+ rb_memory_view_release(&view);
+
+ return hash;
+}
+
+static VALUE
+memory_view_fill_contiguous_strides(VALUE mod, VALUE ndim_v, VALUE item_size_v, VALUE shape_v, VALUE row_major_p)
+{
+ ssize_t i, ndim = NUM2SSIZET(ndim_v);
+
+ Check_Type(shape_v, T_ARRAY);
+ ssize_t *shape = ALLOC_N(ssize_t, ndim);
+ for (i = 0; i < ndim; ++i) {
+ shape[i] = NUM2SSIZET(RARRAY_AREF(shape_v, i));
+ }
+
+ ssize_t *strides = ALLOC_N(ssize_t, ndim);
+ rb_memory_view_fill_contiguous_strides(ndim, NUM2SSIZET(item_size_v), shape, RTEST(row_major_p), strides);
+
+ VALUE result = rb_ary_new_capa(ndim);
+ for (i = 0; i < ndim; ++i) {
+ rb_ary_push(result, SSIZET2NUM(strides[i]));
+ }
+
+ xfree(strides);
+ xfree(shape);
+
+ return result;
+}
+
+static VALUE
+memory_view_get_ref_count(VALUE obj)
+{
+ if (rb_memory_view_exported_object_registry == Qundef) {
+ return Qnil;
+ }
+
+ st_table *table;
+ TypedData_Get_Struct(rb_memory_view_exported_object_registry, st_table,
+ &rb_memory_view_exported_object_registry_data_type,
+ table);
+
+ st_data_t count;
+ if (st_lookup(table, (st_data_t)obj, &count)) {
+ return ULL2NUM(count);
+ }
+
+ return Qnil;
+}
+
+static VALUE
+memory_view_ref_count_while_exporting_i(VALUE obj, long n)
+{
+ if (n == 0) {
+ return memory_view_get_ref_count(obj);
+ }
+
+ rb_memory_view_t view;
+ if (!rb_memory_view_get(obj, &view, 0)) {
+ return Qnil;
+ }
+
+ VALUE ref_count = memory_view_ref_count_while_exporting_i(obj, n-1);
+ rb_memory_view_release(&view);
+
+ return ref_count;
+}
+
+static VALUE
+memory_view_ref_count_while_exporting(VALUE mod, VALUE obj, VALUE n)
+{
+ Check_Type(n, T_FIXNUM);
+ return memory_view_ref_count_while_exporting_i(obj, FIX2LONG(n));
+}
+
+static VALUE
+memory_view_extract_item_members(VALUE mod, VALUE str, VALUE format)
+{
+ StringValue(str);
+ StringValue(format);
+
+ rb_memory_view_item_component_t *members;
+ size_t n_members;
+ const char *err = NULL;
+ (void)rb_memory_view_parse_item_format(RSTRING_PTR(format), &members, &n_members, &err);
+ if (err != NULL) {
+ rb_raise(rb_eArgError, "Unable to parse item format");
+ }
+
+ VALUE item = rb_memory_view_extract_item_members(RSTRING_PTR(str), members, n_members);
+ xfree(members);
+
+ return item;
+}
+
+static VALUE
+expstr_initialize(VALUE obj, VALUE s)
+{
+ if (!NIL_P(s)) {
+ Check_Type(s, T_STRING);
+ }
+ rb_ivar_set(obj, id_str, s);
+ return Qnil;
+}
+
+static bool
+mdview_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
+{
+ VALUE buf_v = rb_ivar_get(obj, id_str);
+ VALUE format_v = rb_ivar_get(obj, SYM2ID(sym_format));
+ VALUE shape_v = rb_ivar_get(obj, SYM2ID(sym_shape));
+ VALUE strides_v = rb_ivar_get(obj, SYM2ID(sym_strides));
+
+ const char *err;
+ const ssize_t item_size = rb_memory_view_item_size_from_format(RSTRING_PTR(format_v), &err);
+ if (item_size < 0) {
+ return false;
+ }
+
+ ssize_t ndim = RARRAY_LEN(shape_v);
+ if (!NIL_P(strides_v) && RARRAY_LEN(strides_v) != ndim) {
+ rb_raise(rb_eArgError, "strides has an invalid dimension");
+ }
+
+ ssize_t *shape = ALLOC_N(ssize_t, ndim);
+ ssize_t *strides = ALLOC_N(ssize_t, ndim);
+ ssize_t i;
+ if (!NIL_P(strides_v)) {
+ for (i = 0; i < ndim; ++i) {
+ shape[i] = NUM2SSIZET(RARRAY_AREF(shape_v, i));
+ strides[i] = NUM2SSIZET(RARRAY_AREF(strides_v, i));
+ }
+ }
+ else {
+ for (i = 0; i < ndim; ++i) {
+ shape[i] = NUM2SSIZET(RARRAY_AREF(shape_v, i));
+ }
+
+ i = ndim - 1;
+ strides[i] = item_size;
+ for (; i > 0; --i) {
+ strides[i-1] = strides[i] * shape[i];
+ }
+ }
+
+ rb_memory_view_init_as_byte_array(view, obj, RSTRING_PTR(buf_v), RSTRING_LEN(buf_v), true);
+ view->format = RSTRING_PTR(format_v);
+ view->item_size = item_size;
+ view->ndim = ndim;
+ view->shape = shape;
+ view->strides = strides;
+ view->sub_offsets = NULL;
+
+ return true;
+}
+
+static bool
+mdview_release_memory_view(VALUE obj, rb_memory_view_t *view)
+{
+ xfree((void *)view->shape);
+ xfree((void *)view->strides);
+
+ return true;
+}
+
+static bool
+mdview_memory_view_available_p(VALUE obj)
+{
+ return true;
+}
+
+static const rb_memory_view_entry_t mdview_memory_view_entry = {
+ mdview_get_memory_view,
+ mdview_release_memory_view,
+ mdview_memory_view_available_p
+};
+
+static VALUE
+mdview_initialize(VALUE obj, VALUE buf, VALUE format, VALUE shape, VALUE strides)
+{
+ Check_Type(buf, T_STRING);
+ StringValue(format);
+ Check_Type(shape, T_ARRAY);
+ if (!NIL_P(strides)) Check_Type(strides, T_ARRAY);
+
+ rb_ivar_set(obj, id_str, buf);
+ rb_ivar_set(obj, SYM2ID(sym_format), format);
+ rb_ivar_set(obj, SYM2ID(sym_shape), shape);
+ rb_ivar_set(obj, SYM2ID(sym_strides), strides);
+ return Qnil;
+}
+
+static VALUE
+mdview_aref(VALUE obj, VALUE indices_v)
+{
+ Check_Type(indices_v, T_ARRAY);
+
+ rb_memory_view_t view;
+ if (!rb_memory_view_get(obj, &view, 0)) {
+ rb_raise(rb_eRuntimeError, "rb_memory_view_get: failed");
+ }
+
+ if (RARRAY_LEN(indices_v) != view.ndim) {
+ rb_raise(rb_eKeyError, "Indices has an invalid dimension");
+ }
+
+ VALUE buf_indices;
+ ssize_t *indices = ALLOCV_N(ssize_t, buf_indices, view.ndim);
+
+ ssize_t i;
+ for (i = 0; i < view.ndim; ++i) {
+ indices[i] = NUM2SSIZET(RARRAY_AREF(indices_v, i));
+ }
+
+ VALUE result = rb_memory_view_get_item(&view, indices);
+ ALLOCV_END(buf_indices);
+ rb_memory_view_release(&view);
+
+ return result;
+}
+
+#endif /* HAVE_RUBY_MEMORY_VIEW_H */
+
+void
+Init_memory_view(void)
+{
+ rb_ext_ractor_safe(true);
+#ifdef HAVE_RUBY_MEMORY_VIEW_H
+ VALUE mMemoryViewTestUtils = rb_define_module("MemoryViewTestUtils");
+
+ rb_define_module_function(mMemoryViewTestUtils, "available?", memory_view_available_p, 1);
+ rb_define_module_function(mMemoryViewTestUtils, "register", memory_view_register, 1);
+ rb_define_module_function(mMemoryViewTestUtils, "item_size_from_format", memory_view_item_size_from_format, 1);
+ rb_define_module_function(mMemoryViewTestUtils, "parse_item_format", memory_view_parse_item_format, 1);
+ rb_define_module_function(mMemoryViewTestUtils, "get_memory_view_info", memory_view_get_memory_view_info, 1);
+ rb_define_module_function(mMemoryViewTestUtils, "fill_contiguous_strides", memory_view_fill_contiguous_strides, 4);
+ rb_define_module_function(mMemoryViewTestUtils, "ref_count_while_exporting", memory_view_ref_count_while_exporting, 2);
+ rb_define_module_function(mMemoryViewTestUtils, "extract_item_members", memory_view_extract_item_members, 2);
+
+ VALUE cExportableString = rb_define_class_under(mMemoryViewTestUtils, "ExportableString", rb_cObject);
+ rb_define_method(cExportableString, "initialize", expstr_initialize, 1);
+ rb_memory_view_register(cExportableString, &exportable_string_memory_view_entry);
+
+ VALUE cMDView = rb_define_class_under(mMemoryViewTestUtils, "MultiDimensionalView", rb_cObject);
+ rb_define_method(cMDView, "initialize", mdview_initialize, 4);
+ rb_define_method(cMDView, "[]", mdview_aref, 1);
+ rb_memory_view_register(cMDView, &mdview_memory_view_entry);
+
+ id_str = rb_intern_const("__str__");
+ sym_format = ID2SYM(rb_intern_const("format"));
+ sym_native_size_p = ID2SYM(rb_intern_const("native_size_p"));
+ sym_offset = ID2SYM(rb_intern_const("offset"));
+ sym_size = ID2SYM(rb_intern_const("size"));
+ sym_repeat = ID2SYM(rb_intern_const("repeat"));
+ sym_obj = ID2SYM(rb_intern_const("obj"));
+ sym_byte_size = ID2SYM(rb_intern_const("byte_size"));
+ sym_readonly = ID2SYM(rb_intern_const("readonly"));
+ sym_format = ID2SYM(rb_intern_const("format"));
+ sym_item_size = ID2SYM(rb_intern_const("item_size"));
+ sym_ndim = ID2SYM(rb_intern_const("ndim"));
+ sym_shape = ID2SYM(rb_intern_const("shape"));
+ sym_strides = ID2SYM(rb_intern_const("strides"));
+ sym_sub_offsets = ID2SYM(rb_intern_const("sub_offsets"));
+ sym_endianness = ID2SYM(rb_intern_const("endianness"));
+ sym_little_endian = ID2SYM(rb_intern_const("little_endian"));
+ sym_big_endian = ID2SYM(rb_intern_const("big_endian"));
+
+#ifdef WORDS_BIGENDIAN
+ rb_const_set(mMemoryViewTestUtils, rb_intern_const("NATIVE_ENDIAN"), sym_big_endian);
+#else
+ rb_const_set(mMemoryViewTestUtils, rb_intern_const("NATIVE_ENDIAN"), sym_little_endian);
+#endif
+
+#define DEF_ALIGNMENT_CONST(type, TYPE) do { \
+ int alignment; \
+ STRUCT_ALIGNOF(type, alignment); \
+ rb_const_set(mMemoryViewTestUtils, rb_intern_const(#TYPE "_ALIGNMENT"), INT2FIX(alignment)); \
+} while(0)
+
+ DEF_ALIGNMENT_CONST(short, SHORT);
+ DEF_ALIGNMENT_CONST(int, INT);
+ DEF_ALIGNMENT_CONST(long, LONG);
+ DEF_ALIGNMENT_CONST(LONG_LONG, LONG_LONG);
+ DEF_ALIGNMENT_CONST(int16_t, INT16);
+ DEF_ALIGNMENT_CONST(int32_t, INT32);
+ DEF_ALIGNMENT_CONST(int64_t, INT64);
+ DEF_ALIGNMENT_CONST(intptr_t, INTPTR);
+ DEF_ALIGNMENT_CONST(float, FLOAT);
+ DEF_ALIGNMENT_CONST(double, DOUBLE);
+
+#undef DEF_ALIGNMENT_CONST
+
+#endif /* HAVE_RUBY_MEMORY_VIEW_H */
+}
diff --git a/ext/-test-/method/arity.c b/ext/-test-/method/arity.c
new file mode 100644
index 0000000000..239b9f7f10
--- /dev/null
+++ b/ext/-test-/method/arity.c
@@ -0,0 +1,22 @@
+#include "ruby.h"
+
+static VALUE
+obj_method_arity(VALUE self, VALUE obj, VALUE mid)
+{
+ int arity = rb_obj_method_arity(obj, rb_check_id(&mid));
+ return INT2FIX(arity);
+}
+
+static VALUE
+mod_method_arity(VALUE self, VALUE mod, VALUE mid)
+{
+ int arity = rb_mod_method_arity(mod, rb_check_id(&mid));
+ return INT2FIX(arity);
+}
+
+void
+Init_arity(VALUE mod)
+{
+ rb_define_module_function(mod, "obj_method_arity", obj_method_arity, 2);
+ rb_define_module_function(mod, "mod_method_arity", mod_method_arity, 2);
+}
diff --git a/ext/-test-/method/depend b/ext/-test-/method/depend
new file mode 100644
index 0000000000..95745b3dae
--- /dev/null
+++ b/ext/-test-/method/depend
@@ -0,0 +1,324 @@
+# AUTOGENERATED DEPENDENCIES START
+arity.o: $(RUBY_EXTCONF_H)
+arity.o: $(arch_hdrdir)/ruby/config.h
+arity.o: $(hdrdir)/ruby.h
+arity.o: $(hdrdir)/ruby/assert.h
+arity.o: $(hdrdir)/ruby/backward.h
+arity.o: $(hdrdir)/ruby/backward/2/assume.h
+arity.o: $(hdrdir)/ruby/backward/2/attributes.h
+arity.o: $(hdrdir)/ruby/backward/2/bool.h
+arity.o: $(hdrdir)/ruby/backward/2/inttypes.h
+arity.o: $(hdrdir)/ruby/backward/2/limits.h
+arity.o: $(hdrdir)/ruby/backward/2/long_long.h
+arity.o: $(hdrdir)/ruby/backward/2/stdalign.h
+arity.o: $(hdrdir)/ruby/backward/2/stdarg.h
+arity.o: $(hdrdir)/ruby/defines.h
+arity.o: $(hdrdir)/ruby/intern.h
+arity.o: $(hdrdir)/ruby/internal/abi.h
+arity.o: $(hdrdir)/ruby/internal/anyargs.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+arity.o: $(hdrdir)/ruby/internal/assume.h
+arity.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+arity.o: $(hdrdir)/ruby/internal/attr/artificial.h
+arity.o: $(hdrdir)/ruby/internal/attr/cold.h
+arity.o: $(hdrdir)/ruby/internal/attr/const.h
+arity.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+arity.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+arity.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+arity.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+arity.o: $(hdrdir)/ruby/internal/attr/error.h
+arity.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+arity.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+arity.o: $(hdrdir)/ruby/internal/attr/format.h
+arity.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+arity.o: $(hdrdir)/ruby/internal/attr/noalias.h
+arity.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+arity.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+arity.o: $(hdrdir)/ruby/internal/attr/noinline.h
+arity.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+arity.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+arity.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+arity.o: $(hdrdir)/ruby/internal/attr/pure.h
+arity.o: $(hdrdir)/ruby/internal/attr/restrict.h
+arity.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+arity.o: $(hdrdir)/ruby/internal/attr/warning.h
+arity.o: $(hdrdir)/ruby/internal/attr/weakref.h
+arity.o: $(hdrdir)/ruby/internal/cast.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+arity.o: $(hdrdir)/ruby/internal/compiler_since.h
+arity.o: $(hdrdir)/ruby/internal/config.h
+arity.o: $(hdrdir)/ruby/internal/constant_p.h
+arity.o: $(hdrdir)/ruby/internal/core.h
+arity.o: $(hdrdir)/ruby/internal/core/rarray.h
+arity.o: $(hdrdir)/ruby/internal/core/rbasic.h
+arity.o: $(hdrdir)/ruby/internal/core/rbignum.h
+arity.o: $(hdrdir)/ruby/internal/core/rclass.h
+arity.o: $(hdrdir)/ruby/internal/core/rdata.h
+arity.o: $(hdrdir)/ruby/internal/core/rfile.h
+arity.o: $(hdrdir)/ruby/internal/core/rhash.h
+arity.o: $(hdrdir)/ruby/internal/core/robject.h
+arity.o: $(hdrdir)/ruby/internal/core/rregexp.h
+arity.o: $(hdrdir)/ruby/internal/core/rstring.h
+arity.o: $(hdrdir)/ruby/internal/core/rstruct.h
+arity.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+arity.o: $(hdrdir)/ruby/internal/ctype.h
+arity.o: $(hdrdir)/ruby/internal/dllexport.h
+arity.o: $(hdrdir)/ruby/internal/dosish.h
+arity.o: $(hdrdir)/ruby/internal/error.h
+arity.o: $(hdrdir)/ruby/internal/eval.h
+arity.o: $(hdrdir)/ruby/internal/event.h
+arity.o: $(hdrdir)/ruby/internal/fl_type.h
+arity.o: $(hdrdir)/ruby/internal/gc.h
+arity.o: $(hdrdir)/ruby/internal/glob.h
+arity.o: $(hdrdir)/ruby/internal/globals.h
+arity.o: $(hdrdir)/ruby/internal/has/attribute.h
+arity.o: $(hdrdir)/ruby/internal/has/builtin.h
+arity.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+arity.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+arity.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+arity.o: $(hdrdir)/ruby/internal/has/extension.h
+arity.o: $(hdrdir)/ruby/internal/has/feature.h
+arity.o: $(hdrdir)/ruby/internal/has/warning.h
+arity.o: $(hdrdir)/ruby/internal/intern/array.h
+arity.o: $(hdrdir)/ruby/internal/intern/bignum.h
+arity.o: $(hdrdir)/ruby/internal/intern/class.h
+arity.o: $(hdrdir)/ruby/internal/intern/compar.h
+arity.o: $(hdrdir)/ruby/internal/intern/complex.h
+arity.o: $(hdrdir)/ruby/internal/intern/cont.h
+arity.o: $(hdrdir)/ruby/internal/intern/dir.h
+arity.o: $(hdrdir)/ruby/internal/intern/enum.h
+arity.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+arity.o: $(hdrdir)/ruby/internal/intern/error.h
+arity.o: $(hdrdir)/ruby/internal/intern/eval.h
+arity.o: $(hdrdir)/ruby/internal/intern/file.h
+arity.o: $(hdrdir)/ruby/internal/intern/hash.h
+arity.o: $(hdrdir)/ruby/internal/intern/io.h
+arity.o: $(hdrdir)/ruby/internal/intern/load.h
+arity.o: $(hdrdir)/ruby/internal/intern/marshal.h
+arity.o: $(hdrdir)/ruby/internal/intern/numeric.h
+arity.o: $(hdrdir)/ruby/internal/intern/object.h
+arity.o: $(hdrdir)/ruby/internal/intern/parse.h
+arity.o: $(hdrdir)/ruby/internal/intern/proc.h
+arity.o: $(hdrdir)/ruby/internal/intern/process.h
+arity.o: $(hdrdir)/ruby/internal/intern/random.h
+arity.o: $(hdrdir)/ruby/internal/intern/range.h
+arity.o: $(hdrdir)/ruby/internal/intern/rational.h
+arity.o: $(hdrdir)/ruby/internal/intern/re.h
+arity.o: $(hdrdir)/ruby/internal/intern/ruby.h
+arity.o: $(hdrdir)/ruby/internal/intern/select.h
+arity.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+arity.o: $(hdrdir)/ruby/internal/intern/set.h
+arity.o: $(hdrdir)/ruby/internal/intern/signal.h
+arity.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+arity.o: $(hdrdir)/ruby/internal/intern/string.h
+arity.o: $(hdrdir)/ruby/internal/intern/struct.h
+arity.o: $(hdrdir)/ruby/internal/intern/thread.h
+arity.o: $(hdrdir)/ruby/internal/intern/time.h
+arity.o: $(hdrdir)/ruby/internal/intern/variable.h
+arity.o: $(hdrdir)/ruby/internal/intern/vm.h
+arity.o: $(hdrdir)/ruby/internal/interpreter.h
+arity.o: $(hdrdir)/ruby/internal/iterator.h
+arity.o: $(hdrdir)/ruby/internal/memory.h
+arity.o: $(hdrdir)/ruby/internal/method.h
+arity.o: $(hdrdir)/ruby/internal/module.h
+arity.o: $(hdrdir)/ruby/internal/newobj.h
+arity.o: $(hdrdir)/ruby/internal/scan_args.h
+arity.o: $(hdrdir)/ruby/internal/special_consts.h
+arity.o: $(hdrdir)/ruby/internal/static_assert.h
+arity.o: $(hdrdir)/ruby/internal/stdalign.h
+arity.o: $(hdrdir)/ruby/internal/stdbool.h
+arity.o: $(hdrdir)/ruby/internal/stdckdint.h
+arity.o: $(hdrdir)/ruby/internal/symbol.h
+arity.o: $(hdrdir)/ruby/internal/value.h
+arity.o: $(hdrdir)/ruby/internal/value_type.h
+arity.o: $(hdrdir)/ruby/internal/variable.h
+arity.o: $(hdrdir)/ruby/internal/warning_push.h
+arity.o: $(hdrdir)/ruby/internal/xmalloc.h
+arity.o: $(hdrdir)/ruby/missing.h
+arity.o: $(hdrdir)/ruby/ruby.h
+arity.o: $(hdrdir)/ruby/st.h
+arity.o: $(hdrdir)/ruby/subst.h
+arity.o: arity.c
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/method/extconf.rb b/ext/-test-/method/extconf.rb
new file mode 100644
index 0000000000..ca51178a18
--- /dev/null
+++ b/ext/-test-/method/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext
diff --git a/ext/-test-/method/init.c b/ext/-test-/method/init.c
new file mode 100644
index 0000000000..cea2346240
--- /dev/null
+++ b/ext/-test-/method/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_method(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_module_under(mBug, "Method");
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/notimplement/bug.c b/ext/-test-/notimplement/bug.c
new file mode 100644
index 0000000000..82e243a81d
--- /dev/null
+++ b/ext/-test-/notimplement/bug.c
@@ -0,0 +1,18 @@
+#include <ruby.h>
+
+static VALUE
+bug_funcall(int argc, VALUE *argv, VALUE self)
+{
+ if (argc < 1) rb_raise(rb_eArgError, "not enough argument");
+ return rb_funcallv(self, rb_to_id(*argv), argc-1, argv+1);
+}
+
+void
+Init_notimplement(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "NotImplement", rb_cObject);
+ rb_define_module_function(mBug, "funcall", bug_funcall, -1);
+ rb_define_module_function(mBug, "notimplement", rb_f_notimplement, -1);
+ rb_define_method(klass, "notimplement", rb_f_notimplement, -1);
+}
diff --git a/ext/-test-/notimplement/depend b/ext/-test-/notimplement/depend
new file mode 100644
index 0000000000..69c970b6f2
--- /dev/null
+++ b/ext/-test-/notimplement/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+bug.o: $(RUBY_EXTCONF_H)
+bug.o: $(arch_hdrdir)/ruby/config.h
+bug.o: $(hdrdir)/ruby.h
+bug.o: $(hdrdir)/ruby/assert.h
+bug.o: $(hdrdir)/ruby/backward.h
+bug.o: $(hdrdir)/ruby/backward/2/assume.h
+bug.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug.o: $(hdrdir)/ruby/backward/2/bool.h
+bug.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug.o: $(hdrdir)/ruby/backward/2/limits.h
+bug.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bug.o: $(hdrdir)/ruby/defines.h
+bug.o: $(hdrdir)/ruby/intern.h
+bug.o: $(hdrdir)/ruby/internal/abi.h
+bug.o: $(hdrdir)/ruby/internal/anyargs.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bug.o: $(hdrdir)/ruby/internal/assume.h
+bug.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bug.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bug.o: $(hdrdir)/ruby/internal/attr/cold.h
+bug.o: $(hdrdir)/ruby/internal/attr/const.h
+bug.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bug.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bug.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bug.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bug.o: $(hdrdir)/ruby/internal/attr/error.h
+bug.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bug.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bug.o: $(hdrdir)/ruby/internal/attr/format.h
+bug.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bug.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bug.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bug.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bug.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bug.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bug.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bug.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+bug.o: $(hdrdir)/ruby/internal/attr/pure.h
+bug.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bug.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bug.o: $(hdrdir)/ruby/internal/attr/warning.h
+bug.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bug.o: $(hdrdir)/ruby/internal/cast.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bug.o: $(hdrdir)/ruby/internal/compiler_since.h
+bug.o: $(hdrdir)/ruby/internal/config.h
+bug.o: $(hdrdir)/ruby/internal/constant_p.h
+bug.o: $(hdrdir)/ruby/internal/core.h
+bug.o: $(hdrdir)/ruby/internal/core/rarray.h
+bug.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bug.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bug.o: $(hdrdir)/ruby/internal/core/rclass.h
+bug.o: $(hdrdir)/ruby/internal/core/rdata.h
+bug.o: $(hdrdir)/ruby/internal/core/rfile.h
+bug.o: $(hdrdir)/ruby/internal/core/rhash.h
+bug.o: $(hdrdir)/ruby/internal/core/robject.h
+bug.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bug.o: $(hdrdir)/ruby/internal/core/rstring.h
+bug.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bug.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bug.o: $(hdrdir)/ruby/internal/ctype.h
+bug.o: $(hdrdir)/ruby/internal/dllexport.h
+bug.o: $(hdrdir)/ruby/internal/dosish.h
+bug.o: $(hdrdir)/ruby/internal/error.h
+bug.o: $(hdrdir)/ruby/internal/eval.h
+bug.o: $(hdrdir)/ruby/internal/event.h
+bug.o: $(hdrdir)/ruby/internal/fl_type.h
+bug.o: $(hdrdir)/ruby/internal/gc.h
+bug.o: $(hdrdir)/ruby/internal/glob.h
+bug.o: $(hdrdir)/ruby/internal/globals.h
+bug.o: $(hdrdir)/ruby/internal/has/attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/builtin.h
+bug.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/extension.h
+bug.o: $(hdrdir)/ruby/internal/has/feature.h
+bug.o: $(hdrdir)/ruby/internal/has/warning.h
+bug.o: $(hdrdir)/ruby/internal/intern/array.h
+bug.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bug.o: $(hdrdir)/ruby/internal/intern/class.h
+bug.o: $(hdrdir)/ruby/internal/intern/compar.h
+bug.o: $(hdrdir)/ruby/internal/intern/complex.h
+bug.o: $(hdrdir)/ruby/internal/intern/cont.h
+bug.o: $(hdrdir)/ruby/internal/intern/dir.h
+bug.o: $(hdrdir)/ruby/internal/intern/enum.h
+bug.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bug.o: $(hdrdir)/ruby/internal/intern/error.h
+bug.o: $(hdrdir)/ruby/internal/intern/eval.h
+bug.o: $(hdrdir)/ruby/internal/intern/file.h
+bug.o: $(hdrdir)/ruby/internal/intern/hash.h
+bug.o: $(hdrdir)/ruby/internal/intern/io.h
+bug.o: $(hdrdir)/ruby/internal/intern/load.h
+bug.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bug.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bug.o: $(hdrdir)/ruby/internal/intern/object.h
+bug.o: $(hdrdir)/ruby/internal/intern/parse.h
+bug.o: $(hdrdir)/ruby/internal/intern/proc.h
+bug.o: $(hdrdir)/ruby/internal/intern/process.h
+bug.o: $(hdrdir)/ruby/internal/intern/random.h
+bug.o: $(hdrdir)/ruby/internal/intern/range.h
+bug.o: $(hdrdir)/ruby/internal/intern/rational.h
+bug.o: $(hdrdir)/ruby/internal/intern/re.h
+bug.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bug.o: $(hdrdir)/ruby/internal/intern/select.h
+bug.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug.o: $(hdrdir)/ruby/internal/intern/set.h
+bug.o: $(hdrdir)/ruby/internal/intern/signal.h
+bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bug.o: $(hdrdir)/ruby/internal/intern/string.h
+bug.o: $(hdrdir)/ruby/internal/intern/struct.h
+bug.o: $(hdrdir)/ruby/internal/intern/thread.h
+bug.o: $(hdrdir)/ruby/internal/intern/time.h
+bug.o: $(hdrdir)/ruby/internal/intern/variable.h
+bug.o: $(hdrdir)/ruby/internal/intern/vm.h
+bug.o: $(hdrdir)/ruby/internal/interpreter.h
+bug.o: $(hdrdir)/ruby/internal/iterator.h
+bug.o: $(hdrdir)/ruby/internal/memory.h
+bug.o: $(hdrdir)/ruby/internal/method.h
+bug.o: $(hdrdir)/ruby/internal/module.h
+bug.o: $(hdrdir)/ruby/internal/newobj.h
+bug.o: $(hdrdir)/ruby/internal/scan_args.h
+bug.o: $(hdrdir)/ruby/internal/special_consts.h
+bug.o: $(hdrdir)/ruby/internal/static_assert.h
+bug.o: $(hdrdir)/ruby/internal/stdalign.h
+bug.o: $(hdrdir)/ruby/internal/stdbool.h
+bug.o: $(hdrdir)/ruby/internal/stdckdint.h
+bug.o: $(hdrdir)/ruby/internal/symbol.h
+bug.o: $(hdrdir)/ruby/internal/value.h
+bug.o: $(hdrdir)/ruby/internal/value_type.h
+bug.o: $(hdrdir)/ruby/internal/variable.h
+bug.o: $(hdrdir)/ruby/internal/warning_push.h
+bug.o: $(hdrdir)/ruby/internal/xmalloc.h
+bug.o: $(hdrdir)/ruby/missing.h
+bug.o: $(hdrdir)/ruby/ruby.h
+bug.o: $(hdrdir)/ruby/st.h
+bug.o: $(hdrdir)/ruby/subst.h
+bug.o: bug.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/notimplement/extconf.rb b/ext/-test-/notimplement/extconf.rb
new file mode 100644
index 0000000000..54403cd7ce
--- /dev/null
+++ b/ext/-test-/notimplement/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/notimplement")
diff --git a/ext/-test-/num2int/depend b/ext/-test-/num2int/depend
new file mode 100644
index 0000000000..75536363ac
--- /dev/null
+++ b/ext/-test-/num2int/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+num2int.o: $(RUBY_EXTCONF_H)
+num2int.o: $(arch_hdrdir)/ruby/config.h
+num2int.o: $(hdrdir)/ruby.h
+num2int.o: $(hdrdir)/ruby/assert.h
+num2int.o: $(hdrdir)/ruby/backward.h
+num2int.o: $(hdrdir)/ruby/backward/2/assume.h
+num2int.o: $(hdrdir)/ruby/backward/2/attributes.h
+num2int.o: $(hdrdir)/ruby/backward/2/bool.h
+num2int.o: $(hdrdir)/ruby/backward/2/inttypes.h
+num2int.o: $(hdrdir)/ruby/backward/2/limits.h
+num2int.o: $(hdrdir)/ruby/backward/2/long_long.h
+num2int.o: $(hdrdir)/ruby/backward/2/stdalign.h
+num2int.o: $(hdrdir)/ruby/backward/2/stdarg.h
+num2int.o: $(hdrdir)/ruby/defines.h
+num2int.o: $(hdrdir)/ruby/intern.h
+num2int.o: $(hdrdir)/ruby/internal/abi.h
+num2int.o: $(hdrdir)/ruby/internal/anyargs.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+num2int.o: $(hdrdir)/ruby/internal/assume.h
+num2int.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+num2int.o: $(hdrdir)/ruby/internal/attr/artificial.h
+num2int.o: $(hdrdir)/ruby/internal/attr/cold.h
+num2int.o: $(hdrdir)/ruby/internal/attr/const.h
+num2int.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+num2int.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+num2int.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+num2int.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+num2int.o: $(hdrdir)/ruby/internal/attr/error.h
+num2int.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+num2int.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+num2int.o: $(hdrdir)/ruby/internal/attr/format.h
+num2int.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+num2int.o: $(hdrdir)/ruby/internal/attr/noalias.h
+num2int.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+num2int.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+num2int.o: $(hdrdir)/ruby/internal/attr/noinline.h
+num2int.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+num2int.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+num2int.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+num2int.o: $(hdrdir)/ruby/internal/attr/pure.h
+num2int.o: $(hdrdir)/ruby/internal/attr/restrict.h
+num2int.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+num2int.o: $(hdrdir)/ruby/internal/attr/warning.h
+num2int.o: $(hdrdir)/ruby/internal/attr/weakref.h
+num2int.o: $(hdrdir)/ruby/internal/cast.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_since.h
+num2int.o: $(hdrdir)/ruby/internal/config.h
+num2int.o: $(hdrdir)/ruby/internal/constant_p.h
+num2int.o: $(hdrdir)/ruby/internal/core.h
+num2int.o: $(hdrdir)/ruby/internal/core/rarray.h
+num2int.o: $(hdrdir)/ruby/internal/core/rbasic.h
+num2int.o: $(hdrdir)/ruby/internal/core/rbignum.h
+num2int.o: $(hdrdir)/ruby/internal/core/rclass.h
+num2int.o: $(hdrdir)/ruby/internal/core/rdata.h
+num2int.o: $(hdrdir)/ruby/internal/core/rfile.h
+num2int.o: $(hdrdir)/ruby/internal/core/rhash.h
+num2int.o: $(hdrdir)/ruby/internal/core/robject.h
+num2int.o: $(hdrdir)/ruby/internal/core/rregexp.h
+num2int.o: $(hdrdir)/ruby/internal/core/rstring.h
+num2int.o: $(hdrdir)/ruby/internal/core/rstruct.h
+num2int.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+num2int.o: $(hdrdir)/ruby/internal/ctype.h
+num2int.o: $(hdrdir)/ruby/internal/dllexport.h
+num2int.o: $(hdrdir)/ruby/internal/dosish.h
+num2int.o: $(hdrdir)/ruby/internal/error.h
+num2int.o: $(hdrdir)/ruby/internal/eval.h
+num2int.o: $(hdrdir)/ruby/internal/event.h
+num2int.o: $(hdrdir)/ruby/internal/fl_type.h
+num2int.o: $(hdrdir)/ruby/internal/gc.h
+num2int.o: $(hdrdir)/ruby/internal/glob.h
+num2int.o: $(hdrdir)/ruby/internal/globals.h
+num2int.o: $(hdrdir)/ruby/internal/has/attribute.h
+num2int.o: $(hdrdir)/ruby/internal/has/builtin.h
+num2int.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+num2int.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+num2int.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+num2int.o: $(hdrdir)/ruby/internal/has/extension.h
+num2int.o: $(hdrdir)/ruby/internal/has/feature.h
+num2int.o: $(hdrdir)/ruby/internal/has/warning.h
+num2int.o: $(hdrdir)/ruby/internal/intern/array.h
+num2int.o: $(hdrdir)/ruby/internal/intern/bignum.h
+num2int.o: $(hdrdir)/ruby/internal/intern/class.h
+num2int.o: $(hdrdir)/ruby/internal/intern/compar.h
+num2int.o: $(hdrdir)/ruby/internal/intern/complex.h
+num2int.o: $(hdrdir)/ruby/internal/intern/cont.h
+num2int.o: $(hdrdir)/ruby/internal/intern/dir.h
+num2int.o: $(hdrdir)/ruby/internal/intern/enum.h
+num2int.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+num2int.o: $(hdrdir)/ruby/internal/intern/error.h
+num2int.o: $(hdrdir)/ruby/internal/intern/eval.h
+num2int.o: $(hdrdir)/ruby/internal/intern/file.h
+num2int.o: $(hdrdir)/ruby/internal/intern/hash.h
+num2int.o: $(hdrdir)/ruby/internal/intern/io.h
+num2int.o: $(hdrdir)/ruby/internal/intern/load.h
+num2int.o: $(hdrdir)/ruby/internal/intern/marshal.h
+num2int.o: $(hdrdir)/ruby/internal/intern/numeric.h
+num2int.o: $(hdrdir)/ruby/internal/intern/object.h
+num2int.o: $(hdrdir)/ruby/internal/intern/parse.h
+num2int.o: $(hdrdir)/ruby/internal/intern/proc.h
+num2int.o: $(hdrdir)/ruby/internal/intern/process.h
+num2int.o: $(hdrdir)/ruby/internal/intern/random.h
+num2int.o: $(hdrdir)/ruby/internal/intern/range.h
+num2int.o: $(hdrdir)/ruby/internal/intern/rational.h
+num2int.o: $(hdrdir)/ruby/internal/intern/re.h
+num2int.o: $(hdrdir)/ruby/internal/intern/ruby.h
+num2int.o: $(hdrdir)/ruby/internal/intern/select.h
+num2int.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+num2int.o: $(hdrdir)/ruby/internal/intern/set.h
+num2int.o: $(hdrdir)/ruby/internal/intern/signal.h
+num2int.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+num2int.o: $(hdrdir)/ruby/internal/intern/string.h
+num2int.o: $(hdrdir)/ruby/internal/intern/struct.h
+num2int.o: $(hdrdir)/ruby/internal/intern/thread.h
+num2int.o: $(hdrdir)/ruby/internal/intern/time.h
+num2int.o: $(hdrdir)/ruby/internal/intern/variable.h
+num2int.o: $(hdrdir)/ruby/internal/intern/vm.h
+num2int.o: $(hdrdir)/ruby/internal/interpreter.h
+num2int.o: $(hdrdir)/ruby/internal/iterator.h
+num2int.o: $(hdrdir)/ruby/internal/memory.h
+num2int.o: $(hdrdir)/ruby/internal/method.h
+num2int.o: $(hdrdir)/ruby/internal/module.h
+num2int.o: $(hdrdir)/ruby/internal/newobj.h
+num2int.o: $(hdrdir)/ruby/internal/scan_args.h
+num2int.o: $(hdrdir)/ruby/internal/special_consts.h
+num2int.o: $(hdrdir)/ruby/internal/static_assert.h
+num2int.o: $(hdrdir)/ruby/internal/stdalign.h
+num2int.o: $(hdrdir)/ruby/internal/stdbool.h
+num2int.o: $(hdrdir)/ruby/internal/stdckdint.h
+num2int.o: $(hdrdir)/ruby/internal/symbol.h
+num2int.o: $(hdrdir)/ruby/internal/value.h
+num2int.o: $(hdrdir)/ruby/internal/value_type.h
+num2int.o: $(hdrdir)/ruby/internal/variable.h
+num2int.o: $(hdrdir)/ruby/internal/warning_push.h
+num2int.o: $(hdrdir)/ruby/internal/xmalloc.h
+num2int.o: $(hdrdir)/ruby/missing.h
+num2int.o: $(hdrdir)/ruby/ruby.h
+num2int.o: $(hdrdir)/ruby/st.h
+num2int.o: $(hdrdir)/ruby/subst.h
+num2int.o: num2int.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/num2int/extconf.rb b/ext/-test-/num2int/extconf.rb
new file mode 100644
index 0000000000..425f261f58
--- /dev/null
+++ b/ext/-test-/num2int/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/num2int")
diff --git a/ext/-test-/num2int/num2int.c b/ext/-test-/num2int/num2int.c
new file mode 100644
index 0000000000..63a441fda6
--- /dev/null
+++ b/ext/-test-/num2int/num2int.c
@@ -0,0 +1,136 @@
+#include <ruby.h>
+
+static VALUE
+test_num2short(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%d", NUM2SHORT(num));
+ return rb_str_new_cstr(buf);
+}
+
+static VALUE
+test_num2ushort(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%u", NUM2USHORT(num));
+ return rb_str_new_cstr(buf);
+}
+
+static VALUE
+test_num2int(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%d", NUM2INT(num));
+ return rb_str_new_cstr(buf);
+}
+
+static VALUE
+test_num2uint(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%u", NUM2UINT(num));
+ return rb_str_new_cstr(buf);
+}
+
+static VALUE
+test_num2long(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%ld", NUM2LONG(num));
+ return rb_str_new_cstr(buf);
+}
+
+static VALUE
+test_num2ulong(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%lu", NUM2ULONG(num));
+ return rb_str_new_cstr(buf);
+}
+
+#ifdef HAVE_LONG_LONG
+static VALUE
+test_num2ll(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%"PRI_LL_PREFIX"d", NUM2LL(num));
+ return rb_str_new_cstr(buf);
+}
+
+static VALUE
+test_num2ull(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%"PRI_LL_PREFIX"u", NUM2ULL(num));
+ return rb_str_new_cstr(buf);
+}
+#endif
+
+static VALUE
+test_fix2short(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%d", FIX2SHORT(num));
+ return rb_str_new_cstr(buf);
+}
+
+static VALUE
+test_fix2int(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%d", FIX2INT(num));
+ return rb_str_new_cstr(buf);
+}
+
+static VALUE
+test_fix2uint(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%u", FIX2UINT(num));
+ return rb_str_new_cstr(buf);
+}
+
+static VALUE
+test_fix2long(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%ld", FIX2LONG(num));
+ return rb_str_new_cstr(buf);
+}
+
+static VALUE
+test_fix2ulong(VALUE obj, VALUE num)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%lu", FIX2ULONG(num));
+ return rb_str_new_cstr(buf);
+}
+
+void
+Init_num2int(void)
+{
+ VALUE mNum2int = rb_define_module("Num2int");
+
+ rb_define_module_function(mNum2int, "NUM2SHORT", test_num2short, 1);
+ rb_define_module_function(mNum2int, "NUM2USHORT", test_num2ushort, 1);
+
+ rb_define_module_function(mNum2int, "NUM2INT", test_num2int, 1);
+ rb_define_module_function(mNum2int, "NUM2UINT", test_num2uint, 1);
+
+ rb_define_module_function(mNum2int, "NUM2LONG", test_num2long, 1);
+ rb_define_module_function(mNum2int, "NUM2ULONG", test_num2ulong, 1);
+
+#ifdef HAVE_LONG_LONG
+ rb_define_module_function(mNum2int, "NUM2LL", test_num2ll, 1);
+ rb_define_module_function(mNum2int, "NUM2ULL", test_num2ull, 1);
+#endif
+
+ rb_define_module_function(mNum2int, "FIX2SHORT", test_fix2short, 1);
+
+ rb_define_module_function(mNum2int, "FIX2INT", test_fix2int, 1);
+ rb_define_module_function(mNum2int, "FIX2UINT", test_fix2uint, 1);
+
+ rb_define_module_function(mNum2int, "FIX2LONG", test_fix2long, 1);
+ rb_define_module_function(mNum2int, "FIX2ULONG", test_fix2ulong, 1);
+}
+
diff --git a/ext/-test-/path_to_class/depend b/ext/-test-/path_to_class/depend
new file mode 100644
index 0000000000..e535058e09
--- /dev/null
+++ b/ext/-test-/path_to_class/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+path_to_class.o: $(RUBY_EXTCONF_H)
+path_to_class.o: $(arch_hdrdir)/ruby/config.h
+path_to_class.o: $(hdrdir)/ruby.h
+path_to_class.o: $(hdrdir)/ruby/assert.h
+path_to_class.o: $(hdrdir)/ruby/backward.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/assume.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/attributes.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/bool.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/inttypes.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/limits.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/long_long.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/stdalign.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/stdarg.h
+path_to_class.o: $(hdrdir)/ruby/defines.h
+path_to_class.o: $(hdrdir)/ruby/intern.h
+path_to_class.o: $(hdrdir)/ruby/internal/abi.h
+path_to_class.o: $(hdrdir)/ruby/internal/anyargs.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/assume.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/artificial.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/cold.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/const.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/error.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/format.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/noalias.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/noinline.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/pure.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/restrict.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/warning.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/weakref.h
+path_to_class.o: $(hdrdir)/ruby/internal/cast.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_since.h
+path_to_class.o: $(hdrdir)/ruby/internal/config.h
+path_to_class.o: $(hdrdir)/ruby/internal/constant_p.h
+path_to_class.o: $(hdrdir)/ruby/internal/core.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rarray.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rbasic.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rbignum.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rclass.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rdata.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rfile.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rhash.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/robject.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rregexp.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rstring.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rstruct.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+path_to_class.o: $(hdrdir)/ruby/internal/ctype.h
+path_to_class.o: $(hdrdir)/ruby/internal/dllexport.h
+path_to_class.o: $(hdrdir)/ruby/internal/dosish.h
+path_to_class.o: $(hdrdir)/ruby/internal/error.h
+path_to_class.o: $(hdrdir)/ruby/internal/eval.h
+path_to_class.o: $(hdrdir)/ruby/internal/event.h
+path_to_class.o: $(hdrdir)/ruby/internal/fl_type.h
+path_to_class.o: $(hdrdir)/ruby/internal/gc.h
+path_to_class.o: $(hdrdir)/ruby/internal/glob.h
+path_to_class.o: $(hdrdir)/ruby/internal/globals.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/attribute.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/builtin.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/extension.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/feature.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/warning.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/array.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/bignum.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/class.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/compar.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/complex.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/cont.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/dir.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/enum.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/error.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/eval.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/file.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/hash.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/io.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/load.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/marshal.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/numeric.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/object.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/parse.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/proc.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/process.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/random.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/range.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/rational.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/re.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/ruby.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/select.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/set.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/signal.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/string.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/struct.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/thread.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/time.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/variable.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/vm.h
+path_to_class.o: $(hdrdir)/ruby/internal/interpreter.h
+path_to_class.o: $(hdrdir)/ruby/internal/iterator.h
+path_to_class.o: $(hdrdir)/ruby/internal/memory.h
+path_to_class.o: $(hdrdir)/ruby/internal/method.h
+path_to_class.o: $(hdrdir)/ruby/internal/module.h
+path_to_class.o: $(hdrdir)/ruby/internal/newobj.h
+path_to_class.o: $(hdrdir)/ruby/internal/scan_args.h
+path_to_class.o: $(hdrdir)/ruby/internal/special_consts.h
+path_to_class.o: $(hdrdir)/ruby/internal/static_assert.h
+path_to_class.o: $(hdrdir)/ruby/internal/stdalign.h
+path_to_class.o: $(hdrdir)/ruby/internal/stdbool.h
+path_to_class.o: $(hdrdir)/ruby/internal/stdckdint.h
+path_to_class.o: $(hdrdir)/ruby/internal/symbol.h
+path_to_class.o: $(hdrdir)/ruby/internal/value.h
+path_to_class.o: $(hdrdir)/ruby/internal/value_type.h
+path_to_class.o: $(hdrdir)/ruby/internal/variable.h
+path_to_class.o: $(hdrdir)/ruby/internal/warning_push.h
+path_to_class.o: $(hdrdir)/ruby/internal/xmalloc.h
+path_to_class.o: $(hdrdir)/ruby/missing.h
+path_to_class.o: $(hdrdir)/ruby/ruby.h
+path_to_class.o: $(hdrdir)/ruby/st.h
+path_to_class.o: $(hdrdir)/ruby/subst.h
+path_to_class.o: path_to_class.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/path_to_class/extconf.rb b/ext/-test-/path_to_class/extconf.rb
new file mode 100644
index 0000000000..d465b36d9c
--- /dev/null
+++ b/ext/-test-/path_to_class/extconf.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: false
+$srcs = Dir[File.join($srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
+inits = $srcs.map {|s| File.basename(s, ".*")}
+inits.delete("init")
+inits.map! {|s|"X(#{s})"}
+$defs << "-DTEST_INIT_FUNCS(X)=\"#{inits.join(' ')}\""
+create_makefile("-test-/path_to_class")
diff --git a/ext/-test-/path_to_class/path_to_class.c b/ext/-test-/path_to_class/path_to_class.c
new file mode 100644
index 0000000000..c8c2831b09
--- /dev/null
+++ b/ext/-test-/path_to_class/path_to_class.c
@@ -0,0 +1,15 @@
+#include "ruby.h"
+
+static VALUE
+path_to_class(VALUE klass, VALUE path)
+{
+ return rb_path_to_class(path);
+}
+
+void
+Init_path_to_class(void)
+{
+ VALUE klass = rb_path2class("Test_PathToClass");
+
+ rb_define_singleton_method(klass, "path_to_class", path_to_class, 1);
+}
diff --git a/ext/-test-/popen_deadlock/depend b/ext/-test-/popen_deadlock/depend
new file mode 100644
index 0000000000..0b8932e8b8
--- /dev/null
+++ b/ext/-test-/popen_deadlock/depend
@@ -0,0 +1,164 @@
+# AUTOGENERATED DEPENDENCIES START
+infinite_loop_dlsym.o: $(RUBY_EXTCONF_H)
+infinite_loop_dlsym.o: $(arch_hdrdir)/ruby/config.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/assert.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/assume.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/attributes.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/bool.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/inttypes.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/limits.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/long_long.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/stdalign.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/stdarg.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/defines.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/intern.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/abi.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/anyargs.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/assume.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/artificial.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/cold.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/const.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/error.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/format.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/noalias.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/noinline.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/pure.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/restrict.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/warning.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/weakref.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/cast.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_since.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/config.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/constant_p.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rarray.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rbasic.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rbignum.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rclass.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rdata.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rfile.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rhash.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/robject.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rregexp.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rstring.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rstruct.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/ctype.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/dllexport.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/dosish.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/error.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/eval.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/event.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/fl_type.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/gc.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/glob.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/globals.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/attribute.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/builtin.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/extension.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/feature.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/warning.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/array.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/bignum.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/class.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/compar.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/complex.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/cont.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/dir.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/enum.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/error.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/eval.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/file.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/hash.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/io.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/load.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/marshal.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/numeric.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/object.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/parse.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/proc.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/process.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/random.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/range.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/rational.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/re.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/ruby.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/select.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/set.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/signal.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/string.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/struct.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/thread.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/time.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/variable.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/vm.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/interpreter.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/iterator.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/memory.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/method.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/module.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/newobj.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/scan_args.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/special_consts.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/static_assert.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/stdalign.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/stdbool.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/stdckdint.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/symbol.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/value.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/value_type.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/variable.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/warning_push.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/xmalloc.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/missing.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/ruby.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/st.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/subst.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/thread.h
+infinite_loop_dlsym.o: infinite_loop_dlsym.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/popen_deadlock/extconf.rb b/ext/-test-/popen_deadlock/extconf.rb
new file mode 100644
index 0000000000..6b6ee7a6b8
--- /dev/null
+++ b/ext/-test-/popen_deadlock/extconf.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: false
+case RUBY_PLATFORM
+when /solaris/i, /linux/i
+ $LDFLAGS << " -ldl"
+ create_makefile("-test-/popen_deadlock/infinite_loop_dlsym")
+end
diff --git a/ext/-test-/popen_deadlock/infinite_loop_dlsym.c b/ext/-test-/popen_deadlock/infinite_loop_dlsym.c
new file mode 100644
index 0000000000..1d95a7cc9a
--- /dev/null
+++ b/ext/-test-/popen_deadlock/infinite_loop_dlsym.c
@@ -0,0 +1,50 @@
+#include "ruby/ruby.h"
+#include "ruby/thread.h"
+#include <dlfcn.h>
+
+struct data_for_loop_dlsym {
+ const char *name;
+ volatile int stop;
+};
+
+static void*
+native_loop_dlsym(void *data)
+{
+ struct data_for_loop_dlsym *s = data;
+
+ while (!(s->stop)) {
+ dlsym(RTLD_DEFAULT, s->name);
+ }
+
+ return NULL;
+}
+
+static void
+ubf_for_loop_dlsym(void *data)
+{
+ struct data_for_loop_dlsym *s = data;
+
+ s->stop = 1;
+
+ return;
+}
+
+static VALUE
+loop_dlsym(VALUE self, VALUE name)
+{
+ struct data_for_loop_dlsym d;
+
+ d.stop = 0;
+ d.name = StringValuePtr(name);
+
+ rb_thread_call_without_gvl(native_loop_dlsym, &d,
+ ubf_for_loop_dlsym, &d);
+
+ return self;
+}
+
+void
+Init_infinite_loop_dlsym(void)
+{
+ rb_define_method(rb_cThread, "__infinite_loop_dlsym__", loop_dlsym, 1);
+}
diff --git a/ext/-test-/postponed_job/depend b/ext/-test-/postponed_job/depend
new file mode 100644
index 0000000000..ff567e3921
--- /dev/null
+++ b/ext/-test-/postponed_job/depend
@@ -0,0 +1,164 @@
+# AUTOGENERATED DEPENDENCIES START
+postponed_job.o: $(RUBY_EXTCONF_H)
+postponed_job.o: $(arch_hdrdir)/ruby/config.h
+postponed_job.o: $(hdrdir)/ruby.h
+postponed_job.o: $(hdrdir)/ruby/assert.h
+postponed_job.o: $(hdrdir)/ruby/backward.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/assume.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/attributes.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/bool.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/inttypes.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/limits.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/long_long.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/stdalign.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/stdarg.h
+postponed_job.o: $(hdrdir)/ruby/debug.h
+postponed_job.o: $(hdrdir)/ruby/defines.h
+postponed_job.o: $(hdrdir)/ruby/intern.h
+postponed_job.o: $(hdrdir)/ruby/internal/abi.h
+postponed_job.o: $(hdrdir)/ruby/internal/anyargs.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/assume.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/artificial.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/cold.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/const.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/error.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/format.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/noalias.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/noinline.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/pure.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/restrict.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/warning.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/weakref.h
+postponed_job.o: $(hdrdir)/ruby/internal/cast.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_since.h
+postponed_job.o: $(hdrdir)/ruby/internal/config.h
+postponed_job.o: $(hdrdir)/ruby/internal/constant_p.h
+postponed_job.o: $(hdrdir)/ruby/internal/core.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rarray.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rbasic.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rbignum.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rclass.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rdata.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rfile.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rhash.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/robject.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rregexp.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rstring.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rstruct.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+postponed_job.o: $(hdrdir)/ruby/internal/ctype.h
+postponed_job.o: $(hdrdir)/ruby/internal/dllexport.h
+postponed_job.o: $(hdrdir)/ruby/internal/dosish.h
+postponed_job.o: $(hdrdir)/ruby/internal/error.h
+postponed_job.o: $(hdrdir)/ruby/internal/eval.h
+postponed_job.o: $(hdrdir)/ruby/internal/event.h
+postponed_job.o: $(hdrdir)/ruby/internal/fl_type.h
+postponed_job.o: $(hdrdir)/ruby/internal/gc.h
+postponed_job.o: $(hdrdir)/ruby/internal/glob.h
+postponed_job.o: $(hdrdir)/ruby/internal/globals.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/attribute.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/builtin.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/extension.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/feature.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/warning.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/array.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/bignum.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/class.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/compar.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/complex.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/cont.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/dir.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/enum.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/error.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/eval.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/file.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/hash.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/io.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/load.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/marshal.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/numeric.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/object.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/parse.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/proc.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/process.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/random.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/range.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/rational.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/re.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/ruby.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/select.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/set.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/signal.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/string.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/struct.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/thread.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/time.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/variable.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/vm.h
+postponed_job.o: $(hdrdir)/ruby/internal/interpreter.h
+postponed_job.o: $(hdrdir)/ruby/internal/iterator.h
+postponed_job.o: $(hdrdir)/ruby/internal/memory.h
+postponed_job.o: $(hdrdir)/ruby/internal/method.h
+postponed_job.o: $(hdrdir)/ruby/internal/module.h
+postponed_job.o: $(hdrdir)/ruby/internal/newobj.h
+postponed_job.o: $(hdrdir)/ruby/internal/scan_args.h
+postponed_job.o: $(hdrdir)/ruby/internal/special_consts.h
+postponed_job.o: $(hdrdir)/ruby/internal/static_assert.h
+postponed_job.o: $(hdrdir)/ruby/internal/stdalign.h
+postponed_job.o: $(hdrdir)/ruby/internal/stdbool.h
+postponed_job.o: $(hdrdir)/ruby/internal/stdckdint.h
+postponed_job.o: $(hdrdir)/ruby/internal/symbol.h
+postponed_job.o: $(hdrdir)/ruby/internal/value.h
+postponed_job.o: $(hdrdir)/ruby/internal/value_type.h
+postponed_job.o: $(hdrdir)/ruby/internal/variable.h
+postponed_job.o: $(hdrdir)/ruby/internal/warning_push.h
+postponed_job.o: $(hdrdir)/ruby/internal/xmalloc.h
+postponed_job.o: $(hdrdir)/ruby/missing.h
+postponed_job.o: $(hdrdir)/ruby/ruby.h
+postponed_job.o: $(hdrdir)/ruby/st.h
+postponed_job.o: $(hdrdir)/ruby/subst.h
+postponed_job.o: postponed_job.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/postponed_job/extconf.rb b/ext/-test-/postponed_job/extconf.rb
new file mode 100644
index 0000000000..58fbd3b461
--- /dev/null
+++ b/ext/-test-/postponed_job/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile('-test-/postponed_job')
diff --git a/ext/-test-/postponed_job/postponed_job.c b/ext/-test-/postponed_job/postponed_job.c
new file mode 100644
index 0000000000..4426fc3104
--- /dev/null
+++ b/ext/-test-/postponed_job/postponed_job.c
@@ -0,0 +1,151 @@
+#include "ruby.h"
+#include "ruby/debug.h"
+
+// We're testing deprecated things, don't print the compiler warnings
+#if 0
+
+#elif defined(_MSC_VER)
+#pragma warning(disable : 4996)
+
+#elif defined(__INTEL_COMPILER)
+#pragma warning(disable : 1786)
+
+#elif defined(__clang__)
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#elif defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+#elif defined(__SUNPRO_CC)
+#pragma error_messages (off,symdeprecated)
+
+#else
+// :FIXME: improve here for your compiler.
+
+#endif
+
+static int counter;
+
+static void
+pjob_callback(void *data)
+{
+ VALUE ary = (VALUE)data;
+ Check_Type(ary, T_ARRAY);
+
+ rb_ary_push(ary, INT2FIX(counter));
+}
+
+static VALUE
+pjob_call_direct(VALUE self, VALUE obj)
+{
+ counter = 0;
+ pjob_callback((void *)obj);
+ rb_gc_start();
+ counter++;
+ rb_gc_start();
+ counter++;
+ rb_gc_start();
+ counter++;
+ return self;
+}
+
+static void pjob_noop_callback(void *data) { }
+
+static void
+pjob_preregistered_callback(void *data)
+{
+ VALUE ary = (VALUE)data;
+ Check_Type(ary, T_ARRAY);
+ rb_ary_push(ary, INT2FIX(counter));
+}
+
+static VALUE
+pjob_preregister_and_call_with_sleep(VALUE self, VALUE obj)
+{
+ counter = 0;
+ rb_postponed_job_handle_t h = rb_postponed_job_preregister(0, pjob_preregistered_callback, (void *)obj);
+ counter++;
+ rb_postponed_job_trigger(h);
+ rb_thread_sleep(0);
+ counter++;
+ rb_postponed_job_trigger(h);
+ rb_thread_sleep(0);
+ counter++;
+ rb_postponed_job_trigger(h);
+ rb_thread_sleep(0);
+ return self;
+}
+
+static VALUE
+pjob_preregister_and_call_without_sleep(VALUE self, VALUE obj)
+{
+ counter = 0;
+ rb_postponed_job_handle_t h = rb_postponed_job_preregister(0, pjob_preregistered_callback, (void *)obj);
+ counter = 3;
+ rb_postponed_job_trigger(h);
+ rb_postponed_job_trigger(h);
+ rb_postponed_job_trigger(h);
+ return self;
+}
+
+static VALUE
+pjob_preregister_multiple_times(VALUE self)
+{
+ int r1 = rb_postponed_job_preregister(0, pjob_noop_callback, NULL);
+ int r2 = rb_postponed_job_preregister(0, pjob_noop_callback, NULL);
+ int r3 = rb_postponed_job_preregister(0, pjob_noop_callback, NULL);
+ VALUE ary = rb_ary_new();
+ rb_ary_push(ary, INT2FIX(r1));
+ rb_ary_push(ary, INT2FIX(r2));
+ rb_ary_push(ary, INT2FIX(r3));
+ return ary;
+
+}
+
+struct pjob_append_data_args {
+ VALUE ary;
+ VALUE data;
+};
+
+static void
+pjob_append_data_callback(void *vctx) {
+ struct pjob_append_data_args *ctx = (struct pjob_append_data_args *)vctx;
+ Check_Type(ctx->ary, T_ARRAY);
+ rb_ary_push(ctx->ary, ctx->data);
+}
+
+static VALUE
+pjob_preregister_calls_with_last_argument(VALUE self)
+{
+ VALUE ary = rb_ary_new();
+
+ struct pjob_append_data_args arg1 = { .ary = ary, .data = INT2FIX(1) };
+ struct pjob_append_data_args arg2 = { .ary = ary, .data = INT2FIX(2) };
+ struct pjob_append_data_args arg3 = { .ary = ary, .data = INT2FIX(3) };
+ struct pjob_append_data_args arg4 = { .ary = ary, .data = INT2FIX(4) };
+
+ rb_postponed_job_handle_t h;
+ h = rb_postponed_job_preregister(0, pjob_append_data_callback, &arg1);
+ rb_postponed_job_preregister(0, pjob_append_data_callback, &arg2);
+ rb_postponed_job_trigger(h);
+ rb_postponed_job_preregister(0, pjob_append_data_callback, &arg3);
+ rb_thread_sleep(0); // should execute with arg3
+
+ rb_postponed_job_preregister(0, pjob_append_data_callback, &arg4);
+ rb_postponed_job_trigger(h);
+ rb_thread_sleep(0); // should execute with arg4
+
+ return ary;
+}
+
+void
+Init_postponed_job(VALUE self)
+{
+ VALUE mBug = rb_define_module("Bug");
+ rb_define_module_function(mBug, "postponed_job_call_direct", pjob_call_direct, 1);
+ rb_define_module_function(mBug, "postponed_job_preregister_and_call_with_sleep", pjob_preregister_and_call_with_sleep, 1);
+ rb_define_module_function(mBug, "postponed_job_preregister_and_call_without_sleep", pjob_preregister_and_call_without_sleep, 1);
+ rb_define_module_function(mBug, "postponed_job_preregister_multiple_times", pjob_preregister_multiple_times, 0);
+ rb_define_module_function(mBug, "postponed_job_preregister_calls_with_last_argument", pjob_preregister_calls_with_last_argument, 0);
+}
+
diff --git a/ext/-test-/printf/depend b/ext/-test-/printf/depend
new file mode 100644
index 0000000000..be895cf769
--- /dev/null
+++ b/ext/-test-/printf/depend
@@ -0,0 +1,175 @@
+# AUTOGENERATED DEPENDENCIES START
+printf.o: $(RUBY_EXTCONF_H)
+printf.o: $(arch_hdrdir)/ruby/config.h
+printf.o: $(hdrdir)/ruby.h
+printf.o: $(hdrdir)/ruby/assert.h
+printf.o: $(hdrdir)/ruby/backward.h
+printf.o: $(hdrdir)/ruby/backward/2/assume.h
+printf.o: $(hdrdir)/ruby/backward/2/attributes.h
+printf.o: $(hdrdir)/ruby/backward/2/bool.h
+printf.o: $(hdrdir)/ruby/backward/2/inttypes.h
+printf.o: $(hdrdir)/ruby/backward/2/limits.h
+printf.o: $(hdrdir)/ruby/backward/2/long_long.h
+printf.o: $(hdrdir)/ruby/backward/2/stdalign.h
+printf.o: $(hdrdir)/ruby/backward/2/stdarg.h
+printf.o: $(hdrdir)/ruby/defines.h
+printf.o: $(hdrdir)/ruby/encoding.h
+printf.o: $(hdrdir)/ruby/intern.h
+printf.o: $(hdrdir)/ruby/internal/abi.h
+printf.o: $(hdrdir)/ruby/internal/anyargs.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+printf.o: $(hdrdir)/ruby/internal/assume.h
+printf.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+printf.o: $(hdrdir)/ruby/internal/attr/artificial.h
+printf.o: $(hdrdir)/ruby/internal/attr/cold.h
+printf.o: $(hdrdir)/ruby/internal/attr/const.h
+printf.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+printf.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+printf.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+printf.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+printf.o: $(hdrdir)/ruby/internal/attr/error.h
+printf.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+printf.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+printf.o: $(hdrdir)/ruby/internal/attr/format.h
+printf.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+printf.o: $(hdrdir)/ruby/internal/attr/noalias.h
+printf.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+printf.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+printf.o: $(hdrdir)/ruby/internal/attr/noinline.h
+printf.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+printf.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+printf.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+printf.o: $(hdrdir)/ruby/internal/attr/pure.h
+printf.o: $(hdrdir)/ruby/internal/attr/restrict.h
+printf.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+printf.o: $(hdrdir)/ruby/internal/attr/warning.h
+printf.o: $(hdrdir)/ruby/internal/attr/weakref.h
+printf.o: $(hdrdir)/ruby/internal/cast.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+printf.o: $(hdrdir)/ruby/internal/compiler_since.h
+printf.o: $(hdrdir)/ruby/internal/config.h
+printf.o: $(hdrdir)/ruby/internal/constant_p.h
+printf.o: $(hdrdir)/ruby/internal/core.h
+printf.o: $(hdrdir)/ruby/internal/core/rarray.h
+printf.o: $(hdrdir)/ruby/internal/core/rbasic.h
+printf.o: $(hdrdir)/ruby/internal/core/rbignum.h
+printf.o: $(hdrdir)/ruby/internal/core/rclass.h
+printf.o: $(hdrdir)/ruby/internal/core/rdata.h
+printf.o: $(hdrdir)/ruby/internal/core/rfile.h
+printf.o: $(hdrdir)/ruby/internal/core/rhash.h
+printf.o: $(hdrdir)/ruby/internal/core/robject.h
+printf.o: $(hdrdir)/ruby/internal/core/rregexp.h
+printf.o: $(hdrdir)/ruby/internal/core/rstring.h
+printf.o: $(hdrdir)/ruby/internal/core/rstruct.h
+printf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+printf.o: $(hdrdir)/ruby/internal/ctype.h
+printf.o: $(hdrdir)/ruby/internal/dllexport.h
+printf.o: $(hdrdir)/ruby/internal/dosish.h
+printf.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+printf.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+printf.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+printf.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+printf.o: $(hdrdir)/ruby/internal/encoding/re.h
+printf.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+printf.o: $(hdrdir)/ruby/internal/encoding/string.h
+printf.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+printf.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+printf.o: $(hdrdir)/ruby/internal/error.h
+printf.o: $(hdrdir)/ruby/internal/eval.h
+printf.o: $(hdrdir)/ruby/internal/event.h
+printf.o: $(hdrdir)/ruby/internal/fl_type.h
+printf.o: $(hdrdir)/ruby/internal/gc.h
+printf.o: $(hdrdir)/ruby/internal/glob.h
+printf.o: $(hdrdir)/ruby/internal/globals.h
+printf.o: $(hdrdir)/ruby/internal/has/attribute.h
+printf.o: $(hdrdir)/ruby/internal/has/builtin.h
+printf.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+printf.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+printf.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+printf.o: $(hdrdir)/ruby/internal/has/extension.h
+printf.o: $(hdrdir)/ruby/internal/has/feature.h
+printf.o: $(hdrdir)/ruby/internal/has/warning.h
+printf.o: $(hdrdir)/ruby/internal/intern/array.h
+printf.o: $(hdrdir)/ruby/internal/intern/bignum.h
+printf.o: $(hdrdir)/ruby/internal/intern/class.h
+printf.o: $(hdrdir)/ruby/internal/intern/compar.h
+printf.o: $(hdrdir)/ruby/internal/intern/complex.h
+printf.o: $(hdrdir)/ruby/internal/intern/cont.h
+printf.o: $(hdrdir)/ruby/internal/intern/dir.h
+printf.o: $(hdrdir)/ruby/internal/intern/enum.h
+printf.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+printf.o: $(hdrdir)/ruby/internal/intern/error.h
+printf.o: $(hdrdir)/ruby/internal/intern/eval.h
+printf.o: $(hdrdir)/ruby/internal/intern/file.h
+printf.o: $(hdrdir)/ruby/internal/intern/hash.h
+printf.o: $(hdrdir)/ruby/internal/intern/io.h
+printf.o: $(hdrdir)/ruby/internal/intern/load.h
+printf.o: $(hdrdir)/ruby/internal/intern/marshal.h
+printf.o: $(hdrdir)/ruby/internal/intern/numeric.h
+printf.o: $(hdrdir)/ruby/internal/intern/object.h
+printf.o: $(hdrdir)/ruby/internal/intern/parse.h
+printf.o: $(hdrdir)/ruby/internal/intern/proc.h
+printf.o: $(hdrdir)/ruby/internal/intern/process.h
+printf.o: $(hdrdir)/ruby/internal/intern/random.h
+printf.o: $(hdrdir)/ruby/internal/intern/range.h
+printf.o: $(hdrdir)/ruby/internal/intern/rational.h
+printf.o: $(hdrdir)/ruby/internal/intern/re.h
+printf.o: $(hdrdir)/ruby/internal/intern/ruby.h
+printf.o: $(hdrdir)/ruby/internal/intern/select.h
+printf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+printf.o: $(hdrdir)/ruby/internal/intern/set.h
+printf.o: $(hdrdir)/ruby/internal/intern/signal.h
+printf.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+printf.o: $(hdrdir)/ruby/internal/intern/string.h
+printf.o: $(hdrdir)/ruby/internal/intern/struct.h
+printf.o: $(hdrdir)/ruby/internal/intern/thread.h
+printf.o: $(hdrdir)/ruby/internal/intern/time.h
+printf.o: $(hdrdir)/ruby/internal/intern/variable.h
+printf.o: $(hdrdir)/ruby/internal/intern/vm.h
+printf.o: $(hdrdir)/ruby/internal/interpreter.h
+printf.o: $(hdrdir)/ruby/internal/iterator.h
+printf.o: $(hdrdir)/ruby/internal/memory.h
+printf.o: $(hdrdir)/ruby/internal/method.h
+printf.o: $(hdrdir)/ruby/internal/module.h
+printf.o: $(hdrdir)/ruby/internal/newobj.h
+printf.o: $(hdrdir)/ruby/internal/scan_args.h
+printf.o: $(hdrdir)/ruby/internal/special_consts.h
+printf.o: $(hdrdir)/ruby/internal/static_assert.h
+printf.o: $(hdrdir)/ruby/internal/stdalign.h
+printf.o: $(hdrdir)/ruby/internal/stdbool.h
+printf.o: $(hdrdir)/ruby/internal/stdckdint.h
+printf.o: $(hdrdir)/ruby/internal/symbol.h
+printf.o: $(hdrdir)/ruby/internal/value.h
+printf.o: $(hdrdir)/ruby/internal/value_type.h
+printf.o: $(hdrdir)/ruby/internal/variable.h
+printf.o: $(hdrdir)/ruby/internal/warning_push.h
+printf.o: $(hdrdir)/ruby/internal/xmalloc.h
+printf.o: $(hdrdir)/ruby/missing.h
+printf.o: $(hdrdir)/ruby/onigmo.h
+printf.o: $(hdrdir)/ruby/oniguruma.h
+printf.o: $(hdrdir)/ruby/ruby.h
+printf.o: $(hdrdir)/ruby/st.h
+printf.o: $(hdrdir)/ruby/subst.h
+printf.o: printf.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/printf/extconf.rb b/ext/-test-/printf/extconf.rb
new file mode 100644
index 0000000000..fb8fa8de36
--- /dev/null
+++ b/ext/-test-/printf/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/printf")
diff --git a/ext/-test-/printf/printf.c b/ext/-test-/printf/printf.c
new file mode 100644
index 0000000000..889c0d9f0d
--- /dev/null
+++ b/ext/-test-/printf/printf.c
@@ -0,0 +1,109 @@
+#include <ruby.h>
+#include <ruby/encoding.h>
+
+static VALUE
+printf_test_s(VALUE self, VALUE obj)
+{
+ return rb_enc_sprintf(rb_usascii_encoding(), "<%"PRIsVALUE">", obj);
+}
+
+static VALUE
+printf_test_v(VALUE self, VALUE obj)
+{
+ return rb_enc_sprintf(rb_usascii_encoding(), "{%+"PRIsVALUE"}", obj);
+}
+
+static VALUE
+printf_test_q(VALUE self, VALUE obj)
+{
+ return rb_enc_sprintf(rb_usascii_encoding(), "[% "PRIsVALUE"]", obj);
+}
+
+static char *
+uint_to_str(char *p, char *e, unsigned int x)
+{
+ char *e0 = e;
+ if (e <= p) return p;
+ do {
+ *--e = x % 10 + '0';
+ } while ((x /= 10) != 0 && e > p);
+ memmove(p, e, e0 - e);
+ return p + (e0 - e);
+}
+
+static VALUE
+printf_test_call(int argc, VALUE *argv, VALUE self)
+{
+ VALUE opt, type, num, result;
+ char format[sizeof(int) * 6 + 8], *p = format, cnv;
+ int n = 0;
+ const char *s = 0;
+
+ rb_scan_args(argc, argv, "2:", &type, &num, &opt);
+ Check_Type(type, T_STRING);
+ if (RSTRING_LEN(type) != 1) rb_raise(rb_eArgError, "wrong length(%ld)", RSTRING_LEN(type));
+ switch (cnv = RSTRING_PTR(type)[0]) {
+ case 'd': case 'x': case 'o': case 'X':
+ n = NUM2INT(num);
+ break;
+ case 's':
+ s = StringValueCStr(num);
+ break;
+ default: rb_raise(rb_eArgError, "wrong conversion(%c)", cnv);
+ }
+ *p++ = '%';
+ if (!NIL_P(opt)) {
+ VALUE v;
+ Check_Type(opt, T_HASH);
+ if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("space"))))) {
+ *p++ = ' ';
+ }
+ if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("hash"))))) {
+ *p++ = '#';
+ }
+ if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("plus"))))) {
+ *p++ = '+';
+ }
+ if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("minus"))))) {
+ *p++ = '-';
+ }
+ if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("zero"))))) {
+ *p++ = '0';
+ }
+ if (!NIL_P(v = rb_hash_aref(opt, ID2SYM(rb_intern("width"))))) {
+ p = uint_to_str(p, format + sizeof(format), NUM2UINT(v));
+ }
+ if (!NIL_P(v = rb_hash_aref(opt, ID2SYM(rb_intern("prec"))))) {
+ *p++ = '.';
+ if (FIXNUM_P(v))
+ p = uint_to_str(p, format + sizeof(format), NUM2UINT(v));
+ }
+ }
+ *p++ = cnv;
+ *p++ = '\0';
+ if (cnv == 's') {
+ result = rb_enc_sprintf(rb_usascii_encoding(), format, s);
+ }
+ else {
+ result = rb_enc_sprintf(rb_usascii_encoding(), format, n);
+ }
+ return rb_assoc_new(result, rb_usascii_str_new_cstr(format));
+}
+
+static VALUE
+snprintf_count(VALUE self, VALUE str)
+{
+ int n = ruby_snprintf(NULL, 0, "%s", StringValueCStr(str));
+ return INT2FIX(n);
+}
+
+void
+Init_printf(void)
+{
+ VALUE m = rb_define_module_under(rb_define_module("Bug"), "Printf");
+ rb_define_singleton_method(m, "s", printf_test_s, 1);
+ rb_define_singleton_method(m, "v", printf_test_v, 1);
+ rb_define_singleton_method(m, "q", printf_test_q, 1);
+ rb_define_singleton_method(m, "call", printf_test_call, -1);
+ rb_define_singleton_method(m, "sncount", snprintf_count, 1);
+}
diff --git a/ext/-test-/proc/depend b/ext/-test-/proc/depend
new file mode 100644
index 0000000000..97834db0a2
--- /dev/null
+++ b/ext/-test-/proc/depend
@@ -0,0 +1,485 @@
+# AUTOGENERATED DEPENDENCIES START
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+receiver.o: $(RUBY_EXTCONF_H)
+receiver.o: $(arch_hdrdir)/ruby/config.h
+receiver.o: $(hdrdir)/ruby.h
+receiver.o: $(hdrdir)/ruby/assert.h
+receiver.o: $(hdrdir)/ruby/backward.h
+receiver.o: $(hdrdir)/ruby/backward/2/assume.h
+receiver.o: $(hdrdir)/ruby/backward/2/attributes.h
+receiver.o: $(hdrdir)/ruby/backward/2/bool.h
+receiver.o: $(hdrdir)/ruby/backward/2/inttypes.h
+receiver.o: $(hdrdir)/ruby/backward/2/limits.h
+receiver.o: $(hdrdir)/ruby/backward/2/long_long.h
+receiver.o: $(hdrdir)/ruby/backward/2/stdalign.h
+receiver.o: $(hdrdir)/ruby/backward/2/stdarg.h
+receiver.o: $(hdrdir)/ruby/defines.h
+receiver.o: $(hdrdir)/ruby/intern.h
+receiver.o: $(hdrdir)/ruby/internal/abi.h
+receiver.o: $(hdrdir)/ruby/internal/anyargs.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+receiver.o: $(hdrdir)/ruby/internal/assume.h
+receiver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+receiver.o: $(hdrdir)/ruby/internal/attr/artificial.h
+receiver.o: $(hdrdir)/ruby/internal/attr/cold.h
+receiver.o: $(hdrdir)/ruby/internal/attr/const.h
+receiver.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+receiver.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+receiver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+receiver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+receiver.o: $(hdrdir)/ruby/internal/attr/error.h
+receiver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+receiver.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+receiver.o: $(hdrdir)/ruby/internal/attr/format.h
+receiver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+receiver.o: $(hdrdir)/ruby/internal/attr/noalias.h
+receiver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+receiver.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+receiver.o: $(hdrdir)/ruby/internal/attr/noinline.h
+receiver.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+receiver.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+receiver.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+receiver.o: $(hdrdir)/ruby/internal/attr/pure.h
+receiver.o: $(hdrdir)/ruby/internal/attr/restrict.h
+receiver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+receiver.o: $(hdrdir)/ruby/internal/attr/warning.h
+receiver.o: $(hdrdir)/ruby/internal/attr/weakref.h
+receiver.o: $(hdrdir)/ruby/internal/cast.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_since.h
+receiver.o: $(hdrdir)/ruby/internal/config.h
+receiver.o: $(hdrdir)/ruby/internal/constant_p.h
+receiver.o: $(hdrdir)/ruby/internal/core.h
+receiver.o: $(hdrdir)/ruby/internal/core/rarray.h
+receiver.o: $(hdrdir)/ruby/internal/core/rbasic.h
+receiver.o: $(hdrdir)/ruby/internal/core/rbignum.h
+receiver.o: $(hdrdir)/ruby/internal/core/rclass.h
+receiver.o: $(hdrdir)/ruby/internal/core/rdata.h
+receiver.o: $(hdrdir)/ruby/internal/core/rfile.h
+receiver.o: $(hdrdir)/ruby/internal/core/rhash.h
+receiver.o: $(hdrdir)/ruby/internal/core/robject.h
+receiver.o: $(hdrdir)/ruby/internal/core/rregexp.h
+receiver.o: $(hdrdir)/ruby/internal/core/rstring.h
+receiver.o: $(hdrdir)/ruby/internal/core/rstruct.h
+receiver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+receiver.o: $(hdrdir)/ruby/internal/ctype.h
+receiver.o: $(hdrdir)/ruby/internal/dllexport.h
+receiver.o: $(hdrdir)/ruby/internal/dosish.h
+receiver.o: $(hdrdir)/ruby/internal/error.h
+receiver.o: $(hdrdir)/ruby/internal/eval.h
+receiver.o: $(hdrdir)/ruby/internal/event.h
+receiver.o: $(hdrdir)/ruby/internal/fl_type.h
+receiver.o: $(hdrdir)/ruby/internal/gc.h
+receiver.o: $(hdrdir)/ruby/internal/glob.h
+receiver.o: $(hdrdir)/ruby/internal/globals.h
+receiver.o: $(hdrdir)/ruby/internal/has/attribute.h
+receiver.o: $(hdrdir)/ruby/internal/has/builtin.h
+receiver.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+receiver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+receiver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+receiver.o: $(hdrdir)/ruby/internal/has/extension.h
+receiver.o: $(hdrdir)/ruby/internal/has/feature.h
+receiver.o: $(hdrdir)/ruby/internal/has/warning.h
+receiver.o: $(hdrdir)/ruby/internal/intern/array.h
+receiver.o: $(hdrdir)/ruby/internal/intern/bignum.h
+receiver.o: $(hdrdir)/ruby/internal/intern/class.h
+receiver.o: $(hdrdir)/ruby/internal/intern/compar.h
+receiver.o: $(hdrdir)/ruby/internal/intern/complex.h
+receiver.o: $(hdrdir)/ruby/internal/intern/cont.h
+receiver.o: $(hdrdir)/ruby/internal/intern/dir.h
+receiver.o: $(hdrdir)/ruby/internal/intern/enum.h
+receiver.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+receiver.o: $(hdrdir)/ruby/internal/intern/error.h
+receiver.o: $(hdrdir)/ruby/internal/intern/eval.h
+receiver.o: $(hdrdir)/ruby/internal/intern/file.h
+receiver.o: $(hdrdir)/ruby/internal/intern/hash.h
+receiver.o: $(hdrdir)/ruby/internal/intern/io.h
+receiver.o: $(hdrdir)/ruby/internal/intern/load.h
+receiver.o: $(hdrdir)/ruby/internal/intern/marshal.h
+receiver.o: $(hdrdir)/ruby/internal/intern/numeric.h
+receiver.o: $(hdrdir)/ruby/internal/intern/object.h
+receiver.o: $(hdrdir)/ruby/internal/intern/parse.h
+receiver.o: $(hdrdir)/ruby/internal/intern/proc.h
+receiver.o: $(hdrdir)/ruby/internal/intern/process.h
+receiver.o: $(hdrdir)/ruby/internal/intern/random.h
+receiver.o: $(hdrdir)/ruby/internal/intern/range.h
+receiver.o: $(hdrdir)/ruby/internal/intern/rational.h
+receiver.o: $(hdrdir)/ruby/internal/intern/re.h
+receiver.o: $(hdrdir)/ruby/internal/intern/ruby.h
+receiver.o: $(hdrdir)/ruby/internal/intern/select.h
+receiver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+receiver.o: $(hdrdir)/ruby/internal/intern/set.h
+receiver.o: $(hdrdir)/ruby/internal/intern/signal.h
+receiver.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+receiver.o: $(hdrdir)/ruby/internal/intern/string.h
+receiver.o: $(hdrdir)/ruby/internal/intern/struct.h
+receiver.o: $(hdrdir)/ruby/internal/intern/thread.h
+receiver.o: $(hdrdir)/ruby/internal/intern/time.h
+receiver.o: $(hdrdir)/ruby/internal/intern/variable.h
+receiver.o: $(hdrdir)/ruby/internal/intern/vm.h
+receiver.o: $(hdrdir)/ruby/internal/interpreter.h
+receiver.o: $(hdrdir)/ruby/internal/iterator.h
+receiver.o: $(hdrdir)/ruby/internal/memory.h
+receiver.o: $(hdrdir)/ruby/internal/method.h
+receiver.o: $(hdrdir)/ruby/internal/module.h
+receiver.o: $(hdrdir)/ruby/internal/newobj.h
+receiver.o: $(hdrdir)/ruby/internal/scan_args.h
+receiver.o: $(hdrdir)/ruby/internal/special_consts.h
+receiver.o: $(hdrdir)/ruby/internal/static_assert.h
+receiver.o: $(hdrdir)/ruby/internal/stdalign.h
+receiver.o: $(hdrdir)/ruby/internal/stdbool.h
+receiver.o: $(hdrdir)/ruby/internal/stdckdint.h
+receiver.o: $(hdrdir)/ruby/internal/symbol.h
+receiver.o: $(hdrdir)/ruby/internal/value.h
+receiver.o: $(hdrdir)/ruby/internal/value_type.h
+receiver.o: $(hdrdir)/ruby/internal/variable.h
+receiver.o: $(hdrdir)/ruby/internal/warning_push.h
+receiver.o: $(hdrdir)/ruby/internal/xmalloc.h
+receiver.o: $(hdrdir)/ruby/missing.h
+receiver.o: $(hdrdir)/ruby/ruby.h
+receiver.o: $(hdrdir)/ruby/st.h
+receiver.o: $(hdrdir)/ruby/subst.h
+receiver.o: receiver.c
+super.o: $(RUBY_EXTCONF_H)
+super.o: $(arch_hdrdir)/ruby/config.h
+super.o: $(hdrdir)/ruby.h
+super.o: $(hdrdir)/ruby/assert.h
+super.o: $(hdrdir)/ruby/backward.h
+super.o: $(hdrdir)/ruby/backward/2/assume.h
+super.o: $(hdrdir)/ruby/backward/2/attributes.h
+super.o: $(hdrdir)/ruby/backward/2/bool.h
+super.o: $(hdrdir)/ruby/backward/2/inttypes.h
+super.o: $(hdrdir)/ruby/backward/2/limits.h
+super.o: $(hdrdir)/ruby/backward/2/long_long.h
+super.o: $(hdrdir)/ruby/backward/2/stdalign.h
+super.o: $(hdrdir)/ruby/backward/2/stdarg.h
+super.o: $(hdrdir)/ruby/defines.h
+super.o: $(hdrdir)/ruby/intern.h
+super.o: $(hdrdir)/ruby/internal/abi.h
+super.o: $(hdrdir)/ruby/internal/anyargs.h
+super.o: $(hdrdir)/ruby/internal/arithmetic.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+super.o: $(hdrdir)/ruby/internal/assume.h
+super.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+super.o: $(hdrdir)/ruby/internal/attr/artificial.h
+super.o: $(hdrdir)/ruby/internal/attr/cold.h
+super.o: $(hdrdir)/ruby/internal/attr/const.h
+super.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+super.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+super.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+super.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+super.o: $(hdrdir)/ruby/internal/attr/error.h
+super.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+super.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+super.o: $(hdrdir)/ruby/internal/attr/format.h
+super.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+super.o: $(hdrdir)/ruby/internal/attr/noalias.h
+super.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+super.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+super.o: $(hdrdir)/ruby/internal/attr/noinline.h
+super.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+super.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+super.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+super.o: $(hdrdir)/ruby/internal/attr/pure.h
+super.o: $(hdrdir)/ruby/internal/attr/restrict.h
+super.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+super.o: $(hdrdir)/ruby/internal/attr/warning.h
+super.o: $(hdrdir)/ruby/internal/attr/weakref.h
+super.o: $(hdrdir)/ruby/internal/cast.h
+super.o: $(hdrdir)/ruby/internal/compiler_is.h
+super.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+super.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+super.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+super.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+super.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+super.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+super.o: $(hdrdir)/ruby/internal/compiler_since.h
+super.o: $(hdrdir)/ruby/internal/config.h
+super.o: $(hdrdir)/ruby/internal/constant_p.h
+super.o: $(hdrdir)/ruby/internal/core.h
+super.o: $(hdrdir)/ruby/internal/core/rarray.h
+super.o: $(hdrdir)/ruby/internal/core/rbasic.h
+super.o: $(hdrdir)/ruby/internal/core/rbignum.h
+super.o: $(hdrdir)/ruby/internal/core/rclass.h
+super.o: $(hdrdir)/ruby/internal/core/rdata.h
+super.o: $(hdrdir)/ruby/internal/core/rfile.h
+super.o: $(hdrdir)/ruby/internal/core/rhash.h
+super.o: $(hdrdir)/ruby/internal/core/robject.h
+super.o: $(hdrdir)/ruby/internal/core/rregexp.h
+super.o: $(hdrdir)/ruby/internal/core/rstring.h
+super.o: $(hdrdir)/ruby/internal/core/rstruct.h
+super.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+super.o: $(hdrdir)/ruby/internal/ctype.h
+super.o: $(hdrdir)/ruby/internal/dllexport.h
+super.o: $(hdrdir)/ruby/internal/dosish.h
+super.o: $(hdrdir)/ruby/internal/error.h
+super.o: $(hdrdir)/ruby/internal/eval.h
+super.o: $(hdrdir)/ruby/internal/event.h
+super.o: $(hdrdir)/ruby/internal/fl_type.h
+super.o: $(hdrdir)/ruby/internal/gc.h
+super.o: $(hdrdir)/ruby/internal/glob.h
+super.o: $(hdrdir)/ruby/internal/globals.h
+super.o: $(hdrdir)/ruby/internal/has/attribute.h
+super.o: $(hdrdir)/ruby/internal/has/builtin.h
+super.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+super.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+super.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+super.o: $(hdrdir)/ruby/internal/has/extension.h
+super.o: $(hdrdir)/ruby/internal/has/feature.h
+super.o: $(hdrdir)/ruby/internal/has/warning.h
+super.o: $(hdrdir)/ruby/internal/intern/array.h
+super.o: $(hdrdir)/ruby/internal/intern/bignum.h
+super.o: $(hdrdir)/ruby/internal/intern/class.h
+super.o: $(hdrdir)/ruby/internal/intern/compar.h
+super.o: $(hdrdir)/ruby/internal/intern/complex.h
+super.o: $(hdrdir)/ruby/internal/intern/cont.h
+super.o: $(hdrdir)/ruby/internal/intern/dir.h
+super.o: $(hdrdir)/ruby/internal/intern/enum.h
+super.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+super.o: $(hdrdir)/ruby/internal/intern/error.h
+super.o: $(hdrdir)/ruby/internal/intern/eval.h
+super.o: $(hdrdir)/ruby/internal/intern/file.h
+super.o: $(hdrdir)/ruby/internal/intern/hash.h
+super.o: $(hdrdir)/ruby/internal/intern/io.h
+super.o: $(hdrdir)/ruby/internal/intern/load.h
+super.o: $(hdrdir)/ruby/internal/intern/marshal.h
+super.o: $(hdrdir)/ruby/internal/intern/numeric.h
+super.o: $(hdrdir)/ruby/internal/intern/object.h
+super.o: $(hdrdir)/ruby/internal/intern/parse.h
+super.o: $(hdrdir)/ruby/internal/intern/proc.h
+super.o: $(hdrdir)/ruby/internal/intern/process.h
+super.o: $(hdrdir)/ruby/internal/intern/random.h
+super.o: $(hdrdir)/ruby/internal/intern/range.h
+super.o: $(hdrdir)/ruby/internal/intern/rational.h
+super.o: $(hdrdir)/ruby/internal/intern/re.h
+super.o: $(hdrdir)/ruby/internal/intern/ruby.h
+super.o: $(hdrdir)/ruby/internal/intern/select.h
+super.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+super.o: $(hdrdir)/ruby/internal/intern/set.h
+super.o: $(hdrdir)/ruby/internal/intern/signal.h
+super.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+super.o: $(hdrdir)/ruby/internal/intern/string.h
+super.o: $(hdrdir)/ruby/internal/intern/struct.h
+super.o: $(hdrdir)/ruby/internal/intern/thread.h
+super.o: $(hdrdir)/ruby/internal/intern/time.h
+super.o: $(hdrdir)/ruby/internal/intern/variable.h
+super.o: $(hdrdir)/ruby/internal/intern/vm.h
+super.o: $(hdrdir)/ruby/internal/interpreter.h
+super.o: $(hdrdir)/ruby/internal/iterator.h
+super.o: $(hdrdir)/ruby/internal/memory.h
+super.o: $(hdrdir)/ruby/internal/method.h
+super.o: $(hdrdir)/ruby/internal/module.h
+super.o: $(hdrdir)/ruby/internal/newobj.h
+super.o: $(hdrdir)/ruby/internal/scan_args.h
+super.o: $(hdrdir)/ruby/internal/special_consts.h
+super.o: $(hdrdir)/ruby/internal/static_assert.h
+super.o: $(hdrdir)/ruby/internal/stdalign.h
+super.o: $(hdrdir)/ruby/internal/stdbool.h
+super.o: $(hdrdir)/ruby/internal/stdckdint.h
+super.o: $(hdrdir)/ruby/internal/symbol.h
+super.o: $(hdrdir)/ruby/internal/value.h
+super.o: $(hdrdir)/ruby/internal/value_type.h
+super.o: $(hdrdir)/ruby/internal/variable.h
+super.o: $(hdrdir)/ruby/internal/warning_push.h
+super.o: $(hdrdir)/ruby/internal/xmalloc.h
+super.o: $(hdrdir)/ruby/missing.h
+super.o: $(hdrdir)/ruby/ruby.h
+super.o: $(hdrdir)/ruby/st.h
+super.o: $(hdrdir)/ruby/subst.h
+super.o: super.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/proc/extconf.rb b/ext/-test-/proc/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/proc/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/proc/init.c b/ext/-test-/proc/init.c
new file mode 100644
index 0000000000..814c55d98b
--- /dev/null
+++ b/ext/-test-/proc/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_proc(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_module_under(mBug, "Proc");
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/proc/receiver.c b/ext/-test-/proc/receiver.c
new file mode 100644
index 0000000000..fe44a2246c
--- /dev/null
+++ b/ext/-test-/proc/receiver.c
@@ -0,0 +1,21 @@
+#include "ruby.h"
+
+VALUE rb_current_receiver(void);
+
+static VALUE
+bug_proc_call_receiver(RB_BLOCK_CALL_FUNC_ARGLIST(yieldarg, procarg))
+{
+ return rb_current_receiver();
+}
+
+static VALUE
+bug_proc_make_call_receiver(VALUE self, VALUE procarg)
+{
+ return rb_proc_new(bug_proc_call_receiver, procarg);
+}
+
+void
+Init_receiver(VALUE klass)
+{
+ rb_define_singleton_method(klass, "make_call_receiver", bug_proc_make_call_receiver, 1);
+}
diff --git a/ext/-test-/proc/super.c b/ext/-test-/proc/super.c
new file mode 100644
index 0000000000..816520e1df
--- /dev/null
+++ b/ext/-test-/proc/super.c
@@ -0,0 +1,27 @@
+#include "ruby.h"
+
+static VALUE
+bug_proc_call_super(RB_BLOCK_CALL_FUNC_ARGLIST(yieldarg, procarg))
+{
+ VALUE args[2];
+ VALUE ret;
+ args[0] = yieldarg;
+ args[1] = procarg;
+ ret = rb_call_super(2, args);
+ if (!NIL_P(blockarg)) {
+ ret = rb_proc_call(blockarg, ret);
+ }
+ return ret;
+}
+
+static VALUE
+bug_proc_make_call_super(VALUE self, VALUE procarg)
+{
+ return rb_proc_new(bug_proc_call_super, procarg);
+}
+
+void
+Init_super(VALUE klass)
+{
+ rb_define_singleton_method(klass, "make_call_super", bug_proc_make_call_super, 1);
+}
diff --git a/ext/-test-/public_header_warnings/extconf.rb b/ext/-test-/public_header_warnings/extconf.rb
new file mode 100644
index 0000000000..4431e09da4
--- /dev/null
+++ b/ext/-test-/public_header_warnings/extconf.rb
@@ -0,0 +1,28 @@
+#
+# Under compilers with WERRORFLAG, MakeMakefile.try_compile treats warnings as errors, so we can
+# use append_cflags to test whether the public header files emit warnings with certain flags turned
+# on.
+#
+def check_append_cflags(flag, msg = nil)
+ msg ||= "flag #{flag} is not acceptable"
+ if $CFLAGS.include?(flag)
+ raise("flag #{flag} already present in $CFLAGS")
+ end
+ append_cflags(flag)
+ unless $CFLAGS.include?(flag)
+ system("cat mkmf.log")
+ raise(msg)
+ end
+end
+
+if %w[gcc clang].include?(RbConfig::CONFIG['CC'])
+ config_string("WERRORFLAG") or raise("expected WERRORFLAG to be defined")
+
+ # should be acceptable on all modern C compilers
+ check_append_cflags("-D_TEST_OK", "baseline compiler warning test failed")
+
+ # Feature #20507: Allow compilation of C extensions with -Wconversion
+ check_append_cflags("-Wconversion", "-Wconversion raising warnings in public headers")
+end
+
+create_makefile("-test-/public_header_warnings")
diff --git a/ext/-test-/random/bad_version.c b/ext/-test-/random/bad_version.c
new file mode 100644
index 0000000000..dae63a6d19
--- /dev/null
+++ b/ext/-test-/random/bad_version.c
@@ -0,0 +1,135 @@
+#include "ruby/random.h"
+
+#if RUBY_RANDOM_INTERFACE_VERSION_MAJOR < RUBY_RANDOM_INTERFACE_VERSION_MAJOR_MAX
+# define DEFINE_VERSION_MAX 1
+#else
+# define DEFINE_VERSION_MAX 0
+#endif
+
+NORETURN(static void must_not_reach(void));
+static void
+must_not_reach(void)
+{
+ rb_raise(rb_eTypeError, "must not reach");
+}
+
+NORETURN(static void bad_version_init(rb_random_t *, const uint32_t *, size_t));
+static void
+bad_version_init(rb_random_t *rnd, const uint32_t *buf, size_t len)
+{
+ must_not_reach();
+}
+
+NORETURN(static void bad_version_init_int32(rb_random_t *, uint32_t));
+RB_RANDOM_DEFINE_INIT_INT32_FUNC(bad_version)
+
+NORETURN(static void bad_version_get_bytes(rb_random_t *, void *, size_t));
+static void
+bad_version_get_bytes(rb_random_t *rnd, void *p, size_t n)
+{
+ must_not_reach();
+}
+
+NORETURN(static uint32_t bad_version_get_int32(rb_random_t *));
+static uint32_t
+bad_version_get_int32(rb_random_t *rnd)
+{
+ must_not_reach();
+ UNREACHABLE_RETURN(0);
+}
+
+static VALUE
+bad_version_alloc(VALUE klass, const rb_data_type_t *type)
+{
+ rb_random_t *rnd;
+ VALUE obj = TypedData_Make_Struct(klass, rb_random_t, type, rnd);
+ rb_random_base_init(rnd);
+ return obj;
+}
+
+/* version 0 */
+static const rb_random_interface_t random_version_zero_if;
+
+static rb_random_data_type_t version_zero_type = {
+ "random/version_zero",
+ {
+ rb_random_mark,
+ RUBY_TYPED_DEFAULT_FREE,
+ },
+ RB_RANDOM_PARENT,
+ (void *)&random_version_zero_if,
+ RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static VALUE
+version_zero_alloc(VALUE klass)
+{
+ return bad_version_alloc(klass, &version_zero_type);
+}
+
+static void
+init_version_zero(VALUE mod, VALUE base)
+{
+ VALUE c = rb_define_class_under(mod, "VersionZero", base);
+ rb_define_alloc_func(c, version_zero_alloc);
+ RB_RANDOM_DATA_INIT_PARENT(version_zero_type);
+}
+
+#if DEFINE_VERSION_MAX
+/* version max */
+static const rb_random_interface_t random_version_max_if;
+static rb_random_data_type_t version_max_type = {
+ "random/version_max",
+ {
+ rb_random_mark,
+ RUBY_TYPED_DEFAULT_FREE,
+ },
+ RB_RANDOM_PARENT,
+ (void *)&random_version_max_if,
+ RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static VALUE
+version_max_alloc(VALUE klass)
+{
+ return bad_version_alloc(klass, &version_max_type);
+}
+
+static void
+init_version_max(VALUE mod, VALUE base)
+{
+ VALUE c = rb_define_class_under(mod, "VersionMax", base);
+ rb_define_alloc_func(c, version_max_alloc);
+ RB_RANDOM_DATA_INIT_PARENT(version_max_type);
+}
+#else
+static void
+init_version_max(mod, base)
+{
+}
+#endif
+
+void
+Init_random_bad_version(VALUE mod, VALUE base)
+{
+ init_version_zero(mod, base);
+ init_version_max(mod, base);
+}
+
+#undef RUBY_RANDOM_INTERFACE_VERSION_MAJOR
+
+#define RUBY_RANDOM_INTERFACE_VERSION_MAJOR 0
+static const rb_random_interface_t random_version_zero_if = {
+ 0,
+ RB_RANDOM_INTERFACE_DEFINE(bad_version)
+};
+#undef RUBY_RANDOM_INTERFACE_VERSION_MAJOR
+
+#if DEFINE_VERSION_MAX
+#define RUBY_RANDOM_INTERFACE_VERSION_MAJOR RUBY_RANDOM_INTERFACE_VERSION_MAJOR_MAX
+static const rb_random_interface_t random_version_max_if = {
+ 0,
+ RB_RANDOM_INTERFACE_DEFINE(bad_version)
+};
+#undef RUBY_RANDOM_INTERFACE_VERSION_MAJOR
+#endif
diff --git a/ext/-test-/random/depend b/ext/-test-/random/depend
new file mode 100644
index 0000000000..380c30fbe4
--- /dev/null
+++ b/ext/-test-/random/depend
@@ -0,0 +1,485 @@
+# AUTOGENERATED DEPENDENCIES START
+bad_version.o: $(RUBY_EXTCONF_H)
+bad_version.o: $(arch_hdrdir)/ruby/config.h
+bad_version.o: $(hdrdir)/ruby/assert.h
+bad_version.o: $(hdrdir)/ruby/backward.h
+bad_version.o: $(hdrdir)/ruby/backward/2/assume.h
+bad_version.o: $(hdrdir)/ruby/backward/2/attributes.h
+bad_version.o: $(hdrdir)/ruby/backward/2/bool.h
+bad_version.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bad_version.o: $(hdrdir)/ruby/backward/2/limits.h
+bad_version.o: $(hdrdir)/ruby/backward/2/long_long.h
+bad_version.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bad_version.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bad_version.o: $(hdrdir)/ruby/defines.h
+bad_version.o: $(hdrdir)/ruby/intern.h
+bad_version.o: $(hdrdir)/ruby/internal/abi.h
+bad_version.o: $(hdrdir)/ruby/internal/anyargs.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bad_version.o: $(hdrdir)/ruby/internal/assume.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/cold.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/const.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/error.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/format.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/pure.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/warning.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bad_version.o: $(hdrdir)/ruby/internal/cast.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_since.h
+bad_version.o: $(hdrdir)/ruby/internal/config.h
+bad_version.o: $(hdrdir)/ruby/internal/constant_p.h
+bad_version.o: $(hdrdir)/ruby/internal/core.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rarray.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rclass.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rdata.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rfile.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rhash.h
+bad_version.o: $(hdrdir)/ruby/internal/core/robject.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rstring.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bad_version.o: $(hdrdir)/ruby/internal/ctype.h
+bad_version.o: $(hdrdir)/ruby/internal/dllexport.h
+bad_version.o: $(hdrdir)/ruby/internal/dosish.h
+bad_version.o: $(hdrdir)/ruby/internal/error.h
+bad_version.o: $(hdrdir)/ruby/internal/eval.h
+bad_version.o: $(hdrdir)/ruby/internal/event.h
+bad_version.o: $(hdrdir)/ruby/internal/fl_type.h
+bad_version.o: $(hdrdir)/ruby/internal/gc.h
+bad_version.o: $(hdrdir)/ruby/internal/glob.h
+bad_version.o: $(hdrdir)/ruby/internal/globals.h
+bad_version.o: $(hdrdir)/ruby/internal/has/attribute.h
+bad_version.o: $(hdrdir)/ruby/internal/has/builtin.h
+bad_version.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bad_version.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bad_version.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bad_version.o: $(hdrdir)/ruby/internal/has/extension.h
+bad_version.o: $(hdrdir)/ruby/internal/has/feature.h
+bad_version.o: $(hdrdir)/ruby/internal/has/warning.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/array.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/class.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/compar.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/complex.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/cont.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/dir.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/enum.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/error.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/eval.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/file.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/hash.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/io.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/load.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/object.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/parse.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/proc.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/process.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/random.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/range.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/rational.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/re.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/select.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/set.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/signal.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/string.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/struct.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/thread.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/time.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/variable.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/vm.h
+bad_version.o: $(hdrdir)/ruby/internal/interpreter.h
+bad_version.o: $(hdrdir)/ruby/internal/iterator.h
+bad_version.o: $(hdrdir)/ruby/internal/memory.h
+bad_version.o: $(hdrdir)/ruby/internal/method.h
+bad_version.o: $(hdrdir)/ruby/internal/module.h
+bad_version.o: $(hdrdir)/ruby/internal/newobj.h
+bad_version.o: $(hdrdir)/ruby/internal/scan_args.h
+bad_version.o: $(hdrdir)/ruby/internal/special_consts.h
+bad_version.o: $(hdrdir)/ruby/internal/static_assert.h
+bad_version.o: $(hdrdir)/ruby/internal/stdalign.h
+bad_version.o: $(hdrdir)/ruby/internal/stdbool.h
+bad_version.o: $(hdrdir)/ruby/internal/stdckdint.h
+bad_version.o: $(hdrdir)/ruby/internal/symbol.h
+bad_version.o: $(hdrdir)/ruby/internal/value.h
+bad_version.o: $(hdrdir)/ruby/internal/value_type.h
+bad_version.o: $(hdrdir)/ruby/internal/variable.h
+bad_version.o: $(hdrdir)/ruby/internal/warning_push.h
+bad_version.o: $(hdrdir)/ruby/internal/xmalloc.h
+bad_version.o: $(hdrdir)/ruby/missing.h
+bad_version.o: $(hdrdir)/ruby/random.h
+bad_version.o: $(hdrdir)/ruby/ruby.h
+bad_version.o: $(hdrdir)/ruby/st.h
+bad_version.o: $(hdrdir)/ruby/subst.h
+bad_version.o: bad_version.c
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+loop.o: $(RUBY_EXTCONF_H)
+loop.o: $(arch_hdrdir)/ruby/config.h
+loop.o: $(hdrdir)/ruby/assert.h
+loop.o: $(hdrdir)/ruby/backward.h
+loop.o: $(hdrdir)/ruby/backward/2/assume.h
+loop.o: $(hdrdir)/ruby/backward/2/attributes.h
+loop.o: $(hdrdir)/ruby/backward/2/bool.h
+loop.o: $(hdrdir)/ruby/backward/2/inttypes.h
+loop.o: $(hdrdir)/ruby/backward/2/limits.h
+loop.o: $(hdrdir)/ruby/backward/2/long_long.h
+loop.o: $(hdrdir)/ruby/backward/2/stdalign.h
+loop.o: $(hdrdir)/ruby/backward/2/stdarg.h
+loop.o: $(hdrdir)/ruby/defines.h
+loop.o: $(hdrdir)/ruby/intern.h
+loop.o: $(hdrdir)/ruby/internal/abi.h
+loop.o: $(hdrdir)/ruby/internal/anyargs.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+loop.o: $(hdrdir)/ruby/internal/assume.h
+loop.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+loop.o: $(hdrdir)/ruby/internal/attr/artificial.h
+loop.o: $(hdrdir)/ruby/internal/attr/cold.h
+loop.o: $(hdrdir)/ruby/internal/attr/const.h
+loop.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+loop.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+loop.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+loop.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+loop.o: $(hdrdir)/ruby/internal/attr/error.h
+loop.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+loop.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+loop.o: $(hdrdir)/ruby/internal/attr/format.h
+loop.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+loop.o: $(hdrdir)/ruby/internal/attr/noalias.h
+loop.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+loop.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+loop.o: $(hdrdir)/ruby/internal/attr/noinline.h
+loop.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+loop.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+loop.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+loop.o: $(hdrdir)/ruby/internal/attr/pure.h
+loop.o: $(hdrdir)/ruby/internal/attr/restrict.h
+loop.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+loop.o: $(hdrdir)/ruby/internal/attr/warning.h
+loop.o: $(hdrdir)/ruby/internal/attr/weakref.h
+loop.o: $(hdrdir)/ruby/internal/cast.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+loop.o: $(hdrdir)/ruby/internal/compiler_since.h
+loop.o: $(hdrdir)/ruby/internal/config.h
+loop.o: $(hdrdir)/ruby/internal/constant_p.h
+loop.o: $(hdrdir)/ruby/internal/core.h
+loop.o: $(hdrdir)/ruby/internal/core/rarray.h
+loop.o: $(hdrdir)/ruby/internal/core/rbasic.h
+loop.o: $(hdrdir)/ruby/internal/core/rbignum.h
+loop.o: $(hdrdir)/ruby/internal/core/rclass.h
+loop.o: $(hdrdir)/ruby/internal/core/rdata.h
+loop.o: $(hdrdir)/ruby/internal/core/rfile.h
+loop.o: $(hdrdir)/ruby/internal/core/rhash.h
+loop.o: $(hdrdir)/ruby/internal/core/robject.h
+loop.o: $(hdrdir)/ruby/internal/core/rregexp.h
+loop.o: $(hdrdir)/ruby/internal/core/rstring.h
+loop.o: $(hdrdir)/ruby/internal/core/rstruct.h
+loop.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+loop.o: $(hdrdir)/ruby/internal/ctype.h
+loop.o: $(hdrdir)/ruby/internal/dllexport.h
+loop.o: $(hdrdir)/ruby/internal/dosish.h
+loop.o: $(hdrdir)/ruby/internal/error.h
+loop.o: $(hdrdir)/ruby/internal/eval.h
+loop.o: $(hdrdir)/ruby/internal/event.h
+loop.o: $(hdrdir)/ruby/internal/fl_type.h
+loop.o: $(hdrdir)/ruby/internal/gc.h
+loop.o: $(hdrdir)/ruby/internal/glob.h
+loop.o: $(hdrdir)/ruby/internal/globals.h
+loop.o: $(hdrdir)/ruby/internal/has/attribute.h
+loop.o: $(hdrdir)/ruby/internal/has/builtin.h
+loop.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+loop.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+loop.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+loop.o: $(hdrdir)/ruby/internal/has/extension.h
+loop.o: $(hdrdir)/ruby/internal/has/feature.h
+loop.o: $(hdrdir)/ruby/internal/has/warning.h
+loop.o: $(hdrdir)/ruby/internal/intern/array.h
+loop.o: $(hdrdir)/ruby/internal/intern/bignum.h
+loop.o: $(hdrdir)/ruby/internal/intern/class.h
+loop.o: $(hdrdir)/ruby/internal/intern/compar.h
+loop.o: $(hdrdir)/ruby/internal/intern/complex.h
+loop.o: $(hdrdir)/ruby/internal/intern/cont.h
+loop.o: $(hdrdir)/ruby/internal/intern/dir.h
+loop.o: $(hdrdir)/ruby/internal/intern/enum.h
+loop.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+loop.o: $(hdrdir)/ruby/internal/intern/error.h
+loop.o: $(hdrdir)/ruby/internal/intern/eval.h
+loop.o: $(hdrdir)/ruby/internal/intern/file.h
+loop.o: $(hdrdir)/ruby/internal/intern/hash.h
+loop.o: $(hdrdir)/ruby/internal/intern/io.h
+loop.o: $(hdrdir)/ruby/internal/intern/load.h
+loop.o: $(hdrdir)/ruby/internal/intern/marshal.h
+loop.o: $(hdrdir)/ruby/internal/intern/numeric.h
+loop.o: $(hdrdir)/ruby/internal/intern/object.h
+loop.o: $(hdrdir)/ruby/internal/intern/parse.h
+loop.o: $(hdrdir)/ruby/internal/intern/proc.h
+loop.o: $(hdrdir)/ruby/internal/intern/process.h
+loop.o: $(hdrdir)/ruby/internal/intern/random.h
+loop.o: $(hdrdir)/ruby/internal/intern/range.h
+loop.o: $(hdrdir)/ruby/internal/intern/rational.h
+loop.o: $(hdrdir)/ruby/internal/intern/re.h
+loop.o: $(hdrdir)/ruby/internal/intern/ruby.h
+loop.o: $(hdrdir)/ruby/internal/intern/select.h
+loop.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+loop.o: $(hdrdir)/ruby/internal/intern/set.h
+loop.o: $(hdrdir)/ruby/internal/intern/signal.h
+loop.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+loop.o: $(hdrdir)/ruby/internal/intern/string.h
+loop.o: $(hdrdir)/ruby/internal/intern/struct.h
+loop.o: $(hdrdir)/ruby/internal/intern/thread.h
+loop.o: $(hdrdir)/ruby/internal/intern/time.h
+loop.o: $(hdrdir)/ruby/internal/intern/variable.h
+loop.o: $(hdrdir)/ruby/internal/intern/vm.h
+loop.o: $(hdrdir)/ruby/internal/interpreter.h
+loop.o: $(hdrdir)/ruby/internal/iterator.h
+loop.o: $(hdrdir)/ruby/internal/memory.h
+loop.o: $(hdrdir)/ruby/internal/method.h
+loop.o: $(hdrdir)/ruby/internal/module.h
+loop.o: $(hdrdir)/ruby/internal/newobj.h
+loop.o: $(hdrdir)/ruby/internal/scan_args.h
+loop.o: $(hdrdir)/ruby/internal/special_consts.h
+loop.o: $(hdrdir)/ruby/internal/static_assert.h
+loop.o: $(hdrdir)/ruby/internal/stdalign.h
+loop.o: $(hdrdir)/ruby/internal/stdbool.h
+loop.o: $(hdrdir)/ruby/internal/stdckdint.h
+loop.o: $(hdrdir)/ruby/internal/symbol.h
+loop.o: $(hdrdir)/ruby/internal/value.h
+loop.o: $(hdrdir)/ruby/internal/value_type.h
+loop.o: $(hdrdir)/ruby/internal/variable.h
+loop.o: $(hdrdir)/ruby/internal/warning_push.h
+loop.o: $(hdrdir)/ruby/internal/xmalloc.h
+loop.o: $(hdrdir)/ruby/missing.h
+loop.o: $(hdrdir)/ruby/random.h
+loop.o: $(hdrdir)/ruby/ruby.h
+loop.o: $(hdrdir)/ruby/st.h
+loop.o: $(hdrdir)/ruby/subst.h
+loop.o: loop.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/random/extconf.rb b/ext/-test-/random/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/random/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/random/init.c b/ext/-test-/random/init.c
new file mode 100644
index 0000000000..320cba0ad6
--- /dev/null
+++ b/ext/-test-/random/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_random_##n(VALUE mod, VALUE base); Init_random_##n(mod, base);}
+
+void
+Init_random(void)
+{
+ VALUE base = rb_const_get(rb_cRandom, rb_intern_const("Base"));
+ VALUE mod = rb_define_module_under(rb_define_module("Bug"), "Random");
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/random/loop.c b/ext/-test-/random/loop.c
new file mode 100644
index 0000000000..f79e5cfd83
--- /dev/null
+++ b/ext/-test-/random/loop.c
@@ -0,0 +1,120 @@
+#include "ruby/random.h"
+
+static const uint32_t max_seeds = 1024;
+
+typedef struct {
+ rb_random_t base;
+ uint32_t num, idx, *buf;
+} rand_loop_t;
+
+RB_RANDOM_INTERFACE_DECLARE_WITH_REAL(loop);
+static const rb_random_interface_t random_loop_if = {
+ 32,
+ RB_RANDOM_INTERFACE_DEFINE_WITH_REAL(loop)
+};
+
+static void
+loop_free(void *ptr)
+{
+ rand_loop_t *r = ptr;
+
+ xfree(r->buf);
+ xfree(r);
+}
+
+RB_RANDOM_DEFINE_INIT_INT32_FUNC(loop)
+static size_t
+random_loop_memsize(const void *ptr)
+{
+ const rand_loop_t *r = ptr;
+ return sizeof(*r) + r->num * sizeof(r->buf[0]);
+}
+
+static rb_random_data_type_t random_loop_type = {
+ "random/loop",
+ {
+ rb_random_mark,
+ loop_free,
+ random_loop_memsize,
+ },
+ RB_RANDOM_PARENT,
+ (void *)&random_loop_if,
+ RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+
+static VALUE
+loop_alloc(VALUE klass)
+{
+ rand_loop_t *rnd;
+ VALUE obj = TypedData_Make_Struct(klass, rand_loop_t, &random_loop_type, rnd);
+ rb_random_base_init(&rnd->base);
+ return obj;
+}
+
+static void
+loop_init(rb_random_t *rnd, const uint32_t *buf, size_t len)
+{
+ rand_loop_t *r = (rand_loop_t *)rnd;
+
+ if (len > max_seeds) len = max_seeds;
+
+ REALLOC_N(r->buf, uint32_t, len);
+ MEMCPY(r->buf, buf, uint32_t, (r->num = (uint32_t)len));
+}
+
+static void
+loop_get_bytes(rb_random_t *rnd, void *p, size_t n)
+{
+ uint8_t *buf = p;
+ while (n > 0) {
+ uint32_t x = loop_get_int32(rnd);
+ switch (n % 4) {
+ case 0:
+ *buf++ = (uint8_t)x;
+ n--;
+ /* FALLTHROUGH */
+ case 3:
+ *buf++ = (uint8_t)x;
+ n--;
+ /* FALLTHROUGH */
+ case 2:
+ *buf++ = (uint8_t)x;
+ n--;
+ /* FALLTHROUGH */
+ case 1:
+ *buf++ = (uint8_t)x;
+ n--;
+ }
+ }
+}
+
+static uint32_t
+loop_get_int32(rb_random_t *rnd)
+{
+ rand_loop_t *r = (rand_loop_t *)rnd;
+ if (r->idx < r->num) {
+ uint32_t x = r->buf[r->idx++];
+ if (r->idx >= r->num) r->idx = 0;
+ return x;
+ }
+ else if (r->num) {
+ return r->buf[r->idx = 0];
+ }
+ return 0;
+}
+
+static double
+loop_get_real(rb_random_t *rnd, int excl)
+{
+ uint32_t a = loop_get_int32(rnd);
+ return ldexp(a, -16);
+}
+
+void
+Init_random_loop(VALUE mod, VALUE base)
+{
+ VALUE c = rb_define_class_under(mod, "Loop", base);
+ rb_define_alloc_func(c, loop_alloc);
+ RB_RANDOM_DATA_INIT_PARENT(random_loop_type);
+}
diff --git a/ext/-test-/rational/depend b/ext/-test-/rational/depend
new file mode 100644
index 0000000000..d949fca66b
--- /dev/null
+++ b/ext/-test-/rational/depend
@@ -0,0 +1,183 @@
+$(OBJS): $(HDRS) $(ruby_headers)
+
+rat.o: rat.c $(top_srcdir)/internal.h
+
+# AUTOGENERATED DEPENDENCIES START
+rat.o: $(RUBY_EXTCONF_H)
+rat.o: $(arch_hdrdir)/ruby/config.h
+rat.o: $(hdrdir)/ruby/assert.h
+rat.o: $(hdrdir)/ruby/backward.h
+rat.o: $(hdrdir)/ruby/backward/2/assume.h
+rat.o: $(hdrdir)/ruby/backward/2/attributes.h
+rat.o: $(hdrdir)/ruby/backward/2/bool.h
+rat.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+rat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rat.o: $(hdrdir)/ruby/backward/2/limits.h
+rat.o: $(hdrdir)/ruby/backward/2/long_long.h
+rat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rat.o: $(hdrdir)/ruby/backward/2/stdarg.h
+rat.o: $(hdrdir)/ruby/defines.h
+rat.o: $(hdrdir)/ruby/intern.h
+rat.o: $(hdrdir)/ruby/internal/abi.h
+rat.o: $(hdrdir)/ruby/internal/anyargs.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rat.o: $(hdrdir)/ruby/internal/assume.h
+rat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rat.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rat.o: $(hdrdir)/ruby/internal/attr/cold.h
+rat.o: $(hdrdir)/ruby/internal/attr/const.h
+rat.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rat.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rat.o: $(hdrdir)/ruby/internal/attr/error.h
+rat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rat.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rat.o: $(hdrdir)/ruby/internal/attr/format.h
+rat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rat.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rat.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rat.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rat.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rat.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rat.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+rat.o: $(hdrdir)/ruby/internal/attr/pure.h
+rat.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rat.o: $(hdrdir)/ruby/internal/attr/warning.h
+rat.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rat.o: $(hdrdir)/ruby/internal/cast.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rat.o: $(hdrdir)/ruby/internal/compiler_since.h
+rat.o: $(hdrdir)/ruby/internal/config.h
+rat.o: $(hdrdir)/ruby/internal/constant_p.h
+rat.o: $(hdrdir)/ruby/internal/core.h
+rat.o: $(hdrdir)/ruby/internal/core/rarray.h
+rat.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rat.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rat.o: $(hdrdir)/ruby/internal/core/rclass.h
+rat.o: $(hdrdir)/ruby/internal/core/rdata.h
+rat.o: $(hdrdir)/ruby/internal/core/rfile.h
+rat.o: $(hdrdir)/ruby/internal/core/rhash.h
+rat.o: $(hdrdir)/ruby/internal/core/robject.h
+rat.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rat.o: $(hdrdir)/ruby/internal/core/rstring.h
+rat.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rat.o: $(hdrdir)/ruby/internal/ctype.h
+rat.o: $(hdrdir)/ruby/internal/dllexport.h
+rat.o: $(hdrdir)/ruby/internal/dosish.h
+rat.o: $(hdrdir)/ruby/internal/error.h
+rat.o: $(hdrdir)/ruby/internal/eval.h
+rat.o: $(hdrdir)/ruby/internal/event.h
+rat.o: $(hdrdir)/ruby/internal/fl_type.h
+rat.o: $(hdrdir)/ruby/internal/gc.h
+rat.o: $(hdrdir)/ruby/internal/glob.h
+rat.o: $(hdrdir)/ruby/internal/globals.h
+rat.o: $(hdrdir)/ruby/internal/has/attribute.h
+rat.o: $(hdrdir)/ruby/internal/has/builtin.h
+rat.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rat.o: $(hdrdir)/ruby/internal/has/extension.h
+rat.o: $(hdrdir)/ruby/internal/has/feature.h
+rat.o: $(hdrdir)/ruby/internal/has/warning.h
+rat.o: $(hdrdir)/ruby/internal/intern/array.h
+rat.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rat.o: $(hdrdir)/ruby/internal/intern/class.h
+rat.o: $(hdrdir)/ruby/internal/intern/compar.h
+rat.o: $(hdrdir)/ruby/internal/intern/complex.h
+rat.o: $(hdrdir)/ruby/internal/intern/cont.h
+rat.o: $(hdrdir)/ruby/internal/intern/dir.h
+rat.o: $(hdrdir)/ruby/internal/intern/enum.h
+rat.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rat.o: $(hdrdir)/ruby/internal/intern/error.h
+rat.o: $(hdrdir)/ruby/internal/intern/eval.h
+rat.o: $(hdrdir)/ruby/internal/intern/file.h
+rat.o: $(hdrdir)/ruby/internal/intern/hash.h
+rat.o: $(hdrdir)/ruby/internal/intern/io.h
+rat.o: $(hdrdir)/ruby/internal/intern/load.h
+rat.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rat.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rat.o: $(hdrdir)/ruby/internal/intern/object.h
+rat.o: $(hdrdir)/ruby/internal/intern/parse.h
+rat.o: $(hdrdir)/ruby/internal/intern/proc.h
+rat.o: $(hdrdir)/ruby/internal/intern/process.h
+rat.o: $(hdrdir)/ruby/internal/intern/random.h
+rat.o: $(hdrdir)/ruby/internal/intern/range.h
+rat.o: $(hdrdir)/ruby/internal/intern/rational.h
+rat.o: $(hdrdir)/ruby/internal/intern/re.h
+rat.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rat.o: $(hdrdir)/ruby/internal/intern/select.h
+rat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rat.o: $(hdrdir)/ruby/internal/intern/set.h
+rat.o: $(hdrdir)/ruby/internal/intern/signal.h
+rat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rat.o: $(hdrdir)/ruby/internal/intern/string.h
+rat.o: $(hdrdir)/ruby/internal/intern/struct.h
+rat.o: $(hdrdir)/ruby/internal/intern/thread.h
+rat.o: $(hdrdir)/ruby/internal/intern/time.h
+rat.o: $(hdrdir)/ruby/internal/intern/variable.h
+rat.o: $(hdrdir)/ruby/internal/intern/vm.h
+rat.o: $(hdrdir)/ruby/internal/interpreter.h
+rat.o: $(hdrdir)/ruby/internal/iterator.h
+rat.o: $(hdrdir)/ruby/internal/memory.h
+rat.o: $(hdrdir)/ruby/internal/method.h
+rat.o: $(hdrdir)/ruby/internal/module.h
+rat.o: $(hdrdir)/ruby/internal/newobj.h
+rat.o: $(hdrdir)/ruby/internal/scan_args.h
+rat.o: $(hdrdir)/ruby/internal/special_consts.h
+rat.o: $(hdrdir)/ruby/internal/static_assert.h
+rat.o: $(hdrdir)/ruby/internal/stdalign.h
+rat.o: $(hdrdir)/ruby/internal/stdbool.h
+rat.o: $(hdrdir)/ruby/internal/stdckdint.h
+rat.o: $(hdrdir)/ruby/internal/symbol.h
+rat.o: $(hdrdir)/ruby/internal/value.h
+rat.o: $(hdrdir)/ruby/internal/value_type.h
+rat.o: $(hdrdir)/ruby/internal/variable.h
+rat.o: $(hdrdir)/ruby/internal/warning_push.h
+rat.o: $(hdrdir)/ruby/internal/xmalloc.h
+rat.o: $(hdrdir)/ruby/missing.h
+rat.o: $(hdrdir)/ruby/ruby.h
+rat.o: $(hdrdir)/ruby/st.h
+rat.o: $(hdrdir)/ruby/subst.h
+rat.o: $(top_srcdir)/internal.h
+rat.o: $(top_srcdir)/internal/basic_operators.h
+rat.o: $(top_srcdir)/internal/bignum.h
+rat.o: $(top_srcdir)/internal/bits.h
+rat.o: $(top_srcdir)/internal/compar.h
+rat.o: $(top_srcdir)/internal/compilers.h
+rat.o: $(top_srcdir)/internal/fixnum.h
+rat.o: $(top_srcdir)/internal/gc.h
+rat.o: $(top_srcdir)/internal/numeric.h
+rat.o: $(top_srcdir)/internal/rational.h
+rat.o: $(top_srcdir)/internal/serial.h
+rat.o: $(top_srcdir)/internal/static_assert.h
+rat.o: $(top_srcdir)/internal/vm.h
+rat.o: $(top_srcdir)/internal/warnings.h
+rat.o: $(top_srcdir)/ruby_assert.h
+rat.o: $(top_srcdir)/shape.h
+rat.o: rat.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/rational/extconf.rb b/ext/-test-/rational/extconf.rb
new file mode 100644
index 0000000000..28c5d690c1
--- /dev/null
+++ b/ext/-test-/rational/extconf.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: false
+$INCFLAGS << " -I$(topdir) -I$(top_srcdir)"
+$srcs = Dir[File.join($srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
+inits = $srcs.map {|s| File.basename(s, ".*")}
+inits.delete("init")
+inits.map! {|s|"X(#{s})"}
+$defs << "-DTEST_INIT_FUNCS(X)=\"#{inits.join(' ')}\""
+create_makefile("-test-/rational")
diff --git a/ext/-test-/rational/rat.c b/ext/-test-/rational/rat.c
new file mode 100644
index 0000000000..6489fe3d7c
--- /dev/null
+++ b/ext/-test-/rational/rat.c
@@ -0,0 +1,48 @@
+#include "internal/rational.h"
+
+#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
+static VALUE
+big(VALUE x)
+{
+ if (FIXNUM_P(x))
+ return rb_int2big(FIX2LONG(x));
+ if (RB_TYPE_P(x, T_BIGNUM))
+ return x;
+ rb_raise(rb_eTypeError, "can't convert %s to Bignum",
+ rb_obj_classname(x));
+}
+#endif
+
+static VALUE
+gcd_normal(VALUE klass, VALUE x, VALUE y)
+{
+ return rb_big_norm(rb_gcd_normal(rb_to_int(x), rb_to_int(y)));
+}
+
+#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
+static VALUE
+gcd_gmp(VALUE klass, VALUE x, VALUE y)
+{
+ return rb_big_norm(rb_gcd_gmp(big(x), big(y)));
+}
+#else
+#define gcd_gmp rb_f_notimplement
+#endif
+
+static VALUE
+s_rational_raw(VALUE klass, VALUE x, VALUE y)
+{
+ return rb_rational_raw(x, y);
+}
+
+void
+Init_rational(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_module_under(mBug, "Rational");
+
+ rb_define_singleton_method(klass, "gcd_normal", gcd_normal, 2);
+ rb_define_singleton_method(klass, "gcd_gmp", gcd_gmp, 2);
+
+ rb_define_singleton_method(klass, "raw", s_rational_raw, 2);
+}
diff --git a/ext/-test-/rb_call_super_kw/depend b/ext/-test-/rb_call_super_kw/depend
new file mode 100644
index 0000000000..bf34323ca7
--- /dev/null
+++ b/ext/-test-/rb_call_super_kw/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+rb_call_super_kw.o: $(RUBY_EXTCONF_H)
+rb_call_super_kw.o: $(arch_hdrdir)/ruby/config.h
+rb_call_super_kw.o: $(hdrdir)/ruby.h
+rb_call_super_kw.o: $(hdrdir)/ruby/assert.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/assume.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/attributes.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/bool.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/limits.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/long_long.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/stdarg.h
+rb_call_super_kw.o: $(hdrdir)/ruby/defines.h
+rb_call_super_kw.o: $(hdrdir)/ruby/intern.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/abi.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/anyargs.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/assume.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/cold.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/const.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/error.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/format.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/pure.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/warning.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/cast.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_since.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/config.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/constant_p.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rarray.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rclass.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rdata.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rfile.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rhash.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/robject.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rstring.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/ctype.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/dllexport.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/dosish.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/error.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/eval.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/event.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/fl_type.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/gc.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/glob.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/globals.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/attribute.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/builtin.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/extension.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/feature.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/warning.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/array.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/class.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/compar.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/complex.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/cont.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/dir.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/enum.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/error.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/eval.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/file.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/hash.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/io.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/load.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/object.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/parse.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/proc.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/process.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/random.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/range.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/rational.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/re.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/select.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/set.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/signal.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/string.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/struct.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/thread.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/time.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/variable.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/vm.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/interpreter.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/iterator.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/memory.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/method.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/module.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/newobj.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/scan_args.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/special_consts.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/static_assert.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/stdalign.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/stdbool.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/stdckdint.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/symbol.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/value.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/value_type.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/variable.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/warning_push.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/xmalloc.h
+rb_call_super_kw.o: $(hdrdir)/ruby/missing.h
+rb_call_super_kw.o: $(hdrdir)/ruby/ruby.h
+rb_call_super_kw.o: $(hdrdir)/ruby/st.h
+rb_call_super_kw.o: $(hdrdir)/ruby/subst.h
+rb_call_super_kw.o: rb_call_super_kw.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/rb_call_super_kw/extconf.rb b/ext/-test-/rb_call_super_kw/extconf.rb
new file mode 100644
index 0000000000..c6a5c720d7
--- /dev/null
+++ b/ext/-test-/rb_call_super_kw/extconf.rb
@@ -0,0 +1 @@
+create_makefile("-test-/rb_call_super_kw")
diff --git a/ext/-test-/rb_call_super_kw/rb_call_super_kw.c b/ext/-test-/rb_call_super_kw/rb_call_super_kw.c
new file mode 100644
index 0000000000..61681ed733
--- /dev/null
+++ b/ext/-test-/rb_call_super_kw/rb_call_super_kw.c
@@ -0,0 +1,15 @@
+#include <ruby.h>
+
+static VALUE
+rb_call_super_kw_m(int argc, VALUE *argv, VALUE self)
+{
+ return rb_call_super_kw(argc, argv, RB_PASS_CALLED_KEYWORDS);
+}
+
+void
+Init_rb_call_super_kw(void)
+{
+ VALUE module = rb_define_module("Bug");
+ module = rb_define_module_under(module, "RbCallSuperKw");
+ rb_define_method(module, "m", rb_call_super_kw_m, -1);
+}
diff --git a/ext/-test-/recursion/depend b/ext/-test-/recursion/depend
new file mode 100644
index 0000000000..b6487eb4df
--- /dev/null
+++ b/ext/-test-/recursion/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+recursion.o: $(RUBY_EXTCONF_H)
+recursion.o: $(arch_hdrdir)/ruby/config.h
+recursion.o: $(hdrdir)/ruby.h
+recursion.o: $(hdrdir)/ruby/assert.h
+recursion.o: $(hdrdir)/ruby/backward.h
+recursion.o: $(hdrdir)/ruby/backward/2/assume.h
+recursion.o: $(hdrdir)/ruby/backward/2/attributes.h
+recursion.o: $(hdrdir)/ruby/backward/2/bool.h
+recursion.o: $(hdrdir)/ruby/backward/2/inttypes.h
+recursion.o: $(hdrdir)/ruby/backward/2/limits.h
+recursion.o: $(hdrdir)/ruby/backward/2/long_long.h
+recursion.o: $(hdrdir)/ruby/backward/2/stdalign.h
+recursion.o: $(hdrdir)/ruby/backward/2/stdarg.h
+recursion.o: $(hdrdir)/ruby/defines.h
+recursion.o: $(hdrdir)/ruby/intern.h
+recursion.o: $(hdrdir)/ruby/internal/abi.h
+recursion.o: $(hdrdir)/ruby/internal/anyargs.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+recursion.o: $(hdrdir)/ruby/internal/assume.h
+recursion.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+recursion.o: $(hdrdir)/ruby/internal/attr/artificial.h
+recursion.o: $(hdrdir)/ruby/internal/attr/cold.h
+recursion.o: $(hdrdir)/ruby/internal/attr/const.h
+recursion.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+recursion.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+recursion.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+recursion.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+recursion.o: $(hdrdir)/ruby/internal/attr/error.h
+recursion.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+recursion.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+recursion.o: $(hdrdir)/ruby/internal/attr/format.h
+recursion.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+recursion.o: $(hdrdir)/ruby/internal/attr/noalias.h
+recursion.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+recursion.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+recursion.o: $(hdrdir)/ruby/internal/attr/noinline.h
+recursion.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+recursion.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+recursion.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+recursion.o: $(hdrdir)/ruby/internal/attr/pure.h
+recursion.o: $(hdrdir)/ruby/internal/attr/restrict.h
+recursion.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+recursion.o: $(hdrdir)/ruby/internal/attr/warning.h
+recursion.o: $(hdrdir)/ruby/internal/attr/weakref.h
+recursion.o: $(hdrdir)/ruby/internal/cast.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_since.h
+recursion.o: $(hdrdir)/ruby/internal/config.h
+recursion.o: $(hdrdir)/ruby/internal/constant_p.h
+recursion.o: $(hdrdir)/ruby/internal/core.h
+recursion.o: $(hdrdir)/ruby/internal/core/rarray.h
+recursion.o: $(hdrdir)/ruby/internal/core/rbasic.h
+recursion.o: $(hdrdir)/ruby/internal/core/rbignum.h
+recursion.o: $(hdrdir)/ruby/internal/core/rclass.h
+recursion.o: $(hdrdir)/ruby/internal/core/rdata.h
+recursion.o: $(hdrdir)/ruby/internal/core/rfile.h
+recursion.o: $(hdrdir)/ruby/internal/core/rhash.h
+recursion.o: $(hdrdir)/ruby/internal/core/robject.h
+recursion.o: $(hdrdir)/ruby/internal/core/rregexp.h
+recursion.o: $(hdrdir)/ruby/internal/core/rstring.h
+recursion.o: $(hdrdir)/ruby/internal/core/rstruct.h
+recursion.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+recursion.o: $(hdrdir)/ruby/internal/ctype.h
+recursion.o: $(hdrdir)/ruby/internal/dllexport.h
+recursion.o: $(hdrdir)/ruby/internal/dosish.h
+recursion.o: $(hdrdir)/ruby/internal/error.h
+recursion.o: $(hdrdir)/ruby/internal/eval.h
+recursion.o: $(hdrdir)/ruby/internal/event.h
+recursion.o: $(hdrdir)/ruby/internal/fl_type.h
+recursion.o: $(hdrdir)/ruby/internal/gc.h
+recursion.o: $(hdrdir)/ruby/internal/glob.h
+recursion.o: $(hdrdir)/ruby/internal/globals.h
+recursion.o: $(hdrdir)/ruby/internal/has/attribute.h
+recursion.o: $(hdrdir)/ruby/internal/has/builtin.h
+recursion.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+recursion.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+recursion.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+recursion.o: $(hdrdir)/ruby/internal/has/extension.h
+recursion.o: $(hdrdir)/ruby/internal/has/feature.h
+recursion.o: $(hdrdir)/ruby/internal/has/warning.h
+recursion.o: $(hdrdir)/ruby/internal/intern/array.h
+recursion.o: $(hdrdir)/ruby/internal/intern/bignum.h
+recursion.o: $(hdrdir)/ruby/internal/intern/class.h
+recursion.o: $(hdrdir)/ruby/internal/intern/compar.h
+recursion.o: $(hdrdir)/ruby/internal/intern/complex.h
+recursion.o: $(hdrdir)/ruby/internal/intern/cont.h
+recursion.o: $(hdrdir)/ruby/internal/intern/dir.h
+recursion.o: $(hdrdir)/ruby/internal/intern/enum.h
+recursion.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+recursion.o: $(hdrdir)/ruby/internal/intern/error.h
+recursion.o: $(hdrdir)/ruby/internal/intern/eval.h
+recursion.o: $(hdrdir)/ruby/internal/intern/file.h
+recursion.o: $(hdrdir)/ruby/internal/intern/hash.h
+recursion.o: $(hdrdir)/ruby/internal/intern/io.h
+recursion.o: $(hdrdir)/ruby/internal/intern/load.h
+recursion.o: $(hdrdir)/ruby/internal/intern/marshal.h
+recursion.o: $(hdrdir)/ruby/internal/intern/numeric.h
+recursion.o: $(hdrdir)/ruby/internal/intern/object.h
+recursion.o: $(hdrdir)/ruby/internal/intern/parse.h
+recursion.o: $(hdrdir)/ruby/internal/intern/proc.h
+recursion.o: $(hdrdir)/ruby/internal/intern/process.h
+recursion.o: $(hdrdir)/ruby/internal/intern/random.h
+recursion.o: $(hdrdir)/ruby/internal/intern/range.h
+recursion.o: $(hdrdir)/ruby/internal/intern/rational.h
+recursion.o: $(hdrdir)/ruby/internal/intern/re.h
+recursion.o: $(hdrdir)/ruby/internal/intern/ruby.h
+recursion.o: $(hdrdir)/ruby/internal/intern/select.h
+recursion.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+recursion.o: $(hdrdir)/ruby/internal/intern/set.h
+recursion.o: $(hdrdir)/ruby/internal/intern/signal.h
+recursion.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+recursion.o: $(hdrdir)/ruby/internal/intern/string.h
+recursion.o: $(hdrdir)/ruby/internal/intern/struct.h
+recursion.o: $(hdrdir)/ruby/internal/intern/thread.h
+recursion.o: $(hdrdir)/ruby/internal/intern/time.h
+recursion.o: $(hdrdir)/ruby/internal/intern/variable.h
+recursion.o: $(hdrdir)/ruby/internal/intern/vm.h
+recursion.o: $(hdrdir)/ruby/internal/interpreter.h
+recursion.o: $(hdrdir)/ruby/internal/iterator.h
+recursion.o: $(hdrdir)/ruby/internal/memory.h
+recursion.o: $(hdrdir)/ruby/internal/method.h
+recursion.o: $(hdrdir)/ruby/internal/module.h
+recursion.o: $(hdrdir)/ruby/internal/newobj.h
+recursion.o: $(hdrdir)/ruby/internal/scan_args.h
+recursion.o: $(hdrdir)/ruby/internal/special_consts.h
+recursion.o: $(hdrdir)/ruby/internal/static_assert.h
+recursion.o: $(hdrdir)/ruby/internal/stdalign.h
+recursion.o: $(hdrdir)/ruby/internal/stdbool.h
+recursion.o: $(hdrdir)/ruby/internal/stdckdint.h
+recursion.o: $(hdrdir)/ruby/internal/symbol.h
+recursion.o: $(hdrdir)/ruby/internal/value.h
+recursion.o: $(hdrdir)/ruby/internal/value_type.h
+recursion.o: $(hdrdir)/ruby/internal/variable.h
+recursion.o: $(hdrdir)/ruby/internal/warning_push.h
+recursion.o: $(hdrdir)/ruby/internal/xmalloc.h
+recursion.o: $(hdrdir)/ruby/missing.h
+recursion.o: $(hdrdir)/ruby/ruby.h
+recursion.o: $(hdrdir)/ruby/st.h
+recursion.o: $(hdrdir)/ruby/subst.h
+recursion.o: recursion.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/recursion/extconf.rb b/ext/-test-/recursion/extconf.rb
new file mode 100644
index 0000000000..13828113f0
--- /dev/null
+++ b/ext/-test-/recursion/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require 'mkmf'
+create_makefile("-test-/recursion")
diff --git a/ext/-test-/recursion/recursion.c b/ext/-test-/recursion/recursion.c
new file mode 100644
index 0000000000..13d41f0ba8
--- /dev/null
+++ b/ext/-test-/recursion/recursion.c
@@ -0,0 +1,28 @@
+#include <ruby.h>
+
+static VALUE
+recursive_i(VALUE obj, VALUE mid, int recur)
+{
+ if (recur) return Qnil;
+ return rb_funcallv(obj, rb_to_id(mid), 0, 0);
+}
+
+static VALUE
+exec_recursive(VALUE self, VALUE mid)
+{
+ return rb_exec_recursive(recursive_i, self, mid);
+}
+
+static VALUE
+exec_recursive_outer(VALUE self, VALUE mid)
+{
+ return rb_exec_recursive_outer(recursive_i, self, mid);
+}
+
+void
+Init_recursion(void)
+{
+ VALUE m = rb_define_module_under(rb_define_module("Bug"), "Recursive");
+ rb_define_method(m, "exec_recursive", exec_recursive, 1);
+ rb_define_method(m, "exec_recursive_outer", exec_recursive_outer, 1);
+}
diff --git a/ext/-test-/regexp/depend b/ext/-test-/regexp/depend
new file mode 100644
index 0000000000..5ba1b92f18
--- /dev/null
+++ b/ext/-test-/regexp/depend
@@ -0,0 +1,325 @@
+# AUTOGENERATED DEPENDENCIES START
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+parse_depth_limit.o: $(RUBY_EXTCONF_H)
+parse_depth_limit.o: $(arch_hdrdir)/ruby/config.h
+parse_depth_limit.o: $(hdrdir)/ruby.h
+parse_depth_limit.o: $(hdrdir)/ruby/assert.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/assume.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/attributes.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/bool.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/inttypes.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/limits.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/long_long.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/stdalign.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/stdarg.h
+parse_depth_limit.o: $(hdrdir)/ruby/defines.h
+parse_depth_limit.o: $(hdrdir)/ruby/intern.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/abi.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/anyargs.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/assume.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/artificial.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/cold.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/const.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/error.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/format.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/noalias.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/noinline.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/pure.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/restrict.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/warning.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/weakref.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/cast.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_since.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/config.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/constant_p.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rarray.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rbasic.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rbignum.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rclass.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rdata.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rfile.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rhash.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/robject.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rregexp.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rstring.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rstruct.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/ctype.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/dllexport.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/dosish.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/error.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/eval.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/event.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/fl_type.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/gc.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/glob.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/globals.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/attribute.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/builtin.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/extension.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/feature.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/warning.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/array.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/bignum.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/class.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/compar.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/complex.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/cont.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/dir.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/enum.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/error.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/eval.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/file.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/hash.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/io.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/load.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/marshal.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/numeric.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/object.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/parse.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/proc.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/process.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/random.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/range.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/rational.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/re.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/ruby.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/select.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/set.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/signal.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/string.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/struct.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/thread.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/time.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/variable.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/vm.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/interpreter.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/iterator.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/memory.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/method.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/module.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/newobj.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/scan_args.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/special_consts.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/static_assert.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/stdalign.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/stdbool.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/stdckdint.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/symbol.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/value.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/value_type.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/variable.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/warning_push.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/xmalloc.h
+parse_depth_limit.o: $(hdrdir)/ruby/missing.h
+parse_depth_limit.o: $(hdrdir)/ruby/onigmo.h
+parse_depth_limit.o: $(hdrdir)/ruby/ruby.h
+parse_depth_limit.o: $(hdrdir)/ruby/st.h
+parse_depth_limit.o: $(hdrdir)/ruby/subst.h
+parse_depth_limit.o: parse_depth_limit.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/regexp/extconf.rb b/ext/-test-/regexp/extconf.rb
new file mode 100644
index 0000000000..ca51178a18
--- /dev/null
+++ b/ext/-test-/regexp/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext
diff --git a/ext/-test-/regexp/init.c b/ext/-test-/regexp/init.c
new file mode 100644
index 0000000000..906abe940f
--- /dev/null
+++ b/ext/-test-/regexp/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_regexp(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "Regexp", rb_cRegexp);
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/regexp/parse_depth_limit.c b/ext/-test-/regexp/parse_depth_limit.c
new file mode 100644
index 0000000000..8e08a5c789
--- /dev/null
+++ b/ext/-test-/regexp/parse_depth_limit.c
@@ -0,0 +1,23 @@
+#include <ruby.h>
+#include <ruby/onigmo.h>
+
+static VALUE
+get_parse_depth_limit(VALUE self)
+{
+ unsigned int depth = onig_get_parse_depth_limit();
+ return UINT2NUM(depth);
+}
+
+static VALUE
+set_parse_depth_limit(VALUE self, VALUE depth)
+{
+ onig_set_parse_depth_limit(NUM2UINT(depth));
+ return depth;
+}
+
+void
+Init_parse_depth_limit(VALUE klass)
+{
+ rb_define_singleton_method(klass, "parse_depth_limit", get_parse_depth_limit, 0);
+ rb_define_singleton_method(klass, "parse_depth_limit=", set_parse_depth_limit, 1);
+}
diff --git a/ext/-test-/sanitizers/depend b/ext/-test-/sanitizers/depend
new file mode 100644
index 0000000000..0e6e632803
--- /dev/null
+++ b/ext/-test-/sanitizers/depend
@@ -0,0 +1,162 @@
+# AUTOGENERATED DEPENDENCIES START
+sanitizers.o: $(RUBY_EXTCONF_H)
+sanitizers.o: $(arch_hdrdir)/ruby/config.h
+sanitizers.o: $(hdrdir)/ruby/assert.h
+sanitizers.o: $(hdrdir)/ruby/backward.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/assume.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/attributes.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/bool.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/limits.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/long_long.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/stdarg.h
+sanitizers.o: $(hdrdir)/ruby/defines.h
+sanitizers.o: $(hdrdir)/ruby/intern.h
+sanitizers.o: $(hdrdir)/ruby/internal/abi.h
+sanitizers.o: $(hdrdir)/ruby/internal/anyargs.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/assume.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/cold.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/const.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/error.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/format.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/pure.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/warning.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sanitizers.o: $(hdrdir)/ruby/internal/cast.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_since.h
+sanitizers.o: $(hdrdir)/ruby/internal/config.h
+sanitizers.o: $(hdrdir)/ruby/internal/constant_p.h
+sanitizers.o: $(hdrdir)/ruby/internal/core.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rarray.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rclass.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rdata.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rfile.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rhash.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/robject.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rstring.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sanitizers.o: $(hdrdir)/ruby/internal/ctype.h
+sanitizers.o: $(hdrdir)/ruby/internal/dllexport.h
+sanitizers.o: $(hdrdir)/ruby/internal/dosish.h
+sanitizers.o: $(hdrdir)/ruby/internal/error.h
+sanitizers.o: $(hdrdir)/ruby/internal/eval.h
+sanitizers.o: $(hdrdir)/ruby/internal/event.h
+sanitizers.o: $(hdrdir)/ruby/internal/fl_type.h
+sanitizers.o: $(hdrdir)/ruby/internal/gc.h
+sanitizers.o: $(hdrdir)/ruby/internal/glob.h
+sanitizers.o: $(hdrdir)/ruby/internal/globals.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/attribute.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/builtin.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/extension.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/feature.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/warning.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/array.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/class.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/compar.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/complex.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/cont.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/dir.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/enum.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/error.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/eval.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/file.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/hash.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/io.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/load.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/object.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/parse.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/proc.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/process.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/random.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/range.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/rational.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/re.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/select.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/set.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/signal.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/string.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/struct.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/thread.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/time.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/variable.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/vm.h
+sanitizers.o: $(hdrdir)/ruby/internal/interpreter.h
+sanitizers.o: $(hdrdir)/ruby/internal/iterator.h
+sanitizers.o: $(hdrdir)/ruby/internal/memory.h
+sanitizers.o: $(hdrdir)/ruby/internal/method.h
+sanitizers.o: $(hdrdir)/ruby/internal/module.h
+sanitizers.o: $(hdrdir)/ruby/internal/newobj.h
+sanitizers.o: $(hdrdir)/ruby/internal/scan_args.h
+sanitizers.o: $(hdrdir)/ruby/internal/special_consts.h
+sanitizers.o: $(hdrdir)/ruby/internal/static_assert.h
+sanitizers.o: $(hdrdir)/ruby/internal/stdalign.h
+sanitizers.o: $(hdrdir)/ruby/internal/stdbool.h
+sanitizers.o: $(hdrdir)/ruby/internal/stdckdint.h
+sanitizers.o: $(hdrdir)/ruby/internal/symbol.h
+sanitizers.o: $(hdrdir)/ruby/internal/value.h
+sanitizers.o: $(hdrdir)/ruby/internal/value_type.h
+sanitizers.o: $(hdrdir)/ruby/internal/variable.h
+sanitizers.o: $(hdrdir)/ruby/internal/warning_push.h
+sanitizers.o: $(hdrdir)/ruby/internal/xmalloc.h
+sanitizers.o: $(hdrdir)/ruby/missing.h
+sanitizers.o: $(hdrdir)/ruby/ruby.h
+sanitizers.o: $(hdrdir)/ruby/st.h
+sanitizers.o: $(hdrdir)/ruby/subst.h
+sanitizers.o: sanitizers.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/sanitizers/extconf.rb b/ext/-test-/sanitizers/extconf.rb
new file mode 100644
index 0000000000..c94a96de6c
--- /dev/null
+++ b/ext/-test-/sanitizers/extconf.rb
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile('-test-/sanitizers')
diff --git a/ext/-test-/sanitizers/sanitizers.c b/ext/-test-/sanitizers/sanitizers.c
new file mode 100644
index 0000000000..97a85b26ef
--- /dev/null
+++ b/ext/-test-/sanitizers/sanitizers.c
@@ -0,0 +1,36 @@
+#include "ruby/ruby.h"
+
+static VALUE
+asan_enabled_p(VALUE self)
+{
+#if defined(__has_feature)
+ /* clang uses __has_feature for determining asan */
+ return __has_feature(address_sanitizer) ? Qtrue : Qfalse;
+#elif defined(__SANITIZE_ADDRESS__)
+ /* GCC sets __SANITIZE_ADDRESS__ for determining asan */
+ return Qtrue;
+#else
+ return Qfalse;
+#endif
+}
+
+static VALUE
+lsan_enabled_p(VALUE self)
+{
+#if defined(__has_feature)
+ /* clang uses __has_feature for determining LSAN */
+ return __has_feature(leak_sanitizer) ? Qtrue : Qfalse;
+#else
+ return Qfalse;
+#endif
+}
+
+void
+Init_sanitizers(void)
+{
+ VALUE m = rb_define_module("Test");
+ VALUE c = rb_define_class_under(m, "Sanitizers", rb_cObject);
+ rb_define_singleton_method(c, "asan_enabled?", asan_enabled_p, 0);
+ rb_define_singleton_method(c, "lsan_enabled?", lsan_enabled_p, 0);
+}
+
diff --git a/ext/-test-/scan_args/depend b/ext/-test-/scan_args/depend
new file mode 100644
index 0000000000..ca0fc19238
--- /dev/null
+++ b/ext/-test-/scan_args/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+scan_args.o: $(RUBY_EXTCONF_H)
+scan_args.o: $(arch_hdrdir)/ruby/config.h
+scan_args.o: $(hdrdir)/ruby.h
+scan_args.o: $(hdrdir)/ruby/assert.h
+scan_args.o: $(hdrdir)/ruby/backward.h
+scan_args.o: $(hdrdir)/ruby/backward/2/assume.h
+scan_args.o: $(hdrdir)/ruby/backward/2/attributes.h
+scan_args.o: $(hdrdir)/ruby/backward/2/bool.h
+scan_args.o: $(hdrdir)/ruby/backward/2/inttypes.h
+scan_args.o: $(hdrdir)/ruby/backward/2/limits.h
+scan_args.o: $(hdrdir)/ruby/backward/2/long_long.h
+scan_args.o: $(hdrdir)/ruby/backward/2/stdalign.h
+scan_args.o: $(hdrdir)/ruby/backward/2/stdarg.h
+scan_args.o: $(hdrdir)/ruby/defines.h
+scan_args.o: $(hdrdir)/ruby/intern.h
+scan_args.o: $(hdrdir)/ruby/internal/abi.h
+scan_args.o: $(hdrdir)/ruby/internal/anyargs.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+scan_args.o: $(hdrdir)/ruby/internal/assume.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/artificial.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/cold.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/const.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/error.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/format.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/noalias.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/noinline.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/pure.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/restrict.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/warning.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/weakref.h
+scan_args.o: $(hdrdir)/ruby/internal/cast.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_since.h
+scan_args.o: $(hdrdir)/ruby/internal/config.h
+scan_args.o: $(hdrdir)/ruby/internal/constant_p.h
+scan_args.o: $(hdrdir)/ruby/internal/core.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rarray.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rbasic.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rbignum.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rclass.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rdata.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rfile.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rhash.h
+scan_args.o: $(hdrdir)/ruby/internal/core/robject.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rregexp.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rstring.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rstruct.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+scan_args.o: $(hdrdir)/ruby/internal/ctype.h
+scan_args.o: $(hdrdir)/ruby/internal/dllexport.h
+scan_args.o: $(hdrdir)/ruby/internal/dosish.h
+scan_args.o: $(hdrdir)/ruby/internal/error.h
+scan_args.o: $(hdrdir)/ruby/internal/eval.h
+scan_args.o: $(hdrdir)/ruby/internal/event.h
+scan_args.o: $(hdrdir)/ruby/internal/fl_type.h
+scan_args.o: $(hdrdir)/ruby/internal/gc.h
+scan_args.o: $(hdrdir)/ruby/internal/glob.h
+scan_args.o: $(hdrdir)/ruby/internal/globals.h
+scan_args.o: $(hdrdir)/ruby/internal/has/attribute.h
+scan_args.o: $(hdrdir)/ruby/internal/has/builtin.h
+scan_args.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+scan_args.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+scan_args.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+scan_args.o: $(hdrdir)/ruby/internal/has/extension.h
+scan_args.o: $(hdrdir)/ruby/internal/has/feature.h
+scan_args.o: $(hdrdir)/ruby/internal/has/warning.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/array.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/bignum.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/class.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/compar.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/complex.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/cont.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/dir.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/enum.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/error.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/eval.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/file.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/hash.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/io.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/load.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/marshal.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/numeric.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/object.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/parse.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/proc.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/process.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/random.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/range.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/rational.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/re.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/ruby.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/select.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/set.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/signal.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/string.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/struct.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/thread.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/time.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/variable.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/vm.h
+scan_args.o: $(hdrdir)/ruby/internal/interpreter.h
+scan_args.o: $(hdrdir)/ruby/internal/iterator.h
+scan_args.o: $(hdrdir)/ruby/internal/memory.h
+scan_args.o: $(hdrdir)/ruby/internal/method.h
+scan_args.o: $(hdrdir)/ruby/internal/module.h
+scan_args.o: $(hdrdir)/ruby/internal/newobj.h
+scan_args.o: $(hdrdir)/ruby/internal/scan_args.h
+scan_args.o: $(hdrdir)/ruby/internal/special_consts.h
+scan_args.o: $(hdrdir)/ruby/internal/static_assert.h
+scan_args.o: $(hdrdir)/ruby/internal/stdalign.h
+scan_args.o: $(hdrdir)/ruby/internal/stdbool.h
+scan_args.o: $(hdrdir)/ruby/internal/stdckdint.h
+scan_args.o: $(hdrdir)/ruby/internal/symbol.h
+scan_args.o: $(hdrdir)/ruby/internal/value.h
+scan_args.o: $(hdrdir)/ruby/internal/value_type.h
+scan_args.o: $(hdrdir)/ruby/internal/variable.h
+scan_args.o: $(hdrdir)/ruby/internal/warning_push.h
+scan_args.o: $(hdrdir)/ruby/internal/xmalloc.h
+scan_args.o: $(hdrdir)/ruby/missing.h
+scan_args.o: $(hdrdir)/ruby/ruby.h
+scan_args.o: $(hdrdir)/ruby/st.h
+scan_args.o: $(hdrdir)/ruby/subst.h
+scan_args.o: scan_args.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/scan_args/extconf.rb b/ext/-test-/scan_args/extconf.rb
new file mode 100644
index 0000000000..6cae9c2779
--- /dev/null
+++ b/ext/-test-/scan_args/extconf.rb
@@ -0,0 +1 @@
+create_makefile("-test-/scan_args")
diff --git a/ext/-test-/scan_args/scan_args.c b/ext/-test-/scan_args/scan_args.c
new file mode 100644
index 0000000000..8696aad3c7
--- /dev/null
+++ b/ext/-test-/scan_args/scan_args.c
@@ -0,0 +1,305 @@
+#include <ruby.h>
+
+#ifndef numberof
+#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
+#endif
+
+static VALUE
+scan_args_lead(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[2];
+ int n = rb_scan_args(argc, argv, "1", args+1);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_opt(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[2];
+ int n = rb_scan_args(argc, argv, "01", args+1);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_opt(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[3];
+ int n = rb_scan_args(argc, argv, "11", args+1, args+2);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+/* var */
+static VALUE
+scan_args_var(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[2];
+ int n = rb_scan_args(argc, argv, "*", args+1);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_var(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[3];
+ int n = rb_scan_args(argc, argv, "1*", args+1, args+2);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_opt_var(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[3];
+ int n = rb_scan_args(argc, argv, "01*", args+1, args+2);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_opt_var(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[4];
+ int n = rb_scan_args(argc, argv, "11*", args+1, args+2, args+3);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+/* trail */
+static VALUE
+scan_args_opt_trail(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[3];
+ int n = rb_scan_args(argc, argv, "011", args+1, args+2);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_opt_trail(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[4];
+ int n = rb_scan_args(argc, argv, "111", args+1, args+2, args+3);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_var_trail(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[3];
+ int n = rb_scan_args(argc, argv, "*1", args+1, args+2);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_var_trail(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[4];
+ int n = rb_scan_args(argc, argv, "1*1", args+1, args+2, args+3);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_opt_var_trail(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[4];
+ int n = rb_scan_args(argc, argv, "01*1", args+1, args+2, args+3);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_opt_var_trail(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[5];
+ int n = rb_scan_args(argc, argv, "11*1", args+1, args+2, args+3, args+4);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+/* hash */
+static VALUE
+scan_args_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[2];
+ int n = rb_scan_args(argc, argv, ":", args+1);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[3];
+ int n = rb_scan_args(argc, argv, "1:", args+1, args+2);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_opt_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[3];
+ int n = rb_scan_args(argc, argv, "01:", args+1, args+2);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_opt_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[4];
+ int n = rb_scan_args(argc, argv, "11:", args+1, args+2, args+3);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_var_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[3];
+ int n = rb_scan_args(argc, argv, "*:", args+1, args+2);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_var_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[4];
+ int n = rb_scan_args(argc, argv, "1*:", args+1, args+2, args+3);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_opt_var_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[4];
+ int n = rb_scan_args(argc, argv, "01*:", args+1, args+2, args+3);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_opt_var_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[5];
+ int n = rb_scan_args(argc, argv, "11*:", args+1, args+2, args+3, args+4);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_opt_trail_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[4];
+ int n = rb_scan_args(argc, argv, "011:", args+1, args+2, args+3);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_opt_trail_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[5];
+ int n = rb_scan_args(argc, argv, "111:", args+1, args+2, args+3, args+4);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_var_trail_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[4];
+ int n = rb_scan_args(argc, argv, "*1:", args+1, args+2, args+3);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_var_trail_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[5];
+ int n = rb_scan_args(argc, argv, "1*1:", args+1, args+2, args+3, args+4);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_opt_var_trail_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[5];
+ int n = rb_scan_args(argc, argv, "01*1:", args+1, args+2, args+3, args+4);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_lead_opt_var_trail_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[6];
+ int n = rb_scan_args(argc, argv, "11*1:", args+1, args+2, args+3, args+4, args+5);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_k_lead_opt_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[4];
+ int n = rb_scan_args_kw(RB_SCAN_ARGS_KEYWORDS, argc, argv, "11:", args+1, args+2, args+3);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+static VALUE
+scan_args_n_lead_opt_hash(int argc, VALUE *argv, VALUE self)
+{
+ VALUE args[4];
+ int n = rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, argc, argv, "11:", args+1, args+2, args+3);
+ args[0] = INT2NUM(n);
+ return rb_ary_new_from_values(numberof(args), args);
+}
+
+void
+Init_scan_args(void)
+{
+ VALUE module = rb_define_module("Bug");
+ module = rb_define_module_under(module, "ScanArgs");
+ rb_define_singleton_method(module, "lead", scan_args_lead, -1);
+ rb_define_singleton_method(module, "opt", scan_args_opt, -1);
+ rb_define_singleton_method(module, "lead_opt", scan_args_lead_opt, -1);
+ rb_define_singleton_method(module, "var", scan_args_var, -1);
+ rb_define_singleton_method(module, "lead_var", scan_args_lead_var, -1);
+ rb_define_singleton_method(module, "opt_var", scan_args_opt_var, -1);
+ rb_define_singleton_method(module, "lead_opt_var", scan_args_lead_opt_var, -1);
+ rb_define_singleton_method(module, "opt_trail", scan_args_opt_trail, -1);
+ rb_define_singleton_method(module, "lead_opt_trail", scan_args_lead_opt_trail, -1);
+ rb_define_singleton_method(module, "var_trail", scan_args_var_trail, -1);
+ rb_define_singleton_method(module, "lead_var_trail", scan_args_lead_var_trail, -1);
+ rb_define_singleton_method(module, "opt_var_trail", scan_args_opt_var_trail, -1);
+ rb_define_singleton_method(module, "lead_opt_var_trail", scan_args_lead_opt_var_trail, -1);
+ rb_define_singleton_method(module, "hash", scan_args_hash, -1);
+ rb_define_singleton_method(module, "lead_hash", scan_args_lead_hash, -1);
+ rb_define_singleton_method(module, "opt_hash", scan_args_opt_hash, -1);
+ rb_define_singleton_method(module, "lead_opt_hash", scan_args_lead_opt_hash, -1);
+ rb_define_singleton_method(module, "var_hash", scan_args_var_hash, -1);
+ rb_define_singleton_method(module, "lead_var_hash", scan_args_lead_var_hash, -1);
+ rb_define_singleton_method(module, "opt_var_hash", scan_args_opt_var_hash, -1);
+ rb_define_singleton_method(module, "lead_opt_var_hash", scan_args_lead_opt_var_hash, -1);
+ rb_define_singleton_method(module, "opt_trail_hash", scan_args_opt_trail_hash, -1);
+ rb_define_singleton_method(module, "lead_opt_trail_hash", scan_args_lead_opt_trail_hash, -1);
+ rb_define_singleton_method(module, "var_trail_hash", scan_args_var_trail_hash, -1);
+ rb_define_singleton_method(module, "lead_var_trail_hash", scan_args_lead_var_trail_hash, -1);
+ rb_define_singleton_method(module, "opt_var_trail_hash", scan_args_opt_var_trail_hash, -1);
+ rb_define_singleton_method(module, "lead_opt_var_trail_hash", scan_args_lead_opt_var_trail_hash, -1);
+ rb_define_singleton_method(module, "k_lead_opt_hash", scan_args_k_lead_opt_hash, -1);
+ rb_define_singleton_method(module, "n_lead_opt_hash", scan_args_n_lead_opt_hash, -1);
+}
diff --git a/ext/-test-/scheduler/extconf.rb b/ext/-test-/scheduler/extconf.rb
new file mode 100644
index 0000000000..159699bd8e
--- /dev/null
+++ b/ext/-test-/scheduler/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/scheduler")
diff --git a/ext/-test-/scheduler/scheduler.c b/ext/-test-/scheduler/scheduler.c
new file mode 100644
index 0000000000..b742a5573b
--- /dev/null
+++ b/ext/-test-/scheduler/scheduler.c
@@ -0,0 +1,92 @@
+#include "ruby/ruby.h"
+#include "ruby/thread.h"
+#include "ruby/io.h"
+#include "ruby/fiber/scheduler.h"
+
+/*
+ * Test extension for reproducing the gRPC interrupt handling bug.
+ *
+ * This reproduces the exact issue from grpc/grpc commit 69f229e (June 2025):
+ * https://github.com/grpc/grpc/commit/69f229edd1d79ab7a7dfda98e3aef6fd807adcad
+ *
+ * The bug occurs when:
+ * 1. A fiber scheduler uses Thread.handle_interrupt(::SignalException => :never)
+ * (like Async::Scheduler does)
+ * 2. Native code uses rb_thread_call_without_gvl in a retry loop that checks
+ * the interrupted flag and retries (like gRPC's completion queue)
+ * 3. A signal (SIGINT/SIGTERM) is sent
+ * 4. The unblock_func sets interrupted=1, but Thread.handle_interrupt defers the signal
+ * 5. The loop sees interrupted=1 and retries without yielding to the scheduler
+ * 6. The deferred interrupt never gets processed -> infinite hang
+ *
+ * The fix is in vm_check_ints_blocking() in thread.c, which should yield to
+ * the fiber scheduler when interrupts are pending, allowing the scheduler to
+ * detect Thread.pending_interrupt? and exit its run loop.
+ */
+
+struct blocking_state {
+ int notify_descriptor;
+ volatile int interrupted;
+};
+
+static void
+unblock_callback(void *argument)
+{
+ struct blocking_state *blocking_state = (struct blocking_state *)argument;
+ blocking_state->interrupted = 1;
+}
+
+static void *
+blocking_operation(void *argument)
+{
+ struct blocking_state *blocking_state = (struct blocking_state *)argument;
+
+ ssize_t ret = write(blocking_state->notify_descriptor, "x", 1);
+ (void)ret; // ignore the result for now
+
+ while (!blocking_state->interrupted) {
+ struct timeval tv = {1, 0}; // 1 second timeout.
+ int result = select(0, NULL, NULL, NULL, &tv);
+
+ if (result == -1 && errno == EINTR) {
+ blocking_state->interrupted = 1;
+ }
+
+ // Otherwise, timeout -> loop again.
+ }
+
+ return NULL;
+}
+
+static VALUE
+scheduler_blocking_loop(VALUE self, VALUE notify)
+{
+ struct blocking_state blocking_state = {
+ .notify_descriptor = rb_io_descriptor(notify),
+ .interrupted = 0,
+ };
+
+ while (true) {
+ blocking_state.interrupted = 0;
+
+ rb_thread_call_without_gvl(
+ blocking_operation, &blocking_state,
+ unblock_callback, &blocking_state
+ );
+
+ // The bug: When interrupted, loop retries without yielding to scheduler.
+ // With Thread.handle_interrupt(:never), this causes an infinite hang,
+ // because the deferred interrupt never gets a chance to be processed.
+ } while (blocking_state.interrupted);
+
+ return Qnil;
+}
+
+void
+Init_scheduler(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE mScheduler = rb_define_module_under(mBug, "Scheduler");
+
+ rb_define_module_function(mScheduler, "blocking_loop", scheduler_blocking_loop, 1);
+}
diff --git a/ext/-test-/st/foreach/depend b/ext/-test-/st/foreach/depend
new file mode 100644
index 0000000000..29aab2bb29
--- /dev/null
+++ b/ext/-test-/st/foreach/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+foreach.o: $(RUBY_EXTCONF_H)
+foreach.o: $(arch_hdrdir)/ruby/config.h
+foreach.o: $(hdrdir)/ruby.h
+foreach.o: $(hdrdir)/ruby/assert.h
+foreach.o: $(hdrdir)/ruby/backward.h
+foreach.o: $(hdrdir)/ruby/backward/2/assume.h
+foreach.o: $(hdrdir)/ruby/backward/2/attributes.h
+foreach.o: $(hdrdir)/ruby/backward/2/bool.h
+foreach.o: $(hdrdir)/ruby/backward/2/inttypes.h
+foreach.o: $(hdrdir)/ruby/backward/2/limits.h
+foreach.o: $(hdrdir)/ruby/backward/2/long_long.h
+foreach.o: $(hdrdir)/ruby/backward/2/stdalign.h
+foreach.o: $(hdrdir)/ruby/backward/2/stdarg.h
+foreach.o: $(hdrdir)/ruby/defines.h
+foreach.o: $(hdrdir)/ruby/intern.h
+foreach.o: $(hdrdir)/ruby/internal/abi.h
+foreach.o: $(hdrdir)/ruby/internal/anyargs.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+foreach.o: $(hdrdir)/ruby/internal/assume.h
+foreach.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+foreach.o: $(hdrdir)/ruby/internal/attr/artificial.h
+foreach.o: $(hdrdir)/ruby/internal/attr/cold.h
+foreach.o: $(hdrdir)/ruby/internal/attr/const.h
+foreach.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+foreach.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+foreach.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+foreach.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+foreach.o: $(hdrdir)/ruby/internal/attr/error.h
+foreach.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+foreach.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+foreach.o: $(hdrdir)/ruby/internal/attr/format.h
+foreach.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+foreach.o: $(hdrdir)/ruby/internal/attr/noalias.h
+foreach.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+foreach.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+foreach.o: $(hdrdir)/ruby/internal/attr/noinline.h
+foreach.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+foreach.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+foreach.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+foreach.o: $(hdrdir)/ruby/internal/attr/pure.h
+foreach.o: $(hdrdir)/ruby/internal/attr/restrict.h
+foreach.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+foreach.o: $(hdrdir)/ruby/internal/attr/warning.h
+foreach.o: $(hdrdir)/ruby/internal/attr/weakref.h
+foreach.o: $(hdrdir)/ruby/internal/cast.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_since.h
+foreach.o: $(hdrdir)/ruby/internal/config.h
+foreach.o: $(hdrdir)/ruby/internal/constant_p.h
+foreach.o: $(hdrdir)/ruby/internal/core.h
+foreach.o: $(hdrdir)/ruby/internal/core/rarray.h
+foreach.o: $(hdrdir)/ruby/internal/core/rbasic.h
+foreach.o: $(hdrdir)/ruby/internal/core/rbignum.h
+foreach.o: $(hdrdir)/ruby/internal/core/rclass.h
+foreach.o: $(hdrdir)/ruby/internal/core/rdata.h
+foreach.o: $(hdrdir)/ruby/internal/core/rfile.h
+foreach.o: $(hdrdir)/ruby/internal/core/rhash.h
+foreach.o: $(hdrdir)/ruby/internal/core/robject.h
+foreach.o: $(hdrdir)/ruby/internal/core/rregexp.h
+foreach.o: $(hdrdir)/ruby/internal/core/rstring.h
+foreach.o: $(hdrdir)/ruby/internal/core/rstruct.h
+foreach.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+foreach.o: $(hdrdir)/ruby/internal/ctype.h
+foreach.o: $(hdrdir)/ruby/internal/dllexport.h
+foreach.o: $(hdrdir)/ruby/internal/dosish.h
+foreach.o: $(hdrdir)/ruby/internal/error.h
+foreach.o: $(hdrdir)/ruby/internal/eval.h
+foreach.o: $(hdrdir)/ruby/internal/event.h
+foreach.o: $(hdrdir)/ruby/internal/fl_type.h
+foreach.o: $(hdrdir)/ruby/internal/gc.h
+foreach.o: $(hdrdir)/ruby/internal/glob.h
+foreach.o: $(hdrdir)/ruby/internal/globals.h
+foreach.o: $(hdrdir)/ruby/internal/has/attribute.h
+foreach.o: $(hdrdir)/ruby/internal/has/builtin.h
+foreach.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+foreach.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+foreach.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+foreach.o: $(hdrdir)/ruby/internal/has/extension.h
+foreach.o: $(hdrdir)/ruby/internal/has/feature.h
+foreach.o: $(hdrdir)/ruby/internal/has/warning.h
+foreach.o: $(hdrdir)/ruby/internal/intern/array.h
+foreach.o: $(hdrdir)/ruby/internal/intern/bignum.h
+foreach.o: $(hdrdir)/ruby/internal/intern/class.h
+foreach.o: $(hdrdir)/ruby/internal/intern/compar.h
+foreach.o: $(hdrdir)/ruby/internal/intern/complex.h
+foreach.o: $(hdrdir)/ruby/internal/intern/cont.h
+foreach.o: $(hdrdir)/ruby/internal/intern/dir.h
+foreach.o: $(hdrdir)/ruby/internal/intern/enum.h
+foreach.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+foreach.o: $(hdrdir)/ruby/internal/intern/error.h
+foreach.o: $(hdrdir)/ruby/internal/intern/eval.h
+foreach.o: $(hdrdir)/ruby/internal/intern/file.h
+foreach.o: $(hdrdir)/ruby/internal/intern/hash.h
+foreach.o: $(hdrdir)/ruby/internal/intern/io.h
+foreach.o: $(hdrdir)/ruby/internal/intern/load.h
+foreach.o: $(hdrdir)/ruby/internal/intern/marshal.h
+foreach.o: $(hdrdir)/ruby/internal/intern/numeric.h
+foreach.o: $(hdrdir)/ruby/internal/intern/object.h
+foreach.o: $(hdrdir)/ruby/internal/intern/parse.h
+foreach.o: $(hdrdir)/ruby/internal/intern/proc.h
+foreach.o: $(hdrdir)/ruby/internal/intern/process.h
+foreach.o: $(hdrdir)/ruby/internal/intern/random.h
+foreach.o: $(hdrdir)/ruby/internal/intern/range.h
+foreach.o: $(hdrdir)/ruby/internal/intern/rational.h
+foreach.o: $(hdrdir)/ruby/internal/intern/re.h
+foreach.o: $(hdrdir)/ruby/internal/intern/ruby.h
+foreach.o: $(hdrdir)/ruby/internal/intern/select.h
+foreach.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+foreach.o: $(hdrdir)/ruby/internal/intern/set.h
+foreach.o: $(hdrdir)/ruby/internal/intern/signal.h
+foreach.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+foreach.o: $(hdrdir)/ruby/internal/intern/string.h
+foreach.o: $(hdrdir)/ruby/internal/intern/struct.h
+foreach.o: $(hdrdir)/ruby/internal/intern/thread.h
+foreach.o: $(hdrdir)/ruby/internal/intern/time.h
+foreach.o: $(hdrdir)/ruby/internal/intern/variable.h
+foreach.o: $(hdrdir)/ruby/internal/intern/vm.h
+foreach.o: $(hdrdir)/ruby/internal/interpreter.h
+foreach.o: $(hdrdir)/ruby/internal/iterator.h
+foreach.o: $(hdrdir)/ruby/internal/memory.h
+foreach.o: $(hdrdir)/ruby/internal/method.h
+foreach.o: $(hdrdir)/ruby/internal/module.h
+foreach.o: $(hdrdir)/ruby/internal/newobj.h
+foreach.o: $(hdrdir)/ruby/internal/scan_args.h
+foreach.o: $(hdrdir)/ruby/internal/special_consts.h
+foreach.o: $(hdrdir)/ruby/internal/static_assert.h
+foreach.o: $(hdrdir)/ruby/internal/stdalign.h
+foreach.o: $(hdrdir)/ruby/internal/stdbool.h
+foreach.o: $(hdrdir)/ruby/internal/stdckdint.h
+foreach.o: $(hdrdir)/ruby/internal/symbol.h
+foreach.o: $(hdrdir)/ruby/internal/value.h
+foreach.o: $(hdrdir)/ruby/internal/value_type.h
+foreach.o: $(hdrdir)/ruby/internal/variable.h
+foreach.o: $(hdrdir)/ruby/internal/warning_push.h
+foreach.o: $(hdrdir)/ruby/internal/xmalloc.h
+foreach.o: $(hdrdir)/ruby/missing.h
+foreach.o: $(hdrdir)/ruby/ruby.h
+foreach.o: $(hdrdir)/ruby/st.h
+foreach.o: $(hdrdir)/ruby/subst.h
+foreach.o: foreach.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/st/foreach/extconf.rb b/ext/-test-/st/foreach/extconf.rb
new file mode 100644
index 0000000000..a7346203c4
--- /dev/null
+++ b/ext/-test-/st/foreach/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/st/foreach")
diff --git a/ext/-test-/st/foreach/foreach.c b/ext/-test-/st/foreach/foreach.c
new file mode 100644
index 0000000000..5c1bfd1631
--- /dev/null
+++ b/ext/-test-/st/foreach/foreach.c
@@ -0,0 +1,163 @@
+#include <ruby.h>
+#include <ruby/st.h>
+
+static st_data_t expect_size = 32;
+struct checker {
+ st_table *tbl;
+ st_index_t nr;
+ VALUE test;
+};
+
+static void
+force_unpack_check(struct checker *c, st_data_t key, st_data_t val)
+{
+ if (c->nr == 0) {
+ st_data_t i;
+
+ /* force unpacking during iteration: */
+ for (i = 1; i < expect_size; i++)
+ st_add_direct(c->tbl, i, i);
+ }
+
+ if (key != c->nr) {
+ rb_bug("unexpected key: %"PRIuVALUE" (expected %"PRIuVALUE")", (VALUE)key, (VALUE)c->nr);
+ }
+ if (val != c->nr) {
+ rb_bug("unexpected val: %"PRIuVALUE" (expected %"PRIuVALUE")", (VALUE)val, (VALUE)c->nr);
+ }
+
+ c->nr++;
+}
+
+static int
+unp_fec_i(st_data_t key, st_data_t val, st_data_t args, int error)
+{
+ struct checker *c = (struct checker *)args;
+
+ if (error) {
+ if (c->test == ID2SYM(rb_intern("delete2")))
+ return ST_STOP;
+
+ rb_bug("unexpected error");
+ }
+
+ force_unpack_check(c, key, val);
+
+ if (c->test == ID2SYM(rb_intern("check"))) {
+ return ST_CHECK;
+ }
+ if (c->test == ID2SYM(rb_intern("delete1"))) {
+ if (c->nr == 1) return ST_DELETE;
+ return ST_CHECK;
+ }
+ if (c->test == ID2SYM(rb_intern("delete2"))) {
+ if (c->nr == 1) {
+ st_data_t k = 0;
+ st_data_t v;
+
+ if (!st_delete(c->tbl, &k, &v)) {
+ rb_bug("failed to delete");
+ }
+ if (v != 0) {
+ rb_bug("unexpected value deleted: %"PRIuVALUE" (expected 0)", (VALUE)v);
+ }
+ }
+ return ST_CHECK;
+ }
+
+ rb_raise(rb_eArgError, "unexpected arg: %+"PRIsVALUE, c->test);
+}
+
+static VALUE
+unp_fec(VALUE self, VALUE test)
+{
+ st_table *tbl = st_init_numtable();
+ struct checker c;
+
+ c.tbl = tbl;
+ c.nr = 0;
+ c.test = test;
+
+ st_add_direct(tbl, 0, 0);
+
+ st_foreach_check(tbl, unp_fec_i, (st_data_t)&c, -1);
+
+ if (c.test == ID2SYM(rb_intern("delete2"))) {
+ if (c.nr != 1) {
+ rb_bug("mismatched iteration: %"PRIuVALUE" (expected 1)", (VALUE)c.nr);
+ }
+ }
+ else if (c.nr != expect_size) {
+ rb_bug("mismatched iteration: %"PRIuVALUE" (expected %"PRIuVALUE")",
+ (VALUE)c.nr, (VALUE)expect_size);
+ }
+
+ st_free_table(tbl);
+
+ return Qnil;
+}
+
+static int
+unp_fe_i(st_data_t key, st_data_t val, st_data_t args)
+{
+ struct checker *c = (struct checker *)args;
+
+ force_unpack_check(c, key, val);
+ if (c->test == ID2SYM(rb_intern("unpacked"))) {
+ return ST_CONTINUE;
+ }
+ else if (c->test == ID2SYM(rb_intern("unpack_delete"))) {
+ if (c->nr == 1) {
+ st_data_t k = 0;
+ st_data_t v;
+
+ if (!st_delete(c->tbl, &k, &v)) {
+ rb_bug("failed to delete");
+ }
+ if (v != 0) {
+ rb_bug("unexpected value deleted: %"PRIuVALUE" (expected 0)", (VALUE)v);
+ }
+ return ST_CONTINUE;
+ }
+ rb_bug("should never get here");
+ }
+
+ rb_raise(rb_eArgError, "unexpected arg: %+"PRIsVALUE, c->test);
+}
+
+static VALUE
+unp_fe(VALUE self, VALUE test)
+{
+ st_table *tbl = st_init_numtable();
+ struct checker c;
+
+ c.tbl = tbl;
+ c.nr = 0;
+ c.test = test;
+
+ st_add_direct(tbl, 0, 0);
+
+ st_foreach(tbl, unp_fe_i, (st_data_t)&c);
+
+ if (c.test == ID2SYM(rb_intern("unpack_delete"))) {
+ if (c.nr != 1) {
+ rb_bug("mismatched iteration: %"PRIuVALUE" (expected 1)", (VALUE)c.nr);
+ }
+ }
+ else if (c.nr != expect_size) {
+ rb_bug("mismatched iteration: %"PRIuVALUE" (expected %"PRIuVALUE"o)",
+ (VALUE)c.nr, (VALUE)expect_size);
+ }
+
+ st_free_table(tbl);
+
+ return Qnil;
+}
+
+void
+Init_foreach(void)
+{
+ VALUE bug = rb_define_module("Bug");
+ rb_define_singleton_method(bug, "unp_st_foreach_check", unp_fec, 1);
+ rb_define_singleton_method(bug, "unp_st_foreach", unp_fe, 1);
+}
diff --git a/ext/-test-/st/numhash/depend b/ext/-test-/st/numhash/depend
new file mode 100644
index 0000000000..18320d55f5
--- /dev/null
+++ b/ext/-test-/st/numhash/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+numhash.o: $(RUBY_EXTCONF_H)
+numhash.o: $(arch_hdrdir)/ruby/config.h
+numhash.o: $(hdrdir)/ruby.h
+numhash.o: $(hdrdir)/ruby/assert.h
+numhash.o: $(hdrdir)/ruby/backward.h
+numhash.o: $(hdrdir)/ruby/backward/2/assume.h
+numhash.o: $(hdrdir)/ruby/backward/2/attributes.h
+numhash.o: $(hdrdir)/ruby/backward/2/bool.h
+numhash.o: $(hdrdir)/ruby/backward/2/inttypes.h
+numhash.o: $(hdrdir)/ruby/backward/2/limits.h
+numhash.o: $(hdrdir)/ruby/backward/2/long_long.h
+numhash.o: $(hdrdir)/ruby/backward/2/stdalign.h
+numhash.o: $(hdrdir)/ruby/backward/2/stdarg.h
+numhash.o: $(hdrdir)/ruby/defines.h
+numhash.o: $(hdrdir)/ruby/intern.h
+numhash.o: $(hdrdir)/ruby/internal/abi.h
+numhash.o: $(hdrdir)/ruby/internal/anyargs.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+numhash.o: $(hdrdir)/ruby/internal/assume.h
+numhash.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+numhash.o: $(hdrdir)/ruby/internal/attr/artificial.h
+numhash.o: $(hdrdir)/ruby/internal/attr/cold.h
+numhash.o: $(hdrdir)/ruby/internal/attr/const.h
+numhash.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+numhash.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+numhash.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+numhash.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+numhash.o: $(hdrdir)/ruby/internal/attr/error.h
+numhash.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+numhash.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+numhash.o: $(hdrdir)/ruby/internal/attr/format.h
+numhash.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+numhash.o: $(hdrdir)/ruby/internal/attr/noalias.h
+numhash.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+numhash.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+numhash.o: $(hdrdir)/ruby/internal/attr/noinline.h
+numhash.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+numhash.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+numhash.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+numhash.o: $(hdrdir)/ruby/internal/attr/pure.h
+numhash.o: $(hdrdir)/ruby/internal/attr/restrict.h
+numhash.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+numhash.o: $(hdrdir)/ruby/internal/attr/warning.h
+numhash.o: $(hdrdir)/ruby/internal/attr/weakref.h
+numhash.o: $(hdrdir)/ruby/internal/cast.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_since.h
+numhash.o: $(hdrdir)/ruby/internal/config.h
+numhash.o: $(hdrdir)/ruby/internal/constant_p.h
+numhash.o: $(hdrdir)/ruby/internal/core.h
+numhash.o: $(hdrdir)/ruby/internal/core/rarray.h
+numhash.o: $(hdrdir)/ruby/internal/core/rbasic.h
+numhash.o: $(hdrdir)/ruby/internal/core/rbignum.h
+numhash.o: $(hdrdir)/ruby/internal/core/rclass.h
+numhash.o: $(hdrdir)/ruby/internal/core/rdata.h
+numhash.o: $(hdrdir)/ruby/internal/core/rfile.h
+numhash.o: $(hdrdir)/ruby/internal/core/rhash.h
+numhash.o: $(hdrdir)/ruby/internal/core/robject.h
+numhash.o: $(hdrdir)/ruby/internal/core/rregexp.h
+numhash.o: $(hdrdir)/ruby/internal/core/rstring.h
+numhash.o: $(hdrdir)/ruby/internal/core/rstruct.h
+numhash.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+numhash.o: $(hdrdir)/ruby/internal/ctype.h
+numhash.o: $(hdrdir)/ruby/internal/dllexport.h
+numhash.o: $(hdrdir)/ruby/internal/dosish.h
+numhash.o: $(hdrdir)/ruby/internal/error.h
+numhash.o: $(hdrdir)/ruby/internal/eval.h
+numhash.o: $(hdrdir)/ruby/internal/event.h
+numhash.o: $(hdrdir)/ruby/internal/fl_type.h
+numhash.o: $(hdrdir)/ruby/internal/gc.h
+numhash.o: $(hdrdir)/ruby/internal/glob.h
+numhash.o: $(hdrdir)/ruby/internal/globals.h
+numhash.o: $(hdrdir)/ruby/internal/has/attribute.h
+numhash.o: $(hdrdir)/ruby/internal/has/builtin.h
+numhash.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+numhash.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+numhash.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+numhash.o: $(hdrdir)/ruby/internal/has/extension.h
+numhash.o: $(hdrdir)/ruby/internal/has/feature.h
+numhash.o: $(hdrdir)/ruby/internal/has/warning.h
+numhash.o: $(hdrdir)/ruby/internal/intern/array.h
+numhash.o: $(hdrdir)/ruby/internal/intern/bignum.h
+numhash.o: $(hdrdir)/ruby/internal/intern/class.h
+numhash.o: $(hdrdir)/ruby/internal/intern/compar.h
+numhash.o: $(hdrdir)/ruby/internal/intern/complex.h
+numhash.o: $(hdrdir)/ruby/internal/intern/cont.h
+numhash.o: $(hdrdir)/ruby/internal/intern/dir.h
+numhash.o: $(hdrdir)/ruby/internal/intern/enum.h
+numhash.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+numhash.o: $(hdrdir)/ruby/internal/intern/error.h
+numhash.o: $(hdrdir)/ruby/internal/intern/eval.h
+numhash.o: $(hdrdir)/ruby/internal/intern/file.h
+numhash.o: $(hdrdir)/ruby/internal/intern/hash.h
+numhash.o: $(hdrdir)/ruby/internal/intern/io.h
+numhash.o: $(hdrdir)/ruby/internal/intern/load.h
+numhash.o: $(hdrdir)/ruby/internal/intern/marshal.h
+numhash.o: $(hdrdir)/ruby/internal/intern/numeric.h
+numhash.o: $(hdrdir)/ruby/internal/intern/object.h
+numhash.o: $(hdrdir)/ruby/internal/intern/parse.h
+numhash.o: $(hdrdir)/ruby/internal/intern/proc.h
+numhash.o: $(hdrdir)/ruby/internal/intern/process.h
+numhash.o: $(hdrdir)/ruby/internal/intern/random.h
+numhash.o: $(hdrdir)/ruby/internal/intern/range.h
+numhash.o: $(hdrdir)/ruby/internal/intern/rational.h
+numhash.o: $(hdrdir)/ruby/internal/intern/re.h
+numhash.o: $(hdrdir)/ruby/internal/intern/ruby.h
+numhash.o: $(hdrdir)/ruby/internal/intern/select.h
+numhash.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+numhash.o: $(hdrdir)/ruby/internal/intern/set.h
+numhash.o: $(hdrdir)/ruby/internal/intern/signal.h
+numhash.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+numhash.o: $(hdrdir)/ruby/internal/intern/string.h
+numhash.o: $(hdrdir)/ruby/internal/intern/struct.h
+numhash.o: $(hdrdir)/ruby/internal/intern/thread.h
+numhash.o: $(hdrdir)/ruby/internal/intern/time.h
+numhash.o: $(hdrdir)/ruby/internal/intern/variable.h
+numhash.o: $(hdrdir)/ruby/internal/intern/vm.h
+numhash.o: $(hdrdir)/ruby/internal/interpreter.h
+numhash.o: $(hdrdir)/ruby/internal/iterator.h
+numhash.o: $(hdrdir)/ruby/internal/memory.h
+numhash.o: $(hdrdir)/ruby/internal/method.h
+numhash.o: $(hdrdir)/ruby/internal/module.h
+numhash.o: $(hdrdir)/ruby/internal/newobj.h
+numhash.o: $(hdrdir)/ruby/internal/scan_args.h
+numhash.o: $(hdrdir)/ruby/internal/special_consts.h
+numhash.o: $(hdrdir)/ruby/internal/static_assert.h
+numhash.o: $(hdrdir)/ruby/internal/stdalign.h
+numhash.o: $(hdrdir)/ruby/internal/stdbool.h
+numhash.o: $(hdrdir)/ruby/internal/stdckdint.h
+numhash.o: $(hdrdir)/ruby/internal/symbol.h
+numhash.o: $(hdrdir)/ruby/internal/value.h
+numhash.o: $(hdrdir)/ruby/internal/value_type.h
+numhash.o: $(hdrdir)/ruby/internal/variable.h
+numhash.o: $(hdrdir)/ruby/internal/warning_push.h
+numhash.o: $(hdrdir)/ruby/internal/xmalloc.h
+numhash.o: $(hdrdir)/ruby/missing.h
+numhash.o: $(hdrdir)/ruby/ruby.h
+numhash.o: $(hdrdir)/ruby/st.h
+numhash.o: $(hdrdir)/ruby/subst.h
+numhash.o: numhash.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/st/numhash/extconf.rb b/ext/-test-/st/numhash/extconf.rb
new file mode 100644
index 0000000000..27d28a0a77
--- /dev/null
+++ b/ext/-test-/st/numhash/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/st/numhash")
diff --git a/ext/-test-/st/numhash/numhash.c b/ext/-test-/st/numhash/numhash.c
new file mode 100644
index 0000000000..7e8d5d9fe2
--- /dev/null
+++ b/ext/-test-/st/numhash/numhash.c
@@ -0,0 +1,137 @@
+#include <ruby.h>
+#include <ruby/st.h>
+
+static void
+numhash_free(void *ptr)
+{
+ if (ptr) st_free_table(ptr);
+}
+
+static size_t
+numhash_memsize(const void *ptr)
+{
+ return st_memsize(ptr);
+}
+
+static const rb_data_type_t numhash_type = {
+ "numhash",
+ {0, numhash_free, numhash_memsize,},
+ 0, 0,
+ RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED,
+};
+
+static VALUE
+numhash_alloc(VALUE klass)
+{
+ return TypedData_Wrap_Struct(klass, &numhash_type, 0);
+}
+
+static VALUE
+numhash_init(VALUE self)
+{
+ st_table *tbl = (st_table *)Check_TypedStruct(self, &numhash_type);
+ if (tbl) st_free_table(tbl);
+ DATA_PTR(self) = st_init_numtable();
+ return self;
+}
+
+static VALUE
+numhash_aref(VALUE self, VALUE key)
+{
+ st_data_t data;
+ st_table *tbl = (st_table *)Check_TypedStruct(self, &numhash_type);
+ if (!SPECIAL_CONST_P(key)) rb_raise(rb_eArgError, "not a special const");
+ if (st_lookup(tbl, (st_data_t)key, &data))
+ return (VALUE)data;
+ return Qnil;
+}
+
+static VALUE
+numhash_aset(VALUE self, VALUE key, VALUE data)
+{
+ st_table *tbl = (st_table *)Check_TypedStruct(self, &numhash_type);
+ if (!SPECIAL_CONST_P(key)) rb_raise(rb_eArgError, "not a special const");
+ if (!SPECIAL_CONST_P(data)) rb_raise(rb_eArgError, "not a special const");
+ st_insert(tbl, (st_data_t)key, (st_data_t)data);
+ return self;
+}
+
+static int
+numhash_i(st_data_t key, st_data_t value, st_data_t arg, int _)
+{
+ VALUE ret;
+ ret = rb_yield_values(3, (VALUE)key, (VALUE)value, (VALUE)arg);
+ if (ret == Qtrue) return ST_CHECK;
+ return ST_CONTINUE;
+}
+
+static VALUE
+numhash_each(VALUE self)
+{
+ st_table *table = (st_table *)Check_TypedStruct(self, &numhash_type);
+ st_data_t data = (st_data_t)self;
+ return st_foreach_check(table, numhash_i, data, data) ? Qtrue : Qfalse;
+}
+
+static int
+update_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
+{
+ VALUE ret = rb_yield_values(existing ? 2 : 1, (VALUE)*key, (VALUE)*value);
+ switch (ret) {
+ case Qfalse:
+ return ST_STOP;
+ case Qnil:
+ return ST_DELETE;
+ default:
+ *value = ret;
+ return ST_CONTINUE;
+ }
+}
+
+static VALUE
+numhash_update(VALUE self, VALUE key)
+{
+ st_table *table = (st_table *)Check_TypedStruct(self, &numhash_type);
+ if (st_update(table, (st_data_t)key, update_func, 0))
+ return Qtrue;
+ else
+ return Qfalse;
+}
+
+#if SIZEOF_LONG == SIZEOF_VOIDP
+# define ST2NUM(x) ULONG2NUM(x)
+#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
+# define ST2NUM(x) ULL2NUM(x)
+#endif
+
+static VALUE
+numhash_size(VALUE self)
+{
+ st_table *table = (st_table *)Check_TypedStruct(self, &numhash_type);
+ return ST2NUM(table->num_entries);
+}
+
+static VALUE
+numhash_delete_safe(VALUE self, VALUE key)
+{
+ st_table *table = (st_table *)Check_TypedStruct(self, &numhash_type);
+ st_data_t val, k = (st_data_t)key;
+ if (st_delete_safe(table, &k, &val, (st_data_t)self)) {
+ return val;
+ }
+ return Qnil;
+}
+
+void
+Init_numhash(void)
+{
+ VALUE st = rb_define_class_under(rb_define_module("Bug"), "StNumHash", rb_cObject);
+ rb_define_alloc_func(st, numhash_alloc);
+ rb_define_method(st, "initialize", numhash_init, 0);
+ rb_define_method(st, "[]", numhash_aref, 1);
+ rb_define_method(st, "[]=", numhash_aset, 2);
+ rb_define_method(st, "each", numhash_each, 0);
+ rb_define_method(st, "update", numhash_update, 1);
+ rb_define_method(st, "size", numhash_size, 0);
+ rb_define_method(st, "delete_safe", numhash_delete_safe, 1);
+}
diff --git a/ext/-test-/st/update/depend b/ext/-test-/st/update/depend
new file mode 100644
index 0000000000..247f0efd6b
--- /dev/null
+++ b/ext/-test-/st/update/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+update.o: $(RUBY_EXTCONF_H)
+update.o: $(arch_hdrdir)/ruby/config.h
+update.o: $(hdrdir)/ruby.h
+update.o: $(hdrdir)/ruby/assert.h
+update.o: $(hdrdir)/ruby/backward.h
+update.o: $(hdrdir)/ruby/backward/2/assume.h
+update.o: $(hdrdir)/ruby/backward/2/attributes.h
+update.o: $(hdrdir)/ruby/backward/2/bool.h
+update.o: $(hdrdir)/ruby/backward/2/inttypes.h
+update.o: $(hdrdir)/ruby/backward/2/limits.h
+update.o: $(hdrdir)/ruby/backward/2/long_long.h
+update.o: $(hdrdir)/ruby/backward/2/stdalign.h
+update.o: $(hdrdir)/ruby/backward/2/stdarg.h
+update.o: $(hdrdir)/ruby/defines.h
+update.o: $(hdrdir)/ruby/intern.h
+update.o: $(hdrdir)/ruby/internal/abi.h
+update.o: $(hdrdir)/ruby/internal/anyargs.h
+update.o: $(hdrdir)/ruby/internal/arithmetic.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+update.o: $(hdrdir)/ruby/internal/assume.h
+update.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+update.o: $(hdrdir)/ruby/internal/attr/artificial.h
+update.o: $(hdrdir)/ruby/internal/attr/cold.h
+update.o: $(hdrdir)/ruby/internal/attr/const.h
+update.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+update.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+update.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+update.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+update.o: $(hdrdir)/ruby/internal/attr/error.h
+update.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+update.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+update.o: $(hdrdir)/ruby/internal/attr/format.h
+update.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+update.o: $(hdrdir)/ruby/internal/attr/noalias.h
+update.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+update.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+update.o: $(hdrdir)/ruby/internal/attr/noinline.h
+update.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+update.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+update.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+update.o: $(hdrdir)/ruby/internal/attr/pure.h
+update.o: $(hdrdir)/ruby/internal/attr/restrict.h
+update.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+update.o: $(hdrdir)/ruby/internal/attr/warning.h
+update.o: $(hdrdir)/ruby/internal/attr/weakref.h
+update.o: $(hdrdir)/ruby/internal/cast.h
+update.o: $(hdrdir)/ruby/internal/compiler_is.h
+update.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+update.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+update.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+update.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+update.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+update.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+update.o: $(hdrdir)/ruby/internal/compiler_since.h
+update.o: $(hdrdir)/ruby/internal/config.h
+update.o: $(hdrdir)/ruby/internal/constant_p.h
+update.o: $(hdrdir)/ruby/internal/core.h
+update.o: $(hdrdir)/ruby/internal/core/rarray.h
+update.o: $(hdrdir)/ruby/internal/core/rbasic.h
+update.o: $(hdrdir)/ruby/internal/core/rbignum.h
+update.o: $(hdrdir)/ruby/internal/core/rclass.h
+update.o: $(hdrdir)/ruby/internal/core/rdata.h
+update.o: $(hdrdir)/ruby/internal/core/rfile.h
+update.o: $(hdrdir)/ruby/internal/core/rhash.h
+update.o: $(hdrdir)/ruby/internal/core/robject.h
+update.o: $(hdrdir)/ruby/internal/core/rregexp.h
+update.o: $(hdrdir)/ruby/internal/core/rstring.h
+update.o: $(hdrdir)/ruby/internal/core/rstruct.h
+update.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+update.o: $(hdrdir)/ruby/internal/ctype.h
+update.o: $(hdrdir)/ruby/internal/dllexport.h
+update.o: $(hdrdir)/ruby/internal/dosish.h
+update.o: $(hdrdir)/ruby/internal/error.h
+update.o: $(hdrdir)/ruby/internal/eval.h
+update.o: $(hdrdir)/ruby/internal/event.h
+update.o: $(hdrdir)/ruby/internal/fl_type.h
+update.o: $(hdrdir)/ruby/internal/gc.h
+update.o: $(hdrdir)/ruby/internal/glob.h
+update.o: $(hdrdir)/ruby/internal/globals.h
+update.o: $(hdrdir)/ruby/internal/has/attribute.h
+update.o: $(hdrdir)/ruby/internal/has/builtin.h
+update.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+update.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+update.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+update.o: $(hdrdir)/ruby/internal/has/extension.h
+update.o: $(hdrdir)/ruby/internal/has/feature.h
+update.o: $(hdrdir)/ruby/internal/has/warning.h
+update.o: $(hdrdir)/ruby/internal/intern/array.h
+update.o: $(hdrdir)/ruby/internal/intern/bignum.h
+update.o: $(hdrdir)/ruby/internal/intern/class.h
+update.o: $(hdrdir)/ruby/internal/intern/compar.h
+update.o: $(hdrdir)/ruby/internal/intern/complex.h
+update.o: $(hdrdir)/ruby/internal/intern/cont.h
+update.o: $(hdrdir)/ruby/internal/intern/dir.h
+update.o: $(hdrdir)/ruby/internal/intern/enum.h
+update.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+update.o: $(hdrdir)/ruby/internal/intern/error.h
+update.o: $(hdrdir)/ruby/internal/intern/eval.h
+update.o: $(hdrdir)/ruby/internal/intern/file.h
+update.o: $(hdrdir)/ruby/internal/intern/hash.h
+update.o: $(hdrdir)/ruby/internal/intern/io.h
+update.o: $(hdrdir)/ruby/internal/intern/load.h
+update.o: $(hdrdir)/ruby/internal/intern/marshal.h
+update.o: $(hdrdir)/ruby/internal/intern/numeric.h
+update.o: $(hdrdir)/ruby/internal/intern/object.h
+update.o: $(hdrdir)/ruby/internal/intern/parse.h
+update.o: $(hdrdir)/ruby/internal/intern/proc.h
+update.o: $(hdrdir)/ruby/internal/intern/process.h
+update.o: $(hdrdir)/ruby/internal/intern/random.h
+update.o: $(hdrdir)/ruby/internal/intern/range.h
+update.o: $(hdrdir)/ruby/internal/intern/rational.h
+update.o: $(hdrdir)/ruby/internal/intern/re.h
+update.o: $(hdrdir)/ruby/internal/intern/ruby.h
+update.o: $(hdrdir)/ruby/internal/intern/select.h
+update.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+update.o: $(hdrdir)/ruby/internal/intern/set.h
+update.o: $(hdrdir)/ruby/internal/intern/signal.h
+update.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+update.o: $(hdrdir)/ruby/internal/intern/string.h
+update.o: $(hdrdir)/ruby/internal/intern/struct.h
+update.o: $(hdrdir)/ruby/internal/intern/thread.h
+update.o: $(hdrdir)/ruby/internal/intern/time.h
+update.o: $(hdrdir)/ruby/internal/intern/variable.h
+update.o: $(hdrdir)/ruby/internal/intern/vm.h
+update.o: $(hdrdir)/ruby/internal/interpreter.h
+update.o: $(hdrdir)/ruby/internal/iterator.h
+update.o: $(hdrdir)/ruby/internal/memory.h
+update.o: $(hdrdir)/ruby/internal/method.h
+update.o: $(hdrdir)/ruby/internal/module.h
+update.o: $(hdrdir)/ruby/internal/newobj.h
+update.o: $(hdrdir)/ruby/internal/scan_args.h
+update.o: $(hdrdir)/ruby/internal/special_consts.h
+update.o: $(hdrdir)/ruby/internal/static_assert.h
+update.o: $(hdrdir)/ruby/internal/stdalign.h
+update.o: $(hdrdir)/ruby/internal/stdbool.h
+update.o: $(hdrdir)/ruby/internal/stdckdint.h
+update.o: $(hdrdir)/ruby/internal/symbol.h
+update.o: $(hdrdir)/ruby/internal/value.h
+update.o: $(hdrdir)/ruby/internal/value_type.h
+update.o: $(hdrdir)/ruby/internal/variable.h
+update.o: $(hdrdir)/ruby/internal/warning_push.h
+update.o: $(hdrdir)/ruby/internal/xmalloc.h
+update.o: $(hdrdir)/ruby/missing.h
+update.o: $(hdrdir)/ruby/ruby.h
+update.o: $(hdrdir)/ruby/st.h
+update.o: $(hdrdir)/ruby/subst.h
+update.o: update.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/st/update/extconf.rb b/ext/-test-/st/update/extconf.rb
new file mode 100644
index 0000000000..5152b24229
--- /dev/null
+++ b/ext/-test-/st/update/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/st/update")
diff --git a/ext/-test-/st/update/update.c b/ext/-test-/st/update/update.c
new file mode 100644
index 0000000000..ea7fab12e1
--- /dev/null
+++ b/ext/-test-/st/update/update.c
@@ -0,0 +1,34 @@
+#include <ruby.h>
+#include <ruby/st.h>
+
+static int
+update_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
+{
+ VALUE ret = rb_yield_values(existing ? 2 : 1, (VALUE)*key, (VALUE)*value);
+ switch (ret) {
+ case Qfalse:
+ return ST_STOP;
+ case Qnil:
+ return ST_DELETE;
+ default:
+ *value = ret;
+ return ST_CONTINUE;
+ }
+}
+
+static VALUE
+test_st_update(VALUE self, VALUE key)
+{
+ if (st_update(RHASH_TBL(self), (st_data_t)key, update_func, 0))
+ return Qtrue;
+ else
+ return Qfalse;
+}
+
+void
+Init_update(void)
+{
+ VALUE st = rb_define_class_under(rb_define_module("Bug"), "StTable", rb_cHash);
+ rb_define_method(st, "st_update", test_st_update, 1);
+}
+
diff --git a/ext/-test-/stack/depend b/ext/-test-/stack/depend
new file mode 100644
index 0000000000..77e93bb201
--- /dev/null
+++ b/ext/-test-/stack/depend
@@ -0,0 +1,179 @@
+# AUTOGENERATED DEPENDENCIES START
+stack.o: $(RUBY_EXTCONF_H)
+stack.o: $(arch_hdrdir)/ruby/config.h
+stack.o: $(hdrdir)/ruby.h
+stack.o: $(hdrdir)/ruby/assert.h
+stack.o: $(hdrdir)/ruby/backward.h
+stack.o: $(hdrdir)/ruby/backward/2/assume.h
+stack.o: $(hdrdir)/ruby/backward/2/attributes.h
+stack.o: $(hdrdir)/ruby/backward/2/bool.h
+stack.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+stack.o: $(hdrdir)/ruby/backward/2/inttypes.h
+stack.o: $(hdrdir)/ruby/backward/2/limits.h
+stack.o: $(hdrdir)/ruby/backward/2/long_long.h
+stack.o: $(hdrdir)/ruby/backward/2/stdalign.h
+stack.o: $(hdrdir)/ruby/backward/2/stdarg.h
+stack.o: $(hdrdir)/ruby/defines.h
+stack.o: $(hdrdir)/ruby/encoding.h
+stack.o: $(hdrdir)/ruby/intern.h
+stack.o: $(hdrdir)/ruby/internal/abi.h
+stack.o: $(hdrdir)/ruby/internal/anyargs.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+stack.o: $(hdrdir)/ruby/internal/assume.h
+stack.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+stack.o: $(hdrdir)/ruby/internal/attr/artificial.h
+stack.o: $(hdrdir)/ruby/internal/attr/cold.h
+stack.o: $(hdrdir)/ruby/internal/attr/const.h
+stack.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+stack.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+stack.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+stack.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+stack.o: $(hdrdir)/ruby/internal/attr/error.h
+stack.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+stack.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+stack.o: $(hdrdir)/ruby/internal/attr/format.h
+stack.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+stack.o: $(hdrdir)/ruby/internal/attr/noalias.h
+stack.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+stack.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+stack.o: $(hdrdir)/ruby/internal/attr/noinline.h
+stack.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+stack.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+stack.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+stack.o: $(hdrdir)/ruby/internal/attr/pure.h
+stack.o: $(hdrdir)/ruby/internal/attr/restrict.h
+stack.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+stack.o: $(hdrdir)/ruby/internal/attr/warning.h
+stack.o: $(hdrdir)/ruby/internal/attr/weakref.h
+stack.o: $(hdrdir)/ruby/internal/cast.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+stack.o: $(hdrdir)/ruby/internal/compiler_since.h
+stack.o: $(hdrdir)/ruby/internal/config.h
+stack.o: $(hdrdir)/ruby/internal/constant_p.h
+stack.o: $(hdrdir)/ruby/internal/core.h
+stack.o: $(hdrdir)/ruby/internal/core/rarray.h
+stack.o: $(hdrdir)/ruby/internal/core/rbasic.h
+stack.o: $(hdrdir)/ruby/internal/core/rbignum.h
+stack.o: $(hdrdir)/ruby/internal/core/rclass.h
+stack.o: $(hdrdir)/ruby/internal/core/rdata.h
+stack.o: $(hdrdir)/ruby/internal/core/rfile.h
+stack.o: $(hdrdir)/ruby/internal/core/rhash.h
+stack.o: $(hdrdir)/ruby/internal/core/robject.h
+stack.o: $(hdrdir)/ruby/internal/core/rregexp.h
+stack.o: $(hdrdir)/ruby/internal/core/rstring.h
+stack.o: $(hdrdir)/ruby/internal/core/rstruct.h
+stack.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+stack.o: $(hdrdir)/ruby/internal/ctype.h
+stack.o: $(hdrdir)/ruby/internal/dllexport.h
+stack.o: $(hdrdir)/ruby/internal/dosish.h
+stack.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+stack.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+stack.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+stack.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+stack.o: $(hdrdir)/ruby/internal/encoding/re.h
+stack.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+stack.o: $(hdrdir)/ruby/internal/encoding/string.h
+stack.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+stack.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+stack.o: $(hdrdir)/ruby/internal/error.h
+stack.o: $(hdrdir)/ruby/internal/eval.h
+stack.o: $(hdrdir)/ruby/internal/event.h
+stack.o: $(hdrdir)/ruby/internal/fl_type.h
+stack.o: $(hdrdir)/ruby/internal/gc.h
+stack.o: $(hdrdir)/ruby/internal/glob.h
+stack.o: $(hdrdir)/ruby/internal/globals.h
+stack.o: $(hdrdir)/ruby/internal/has/attribute.h
+stack.o: $(hdrdir)/ruby/internal/has/builtin.h
+stack.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+stack.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+stack.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+stack.o: $(hdrdir)/ruby/internal/has/extension.h
+stack.o: $(hdrdir)/ruby/internal/has/feature.h
+stack.o: $(hdrdir)/ruby/internal/has/warning.h
+stack.o: $(hdrdir)/ruby/internal/intern/array.h
+stack.o: $(hdrdir)/ruby/internal/intern/bignum.h
+stack.o: $(hdrdir)/ruby/internal/intern/class.h
+stack.o: $(hdrdir)/ruby/internal/intern/compar.h
+stack.o: $(hdrdir)/ruby/internal/intern/complex.h
+stack.o: $(hdrdir)/ruby/internal/intern/cont.h
+stack.o: $(hdrdir)/ruby/internal/intern/dir.h
+stack.o: $(hdrdir)/ruby/internal/intern/enum.h
+stack.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+stack.o: $(hdrdir)/ruby/internal/intern/error.h
+stack.o: $(hdrdir)/ruby/internal/intern/eval.h
+stack.o: $(hdrdir)/ruby/internal/intern/file.h
+stack.o: $(hdrdir)/ruby/internal/intern/hash.h
+stack.o: $(hdrdir)/ruby/internal/intern/io.h
+stack.o: $(hdrdir)/ruby/internal/intern/load.h
+stack.o: $(hdrdir)/ruby/internal/intern/marshal.h
+stack.o: $(hdrdir)/ruby/internal/intern/numeric.h
+stack.o: $(hdrdir)/ruby/internal/intern/object.h
+stack.o: $(hdrdir)/ruby/internal/intern/parse.h
+stack.o: $(hdrdir)/ruby/internal/intern/proc.h
+stack.o: $(hdrdir)/ruby/internal/intern/process.h
+stack.o: $(hdrdir)/ruby/internal/intern/random.h
+stack.o: $(hdrdir)/ruby/internal/intern/range.h
+stack.o: $(hdrdir)/ruby/internal/intern/rational.h
+stack.o: $(hdrdir)/ruby/internal/intern/re.h
+stack.o: $(hdrdir)/ruby/internal/intern/ruby.h
+stack.o: $(hdrdir)/ruby/internal/intern/select.h
+stack.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+stack.o: $(hdrdir)/ruby/internal/intern/set.h
+stack.o: $(hdrdir)/ruby/internal/intern/signal.h
+stack.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+stack.o: $(hdrdir)/ruby/internal/intern/string.h
+stack.o: $(hdrdir)/ruby/internal/intern/struct.h
+stack.o: $(hdrdir)/ruby/internal/intern/thread.h
+stack.o: $(hdrdir)/ruby/internal/intern/time.h
+stack.o: $(hdrdir)/ruby/internal/intern/variable.h
+stack.o: $(hdrdir)/ruby/internal/intern/vm.h
+stack.o: $(hdrdir)/ruby/internal/interpreter.h
+stack.o: $(hdrdir)/ruby/internal/iterator.h
+stack.o: $(hdrdir)/ruby/internal/memory.h
+stack.o: $(hdrdir)/ruby/internal/method.h
+stack.o: $(hdrdir)/ruby/internal/module.h
+stack.o: $(hdrdir)/ruby/internal/newobj.h
+stack.o: $(hdrdir)/ruby/internal/scan_args.h
+stack.o: $(hdrdir)/ruby/internal/special_consts.h
+stack.o: $(hdrdir)/ruby/internal/static_assert.h
+stack.o: $(hdrdir)/ruby/internal/stdalign.h
+stack.o: $(hdrdir)/ruby/internal/stdbool.h
+stack.o: $(hdrdir)/ruby/internal/stdckdint.h
+stack.o: $(hdrdir)/ruby/internal/symbol.h
+stack.o: $(hdrdir)/ruby/internal/value.h
+stack.o: $(hdrdir)/ruby/internal/value_type.h
+stack.o: $(hdrdir)/ruby/internal/variable.h
+stack.o: $(hdrdir)/ruby/internal/warning_push.h
+stack.o: $(hdrdir)/ruby/internal/xmalloc.h
+stack.o: $(hdrdir)/ruby/missing.h
+stack.o: $(hdrdir)/ruby/onigmo.h
+stack.o: $(hdrdir)/ruby/oniguruma.h
+stack.o: $(hdrdir)/ruby/ruby.h
+stack.o: $(hdrdir)/ruby/st.h
+stack.o: $(hdrdir)/ruby/subst.h
+stack.o: $(top_srcdir)/encindex.h
+stack.o: $(top_srcdir)/internal/compilers.h
+stack.o: $(top_srcdir)/internal/string.h
+stack.o: stack.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/stack/extconf.rb b/ext/-test-/stack/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/stack/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/stack/stack.c b/ext/-test-/stack/stack.c
new file mode 100644
index 0000000000..f0e65e74b2
--- /dev/null
+++ b/ext/-test-/stack/stack.c
@@ -0,0 +1,35 @@
+#include "ruby.h"
+#include "internal/string.h"
+
+static VALUE
+stack_overflow(VALUE self)
+{
+ size_t i = 0;
+
+ while (1) {
+ // Allocate and touch memory to force actual stack usage:
+ volatile char *stack = alloca(1024);
+ stack[0] = (char)i;
+ stack[1023] = (char)i;
+ i++;
+ }
+
+ return Qnil;
+}
+
+static VALUE
+asan_p(VALUE klass)
+{
+#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
+ return Qtrue;
+#else
+ return Qfalse;
+#endif
+}
+
+void
+Init_stack(VALUE klass)
+{
+ rb_define_singleton_method(rb_cThread, "stack_overflow", stack_overflow, 0);
+ rb_define_singleton_method(rb_cThread, "asan?", asan_p, 0);
+}
diff --git a/ext/-test-/string/capacity.c b/ext/-test-/string/capacity.c
new file mode 100644
index 0000000000..33b2023fd3
--- /dev/null
+++ b/ext/-test-/string/capacity.c
@@ -0,0 +1,18 @@
+#include "ruby.h"
+#include "internal/string.h"
+
+static VALUE
+bug_str_capacity(VALUE klass, VALUE str)
+{
+ if (!STR_EMBED_P(str) && STR_SHARED_P(str)) {
+ return INT2FIX(0);
+ }
+
+ return LONG2FIX(rb_str_capacity(str));
+}
+
+void
+Init_string_capacity(VALUE klass)
+{
+ rb_define_singleton_method(klass, "capacity", bug_str_capacity, 1);
+}
diff --git a/ext/-test-/string/coderange.c b/ext/-test-/string/coderange.c
new file mode 100644
index 0000000000..4197ecca9f
--- /dev/null
+++ b/ext/-test-/string/coderange.c
@@ -0,0 +1,47 @@
+#include "ruby/ruby.h"
+#include "ruby/encoding.h"
+
+static VALUE sym_7bit, sym_valid, sym_unknown, sym_broken;
+
+static VALUE
+coderange_int2sym(int coderange)
+{
+ switch (coderange) {
+ case ENC_CODERANGE_7BIT:
+ return sym_7bit;
+ case ENC_CODERANGE_VALID:
+ return sym_valid;
+ case ENC_CODERANGE_UNKNOWN:
+ return sym_unknown;
+ case ENC_CODERANGE_BROKEN:
+ return sym_broken;
+ }
+ rb_bug("wrong condition of coderange");
+ UNREACHABLE_RETURN(Qnil);
+}
+
+/* return coderange without scan */
+static VALUE
+str_coderange(VALUE str)
+{
+ return coderange_int2sym(ENC_CODERANGE(str));
+}
+
+/* scan coderange and return the result */
+static VALUE
+str_coderange_scan(VALUE str)
+{
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_UNKNOWN);
+ return coderange_int2sym(rb_enc_str_coderange(str));
+}
+
+void
+Init_string_coderange(VALUE klass)
+{
+ sym_7bit = ID2SYM(rb_intern_const("7bit"));
+ sym_valid = ID2SYM(rb_intern_const("valid"));
+ sym_unknown = ID2SYM(rb_intern_const("unknown"));
+ sym_broken = ID2SYM(rb_intern_const("broken"));
+ rb_define_method(klass, "coderange", str_coderange, 0);
+ rb_define_method(klass, "coderange_scan", str_coderange_scan, 0);
+}
diff --git a/ext/-test-/string/cstr.c b/ext/-test-/string/cstr.c
new file mode 100644
index 0000000000..931220b46b
--- /dev/null
+++ b/ext/-test-/string/cstr.c
@@ -0,0 +1,147 @@
+#include "internal.h"
+#include "internal/string.h"
+#include "ruby/encoding.h"
+
+static VALUE
+bug_str_cstr_term(VALUE str)
+{
+ long len;
+ char *s;
+ int c;
+ rb_encoding *enc;
+
+ len = RSTRING_LEN(str);
+ s = StringValueCStr(str);
+ rb_gc();
+ enc = rb_enc_get(str);
+ c = rb_enc_codepoint(&s[len], &s[len+rb_enc_mbminlen(enc)], enc);
+ return INT2NUM(c);
+}
+
+static VALUE
+bug_str_cstr_unterm(VALUE str, VALUE c)
+{
+ long len;
+
+ rb_str_modify(str);
+ len = RSTRING_LEN(str);
+ RSTRING_PTR(str)[len] = NUM2CHR(c);
+ return str;
+}
+
+static VALUE
+bug_str_cstr_term_char(VALUE str)
+{
+ long len;
+ char *s;
+ int c;
+ rb_encoding *enc = rb_enc_get(str);
+
+ RSTRING_GETMEM(str, s, len);
+ s += len;
+ len = rb_enc_mbminlen(enc);
+ c = rb_enc_precise_mbclen(s, s + len, enc);
+ if (!MBCLEN_CHARFOUND_P(c)) {
+ c = (unsigned char)*s;
+ }
+ else {
+ c = rb_enc_mbc_to_codepoint(s, s + len, enc);
+ if (!c) return Qnil;
+ }
+ return rb_enc_uint_chr((unsigned int)c, enc);
+}
+
+static VALUE
+bug_str_unterminated_substring(VALUE str, VALUE vbeg, VALUE vlen)
+{
+ long beg = NUM2LONG(vbeg);
+ long len = NUM2LONG(vlen);
+ rb_str_modify(str);
+ if (len < 0) rb_raise(rb_eArgError, "negative length: %ld", len);
+ if (RSTRING_LEN(str) < beg) rb_raise(rb_eIndexError, "beg: %ld", beg);
+ if (RSTRING_LEN(str) < beg + len) rb_raise(rb_eIndexError, "end: %ld", beg + len);
+ str = rb_str_new_shared(str);
+ RSTRING(str)->len = len;
+ if (STR_EMBED_P(str)) {
+ memmove(RSTRING(str)->as.embed.ary, RSTRING(str)->as.embed.ary + beg, len);
+ }
+ else {
+ RSTRING(str)->as.heap.ptr += beg;
+ }
+ return str;
+}
+
+static VALUE
+bug_str_s_cstr_term(VALUE self, VALUE str)
+{
+ Check_Type(str, T_STRING);
+ return bug_str_cstr_term(str);
+}
+
+static VALUE
+bug_str_s_cstr_unterm(VALUE self, VALUE str, VALUE c)
+{
+ Check_Type(str, T_STRING);
+ return bug_str_cstr_unterm(str, c);
+}
+
+static VALUE
+bug_str_s_cstr_term_char(VALUE self, VALUE str)
+{
+ Check_Type(str, T_STRING);
+ return bug_str_cstr_term_char(str);
+}
+
+#define TERM_LEN(str) rb_enc_mbminlen(rb_enc_get(str))
+#define TERM_FILL(ptr, termlen) do {\
+ char *const term_fill_ptr = (ptr);\
+ const int term_fill_len = (termlen);\
+ *term_fill_ptr = '\0';\
+ if (UNLIKELY(term_fill_len > 1))\
+ memset(term_fill_ptr, 0, term_fill_len);\
+} while (0)
+
+static VALUE
+bug_str_s_cstr_noembed(VALUE self, VALUE str)
+{
+ VALUE str2 = rb_str_new(NULL, 0);
+ long capacity = RSTRING_LEN(str) + TERM_LEN(str);
+ char *buf = ALLOC_N(char, capacity);
+ Check_Type(str, T_STRING);
+ FL_SET((str2), STR_NOEMBED);
+ memcpy(buf, RSTRING_PTR(str), capacity);
+ RBASIC(str2)->flags &= ~(STR_SHARED | FL_USER5 | FL_USER6);
+ RSTRING(str2)->as.heap.aux.capa = RSTRING_LEN(str);
+ RSTRING(str2)->as.heap.ptr = buf;
+ RSTRING(str2)->len = RSTRING_LEN(str);
+
+ TERM_FILL(RSTRING_END(str2), TERM_LEN(str));
+ return str2;
+}
+
+static VALUE
+bug_str_s_cstr_embedded_p(VALUE self, VALUE str)
+{
+ return STR_EMBED_P(str) ? Qtrue : Qfalse;
+}
+
+static VALUE
+bug_str_s_rb_str_new_frozen(VALUE self, VALUE str)
+{
+ return rb_str_new_frozen(str);
+}
+
+void
+Init_string_cstr(VALUE klass)
+{
+ rb_define_method(klass, "cstr_term", bug_str_cstr_term, 0);
+ rb_define_method(klass, "cstr_unterm", bug_str_cstr_unterm, 1);
+ rb_define_method(klass, "cstr_term_char", bug_str_cstr_term_char, 0);
+ rb_define_method(klass, "unterminated_substring", bug_str_unterminated_substring, 2);
+ rb_define_singleton_method(klass, "cstr_term", bug_str_s_cstr_term, 1);
+ rb_define_singleton_method(klass, "cstr_unterm", bug_str_s_cstr_unterm, 2);
+ rb_define_singleton_method(klass, "cstr_term_char", bug_str_s_cstr_term_char, 1);
+ rb_define_singleton_method(klass, "cstr_noembed", bug_str_s_cstr_noembed, 1);
+ rb_define_singleton_method(klass, "cstr_embedded?", bug_str_s_cstr_embedded_p, 1);
+ rb_define_singleton_method(klass, "rb_str_new_frozen", bug_str_s_rb_str_new_frozen, 1);
+}
diff --git a/ext/-test-/string/depend b/ext/-test-/string/depend
new file mode 100644
index 0000000000..478ae3b82b
--- /dev/null
+++ b/ext/-test-/string/depend
@@ -0,0 +1,3030 @@
+# AUTOGENERATED DEPENDENCIES START
+capacity.o: $(RUBY_EXTCONF_H)
+capacity.o: $(arch_hdrdir)/ruby/config.h
+capacity.o: $(hdrdir)/ruby.h
+capacity.o: $(hdrdir)/ruby/assert.h
+capacity.o: $(hdrdir)/ruby/backward.h
+capacity.o: $(hdrdir)/ruby/backward/2/assume.h
+capacity.o: $(hdrdir)/ruby/backward/2/attributes.h
+capacity.o: $(hdrdir)/ruby/backward/2/bool.h
+capacity.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+capacity.o: $(hdrdir)/ruby/backward/2/inttypes.h
+capacity.o: $(hdrdir)/ruby/backward/2/limits.h
+capacity.o: $(hdrdir)/ruby/backward/2/long_long.h
+capacity.o: $(hdrdir)/ruby/backward/2/stdalign.h
+capacity.o: $(hdrdir)/ruby/backward/2/stdarg.h
+capacity.o: $(hdrdir)/ruby/defines.h
+capacity.o: $(hdrdir)/ruby/encoding.h
+capacity.o: $(hdrdir)/ruby/intern.h
+capacity.o: $(hdrdir)/ruby/internal/abi.h
+capacity.o: $(hdrdir)/ruby/internal/anyargs.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+capacity.o: $(hdrdir)/ruby/internal/assume.h
+capacity.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+capacity.o: $(hdrdir)/ruby/internal/attr/artificial.h
+capacity.o: $(hdrdir)/ruby/internal/attr/cold.h
+capacity.o: $(hdrdir)/ruby/internal/attr/const.h
+capacity.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+capacity.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+capacity.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+capacity.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+capacity.o: $(hdrdir)/ruby/internal/attr/error.h
+capacity.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+capacity.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+capacity.o: $(hdrdir)/ruby/internal/attr/format.h
+capacity.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+capacity.o: $(hdrdir)/ruby/internal/attr/noalias.h
+capacity.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+capacity.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+capacity.o: $(hdrdir)/ruby/internal/attr/noinline.h
+capacity.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+capacity.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+capacity.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+capacity.o: $(hdrdir)/ruby/internal/attr/pure.h
+capacity.o: $(hdrdir)/ruby/internal/attr/restrict.h
+capacity.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+capacity.o: $(hdrdir)/ruby/internal/attr/warning.h
+capacity.o: $(hdrdir)/ruby/internal/attr/weakref.h
+capacity.o: $(hdrdir)/ruby/internal/cast.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_since.h
+capacity.o: $(hdrdir)/ruby/internal/config.h
+capacity.o: $(hdrdir)/ruby/internal/constant_p.h
+capacity.o: $(hdrdir)/ruby/internal/core.h
+capacity.o: $(hdrdir)/ruby/internal/core/rarray.h
+capacity.o: $(hdrdir)/ruby/internal/core/rbasic.h
+capacity.o: $(hdrdir)/ruby/internal/core/rbignum.h
+capacity.o: $(hdrdir)/ruby/internal/core/rclass.h
+capacity.o: $(hdrdir)/ruby/internal/core/rdata.h
+capacity.o: $(hdrdir)/ruby/internal/core/rfile.h
+capacity.o: $(hdrdir)/ruby/internal/core/rhash.h
+capacity.o: $(hdrdir)/ruby/internal/core/robject.h
+capacity.o: $(hdrdir)/ruby/internal/core/rregexp.h
+capacity.o: $(hdrdir)/ruby/internal/core/rstring.h
+capacity.o: $(hdrdir)/ruby/internal/core/rstruct.h
+capacity.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+capacity.o: $(hdrdir)/ruby/internal/ctype.h
+capacity.o: $(hdrdir)/ruby/internal/dllexport.h
+capacity.o: $(hdrdir)/ruby/internal/dosish.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/re.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/string.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+capacity.o: $(hdrdir)/ruby/internal/error.h
+capacity.o: $(hdrdir)/ruby/internal/eval.h
+capacity.o: $(hdrdir)/ruby/internal/event.h
+capacity.o: $(hdrdir)/ruby/internal/fl_type.h
+capacity.o: $(hdrdir)/ruby/internal/gc.h
+capacity.o: $(hdrdir)/ruby/internal/glob.h
+capacity.o: $(hdrdir)/ruby/internal/globals.h
+capacity.o: $(hdrdir)/ruby/internal/has/attribute.h
+capacity.o: $(hdrdir)/ruby/internal/has/builtin.h
+capacity.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+capacity.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+capacity.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+capacity.o: $(hdrdir)/ruby/internal/has/extension.h
+capacity.o: $(hdrdir)/ruby/internal/has/feature.h
+capacity.o: $(hdrdir)/ruby/internal/has/warning.h
+capacity.o: $(hdrdir)/ruby/internal/intern/array.h
+capacity.o: $(hdrdir)/ruby/internal/intern/bignum.h
+capacity.o: $(hdrdir)/ruby/internal/intern/class.h
+capacity.o: $(hdrdir)/ruby/internal/intern/compar.h
+capacity.o: $(hdrdir)/ruby/internal/intern/complex.h
+capacity.o: $(hdrdir)/ruby/internal/intern/cont.h
+capacity.o: $(hdrdir)/ruby/internal/intern/dir.h
+capacity.o: $(hdrdir)/ruby/internal/intern/enum.h
+capacity.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+capacity.o: $(hdrdir)/ruby/internal/intern/error.h
+capacity.o: $(hdrdir)/ruby/internal/intern/eval.h
+capacity.o: $(hdrdir)/ruby/internal/intern/file.h
+capacity.o: $(hdrdir)/ruby/internal/intern/hash.h
+capacity.o: $(hdrdir)/ruby/internal/intern/io.h
+capacity.o: $(hdrdir)/ruby/internal/intern/load.h
+capacity.o: $(hdrdir)/ruby/internal/intern/marshal.h
+capacity.o: $(hdrdir)/ruby/internal/intern/numeric.h
+capacity.o: $(hdrdir)/ruby/internal/intern/object.h
+capacity.o: $(hdrdir)/ruby/internal/intern/parse.h
+capacity.o: $(hdrdir)/ruby/internal/intern/proc.h
+capacity.o: $(hdrdir)/ruby/internal/intern/process.h
+capacity.o: $(hdrdir)/ruby/internal/intern/random.h
+capacity.o: $(hdrdir)/ruby/internal/intern/range.h
+capacity.o: $(hdrdir)/ruby/internal/intern/rational.h
+capacity.o: $(hdrdir)/ruby/internal/intern/re.h
+capacity.o: $(hdrdir)/ruby/internal/intern/ruby.h
+capacity.o: $(hdrdir)/ruby/internal/intern/select.h
+capacity.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+capacity.o: $(hdrdir)/ruby/internal/intern/set.h
+capacity.o: $(hdrdir)/ruby/internal/intern/signal.h
+capacity.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+capacity.o: $(hdrdir)/ruby/internal/intern/string.h
+capacity.o: $(hdrdir)/ruby/internal/intern/struct.h
+capacity.o: $(hdrdir)/ruby/internal/intern/thread.h
+capacity.o: $(hdrdir)/ruby/internal/intern/time.h
+capacity.o: $(hdrdir)/ruby/internal/intern/variable.h
+capacity.o: $(hdrdir)/ruby/internal/intern/vm.h
+capacity.o: $(hdrdir)/ruby/internal/interpreter.h
+capacity.o: $(hdrdir)/ruby/internal/iterator.h
+capacity.o: $(hdrdir)/ruby/internal/memory.h
+capacity.o: $(hdrdir)/ruby/internal/method.h
+capacity.o: $(hdrdir)/ruby/internal/module.h
+capacity.o: $(hdrdir)/ruby/internal/newobj.h
+capacity.o: $(hdrdir)/ruby/internal/scan_args.h
+capacity.o: $(hdrdir)/ruby/internal/special_consts.h
+capacity.o: $(hdrdir)/ruby/internal/static_assert.h
+capacity.o: $(hdrdir)/ruby/internal/stdalign.h
+capacity.o: $(hdrdir)/ruby/internal/stdbool.h
+capacity.o: $(hdrdir)/ruby/internal/stdckdint.h
+capacity.o: $(hdrdir)/ruby/internal/symbol.h
+capacity.o: $(hdrdir)/ruby/internal/value.h
+capacity.o: $(hdrdir)/ruby/internal/value_type.h
+capacity.o: $(hdrdir)/ruby/internal/variable.h
+capacity.o: $(hdrdir)/ruby/internal/warning_push.h
+capacity.o: $(hdrdir)/ruby/internal/xmalloc.h
+capacity.o: $(hdrdir)/ruby/missing.h
+capacity.o: $(hdrdir)/ruby/onigmo.h
+capacity.o: $(hdrdir)/ruby/oniguruma.h
+capacity.o: $(hdrdir)/ruby/ruby.h
+capacity.o: $(hdrdir)/ruby/st.h
+capacity.o: $(hdrdir)/ruby/subst.h
+capacity.o: $(top_srcdir)/encindex.h
+capacity.o: $(top_srcdir)/internal/compilers.h
+capacity.o: $(top_srcdir)/internal/string.h
+capacity.o: capacity.c
+chilled.o: $(RUBY_EXTCONF_H)
+chilled.o: $(arch_hdrdir)/ruby/config.h
+chilled.o: $(hdrdir)/ruby.h
+chilled.o: $(hdrdir)/ruby/assert.h
+chilled.o: $(hdrdir)/ruby/backward.h
+chilled.o: $(hdrdir)/ruby/backward/2/assume.h
+chilled.o: $(hdrdir)/ruby/backward/2/attributes.h
+chilled.o: $(hdrdir)/ruby/backward/2/bool.h
+chilled.o: $(hdrdir)/ruby/backward/2/inttypes.h
+chilled.o: $(hdrdir)/ruby/backward/2/limits.h
+chilled.o: $(hdrdir)/ruby/backward/2/long_long.h
+chilled.o: $(hdrdir)/ruby/backward/2/stdalign.h
+chilled.o: $(hdrdir)/ruby/backward/2/stdarg.h
+chilled.o: $(hdrdir)/ruby/defines.h
+chilled.o: $(hdrdir)/ruby/intern.h
+chilled.o: $(hdrdir)/ruby/internal/abi.h
+chilled.o: $(hdrdir)/ruby/internal/anyargs.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+chilled.o: $(hdrdir)/ruby/internal/assume.h
+chilled.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+chilled.o: $(hdrdir)/ruby/internal/attr/artificial.h
+chilled.o: $(hdrdir)/ruby/internal/attr/cold.h
+chilled.o: $(hdrdir)/ruby/internal/attr/const.h
+chilled.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+chilled.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+chilled.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+chilled.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+chilled.o: $(hdrdir)/ruby/internal/attr/error.h
+chilled.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+chilled.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+chilled.o: $(hdrdir)/ruby/internal/attr/format.h
+chilled.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+chilled.o: $(hdrdir)/ruby/internal/attr/noalias.h
+chilled.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+chilled.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+chilled.o: $(hdrdir)/ruby/internal/attr/noinline.h
+chilled.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+chilled.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+chilled.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+chilled.o: $(hdrdir)/ruby/internal/attr/pure.h
+chilled.o: $(hdrdir)/ruby/internal/attr/restrict.h
+chilled.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+chilled.o: $(hdrdir)/ruby/internal/attr/warning.h
+chilled.o: $(hdrdir)/ruby/internal/attr/weakref.h
+chilled.o: $(hdrdir)/ruby/internal/cast.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_since.h
+chilled.o: $(hdrdir)/ruby/internal/config.h
+chilled.o: $(hdrdir)/ruby/internal/constant_p.h
+chilled.o: $(hdrdir)/ruby/internal/core.h
+chilled.o: $(hdrdir)/ruby/internal/core/rarray.h
+chilled.o: $(hdrdir)/ruby/internal/core/rbasic.h
+chilled.o: $(hdrdir)/ruby/internal/core/rbignum.h
+chilled.o: $(hdrdir)/ruby/internal/core/rclass.h
+chilled.o: $(hdrdir)/ruby/internal/core/rdata.h
+chilled.o: $(hdrdir)/ruby/internal/core/rfile.h
+chilled.o: $(hdrdir)/ruby/internal/core/rhash.h
+chilled.o: $(hdrdir)/ruby/internal/core/robject.h
+chilled.o: $(hdrdir)/ruby/internal/core/rregexp.h
+chilled.o: $(hdrdir)/ruby/internal/core/rstring.h
+chilled.o: $(hdrdir)/ruby/internal/core/rstruct.h
+chilled.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+chilled.o: $(hdrdir)/ruby/internal/ctype.h
+chilled.o: $(hdrdir)/ruby/internal/dllexport.h
+chilled.o: $(hdrdir)/ruby/internal/dosish.h
+chilled.o: $(hdrdir)/ruby/internal/error.h
+chilled.o: $(hdrdir)/ruby/internal/eval.h
+chilled.o: $(hdrdir)/ruby/internal/event.h
+chilled.o: $(hdrdir)/ruby/internal/fl_type.h
+chilled.o: $(hdrdir)/ruby/internal/gc.h
+chilled.o: $(hdrdir)/ruby/internal/glob.h
+chilled.o: $(hdrdir)/ruby/internal/globals.h
+chilled.o: $(hdrdir)/ruby/internal/has/attribute.h
+chilled.o: $(hdrdir)/ruby/internal/has/builtin.h
+chilled.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+chilled.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+chilled.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+chilled.o: $(hdrdir)/ruby/internal/has/extension.h
+chilled.o: $(hdrdir)/ruby/internal/has/feature.h
+chilled.o: $(hdrdir)/ruby/internal/has/warning.h
+chilled.o: $(hdrdir)/ruby/internal/intern/array.h
+chilled.o: $(hdrdir)/ruby/internal/intern/bignum.h
+chilled.o: $(hdrdir)/ruby/internal/intern/class.h
+chilled.o: $(hdrdir)/ruby/internal/intern/compar.h
+chilled.o: $(hdrdir)/ruby/internal/intern/complex.h
+chilled.o: $(hdrdir)/ruby/internal/intern/cont.h
+chilled.o: $(hdrdir)/ruby/internal/intern/dir.h
+chilled.o: $(hdrdir)/ruby/internal/intern/enum.h
+chilled.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+chilled.o: $(hdrdir)/ruby/internal/intern/error.h
+chilled.o: $(hdrdir)/ruby/internal/intern/eval.h
+chilled.o: $(hdrdir)/ruby/internal/intern/file.h
+chilled.o: $(hdrdir)/ruby/internal/intern/hash.h
+chilled.o: $(hdrdir)/ruby/internal/intern/io.h
+chilled.o: $(hdrdir)/ruby/internal/intern/load.h
+chilled.o: $(hdrdir)/ruby/internal/intern/marshal.h
+chilled.o: $(hdrdir)/ruby/internal/intern/numeric.h
+chilled.o: $(hdrdir)/ruby/internal/intern/object.h
+chilled.o: $(hdrdir)/ruby/internal/intern/parse.h
+chilled.o: $(hdrdir)/ruby/internal/intern/proc.h
+chilled.o: $(hdrdir)/ruby/internal/intern/process.h
+chilled.o: $(hdrdir)/ruby/internal/intern/random.h
+chilled.o: $(hdrdir)/ruby/internal/intern/range.h
+chilled.o: $(hdrdir)/ruby/internal/intern/rational.h
+chilled.o: $(hdrdir)/ruby/internal/intern/re.h
+chilled.o: $(hdrdir)/ruby/internal/intern/ruby.h
+chilled.o: $(hdrdir)/ruby/internal/intern/select.h
+chilled.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+chilled.o: $(hdrdir)/ruby/internal/intern/signal.h
+chilled.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+chilled.o: $(hdrdir)/ruby/internal/intern/string.h
+chilled.o: $(hdrdir)/ruby/internal/intern/struct.h
+chilled.o: $(hdrdir)/ruby/internal/intern/thread.h
+chilled.o: $(hdrdir)/ruby/internal/intern/time.h
+chilled.o: $(hdrdir)/ruby/internal/intern/variable.h
+chilled.o: $(hdrdir)/ruby/internal/intern/vm.h
+chilled.o: $(hdrdir)/ruby/internal/interpreter.h
+chilled.o: $(hdrdir)/ruby/internal/iterator.h
+chilled.o: $(hdrdir)/ruby/internal/memory.h
+chilled.o: $(hdrdir)/ruby/internal/method.h
+chilled.o: $(hdrdir)/ruby/internal/module.h
+chilled.o: $(hdrdir)/ruby/internal/newobj.h
+chilled.o: $(hdrdir)/ruby/internal/scan_args.h
+chilled.o: $(hdrdir)/ruby/internal/special_consts.h
+chilled.o: $(hdrdir)/ruby/internal/static_assert.h
+chilled.o: $(hdrdir)/ruby/internal/stdalign.h
+chilled.o: $(hdrdir)/ruby/internal/stdbool.h
+chilled.o: $(hdrdir)/ruby/internal/stdckdint.h
+chilled.o: $(hdrdir)/ruby/internal/symbol.h
+chilled.o: $(hdrdir)/ruby/internal/value.h
+chilled.o: $(hdrdir)/ruby/internal/value_type.h
+chilled.o: $(hdrdir)/ruby/internal/variable.h
+chilled.o: $(hdrdir)/ruby/internal/warning_push.h
+chilled.o: $(hdrdir)/ruby/internal/xmalloc.h
+chilled.o: $(hdrdir)/ruby/missing.h
+chilled.o: $(hdrdir)/ruby/ruby.h
+chilled.o: $(hdrdir)/ruby/st.h
+chilled.o: $(hdrdir)/ruby/subst.h
+chilled.o: chilled.c
+coderange.o: $(RUBY_EXTCONF_H)
+coderange.o: $(arch_hdrdir)/ruby/config.h
+coderange.o: $(hdrdir)/ruby/assert.h
+coderange.o: $(hdrdir)/ruby/backward.h
+coderange.o: $(hdrdir)/ruby/backward/2/assume.h
+coderange.o: $(hdrdir)/ruby/backward/2/attributes.h
+coderange.o: $(hdrdir)/ruby/backward/2/bool.h
+coderange.o: $(hdrdir)/ruby/backward/2/inttypes.h
+coderange.o: $(hdrdir)/ruby/backward/2/limits.h
+coderange.o: $(hdrdir)/ruby/backward/2/long_long.h
+coderange.o: $(hdrdir)/ruby/backward/2/stdalign.h
+coderange.o: $(hdrdir)/ruby/backward/2/stdarg.h
+coderange.o: $(hdrdir)/ruby/defines.h
+coderange.o: $(hdrdir)/ruby/encoding.h
+coderange.o: $(hdrdir)/ruby/intern.h
+coderange.o: $(hdrdir)/ruby/internal/abi.h
+coderange.o: $(hdrdir)/ruby/internal/anyargs.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+coderange.o: $(hdrdir)/ruby/internal/assume.h
+coderange.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+coderange.o: $(hdrdir)/ruby/internal/attr/artificial.h
+coderange.o: $(hdrdir)/ruby/internal/attr/cold.h
+coderange.o: $(hdrdir)/ruby/internal/attr/const.h
+coderange.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+coderange.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+coderange.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+coderange.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+coderange.o: $(hdrdir)/ruby/internal/attr/error.h
+coderange.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+coderange.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+coderange.o: $(hdrdir)/ruby/internal/attr/format.h
+coderange.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+coderange.o: $(hdrdir)/ruby/internal/attr/noalias.h
+coderange.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+coderange.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+coderange.o: $(hdrdir)/ruby/internal/attr/noinline.h
+coderange.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+coderange.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+coderange.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+coderange.o: $(hdrdir)/ruby/internal/attr/pure.h
+coderange.o: $(hdrdir)/ruby/internal/attr/restrict.h
+coderange.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+coderange.o: $(hdrdir)/ruby/internal/attr/warning.h
+coderange.o: $(hdrdir)/ruby/internal/attr/weakref.h
+coderange.o: $(hdrdir)/ruby/internal/cast.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_since.h
+coderange.o: $(hdrdir)/ruby/internal/config.h
+coderange.o: $(hdrdir)/ruby/internal/constant_p.h
+coderange.o: $(hdrdir)/ruby/internal/core.h
+coderange.o: $(hdrdir)/ruby/internal/core/rarray.h
+coderange.o: $(hdrdir)/ruby/internal/core/rbasic.h
+coderange.o: $(hdrdir)/ruby/internal/core/rbignum.h
+coderange.o: $(hdrdir)/ruby/internal/core/rclass.h
+coderange.o: $(hdrdir)/ruby/internal/core/rdata.h
+coderange.o: $(hdrdir)/ruby/internal/core/rfile.h
+coderange.o: $(hdrdir)/ruby/internal/core/rhash.h
+coderange.o: $(hdrdir)/ruby/internal/core/robject.h
+coderange.o: $(hdrdir)/ruby/internal/core/rregexp.h
+coderange.o: $(hdrdir)/ruby/internal/core/rstring.h
+coderange.o: $(hdrdir)/ruby/internal/core/rstruct.h
+coderange.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+coderange.o: $(hdrdir)/ruby/internal/ctype.h
+coderange.o: $(hdrdir)/ruby/internal/dllexport.h
+coderange.o: $(hdrdir)/ruby/internal/dosish.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/re.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/string.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+coderange.o: $(hdrdir)/ruby/internal/error.h
+coderange.o: $(hdrdir)/ruby/internal/eval.h
+coderange.o: $(hdrdir)/ruby/internal/event.h
+coderange.o: $(hdrdir)/ruby/internal/fl_type.h
+coderange.o: $(hdrdir)/ruby/internal/gc.h
+coderange.o: $(hdrdir)/ruby/internal/glob.h
+coderange.o: $(hdrdir)/ruby/internal/globals.h
+coderange.o: $(hdrdir)/ruby/internal/has/attribute.h
+coderange.o: $(hdrdir)/ruby/internal/has/builtin.h
+coderange.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+coderange.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+coderange.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+coderange.o: $(hdrdir)/ruby/internal/has/extension.h
+coderange.o: $(hdrdir)/ruby/internal/has/feature.h
+coderange.o: $(hdrdir)/ruby/internal/has/warning.h
+coderange.o: $(hdrdir)/ruby/internal/intern/array.h
+coderange.o: $(hdrdir)/ruby/internal/intern/bignum.h
+coderange.o: $(hdrdir)/ruby/internal/intern/class.h
+coderange.o: $(hdrdir)/ruby/internal/intern/compar.h
+coderange.o: $(hdrdir)/ruby/internal/intern/complex.h
+coderange.o: $(hdrdir)/ruby/internal/intern/cont.h
+coderange.o: $(hdrdir)/ruby/internal/intern/dir.h
+coderange.o: $(hdrdir)/ruby/internal/intern/enum.h
+coderange.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+coderange.o: $(hdrdir)/ruby/internal/intern/error.h
+coderange.o: $(hdrdir)/ruby/internal/intern/eval.h
+coderange.o: $(hdrdir)/ruby/internal/intern/file.h
+coderange.o: $(hdrdir)/ruby/internal/intern/hash.h
+coderange.o: $(hdrdir)/ruby/internal/intern/io.h
+coderange.o: $(hdrdir)/ruby/internal/intern/load.h
+coderange.o: $(hdrdir)/ruby/internal/intern/marshal.h
+coderange.o: $(hdrdir)/ruby/internal/intern/numeric.h
+coderange.o: $(hdrdir)/ruby/internal/intern/object.h
+coderange.o: $(hdrdir)/ruby/internal/intern/parse.h
+coderange.o: $(hdrdir)/ruby/internal/intern/proc.h
+coderange.o: $(hdrdir)/ruby/internal/intern/process.h
+coderange.o: $(hdrdir)/ruby/internal/intern/random.h
+coderange.o: $(hdrdir)/ruby/internal/intern/range.h
+coderange.o: $(hdrdir)/ruby/internal/intern/rational.h
+coderange.o: $(hdrdir)/ruby/internal/intern/re.h
+coderange.o: $(hdrdir)/ruby/internal/intern/ruby.h
+coderange.o: $(hdrdir)/ruby/internal/intern/select.h
+coderange.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+coderange.o: $(hdrdir)/ruby/internal/intern/set.h
+coderange.o: $(hdrdir)/ruby/internal/intern/signal.h
+coderange.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+coderange.o: $(hdrdir)/ruby/internal/intern/string.h
+coderange.o: $(hdrdir)/ruby/internal/intern/struct.h
+coderange.o: $(hdrdir)/ruby/internal/intern/thread.h
+coderange.o: $(hdrdir)/ruby/internal/intern/time.h
+coderange.o: $(hdrdir)/ruby/internal/intern/variable.h
+coderange.o: $(hdrdir)/ruby/internal/intern/vm.h
+coderange.o: $(hdrdir)/ruby/internal/interpreter.h
+coderange.o: $(hdrdir)/ruby/internal/iterator.h
+coderange.o: $(hdrdir)/ruby/internal/memory.h
+coderange.o: $(hdrdir)/ruby/internal/method.h
+coderange.o: $(hdrdir)/ruby/internal/module.h
+coderange.o: $(hdrdir)/ruby/internal/newobj.h
+coderange.o: $(hdrdir)/ruby/internal/scan_args.h
+coderange.o: $(hdrdir)/ruby/internal/special_consts.h
+coderange.o: $(hdrdir)/ruby/internal/static_assert.h
+coderange.o: $(hdrdir)/ruby/internal/stdalign.h
+coderange.o: $(hdrdir)/ruby/internal/stdbool.h
+coderange.o: $(hdrdir)/ruby/internal/stdckdint.h
+coderange.o: $(hdrdir)/ruby/internal/symbol.h
+coderange.o: $(hdrdir)/ruby/internal/value.h
+coderange.o: $(hdrdir)/ruby/internal/value_type.h
+coderange.o: $(hdrdir)/ruby/internal/variable.h
+coderange.o: $(hdrdir)/ruby/internal/warning_push.h
+coderange.o: $(hdrdir)/ruby/internal/xmalloc.h
+coderange.o: $(hdrdir)/ruby/missing.h
+coderange.o: $(hdrdir)/ruby/onigmo.h
+coderange.o: $(hdrdir)/ruby/oniguruma.h
+coderange.o: $(hdrdir)/ruby/ruby.h
+coderange.o: $(hdrdir)/ruby/st.h
+coderange.o: $(hdrdir)/ruby/subst.h
+coderange.o: coderange.c
+cstr.o: $(RUBY_EXTCONF_H)
+cstr.o: $(arch_hdrdir)/ruby/config.h
+cstr.o: $(hdrdir)/ruby/assert.h
+cstr.o: $(hdrdir)/ruby/backward.h
+cstr.o: $(hdrdir)/ruby/backward/2/assume.h
+cstr.o: $(hdrdir)/ruby/backward/2/attributes.h
+cstr.o: $(hdrdir)/ruby/backward/2/bool.h
+cstr.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+cstr.o: $(hdrdir)/ruby/backward/2/inttypes.h
+cstr.o: $(hdrdir)/ruby/backward/2/limits.h
+cstr.o: $(hdrdir)/ruby/backward/2/long_long.h
+cstr.o: $(hdrdir)/ruby/backward/2/stdalign.h
+cstr.o: $(hdrdir)/ruby/backward/2/stdarg.h
+cstr.o: $(hdrdir)/ruby/defines.h
+cstr.o: $(hdrdir)/ruby/encoding.h
+cstr.o: $(hdrdir)/ruby/intern.h
+cstr.o: $(hdrdir)/ruby/internal/abi.h
+cstr.o: $(hdrdir)/ruby/internal/anyargs.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+cstr.o: $(hdrdir)/ruby/internal/assume.h
+cstr.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+cstr.o: $(hdrdir)/ruby/internal/attr/artificial.h
+cstr.o: $(hdrdir)/ruby/internal/attr/cold.h
+cstr.o: $(hdrdir)/ruby/internal/attr/const.h
+cstr.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+cstr.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+cstr.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+cstr.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+cstr.o: $(hdrdir)/ruby/internal/attr/error.h
+cstr.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+cstr.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+cstr.o: $(hdrdir)/ruby/internal/attr/format.h
+cstr.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+cstr.o: $(hdrdir)/ruby/internal/attr/noalias.h
+cstr.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+cstr.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+cstr.o: $(hdrdir)/ruby/internal/attr/noinline.h
+cstr.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+cstr.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+cstr.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+cstr.o: $(hdrdir)/ruby/internal/attr/pure.h
+cstr.o: $(hdrdir)/ruby/internal/attr/restrict.h
+cstr.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+cstr.o: $(hdrdir)/ruby/internal/attr/warning.h
+cstr.o: $(hdrdir)/ruby/internal/attr/weakref.h
+cstr.o: $(hdrdir)/ruby/internal/cast.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_since.h
+cstr.o: $(hdrdir)/ruby/internal/config.h
+cstr.o: $(hdrdir)/ruby/internal/constant_p.h
+cstr.o: $(hdrdir)/ruby/internal/core.h
+cstr.o: $(hdrdir)/ruby/internal/core/rarray.h
+cstr.o: $(hdrdir)/ruby/internal/core/rbasic.h
+cstr.o: $(hdrdir)/ruby/internal/core/rbignum.h
+cstr.o: $(hdrdir)/ruby/internal/core/rclass.h
+cstr.o: $(hdrdir)/ruby/internal/core/rdata.h
+cstr.o: $(hdrdir)/ruby/internal/core/rfile.h
+cstr.o: $(hdrdir)/ruby/internal/core/rhash.h
+cstr.o: $(hdrdir)/ruby/internal/core/robject.h
+cstr.o: $(hdrdir)/ruby/internal/core/rregexp.h
+cstr.o: $(hdrdir)/ruby/internal/core/rstring.h
+cstr.o: $(hdrdir)/ruby/internal/core/rstruct.h
+cstr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+cstr.o: $(hdrdir)/ruby/internal/ctype.h
+cstr.o: $(hdrdir)/ruby/internal/dllexport.h
+cstr.o: $(hdrdir)/ruby/internal/dosish.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/re.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/string.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+cstr.o: $(hdrdir)/ruby/internal/error.h
+cstr.o: $(hdrdir)/ruby/internal/eval.h
+cstr.o: $(hdrdir)/ruby/internal/event.h
+cstr.o: $(hdrdir)/ruby/internal/fl_type.h
+cstr.o: $(hdrdir)/ruby/internal/gc.h
+cstr.o: $(hdrdir)/ruby/internal/glob.h
+cstr.o: $(hdrdir)/ruby/internal/globals.h
+cstr.o: $(hdrdir)/ruby/internal/has/attribute.h
+cstr.o: $(hdrdir)/ruby/internal/has/builtin.h
+cstr.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+cstr.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+cstr.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+cstr.o: $(hdrdir)/ruby/internal/has/extension.h
+cstr.o: $(hdrdir)/ruby/internal/has/feature.h
+cstr.o: $(hdrdir)/ruby/internal/has/warning.h
+cstr.o: $(hdrdir)/ruby/internal/intern/array.h
+cstr.o: $(hdrdir)/ruby/internal/intern/bignum.h
+cstr.o: $(hdrdir)/ruby/internal/intern/class.h
+cstr.o: $(hdrdir)/ruby/internal/intern/compar.h
+cstr.o: $(hdrdir)/ruby/internal/intern/complex.h
+cstr.o: $(hdrdir)/ruby/internal/intern/cont.h
+cstr.o: $(hdrdir)/ruby/internal/intern/dir.h
+cstr.o: $(hdrdir)/ruby/internal/intern/enum.h
+cstr.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+cstr.o: $(hdrdir)/ruby/internal/intern/error.h
+cstr.o: $(hdrdir)/ruby/internal/intern/eval.h
+cstr.o: $(hdrdir)/ruby/internal/intern/file.h
+cstr.o: $(hdrdir)/ruby/internal/intern/hash.h
+cstr.o: $(hdrdir)/ruby/internal/intern/io.h
+cstr.o: $(hdrdir)/ruby/internal/intern/load.h
+cstr.o: $(hdrdir)/ruby/internal/intern/marshal.h
+cstr.o: $(hdrdir)/ruby/internal/intern/numeric.h
+cstr.o: $(hdrdir)/ruby/internal/intern/object.h
+cstr.o: $(hdrdir)/ruby/internal/intern/parse.h
+cstr.o: $(hdrdir)/ruby/internal/intern/proc.h
+cstr.o: $(hdrdir)/ruby/internal/intern/process.h
+cstr.o: $(hdrdir)/ruby/internal/intern/random.h
+cstr.o: $(hdrdir)/ruby/internal/intern/range.h
+cstr.o: $(hdrdir)/ruby/internal/intern/rational.h
+cstr.o: $(hdrdir)/ruby/internal/intern/re.h
+cstr.o: $(hdrdir)/ruby/internal/intern/ruby.h
+cstr.o: $(hdrdir)/ruby/internal/intern/select.h
+cstr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+cstr.o: $(hdrdir)/ruby/internal/intern/set.h
+cstr.o: $(hdrdir)/ruby/internal/intern/signal.h
+cstr.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+cstr.o: $(hdrdir)/ruby/internal/intern/string.h
+cstr.o: $(hdrdir)/ruby/internal/intern/struct.h
+cstr.o: $(hdrdir)/ruby/internal/intern/thread.h
+cstr.o: $(hdrdir)/ruby/internal/intern/time.h
+cstr.o: $(hdrdir)/ruby/internal/intern/variable.h
+cstr.o: $(hdrdir)/ruby/internal/intern/vm.h
+cstr.o: $(hdrdir)/ruby/internal/interpreter.h
+cstr.o: $(hdrdir)/ruby/internal/iterator.h
+cstr.o: $(hdrdir)/ruby/internal/memory.h
+cstr.o: $(hdrdir)/ruby/internal/method.h
+cstr.o: $(hdrdir)/ruby/internal/module.h
+cstr.o: $(hdrdir)/ruby/internal/newobj.h
+cstr.o: $(hdrdir)/ruby/internal/scan_args.h
+cstr.o: $(hdrdir)/ruby/internal/special_consts.h
+cstr.o: $(hdrdir)/ruby/internal/static_assert.h
+cstr.o: $(hdrdir)/ruby/internal/stdalign.h
+cstr.o: $(hdrdir)/ruby/internal/stdbool.h
+cstr.o: $(hdrdir)/ruby/internal/stdckdint.h
+cstr.o: $(hdrdir)/ruby/internal/symbol.h
+cstr.o: $(hdrdir)/ruby/internal/value.h
+cstr.o: $(hdrdir)/ruby/internal/value_type.h
+cstr.o: $(hdrdir)/ruby/internal/variable.h
+cstr.o: $(hdrdir)/ruby/internal/warning_push.h
+cstr.o: $(hdrdir)/ruby/internal/xmalloc.h
+cstr.o: $(hdrdir)/ruby/missing.h
+cstr.o: $(hdrdir)/ruby/onigmo.h
+cstr.o: $(hdrdir)/ruby/oniguruma.h
+cstr.o: $(hdrdir)/ruby/ruby.h
+cstr.o: $(hdrdir)/ruby/st.h
+cstr.o: $(hdrdir)/ruby/subst.h
+cstr.o: $(top_srcdir)/encindex.h
+cstr.o: $(top_srcdir)/internal.h
+cstr.o: $(top_srcdir)/internal/compilers.h
+cstr.o: $(top_srcdir)/internal/string.h
+cstr.o: cstr.c
+ellipsize.o: $(RUBY_EXTCONF_H)
+ellipsize.o: $(arch_hdrdir)/ruby/config.h
+ellipsize.o: $(hdrdir)/ruby.h
+ellipsize.o: $(hdrdir)/ruby/assert.h
+ellipsize.o: $(hdrdir)/ruby/backward.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/assume.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/attributes.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/bool.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/limits.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/long_long.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ellipsize.o: $(hdrdir)/ruby/defines.h
+ellipsize.o: $(hdrdir)/ruby/intern.h
+ellipsize.o: $(hdrdir)/ruby/internal/abi.h
+ellipsize.o: $(hdrdir)/ruby/internal/anyargs.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/assume.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/cold.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/const.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/error.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/format.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/pure.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/warning.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ellipsize.o: $(hdrdir)/ruby/internal/cast.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_since.h
+ellipsize.o: $(hdrdir)/ruby/internal/config.h
+ellipsize.o: $(hdrdir)/ruby/internal/constant_p.h
+ellipsize.o: $(hdrdir)/ruby/internal/core.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rarray.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rclass.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rdata.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rfile.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rhash.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/robject.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rstring.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ellipsize.o: $(hdrdir)/ruby/internal/ctype.h
+ellipsize.o: $(hdrdir)/ruby/internal/dllexport.h
+ellipsize.o: $(hdrdir)/ruby/internal/dosish.h
+ellipsize.o: $(hdrdir)/ruby/internal/error.h
+ellipsize.o: $(hdrdir)/ruby/internal/eval.h
+ellipsize.o: $(hdrdir)/ruby/internal/event.h
+ellipsize.o: $(hdrdir)/ruby/internal/fl_type.h
+ellipsize.o: $(hdrdir)/ruby/internal/gc.h
+ellipsize.o: $(hdrdir)/ruby/internal/glob.h
+ellipsize.o: $(hdrdir)/ruby/internal/globals.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/attribute.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/builtin.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/extension.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/feature.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/warning.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/array.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/class.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/compar.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/complex.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/cont.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/dir.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/enum.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/error.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/eval.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/file.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/hash.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/io.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/load.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/object.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/parse.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/proc.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/process.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/random.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/range.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/rational.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/re.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/select.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/set.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/signal.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/string.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/struct.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/thread.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/time.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/variable.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/vm.h
+ellipsize.o: $(hdrdir)/ruby/internal/interpreter.h
+ellipsize.o: $(hdrdir)/ruby/internal/iterator.h
+ellipsize.o: $(hdrdir)/ruby/internal/memory.h
+ellipsize.o: $(hdrdir)/ruby/internal/method.h
+ellipsize.o: $(hdrdir)/ruby/internal/module.h
+ellipsize.o: $(hdrdir)/ruby/internal/newobj.h
+ellipsize.o: $(hdrdir)/ruby/internal/scan_args.h
+ellipsize.o: $(hdrdir)/ruby/internal/special_consts.h
+ellipsize.o: $(hdrdir)/ruby/internal/static_assert.h
+ellipsize.o: $(hdrdir)/ruby/internal/stdalign.h
+ellipsize.o: $(hdrdir)/ruby/internal/stdbool.h
+ellipsize.o: $(hdrdir)/ruby/internal/stdckdint.h
+ellipsize.o: $(hdrdir)/ruby/internal/symbol.h
+ellipsize.o: $(hdrdir)/ruby/internal/value.h
+ellipsize.o: $(hdrdir)/ruby/internal/value_type.h
+ellipsize.o: $(hdrdir)/ruby/internal/variable.h
+ellipsize.o: $(hdrdir)/ruby/internal/warning_push.h
+ellipsize.o: $(hdrdir)/ruby/internal/xmalloc.h
+ellipsize.o: $(hdrdir)/ruby/missing.h
+ellipsize.o: $(hdrdir)/ruby/ruby.h
+ellipsize.o: $(hdrdir)/ruby/st.h
+ellipsize.o: $(hdrdir)/ruby/subst.h
+ellipsize.o: ellipsize.c
+enc_associate.o: $(RUBY_EXTCONF_H)
+enc_associate.o: $(arch_hdrdir)/ruby/config.h
+enc_associate.o: $(hdrdir)/ruby.h
+enc_associate.o: $(hdrdir)/ruby/assert.h
+enc_associate.o: $(hdrdir)/ruby/backward.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/assume.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/attributes.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/bool.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/inttypes.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/limits.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/long_long.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/stdalign.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/stdarg.h
+enc_associate.o: $(hdrdir)/ruby/defines.h
+enc_associate.o: $(hdrdir)/ruby/encoding.h
+enc_associate.o: $(hdrdir)/ruby/intern.h
+enc_associate.o: $(hdrdir)/ruby/internal/abi.h
+enc_associate.o: $(hdrdir)/ruby/internal/anyargs.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/assume.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/artificial.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/cold.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/const.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/error.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/format.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/noalias.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/noinline.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/pure.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/restrict.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/warning.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/weakref.h
+enc_associate.o: $(hdrdir)/ruby/internal/cast.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_since.h
+enc_associate.o: $(hdrdir)/ruby/internal/config.h
+enc_associate.o: $(hdrdir)/ruby/internal/constant_p.h
+enc_associate.o: $(hdrdir)/ruby/internal/core.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rarray.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rbasic.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rbignum.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rclass.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rdata.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rfile.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rhash.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/robject.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rregexp.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rstring.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rstruct.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+enc_associate.o: $(hdrdir)/ruby/internal/ctype.h
+enc_associate.o: $(hdrdir)/ruby/internal/dllexport.h
+enc_associate.o: $(hdrdir)/ruby/internal/dosish.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/re.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/string.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+enc_associate.o: $(hdrdir)/ruby/internal/error.h
+enc_associate.o: $(hdrdir)/ruby/internal/eval.h
+enc_associate.o: $(hdrdir)/ruby/internal/event.h
+enc_associate.o: $(hdrdir)/ruby/internal/fl_type.h
+enc_associate.o: $(hdrdir)/ruby/internal/gc.h
+enc_associate.o: $(hdrdir)/ruby/internal/glob.h
+enc_associate.o: $(hdrdir)/ruby/internal/globals.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/attribute.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/builtin.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/extension.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/feature.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/warning.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/array.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/bignum.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/class.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/compar.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/complex.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/cont.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/dir.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/enum.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/error.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/eval.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/file.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/hash.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/io.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/load.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/marshal.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/numeric.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/object.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/parse.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/proc.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/process.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/random.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/range.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/rational.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/re.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/ruby.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/select.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/set.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/signal.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/string.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/struct.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/thread.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/time.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/variable.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/vm.h
+enc_associate.o: $(hdrdir)/ruby/internal/interpreter.h
+enc_associate.o: $(hdrdir)/ruby/internal/iterator.h
+enc_associate.o: $(hdrdir)/ruby/internal/memory.h
+enc_associate.o: $(hdrdir)/ruby/internal/method.h
+enc_associate.o: $(hdrdir)/ruby/internal/module.h
+enc_associate.o: $(hdrdir)/ruby/internal/newobj.h
+enc_associate.o: $(hdrdir)/ruby/internal/scan_args.h
+enc_associate.o: $(hdrdir)/ruby/internal/special_consts.h
+enc_associate.o: $(hdrdir)/ruby/internal/static_assert.h
+enc_associate.o: $(hdrdir)/ruby/internal/stdalign.h
+enc_associate.o: $(hdrdir)/ruby/internal/stdbool.h
+enc_associate.o: $(hdrdir)/ruby/internal/stdckdint.h
+enc_associate.o: $(hdrdir)/ruby/internal/symbol.h
+enc_associate.o: $(hdrdir)/ruby/internal/value.h
+enc_associate.o: $(hdrdir)/ruby/internal/value_type.h
+enc_associate.o: $(hdrdir)/ruby/internal/variable.h
+enc_associate.o: $(hdrdir)/ruby/internal/warning_push.h
+enc_associate.o: $(hdrdir)/ruby/internal/xmalloc.h
+enc_associate.o: $(hdrdir)/ruby/missing.h
+enc_associate.o: $(hdrdir)/ruby/onigmo.h
+enc_associate.o: $(hdrdir)/ruby/oniguruma.h
+enc_associate.o: $(hdrdir)/ruby/ruby.h
+enc_associate.o: $(hdrdir)/ruby/st.h
+enc_associate.o: $(hdrdir)/ruby/subst.h
+enc_associate.o: enc_associate.c
+enc_dummy.o: $(RUBY_EXTCONF_H)
+enc_dummy.o: $(arch_hdrdir)/ruby/config.h
+enc_dummy.o: $(hdrdir)/ruby.h
+enc_dummy.o: $(hdrdir)/ruby/assert.h
+enc_dummy.o: $(hdrdir)/ruby/backward.h
+enc_dummy.o: $(hdrdir)/ruby/backward/2/assume.h
+enc_dummy.o: $(hdrdir)/ruby/backward/2/attributes.h
+enc_dummy.o: $(hdrdir)/ruby/backward/2/bool.h
+enc_dummy.o: $(hdrdir)/ruby/backward/2/inttypes.h
+enc_dummy.o: $(hdrdir)/ruby/backward/2/limits.h
+enc_dummy.o: $(hdrdir)/ruby/backward/2/long_long.h
+enc_dummy.o: $(hdrdir)/ruby/backward/2/stdalign.h
+enc_dummy.o: $(hdrdir)/ruby/backward/2/stdarg.h
+enc_dummy.o: $(hdrdir)/ruby/defines.h
+enc_dummy.o: $(hdrdir)/ruby/encoding.h
+enc_dummy.o: $(hdrdir)/ruby/intern.h
+enc_dummy.o: $(hdrdir)/ruby/internal/abi.h
+enc_dummy.o: $(hdrdir)/ruby/internal/anyargs.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+enc_dummy.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+enc_dummy.o: $(hdrdir)/ruby/internal/assume.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/artificial.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/cold.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/const.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/error.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/format.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/noalias.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/noinline.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/pure.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/restrict.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/warning.h
+enc_dummy.o: $(hdrdir)/ruby/internal/attr/weakref.h
+enc_dummy.o: $(hdrdir)/ruby/internal/cast.h
+enc_dummy.o: $(hdrdir)/ruby/internal/compiler_is.h
+enc_dummy.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+enc_dummy.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+enc_dummy.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+enc_dummy.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+enc_dummy.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+enc_dummy.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+enc_dummy.o: $(hdrdir)/ruby/internal/compiler_since.h
+enc_dummy.o: $(hdrdir)/ruby/internal/config.h
+enc_dummy.o: $(hdrdir)/ruby/internal/constant_p.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core/rarray.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core/rbasic.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core/rbignum.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core/rclass.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core/rdata.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core/rfile.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core/rhash.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core/robject.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core/rregexp.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core/rstring.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core/rstruct.h
+enc_dummy.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+enc_dummy.o: $(hdrdir)/ruby/internal/ctype.h
+enc_dummy.o: $(hdrdir)/ruby/internal/dllexport.h
+enc_dummy.o: $(hdrdir)/ruby/internal/dosish.h
+enc_dummy.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+enc_dummy.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+enc_dummy.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+enc_dummy.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+enc_dummy.o: $(hdrdir)/ruby/internal/encoding/re.h
+enc_dummy.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+enc_dummy.o: $(hdrdir)/ruby/internal/encoding/string.h
+enc_dummy.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+enc_dummy.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+enc_dummy.o: $(hdrdir)/ruby/internal/error.h
+enc_dummy.o: $(hdrdir)/ruby/internal/eval.h
+enc_dummy.o: $(hdrdir)/ruby/internal/event.h
+enc_dummy.o: $(hdrdir)/ruby/internal/fl_type.h
+enc_dummy.o: $(hdrdir)/ruby/internal/gc.h
+enc_dummy.o: $(hdrdir)/ruby/internal/glob.h
+enc_dummy.o: $(hdrdir)/ruby/internal/globals.h
+enc_dummy.o: $(hdrdir)/ruby/internal/has/attribute.h
+enc_dummy.o: $(hdrdir)/ruby/internal/has/builtin.h
+enc_dummy.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+enc_dummy.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+enc_dummy.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+enc_dummy.o: $(hdrdir)/ruby/internal/has/extension.h
+enc_dummy.o: $(hdrdir)/ruby/internal/has/feature.h
+enc_dummy.o: $(hdrdir)/ruby/internal/has/warning.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/array.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/bignum.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/class.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/compar.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/complex.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/cont.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/dir.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/enum.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/error.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/eval.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/file.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/hash.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/io.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/load.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/marshal.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/numeric.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/object.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/parse.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/proc.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/process.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/random.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/range.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/rational.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/re.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/ruby.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/select.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/set.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/signal.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/string.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/struct.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/thread.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/time.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/variable.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/vm.h
+enc_dummy.o: $(hdrdir)/ruby/internal/interpreter.h
+enc_dummy.o: $(hdrdir)/ruby/internal/iterator.h
+enc_dummy.o: $(hdrdir)/ruby/internal/memory.h
+enc_dummy.o: $(hdrdir)/ruby/internal/method.h
+enc_dummy.o: $(hdrdir)/ruby/internal/module.h
+enc_dummy.o: $(hdrdir)/ruby/internal/newobj.h
+enc_dummy.o: $(hdrdir)/ruby/internal/scan_args.h
+enc_dummy.o: $(hdrdir)/ruby/internal/special_consts.h
+enc_dummy.o: $(hdrdir)/ruby/internal/static_assert.h
+enc_dummy.o: $(hdrdir)/ruby/internal/stdalign.h
+enc_dummy.o: $(hdrdir)/ruby/internal/stdbool.h
+enc_dummy.o: $(hdrdir)/ruby/internal/stdckdint.h
+enc_dummy.o: $(hdrdir)/ruby/internal/symbol.h
+enc_dummy.o: $(hdrdir)/ruby/internal/value.h
+enc_dummy.o: $(hdrdir)/ruby/internal/value_type.h
+enc_dummy.o: $(hdrdir)/ruby/internal/variable.h
+enc_dummy.o: $(hdrdir)/ruby/internal/warning_push.h
+enc_dummy.o: $(hdrdir)/ruby/internal/xmalloc.h
+enc_dummy.o: $(hdrdir)/ruby/missing.h
+enc_dummy.o: $(hdrdir)/ruby/onigmo.h
+enc_dummy.o: $(hdrdir)/ruby/oniguruma.h
+enc_dummy.o: $(hdrdir)/ruby/ruby.h
+enc_dummy.o: $(hdrdir)/ruby/st.h
+enc_dummy.o: $(hdrdir)/ruby/subst.h
+enc_dummy.o: enc_dummy.c
+enc_str_buf_cat.o: $(RUBY_EXTCONF_H)
+enc_str_buf_cat.o: $(arch_hdrdir)/ruby/config.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/assert.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/assume.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/attributes.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/bool.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/limits.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/long_long.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/stdarg.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/defines.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/encoding.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/intern.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/abi.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/anyargs.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/assume.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/artificial.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/cold.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/const.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/error.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/format.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/noalias.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/noinline.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/pure.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/restrict.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/warning.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/weakref.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/cast.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_since.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/config.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/constant_p.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rarray.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rbasic.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rbignum.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rclass.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rdata.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rfile.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rhash.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/robject.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rregexp.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rstring.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rstruct.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/ctype.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/dllexport.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/dosish.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/re.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/string.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/error.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/eval.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/event.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/fl_type.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/gc.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/glob.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/globals.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/attribute.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/builtin.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/extension.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/feature.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/warning.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/array.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/bignum.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/class.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/compar.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/complex.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/cont.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/dir.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/enum.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/error.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/eval.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/file.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/hash.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/io.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/load.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/marshal.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/numeric.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/object.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/parse.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/proc.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/process.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/random.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/range.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/rational.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/re.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/ruby.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/select.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/set.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/signal.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/string.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/struct.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/thread.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/time.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/variable.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/vm.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/interpreter.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/iterator.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/memory.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/method.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/module.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/newobj.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/scan_args.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/special_consts.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/static_assert.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/stdalign.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/stdbool.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/stdckdint.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/symbol.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/value.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/value_type.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/variable.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/warning_push.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/xmalloc.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/missing.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/onigmo.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/oniguruma.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/ruby.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/st.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/subst.h
+enc_str_buf_cat.o: enc_str_buf_cat.c
+fstring.o: $(RUBY_EXTCONF_H)
+fstring.o: $(arch_hdrdir)/ruby/config.h
+fstring.o: $(hdrdir)/ruby.h
+fstring.o: $(hdrdir)/ruby/assert.h
+fstring.o: $(hdrdir)/ruby/backward.h
+fstring.o: $(hdrdir)/ruby/backward/2/assume.h
+fstring.o: $(hdrdir)/ruby/backward/2/attributes.h
+fstring.o: $(hdrdir)/ruby/backward/2/bool.h
+fstring.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+fstring.o: $(hdrdir)/ruby/backward/2/inttypes.h
+fstring.o: $(hdrdir)/ruby/backward/2/limits.h
+fstring.o: $(hdrdir)/ruby/backward/2/long_long.h
+fstring.o: $(hdrdir)/ruby/backward/2/stdalign.h
+fstring.o: $(hdrdir)/ruby/backward/2/stdarg.h
+fstring.o: $(hdrdir)/ruby/defines.h
+fstring.o: $(hdrdir)/ruby/encoding.h
+fstring.o: $(hdrdir)/ruby/intern.h
+fstring.o: $(hdrdir)/ruby/internal/abi.h
+fstring.o: $(hdrdir)/ruby/internal/anyargs.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+fstring.o: $(hdrdir)/ruby/internal/assume.h
+fstring.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+fstring.o: $(hdrdir)/ruby/internal/attr/artificial.h
+fstring.o: $(hdrdir)/ruby/internal/attr/cold.h
+fstring.o: $(hdrdir)/ruby/internal/attr/const.h
+fstring.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+fstring.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+fstring.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+fstring.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+fstring.o: $(hdrdir)/ruby/internal/attr/error.h
+fstring.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+fstring.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+fstring.o: $(hdrdir)/ruby/internal/attr/format.h
+fstring.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+fstring.o: $(hdrdir)/ruby/internal/attr/noalias.h
+fstring.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+fstring.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+fstring.o: $(hdrdir)/ruby/internal/attr/noinline.h
+fstring.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+fstring.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+fstring.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+fstring.o: $(hdrdir)/ruby/internal/attr/pure.h
+fstring.o: $(hdrdir)/ruby/internal/attr/restrict.h
+fstring.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+fstring.o: $(hdrdir)/ruby/internal/attr/warning.h
+fstring.o: $(hdrdir)/ruby/internal/attr/weakref.h
+fstring.o: $(hdrdir)/ruby/internal/cast.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_since.h
+fstring.o: $(hdrdir)/ruby/internal/config.h
+fstring.o: $(hdrdir)/ruby/internal/constant_p.h
+fstring.o: $(hdrdir)/ruby/internal/core.h
+fstring.o: $(hdrdir)/ruby/internal/core/rarray.h
+fstring.o: $(hdrdir)/ruby/internal/core/rbasic.h
+fstring.o: $(hdrdir)/ruby/internal/core/rbignum.h
+fstring.o: $(hdrdir)/ruby/internal/core/rclass.h
+fstring.o: $(hdrdir)/ruby/internal/core/rdata.h
+fstring.o: $(hdrdir)/ruby/internal/core/rfile.h
+fstring.o: $(hdrdir)/ruby/internal/core/rhash.h
+fstring.o: $(hdrdir)/ruby/internal/core/robject.h
+fstring.o: $(hdrdir)/ruby/internal/core/rregexp.h
+fstring.o: $(hdrdir)/ruby/internal/core/rstring.h
+fstring.o: $(hdrdir)/ruby/internal/core/rstruct.h
+fstring.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+fstring.o: $(hdrdir)/ruby/internal/ctype.h
+fstring.o: $(hdrdir)/ruby/internal/dllexport.h
+fstring.o: $(hdrdir)/ruby/internal/dosish.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/re.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/string.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+fstring.o: $(hdrdir)/ruby/internal/error.h
+fstring.o: $(hdrdir)/ruby/internal/eval.h
+fstring.o: $(hdrdir)/ruby/internal/event.h
+fstring.o: $(hdrdir)/ruby/internal/fl_type.h
+fstring.o: $(hdrdir)/ruby/internal/gc.h
+fstring.o: $(hdrdir)/ruby/internal/glob.h
+fstring.o: $(hdrdir)/ruby/internal/globals.h
+fstring.o: $(hdrdir)/ruby/internal/has/attribute.h
+fstring.o: $(hdrdir)/ruby/internal/has/builtin.h
+fstring.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+fstring.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+fstring.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+fstring.o: $(hdrdir)/ruby/internal/has/extension.h
+fstring.o: $(hdrdir)/ruby/internal/has/feature.h
+fstring.o: $(hdrdir)/ruby/internal/has/warning.h
+fstring.o: $(hdrdir)/ruby/internal/intern/array.h
+fstring.o: $(hdrdir)/ruby/internal/intern/bignum.h
+fstring.o: $(hdrdir)/ruby/internal/intern/class.h
+fstring.o: $(hdrdir)/ruby/internal/intern/compar.h
+fstring.o: $(hdrdir)/ruby/internal/intern/complex.h
+fstring.o: $(hdrdir)/ruby/internal/intern/cont.h
+fstring.o: $(hdrdir)/ruby/internal/intern/dir.h
+fstring.o: $(hdrdir)/ruby/internal/intern/enum.h
+fstring.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+fstring.o: $(hdrdir)/ruby/internal/intern/error.h
+fstring.o: $(hdrdir)/ruby/internal/intern/eval.h
+fstring.o: $(hdrdir)/ruby/internal/intern/file.h
+fstring.o: $(hdrdir)/ruby/internal/intern/hash.h
+fstring.o: $(hdrdir)/ruby/internal/intern/io.h
+fstring.o: $(hdrdir)/ruby/internal/intern/load.h
+fstring.o: $(hdrdir)/ruby/internal/intern/marshal.h
+fstring.o: $(hdrdir)/ruby/internal/intern/numeric.h
+fstring.o: $(hdrdir)/ruby/internal/intern/object.h
+fstring.o: $(hdrdir)/ruby/internal/intern/parse.h
+fstring.o: $(hdrdir)/ruby/internal/intern/proc.h
+fstring.o: $(hdrdir)/ruby/internal/intern/process.h
+fstring.o: $(hdrdir)/ruby/internal/intern/random.h
+fstring.o: $(hdrdir)/ruby/internal/intern/range.h
+fstring.o: $(hdrdir)/ruby/internal/intern/rational.h
+fstring.o: $(hdrdir)/ruby/internal/intern/re.h
+fstring.o: $(hdrdir)/ruby/internal/intern/ruby.h
+fstring.o: $(hdrdir)/ruby/internal/intern/select.h
+fstring.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+fstring.o: $(hdrdir)/ruby/internal/intern/set.h
+fstring.o: $(hdrdir)/ruby/internal/intern/signal.h
+fstring.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+fstring.o: $(hdrdir)/ruby/internal/intern/string.h
+fstring.o: $(hdrdir)/ruby/internal/intern/struct.h
+fstring.o: $(hdrdir)/ruby/internal/intern/thread.h
+fstring.o: $(hdrdir)/ruby/internal/intern/time.h
+fstring.o: $(hdrdir)/ruby/internal/intern/variable.h
+fstring.o: $(hdrdir)/ruby/internal/intern/vm.h
+fstring.o: $(hdrdir)/ruby/internal/interpreter.h
+fstring.o: $(hdrdir)/ruby/internal/iterator.h
+fstring.o: $(hdrdir)/ruby/internal/memory.h
+fstring.o: $(hdrdir)/ruby/internal/method.h
+fstring.o: $(hdrdir)/ruby/internal/module.h
+fstring.o: $(hdrdir)/ruby/internal/newobj.h
+fstring.o: $(hdrdir)/ruby/internal/scan_args.h
+fstring.o: $(hdrdir)/ruby/internal/special_consts.h
+fstring.o: $(hdrdir)/ruby/internal/static_assert.h
+fstring.o: $(hdrdir)/ruby/internal/stdalign.h
+fstring.o: $(hdrdir)/ruby/internal/stdbool.h
+fstring.o: $(hdrdir)/ruby/internal/stdckdint.h
+fstring.o: $(hdrdir)/ruby/internal/symbol.h
+fstring.o: $(hdrdir)/ruby/internal/value.h
+fstring.o: $(hdrdir)/ruby/internal/value_type.h
+fstring.o: $(hdrdir)/ruby/internal/variable.h
+fstring.o: $(hdrdir)/ruby/internal/warning_push.h
+fstring.o: $(hdrdir)/ruby/internal/xmalloc.h
+fstring.o: $(hdrdir)/ruby/missing.h
+fstring.o: $(hdrdir)/ruby/onigmo.h
+fstring.o: $(hdrdir)/ruby/oniguruma.h
+fstring.o: $(hdrdir)/ruby/ruby.h
+fstring.o: $(hdrdir)/ruby/st.h
+fstring.o: $(hdrdir)/ruby/subst.h
+fstring.o: $(top_srcdir)/encindex.h
+fstring.o: $(top_srcdir)/internal/compilers.h
+fstring.o: $(top_srcdir)/internal/string.h
+fstring.o: fstring.c
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+modify.o: $(RUBY_EXTCONF_H)
+modify.o: $(arch_hdrdir)/ruby/config.h
+modify.o: $(hdrdir)/ruby.h
+modify.o: $(hdrdir)/ruby/assert.h
+modify.o: $(hdrdir)/ruby/backward.h
+modify.o: $(hdrdir)/ruby/backward/2/assume.h
+modify.o: $(hdrdir)/ruby/backward/2/attributes.h
+modify.o: $(hdrdir)/ruby/backward/2/bool.h
+modify.o: $(hdrdir)/ruby/backward/2/inttypes.h
+modify.o: $(hdrdir)/ruby/backward/2/limits.h
+modify.o: $(hdrdir)/ruby/backward/2/long_long.h
+modify.o: $(hdrdir)/ruby/backward/2/stdalign.h
+modify.o: $(hdrdir)/ruby/backward/2/stdarg.h
+modify.o: $(hdrdir)/ruby/defines.h
+modify.o: $(hdrdir)/ruby/intern.h
+modify.o: $(hdrdir)/ruby/internal/abi.h
+modify.o: $(hdrdir)/ruby/internal/anyargs.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+modify.o: $(hdrdir)/ruby/internal/assume.h
+modify.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+modify.o: $(hdrdir)/ruby/internal/attr/artificial.h
+modify.o: $(hdrdir)/ruby/internal/attr/cold.h
+modify.o: $(hdrdir)/ruby/internal/attr/const.h
+modify.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+modify.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+modify.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+modify.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+modify.o: $(hdrdir)/ruby/internal/attr/error.h
+modify.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+modify.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+modify.o: $(hdrdir)/ruby/internal/attr/format.h
+modify.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+modify.o: $(hdrdir)/ruby/internal/attr/noalias.h
+modify.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+modify.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+modify.o: $(hdrdir)/ruby/internal/attr/noinline.h
+modify.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+modify.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+modify.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+modify.o: $(hdrdir)/ruby/internal/attr/pure.h
+modify.o: $(hdrdir)/ruby/internal/attr/restrict.h
+modify.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+modify.o: $(hdrdir)/ruby/internal/attr/warning.h
+modify.o: $(hdrdir)/ruby/internal/attr/weakref.h
+modify.o: $(hdrdir)/ruby/internal/cast.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+modify.o: $(hdrdir)/ruby/internal/compiler_since.h
+modify.o: $(hdrdir)/ruby/internal/config.h
+modify.o: $(hdrdir)/ruby/internal/constant_p.h
+modify.o: $(hdrdir)/ruby/internal/core.h
+modify.o: $(hdrdir)/ruby/internal/core/rarray.h
+modify.o: $(hdrdir)/ruby/internal/core/rbasic.h
+modify.o: $(hdrdir)/ruby/internal/core/rbignum.h
+modify.o: $(hdrdir)/ruby/internal/core/rclass.h
+modify.o: $(hdrdir)/ruby/internal/core/rdata.h
+modify.o: $(hdrdir)/ruby/internal/core/rfile.h
+modify.o: $(hdrdir)/ruby/internal/core/rhash.h
+modify.o: $(hdrdir)/ruby/internal/core/robject.h
+modify.o: $(hdrdir)/ruby/internal/core/rregexp.h
+modify.o: $(hdrdir)/ruby/internal/core/rstring.h
+modify.o: $(hdrdir)/ruby/internal/core/rstruct.h
+modify.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+modify.o: $(hdrdir)/ruby/internal/ctype.h
+modify.o: $(hdrdir)/ruby/internal/dllexport.h
+modify.o: $(hdrdir)/ruby/internal/dosish.h
+modify.o: $(hdrdir)/ruby/internal/error.h
+modify.o: $(hdrdir)/ruby/internal/eval.h
+modify.o: $(hdrdir)/ruby/internal/event.h
+modify.o: $(hdrdir)/ruby/internal/fl_type.h
+modify.o: $(hdrdir)/ruby/internal/gc.h
+modify.o: $(hdrdir)/ruby/internal/glob.h
+modify.o: $(hdrdir)/ruby/internal/globals.h
+modify.o: $(hdrdir)/ruby/internal/has/attribute.h
+modify.o: $(hdrdir)/ruby/internal/has/builtin.h
+modify.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+modify.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+modify.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+modify.o: $(hdrdir)/ruby/internal/has/extension.h
+modify.o: $(hdrdir)/ruby/internal/has/feature.h
+modify.o: $(hdrdir)/ruby/internal/has/warning.h
+modify.o: $(hdrdir)/ruby/internal/intern/array.h
+modify.o: $(hdrdir)/ruby/internal/intern/bignum.h
+modify.o: $(hdrdir)/ruby/internal/intern/class.h
+modify.o: $(hdrdir)/ruby/internal/intern/compar.h
+modify.o: $(hdrdir)/ruby/internal/intern/complex.h
+modify.o: $(hdrdir)/ruby/internal/intern/cont.h
+modify.o: $(hdrdir)/ruby/internal/intern/dir.h
+modify.o: $(hdrdir)/ruby/internal/intern/enum.h
+modify.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+modify.o: $(hdrdir)/ruby/internal/intern/error.h
+modify.o: $(hdrdir)/ruby/internal/intern/eval.h
+modify.o: $(hdrdir)/ruby/internal/intern/file.h
+modify.o: $(hdrdir)/ruby/internal/intern/hash.h
+modify.o: $(hdrdir)/ruby/internal/intern/io.h
+modify.o: $(hdrdir)/ruby/internal/intern/load.h
+modify.o: $(hdrdir)/ruby/internal/intern/marshal.h
+modify.o: $(hdrdir)/ruby/internal/intern/numeric.h
+modify.o: $(hdrdir)/ruby/internal/intern/object.h
+modify.o: $(hdrdir)/ruby/internal/intern/parse.h
+modify.o: $(hdrdir)/ruby/internal/intern/proc.h
+modify.o: $(hdrdir)/ruby/internal/intern/process.h
+modify.o: $(hdrdir)/ruby/internal/intern/random.h
+modify.o: $(hdrdir)/ruby/internal/intern/range.h
+modify.o: $(hdrdir)/ruby/internal/intern/rational.h
+modify.o: $(hdrdir)/ruby/internal/intern/re.h
+modify.o: $(hdrdir)/ruby/internal/intern/ruby.h
+modify.o: $(hdrdir)/ruby/internal/intern/select.h
+modify.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+modify.o: $(hdrdir)/ruby/internal/intern/set.h
+modify.o: $(hdrdir)/ruby/internal/intern/signal.h
+modify.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+modify.o: $(hdrdir)/ruby/internal/intern/string.h
+modify.o: $(hdrdir)/ruby/internal/intern/struct.h
+modify.o: $(hdrdir)/ruby/internal/intern/thread.h
+modify.o: $(hdrdir)/ruby/internal/intern/time.h
+modify.o: $(hdrdir)/ruby/internal/intern/variable.h
+modify.o: $(hdrdir)/ruby/internal/intern/vm.h
+modify.o: $(hdrdir)/ruby/internal/interpreter.h
+modify.o: $(hdrdir)/ruby/internal/iterator.h
+modify.o: $(hdrdir)/ruby/internal/memory.h
+modify.o: $(hdrdir)/ruby/internal/method.h
+modify.o: $(hdrdir)/ruby/internal/module.h
+modify.o: $(hdrdir)/ruby/internal/newobj.h
+modify.o: $(hdrdir)/ruby/internal/scan_args.h
+modify.o: $(hdrdir)/ruby/internal/special_consts.h
+modify.o: $(hdrdir)/ruby/internal/static_assert.h
+modify.o: $(hdrdir)/ruby/internal/stdalign.h
+modify.o: $(hdrdir)/ruby/internal/stdbool.h
+modify.o: $(hdrdir)/ruby/internal/stdckdint.h
+modify.o: $(hdrdir)/ruby/internal/symbol.h
+modify.o: $(hdrdir)/ruby/internal/value.h
+modify.o: $(hdrdir)/ruby/internal/value_type.h
+modify.o: $(hdrdir)/ruby/internal/variable.h
+modify.o: $(hdrdir)/ruby/internal/warning_push.h
+modify.o: $(hdrdir)/ruby/internal/xmalloc.h
+modify.o: $(hdrdir)/ruby/missing.h
+modify.o: $(hdrdir)/ruby/ruby.h
+modify.o: $(hdrdir)/ruby/st.h
+modify.o: $(hdrdir)/ruby/subst.h
+modify.o: modify.c
+new.o: $(RUBY_EXTCONF_H)
+new.o: $(arch_hdrdir)/ruby/config.h
+new.o: $(hdrdir)/ruby.h
+new.o: $(hdrdir)/ruby/assert.h
+new.o: $(hdrdir)/ruby/backward.h
+new.o: $(hdrdir)/ruby/backward/2/assume.h
+new.o: $(hdrdir)/ruby/backward/2/attributes.h
+new.o: $(hdrdir)/ruby/backward/2/bool.h
+new.o: $(hdrdir)/ruby/backward/2/inttypes.h
+new.o: $(hdrdir)/ruby/backward/2/limits.h
+new.o: $(hdrdir)/ruby/backward/2/long_long.h
+new.o: $(hdrdir)/ruby/backward/2/stdalign.h
+new.o: $(hdrdir)/ruby/backward/2/stdarg.h
+new.o: $(hdrdir)/ruby/defines.h
+new.o: $(hdrdir)/ruby/encoding.h
+new.o: $(hdrdir)/ruby/intern.h
+new.o: $(hdrdir)/ruby/internal/abi.h
+new.o: $(hdrdir)/ruby/internal/anyargs.h
+new.o: $(hdrdir)/ruby/internal/arithmetic.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+new.o: $(hdrdir)/ruby/internal/assume.h
+new.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+new.o: $(hdrdir)/ruby/internal/attr/artificial.h
+new.o: $(hdrdir)/ruby/internal/attr/cold.h
+new.o: $(hdrdir)/ruby/internal/attr/const.h
+new.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+new.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+new.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+new.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+new.o: $(hdrdir)/ruby/internal/attr/error.h
+new.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+new.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+new.o: $(hdrdir)/ruby/internal/attr/format.h
+new.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+new.o: $(hdrdir)/ruby/internal/attr/noalias.h
+new.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+new.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+new.o: $(hdrdir)/ruby/internal/attr/noinline.h
+new.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+new.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+new.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+new.o: $(hdrdir)/ruby/internal/attr/pure.h
+new.o: $(hdrdir)/ruby/internal/attr/restrict.h
+new.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+new.o: $(hdrdir)/ruby/internal/attr/warning.h
+new.o: $(hdrdir)/ruby/internal/attr/weakref.h
+new.o: $(hdrdir)/ruby/internal/cast.h
+new.o: $(hdrdir)/ruby/internal/compiler_is.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+new.o: $(hdrdir)/ruby/internal/compiler_since.h
+new.o: $(hdrdir)/ruby/internal/config.h
+new.o: $(hdrdir)/ruby/internal/constant_p.h
+new.o: $(hdrdir)/ruby/internal/core.h
+new.o: $(hdrdir)/ruby/internal/core/rarray.h
+new.o: $(hdrdir)/ruby/internal/core/rbasic.h
+new.o: $(hdrdir)/ruby/internal/core/rbignum.h
+new.o: $(hdrdir)/ruby/internal/core/rclass.h
+new.o: $(hdrdir)/ruby/internal/core/rdata.h
+new.o: $(hdrdir)/ruby/internal/core/rfile.h
+new.o: $(hdrdir)/ruby/internal/core/rhash.h
+new.o: $(hdrdir)/ruby/internal/core/robject.h
+new.o: $(hdrdir)/ruby/internal/core/rregexp.h
+new.o: $(hdrdir)/ruby/internal/core/rstring.h
+new.o: $(hdrdir)/ruby/internal/core/rstruct.h
+new.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+new.o: $(hdrdir)/ruby/internal/ctype.h
+new.o: $(hdrdir)/ruby/internal/dllexport.h
+new.o: $(hdrdir)/ruby/internal/dosish.h
+new.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+new.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+new.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+new.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+new.o: $(hdrdir)/ruby/internal/encoding/re.h
+new.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+new.o: $(hdrdir)/ruby/internal/encoding/string.h
+new.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+new.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+new.o: $(hdrdir)/ruby/internal/error.h
+new.o: $(hdrdir)/ruby/internal/eval.h
+new.o: $(hdrdir)/ruby/internal/event.h
+new.o: $(hdrdir)/ruby/internal/fl_type.h
+new.o: $(hdrdir)/ruby/internal/gc.h
+new.o: $(hdrdir)/ruby/internal/glob.h
+new.o: $(hdrdir)/ruby/internal/globals.h
+new.o: $(hdrdir)/ruby/internal/has/attribute.h
+new.o: $(hdrdir)/ruby/internal/has/builtin.h
+new.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+new.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+new.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+new.o: $(hdrdir)/ruby/internal/has/extension.h
+new.o: $(hdrdir)/ruby/internal/has/feature.h
+new.o: $(hdrdir)/ruby/internal/has/warning.h
+new.o: $(hdrdir)/ruby/internal/intern/array.h
+new.o: $(hdrdir)/ruby/internal/intern/bignum.h
+new.o: $(hdrdir)/ruby/internal/intern/class.h
+new.o: $(hdrdir)/ruby/internal/intern/compar.h
+new.o: $(hdrdir)/ruby/internal/intern/complex.h
+new.o: $(hdrdir)/ruby/internal/intern/cont.h
+new.o: $(hdrdir)/ruby/internal/intern/dir.h
+new.o: $(hdrdir)/ruby/internal/intern/enum.h
+new.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+new.o: $(hdrdir)/ruby/internal/intern/error.h
+new.o: $(hdrdir)/ruby/internal/intern/eval.h
+new.o: $(hdrdir)/ruby/internal/intern/file.h
+new.o: $(hdrdir)/ruby/internal/intern/hash.h
+new.o: $(hdrdir)/ruby/internal/intern/io.h
+new.o: $(hdrdir)/ruby/internal/intern/load.h
+new.o: $(hdrdir)/ruby/internal/intern/marshal.h
+new.o: $(hdrdir)/ruby/internal/intern/numeric.h
+new.o: $(hdrdir)/ruby/internal/intern/object.h
+new.o: $(hdrdir)/ruby/internal/intern/parse.h
+new.o: $(hdrdir)/ruby/internal/intern/proc.h
+new.o: $(hdrdir)/ruby/internal/intern/process.h
+new.o: $(hdrdir)/ruby/internal/intern/random.h
+new.o: $(hdrdir)/ruby/internal/intern/range.h
+new.o: $(hdrdir)/ruby/internal/intern/rational.h
+new.o: $(hdrdir)/ruby/internal/intern/re.h
+new.o: $(hdrdir)/ruby/internal/intern/ruby.h
+new.o: $(hdrdir)/ruby/internal/intern/select.h
+new.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+new.o: $(hdrdir)/ruby/internal/intern/set.h
+new.o: $(hdrdir)/ruby/internal/intern/signal.h
+new.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+new.o: $(hdrdir)/ruby/internal/intern/string.h
+new.o: $(hdrdir)/ruby/internal/intern/struct.h
+new.o: $(hdrdir)/ruby/internal/intern/thread.h
+new.o: $(hdrdir)/ruby/internal/intern/time.h
+new.o: $(hdrdir)/ruby/internal/intern/variable.h
+new.o: $(hdrdir)/ruby/internal/intern/vm.h
+new.o: $(hdrdir)/ruby/internal/interpreter.h
+new.o: $(hdrdir)/ruby/internal/iterator.h
+new.o: $(hdrdir)/ruby/internal/memory.h
+new.o: $(hdrdir)/ruby/internal/method.h
+new.o: $(hdrdir)/ruby/internal/module.h
+new.o: $(hdrdir)/ruby/internal/newobj.h
+new.o: $(hdrdir)/ruby/internal/scan_args.h
+new.o: $(hdrdir)/ruby/internal/special_consts.h
+new.o: $(hdrdir)/ruby/internal/static_assert.h
+new.o: $(hdrdir)/ruby/internal/stdalign.h
+new.o: $(hdrdir)/ruby/internal/stdbool.h
+new.o: $(hdrdir)/ruby/internal/stdckdint.h
+new.o: $(hdrdir)/ruby/internal/symbol.h
+new.o: $(hdrdir)/ruby/internal/value.h
+new.o: $(hdrdir)/ruby/internal/value_type.h
+new.o: $(hdrdir)/ruby/internal/variable.h
+new.o: $(hdrdir)/ruby/internal/warning_push.h
+new.o: $(hdrdir)/ruby/internal/xmalloc.h
+new.o: $(hdrdir)/ruby/missing.h
+new.o: $(hdrdir)/ruby/onigmo.h
+new.o: $(hdrdir)/ruby/oniguruma.h
+new.o: $(hdrdir)/ruby/ruby.h
+new.o: $(hdrdir)/ruby/st.h
+new.o: $(hdrdir)/ruby/subst.h
+new.o: new.c
+nofree.o: $(RUBY_EXTCONF_H)
+nofree.o: $(arch_hdrdir)/ruby/config.h
+nofree.o: $(hdrdir)/ruby.h
+nofree.o: $(hdrdir)/ruby/assert.h
+nofree.o: $(hdrdir)/ruby/backward.h
+nofree.o: $(hdrdir)/ruby/backward/2/assume.h
+nofree.o: $(hdrdir)/ruby/backward/2/attributes.h
+nofree.o: $(hdrdir)/ruby/backward/2/bool.h
+nofree.o: $(hdrdir)/ruby/backward/2/inttypes.h
+nofree.o: $(hdrdir)/ruby/backward/2/limits.h
+nofree.o: $(hdrdir)/ruby/backward/2/long_long.h
+nofree.o: $(hdrdir)/ruby/backward/2/stdalign.h
+nofree.o: $(hdrdir)/ruby/backward/2/stdarg.h
+nofree.o: $(hdrdir)/ruby/defines.h
+nofree.o: $(hdrdir)/ruby/intern.h
+nofree.o: $(hdrdir)/ruby/internal/abi.h
+nofree.o: $(hdrdir)/ruby/internal/anyargs.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+nofree.o: $(hdrdir)/ruby/internal/assume.h
+nofree.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+nofree.o: $(hdrdir)/ruby/internal/attr/artificial.h
+nofree.o: $(hdrdir)/ruby/internal/attr/cold.h
+nofree.o: $(hdrdir)/ruby/internal/attr/const.h
+nofree.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+nofree.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+nofree.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+nofree.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+nofree.o: $(hdrdir)/ruby/internal/attr/error.h
+nofree.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+nofree.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+nofree.o: $(hdrdir)/ruby/internal/attr/format.h
+nofree.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+nofree.o: $(hdrdir)/ruby/internal/attr/noalias.h
+nofree.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+nofree.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+nofree.o: $(hdrdir)/ruby/internal/attr/noinline.h
+nofree.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+nofree.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+nofree.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+nofree.o: $(hdrdir)/ruby/internal/attr/pure.h
+nofree.o: $(hdrdir)/ruby/internal/attr/restrict.h
+nofree.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+nofree.o: $(hdrdir)/ruby/internal/attr/warning.h
+nofree.o: $(hdrdir)/ruby/internal/attr/weakref.h
+nofree.o: $(hdrdir)/ruby/internal/cast.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_since.h
+nofree.o: $(hdrdir)/ruby/internal/config.h
+nofree.o: $(hdrdir)/ruby/internal/constant_p.h
+nofree.o: $(hdrdir)/ruby/internal/core.h
+nofree.o: $(hdrdir)/ruby/internal/core/rarray.h
+nofree.o: $(hdrdir)/ruby/internal/core/rbasic.h
+nofree.o: $(hdrdir)/ruby/internal/core/rbignum.h
+nofree.o: $(hdrdir)/ruby/internal/core/rclass.h
+nofree.o: $(hdrdir)/ruby/internal/core/rdata.h
+nofree.o: $(hdrdir)/ruby/internal/core/rfile.h
+nofree.o: $(hdrdir)/ruby/internal/core/rhash.h
+nofree.o: $(hdrdir)/ruby/internal/core/robject.h
+nofree.o: $(hdrdir)/ruby/internal/core/rregexp.h
+nofree.o: $(hdrdir)/ruby/internal/core/rstring.h
+nofree.o: $(hdrdir)/ruby/internal/core/rstruct.h
+nofree.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+nofree.o: $(hdrdir)/ruby/internal/ctype.h
+nofree.o: $(hdrdir)/ruby/internal/dllexport.h
+nofree.o: $(hdrdir)/ruby/internal/dosish.h
+nofree.o: $(hdrdir)/ruby/internal/error.h
+nofree.o: $(hdrdir)/ruby/internal/eval.h
+nofree.o: $(hdrdir)/ruby/internal/event.h
+nofree.o: $(hdrdir)/ruby/internal/fl_type.h
+nofree.o: $(hdrdir)/ruby/internal/gc.h
+nofree.o: $(hdrdir)/ruby/internal/glob.h
+nofree.o: $(hdrdir)/ruby/internal/globals.h
+nofree.o: $(hdrdir)/ruby/internal/has/attribute.h
+nofree.o: $(hdrdir)/ruby/internal/has/builtin.h
+nofree.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+nofree.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+nofree.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+nofree.o: $(hdrdir)/ruby/internal/has/extension.h
+nofree.o: $(hdrdir)/ruby/internal/has/feature.h
+nofree.o: $(hdrdir)/ruby/internal/has/warning.h
+nofree.o: $(hdrdir)/ruby/internal/intern/array.h
+nofree.o: $(hdrdir)/ruby/internal/intern/bignum.h
+nofree.o: $(hdrdir)/ruby/internal/intern/class.h
+nofree.o: $(hdrdir)/ruby/internal/intern/compar.h
+nofree.o: $(hdrdir)/ruby/internal/intern/complex.h
+nofree.o: $(hdrdir)/ruby/internal/intern/cont.h
+nofree.o: $(hdrdir)/ruby/internal/intern/dir.h
+nofree.o: $(hdrdir)/ruby/internal/intern/enum.h
+nofree.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+nofree.o: $(hdrdir)/ruby/internal/intern/error.h
+nofree.o: $(hdrdir)/ruby/internal/intern/eval.h
+nofree.o: $(hdrdir)/ruby/internal/intern/file.h
+nofree.o: $(hdrdir)/ruby/internal/intern/hash.h
+nofree.o: $(hdrdir)/ruby/internal/intern/io.h
+nofree.o: $(hdrdir)/ruby/internal/intern/load.h
+nofree.o: $(hdrdir)/ruby/internal/intern/marshal.h
+nofree.o: $(hdrdir)/ruby/internal/intern/numeric.h
+nofree.o: $(hdrdir)/ruby/internal/intern/object.h
+nofree.o: $(hdrdir)/ruby/internal/intern/parse.h
+nofree.o: $(hdrdir)/ruby/internal/intern/proc.h
+nofree.o: $(hdrdir)/ruby/internal/intern/process.h
+nofree.o: $(hdrdir)/ruby/internal/intern/random.h
+nofree.o: $(hdrdir)/ruby/internal/intern/range.h
+nofree.o: $(hdrdir)/ruby/internal/intern/rational.h
+nofree.o: $(hdrdir)/ruby/internal/intern/re.h
+nofree.o: $(hdrdir)/ruby/internal/intern/ruby.h
+nofree.o: $(hdrdir)/ruby/internal/intern/select.h
+nofree.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+nofree.o: $(hdrdir)/ruby/internal/intern/set.h
+nofree.o: $(hdrdir)/ruby/internal/intern/signal.h
+nofree.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+nofree.o: $(hdrdir)/ruby/internal/intern/string.h
+nofree.o: $(hdrdir)/ruby/internal/intern/struct.h
+nofree.o: $(hdrdir)/ruby/internal/intern/thread.h
+nofree.o: $(hdrdir)/ruby/internal/intern/time.h
+nofree.o: $(hdrdir)/ruby/internal/intern/variable.h
+nofree.o: $(hdrdir)/ruby/internal/intern/vm.h
+nofree.o: $(hdrdir)/ruby/internal/interpreter.h
+nofree.o: $(hdrdir)/ruby/internal/iterator.h
+nofree.o: $(hdrdir)/ruby/internal/memory.h
+nofree.o: $(hdrdir)/ruby/internal/method.h
+nofree.o: $(hdrdir)/ruby/internal/module.h
+nofree.o: $(hdrdir)/ruby/internal/newobj.h
+nofree.o: $(hdrdir)/ruby/internal/scan_args.h
+nofree.o: $(hdrdir)/ruby/internal/special_consts.h
+nofree.o: $(hdrdir)/ruby/internal/static_assert.h
+nofree.o: $(hdrdir)/ruby/internal/stdalign.h
+nofree.o: $(hdrdir)/ruby/internal/stdbool.h
+nofree.o: $(hdrdir)/ruby/internal/stdckdint.h
+nofree.o: $(hdrdir)/ruby/internal/symbol.h
+nofree.o: $(hdrdir)/ruby/internal/value.h
+nofree.o: $(hdrdir)/ruby/internal/value_type.h
+nofree.o: $(hdrdir)/ruby/internal/variable.h
+nofree.o: $(hdrdir)/ruby/internal/warning_push.h
+nofree.o: $(hdrdir)/ruby/internal/xmalloc.h
+nofree.o: $(hdrdir)/ruby/missing.h
+nofree.o: $(hdrdir)/ruby/ruby.h
+nofree.o: $(hdrdir)/ruby/st.h
+nofree.o: $(hdrdir)/ruby/subst.h
+nofree.o: nofree.c
+normalize.o: $(RUBY_EXTCONF_H)
+normalize.o: $(arch_hdrdir)/ruby/config.h
+normalize.o: $(hdrdir)/ruby/assert.h
+normalize.o: $(hdrdir)/ruby/backward.h
+normalize.o: $(hdrdir)/ruby/backward/2/assume.h
+normalize.o: $(hdrdir)/ruby/backward/2/attributes.h
+normalize.o: $(hdrdir)/ruby/backward/2/bool.h
+normalize.o: $(hdrdir)/ruby/backward/2/inttypes.h
+normalize.o: $(hdrdir)/ruby/backward/2/limits.h
+normalize.o: $(hdrdir)/ruby/backward/2/long_long.h
+normalize.o: $(hdrdir)/ruby/backward/2/stdalign.h
+normalize.o: $(hdrdir)/ruby/backward/2/stdarg.h
+normalize.o: $(hdrdir)/ruby/defines.h
+normalize.o: $(hdrdir)/ruby/encoding.h
+normalize.o: $(hdrdir)/ruby/intern.h
+normalize.o: $(hdrdir)/ruby/internal/abi.h
+normalize.o: $(hdrdir)/ruby/internal/anyargs.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+normalize.o: $(hdrdir)/ruby/internal/assume.h
+normalize.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+normalize.o: $(hdrdir)/ruby/internal/attr/artificial.h
+normalize.o: $(hdrdir)/ruby/internal/attr/cold.h
+normalize.o: $(hdrdir)/ruby/internal/attr/const.h
+normalize.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+normalize.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+normalize.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+normalize.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+normalize.o: $(hdrdir)/ruby/internal/attr/error.h
+normalize.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+normalize.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+normalize.o: $(hdrdir)/ruby/internal/attr/format.h
+normalize.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+normalize.o: $(hdrdir)/ruby/internal/attr/noalias.h
+normalize.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+normalize.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+normalize.o: $(hdrdir)/ruby/internal/attr/noinline.h
+normalize.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+normalize.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+normalize.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+normalize.o: $(hdrdir)/ruby/internal/attr/pure.h
+normalize.o: $(hdrdir)/ruby/internal/attr/restrict.h
+normalize.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+normalize.o: $(hdrdir)/ruby/internal/attr/warning.h
+normalize.o: $(hdrdir)/ruby/internal/attr/weakref.h
+normalize.o: $(hdrdir)/ruby/internal/cast.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_since.h
+normalize.o: $(hdrdir)/ruby/internal/config.h
+normalize.o: $(hdrdir)/ruby/internal/constant_p.h
+normalize.o: $(hdrdir)/ruby/internal/core.h
+normalize.o: $(hdrdir)/ruby/internal/core/rarray.h
+normalize.o: $(hdrdir)/ruby/internal/core/rbasic.h
+normalize.o: $(hdrdir)/ruby/internal/core/rbignum.h
+normalize.o: $(hdrdir)/ruby/internal/core/rclass.h
+normalize.o: $(hdrdir)/ruby/internal/core/rdata.h
+normalize.o: $(hdrdir)/ruby/internal/core/rfile.h
+normalize.o: $(hdrdir)/ruby/internal/core/rhash.h
+normalize.o: $(hdrdir)/ruby/internal/core/robject.h
+normalize.o: $(hdrdir)/ruby/internal/core/rregexp.h
+normalize.o: $(hdrdir)/ruby/internal/core/rstring.h
+normalize.o: $(hdrdir)/ruby/internal/core/rstruct.h
+normalize.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+normalize.o: $(hdrdir)/ruby/internal/ctype.h
+normalize.o: $(hdrdir)/ruby/internal/dllexport.h
+normalize.o: $(hdrdir)/ruby/internal/dosish.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/re.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/string.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+normalize.o: $(hdrdir)/ruby/internal/error.h
+normalize.o: $(hdrdir)/ruby/internal/eval.h
+normalize.o: $(hdrdir)/ruby/internal/event.h
+normalize.o: $(hdrdir)/ruby/internal/fl_type.h
+normalize.o: $(hdrdir)/ruby/internal/gc.h
+normalize.o: $(hdrdir)/ruby/internal/glob.h
+normalize.o: $(hdrdir)/ruby/internal/globals.h
+normalize.o: $(hdrdir)/ruby/internal/has/attribute.h
+normalize.o: $(hdrdir)/ruby/internal/has/builtin.h
+normalize.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+normalize.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+normalize.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+normalize.o: $(hdrdir)/ruby/internal/has/extension.h
+normalize.o: $(hdrdir)/ruby/internal/has/feature.h
+normalize.o: $(hdrdir)/ruby/internal/has/warning.h
+normalize.o: $(hdrdir)/ruby/internal/intern/array.h
+normalize.o: $(hdrdir)/ruby/internal/intern/bignum.h
+normalize.o: $(hdrdir)/ruby/internal/intern/class.h
+normalize.o: $(hdrdir)/ruby/internal/intern/compar.h
+normalize.o: $(hdrdir)/ruby/internal/intern/complex.h
+normalize.o: $(hdrdir)/ruby/internal/intern/cont.h
+normalize.o: $(hdrdir)/ruby/internal/intern/dir.h
+normalize.o: $(hdrdir)/ruby/internal/intern/enum.h
+normalize.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+normalize.o: $(hdrdir)/ruby/internal/intern/error.h
+normalize.o: $(hdrdir)/ruby/internal/intern/eval.h
+normalize.o: $(hdrdir)/ruby/internal/intern/file.h
+normalize.o: $(hdrdir)/ruby/internal/intern/hash.h
+normalize.o: $(hdrdir)/ruby/internal/intern/io.h
+normalize.o: $(hdrdir)/ruby/internal/intern/load.h
+normalize.o: $(hdrdir)/ruby/internal/intern/marshal.h
+normalize.o: $(hdrdir)/ruby/internal/intern/numeric.h
+normalize.o: $(hdrdir)/ruby/internal/intern/object.h
+normalize.o: $(hdrdir)/ruby/internal/intern/parse.h
+normalize.o: $(hdrdir)/ruby/internal/intern/proc.h
+normalize.o: $(hdrdir)/ruby/internal/intern/process.h
+normalize.o: $(hdrdir)/ruby/internal/intern/random.h
+normalize.o: $(hdrdir)/ruby/internal/intern/range.h
+normalize.o: $(hdrdir)/ruby/internal/intern/rational.h
+normalize.o: $(hdrdir)/ruby/internal/intern/re.h
+normalize.o: $(hdrdir)/ruby/internal/intern/ruby.h
+normalize.o: $(hdrdir)/ruby/internal/intern/select.h
+normalize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+normalize.o: $(hdrdir)/ruby/internal/intern/set.h
+normalize.o: $(hdrdir)/ruby/internal/intern/signal.h
+normalize.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+normalize.o: $(hdrdir)/ruby/internal/intern/string.h
+normalize.o: $(hdrdir)/ruby/internal/intern/struct.h
+normalize.o: $(hdrdir)/ruby/internal/intern/thread.h
+normalize.o: $(hdrdir)/ruby/internal/intern/time.h
+normalize.o: $(hdrdir)/ruby/internal/intern/variable.h
+normalize.o: $(hdrdir)/ruby/internal/intern/vm.h
+normalize.o: $(hdrdir)/ruby/internal/interpreter.h
+normalize.o: $(hdrdir)/ruby/internal/iterator.h
+normalize.o: $(hdrdir)/ruby/internal/memory.h
+normalize.o: $(hdrdir)/ruby/internal/method.h
+normalize.o: $(hdrdir)/ruby/internal/module.h
+normalize.o: $(hdrdir)/ruby/internal/newobj.h
+normalize.o: $(hdrdir)/ruby/internal/scan_args.h
+normalize.o: $(hdrdir)/ruby/internal/special_consts.h
+normalize.o: $(hdrdir)/ruby/internal/static_assert.h
+normalize.o: $(hdrdir)/ruby/internal/stdalign.h
+normalize.o: $(hdrdir)/ruby/internal/stdbool.h
+normalize.o: $(hdrdir)/ruby/internal/stdckdint.h
+normalize.o: $(hdrdir)/ruby/internal/symbol.h
+normalize.o: $(hdrdir)/ruby/internal/value.h
+normalize.o: $(hdrdir)/ruby/internal/value_type.h
+normalize.o: $(hdrdir)/ruby/internal/variable.h
+normalize.o: $(hdrdir)/ruby/internal/warning_push.h
+normalize.o: $(hdrdir)/ruby/internal/xmalloc.h
+normalize.o: $(hdrdir)/ruby/missing.h
+normalize.o: $(hdrdir)/ruby/onigmo.h
+normalize.o: $(hdrdir)/ruby/oniguruma.h
+normalize.o: $(hdrdir)/ruby/ruby.h
+normalize.o: $(hdrdir)/ruby/st.h
+normalize.o: $(hdrdir)/ruby/subst.h
+normalize.o: $(top_srcdir)/internal/file.h
+normalize.o: normalize.c
+qsort.o: $(RUBY_EXTCONF_H)
+qsort.o: $(arch_hdrdir)/ruby/config.h
+qsort.o: $(hdrdir)/ruby.h
+qsort.o: $(hdrdir)/ruby/assert.h
+qsort.o: $(hdrdir)/ruby/backward.h
+qsort.o: $(hdrdir)/ruby/backward/2/assume.h
+qsort.o: $(hdrdir)/ruby/backward/2/attributes.h
+qsort.o: $(hdrdir)/ruby/backward/2/bool.h
+qsort.o: $(hdrdir)/ruby/backward/2/inttypes.h
+qsort.o: $(hdrdir)/ruby/backward/2/limits.h
+qsort.o: $(hdrdir)/ruby/backward/2/long_long.h
+qsort.o: $(hdrdir)/ruby/backward/2/stdalign.h
+qsort.o: $(hdrdir)/ruby/backward/2/stdarg.h
+qsort.o: $(hdrdir)/ruby/defines.h
+qsort.o: $(hdrdir)/ruby/encoding.h
+qsort.o: $(hdrdir)/ruby/intern.h
+qsort.o: $(hdrdir)/ruby/internal/abi.h
+qsort.o: $(hdrdir)/ruby/internal/anyargs.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+qsort.o: $(hdrdir)/ruby/internal/assume.h
+qsort.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+qsort.o: $(hdrdir)/ruby/internal/attr/artificial.h
+qsort.o: $(hdrdir)/ruby/internal/attr/cold.h
+qsort.o: $(hdrdir)/ruby/internal/attr/const.h
+qsort.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+qsort.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+qsort.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+qsort.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+qsort.o: $(hdrdir)/ruby/internal/attr/error.h
+qsort.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+qsort.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+qsort.o: $(hdrdir)/ruby/internal/attr/format.h
+qsort.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+qsort.o: $(hdrdir)/ruby/internal/attr/noalias.h
+qsort.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+qsort.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+qsort.o: $(hdrdir)/ruby/internal/attr/noinline.h
+qsort.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+qsort.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+qsort.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+qsort.o: $(hdrdir)/ruby/internal/attr/pure.h
+qsort.o: $(hdrdir)/ruby/internal/attr/restrict.h
+qsort.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+qsort.o: $(hdrdir)/ruby/internal/attr/warning.h
+qsort.o: $(hdrdir)/ruby/internal/attr/weakref.h
+qsort.o: $(hdrdir)/ruby/internal/cast.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_since.h
+qsort.o: $(hdrdir)/ruby/internal/config.h
+qsort.o: $(hdrdir)/ruby/internal/constant_p.h
+qsort.o: $(hdrdir)/ruby/internal/core.h
+qsort.o: $(hdrdir)/ruby/internal/core/rarray.h
+qsort.o: $(hdrdir)/ruby/internal/core/rbasic.h
+qsort.o: $(hdrdir)/ruby/internal/core/rbignum.h
+qsort.o: $(hdrdir)/ruby/internal/core/rclass.h
+qsort.o: $(hdrdir)/ruby/internal/core/rdata.h
+qsort.o: $(hdrdir)/ruby/internal/core/rfile.h
+qsort.o: $(hdrdir)/ruby/internal/core/rhash.h
+qsort.o: $(hdrdir)/ruby/internal/core/robject.h
+qsort.o: $(hdrdir)/ruby/internal/core/rregexp.h
+qsort.o: $(hdrdir)/ruby/internal/core/rstring.h
+qsort.o: $(hdrdir)/ruby/internal/core/rstruct.h
+qsort.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+qsort.o: $(hdrdir)/ruby/internal/ctype.h
+qsort.o: $(hdrdir)/ruby/internal/dllexport.h
+qsort.o: $(hdrdir)/ruby/internal/dosish.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/re.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/string.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+qsort.o: $(hdrdir)/ruby/internal/error.h
+qsort.o: $(hdrdir)/ruby/internal/eval.h
+qsort.o: $(hdrdir)/ruby/internal/event.h
+qsort.o: $(hdrdir)/ruby/internal/fl_type.h
+qsort.o: $(hdrdir)/ruby/internal/gc.h
+qsort.o: $(hdrdir)/ruby/internal/glob.h
+qsort.o: $(hdrdir)/ruby/internal/globals.h
+qsort.o: $(hdrdir)/ruby/internal/has/attribute.h
+qsort.o: $(hdrdir)/ruby/internal/has/builtin.h
+qsort.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+qsort.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+qsort.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+qsort.o: $(hdrdir)/ruby/internal/has/extension.h
+qsort.o: $(hdrdir)/ruby/internal/has/feature.h
+qsort.o: $(hdrdir)/ruby/internal/has/warning.h
+qsort.o: $(hdrdir)/ruby/internal/intern/array.h
+qsort.o: $(hdrdir)/ruby/internal/intern/bignum.h
+qsort.o: $(hdrdir)/ruby/internal/intern/class.h
+qsort.o: $(hdrdir)/ruby/internal/intern/compar.h
+qsort.o: $(hdrdir)/ruby/internal/intern/complex.h
+qsort.o: $(hdrdir)/ruby/internal/intern/cont.h
+qsort.o: $(hdrdir)/ruby/internal/intern/dir.h
+qsort.o: $(hdrdir)/ruby/internal/intern/enum.h
+qsort.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+qsort.o: $(hdrdir)/ruby/internal/intern/error.h
+qsort.o: $(hdrdir)/ruby/internal/intern/eval.h
+qsort.o: $(hdrdir)/ruby/internal/intern/file.h
+qsort.o: $(hdrdir)/ruby/internal/intern/hash.h
+qsort.o: $(hdrdir)/ruby/internal/intern/io.h
+qsort.o: $(hdrdir)/ruby/internal/intern/load.h
+qsort.o: $(hdrdir)/ruby/internal/intern/marshal.h
+qsort.o: $(hdrdir)/ruby/internal/intern/numeric.h
+qsort.o: $(hdrdir)/ruby/internal/intern/object.h
+qsort.o: $(hdrdir)/ruby/internal/intern/parse.h
+qsort.o: $(hdrdir)/ruby/internal/intern/proc.h
+qsort.o: $(hdrdir)/ruby/internal/intern/process.h
+qsort.o: $(hdrdir)/ruby/internal/intern/random.h
+qsort.o: $(hdrdir)/ruby/internal/intern/range.h
+qsort.o: $(hdrdir)/ruby/internal/intern/rational.h
+qsort.o: $(hdrdir)/ruby/internal/intern/re.h
+qsort.o: $(hdrdir)/ruby/internal/intern/ruby.h
+qsort.o: $(hdrdir)/ruby/internal/intern/select.h
+qsort.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+qsort.o: $(hdrdir)/ruby/internal/intern/set.h
+qsort.o: $(hdrdir)/ruby/internal/intern/signal.h
+qsort.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+qsort.o: $(hdrdir)/ruby/internal/intern/string.h
+qsort.o: $(hdrdir)/ruby/internal/intern/struct.h
+qsort.o: $(hdrdir)/ruby/internal/intern/thread.h
+qsort.o: $(hdrdir)/ruby/internal/intern/time.h
+qsort.o: $(hdrdir)/ruby/internal/intern/variable.h
+qsort.o: $(hdrdir)/ruby/internal/intern/vm.h
+qsort.o: $(hdrdir)/ruby/internal/interpreter.h
+qsort.o: $(hdrdir)/ruby/internal/iterator.h
+qsort.o: $(hdrdir)/ruby/internal/memory.h
+qsort.o: $(hdrdir)/ruby/internal/method.h
+qsort.o: $(hdrdir)/ruby/internal/module.h
+qsort.o: $(hdrdir)/ruby/internal/newobj.h
+qsort.o: $(hdrdir)/ruby/internal/scan_args.h
+qsort.o: $(hdrdir)/ruby/internal/special_consts.h
+qsort.o: $(hdrdir)/ruby/internal/static_assert.h
+qsort.o: $(hdrdir)/ruby/internal/stdalign.h
+qsort.o: $(hdrdir)/ruby/internal/stdbool.h
+qsort.o: $(hdrdir)/ruby/internal/stdckdint.h
+qsort.o: $(hdrdir)/ruby/internal/symbol.h
+qsort.o: $(hdrdir)/ruby/internal/value.h
+qsort.o: $(hdrdir)/ruby/internal/value_type.h
+qsort.o: $(hdrdir)/ruby/internal/variable.h
+qsort.o: $(hdrdir)/ruby/internal/warning_push.h
+qsort.o: $(hdrdir)/ruby/internal/xmalloc.h
+qsort.o: $(hdrdir)/ruby/missing.h
+qsort.o: $(hdrdir)/ruby/onigmo.h
+qsort.o: $(hdrdir)/ruby/oniguruma.h
+qsort.o: $(hdrdir)/ruby/ruby.h
+qsort.o: $(hdrdir)/ruby/st.h
+qsort.o: $(hdrdir)/ruby/subst.h
+qsort.o: $(hdrdir)/ruby/util.h
+qsort.o: qsort.c
+rb_interned_str.o: $(RUBY_EXTCONF_H)
+rb_interned_str.o: $(arch_hdrdir)/ruby/config.h
+rb_interned_str.o: $(hdrdir)/ruby.h
+rb_interned_str.o: $(hdrdir)/ruby/assert.h
+rb_interned_str.o: $(hdrdir)/ruby/backward.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/assume.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/attributes.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/bool.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/limits.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/long_long.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/stdarg.h
+rb_interned_str.o: $(hdrdir)/ruby/defines.h
+rb_interned_str.o: $(hdrdir)/ruby/intern.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/abi.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/anyargs.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/assume.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/cold.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/const.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/error.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/format.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/pure.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/warning.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/cast.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_since.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/config.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/constant_p.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rarray.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rclass.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rdata.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rfile.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rhash.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/robject.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rstring.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/ctype.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/dllexport.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/dosish.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/error.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/eval.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/event.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/fl_type.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/gc.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/glob.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/globals.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/attribute.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/builtin.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/extension.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/feature.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/warning.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/array.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/class.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/compar.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/complex.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/cont.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/dir.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/enum.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/error.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/eval.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/file.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/hash.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/io.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/load.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/object.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/parse.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/proc.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/process.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/random.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/range.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/rational.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/re.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/select.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/set.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/signal.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/string.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/struct.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/thread.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/time.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/variable.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/vm.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/interpreter.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/iterator.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/memory.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/method.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/module.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/newobj.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/scan_args.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/special_consts.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/static_assert.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/stdalign.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/stdbool.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/stdckdint.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/symbol.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/value.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/value_type.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/variable.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/warning_push.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/xmalloc.h
+rb_interned_str.o: $(hdrdir)/ruby/missing.h
+rb_interned_str.o: $(hdrdir)/ruby/ruby.h
+rb_interned_str.o: $(hdrdir)/ruby/st.h
+rb_interned_str.o: $(hdrdir)/ruby/subst.h
+rb_interned_str.o: rb_interned_str.c
+rb_str_dup.o: $(RUBY_EXTCONF_H)
+rb_str_dup.o: $(arch_hdrdir)/ruby/config.h
+rb_str_dup.o: $(hdrdir)/ruby.h
+rb_str_dup.o: $(hdrdir)/ruby/assert.h
+rb_str_dup.o: $(hdrdir)/ruby/backward.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/assume.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/attributes.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/bool.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/limits.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/long_long.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/stdarg.h
+rb_str_dup.o: $(hdrdir)/ruby/defines.h
+rb_str_dup.o: $(hdrdir)/ruby/intern.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/abi.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/anyargs.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/assume.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/cold.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/const.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/error.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/format.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/pure.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/warning.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/cast.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_since.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/config.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/constant_p.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rarray.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rclass.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rdata.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rfile.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rhash.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/robject.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rstring.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/ctype.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/dllexport.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/dosish.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/error.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/eval.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/event.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/fl_type.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/gc.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/glob.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/globals.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/attribute.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/builtin.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/extension.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/feature.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/warning.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/array.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/class.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/compar.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/complex.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/cont.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/dir.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/enum.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/error.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/eval.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/file.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/hash.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/io.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/load.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/object.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/parse.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/proc.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/process.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/random.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/range.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/rational.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/re.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/select.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/set.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/signal.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/string.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/struct.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/thread.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/time.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/variable.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/vm.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/interpreter.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/iterator.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/memory.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/method.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/module.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/newobj.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/scan_args.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/special_consts.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/static_assert.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/stdalign.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/stdbool.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/stdckdint.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/symbol.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/value.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/value_type.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/variable.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/warning_push.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/xmalloc.h
+rb_str_dup.o: $(hdrdir)/ruby/missing.h
+rb_str_dup.o: $(hdrdir)/ruby/ruby.h
+rb_str_dup.o: $(hdrdir)/ruby/st.h
+rb_str_dup.o: $(hdrdir)/ruby/subst.h
+rb_str_dup.o: rb_str_dup.c
+set_len.o: $(RUBY_EXTCONF_H)
+set_len.o: $(arch_hdrdir)/ruby/config.h
+set_len.o: $(hdrdir)/ruby.h
+set_len.o: $(hdrdir)/ruby/assert.h
+set_len.o: $(hdrdir)/ruby/backward.h
+set_len.o: $(hdrdir)/ruby/backward/2/assume.h
+set_len.o: $(hdrdir)/ruby/backward/2/attributes.h
+set_len.o: $(hdrdir)/ruby/backward/2/bool.h
+set_len.o: $(hdrdir)/ruby/backward/2/inttypes.h
+set_len.o: $(hdrdir)/ruby/backward/2/limits.h
+set_len.o: $(hdrdir)/ruby/backward/2/long_long.h
+set_len.o: $(hdrdir)/ruby/backward/2/stdalign.h
+set_len.o: $(hdrdir)/ruby/backward/2/stdarg.h
+set_len.o: $(hdrdir)/ruby/defines.h
+set_len.o: $(hdrdir)/ruby/intern.h
+set_len.o: $(hdrdir)/ruby/internal/abi.h
+set_len.o: $(hdrdir)/ruby/internal/anyargs.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+set_len.o: $(hdrdir)/ruby/internal/assume.h
+set_len.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+set_len.o: $(hdrdir)/ruby/internal/attr/artificial.h
+set_len.o: $(hdrdir)/ruby/internal/attr/cold.h
+set_len.o: $(hdrdir)/ruby/internal/attr/const.h
+set_len.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+set_len.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+set_len.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+set_len.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+set_len.o: $(hdrdir)/ruby/internal/attr/error.h
+set_len.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+set_len.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+set_len.o: $(hdrdir)/ruby/internal/attr/format.h
+set_len.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+set_len.o: $(hdrdir)/ruby/internal/attr/noalias.h
+set_len.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+set_len.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+set_len.o: $(hdrdir)/ruby/internal/attr/noinline.h
+set_len.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+set_len.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+set_len.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+set_len.o: $(hdrdir)/ruby/internal/attr/pure.h
+set_len.o: $(hdrdir)/ruby/internal/attr/restrict.h
+set_len.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+set_len.o: $(hdrdir)/ruby/internal/attr/warning.h
+set_len.o: $(hdrdir)/ruby/internal/attr/weakref.h
+set_len.o: $(hdrdir)/ruby/internal/cast.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_since.h
+set_len.o: $(hdrdir)/ruby/internal/config.h
+set_len.o: $(hdrdir)/ruby/internal/constant_p.h
+set_len.o: $(hdrdir)/ruby/internal/core.h
+set_len.o: $(hdrdir)/ruby/internal/core/rarray.h
+set_len.o: $(hdrdir)/ruby/internal/core/rbasic.h
+set_len.o: $(hdrdir)/ruby/internal/core/rbignum.h
+set_len.o: $(hdrdir)/ruby/internal/core/rclass.h
+set_len.o: $(hdrdir)/ruby/internal/core/rdata.h
+set_len.o: $(hdrdir)/ruby/internal/core/rfile.h
+set_len.o: $(hdrdir)/ruby/internal/core/rhash.h
+set_len.o: $(hdrdir)/ruby/internal/core/robject.h
+set_len.o: $(hdrdir)/ruby/internal/core/rregexp.h
+set_len.o: $(hdrdir)/ruby/internal/core/rstring.h
+set_len.o: $(hdrdir)/ruby/internal/core/rstruct.h
+set_len.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+set_len.o: $(hdrdir)/ruby/internal/ctype.h
+set_len.o: $(hdrdir)/ruby/internal/dllexport.h
+set_len.o: $(hdrdir)/ruby/internal/dosish.h
+set_len.o: $(hdrdir)/ruby/internal/error.h
+set_len.o: $(hdrdir)/ruby/internal/eval.h
+set_len.o: $(hdrdir)/ruby/internal/event.h
+set_len.o: $(hdrdir)/ruby/internal/fl_type.h
+set_len.o: $(hdrdir)/ruby/internal/gc.h
+set_len.o: $(hdrdir)/ruby/internal/glob.h
+set_len.o: $(hdrdir)/ruby/internal/globals.h
+set_len.o: $(hdrdir)/ruby/internal/has/attribute.h
+set_len.o: $(hdrdir)/ruby/internal/has/builtin.h
+set_len.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+set_len.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+set_len.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+set_len.o: $(hdrdir)/ruby/internal/has/extension.h
+set_len.o: $(hdrdir)/ruby/internal/has/feature.h
+set_len.o: $(hdrdir)/ruby/internal/has/warning.h
+set_len.o: $(hdrdir)/ruby/internal/intern/array.h
+set_len.o: $(hdrdir)/ruby/internal/intern/bignum.h
+set_len.o: $(hdrdir)/ruby/internal/intern/class.h
+set_len.o: $(hdrdir)/ruby/internal/intern/compar.h
+set_len.o: $(hdrdir)/ruby/internal/intern/complex.h
+set_len.o: $(hdrdir)/ruby/internal/intern/cont.h
+set_len.o: $(hdrdir)/ruby/internal/intern/dir.h
+set_len.o: $(hdrdir)/ruby/internal/intern/enum.h
+set_len.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+set_len.o: $(hdrdir)/ruby/internal/intern/error.h
+set_len.o: $(hdrdir)/ruby/internal/intern/eval.h
+set_len.o: $(hdrdir)/ruby/internal/intern/file.h
+set_len.o: $(hdrdir)/ruby/internal/intern/hash.h
+set_len.o: $(hdrdir)/ruby/internal/intern/io.h
+set_len.o: $(hdrdir)/ruby/internal/intern/load.h
+set_len.o: $(hdrdir)/ruby/internal/intern/marshal.h
+set_len.o: $(hdrdir)/ruby/internal/intern/numeric.h
+set_len.o: $(hdrdir)/ruby/internal/intern/object.h
+set_len.o: $(hdrdir)/ruby/internal/intern/parse.h
+set_len.o: $(hdrdir)/ruby/internal/intern/proc.h
+set_len.o: $(hdrdir)/ruby/internal/intern/process.h
+set_len.o: $(hdrdir)/ruby/internal/intern/random.h
+set_len.o: $(hdrdir)/ruby/internal/intern/range.h
+set_len.o: $(hdrdir)/ruby/internal/intern/rational.h
+set_len.o: $(hdrdir)/ruby/internal/intern/re.h
+set_len.o: $(hdrdir)/ruby/internal/intern/ruby.h
+set_len.o: $(hdrdir)/ruby/internal/intern/select.h
+set_len.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+set_len.o: $(hdrdir)/ruby/internal/intern/set.h
+set_len.o: $(hdrdir)/ruby/internal/intern/signal.h
+set_len.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+set_len.o: $(hdrdir)/ruby/internal/intern/string.h
+set_len.o: $(hdrdir)/ruby/internal/intern/struct.h
+set_len.o: $(hdrdir)/ruby/internal/intern/thread.h
+set_len.o: $(hdrdir)/ruby/internal/intern/time.h
+set_len.o: $(hdrdir)/ruby/internal/intern/variable.h
+set_len.o: $(hdrdir)/ruby/internal/intern/vm.h
+set_len.o: $(hdrdir)/ruby/internal/interpreter.h
+set_len.o: $(hdrdir)/ruby/internal/iterator.h
+set_len.o: $(hdrdir)/ruby/internal/memory.h
+set_len.o: $(hdrdir)/ruby/internal/method.h
+set_len.o: $(hdrdir)/ruby/internal/module.h
+set_len.o: $(hdrdir)/ruby/internal/newobj.h
+set_len.o: $(hdrdir)/ruby/internal/scan_args.h
+set_len.o: $(hdrdir)/ruby/internal/special_consts.h
+set_len.o: $(hdrdir)/ruby/internal/static_assert.h
+set_len.o: $(hdrdir)/ruby/internal/stdalign.h
+set_len.o: $(hdrdir)/ruby/internal/stdbool.h
+set_len.o: $(hdrdir)/ruby/internal/stdckdint.h
+set_len.o: $(hdrdir)/ruby/internal/symbol.h
+set_len.o: $(hdrdir)/ruby/internal/value.h
+set_len.o: $(hdrdir)/ruby/internal/value_type.h
+set_len.o: $(hdrdir)/ruby/internal/variable.h
+set_len.o: $(hdrdir)/ruby/internal/warning_push.h
+set_len.o: $(hdrdir)/ruby/internal/xmalloc.h
+set_len.o: $(hdrdir)/ruby/missing.h
+set_len.o: $(hdrdir)/ruby/ruby.h
+set_len.o: $(hdrdir)/ruby/st.h
+set_len.o: $(hdrdir)/ruby/subst.h
+set_len.o: set_len.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/string/ellipsize.c b/ext/-test-/string/ellipsize.c
new file mode 100644
index 0000000000..6034408724
--- /dev/null
+++ b/ext/-test-/string/ellipsize.c
@@ -0,0 +1,13 @@
+#include "ruby.h"
+
+static VALUE
+bug_str_ellipsize(VALUE str, VALUE len)
+{
+ return rb_str_ellipsize(str, NUM2LONG(len));
+}
+
+void
+Init_string_ellipsize(VALUE klass)
+{
+ rb_define_method(klass, "ellipsize", bug_str_ellipsize, 1);
+}
diff --git a/ext/-test-/string/enc_associate.c b/ext/-test-/string/enc_associate.c
new file mode 100644
index 0000000000..594d8a43a4
--- /dev/null
+++ b/ext/-test-/string/enc_associate.c
@@ -0,0 +1,22 @@
+#include "ruby.h"
+#include "ruby/encoding.h"
+
+VALUE
+bug_str_enc_associate(VALUE str, VALUE enc)
+{
+ return rb_enc_associate(str, rb_to_encoding(enc));
+}
+
+VALUE
+bug_str_encoding_index(VALUE self, VALUE str)
+{
+ int idx = rb_enc_get_index(str);
+ return INT2NUM(idx);
+}
+
+void
+Init_string_enc_associate(VALUE klass)
+{
+ rb_define_method(klass, "associate_encoding!", bug_str_enc_associate, 1);
+ rb_define_singleton_method(klass, "encoding_index", bug_str_encoding_index, 1);
+}
diff --git a/ext/-test-/string/enc_dummy.c b/ext/-test-/string/enc_dummy.c
new file mode 100644
index 0000000000..4169552655
--- /dev/null
+++ b/ext/-test-/string/enc_dummy.c
@@ -0,0 +1,15 @@
+#include "ruby.h"
+#include "ruby/encoding.h"
+
+VALUE
+bug_rb_define_dummy_encoding(VALUE self, VALUE name)
+{
+ int idx = rb_define_dummy_encoding(RSTRING_PTR(name));
+ return rb_enc_from_encoding(rb_enc_from_index(idx));
+}
+
+void
+Init_string_enc_dummy(VALUE klass)
+{
+ rb_define_singleton_method(klass, "rb_define_dummy_encoding", bug_rb_define_dummy_encoding, 1);
+}
diff --git a/ext/-test-/string/enc_str_buf_cat.c b/ext/-test-/string/enc_str_buf_cat.c
new file mode 100644
index 0000000000..4c1b262e1e
--- /dev/null
+++ b/ext/-test-/string/enc_str_buf_cat.c
@@ -0,0 +1,28 @@
+#include "ruby/ruby.h"
+#include "ruby/encoding.h"
+
+static VALUE
+enc_str_buf_cat(VALUE str, VALUE str2)
+{
+ return rb_enc_str_buf_cat(str, RSTRING_PTR(str2), RSTRING_LEN(str2), rb_enc_get(str2));
+}
+
+static VALUE
+str_conv_enc_opts(VALUE str, VALUE from, VALUE to, VALUE ecflags, VALUE ecopts)
+{
+ rb_encoding *from_enc = NIL_P(from) ? NULL : rb_to_encoding(from);
+ rb_encoding *to_enc = NIL_P(to) ? NULL : rb_to_encoding(to);
+ int flags = NUM2INT(ecflags);
+ if (!NIL_P(ecopts)) {
+ Check_Type(ecopts, T_HASH);
+ OBJ_FREEZE(ecopts);
+ }
+ return rb_str_conv_enc_opts(str, from_enc, to_enc, flags, ecopts);
+}
+
+void
+Init_string_enc_str_buf_cat(VALUE klass)
+{
+ rb_define_method(klass, "enc_str_buf_cat", enc_str_buf_cat, 1);
+ rb_define_method(klass, "str_conv_enc_opts", str_conv_enc_opts, 4);
+}
diff --git a/ext/-test-/string/extconf.rb b/ext/-test-/string/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/string/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/string/fstring.c b/ext/-test-/string/fstring.c
new file mode 100644
index 0000000000..0b5940f28c
--- /dev/null
+++ b/ext/-test-/string/fstring.c
@@ -0,0 +1,38 @@
+#include "ruby.h"
+#include "ruby/encoding.h"
+#include "internal/string.h"
+
+VALUE
+bug_s_fstring(VALUE self, VALUE str)
+{
+ return rb_str_to_interned_str(str);
+}
+
+VALUE
+bug_s_fstring_fake_str(VALUE self)
+{
+ static const char literal[] = "abcdefghijklmnopqrstuvwxyz";
+ struct RString fake_str = {RBASIC_INIT};
+ return rb_str_to_interned_str(rb_setup_fake_str(&fake_str, literal, sizeof(literal) - 1, 0));
+}
+
+VALUE
+bug_s_rb_enc_interned_str(VALUE self, VALUE encoding)
+{
+ return rb_enc_interned_str("foo", 3, NIL_P(encoding) ? NULL : RTYPEDDATA_GET_DATA(encoding));
+}
+
+VALUE
+bug_s_rb_enc_str_new(VALUE self, VALUE encoding)
+{
+ return rb_enc_str_new("foo", 3, NIL_P(encoding) ? NULL : RTYPEDDATA_GET_DATA(encoding));
+}
+
+void
+Init_string_fstring(VALUE klass)
+{
+ rb_define_singleton_method(klass, "fstring", bug_s_fstring, 1);
+ rb_define_singleton_method(klass, "fstring_fake_str", bug_s_fstring_fake_str, 0);
+ rb_define_singleton_method(klass, "rb_enc_interned_str", bug_s_rb_enc_interned_str, 1);
+ rb_define_singleton_method(klass, "rb_enc_str_new", bug_s_rb_enc_str_new, 1);
+}
diff --git a/ext/-test-/string/init.c b/ext/-test-/string/init.c
new file mode 100644
index 0000000000..a74245c8d7
--- /dev/null
+++ b/ext/-test-/string/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_string_##n(VALUE klass); Init_string_##n(klass);}
+
+void
+Init_string(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "String", rb_cString);
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/string/modify.c b/ext/-test-/string/modify.c
new file mode 100644
index 0000000000..945febc7e3
--- /dev/null
+++ b/ext/-test-/string/modify.c
@@ -0,0 +1,22 @@
+#include "ruby.h"
+
+VALUE
+bug_str_modify(VALUE str)
+{
+ rb_str_modify(str);
+ return str;
+}
+
+VALUE
+bug_str_modify_expand(VALUE str, VALUE expand)
+{
+ rb_str_modify_expand(str, NUM2LONG(expand));
+ return str;
+}
+
+void
+Init_string_modify(VALUE klass)
+{
+ rb_define_method(klass, "modify!", bug_str_modify, 0);
+ rb_define_method(klass, "modify_expand!", bug_str_modify_expand, 1);
+}
diff --git a/ext/-test-/string/new.c b/ext/-test-/string/new.c
new file mode 100644
index 0000000000..60625b8300
--- /dev/null
+++ b/ext/-test-/string/new.c
@@ -0,0 +1,21 @@
+#include "ruby.h"
+#include "ruby/encoding.h"
+
+static VALUE
+bug_str_buf_new(VALUE self, VALUE len)
+{
+ return rb_str_buf_new(NUM2LONG(len));
+}
+
+static VALUE
+bug_external_str_new(VALUE self, VALUE len, VALUE enc)
+{
+ return rb_external_str_new_with_enc(NULL, NUM2LONG(len), rb_to_encoding(enc));
+}
+
+void
+Init_string_new(VALUE klass)
+{
+ rb_define_singleton_method(klass, "buf_new", bug_str_buf_new, 1);
+ rb_define_singleton_method(klass, "external_new", bug_external_str_new, 2);
+}
diff --git a/ext/-test-/string/nofree.c b/ext/-test-/string/nofree.c
new file mode 100644
index 0000000000..fdf810c741
--- /dev/null
+++ b/ext/-test-/string/nofree.c
@@ -0,0 +1,13 @@
+#include "ruby.h"
+
+VALUE
+bug_str_nofree(VALUE self)
+{
+ return rb_str_new_cstr("abcdef");
+}
+
+void
+Init_string_nofree(VALUE klass)
+{
+ rb_define_singleton_method(klass, "nofree", bug_str_nofree, 0);
+}
diff --git a/ext/-test-/string/normalize.c b/ext/-test-/string/normalize.c
new file mode 100644
index 0000000000..a069288ee8
--- /dev/null
+++ b/ext/-test-/string/normalize.c
@@ -0,0 +1,17 @@
+#include "internal/file.h"
+
+#ifdef __APPLE__
+static VALUE
+normalize_ospath(VALUE str)
+{
+ return rb_str_normalize_ospath(RSTRING_PTR(str), RSTRING_LEN(str));
+}
+#else
+#define normalize_ospath rb_f_notimplement
+#endif
+
+void
+Init_string_normalize(VALUE klass)
+{
+ rb_define_method(klass, "normalize_ospath", normalize_ospath, 0);
+}
diff --git a/ext/-test-/string/qsort.c b/ext/-test-/string/qsort.c
new file mode 100644
index 0000000000..4a641e74e3
--- /dev/null
+++ b/ext/-test-/string/qsort.c
@@ -0,0 +1,61 @@
+#include "ruby.h"
+#include "ruby/util.h"
+#include "ruby/encoding.h"
+
+struct sort_data {
+ rb_encoding *enc;
+ long elsize;
+};
+
+static int
+cmp_1(const void *ap, const void *bp, void *dummy)
+{
+ struct sort_data *d = dummy;
+ VALUE a = rb_enc_str_new(ap, d->elsize, d->enc);
+ VALUE b = rb_enc_str_new(bp, d->elsize, d->enc);
+ VALUE retval = rb_yield_values(2, a, b);
+ return rb_cmpint(retval, a, b);
+}
+
+static int
+cmp_2(const void *ap, const void *bp, void *dummy)
+{
+ int a = *(const unsigned char *)ap;
+ int b = *(const unsigned char *)bp;
+ return a - b;
+}
+
+static VALUE
+bug_str_qsort_bang(int argc, VALUE *argv, VALUE str)
+{
+ VALUE beg, len, size;
+ long l, b = 0, n, s = 1;
+ struct sort_data d;
+
+ rb_scan_args(argc, argv, "03", &beg, &len, &size);
+ l = RSTRING_LEN(str);
+ if (!NIL_P(beg) && (b = NUM2INT(beg)) < 0 && (b += l) < 0) {
+ rb_raise(rb_eArgError, "out of bounds");
+ }
+ if (!NIL_P(size) && (s = NUM2INT(size)) < 0) {
+ rb_raise(rb_eArgError, "negative size");
+ }
+ if (NIL_P(len) ||
+ (((n = NUM2INT(len)) < 0) ?
+ (rb_raise(rb_eArgError, "negative length"), 0) :
+ (b + n * s > l))) {
+ n = (l - b) / s;
+ }
+ rb_str_modify(str);
+ d.enc = rb_enc_get(str);
+ d.elsize = s;
+ ruby_qsort(RSTRING_PTR(str) + b, n, s,
+ rb_block_given_p() ? cmp_1 : cmp_2, &d);
+ return str;
+}
+
+void
+Init_string_qsort(VALUE klass)
+{
+ rb_define_method(klass, "qsort!", bug_str_qsort_bang, -1);
+}
diff --git a/ext/-test-/string/rb_interned_str.c b/ext/-test-/string/rb_interned_str.c
new file mode 100644
index 0000000000..47643ec249
--- /dev/null
+++ b/ext/-test-/string/rb_interned_str.c
@@ -0,0 +1,14 @@
+#include "ruby.h"
+
+static VALUE
+bug_rb_interned_str_dup(VALUE self, VALUE str)
+{
+ Check_Type(str, T_STRING);
+ return rb_interned_str(RSTRING_PTR(str), RSTRING_LEN(str));
+}
+
+void
+Init_string_rb_interned_str(VALUE klass)
+{
+ rb_define_singleton_method(klass, "rb_interned_str_dup", bug_rb_interned_str_dup, 1);
+}
diff --git a/ext/-test-/string/rb_str_dup.c b/ext/-test-/string/rb_str_dup.c
new file mode 100644
index 0000000000..a0bd65820f
--- /dev/null
+++ b/ext/-test-/string/rb_str_dup.c
@@ -0,0 +1,35 @@
+#include "ruby.h"
+
+VALUE rb_str_dup(VALUE str);
+
+static VALUE
+bug_rb_str_dup(VALUE self, VALUE str)
+{
+ rb_check_type(str, T_STRING);
+ return rb_str_dup(str);
+}
+
+static VALUE
+bug_shared_string_p(VALUE self, VALUE str)
+{
+ rb_check_type(str, T_STRING);
+ return RB_FL_TEST(str, RUBY_ELTS_SHARED) && RB_FL_TEST(str, RSTRING_NOEMBED) ? Qtrue : Qfalse;
+}
+
+static VALUE
+bug_sharing_with_shared_p(VALUE self, VALUE str)
+{
+ rb_check_type(str, T_STRING);
+ if (bug_shared_string_p(self, str)) {
+ return bug_shared_string_p(self, RSTRING(str)->as.heap.aux.shared);
+ }
+ return Qfalse;
+}
+
+void
+Init_string_rb_str_dup(VALUE klass)
+{
+ rb_define_singleton_method(klass, "rb_str_dup", bug_rb_str_dup, 1);
+ rb_define_singleton_method(klass, "shared_string?", bug_shared_string_p, 1);
+ rb_define_singleton_method(klass, "sharing_with_shared?", bug_sharing_with_shared_p, 1);
+}
diff --git a/ext/-test-/string/set_len.c b/ext/-test-/string/set_len.c
new file mode 100644
index 0000000000..b55ef6f469
--- /dev/null
+++ b/ext/-test-/string/set_len.c
@@ -0,0 +1,32 @@
+#include "ruby.h"
+
+static VALUE
+bug_str_set_len(VALUE str, VALUE len)
+{
+ rb_str_set_len(str, NUM2LONG(len));
+ return str;
+}
+
+static VALUE
+bug_str_append(VALUE str, VALUE addendum)
+{
+ StringValue(addendum);
+ rb_str_modify_expand(str, RSTRING_LEN(addendum));
+ memcpy(RSTRING_END(str), RSTRING_PTR(addendum), RSTRING_LEN(addendum));
+ return str;
+}
+
+static VALUE
+bug_str_resize(VALUE str, VALUE len)
+{
+ rb_str_resize(str, NUM2LONG(len));
+ return str;
+}
+
+void
+Init_string_set_len(VALUE klass)
+{
+ rb_define_method(klass, "set_len", bug_str_set_len, 1);
+ rb_define_method(klass, "append", bug_str_append, 1);
+ rb_define_method(klass, "resize", bug_str_resize, 1);
+}
diff --git a/ext/-test-/struct/data.c b/ext/-test-/struct/data.c
new file mode 100644
index 0000000000..5841c342e7
--- /dev/null
+++ b/ext/-test-/struct/data.c
@@ -0,0 +1,13 @@
+#include "ruby.h"
+
+static VALUE
+bug_data_new(VALUE self, VALUE super)
+{
+ return rb_data_define(super, "mem1", "mem2", NULL);
+}
+
+void
+Init_data(VALUE klass)
+{
+ rb_define_singleton_method(klass, "data_new", bug_data_new, 1);
+}
diff --git a/ext/-test-/struct/depend b/ext/-test-/struct/depend
new file mode 100644
index 0000000000..e2638e4cdf
--- /dev/null
+++ b/ext/-test-/struct/depend
@@ -0,0 +1,807 @@
+# AUTOGENERATED DEPENDENCIES START
+data.o: $(RUBY_EXTCONF_H)
+data.o: $(arch_hdrdir)/ruby/config.h
+data.o: $(hdrdir)/ruby.h
+data.o: $(hdrdir)/ruby/assert.h
+data.o: $(hdrdir)/ruby/backward.h
+data.o: $(hdrdir)/ruby/backward/2/assume.h
+data.o: $(hdrdir)/ruby/backward/2/attributes.h
+data.o: $(hdrdir)/ruby/backward/2/bool.h
+data.o: $(hdrdir)/ruby/backward/2/inttypes.h
+data.o: $(hdrdir)/ruby/backward/2/limits.h
+data.o: $(hdrdir)/ruby/backward/2/long_long.h
+data.o: $(hdrdir)/ruby/backward/2/stdalign.h
+data.o: $(hdrdir)/ruby/backward/2/stdarg.h
+data.o: $(hdrdir)/ruby/defines.h
+data.o: $(hdrdir)/ruby/intern.h
+data.o: $(hdrdir)/ruby/internal/abi.h
+data.o: $(hdrdir)/ruby/internal/anyargs.h
+data.o: $(hdrdir)/ruby/internal/arithmetic.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+data.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+data.o: $(hdrdir)/ruby/internal/assume.h
+data.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+data.o: $(hdrdir)/ruby/internal/attr/artificial.h
+data.o: $(hdrdir)/ruby/internal/attr/cold.h
+data.o: $(hdrdir)/ruby/internal/attr/const.h
+data.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+data.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+data.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+data.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+data.o: $(hdrdir)/ruby/internal/attr/error.h
+data.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+data.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+data.o: $(hdrdir)/ruby/internal/attr/format.h
+data.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+data.o: $(hdrdir)/ruby/internal/attr/noalias.h
+data.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+data.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+data.o: $(hdrdir)/ruby/internal/attr/noinline.h
+data.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+data.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+data.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+data.o: $(hdrdir)/ruby/internal/attr/pure.h
+data.o: $(hdrdir)/ruby/internal/attr/restrict.h
+data.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+data.o: $(hdrdir)/ruby/internal/attr/warning.h
+data.o: $(hdrdir)/ruby/internal/attr/weakref.h
+data.o: $(hdrdir)/ruby/internal/cast.h
+data.o: $(hdrdir)/ruby/internal/compiler_is.h
+data.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+data.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+data.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+data.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+data.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+data.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+data.o: $(hdrdir)/ruby/internal/compiler_since.h
+data.o: $(hdrdir)/ruby/internal/config.h
+data.o: $(hdrdir)/ruby/internal/constant_p.h
+data.o: $(hdrdir)/ruby/internal/core.h
+data.o: $(hdrdir)/ruby/internal/core/rarray.h
+data.o: $(hdrdir)/ruby/internal/core/rbasic.h
+data.o: $(hdrdir)/ruby/internal/core/rbignum.h
+data.o: $(hdrdir)/ruby/internal/core/rclass.h
+data.o: $(hdrdir)/ruby/internal/core/rdata.h
+data.o: $(hdrdir)/ruby/internal/core/rfile.h
+data.o: $(hdrdir)/ruby/internal/core/rhash.h
+data.o: $(hdrdir)/ruby/internal/core/robject.h
+data.o: $(hdrdir)/ruby/internal/core/rregexp.h
+data.o: $(hdrdir)/ruby/internal/core/rstring.h
+data.o: $(hdrdir)/ruby/internal/core/rstruct.h
+data.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+data.o: $(hdrdir)/ruby/internal/ctype.h
+data.o: $(hdrdir)/ruby/internal/dllexport.h
+data.o: $(hdrdir)/ruby/internal/dosish.h
+data.o: $(hdrdir)/ruby/internal/error.h
+data.o: $(hdrdir)/ruby/internal/eval.h
+data.o: $(hdrdir)/ruby/internal/event.h
+data.o: $(hdrdir)/ruby/internal/fl_type.h
+data.o: $(hdrdir)/ruby/internal/gc.h
+data.o: $(hdrdir)/ruby/internal/glob.h
+data.o: $(hdrdir)/ruby/internal/globals.h
+data.o: $(hdrdir)/ruby/internal/has/attribute.h
+data.o: $(hdrdir)/ruby/internal/has/builtin.h
+data.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+data.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+data.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+data.o: $(hdrdir)/ruby/internal/has/extension.h
+data.o: $(hdrdir)/ruby/internal/has/feature.h
+data.o: $(hdrdir)/ruby/internal/has/warning.h
+data.o: $(hdrdir)/ruby/internal/intern/array.h
+data.o: $(hdrdir)/ruby/internal/intern/bignum.h
+data.o: $(hdrdir)/ruby/internal/intern/class.h
+data.o: $(hdrdir)/ruby/internal/intern/compar.h
+data.o: $(hdrdir)/ruby/internal/intern/complex.h
+data.o: $(hdrdir)/ruby/internal/intern/cont.h
+data.o: $(hdrdir)/ruby/internal/intern/dir.h
+data.o: $(hdrdir)/ruby/internal/intern/enum.h
+data.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+data.o: $(hdrdir)/ruby/internal/intern/error.h
+data.o: $(hdrdir)/ruby/internal/intern/eval.h
+data.o: $(hdrdir)/ruby/internal/intern/file.h
+data.o: $(hdrdir)/ruby/internal/intern/hash.h
+data.o: $(hdrdir)/ruby/internal/intern/io.h
+data.o: $(hdrdir)/ruby/internal/intern/load.h
+data.o: $(hdrdir)/ruby/internal/intern/marshal.h
+data.o: $(hdrdir)/ruby/internal/intern/numeric.h
+data.o: $(hdrdir)/ruby/internal/intern/object.h
+data.o: $(hdrdir)/ruby/internal/intern/parse.h
+data.o: $(hdrdir)/ruby/internal/intern/proc.h
+data.o: $(hdrdir)/ruby/internal/intern/process.h
+data.o: $(hdrdir)/ruby/internal/intern/random.h
+data.o: $(hdrdir)/ruby/internal/intern/range.h
+data.o: $(hdrdir)/ruby/internal/intern/rational.h
+data.o: $(hdrdir)/ruby/internal/intern/re.h
+data.o: $(hdrdir)/ruby/internal/intern/ruby.h
+data.o: $(hdrdir)/ruby/internal/intern/select.h
+data.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+data.o: $(hdrdir)/ruby/internal/intern/set.h
+data.o: $(hdrdir)/ruby/internal/intern/signal.h
+data.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+data.o: $(hdrdir)/ruby/internal/intern/string.h
+data.o: $(hdrdir)/ruby/internal/intern/struct.h
+data.o: $(hdrdir)/ruby/internal/intern/thread.h
+data.o: $(hdrdir)/ruby/internal/intern/time.h
+data.o: $(hdrdir)/ruby/internal/intern/variable.h
+data.o: $(hdrdir)/ruby/internal/intern/vm.h
+data.o: $(hdrdir)/ruby/internal/interpreter.h
+data.o: $(hdrdir)/ruby/internal/iterator.h
+data.o: $(hdrdir)/ruby/internal/memory.h
+data.o: $(hdrdir)/ruby/internal/method.h
+data.o: $(hdrdir)/ruby/internal/module.h
+data.o: $(hdrdir)/ruby/internal/newobj.h
+data.o: $(hdrdir)/ruby/internal/scan_args.h
+data.o: $(hdrdir)/ruby/internal/special_consts.h
+data.o: $(hdrdir)/ruby/internal/static_assert.h
+data.o: $(hdrdir)/ruby/internal/stdalign.h
+data.o: $(hdrdir)/ruby/internal/stdbool.h
+data.o: $(hdrdir)/ruby/internal/stdckdint.h
+data.o: $(hdrdir)/ruby/internal/symbol.h
+data.o: $(hdrdir)/ruby/internal/value.h
+data.o: $(hdrdir)/ruby/internal/value_type.h
+data.o: $(hdrdir)/ruby/internal/variable.h
+data.o: $(hdrdir)/ruby/internal/warning_push.h
+data.o: $(hdrdir)/ruby/internal/xmalloc.h
+data.o: $(hdrdir)/ruby/missing.h
+data.o: $(hdrdir)/ruby/ruby.h
+data.o: $(hdrdir)/ruby/st.h
+data.o: $(hdrdir)/ruby/subst.h
+data.o: data.c
+duplicate.o: $(RUBY_EXTCONF_H)
+duplicate.o: $(arch_hdrdir)/ruby/config.h
+duplicate.o: $(hdrdir)/ruby.h
+duplicate.o: $(hdrdir)/ruby/assert.h
+duplicate.o: $(hdrdir)/ruby/backward.h
+duplicate.o: $(hdrdir)/ruby/backward/2/assume.h
+duplicate.o: $(hdrdir)/ruby/backward/2/attributes.h
+duplicate.o: $(hdrdir)/ruby/backward/2/bool.h
+duplicate.o: $(hdrdir)/ruby/backward/2/inttypes.h
+duplicate.o: $(hdrdir)/ruby/backward/2/limits.h
+duplicate.o: $(hdrdir)/ruby/backward/2/long_long.h
+duplicate.o: $(hdrdir)/ruby/backward/2/stdalign.h
+duplicate.o: $(hdrdir)/ruby/backward/2/stdarg.h
+duplicate.o: $(hdrdir)/ruby/defines.h
+duplicate.o: $(hdrdir)/ruby/intern.h
+duplicate.o: $(hdrdir)/ruby/internal/abi.h
+duplicate.o: $(hdrdir)/ruby/internal/anyargs.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+duplicate.o: $(hdrdir)/ruby/internal/assume.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/artificial.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/cold.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/const.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/error.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/format.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/noalias.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/noinline.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/pure.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/restrict.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/warning.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/weakref.h
+duplicate.o: $(hdrdir)/ruby/internal/cast.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_since.h
+duplicate.o: $(hdrdir)/ruby/internal/config.h
+duplicate.o: $(hdrdir)/ruby/internal/constant_p.h
+duplicate.o: $(hdrdir)/ruby/internal/core.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rarray.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rbasic.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rbignum.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rclass.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rdata.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rfile.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rhash.h
+duplicate.o: $(hdrdir)/ruby/internal/core/robject.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rregexp.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rstring.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rstruct.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+duplicate.o: $(hdrdir)/ruby/internal/ctype.h
+duplicate.o: $(hdrdir)/ruby/internal/dllexport.h
+duplicate.o: $(hdrdir)/ruby/internal/dosish.h
+duplicate.o: $(hdrdir)/ruby/internal/error.h
+duplicate.o: $(hdrdir)/ruby/internal/eval.h
+duplicate.o: $(hdrdir)/ruby/internal/event.h
+duplicate.o: $(hdrdir)/ruby/internal/fl_type.h
+duplicate.o: $(hdrdir)/ruby/internal/gc.h
+duplicate.o: $(hdrdir)/ruby/internal/glob.h
+duplicate.o: $(hdrdir)/ruby/internal/globals.h
+duplicate.o: $(hdrdir)/ruby/internal/has/attribute.h
+duplicate.o: $(hdrdir)/ruby/internal/has/builtin.h
+duplicate.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+duplicate.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+duplicate.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+duplicate.o: $(hdrdir)/ruby/internal/has/extension.h
+duplicate.o: $(hdrdir)/ruby/internal/has/feature.h
+duplicate.o: $(hdrdir)/ruby/internal/has/warning.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/array.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/bignum.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/class.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/compar.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/complex.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/cont.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/dir.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/enum.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/error.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/eval.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/file.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/hash.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/io.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/load.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/marshal.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/numeric.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/object.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/parse.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/proc.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/process.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/random.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/range.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/rational.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/re.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/ruby.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/select.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/set.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/signal.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/string.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/struct.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/thread.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/time.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/variable.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/vm.h
+duplicate.o: $(hdrdir)/ruby/internal/interpreter.h
+duplicate.o: $(hdrdir)/ruby/internal/iterator.h
+duplicate.o: $(hdrdir)/ruby/internal/memory.h
+duplicate.o: $(hdrdir)/ruby/internal/method.h
+duplicate.o: $(hdrdir)/ruby/internal/module.h
+duplicate.o: $(hdrdir)/ruby/internal/newobj.h
+duplicate.o: $(hdrdir)/ruby/internal/scan_args.h
+duplicate.o: $(hdrdir)/ruby/internal/special_consts.h
+duplicate.o: $(hdrdir)/ruby/internal/static_assert.h
+duplicate.o: $(hdrdir)/ruby/internal/stdalign.h
+duplicate.o: $(hdrdir)/ruby/internal/stdbool.h
+duplicate.o: $(hdrdir)/ruby/internal/stdckdint.h
+duplicate.o: $(hdrdir)/ruby/internal/symbol.h
+duplicate.o: $(hdrdir)/ruby/internal/value.h
+duplicate.o: $(hdrdir)/ruby/internal/value_type.h
+duplicate.o: $(hdrdir)/ruby/internal/variable.h
+duplicate.o: $(hdrdir)/ruby/internal/warning_push.h
+duplicate.o: $(hdrdir)/ruby/internal/xmalloc.h
+duplicate.o: $(hdrdir)/ruby/missing.h
+duplicate.o: $(hdrdir)/ruby/ruby.h
+duplicate.o: $(hdrdir)/ruby/st.h
+duplicate.o: $(hdrdir)/ruby/subst.h
+duplicate.o: duplicate.c
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+len.o: $(RUBY_EXTCONF_H)
+len.o: $(arch_hdrdir)/ruby/config.h
+len.o: $(hdrdir)/ruby.h
+len.o: $(hdrdir)/ruby/assert.h
+len.o: $(hdrdir)/ruby/backward.h
+len.o: $(hdrdir)/ruby/backward/2/assume.h
+len.o: $(hdrdir)/ruby/backward/2/attributes.h
+len.o: $(hdrdir)/ruby/backward/2/bool.h
+len.o: $(hdrdir)/ruby/backward/2/inttypes.h
+len.o: $(hdrdir)/ruby/backward/2/limits.h
+len.o: $(hdrdir)/ruby/backward/2/long_long.h
+len.o: $(hdrdir)/ruby/backward/2/stdalign.h
+len.o: $(hdrdir)/ruby/backward/2/stdarg.h
+len.o: $(hdrdir)/ruby/defines.h
+len.o: $(hdrdir)/ruby/intern.h
+len.o: $(hdrdir)/ruby/internal/abi.h
+len.o: $(hdrdir)/ruby/internal/anyargs.h
+len.o: $(hdrdir)/ruby/internal/arithmetic.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+len.o: $(hdrdir)/ruby/internal/assume.h
+len.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+len.o: $(hdrdir)/ruby/internal/attr/artificial.h
+len.o: $(hdrdir)/ruby/internal/attr/cold.h
+len.o: $(hdrdir)/ruby/internal/attr/const.h
+len.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+len.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+len.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+len.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+len.o: $(hdrdir)/ruby/internal/attr/error.h
+len.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+len.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+len.o: $(hdrdir)/ruby/internal/attr/format.h
+len.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+len.o: $(hdrdir)/ruby/internal/attr/noalias.h
+len.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+len.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+len.o: $(hdrdir)/ruby/internal/attr/noinline.h
+len.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+len.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+len.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+len.o: $(hdrdir)/ruby/internal/attr/pure.h
+len.o: $(hdrdir)/ruby/internal/attr/restrict.h
+len.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+len.o: $(hdrdir)/ruby/internal/attr/warning.h
+len.o: $(hdrdir)/ruby/internal/attr/weakref.h
+len.o: $(hdrdir)/ruby/internal/cast.h
+len.o: $(hdrdir)/ruby/internal/compiler_is.h
+len.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+len.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+len.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+len.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+len.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+len.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+len.o: $(hdrdir)/ruby/internal/compiler_since.h
+len.o: $(hdrdir)/ruby/internal/config.h
+len.o: $(hdrdir)/ruby/internal/constant_p.h
+len.o: $(hdrdir)/ruby/internal/core.h
+len.o: $(hdrdir)/ruby/internal/core/rarray.h
+len.o: $(hdrdir)/ruby/internal/core/rbasic.h
+len.o: $(hdrdir)/ruby/internal/core/rbignum.h
+len.o: $(hdrdir)/ruby/internal/core/rclass.h
+len.o: $(hdrdir)/ruby/internal/core/rdata.h
+len.o: $(hdrdir)/ruby/internal/core/rfile.h
+len.o: $(hdrdir)/ruby/internal/core/rhash.h
+len.o: $(hdrdir)/ruby/internal/core/robject.h
+len.o: $(hdrdir)/ruby/internal/core/rregexp.h
+len.o: $(hdrdir)/ruby/internal/core/rstring.h
+len.o: $(hdrdir)/ruby/internal/core/rstruct.h
+len.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+len.o: $(hdrdir)/ruby/internal/ctype.h
+len.o: $(hdrdir)/ruby/internal/dllexport.h
+len.o: $(hdrdir)/ruby/internal/dosish.h
+len.o: $(hdrdir)/ruby/internal/error.h
+len.o: $(hdrdir)/ruby/internal/eval.h
+len.o: $(hdrdir)/ruby/internal/event.h
+len.o: $(hdrdir)/ruby/internal/fl_type.h
+len.o: $(hdrdir)/ruby/internal/gc.h
+len.o: $(hdrdir)/ruby/internal/glob.h
+len.o: $(hdrdir)/ruby/internal/globals.h
+len.o: $(hdrdir)/ruby/internal/has/attribute.h
+len.o: $(hdrdir)/ruby/internal/has/builtin.h
+len.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+len.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+len.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+len.o: $(hdrdir)/ruby/internal/has/extension.h
+len.o: $(hdrdir)/ruby/internal/has/feature.h
+len.o: $(hdrdir)/ruby/internal/has/warning.h
+len.o: $(hdrdir)/ruby/internal/intern/array.h
+len.o: $(hdrdir)/ruby/internal/intern/bignum.h
+len.o: $(hdrdir)/ruby/internal/intern/class.h
+len.o: $(hdrdir)/ruby/internal/intern/compar.h
+len.o: $(hdrdir)/ruby/internal/intern/complex.h
+len.o: $(hdrdir)/ruby/internal/intern/cont.h
+len.o: $(hdrdir)/ruby/internal/intern/dir.h
+len.o: $(hdrdir)/ruby/internal/intern/enum.h
+len.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+len.o: $(hdrdir)/ruby/internal/intern/error.h
+len.o: $(hdrdir)/ruby/internal/intern/eval.h
+len.o: $(hdrdir)/ruby/internal/intern/file.h
+len.o: $(hdrdir)/ruby/internal/intern/hash.h
+len.o: $(hdrdir)/ruby/internal/intern/io.h
+len.o: $(hdrdir)/ruby/internal/intern/load.h
+len.o: $(hdrdir)/ruby/internal/intern/marshal.h
+len.o: $(hdrdir)/ruby/internal/intern/numeric.h
+len.o: $(hdrdir)/ruby/internal/intern/object.h
+len.o: $(hdrdir)/ruby/internal/intern/parse.h
+len.o: $(hdrdir)/ruby/internal/intern/proc.h
+len.o: $(hdrdir)/ruby/internal/intern/process.h
+len.o: $(hdrdir)/ruby/internal/intern/random.h
+len.o: $(hdrdir)/ruby/internal/intern/range.h
+len.o: $(hdrdir)/ruby/internal/intern/rational.h
+len.o: $(hdrdir)/ruby/internal/intern/re.h
+len.o: $(hdrdir)/ruby/internal/intern/ruby.h
+len.o: $(hdrdir)/ruby/internal/intern/select.h
+len.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+len.o: $(hdrdir)/ruby/internal/intern/set.h
+len.o: $(hdrdir)/ruby/internal/intern/signal.h
+len.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+len.o: $(hdrdir)/ruby/internal/intern/string.h
+len.o: $(hdrdir)/ruby/internal/intern/struct.h
+len.o: $(hdrdir)/ruby/internal/intern/thread.h
+len.o: $(hdrdir)/ruby/internal/intern/time.h
+len.o: $(hdrdir)/ruby/internal/intern/variable.h
+len.o: $(hdrdir)/ruby/internal/intern/vm.h
+len.o: $(hdrdir)/ruby/internal/interpreter.h
+len.o: $(hdrdir)/ruby/internal/iterator.h
+len.o: $(hdrdir)/ruby/internal/memory.h
+len.o: $(hdrdir)/ruby/internal/method.h
+len.o: $(hdrdir)/ruby/internal/module.h
+len.o: $(hdrdir)/ruby/internal/newobj.h
+len.o: $(hdrdir)/ruby/internal/scan_args.h
+len.o: $(hdrdir)/ruby/internal/special_consts.h
+len.o: $(hdrdir)/ruby/internal/static_assert.h
+len.o: $(hdrdir)/ruby/internal/stdalign.h
+len.o: $(hdrdir)/ruby/internal/stdbool.h
+len.o: $(hdrdir)/ruby/internal/stdckdint.h
+len.o: $(hdrdir)/ruby/internal/symbol.h
+len.o: $(hdrdir)/ruby/internal/value.h
+len.o: $(hdrdir)/ruby/internal/value_type.h
+len.o: $(hdrdir)/ruby/internal/variable.h
+len.o: $(hdrdir)/ruby/internal/warning_push.h
+len.o: $(hdrdir)/ruby/internal/xmalloc.h
+len.o: $(hdrdir)/ruby/missing.h
+len.o: $(hdrdir)/ruby/ruby.h
+len.o: $(hdrdir)/ruby/st.h
+len.o: $(hdrdir)/ruby/subst.h
+len.o: len.c
+member.o: $(RUBY_EXTCONF_H)
+member.o: $(arch_hdrdir)/ruby/config.h
+member.o: $(hdrdir)/ruby.h
+member.o: $(hdrdir)/ruby/assert.h
+member.o: $(hdrdir)/ruby/backward.h
+member.o: $(hdrdir)/ruby/backward/2/assume.h
+member.o: $(hdrdir)/ruby/backward/2/attributes.h
+member.o: $(hdrdir)/ruby/backward/2/bool.h
+member.o: $(hdrdir)/ruby/backward/2/inttypes.h
+member.o: $(hdrdir)/ruby/backward/2/limits.h
+member.o: $(hdrdir)/ruby/backward/2/long_long.h
+member.o: $(hdrdir)/ruby/backward/2/stdalign.h
+member.o: $(hdrdir)/ruby/backward/2/stdarg.h
+member.o: $(hdrdir)/ruby/defines.h
+member.o: $(hdrdir)/ruby/intern.h
+member.o: $(hdrdir)/ruby/internal/abi.h
+member.o: $(hdrdir)/ruby/internal/anyargs.h
+member.o: $(hdrdir)/ruby/internal/arithmetic.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+member.o: $(hdrdir)/ruby/internal/assume.h
+member.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+member.o: $(hdrdir)/ruby/internal/attr/artificial.h
+member.o: $(hdrdir)/ruby/internal/attr/cold.h
+member.o: $(hdrdir)/ruby/internal/attr/const.h
+member.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+member.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+member.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+member.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+member.o: $(hdrdir)/ruby/internal/attr/error.h
+member.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+member.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+member.o: $(hdrdir)/ruby/internal/attr/format.h
+member.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+member.o: $(hdrdir)/ruby/internal/attr/noalias.h
+member.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+member.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+member.o: $(hdrdir)/ruby/internal/attr/noinline.h
+member.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+member.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+member.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+member.o: $(hdrdir)/ruby/internal/attr/pure.h
+member.o: $(hdrdir)/ruby/internal/attr/restrict.h
+member.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+member.o: $(hdrdir)/ruby/internal/attr/warning.h
+member.o: $(hdrdir)/ruby/internal/attr/weakref.h
+member.o: $(hdrdir)/ruby/internal/cast.h
+member.o: $(hdrdir)/ruby/internal/compiler_is.h
+member.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+member.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+member.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+member.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+member.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+member.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+member.o: $(hdrdir)/ruby/internal/compiler_since.h
+member.o: $(hdrdir)/ruby/internal/config.h
+member.o: $(hdrdir)/ruby/internal/constant_p.h
+member.o: $(hdrdir)/ruby/internal/core.h
+member.o: $(hdrdir)/ruby/internal/core/rarray.h
+member.o: $(hdrdir)/ruby/internal/core/rbasic.h
+member.o: $(hdrdir)/ruby/internal/core/rbignum.h
+member.o: $(hdrdir)/ruby/internal/core/rclass.h
+member.o: $(hdrdir)/ruby/internal/core/rdata.h
+member.o: $(hdrdir)/ruby/internal/core/rfile.h
+member.o: $(hdrdir)/ruby/internal/core/rhash.h
+member.o: $(hdrdir)/ruby/internal/core/robject.h
+member.o: $(hdrdir)/ruby/internal/core/rregexp.h
+member.o: $(hdrdir)/ruby/internal/core/rstring.h
+member.o: $(hdrdir)/ruby/internal/core/rstruct.h
+member.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+member.o: $(hdrdir)/ruby/internal/ctype.h
+member.o: $(hdrdir)/ruby/internal/dllexport.h
+member.o: $(hdrdir)/ruby/internal/dosish.h
+member.o: $(hdrdir)/ruby/internal/error.h
+member.o: $(hdrdir)/ruby/internal/eval.h
+member.o: $(hdrdir)/ruby/internal/event.h
+member.o: $(hdrdir)/ruby/internal/fl_type.h
+member.o: $(hdrdir)/ruby/internal/gc.h
+member.o: $(hdrdir)/ruby/internal/glob.h
+member.o: $(hdrdir)/ruby/internal/globals.h
+member.o: $(hdrdir)/ruby/internal/has/attribute.h
+member.o: $(hdrdir)/ruby/internal/has/builtin.h
+member.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+member.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+member.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+member.o: $(hdrdir)/ruby/internal/has/extension.h
+member.o: $(hdrdir)/ruby/internal/has/feature.h
+member.o: $(hdrdir)/ruby/internal/has/warning.h
+member.o: $(hdrdir)/ruby/internal/intern/array.h
+member.o: $(hdrdir)/ruby/internal/intern/bignum.h
+member.o: $(hdrdir)/ruby/internal/intern/class.h
+member.o: $(hdrdir)/ruby/internal/intern/compar.h
+member.o: $(hdrdir)/ruby/internal/intern/complex.h
+member.o: $(hdrdir)/ruby/internal/intern/cont.h
+member.o: $(hdrdir)/ruby/internal/intern/dir.h
+member.o: $(hdrdir)/ruby/internal/intern/enum.h
+member.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+member.o: $(hdrdir)/ruby/internal/intern/error.h
+member.o: $(hdrdir)/ruby/internal/intern/eval.h
+member.o: $(hdrdir)/ruby/internal/intern/file.h
+member.o: $(hdrdir)/ruby/internal/intern/hash.h
+member.o: $(hdrdir)/ruby/internal/intern/io.h
+member.o: $(hdrdir)/ruby/internal/intern/load.h
+member.o: $(hdrdir)/ruby/internal/intern/marshal.h
+member.o: $(hdrdir)/ruby/internal/intern/numeric.h
+member.o: $(hdrdir)/ruby/internal/intern/object.h
+member.o: $(hdrdir)/ruby/internal/intern/parse.h
+member.o: $(hdrdir)/ruby/internal/intern/proc.h
+member.o: $(hdrdir)/ruby/internal/intern/process.h
+member.o: $(hdrdir)/ruby/internal/intern/random.h
+member.o: $(hdrdir)/ruby/internal/intern/range.h
+member.o: $(hdrdir)/ruby/internal/intern/rational.h
+member.o: $(hdrdir)/ruby/internal/intern/re.h
+member.o: $(hdrdir)/ruby/internal/intern/ruby.h
+member.o: $(hdrdir)/ruby/internal/intern/select.h
+member.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+member.o: $(hdrdir)/ruby/internal/intern/set.h
+member.o: $(hdrdir)/ruby/internal/intern/signal.h
+member.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+member.o: $(hdrdir)/ruby/internal/intern/string.h
+member.o: $(hdrdir)/ruby/internal/intern/struct.h
+member.o: $(hdrdir)/ruby/internal/intern/thread.h
+member.o: $(hdrdir)/ruby/internal/intern/time.h
+member.o: $(hdrdir)/ruby/internal/intern/variable.h
+member.o: $(hdrdir)/ruby/internal/intern/vm.h
+member.o: $(hdrdir)/ruby/internal/interpreter.h
+member.o: $(hdrdir)/ruby/internal/iterator.h
+member.o: $(hdrdir)/ruby/internal/memory.h
+member.o: $(hdrdir)/ruby/internal/method.h
+member.o: $(hdrdir)/ruby/internal/module.h
+member.o: $(hdrdir)/ruby/internal/newobj.h
+member.o: $(hdrdir)/ruby/internal/scan_args.h
+member.o: $(hdrdir)/ruby/internal/special_consts.h
+member.o: $(hdrdir)/ruby/internal/static_assert.h
+member.o: $(hdrdir)/ruby/internal/stdalign.h
+member.o: $(hdrdir)/ruby/internal/stdbool.h
+member.o: $(hdrdir)/ruby/internal/stdckdint.h
+member.o: $(hdrdir)/ruby/internal/symbol.h
+member.o: $(hdrdir)/ruby/internal/value.h
+member.o: $(hdrdir)/ruby/internal/value_type.h
+member.o: $(hdrdir)/ruby/internal/variable.h
+member.o: $(hdrdir)/ruby/internal/warning_push.h
+member.o: $(hdrdir)/ruby/internal/xmalloc.h
+member.o: $(hdrdir)/ruby/missing.h
+member.o: $(hdrdir)/ruby/ruby.h
+member.o: $(hdrdir)/ruby/st.h
+member.o: $(hdrdir)/ruby/subst.h
+member.o: member.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/struct/duplicate.c b/ext/-test-/struct/duplicate.c
new file mode 100644
index 0000000000..596d32aad8
--- /dev/null
+++ b/ext/-test-/struct/duplicate.c
@@ -0,0 +1,24 @@
+#include "ruby.h"
+
+static VALUE
+bug_struct_new_duplicate(VALUE obj, VALUE name, VALUE mem)
+{
+ const char *n = NIL_P(name) ? 0 : StringValueCStr(name);
+ const char *m = StringValueCStr(mem);
+ return rb_struct_define(n, m, m, NULL);
+}
+
+static VALUE
+bug_struct_new_duplicate_under(VALUE obj, VALUE name, VALUE mem)
+{
+ const char *n = StringValueCStr(name);
+ const char *m = StringValueCStr(mem);
+ return rb_struct_define_under(obj, n, m, m, NULL);
+}
+
+void
+Init_duplicate(VALUE klass)
+{
+ rb_define_singleton_method(klass, "new_duplicate", bug_struct_new_duplicate, 2);
+ rb_define_singleton_method(klass, "new_duplicate_under", bug_struct_new_duplicate_under, 2);
+}
diff --git a/ext/-test-/struct/extconf.rb b/ext/-test-/struct/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/struct/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/struct/init.c b/ext/-test-/struct/init.c
new file mode 100644
index 0000000000..459a939e79
--- /dev/null
+++ b/ext/-test-/struct/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_struct(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "Struct", rb_cStruct);
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/struct/len.c b/ext/-test-/struct/len.c
new file mode 100644
index 0000000000..6153c720b2
--- /dev/null
+++ b/ext/-test-/struct/len.c
@@ -0,0 +1,13 @@
+#include "ruby.h"
+
+static VALUE
+bug_struct_len(VALUE obj)
+{
+ return LONG2NUM(RSTRUCT_LEN(obj));
+}
+
+void
+Init_len(VALUE klass)
+{
+ rb_define_method(klass, "rstruct_len", bug_struct_len, 0);
+}
diff --git a/ext/-test-/struct/member.c b/ext/-test-/struct/member.c
new file mode 100644
index 0000000000..29ddff93e8
--- /dev/null
+++ b/ext/-test-/struct/member.c
@@ -0,0 +1,18 @@
+#include "ruby.h"
+
+static VALUE
+bug_struct_get(VALUE obj, VALUE name)
+{
+ ID id = rb_check_id(&name);
+
+ if (!id) {
+ rb_name_error_str(name, "'%"PRIsVALUE"' is not a struct member", name);
+ }
+ return rb_struct_getmember(obj, id);
+}
+
+void
+Init_member(VALUE klass)
+{
+ rb_define_method(klass, "get", bug_struct_get, 1);
+}
diff --git a/ext/-test-/symbol/depend b/ext/-test-/symbol/depend
new file mode 100644
index 0000000000..b1d8e1aab6
--- /dev/null
+++ b/ext/-test-/symbol/depend
@@ -0,0 +1,324 @@
+# AUTOGENERATED DEPENDENCIES START
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+type.o: $(RUBY_EXTCONF_H)
+type.o: $(arch_hdrdir)/ruby/config.h
+type.o: $(hdrdir)/ruby.h
+type.o: $(hdrdir)/ruby/assert.h
+type.o: $(hdrdir)/ruby/backward.h
+type.o: $(hdrdir)/ruby/backward/2/assume.h
+type.o: $(hdrdir)/ruby/backward/2/attributes.h
+type.o: $(hdrdir)/ruby/backward/2/bool.h
+type.o: $(hdrdir)/ruby/backward/2/inttypes.h
+type.o: $(hdrdir)/ruby/backward/2/limits.h
+type.o: $(hdrdir)/ruby/backward/2/long_long.h
+type.o: $(hdrdir)/ruby/backward/2/stdalign.h
+type.o: $(hdrdir)/ruby/backward/2/stdarg.h
+type.o: $(hdrdir)/ruby/defines.h
+type.o: $(hdrdir)/ruby/intern.h
+type.o: $(hdrdir)/ruby/internal/abi.h
+type.o: $(hdrdir)/ruby/internal/anyargs.h
+type.o: $(hdrdir)/ruby/internal/arithmetic.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+type.o: $(hdrdir)/ruby/internal/assume.h
+type.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+type.o: $(hdrdir)/ruby/internal/attr/artificial.h
+type.o: $(hdrdir)/ruby/internal/attr/cold.h
+type.o: $(hdrdir)/ruby/internal/attr/const.h
+type.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+type.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+type.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+type.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+type.o: $(hdrdir)/ruby/internal/attr/error.h
+type.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+type.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+type.o: $(hdrdir)/ruby/internal/attr/format.h
+type.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+type.o: $(hdrdir)/ruby/internal/attr/noalias.h
+type.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+type.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+type.o: $(hdrdir)/ruby/internal/attr/noinline.h
+type.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+type.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+type.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+type.o: $(hdrdir)/ruby/internal/attr/pure.h
+type.o: $(hdrdir)/ruby/internal/attr/restrict.h
+type.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+type.o: $(hdrdir)/ruby/internal/attr/warning.h
+type.o: $(hdrdir)/ruby/internal/attr/weakref.h
+type.o: $(hdrdir)/ruby/internal/cast.h
+type.o: $(hdrdir)/ruby/internal/compiler_is.h
+type.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+type.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+type.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+type.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+type.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+type.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+type.o: $(hdrdir)/ruby/internal/compiler_since.h
+type.o: $(hdrdir)/ruby/internal/config.h
+type.o: $(hdrdir)/ruby/internal/constant_p.h
+type.o: $(hdrdir)/ruby/internal/core.h
+type.o: $(hdrdir)/ruby/internal/core/rarray.h
+type.o: $(hdrdir)/ruby/internal/core/rbasic.h
+type.o: $(hdrdir)/ruby/internal/core/rbignum.h
+type.o: $(hdrdir)/ruby/internal/core/rclass.h
+type.o: $(hdrdir)/ruby/internal/core/rdata.h
+type.o: $(hdrdir)/ruby/internal/core/rfile.h
+type.o: $(hdrdir)/ruby/internal/core/rhash.h
+type.o: $(hdrdir)/ruby/internal/core/robject.h
+type.o: $(hdrdir)/ruby/internal/core/rregexp.h
+type.o: $(hdrdir)/ruby/internal/core/rstring.h
+type.o: $(hdrdir)/ruby/internal/core/rstruct.h
+type.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+type.o: $(hdrdir)/ruby/internal/ctype.h
+type.o: $(hdrdir)/ruby/internal/dllexport.h
+type.o: $(hdrdir)/ruby/internal/dosish.h
+type.o: $(hdrdir)/ruby/internal/error.h
+type.o: $(hdrdir)/ruby/internal/eval.h
+type.o: $(hdrdir)/ruby/internal/event.h
+type.o: $(hdrdir)/ruby/internal/fl_type.h
+type.o: $(hdrdir)/ruby/internal/gc.h
+type.o: $(hdrdir)/ruby/internal/glob.h
+type.o: $(hdrdir)/ruby/internal/globals.h
+type.o: $(hdrdir)/ruby/internal/has/attribute.h
+type.o: $(hdrdir)/ruby/internal/has/builtin.h
+type.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+type.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+type.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+type.o: $(hdrdir)/ruby/internal/has/extension.h
+type.o: $(hdrdir)/ruby/internal/has/feature.h
+type.o: $(hdrdir)/ruby/internal/has/warning.h
+type.o: $(hdrdir)/ruby/internal/intern/array.h
+type.o: $(hdrdir)/ruby/internal/intern/bignum.h
+type.o: $(hdrdir)/ruby/internal/intern/class.h
+type.o: $(hdrdir)/ruby/internal/intern/compar.h
+type.o: $(hdrdir)/ruby/internal/intern/complex.h
+type.o: $(hdrdir)/ruby/internal/intern/cont.h
+type.o: $(hdrdir)/ruby/internal/intern/dir.h
+type.o: $(hdrdir)/ruby/internal/intern/enum.h
+type.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+type.o: $(hdrdir)/ruby/internal/intern/error.h
+type.o: $(hdrdir)/ruby/internal/intern/eval.h
+type.o: $(hdrdir)/ruby/internal/intern/file.h
+type.o: $(hdrdir)/ruby/internal/intern/hash.h
+type.o: $(hdrdir)/ruby/internal/intern/io.h
+type.o: $(hdrdir)/ruby/internal/intern/load.h
+type.o: $(hdrdir)/ruby/internal/intern/marshal.h
+type.o: $(hdrdir)/ruby/internal/intern/numeric.h
+type.o: $(hdrdir)/ruby/internal/intern/object.h
+type.o: $(hdrdir)/ruby/internal/intern/parse.h
+type.o: $(hdrdir)/ruby/internal/intern/proc.h
+type.o: $(hdrdir)/ruby/internal/intern/process.h
+type.o: $(hdrdir)/ruby/internal/intern/random.h
+type.o: $(hdrdir)/ruby/internal/intern/range.h
+type.o: $(hdrdir)/ruby/internal/intern/rational.h
+type.o: $(hdrdir)/ruby/internal/intern/re.h
+type.o: $(hdrdir)/ruby/internal/intern/ruby.h
+type.o: $(hdrdir)/ruby/internal/intern/select.h
+type.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+type.o: $(hdrdir)/ruby/internal/intern/set.h
+type.o: $(hdrdir)/ruby/internal/intern/signal.h
+type.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+type.o: $(hdrdir)/ruby/internal/intern/string.h
+type.o: $(hdrdir)/ruby/internal/intern/struct.h
+type.o: $(hdrdir)/ruby/internal/intern/thread.h
+type.o: $(hdrdir)/ruby/internal/intern/time.h
+type.o: $(hdrdir)/ruby/internal/intern/variable.h
+type.o: $(hdrdir)/ruby/internal/intern/vm.h
+type.o: $(hdrdir)/ruby/internal/interpreter.h
+type.o: $(hdrdir)/ruby/internal/iterator.h
+type.o: $(hdrdir)/ruby/internal/memory.h
+type.o: $(hdrdir)/ruby/internal/method.h
+type.o: $(hdrdir)/ruby/internal/module.h
+type.o: $(hdrdir)/ruby/internal/newobj.h
+type.o: $(hdrdir)/ruby/internal/scan_args.h
+type.o: $(hdrdir)/ruby/internal/special_consts.h
+type.o: $(hdrdir)/ruby/internal/static_assert.h
+type.o: $(hdrdir)/ruby/internal/stdalign.h
+type.o: $(hdrdir)/ruby/internal/stdbool.h
+type.o: $(hdrdir)/ruby/internal/stdckdint.h
+type.o: $(hdrdir)/ruby/internal/symbol.h
+type.o: $(hdrdir)/ruby/internal/value.h
+type.o: $(hdrdir)/ruby/internal/value_type.h
+type.o: $(hdrdir)/ruby/internal/variable.h
+type.o: $(hdrdir)/ruby/internal/warning_push.h
+type.o: $(hdrdir)/ruby/internal/xmalloc.h
+type.o: $(hdrdir)/ruby/missing.h
+type.o: $(hdrdir)/ruby/ruby.h
+type.o: $(hdrdir)/ruby/st.h
+type.o: $(hdrdir)/ruby/subst.h
+type.o: type.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/symbol/extconf.rb b/ext/-test-/symbol/extconf.rb
new file mode 100644
index 0000000000..ecebdb7d6b
--- /dev/null
+++ b/ext/-test-/symbol/extconf.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+have_func("rb_pin_dynamic_symbol")
+auto_ext
diff --git a/ext/-test-/symbol/init.c b/ext/-test-/symbol/init.c
new file mode 100644
index 0000000000..4038701ac9
--- /dev/null
+++ b/ext/-test-/symbol/init.c
@@ -0,0 +1,39 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+static VALUE
+sym_find(VALUE dummy, VALUE sym)
+{
+ return rb_check_symbol(&sym);
+}
+
+static VALUE
+sym_pinneddown_p(VALUE dummy, VALUE sym)
+{
+ ID id = rb_check_id(&sym);
+ if (!id) return Qnil;
+#ifdef ULL2NUM
+ return ULL2NUM(id);
+#else
+ return ULONG2NUM(id);
+#endif
+}
+
+static VALUE
+sym_iv_get(VALUE dummy, VALUE obj, VALUE name)
+{
+ const char *n = StringValueCStr(name);
+ return rb_iv_get(obj, n);
+}
+
+void
+Init_symbol(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "Symbol", rb_cSymbol);
+ rb_define_singleton_method(klass, "find", sym_find, 1);
+ rb_define_singleton_method(klass, "pinneddown?", sym_pinneddown_p, 1);
+ rb_define_singleton_method(klass, "iv_get", sym_iv_get, 2);
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/symbol/type.c b/ext/-test-/symbol/type.c
new file mode 100644
index 0000000000..8d0e647340
--- /dev/null
+++ b/ext/-test-/symbol/type.c
@@ -0,0 +1,78 @@
+#include "ruby.h"
+
+#ifdef HAVE_RB_IS_CONST_NAME
+# define get_symbol_type(type, t, name) do { \
+ ID id = rb_check_id(&name); \
+ t = (id ? rb_is_##type##_id(id) : rb_is_##type##_name(name)); \
+ } while (0)
+#else
+# define get_symbol_type(type, t, name) do { \
+ t = rb_is_##type##_id(rb_to_id(name)); \
+ } while (0)
+#endif
+
+#define define_symbol_type_p(type) \
+static VALUE \
+bug_sym_##type##_p(VALUE self, VALUE name) \
+{ \
+ int t; \
+ get_symbol_type(type, t, name); \
+ return (t ? Qtrue : Qfalse); \
+}
+
+#define declare_symbol_type_p(type) \
+ rb_define_singleton_method(klass, #type"?", bug_sym_##type##_p, 1);
+
+#define FOREACH_ID_TYPES(x) x(const) x(class) x(global) x(instance) x(attrset) x(local) x(junk)
+
+FOREACH_ID_TYPES(define_symbol_type_p)
+
+static VALUE
+bug_sym_attrset(VALUE self, VALUE name)
+{
+ ID id = rb_to_id(name);
+ id = rb_id_attrset(id);
+ return ID2SYM(id);
+}
+
+static VALUE
+bug_id2str(VALUE self, VALUE sym)
+{
+ return rb_sym2str(sym);
+}
+
+static VALUE
+bug_static_p(VALUE self, VALUE sym)
+{
+ return STATIC_SYM_P(sym) ? Qtrue : Qfalse;
+}
+
+static VALUE
+bug_dynamic_p(VALUE self, VALUE sym)
+{
+ return DYNAMIC_SYM_P(sym) ? Qtrue : Qfalse;
+}
+
+#ifdef HAVE_RB_PIN_DYNAMIC_SYMBOL
+ID rb_pin_dynamic_symbol(VALUE);
+
+static VALUE
+bug_pindown(VALUE self, VALUE sym)
+{
+ rb_pin_dynamic_symbol(sym);
+ return sym;
+}
+#endif
+
+void
+Init_type(VALUE klass)
+{
+ FOREACH_ID_TYPES(declare_symbol_type_p);
+ rb_define_singleton_method(klass, "attrset", bug_sym_attrset, 1);
+ rb_define_singleton_method(klass, "id2str", bug_id2str, 1);
+ rb_define_singleton_method(klass, "static?", bug_static_p, 1);
+ rb_define_singleton_method(klass, "dynamic?", bug_dynamic_p, 1);
+#ifdef HAVE_RB_PIN_DYNAMIC_SYMBOL
+ rb_define_singleton_method(klass, "pindown", bug_pindown, 1);
+#endif
+}
diff --git a/ext/-test-/thread/id/depend b/ext/-test-/thread/id/depend
new file mode 100644
index 0000000000..6b76b31ddc
--- /dev/null
+++ b/ext/-test-/thread/id/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+id.o: $(RUBY_EXTCONF_H)
+id.o: $(arch_hdrdir)/ruby/config.h
+id.o: $(hdrdir)/ruby.h
+id.o: $(hdrdir)/ruby/assert.h
+id.o: $(hdrdir)/ruby/backward.h
+id.o: $(hdrdir)/ruby/backward/2/assume.h
+id.o: $(hdrdir)/ruby/backward/2/attributes.h
+id.o: $(hdrdir)/ruby/backward/2/bool.h
+id.o: $(hdrdir)/ruby/backward/2/inttypes.h
+id.o: $(hdrdir)/ruby/backward/2/limits.h
+id.o: $(hdrdir)/ruby/backward/2/long_long.h
+id.o: $(hdrdir)/ruby/backward/2/stdalign.h
+id.o: $(hdrdir)/ruby/backward/2/stdarg.h
+id.o: $(hdrdir)/ruby/defines.h
+id.o: $(hdrdir)/ruby/intern.h
+id.o: $(hdrdir)/ruby/internal/abi.h
+id.o: $(hdrdir)/ruby/internal/anyargs.h
+id.o: $(hdrdir)/ruby/internal/arithmetic.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+id.o: $(hdrdir)/ruby/internal/assume.h
+id.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+id.o: $(hdrdir)/ruby/internal/attr/artificial.h
+id.o: $(hdrdir)/ruby/internal/attr/cold.h
+id.o: $(hdrdir)/ruby/internal/attr/const.h
+id.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+id.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+id.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+id.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+id.o: $(hdrdir)/ruby/internal/attr/error.h
+id.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+id.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+id.o: $(hdrdir)/ruby/internal/attr/format.h
+id.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+id.o: $(hdrdir)/ruby/internal/attr/noalias.h
+id.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+id.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+id.o: $(hdrdir)/ruby/internal/attr/noinline.h
+id.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+id.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+id.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+id.o: $(hdrdir)/ruby/internal/attr/pure.h
+id.o: $(hdrdir)/ruby/internal/attr/restrict.h
+id.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+id.o: $(hdrdir)/ruby/internal/attr/warning.h
+id.o: $(hdrdir)/ruby/internal/attr/weakref.h
+id.o: $(hdrdir)/ruby/internal/cast.h
+id.o: $(hdrdir)/ruby/internal/compiler_is.h
+id.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+id.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+id.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+id.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+id.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+id.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+id.o: $(hdrdir)/ruby/internal/compiler_since.h
+id.o: $(hdrdir)/ruby/internal/config.h
+id.o: $(hdrdir)/ruby/internal/constant_p.h
+id.o: $(hdrdir)/ruby/internal/core.h
+id.o: $(hdrdir)/ruby/internal/core/rarray.h
+id.o: $(hdrdir)/ruby/internal/core/rbasic.h
+id.o: $(hdrdir)/ruby/internal/core/rbignum.h
+id.o: $(hdrdir)/ruby/internal/core/rclass.h
+id.o: $(hdrdir)/ruby/internal/core/rdata.h
+id.o: $(hdrdir)/ruby/internal/core/rfile.h
+id.o: $(hdrdir)/ruby/internal/core/rhash.h
+id.o: $(hdrdir)/ruby/internal/core/robject.h
+id.o: $(hdrdir)/ruby/internal/core/rregexp.h
+id.o: $(hdrdir)/ruby/internal/core/rstring.h
+id.o: $(hdrdir)/ruby/internal/core/rstruct.h
+id.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+id.o: $(hdrdir)/ruby/internal/ctype.h
+id.o: $(hdrdir)/ruby/internal/dllexport.h
+id.o: $(hdrdir)/ruby/internal/dosish.h
+id.o: $(hdrdir)/ruby/internal/error.h
+id.o: $(hdrdir)/ruby/internal/eval.h
+id.o: $(hdrdir)/ruby/internal/event.h
+id.o: $(hdrdir)/ruby/internal/fl_type.h
+id.o: $(hdrdir)/ruby/internal/gc.h
+id.o: $(hdrdir)/ruby/internal/glob.h
+id.o: $(hdrdir)/ruby/internal/globals.h
+id.o: $(hdrdir)/ruby/internal/has/attribute.h
+id.o: $(hdrdir)/ruby/internal/has/builtin.h
+id.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+id.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+id.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+id.o: $(hdrdir)/ruby/internal/has/extension.h
+id.o: $(hdrdir)/ruby/internal/has/feature.h
+id.o: $(hdrdir)/ruby/internal/has/warning.h
+id.o: $(hdrdir)/ruby/internal/intern/array.h
+id.o: $(hdrdir)/ruby/internal/intern/bignum.h
+id.o: $(hdrdir)/ruby/internal/intern/class.h
+id.o: $(hdrdir)/ruby/internal/intern/compar.h
+id.o: $(hdrdir)/ruby/internal/intern/complex.h
+id.o: $(hdrdir)/ruby/internal/intern/cont.h
+id.o: $(hdrdir)/ruby/internal/intern/dir.h
+id.o: $(hdrdir)/ruby/internal/intern/enum.h
+id.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+id.o: $(hdrdir)/ruby/internal/intern/error.h
+id.o: $(hdrdir)/ruby/internal/intern/eval.h
+id.o: $(hdrdir)/ruby/internal/intern/file.h
+id.o: $(hdrdir)/ruby/internal/intern/hash.h
+id.o: $(hdrdir)/ruby/internal/intern/io.h
+id.o: $(hdrdir)/ruby/internal/intern/load.h
+id.o: $(hdrdir)/ruby/internal/intern/marshal.h
+id.o: $(hdrdir)/ruby/internal/intern/numeric.h
+id.o: $(hdrdir)/ruby/internal/intern/object.h
+id.o: $(hdrdir)/ruby/internal/intern/parse.h
+id.o: $(hdrdir)/ruby/internal/intern/proc.h
+id.o: $(hdrdir)/ruby/internal/intern/process.h
+id.o: $(hdrdir)/ruby/internal/intern/random.h
+id.o: $(hdrdir)/ruby/internal/intern/range.h
+id.o: $(hdrdir)/ruby/internal/intern/rational.h
+id.o: $(hdrdir)/ruby/internal/intern/re.h
+id.o: $(hdrdir)/ruby/internal/intern/ruby.h
+id.o: $(hdrdir)/ruby/internal/intern/select.h
+id.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+id.o: $(hdrdir)/ruby/internal/intern/set.h
+id.o: $(hdrdir)/ruby/internal/intern/signal.h
+id.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+id.o: $(hdrdir)/ruby/internal/intern/string.h
+id.o: $(hdrdir)/ruby/internal/intern/struct.h
+id.o: $(hdrdir)/ruby/internal/intern/thread.h
+id.o: $(hdrdir)/ruby/internal/intern/time.h
+id.o: $(hdrdir)/ruby/internal/intern/variable.h
+id.o: $(hdrdir)/ruby/internal/intern/vm.h
+id.o: $(hdrdir)/ruby/internal/interpreter.h
+id.o: $(hdrdir)/ruby/internal/iterator.h
+id.o: $(hdrdir)/ruby/internal/memory.h
+id.o: $(hdrdir)/ruby/internal/method.h
+id.o: $(hdrdir)/ruby/internal/module.h
+id.o: $(hdrdir)/ruby/internal/newobj.h
+id.o: $(hdrdir)/ruby/internal/scan_args.h
+id.o: $(hdrdir)/ruby/internal/special_consts.h
+id.o: $(hdrdir)/ruby/internal/static_assert.h
+id.o: $(hdrdir)/ruby/internal/stdalign.h
+id.o: $(hdrdir)/ruby/internal/stdbool.h
+id.o: $(hdrdir)/ruby/internal/stdckdint.h
+id.o: $(hdrdir)/ruby/internal/symbol.h
+id.o: $(hdrdir)/ruby/internal/value.h
+id.o: $(hdrdir)/ruby/internal/value_type.h
+id.o: $(hdrdir)/ruby/internal/variable.h
+id.o: $(hdrdir)/ruby/internal/warning_push.h
+id.o: $(hdrdir)/ruby/internal/xmalloc.h
+id.o: $(hdrdir)/ruby/missing.h
+id.o: $(hdrdir)/ruby/ruby.h
+id.o: $(hdrdir)/ruby/st.h
+id.o: $(hdrdir)/ruby/subst.h
+id.o: id.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/thread/id/extconf.rb b/ext/-test-/thread/id/extconf.rb
new file mode 100644
index 0000000000..a0ae0eff15
--- /dev/null
+++ b/ext/-test-/thread/id/extconf.rb
@@ -0,0 +1,3 @@
+if have_func("gettid")
+ create_makefile("-test-/thread/id")
+end
diff --git a/ext/-test-/thread/id/id.c b/ext/-test-/thread/id/id.c
new file mode 100644
index 0000000000..b46a5955e2
--- /dev/null
+++ b/ext/-test-/thread/id/id.c
@@ -0,0 +1,15 @@
+#include <ruby.h>
+
+static VALUE
+bug_gettid(VALUE self)
+{
+ pid_t tid = gettid();
+ return PIDT2NUM(tid);
+}
+
+void
+Init_id(void)
+{
+ VALUE klass = rb_define_module_under(rb_define_module("Bug"), "ThreadID");
+ rb_define_module_function(klass, "gettid", bug_gettid, 0);
+}
diff --git a/ext/-test-/thread/instrumentation/depend b/ext/-test-/thread/instrumentation/depend
new file mode 100644
index 0000000000..63e1c7e44f
--- /dev/null
+++ b/ext/-test-/thread/instrumentation/depend
@@ -0,0 +1,165 @@
+# AUTOGENERATED DEPENDENCIES START
+instrumentation.o: $(RUBY_EXTCONF_H)
+instrumentation.o: $(arch_hdrdir)/ruby/config.h
+instrumentation.o: $(hdrdir)/ruby/assert.h
+instrumentation.o: $(hdrdir)/ruby/atomic.h
+instrumentation.o: $(hdrdir)/ruby/backward.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/assume.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/attributes.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/bool.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/inttypes.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/limits.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/long_long.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/stdalign.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/stdarg.h
+instrumentation.o: $(hdrdir)/ruby/defines.h
+instrumentation.o: $(hdrdir)/ruby/intern.h
+instrumentation.o: $(hdrdir)/ruby/internal/abi.h
+instrumentation.o: $(hdrdir)/ruby/internal/anyargs.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/assume.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/artificial.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/cold.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/const.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/error.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/format.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/noalias.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/noinline.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/pure.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/restrict.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/warning.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/weakref.h
+instrumentation.o: $(hdrdir)/ruby/internal/cast.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_since.h
+instrumentation.o: $(hdrdir)/ruby/internal/config.h
+instrumentation.o: $(hdrdir)/ruby/internal/constant_p.h
+instrumentation.o: $(hdrdir)/ruby/internal/core.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rarray.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rbasic.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rbignum.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rclass.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rdata.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rfile.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rhash.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/robject.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rregexp.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rstring.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rstruct.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+instrumentation.o: $(hdrdir)/ruby/internal/ctype.h
+instrumentation.o: $(hdrdir)/ruby/internal/dllexport.h
+instrumentation.o: $(hdrdir)/ruby/internal/dosish.h
+instrumentation.o: $(hdrdir)/ruby/internal/error.h
+instrumentation.o: $(hdrdir)/ruby/internal/eval.h
+instrumentation.o: $(hdrdir)/ruby/internal/event.h
+instrumentation.o: $(hdrdir)/ruby/internal/fl_type.h
+instrumentation.o: $(hdrdir)/ruby/internal/gc.h
+instrumentation.o: $(hdrdir)/ruby/internal/glob.h
+instrumentation.o: $(hdrdir)/ruby/internal/globals.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/attribute.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/builtin.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/extension.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/feature.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/warning.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/array.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/bignum.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/class.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/compar.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/complex.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/cont.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/dir.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/enum.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/error.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/eval.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/file.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/hash.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/io.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/load.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/marshal.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/numeric.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/object.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/parse.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/proc.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/process.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/random.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/range.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/rational.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/re.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/ruby.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/select.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/set.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/signal.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/string.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/struct.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/thread.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/time.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/variable.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/vm.h
+instrumentation.o: $(hdrdir)/ruby/internal/interpreter.h
+instrumentation.o: $(hdrdir)/ruby/internal/iterator.h
+instrumentation.o: $(hdrdir)/ruby/internal/memory.h
+instrumentation.o: $(hdrdir)/ruby/internal/method.h
+instrumentation.o: $(hdrdir)/ruby/internal/module.h
+instrumentation.o: $(hdrdir)/ruby/internal/newobj.h
+instrumentation.o: $(hdrdir)/ruby/internal/scan_args.h
+instrumentation.o: $(hdrdir)/ruby/internal/special_consts.h
+instrumentation.o: $(hdrdir)/ruby/internal/static_assert.h
+instrumentation.o: $(hdrdir)/ruby/internal/stdalign.h
+instrumentation.o: $(hdrdir)/ruby/internal/stdbool.h
+instrumentation.o: $(hdrdir)/ruby/internal/stdckdint.h
+instrumentation.o: $(hdrdir)/ruby/internal/symbol.h
+instrumentation.o: $(hdrdir)/ruby/internal/value.h
+instrumentation.o: $(hdrdir)/ruby/internal/value_type.h
+instrumentation.o: $(hdrdir)/ruby/internal/variable.h
+instrumentation.o: $(hdrdir)/ruby/internal/warning_push.h
+instrumentation.o: $(hdrdir)/ruby/internal/xmalloc.h
+instrumentation.o: $(hdrdir)/ruby/missing.h
+instrumentation.o: $(hdrdir)/ruby/ruby.h
+instrumentation.o: $(hdrdir)/ruby/st.h
+instrumentation.o: $(hdrdir)/ruby/subst.h
+instrumentation.o: $(hdrdir)/ruby/thread.h
+instrumentation.o: $(hdrdir)/ruby/thread_native.h
+instrumentation.o: instrumentation.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/thread/instrumentation/extconf.rb b/ext/-test-/thread/instrumentation/extconf.rb
new file mode 100644
index 0000000000..a48ba3c045
--- /dev/null
+++ b/ext/-test-/thread/instrumentation/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/thread/instrumentation")
diff --git a/ext/-test-/thread/instrumentation/instrumentation.c b/ext/-test-/thread/instrumentation/instrumentation.c
new file mode 100644
index 0000000000..25e2902a78
--- /dev/null
+++ b/ext/-test-/thread/instrumentation/instrumentation.c
@@ -0,0 +1,218 @@
+#include "ruby/ruby.h"
+#include "ruby/atomic.h"
+#include "ruby/thread.h"
+
+#ifndef RB_THREAD_LOCAL_SPECIFIER
+# define RB_THREAD_LOCAL_SPECIFIER
+#endif
+
+static VALUE timeline_value = Qnil;
+
+struct thread_event {
+ VALUE thread;
+ rb_event_flag_t event;
+};
+
+#define MAX_EVENTS 1024
+static struct thread_event event_timeline[MAX_EVENTS];
+static rb_atomic_t timeline_cursor;
+
+static void
+event_timeline_gc_mark(void *ptr) {
+ rb_atomic_t cursor;
+ for (cursor = 0; cursor < timeline_cursor; cursor++) {
+ rb_gc_mark(event_timeline[cursor].thread);
+ }
+}
+
+static const rb_data_type_t event_timeline_type = {
+ "TestThreadInstrumentation/event_timeline",
+ {event_timeline_gc_mark, NULL, NULL,},
+ 0, 0,
+ RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static void
+reset_timeline(void)
+{
+ timeline_cursor = 0;
+ memset(event_timeline, 0, sizeof(struct thread_event) * MAX_EVENTS);
+}
+
+static rb_event_flag_t
+find_last_event(VALUE thread)
+{
+ rb_atomic_t cursor = timeline_cursor;
+ if (cursor) {
+ do {
+ if (event_timeline[cursor].thread == thread){
+ return event_timeline[cursor].event;
+ }
+ cursor--;
+ } while (cursor > 0);
+ }
+ return 0;
+}
+
+static const char *
+event_name(rb_event_flag_t event)
+{
+ switch (event) {
+ case RUBY_INTERNAL_THREAD_EVENT_STARTED:
+ return "started";
+ case RUBY_INTERNAL_THREAD_EVENT_READY:
+ return "ready";
+ case RUBY_INTERNAL_THREAD_EVENT_RESUMED:
+ return "resumed";
+ case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED:
+ return "suspended";
+ case RUBY_INTERNAL_THREAD_EVENT_EXITED:
+ return "exited";
+ }
+ return "no-event";
+}
+
+static void
+unexpected(bool strict, const char *format, VALUE thread, rb_event_flag_t last_event)
+{
+ const char *last_event_name = event_name(last_event);
+ if (strict) {
+ rb_bug(format, thread, last_event_name);
+ }
+ else {
+ fprintf(stderr, format, thread, last_event_name);
+ fprintf(stderr, "\n");
+ }
+}
+
+static void
+ex_callback(rb_event_flag_t event, const rb_internal_thread_event_data_t *event_data, void *user_data)
+{
+ rb_event_flag_t last_event = find_last_event(event_data->thread);
+ bool strict = (bool)user_data;
+
+ if (last_event != 0) {
+ switch (event) {
+ case RUBY_INTERNAL_THREAD_EVENT_STARTED:
+ unexpected(strict, "[thread=%"PRIxVALUE"] `started` event can't be preceded by `%s`", event_data->thread, last_event);
+ break;
+ case RUBY_INTERNAL_THREAD_EVENT_READY:
+ if (last_event != RUBY_INTERNAL_THREAD_EVENT_STARTED && last_event != RUBY_INTERNAL_THREAD_EVENT_SUSPENDED) {
+ unexpected(strict, "[thread=%"PRIxVALUE"] `ready` must be preceded by `started` or `suspended`, got: `%s`", event_data->thread, last_event);
+ }
+ break;
+ case RUBY_INTERNAL_THREAD_EVENT_RESUMED:
+ if (last_event != RUBY_INTERNAL_THREAD_EVENT_READY) {
+ unexpected(strict, "[thread=%"PRIxVALUE"] `resumed` must be preceded by `ready`, got: `%s`", event_data->thread, last_event);
+ }
+ break;
+ case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED:
+ if (last_event != RUBY_INTERNAL_THREAD_EVENT_RESUMED) {
+ unexpected(strict, "[thread=%"PRIxVALUE"] `suspended` must be preceded by `resumed`, got: `%s`", event_data->thread, last_event);
+ }
+ break;
+ case RUBY_INTERNAL_THREAD_EVENT_EXITED:
+ if (last_event != RUBY_INTERNAL_THREAD_EVENT_RESUMED && last_event != RUBY_INTERNAL_THREAD_EVENT_SUSPENDED) {
+ unexpected(strict, "[thread=%"PRIxVALUE"] `exited` must be preceded by `resumed` or `suspended`, got: `%s`", event_data->thread, last_event);
+ }
+ break;
+ }
+ }
+
+ rb_atomic_t cursor = RUBY_ATOMIC_FETCH_ADD(timeline_cursor, 1);
+ if (cursor >= MAX_EVENTS) {
+ rb_bug("TestThreadInstrumentation: ran out of event_timeline space");
+ }
+
+ event_timeline[cursor].thread = event_data->thread;
+ event_timeline[cursor].event = event;
+}
+
+static rb_internal_thread_event_hook_t * single_hook = NULL;
+
+static VALUE
+thread_register_callback(VALUE thread, VALUE strict)
+{
+ single_hook = rb_internal_thread_add_event_hook(
+ ex_callback,
+ RUBY_INTERNAL_THREAD_EVENT_STARTED |
+ RUBY_INTERNAL_THREAD_EVENT_READY |
+ RUBY_INTERNAL_THREAD_EVENT_RESUMED |
+ RUBY_INTERNAL_THREAD_EVENT_SUSPENDED |
+ RUBY_INTERNAL_THREAD_EVENT_EXITED,
+ (void *)RTEST(strict)
+ );
+
+ return Qnil;
+}
+
+static VALUE
+event_symbol(rb_event_flag_t event)
+{
+ switch (event) {
+ case RUBY_INTERNAL_THREAD_EVENT_STARTED:
+ return rb_id2sym(rb_intern("started"));
+ case RUBY_INTERNAL_THREAD_EVENT_READY:
+ return rb_id2sym(rb_intern("ready"));
+ case RUBY_INTERNAL_THREAD_EVENT_RESUMED:
+ return rb_id2sym(rb_intern("resumed"));
+ case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED:
+ return rb_id2sym(rb_intern("suspended"));
+ case RUBY_INTERNAL_THREAD_EVENT_EXITED:
+ return rb_id2sym(rb_intern("exited"));
+ default:
+ rb_bug("TestThreadInstrumentation: Unexpected event");
+ break;
+ }
+}
+
+static VALUE
+thread_unregister_callback(VALUE thread)
+{
+ if (single_hook) {
+ rb_internal_thread_remove_event_hook(single_hook);
+ single_hook = NULL;
+ }
+
+ VALUE events = rb_ary_new_capa(timeline_cursor);
+ rb_atomic_t cursor;
+ for (cursor = 0; cursor < timeline_cursor; cursor++) {
+ VALUE pair = rb_ary_new_capa(2);
+ rb_ary_push(pair, event_timeline[cursor].thread);
+ rb_ary_push(pair, event_symbol(event_timeline[cursor].event));
+ rb_ary_push(events, pair);
+ }
+
+ reset_timeline();
+
+ return events;
+}
+
+static VALUE
+thread_register_and_unregister_callback(VALUE thread)
+{
+ rb_internal_thread_event_hook_t * hooks[5];
+ for (int i = 0; i < 5; i++) {
+ hooks[i] = rb_internal_thread_add_event_hook(ex_callback, RUBY_INTERNAL_THREAD_EVENT_READY, NULL);
+ }
+
+ if (!rb_internal_thread_remove_event_hook(hooks[4])) return Qfalse;
+ if (!rb_internal_thread_remove_event_hook(hooks[0])) return Qfalse;
+ if (!rb_internal_thread_remove_event_hook(hooks[3])) return Qfalse;
+ if (!rb_internal_thread_remove_event_hook(hooks[2])) return Qfalse;
+ if (!rb_internal_thread_remove_event_hook(hooks[1])) return Qfalse;
+ return Qtrue;
+}
+
+void
+Init_instrumentation(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_module_under(mBug, "ThreadInstrumentation");
+ rb_global_variable(&timeline_value);
+ timeline_value = TypedData_Wrap_Struct(0, &event_timeline_type, (void *)1);
+
+ rb_define_singleton_method(klass, "register_callback", thread_register_callback, 1);
+ rb_define_singleton_method(klass, "unregister_callback", thread_unregister_callback, 0);
+ rb_define_singleton_method(klass, "register_and_unregister_callbacks", thread_register_and_unregister_callback, 0);
+}
diff --git a/ext/-test-/thread/lock_native_thread/depend b/ext/-test-/thread/lock_native_thread/depend
new file mode 100644
index 0000000000..a32843e531
--- /dev/null
+++ b/ext/-test-/thread/lock_native_thread/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+lock_native_thread.o: $(RUBY_EXTCONF_H)
+lock_native_thread.o: $(arch_hdrdir)/ruby/config.h
+lock_native_thread.o: $(hdrdir)/ruby/assert.h
+lock_native_thread.o: $(hdrdir)/ruby/backward.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/assume.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/attributes.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/bool.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/inttypes.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/limits.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/long_long.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/stdalign.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/stdarg.h
+lock_native_thread.o: $(hdrdir)/ruby/defines.h
+lock_native_thread.o: $(hdrdir)/ruby/intern.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/abi.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/anyargs.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/assume.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/artificial.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/cold.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/const.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/error.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/format.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noalias.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noinline.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/pure.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/restrict.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/warning.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/weakref.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/cast.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_since.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/config.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/constant_p.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rarray.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rbasic.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rbignum.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rclass.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rdata.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rfile.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rhash.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/robject.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rregexp.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rstring.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rstruct.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/ctype.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/dllexport.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/dosish.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/error.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/eval.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/event.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/fl_type.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/gc.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/glob.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/globals.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/attribute.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/builtin.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/extension.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/feature.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/warning.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/array.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/bignum.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/class.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/compar.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/complex.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/cont.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/dir.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/enum.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/error.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/eval.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/file.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/hash.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/io.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/load.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/marshal.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/numeric.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/object.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/parse.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/proc.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/process.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/random.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/range.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/rational.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/re.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/ruby.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/select.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/set.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/signal.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/string.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/struct.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/thread.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/time.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/variable.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/vm.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/interpreter.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/iterator.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/memory.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/method.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/module.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/newobj.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/scan_args.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/special_consts.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/static_assert.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/stdalign.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/stdbool.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/stdckdint.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/symbol.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/value.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/value_type.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/variable.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/warning_push.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/xmalloc.h
+lock_native_thread.o: $(hdrdir)/ruby/missing.h
+lock_native_thread.o: $(hdrdir)/ruby/ruby.h
+lock_native_thread.o: $(hdrdir)/ruby/st.h
+lock_native_thread.o: $(hdrdir)/ruby/subst.h
+lock_native_thread.o: $(hdrdir)/ruby/thread.h
+lock_native_thread.o: lock_native_thread.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/thread/lock_native_thread/extconf.rb b/ext/-test-/thread/lock_native_thread/extconf.rb
new file mode 100644
index 0000000000..832bfde01a
--- /dev/null
+++ b/ext/-test-/thread/lock_native_thread/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/thread/lock_native_thread")
diff --git a/ext/-test-/thread/lock_native_thread/lock_native_thread.c b/ext/-test-/thread/lock_native_thread/lock_native_thread.c
new file mode 100644
index 0000000000..2eb75809a9
--- /dev/null
+++ b/ext/-test-/thread/lock_native_thread/lock_native_thread.c
@@ -0,0 +1,50 @@
+
+#include "ruby/ruby.h"
+#include "ruby/thread.h"
+
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+
+static pthread_key_t tls_key;
+
+static VALUE
+get_tls(VALUE self)
+{
+ return (VALUE)pthread_getspecific(tls_key);
+}
+
+static VALUE
+set_tls(VALUE self, VALUE vn)
+{
+ pthread_setspecific(tls_key, (void *)vn);
+ return Qnil;
+}
+
+static VALUE
+lock_native_thread(VALUE self)
+{
+ return rb_thread_lock_native_thread() ? Qtrue : Qfalse;
+}
+
+void
+Init_lock_native_thread(void)
+{
+ int r;
+
+ if ((r = pthread_key_create(&tls_key, NULL)) != 0) {
+ rb_bug("pthread_key_create() returns %d", r);
+ }
+ pthread_setspecific(tls_key, NULL);
+
+ rb_define_method(rb_cThread, "lock_native_thread", lock_native_thread, 0);
+ rb_define_method(rb_cThread, "get_tls", get_tls, 0);
+ rb_define_method(rb_cThread, "set_tls", set_tls, 1);
+}
+
+#else // HAVE_PTHREAD_H
+void
+Init_lock_native_thread(void)
+{
+ // do nothing
+}
+#endif // HAVE_PTHREAD_H
diff --git a/ext/-test-/time/depend b/ext/-test-/time/depend
new file mode 100644
index 0000000000..e5b05f3113
--- /dev/null
+++ b/ext/-test-/time/depend
@@ -0,0 +1,490 @@
+# AUTOGENERATED DEPENDENCIES START
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+leap_second.o: $(RUBY_EXTCONF_H)
+leap_second.o: $(arch_hdrdir)/ruby/config.h
+leap_second.o: $(hdrdir)/ruby.h
+leap_second.o: $(hdrdir)/ruby/assert.h
+leap_second.o: $(hdrdir)/ruby/backward.h
+leap_second.o: $(hdrdir)/ruby/backward/2/assume.h
+leap_second.o: $(hdrdir)/ruby/backward/2/attributes.h
+leap_second.o: $(hdrdir)/ruby/backward/2/bool.h
+leap_second.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+leap_second.o: $(hdrdir)/ruby/backward/2/inttypes.h
+leap_second.o: $(hdrdir)/ruby/backward/2/limits.h
+leap_second.o: $(hdrdir)/ruby/backward/2/long_long.h
+leap_second.o: $(hdrdir)/ruby/backward/2/stdalign.h
+leap_second.o: $(hdrdir)/ruby/backward/2/stdarg.h
+leap_second.o: $(hdrdir)/ruby/defines.h
+leap_second.o: $(hdrdir)/ruby/intern.h
+leap_second.o: $(hdrdir)/ruby/internal/abi.h
+leap_second.o: $(hdrdir)/ruby/internal/anyargs.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+leap_second.o: $(hdrdir)/ruby/internal/assume.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/artificial.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/cold.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/const.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/error.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/format.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/noalias.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/noinline.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/pure.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/restrict.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/warning.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/weakref.h
+leap_second.o: $(hdrdir)/ruby/internal/cast.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_since.h
+leap_second.o: $(hdrdir)/ruby/internal/config.h
+leap_second.o: $(hdrdir)/ruby/internal/constant_p.h
+leap_second.o: $(hdrdir)/ruby/internal/core.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rarray.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rbasic.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rbignum.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rclass.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rdata.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rfile.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rhash.h
+leap_second.o: $(hdrdir)/ruby/internal/core/robject.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rregexp.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rstring.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rstruct.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+leap_second.o: $(hdrdir)/ruby/internal/ctype.h
+leap_second.o: $(hdrdir)/ruby/internal/dllexport.h
+leap_second.o: $(hdrdir)/ruby/internal/dosish.h
+leap_second.o: $(hdrdir)/ruby/internal/error.h
+leap_second.o: $(hdrdir)/ruby/internal/eval.h
+leap_second.o: $(hdrdir)/ruby/internal/event.h
+leap_second.o: $(hdrdir)/ruby/internal/fl_type.h
+leap_second.o: $(hdrdir)/ruby/internal/gc.h
+leap_second.o: $(hdrdir)/ruby/internal/glob.h
+leap_second.o: $(hdrdir)/ruby/internal/globals.h
+leap_second.o: $(hdrdir)/ruby/internal/has/attribute.h
+leap_second.o: $(hdrdir)/ruby/internal/has/builtin.h
+leap_second.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+leap_second.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+leap_second.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+leap_second.o: $(hdrdir)/ruby/internal/has/extension.h
+leap_second.o: $(hdrdir)/ruby/internal/has/feature.h
+leap_second.o: $(hdrdir)/ruby/internal/has/warning.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/array.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/bignum.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/class.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/compar.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/complex.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/cont.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/dir.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/enum.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/error.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/eval.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/file.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/hash.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/io.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/load.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/marshal.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/numeric.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/object.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/parse.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/proc.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/process.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/random.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/range.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/rational.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/re.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/ruby.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/select.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/set.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/signal.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/string.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/struct.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/thread.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/time.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/variable.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/vm.h
+leap_second.o: $(hdrdir)/ruby/internal/interpreter.h
+leap_second.o: $(hdrdir)/ruby/internal/iterator.h
+leap_second.o: $(hdrdir)/ruby/internal/memory.h
+leap_second.o: $(hdrdir)/ruby/internal/method.h
+leap_second.o: $(hdrdir)/ruby/internal/module.h
+leap_second.o: $(hdrdir)/ruby/internal/newobj.h
+leap_second.o: $(hdrdir)/ruby/internal/scan_args.h
+leap_second.o: $(hdrdir)/ruby/internal/special_consts.h
+leap_second.o: $(hdrdir)/ruby/internal/static_assert.h
+leap_second.o: $(hdrdir)/ruby/internal/stdalign.h
+leap_second.o: $(hdrdir)/ruby/internal/stdbool.h
+leap_second.o: $(hdrdir)/ruby/internal/stdckdint.h
+leap_second.o: $(hdrdir)/ruby/internal/symbol.h
+leap_second.o: $(hdrdir)/ruby/internal/value.h
+leap_second.o: $(hdrdir)/ruby/internal/value_type.h
+leap_second.o: $(hdrdir)/ruby/internal/variable.h
+leap_second.o: $(hdrdir)/ruby/internal/warning_push.h
+leap_second.o: $(hdrdir)/ruby/internal/xmalloc.h
+leap_second.o: $(hdrdir)/ruby/missing.h
+leap_second.o: $(hdrdir)/ruby/ruby.h
+leap_second.o: $(hdrdir)/ruby/st.h
+leap_second.o: $(hdrdir)/ruby/subst.h
+leap_second.o: $(top_srcdir)/internal/bits.h
+leap_second.o: $(top_srcdir)/internal/compilers.h
+leap_second.o: $(top_srcdir)/internal/static_assert.h
+leap_second.o: $(top_srcdir)/internal/time.h
+leap_second.o: leap_second.c
+new.o: $(RUBY_EXTCONF_H)
+new.o: $(arch_hdrdir)/ruby/config.h
+new.o: $(hdrdir)/ruby.h
+new.o: $(hdrdir)/ruby/assert.h
+new.o: $(hdrdir)/ruby/backward.h
+new.o: $(hdrdir)/ruby/backward/2/assume.h
+new.o: $(hdrdir)/ruby/backward/2/attributes.h
+new.o: $(hdrdir)/ruby/backward/2/bool.h
+new.o: $(hdrdir)/ruby/backward/2/inttypes.h
+new.o: $(hdrdir)/ruby/backward/2/limits.h
+new.o: $(hdrdir)/ruby/backward/2/long_long.h
+new.o: $(hdrdir)/ruby/backward/2/stdalign.h
+new.o: $(hdrdir)/ruby/backward/2/stdarg.h
+new.o: $(hdrdir)/ruby/defines.h
+new.o: $(hdrdir)/ruby/intern.h
+new.o: $(hdrdir)/ruby/internal/abi.h
+new.o: $(hdrdir)/ruby/internal/anyargs.h
+new.o: $(hdrdir)/ruby/internal/arithmetic.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+new.o: $(hdrdir)/ruby/internal/assume.h
+new.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+new.o: $(hdrdir)/ruby/internal/attr/artificial.h
+new.o: $(hdrdir)/ruby/internal/attr/cold.h
+new.o: $(hdrdir)/ruby/internal/attr/const.h
+new.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+new.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+new.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+new.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+new.o: $(hdrdir)/ruby/internal/attr/error.h
+new.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+new.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+new.o: $(hdrdir)/ruby/internal/attr/format.h
+new.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+new.o: $(hdrdir)/ruby/internal/attr/noalias.h
+new.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+new.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+new.o: $(hdrdir)/ruby/internal/attr/noinline.h
+new.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+new.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+new.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+new.o: $(hdrdir)/ruby/internal/attr/pure.h
+new.o: $(hdrdir)/ruby/internal/attr/restrict.h
+new.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+new.o: $(hdrdir)/ruby/internal/attr/warning.h
+new.o: $(hdrdir)/ruby/internal/attr/weakref.h
+new.o: $(hdrdir)/ruby/internal/cast.h
+new.o: $(hdrdir)/ruby/internal/compiler_is.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+new.o: $(hdrdir)/ruby/internal/compiler_since.h
+new.o: $(hdrdir)/ruby/internal/config.h
+new.o: $(hdrdir)/ruby/internal/constant_p.h
+new.o: $(hdrdir)/ruby/internal/core.h
+new.o: $(hdrdir)/ruby/internal/core/rarray.h
+new.o: $(hdrdir)/ruby/internal/core/rbasic.h
+new.o: $(hdrdir)/ruby/internal/core/rbignum.h
+new.o: $(hdrdir)/ruby/internal/core/rclass.h
+new.o: $(hdrdir)/ruby/internal/core/rdata.h
+new.o: $(hdrdir)/ruby/internal/core/rfile.h
+new.o: $(hdrdir)/ruby/internal/core/rhash.h
+new.o: $(hdrdir)/ruby/internal/core/robject.h
+new.o: $(hdrdir)/ruby/internal/core/rregexp.h
+new.o: $(hdrdir)/ruby/internal/core/rstring.h
+new.o: $(hdrdir)/ruby/internal/core/rstruct.h
+new.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+new.o: $(hdrdir)/ruby/internal/ctype.h
+new.o: $(hdrdir)/ruby/internal/dllexport.h
+new.o: $(hdrdir)/ruby/internal/dosish.h
+new.o: $(hdrdir)/ruby/internal/error.h
+new.o: $(hdrdir)/ruby/internal/eval.h
+new.o: $(hdrdir)/ruby/internal/event.h
+new.o: $(hdrdir)/ruby/internal/fl_type.h
+new.o: $(hdrdir)/ruby/internal/gc.h
+new.o: $(hdrdir)/ruby/internal/glob.h
+new.o: $(hdrdir)/ruby/internal/globals.h
+new.o: $(hdrdir)/ruby/internal/has/attribute.h
+new.o: $(hdrdir)/ruby/internal/has/builtin.h
+new.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+new.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+new.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+new.o: $(hdrdir)/ruby/internal/has/extension.h
+new.o: $(hdrdir)/ruby/internal/has/feature.h
+new.o: $(hdrdir)/ruby/internal/has/warning.h
+new.o: $(hdrdir)/ruby/internal/intern/array.h
+new.o: $(hdrdir)/ruby/internal/intern/bignum.h
+new.o: $(hdrdir)/ruby/internal/intern/class.h
+new.o: $(hdrdir)/ruby/internal/intern/compar.h
+new.o: $(hdrdir)/ruby/internal/intern/complex.h
+new.o: $(hdrdir)/ruby/internal/intern/cont.h
+new.o: $(hdrdir)/ruby/internal/intern/dir.h
+new.o: $(hdrdir)/ruby/internal/intern/enum.h
+new.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+new.o: $(hdrdir)/ruby/internal/intern/error.h
+new.o: $(hdrdir)/ruby/internal/intern/eval.h
+new.o: $(hdrdir)/ruby/internal/intern/file.h
+new.o: $(hdrdir)/ruby/internal/intern/hash.h
+new.o: $(hdrdir)/ruby/internal/intern/io.h
+new.o: $(hdrdir)/ruby/internal/intern/load.h
+new.o: $(hdrdir)/ruby/internal/intern/marshal.h
+new.o: $(hdrdir)/ruby/internal/intern/numeric.h
+new.o: $(hdrdir)/ruby/internal/intern/object.h
+new.o: $(hdrdir)/ruby/internal/intern/parse.h
+new.o: $(hdrdir)/ruby/internal/intern/proc.h
+new.o: $(hdrdir)/ruby/internal/intern/process.h
+new.o: $(hdrdir)/ruby/internal/intern/random.h
+new.o: $(hdrdir)/ruby/internal/intern/range.h
+new.o: $(hdrdir)/ruby/internal/intern/rational.h
+new.o: $(hdrdir)/ruby/internal/intern/re.h
+new.o: $(hdrdir)/ruby/internal/intern/ruby.h
+new.o: $(hdrdir)/ruby/internal/intern/select.h
+new.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+new.o: $(hdrdir)/ruby/internal/intern/set.h
+new.o: $(hdrdir)/ruby/internal/intern/signal.h
+new.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+new.o: $(hdrdir)/ruby/internal/intern/string.h
+new.o: $(hdrdir)/ruby/internal/intern/struct.h
+new.o: $(hdrdir)/ruby/internal/intern/thread.h
+new.o: $(hdrdir)/ruby/internal/intern/time.h
+new.o: $(hdrdir)/ruby/internal/intern/variable.h
+new.o: $(hdrdir)/ruby/internal/intern/vm.h
+new.o: $(hdrdir)/ruby/internal/interpreter.h
+new.o: $(hdrdir)/ruby/internal/iterator.h
+new.o: $(hdrdir)/ruby/internal/memory.h
+new.o: $(hdrdir)/ruby/internal/method.h
+new.o: $(hdrdir)/ruby/internal/module.h
+new.o: $(hdrdir)/ruby/internal/newobj.h
+new.o: $(hdrdir)/ruby/internal/scan_args.h
+new.o: $(hdrdir)/ruby/internal/special_consts.h
+new.o: $(hdrdir)/ruby/internal/static_assert.h
+new.o: $(hdrdir)/ruby/internal/stdalign.h
+new.o: $(hdrdir)/ruby/internal/stdbool.h
+new.o: $(hdrdir)/ruby/internal/stdckdint.h
+new.o: $(hdrdir)/ruby/internal/symbol.h
+new.o: $(hdrdir)/ruby/internal/value.h
+new.o: $(hdrdir)/ruby/internal/value_type.h
+new.o: $(hdrdir)/ruby/internal/variable.h
+new.o: $(hdrdir)/ruby/internal/warning_push.h
+new.o: $(hdrdir)/ruby/internal/xmalloc.h
+new.o: $(hdrdir)/ruby/missing.h
+new.o: $(hdrdir)/ruby/ruby.h
+new.o: $(hdrdir)/ruby/st.h
+new.o: $(hdrdir)/ruby/subst.h
+new.o: new.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/time/extconf.rb b/ext/-test-/time/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/time/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/time/init.c b/ext/-test-/time/init.c
new file mode 100644
index 0000000000..91f8bf825b
--- /dev/null
+++ b/ext/-test-/time/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_time_##n(VALUE klass); Init_time_##n(klass);}
+
+void
+Init_time(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "Time", rb_cTime);
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/time/new.c b/ext/-test-/time/new.c
new file mode 100644
index 0000000000..6f894417b6
--- /dev/null
+++ b/ext/-test-/time/new.c
@@ -0,0 +1,34 @@
+#include "ruby.h"
+
+static VALUE
+bug_time_s_nano_new(VALUE klass, VALUE sec, VALUE nsec)
+{
+ return rb_time_nano_new(NUM2TIMET(sec), NUM2LONG(nsec));
+}
+
+static VALUE
+bug_time_s_timespec_new(VALUE klass, VALUE sec, VALUE nsec, VALUE gmtoff)
+{
+ struct timespec ts;
+ ts.tv_sec = NUM2TIMET(sec);
+ ts.tv_nsec = NUM2LONG(nsec);
+ return rb_time_timespec_new(&ts, NUM2INT(gmtoff));
+}
+
+static VALUE
+bug_time_s_timespec_now(VALUE klass)
+{
+ struct timespec ts;
+ VALUE v;
+ rb_timespec_now(&ts);
+ v = rb_Rational(LONG2NUM(ts.tv_nsec), LONG2NUM(1000000000L));
+ return rb_num_coerce_bin(TIMET2NUM(ts.tv_sec), v, '+');
+}
+
+void
+Init_time_new(VALUE klass)
+{
+ rb_define_singleton_method(klass, "nano_new", bug_time_s_nano_new, 2);
+ rb_define_singleton_method(klass, "timespec_new", bug_time_s_timespec_new, 3);
+ rb_define_singleton_method(klass, "timespec_now", bug_time_s_timespec_now, 0);
+}
diff --git a/ext/-test-/tracepoint/depend b/ext/-test-/tracepoint/depend
new file mode 100644
index 0000000000..014ba83b16
--- /dev/null
+++ b/ext/-test-/tracepoint/depend
@@ -0,0 +1,324 @@
+# AUTOGENERATED DEPENDENCIES START
+gc_hook.o: $(RUBY_EXTCONF_H)
+gc_hook.o: $(arch_hdrdir)/ruby/config.h
+gc_hook.o: $(hdrdir)/ruby/assert.h
+gc_hook.o: $(hdrdir)/ruby/backward.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/assume.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/attributes.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/bool.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/inttypes.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/limits.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/long_long.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/stdalign.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/stdarg.h
+gc_hook.o: $(hdrdir)/ruby/debug.h
+gc_hook.o: $(hdrdir)/ruby/defines.h
+gc_hook.o: $(hdrdir)/ruby/intern.h
+gc_hook.o: $(hdrdir)/ruby/internal/abi.h
+gc_hook.o: $(hdrdir)/ruby/internal/anyargs.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/assume.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/artificial.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/cold.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/const.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/error.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/format.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/noalias.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/noinline.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/pure.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/restrict.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/warning.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/weakref.h
+gc_hook.o: $(hdrdir)/ruby/internal/cast.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_since.h
+gc_hook.o: $(hdrdir)/ruby/internal/config.h
+gc_hook.o: $(hdrdir)/ruby/internal/constant_p.h
+gc_hook.o: $(hdrdir)/ruby/internal/core.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rarray.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rbasic.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rbignum.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rclass.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rdata.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rfile.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rhash.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/robject.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rregexp.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rstring.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rstruct.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+gc_hook.o: $(hdrdir)/ruby/internal/ctype.h
+gc_hook.o: $(hdrdir)/ruby/internal/dllexport.h
+gc_hook.o: $(hdrdir)/ruby/internal/dosish.h
+gc_hook.o: $(hdrdir)/ruby/internal/error.h
+gc_hook.o: $(hdrdir)/ruby/internal/eval.h
+gc_hook.o: $(hdrdir)/ruby/internal/event.h
+gc_hook.o: $(hdrdir)/ruby/internal/fl_type.h
+gc_hook.o: $(hdrdir)/ruby/internal/gc.h
+gc_hook.o: $(hdrdir)/ruby/internal/glob.h
+gc_hook.o: $(hdrdir)/ruby/internal/globals.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/attribute.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/builtin.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/extension.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/feature.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/warning.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/array.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/bignum.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/class.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/compar.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/complex.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/cont.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/dir.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/enum.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/error.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/eval.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/file.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/hash.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/io.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/load.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/marshal.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/numeric.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/object.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/parse.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/proc.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/process.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/random.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/range.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/rational.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/re.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/ruby.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/select.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/set.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/signal.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/string.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/struct.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/thread.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/time.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/variable.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/vm.h
+gc_hook.o: $(hdrdir)/ruby/internal/interpreter.h
+gc_hook.o: $(hdrdir)/ruby/internal/iterator.h
+gc_hook.o: $(hdrdir)/ruby/internal/memory.h
+gc_hook.o: $(hdrdir)/ruby/internal/method.h
+gc_hook.o: $(hdrdir)/ruby/internal/module.h
+gc_hook.o: $(hdrdir)/ruby/internal/newobj.h
+gc_hook.o: $(hdrdir)/ruby/internal/scan_args.h
+gc_hook.o: $(hdrdir)/ruby/internal/special_consts.h
+gc_hook.o: $(hdrdir)/ruby/internal/static_assert.h
+gc_hook.o: $(hdrdir)/ruby/internal/stdalign.h
+gc_hook.o: $(hdrdir)/ruby/internal/stdbool.h
+gc_hook.o: $(hdrdir)/ruby/internal/stdckdint.h
+gc_hook.o: $(hdrdir)/ruby/internal/symbol.h
+gc_hook.o: $(hdrdir)/ruby/internal/value.h
+gc_hook.o: $(hdrdir)/ruby/internal/value_type.h
+gc_hook.o: $(hdrdir)/ruby/internal/variable.h
+gc_hook.o: $(hdrdir)/ruby/internal/warning_push.h
+gc_hook.o: $(hdrdir)/ruby/internal/xmalloc.h
+gc_hook.o: $(hdrdir)/ruby/missing.h
+gc_hook.o: $(hdrdir)/ruby/ruby.h
+gc_hook.o: $(hdrdir)/ruby/st.h
+gc_hook.o: $(hdrdir)/ruby/subst.h
+gc_hook.o: gc_hook.c
+tracepoint.o: $(RUBY_EXTCONF_H)
+tracepoint.o: $(arch_hdrdir)/ruby/config.h
+tracepoint.o: $(hdrdir)/ruby/assert.h
+tracepoint.o: $(hdrdir)/ruby/backward.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/assume.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/attributes.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/bool.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/inttypes.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/limits.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/long_long.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/stdalign.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/stdarg.h
+tracepoint.o: $(hdrdir)/ruby/debug.h
+tracepoint.o: $(hdrdir)/ruby/defines.h
+tracepoint.o: $(hdrdir)/ruby/intern.h
+tracepoint.o: $(hdrdir)/ruby/internal/abi.h
+tracepoint.o: $(hdrdir)/ruby/internal/anyargs.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/assume.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/artificial.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/cold.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/const.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/error.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/format.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/noalias.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/noinline.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/pure.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/restrict.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/warning.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/weakref.h
+tracepoint.o: $(hdrdir)/ruby/internal/cast.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_since.h
+tracepoint.o: $(hdrdir)/ruby/internal/config.h
+tracepoint.o: $(hdrdir)/ruby/internal/constant_p.h
+tracepoint.o: $(hdrdir)/ruby/internal/core.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rarray.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rbasic.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rbignum.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rclass.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rdata.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rfile.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rhash.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/robject.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rregexp.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rstring.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rstruct.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+tracepoint.o: $(hdrdir)/ruby/internal/ctype.h
+tracepoint.o: $(hdrdir)/ruby/internal/dllexport.h
+tracepoint.o: $(hdrdir)/ruby/internal/dosish.h
+tracepoint.o: $(hdrdir)/ruby/internal/error.h
+tracepoint.o: $(hdrdir)/ruby/internal/eval.h
+tracepoint.o: $(hdrdir)/ruby/internal/event.h
+tracepoint.o: $(hdrdir)/ruby/internal/fl_type.h
+tracepoint.o: $(hdrdir)/ruby/internal/gc.h
+tracepoint.o: $(hdrdir)/ruby/internal/glob.h
+tracepoint.o: $(hdrdir)/ruby/internal/globals.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/attribute.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/builtin.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/extension.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/feature.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/warning.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/array.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/bignum.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/class.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/compar.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/complex.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/cont.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/dir.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/enum.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/error.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/eval.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/file.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/hash.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/io.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/load.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/marshal.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/numeric.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/object.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/parse.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/proc.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/process.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/random.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/range.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/rational.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/re.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/ruby.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/select.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/set.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/signal.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/string.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/struct.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/thread.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/time.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/variable.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/vm.h
+tracepoint.o: $(hdrdir)/ruby/internal/interpreter.h
+tracepoint.o: $(hdrdir)/ruby/internal/iterator.h
+tracepoint.o: $(hdrdir)/ruby/internal/memory.h
+tracepoint.o: $(hdrdir)/ruby/internal/method.h
+tracepoint.o: $(hdrdir)/ruby/internal/module.h
+tracepoint.o: $(hdrdir)/ruby/internal/newobj.h
+tracepoint.o: $(hdrdir)/ruby/internal/scan_args.h
+tracepoint.o: $(hdrdir)/ruby/internal/special_consts.h
+tracepoint.o: $(hdrdir)/ruby/internal/static_assert.h
+tracepoint.o: $(hdrdir)/ruby/internal/stdalign.h
+tracepoint.o: $(hdrdir)/ruby/internal/stdbool.h
+tracepoint.o: $(hdrdir)/ruby/internal/stdckdint.h
+tracepoint.o: $(hdrdir)/ruby/internal/symbol.h
+tracepoint.o: $(hdrdir)/ruby/internal/value.h
+tracepoint.o: $(hdrdir)/ruby/internal/value_type.h
+tracepoint.o: $(hdrdir)/ruby/internal/variable.h
+tracepoint.o: $(hdrdir)/ruby/internal/warning_push.h
+tracepoint.o: $(hdrdir)/ruby/internal/xmalloc.h
+tracepoint.o: $(hdrdir)/ruby/missing.h
+tracepoint.o: $(hdrdir)/ruby/ruby.h
+tracepoint.o: $(hdrdir)/ruby/st.h
+tracepoint.o: $(hdrdir)/ruby/subst.h
+tracepoint.o: tracepoint.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/tracepoint/extconf.rb b/ext/-test-/tracepoint/extconf.rb
new file mode 100644
index 0000000000..2b7258d072
--- /dev/null
+++ b/ext/-test-/tracepoint/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/tracepoint")
diff --git a/ext/-test-/tracepoint/gc_hook.c b/ext/-test-/tracepoint/gc_hook.c
new file mode 100644
index 0000000000..525be6da63
--- /dev/null
+++ b/ext/-test-/tracepoint/gc_hook.c
@@ -0,0 +1,89 @@
+#include "ruby/ruby.h"
+#include "ruby/debug.h"
+
+static int invoking; /* TODO: should not be global variable */
+extern VALUE tp_mBug;
+
+static VALUE
+invoke_proc_ensure(VALUE _)
+{
+ invoking = 0;
+ return Qnil;
+}
+
+static VALUE
+invoke_proc_begin(VALUE proc)
+{
+ return rb_proc_call(proc, rb_ary_new());
+}
+
+static void
+invoke_proc(void *ivar_name)
+{
+ VALUE proc = rb_ivar_get(tp_mBug, rb_intern(ivar_name));
+ invoking += 1;
+ rb_ensure(invoke_proc_begin, proc, invoke_proc_ensure, 0);
+}
+
+static void
+gc_start_end_i(VALUE tpval, void *data)
+{
+ if (0) {
+ rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval);
+ fprintf(stderr, "trace: %s\n", rb_tracearg_event_flag(tparg) == RUBY_INTERNAL_EVENT_GC_START ? "gc_start" : "gc_end");
+ }
+
+ if (invoking == 0) {
+ /* will overwrite the existing handle with new data on the second and subsequent call */
+ rb_postponed_job_handle_t h = rb_postponed_job_preregister(0, invoke_proc, data);
+ rb_postponed_job_trigger(h);
+ }
+}
+
+static VALUE
+set_gc_hook(VALUE proc, rb_event_flag_t event, const char *tp_str, const char *proc_str)
+{
+ VALUE tpval;
+ ID tp_key = rb_intern(tp_str);
+
+ /* disable previous keys */
+ if (rb_ivar_defined(tp_mBug, tp_key) != 0 &&
+ RTEST(tpval = rb_ivar_get(tp_mBug, tp_key))) {
+ rb_tracepoint_disable(tpval);
+ rb_ivar_set(tp_mBug, tp_key, Qnil);
+ }
+
+ if (RTEST(proc)) {
+ if (!rb_obj_is_proc(proc)) {
+ rb_raise(rb_eTypeError, "trace_func needs to be Proc");
+ }
+
+ rb_ivar_set(tp_mBug, rb_intern(proc_str), proc);
+ tpval = rb_tracepoint_new(0, event, gc_start_end_i, (void *)proc_str);
+ rb_ivar_set(tp_mBug, tp_key, tpval);
+ rb_tracepoint_enable(tpval);
+ }
+
+ return proc;
+}
+
+static VALUE
+set_after_gc_start(VALUE _self, VALUE proc)
+{
+ return set_gc_hook(proc, RUBY_INTERNAL_EVENT_GC_START,
+ "__set_after_gc_start_tpval__", "__set_after_gc_start_proc__");
+}
+
+static VALUE
+start_after_gc_exit(VALUE _self, VALUE proc)
+{
+ return set_gc_hook(proc, RUBY_INTERNAL_EVENT_GC_EXIT,
+ "__set_after_gc_exit_tpval__", "__set_after_gc_exit_proc__");
+}
+
+void
+Init_gc_hook(VALUE module)
+{
+ rb_define_module_function(module, "after_gc_start_hook=", set_after_gc_start, 1);
+ rb_define_module_function(module, "after_gc_exit_hook=", start_after_gc_exit, 1);
+}
diff --git a/ext/-test-/tracepoint/tracepoint.c b/ext/-test-/tracepoint/tracepoint.c
new file mode 100644
index 0000000000..001d9513b2
--- /dev/null
+++ b/ext/-test-/tracepoint/tracepoint.c
@@ -0,0 +1,98 @@
+#include "ruby/ruby.h"
+#include "ruby/debug.h"
+
+VALUE tp_mBug;
+
+struct tracepoint_track {
+ size_t newobj_count;
+ size_t free_count;
+ size_t gc_start_count;
+ size_t gc_end_mark_count;
+ size_t gc_end_sweep_count;
+ size_t objects_count;
+ VALUE objects[10];
+};
+
+#define objects_max (sizeof(((struct tracepoint_track *)NULL)->objects)/sizeof(VALUE))
+
+static void
+tracepoint_track_objspace_events_i(VALUE tpval, void *data)
+{
+ rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval);
+ struct tracepoint_track *track = data;
+
+ switch (rb_tracearg_event_flag(tparg)) {
+ case RUBY_INTERNAL_EVENT_NEWOBJ:
+ {
+ VALUE obj = rb_tracearg_object(tparg);
+ if (track->objects_count < objects_max)
+ track->objects[track->objects_count++] = obj;
+ track->newobj_count++;
+ break;
+ }
+ case RUBY_INTERNAL_EVENT_FREEOBJ:
+ {
+ track->free_count++;
+ break;
+ }
+ case RUBY_INTERNAL_EVENT_GC_START:
+ {
+ track->gc_start_count++;
+ break;
+ }
+ case RUBY_INTERNAL_EVENT_GC_END_MARK:
+ {
+ track->gc_end_mark_count++;
+ break;
+ }
+ case RUBY_INTERNAL_EVENT_GC_END_SWEEP:
+ {
+ track->gc_end_sweep_count++;
+ break;
+ }
+ default:
+ rb_raise(rb_eRuntimeError, "unknown event");
+ }
+}
+
+static VALUE
+tracepoint_track_objspace_events(VALUE self)
+{
+ struct tracepoint_track track = {0, 0, 0, 0, 0,};
+ VALUE tpval = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ | RUBY_INTERNAL_EVENT_FREEOBJ |
+ RUBY_INTERNAL_EVENT_GC_START | RUBY_INTERNAL_EVENT_GC_END_MARK |
+ RUBY_INTERNAL_EVENT_GC_END_SWEEP,
+ tracepoint_track_objspace_events_i, &track);
+ VALUE result = rb_ary_new();
+
+ rb_tracepoint_enable(tpval);
+ rb_ensure(rb_yield, Qundef, rb_tracepoint_disable, tpval);
+
+ rb_ary_push(result, SIZET2NUM(track.newobj_count));
+ rb_ary_push(result, SIZET2NUM(track.free_count));
+ rb_ary_push(result, SIZET2NUM(track.gc_start_count));
+ rb_ary_push(result, SIZET2NUM(track.gc_end_mark_count));
+ rb_ary_push(result, SIZET2NUM(track.gc_end_sweep_count));
+ rb_ary_cat(result, track.objects, track.objects_count);
+
+ return result;
+}
+
+static VALUE
+tracepoint_specify_normal_and_internal_events(VALUE self)
+{
+ VALUE tpval = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ | RUBY_EVENT_CALL, 0, 0);
+ rb_tracepoint_enable(tpval);
+ return Qnil; /* should not be reached */
+}
+
+void Init_gc_hook(VALUE);
+
+void
+Init_tracepoint(void)
+{
+ tp_mBug = rb_define_module("Bug"); // GC root
+ Init_gc_hook(tp_mBug);
+ rb_define_module_function(tp_mBug, "tracepoint_track_objspace_events", tracepoint_track_objspace_events, 0);
+ rb_define_module_function(tp_mBug, "tracepoint_specify_normal_and_internal_events", tracepoint_specify_normal_and_internal_events, 0);
+}
diff --git a/ext/-test-/typeddata/depend b/ext/-test-/typeddata/depend
new file mode 100644
index 0000000000..b9b4915eee
--- /dev/null
+++ b/ext/-test-/typeddata/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+typeddata.o: $(RUBY_EXTCONF_H)
+typeddata.o: $(arch_hdrdir)/ruby/config.h
+typeddata.o: $(hdrdir)/ruby.h
+typeddata.o: $(hdrdir)/ruby/assert.h
+typeddata.o: $(hdrdir)/ruby/backward.h
+typeddata.o: $(hdrdir)/ruby/backward/2/assume.h
+typeddata.o: $(hdrdir)/ruby/backward/2/attributes.h
+typeddata.o: $(hdrdir)/ruby/backward/2/bool.h
+typeddata.o: $(hdrdir)/ruby/backward/2/inttypes.h
+typeddata.o: $(hdrdir)/ruby/backward/2/limits.h
+typeddata.o: $(hdrdir)/ruby/backward/2/long_long.h
+typeddata.o: $(hdrdir)/ruby/backward/2/stdalign.h
+typeddata.o: $(hdrdir)/ruby/backward/2/stdarg.h
+typeddata.o: $(hdrdir)/ruby/defines.h
+typeddata.o: $(hdrdir)/ruby/intern.h
+typeddata.o: $(hdrdir)/ruby/internal/abi.h
+typeddata.o: $(hdrdir)/ruby/internal/anyargs.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+typeddata.o: $(hdrdir)/ruby/internal/assume.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/artificial.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/cold.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/const.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/error.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/format.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/noalias.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/noinline.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/pure.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/restrict.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/warning.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/weakref.h
+typeddata.o: $(hdrdir)/ruby/internal/cast.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_since.h
+typeddata.o: $(hdrdir)/ruby/internal/config.h
+typeddata.o: $(hdrdir)/ruby/internal/constant_p.h
+typeddata.o: $(hdrdir)/ruby/internal/core.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rarray.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rbasic.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rbignum.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rclass.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rdata.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rfile.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rhash.h
+typeddata.o: $(hdrdir)/ruby/internal/core/robject.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rregexp.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rstring.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rstruct.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+typeddata.o: $(hdrdir)/ruby/internal/ctype.h
+typeddata.o: $(hdrdir)/ruby/internal/dllexport.h
+typeddata.o: $(hdrdir)/ruby/internal/dosish.h
+typeddata.o: $(hdrdir)/ruby/internal/error.h
+typeddata.o: $(hdrdir)/ruby/internal/eval.h
+typeddata.o: $(hdrdir)/ruby/internal/event.h
+typeddata.o: $(hdrdir)/ruby/internal/fl_type.h
+typeddata.o: $(hdrdir)/ruby/internal/gc.h
+typeddata.o: $(hdrdir)/ruby/internal/glob.h
+typeddata.o: $(hdrdir)/ruby/internal/globals.h
+typeddata.o: $(hdrdir)/ruby/internal/has/attribute.h
+typeddata.o: $(hdrdir)/ruby/internal/has/builtin.h
+typeddata.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+typeddata.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+typeddata.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+typeddata.o: $(hdrdir)/ruby/internal/has/extension.h
+typeddata.o: $(hdrdir)/ruby/internal/has/feature.h
+typeddata.o: $(hdrdir)/ruby/internal/has/warning.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/array.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/bignum.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/class.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/compar.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/complex.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/cont.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/dir.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/enum.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/error.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/eval.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/file.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/hash.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/io.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/load.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/marshal.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/numeric.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/object.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/parse.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/proc.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/process.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/random.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/range.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/rational.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/re.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/ruby.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/select.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/set.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/signal.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/string.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/struct.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/thread.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/time.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/variable.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/vm.h
+typeddata.o: $(hdrdir)/ruby/internal/interpreter.h
+typeddata.o: $(hdrdir)/ruby/internal/iterator.h
+typeddata.o: $(hdrdir)/ruby/internal/memory.h
+typeddata.o: $(hdrdir)/ruby/internal/method.h
+typeddata.o: $(hdrdir)/ruby/internal/module.h
+typeddata.o: $(hdrdir)/ruby/internal/newobj.h
+typeddata.o: $(hdrdir)/ruby/internal/scan_args.h
+typeddata.o: $(hdrdir)/ruby/internal/special_consts.h
+typeddata.o: $(hdrdir)/ruby/internal/static_assert.h
+typeddata.o: $(hdrdir)/ruby/internal/stdalign.h
+typeddata.o: $(hdrdir)/ruby/internal/stdbool.h
+typeddata.o: $(hdrdir)/ruby/internal/stdckdint.h
+typeddata.o: $(hdrdir)/ruby/internal/symbol.h
+typeddata.o: $(hdrdir)/ruby/internal/value.h
+typeddata.o: $(hdrdir)/ruby/internal/value_type.h
+typeddata.o: $(hdrdir)/ruby/internal/variable.h
+typeddata.o: $(hdrdir)/ruby/internal/warning_push.h
+typeddata.o: $(hdrdir)/ruby/internal/xmalloc.h
+typeddata.o: $(hdrdir)/ruby/missing.h
+typeddata.o: $(hdrdir)/ruby/ruby.h
+typeddata.o: $(hdrdir)/ruby/st.h
+typeddata.o: $(hdrdir)/ruby/subst.h
+typeddata.o: typeddata.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/typeddata/extconf.rb b/ext/-test-/typeddata/extconf.rb
new file mode 100644
index 0000000000..731701111b
--- /dev/null
+++ b/ext/-test-/typeddata/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/typeddata")
diff --git a/ext/-test-/typeddata/typeddata.c b/ext/-test-/typeddata/typeddata.c
new file mode 100644
index 0000000000..cf3178fd18
--- /dev/null
+++ b/ext/-test-/typeddata/typeddata.c
@@ -0,0 +1,44 @@
+#include <ruby.h>
+
+static const rb_data_type_t test_data = {
+ "typed_data",
+ {0, ruby_xfree, 0},
+ NULL, NULL,
+ 0/* deferred free */,
+};
+
+static VALUE
+test_alloc(VALUE klass)
+{
+ char *p;
+ return TypedData_Make_Struct(klass, char, &test_data, p);
+}
+
+static VALUE
+test_check(VALUE self, VALUE obj)
+{
+ rb_check_typeddata(obj, &test_data);
+ return obj;
+}
+
+static VALUE
+test_make(VALUE klass, VALUE num)
+{
+ unsigned long i, n = NUM2UINT(num);
+
+ for (i = 0; i < n; i++) {
+ test_alloc(klass);
+ }
+
+ return Qnil;
+}
+
+void
+Init_typeddata(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "TypedData", rb_cObject);
+ rb_define_alloc_func(klass, test_alloc);
+ rb_define_singleton_method(klass, "check", test_check, 1);
+ rb_define_singleton_method(klass, "make", test_make, 1);
+}
diff --git a/ext/-test-/vm/at_exit.c b/ext/-test-/vm/at_exit.c
new file mode 100644
index 0000000000..efc439b26a
--- /dev/null
+++ b/ext/-test-/vm/at_exit.c
@@ -0,0 +1,44 @@
+#include <ruby/ruby.h>
+#include <ruby/vm.h>
+
+static void
+do_nothing(ruby_vm_t *vm)
+{
+}
+
+static void
+print_begin(ruby_vm_t *vm)
+{
+ printf("begin\n");
+}
+
+static void
+print_end(ruby_vm_t *vm)
+{
+ printf("end\n");
+}
+
+static VALUE
+register_at_exit(VALUE self, VALUE t)
+{
+ switch (t) {
+ case Qtrue:
+ ruby_vm_at_exit(print_begin);
+ break;
+ case Qfalse:
+ ruby_vm_at_exit(print_end);
+ break;
+ default:
+ ruby_vm_at_exit(do_nothing);
+ break;
+ }
+ return self;
+}
+
+void
+Init_at_exit(void)
+{
+ VALUE m = rb_define_module("Bug");
+ VALUE c = rb_define_class_under(m, "VM", rb_cObject);
+ rb_define_singleton_method(c, "register_at_exit", register_at_exit, 1);
+}
diff --git a/ext/-test-/vm/depend b/ext/-test-/vm/depend
new file mode 100644
index 0000000000..9313f2ee36
--- /dev/null
+++ b/ext/-test-/vm/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+at_exit.o: $(RUBY_EXTCONF_H)
+at_exit.o: $(arch_hdrdir)/ruby/config.h
+at_exit.o: $(hdrdir)/ruby/assert.h
+at_exit.o: $(hdrdir)/ruby/backward.h
+at_exit.o: $(hdrdir)/ruby/backward/2/assume.h
+at_exit.o: $(hdrdir)/ruby/backward/2/attributes.h
+at_exit.o: $(hdrdir)/ruby/backward/2/bool.h
+at_exit.o: $(hdrdir)/ruby/backward/2/inttypes.h
+at_exit.o: $(hdrdir)/ruby/backward/2/limits.h
+at_exit.o: $(hdrdir)/ruby/backward/2/long_long.h
+at_exit.o: $(hdrdir)/ruby/backward/2/stdalign.h
+at_exit.o: $(hdrdir)/ruby/backward/2/stdarg.h
+at_exit.o: $(hdrdir)/ruby/defines.h
+at_exit.o: $(hdrdir)/ruby/intern.h
+at_exit.o: $(hdrdir)/ruby/internal/abi.h
+at_exit.o: $(hdrdir)/ruby/internal/anyargs.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+at_exit.o: $(hdrdir)/ruby/internal/assume.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/artificial.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/cold.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/const.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/error.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/format.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/noalias.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/noinline.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/pure.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/restrict.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/warning.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/weakref.h
+at_exit.o: $(hdrdir)/ruby/internal/cast.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_since.h
+at_exit.o: $(hdrdir)/ruby/internal/config.h
+at_exit.o: $(hdrdir)/ruby/internal/constant_p.h
+at_exit.o: $(hdrdir)/ruby/internal/core.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rarray.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rbasic.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rbignum.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rclass.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rdata.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rfile.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rhash.h
+at_exit.o: $(hdrdir)/ruby/internal/core/robject.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rregexp.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rstring.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rstruct.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+at_exit.o: $(hdrdir)/ruby/internal/ctype.h
+at_exit.o: $(hdrdir)/ruby/internal/dllexport.h
+at_exit.o: $(hdrdir)/ruby/internal/dosish.h
+at_exit.o: $(hdrdir)/ruby/internal/error.h
+at_exit.o: $(hdrdir)/ruby/internal/eval.h
+at_exit.o: $(hdrdir)/ruby/internal/event.h
+at_exit.o: $(hdrdir)/ruby/internal/fl_type.h
+at_exit.o: $(hdrdir)/ruby/internal/gc.h
+at_exit.o: $(hdrdir)/ruby/internal/glob.h
+at_exit.o: $(hdrdir)/ruby/internal/globals.h
+at_exit.o: $(hdrdir)/ruby/internal/has/attribute.h
+at_exit.o: $(hdrdir)/ruby/internal/has/builtin.h
+at_exit.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+at_exit.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+at_exit.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+at_exit.o: $(hdrdir)/ruby/internal/has/extension.h
+at_exit.o: $(hdrdir)/ruby/internal/has/feature.h
+at_exit.o: $(hdrdir)/ruby/internal/has/warning.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/array.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/bignum.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/class.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/compar.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/complex.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/cont.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/dir.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/enum.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/error.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/eval.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/file.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/hash.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/io.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/load.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/marshal.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/numeric.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/object.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/parse.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/proc.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/process.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/random.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/range.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/rational.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/re.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/ruby.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/select.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/set.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/signal.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/string.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/struct.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/thread.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/time.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/variable.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/vm.h
+at_exit.o: $(hdrdir)/ruby/internal/interpreter.h
+at_exit.o: $(hdrdir)/ruby/internal/iterator.h
+at_exit.o: $(hdrdir)/ruby/internal/memory.h
+at_exit.o: $(hdrdir)/ruby/internal/method.h
+at_exit.o: $(hdrdir)/ruby/internal/module.h
+at_exit.o: $(hdrdir)/ruby/internal/newobj.h
+at_exit.o: $(hdrdir)/ruby/internal/scan_args.h
+at_exit.o: $(hdrdir)/ruby/internal/special_consts.h
+at_exit.o: $(hdrdir)/ruby/internal/static_assert.h
+at_exit.o: $(hdrdir)/ruby/internal/stdalign.h
+at_exit.o: $(hdrdir)/ruby/internal/stdbool.h
+at_exit.o: $(hdrdir)/ruby/internal/stdckdint.h
+at_exit.o: $(hdrdir)/ruby/internal/symbol.h
+at_exit.o: $(hdrdir)/ruby/internal/value.h
+at_exit.o: $(hdrdir)/ruby/internal/value_type.h
+at_exit.o: $(hdrdir)/ruby/internal/variable.h
+at_exit.o: $(hdrdir)/ruby/internal/warning_push.h
+at_exit.o: $(hdrdir)/ruby/internal/xmalloc.h
+at_exit.o: $(hdrdir)/ruby/missing.h
+at_exit.o: $(hdrdir)/ruby/ruby.h
+at_exit.o: $(hdrdir)/ruby/st.h
+at_exit.o: $(hdrdir)/ruby/subst.h
+at_exit.o: $(hdrdir)/ruby/vm.h
+at_exit.o: at_exit.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/vm/extconf.rb b/ext/-test-/vm/extconf.rb
new file mode 100644
index 0000000000..614ec960d8
--- /dev/null
+++ b/ext/-test-/vm/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/vm/at_exit')
diff --git a/ext/-test-/wait/depend b/ext/-test-/wait/depend
new file mode 100644
index 0000000000..f793d84831
--- /dev/null
+++ b/ext/-test-/wait/depend
@@ -0,0 +1,175 @@
+# AUTOGENERATED DEPENDENCIES START
+wait.o: $(RUBY_EXTCONF_H)
+wait.o: $(arch_hdrdir)/ruby/config.h
+wait.o: $(hdrdir)/ruby/assert.h
+wait.o: $(hdrdir)/ruby/backward.h
+wait.o: $(hdrdir)/ruby/backward/2/assume.h
+wait.o: $(hdrdir)/ruby/backward/2/attributes.h
+wait.o: $(hdrdir)/ruby/backward/2/bool.h
+wait.o: $(hdrdir)/ruby/backward/2/inttypes.h
+wait.o: $(hdrdir)/ruby/backward/2/limits.h
+wait.o: $(hdrdir)/ruby/backward/2/long_long.h
+wait.o: $(hdrdir)/ruby/backward/2/stdalign.h
+wait.o: $(hdrdir)/ruby/backward/2/stdarg.h
+wait.o: $(hdrdir)/ruby/defines.h
+wait.o: $(hdrdir)/ruby/encoding.h
+wait.o: $(hdrdir)/ruby/intern.h
+wait.o: $(hdrdir)/ruby/internal/abi.h
+wait.o: $(hdrdir)/ruby/internal/anyargs.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+wait.o: $(hdrdir)/ruby/internal/assume.h
+wait.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+wait.o: $(hdrdir)/ruby/internal/attr/artificial.h
+wait.o: $(hdrdir)/ruby/internal/attr/cold.h
+wait.o: $(hdrdir)/ruby/internal/attr/const.h
+wait.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+wait.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+wait.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+wait.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+wait.o: $(hdrdir)/ruby/internal/attr/error.h
+wait.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+wait.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+wait.o: $(hdrdir)/ruby/internal/attr/format.h
+wait.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+wait.o: $(hdrdir)/ruby/internal/attr/noalias.h
+wait.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+wait.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+wait.o: $(hdrdir)/ruby/internal/attr/noinline.h
+wait.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+wait.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+wait.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+wait.o: $(hdrdir)/ruby/internal/attr/pure.h
+wait.o: $(hdrdir)/ruby/internal/attr/restrict.h
+wait.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+wait.o: $(hdrdir)/ruby/internal/attr/warning.h
+wait.o: $(hdrdir)/ruby/internal/attr/weakref.h
+wait.o: $(hdrdir)/ruby/internal/cast.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+wait.o: $(hdrdir)/ruby/internal/compiler_since.h
+wait.o: $(hdrdir)/ruby/internal/config.h
+wait.o: $(hdrdir)/ruby/internal/constant_p.h
+wait.o: $(hdrdir)/ruby/internal/core.h
+wait.o: $(hdrdir)/ruby/internal/core/rarray.h
+wait.o: $(hdrdir)/ruby/internal/core/rbasic.h
+wait.o: $(hdrdir)/ruby/internal/core/rbignum.h
+wait.o: $(hdrdir)/ruby/internal/core/rclass.h
+wait.o: $(hdrdir)/ruby/internal/core/rdata.h
+wait.o: $(hdrdir)/ruby/internal/core/rfile.h
+wait.o: $(hdrdir)/ruby/internal/core/rhash.h
+wait.o: $(hdrdir)/ruby/internal/core/robject.h
+wait.o: $(hdrdir)/ruby/internal/core/rregexp.h
+wait.o: $(hdrdir)/ruby/internal/core/rstring.h
+wait.o: $(hdrdir)/ruby/internal/core/rstruct.h
+wait.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+wait.o: $(hdrdir)/ruby/internal/ctype.h
+wait.o: $(hdrdir)/ruby/internal/dllexport.h
+wait.o: $(hdrdir)/ruby/internal/dosish.h
+wait.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+wait.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+wait.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+wait.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+wait.o: $(hdrdir)/ruby/internal/encoding/re.h
+wait.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+wait.o: $(hdrdir)/ruby/internal/encoding/string.h
+wait.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+wait.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+wait.o: $(hdrdir)/ruby/internal/error.h
+wait.o: $(hdrdir)/ruby/internal/eval.h
+wait.o: $(hdrdir)/ruby/internal/event.h
+wait.o: $(hdrdir)/ruby/internal/fl_type.h
+wait.o: $(hdrdir)/ruby/internal/gc.h
+wait.o: $(hdrdir)/ruby/internal/glob.h
+wait.o: $(hdrdir)/ruby/internal/globals.h
+wait.o: $(hdrdir)/ruby/internal/has/attribute.h
+wait.o: $(hdrdir)/ruby/internal/has/builtin.h
+wait.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+wait.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+wait.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+wait.o: $(hdrdir)/ruby/internal/has/extension.h
+wait.o: $(hdrdir)/ruby/internal/has/feature.h
+wait.o: $(hdrdir)/ruby/internal/has/warning.h
+wait.o: $(hdrdir)/ruby/internal/intern/array.h
+wait.o: $(hdrdir)/ruby/internal/intern/bignum.h
+wait.o: $(hdrdir)/ruby/internal/intern/class.h
+wait.o: $(hdrdir)/ruby/internal/intern/compar.h
+wait.o: $(hdrdir)/ruby/internal/intern/complex.h
+wait.o: $(hdrdir)/ruby/internal/intern/cont.h
+wait.o: $(hdrdir)/ruby/internal/intern/dir.h
+wait.o: $(hdrdir)/ruby/internal/intern/enum.h
+wait.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+wait.o: $(hdrdir)/ruby/internal/intern/error.h
+wait.o: $(hdrdir)/ruby/internal/intern/eval.h
+wait.o: $(hdrdir)/ruby/internal/intern/file.h
+wait.o: $(hdrdir)/ruby/internal/intern/hash.h
+wait.o: $(hdrdir)/ruby/internal/intern/io.h
+wait.o: $(hdrdir)/ruby/internal/intern/load.h
+wait.o: $(hdrdir)/ruby/internal/intern/marshal.h
+wait.o: $(hdrdir)/ruby/internal/intern/numeric.h
+wait.o: $(hdrdir)/ruby/internal/intern/object.h
+wait.o: $(hdrdir)/ruby/internal/intern/parse.h
+wait.o: $(hdrdir)/ruby/internal/intern/proc.h
+wait.o: $(hdrdir)/ruby/internal/intern/process.h
+wait.o: $(hdrdir)/ruby/internal/intern/random.h
+wait.o: $(hdrdir)/ruby/internal/intern/range.h
+wait.o: $(hdrdir)/ruby/internal/intern/rational.h
+wait.o: $(hdrdir)/ruby/internal/intern/re.h
+wait.o: $(hdrdir)/ruby/internal/intern/ruby.h
+wait.o: $(hdrdir)/ruby/internal/intern/select.h
+wait.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+wait.o: $(hdrdir)/ruby/internal/intern/set.h
+wait.o: $(hdrdir)/ruby/internal/intern/signal.h
+wait.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+wait.o: $(hdrdir)/ruby/internal/intern/string.h
+wait.o: $(hdrdir)/ruby/internal/intern/struct.h
+wait.o: $(hdrdir)/ruby/internal/intern/thread.h
+wait.o: $(hdrdir)/ruby/internal/intern/time.h
+wait.o: $(hdrdir)/ruby/internal/intern/variable.h
+wait.o: $(hdrdir)/ruby/internal/intern/vm.h
+wait.o: $(hdrdir)/ruby/internal/interpreter.h
+wait.o: $(hdrdir)/ruby/internal/iterator.h
+wait.o: $(hdrdir)/ruby/internal/memory.h
+wait.o: $(hdrdir)/ruby/internal/method.h
+wait.o: $(hdrdir)/ruby/internal/module.h
+wait.o: $(hdrdir)/ruby/internal/newobj.h
+wait.o: $(hdrdir)/ruby/internal/scan_args.h
+wait.o: $(hdrdir)/ruby/internal/special_consts.h
+wait.o: $(hdrdir)/ruby/internal/static_assert.h
+wait.o: $(hdrdir)/ruby/internal/stdalign.h
+wait.o: $(hdrdir)/ruby/internal/stdbool.h
+wait.o: $(hdrdir)/ruby/internal/stdckdint.h
+wait.o: $(hdrdir)/ruby/internal/symbol.h
+wait.o: $(hdrdir)/ruby/internal/value.h
+wait.o: $(hdrdir)/ruby/internal/value_type.h
+wait.o: $(hdrdir)/ruby/internal/variable.h
+wait.o: $(hdrdir)/ruby/internal/warning_push.h
+wait.o: $(hdrdir)/ruby/internal/xmalloc.h
+wait.o: $(hdrdir)/ruby/io.h
+wait.o: $(hdrdir)/ruby/missing.h
+wait.o: $(hdrdir)/ruby/onigmo.h
+wait.o: $(hdrdir)/ruby/oniguruma.h
+wait.o: $(hdrdir)/ruby/ruby.h
+wait.o: $(hdrdir)/ruby/st.h
+wait.o: $(hdrdir)/ruby/subst.h
+wait.o: wait.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/wait/extconf.rb b/ext/-test-/wait/extconf.rb
new file mode 100644
index 0000000000..92787876ad
--- /dev/null
+++ b/ext/-test-/wait/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/wait")
diff --git a/ext/-test-/wait/wait.c b/ext/-test-/wait/wait.c
new file mode 100644
index 0000000000..b73ee35809
--- /dev/null
+++ b/ext/-test-/wait/wait.c
@@ -0,0 +1,39 @@
+#include "ruby/ruby.h"
+#include "ruby/io.h"
+
+static VALUE
+io_wait(VALUE klass, VALUE io, VALUE events, VALUE timeout)
+{
+ return rb_io_wait(io, events, timeout);
+}
+
+static VALUE
+io_maybe_wait(VALUE klass, VALUE error, VALUE io, VALUE events, VALUE timeout)
+{
+ return rb_io_maybe_wait(RB_NUM2INT(error), io, events, timeout);
+}
+
+static VALUE
+io_maybe_wait_readable(VALUE klass, VALUE error, VALUE io, VALUE timeout)
+{
+ return RB_INT2NUM(
+ rb_io_maybe_wait_readable(RB_NUM2INT(error), io, timeout)
+ );
+}
+
+static VALUE
+io_maybe_wait_writable(VALUE klass, VALUE error, VALUE io, VALUE timeout)
+{
+ return RB_INT2NUM(
+ rb_io_maybe_wait_writable(RB_NUM2INT(error), io, timeout)
+ );
+}
+
+void
+Init_wait(void)
+{
+ rb_define_singleton_method(rb_cIO, "io_wait", io_wait, 3);
+ rb_define_singleton_method(rb_cIO, "io_maybe_wait", io_maybe_wait, 4);
+ rb_define_singleton_method(rb_cIO, "io_maybe_wait_readable", io_maybe_wait_readable, 3);
+ rb_define_singleton_method(rb_cIO, "io_maybe_wait_writable", io_maybe_wait_writable, 3);
+}
diff --git a/ext/-test-/win32/console/attribute.c b/ext/-test-/win32/console/attribute.c
new file mode 100644
index 0000000000..b43ba23a5c
--- /dev/null
+++ b/ext/-test-/win32/console/attribute.c
@@ -0,0 +1,69 @@
+#include <ruby.h>
+
+static VALUE rb_cConsoleScreenBufferInfo;
+
+static HANDLE
+io_handle(VALUE io)
+{
+ int fd = NUM2INT(rb_funcallv(io, rb_intern("fileno"), 0, 0));
+ HANDLE h = (HANDLE)rb_w32_get_osfhandle(fd);
+
+ if (h == (HANDLE)-1) rb_raise(rb_eIOError, "invalid io");
+ return h;
+}
+
+static VALUE
+console_info(VALUE klass, VALUE io)
+{
+ HANDLE h = io_handle(io);
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+ if (!GetConsoleScreenBufferInfo(h, &csbi))
+ rb_syserr_fail(rb_w32_map_errno(GetLastError()), "not console");
+ return rb_struct_new(rb_cConsoleScreenBufferInfo,
+ INT2FIX(csbi.dwSize.X),
+ INT2FIX(csbi.dwSize.Y),
+ INT2FIX(csbi.dwCursorPosition.X),
+ INT2FIX(csbi.dwCursorPosition.Y),
+ INT2FIX(csbi.wAttributes));
+}
+
+static VALUE
+console_set_attribute(VALUE klass, VALUE io, VALUE attr)
+{
+ HANDLE h = io_handle(io);
+
+ SetConsoleTextAttribute(h, (WORD)NUM2INT(attr));
+ return Qnil;
+}
+
+#define FOREGROUND_MASK (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
+#define BACKGROUND_MASK (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
+
+void
+Init_attribute(VALUE m)
+{
+ rb_cConsoleScreenBufferInfo = rb_struct_define_under(m, "ConsoleScreenBufferInfo",
+ "size_x", "size_y",
+ "cur_x", "cur_y",
+ "attr", NULL);
+ rb_define_singleton_method(m, "console_info", console_info, 1);
+ rb_define_singleton_method(m, "console_attribute", console_set_attribute, 2);
+
+ rb_define_const(m, "FOREGROUND_MASK", INT2FIX(FOREGROUND_MASK));
+ rb_define_const(m, "FOREGROUND_BLUE", INT2FIX(FOREGROUND_BLUE));
+ rb_define_const(m, "FOREGROUND_GREEN", INT2FIX(FOREGROUND_GREEN));
+ rb_define_const(m, "FOREGROUND_RED", INT2FIX(FOREGROUND_RED));
+ rb_define_const(m, "FOREGROUND_INTENSITY", INT2FIX(FOREGROUND_INTENSITY));
+
+ rb_define_const(m, "BACKGROUND_MASK", INT2FIX(BACKGROUND_MASK));
+ rb_define_const(m, "BACKGROUND_BLUE", INT2FIX(BACKGROUND_BLUE));
+ rb_define_const(m, "BACKGROUND_GREEN", INT2FIX(BACKGROUND_GREEN));
+ rb_define_const(m, "BACKGROUND_RED", INT2FIX(BACKGROUND_RED));
+ rb_define_const(m, "BACKGROUND_INTENSITY", INT2FIX(BACKGROUND_INTENSITY));
+
+#ifndef COMMON_LVB_REVERSE_VIDEO
+#define COMMON_LVB_REVERSE_VIDEO 0x4000
+#endif
+ rb_define_const(m, "REVERSE_VIDEO", INT2FIX(COMMON_LVB_REVERSE_VIDEO));
+}
diff --git a/ext/-test-/win32/console/depend b/ext/-test-/win32/console/depend
new file mode 100644
index 0000000000..f4f65adf9a
--- /dev/null
+++ b/ext/-test-/win32/console/depend
@@ -0,0 +1 @@
+attribute.o: $(ruby_headers) $(hdrdir)/ruby/win32.h
diff --git a/ext/-test-/win32/console/extconf.rb b/ext/-test-/win32/console/extconf.rb
new file mode 100644
index 0000000000..5162172890
--- /dev/null
+++ b/ext/-test-/win32/console/extconf.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: false
+if $mingw or $mswin
+ require_relative "../../auto_ext.rb"
+ auto_ext
+end
diff --git a/ext/-test-/win32/console/init.c b/ext/-test-/win32/console/init.c
new file mode 100644
index 0000000000..f2e0d1c821
--- /dev/null
+++ b/ext/-test-/win32/console/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE m); Init_##n(m);}
+
+void
+Init_console(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE m = rb_define_module_under(mBug, "Win32");
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/win32/dln/depend b/ext/-test-/win32/dln/depend
new file mode 100644
index 0000000000..c3f14db4f7
--- /dev/null
+++ b/ext/-test-/win32/dln/depend
@@ -0,0 +1,9 @@
+$(TARGET_SO): $(DLNTESTLIB)
+
+$(DLNTESTLIB): dlntest.dll
+
+dlntest.dll: libdlntest.o libdlntest.def
+ $(ECHO) linking shared-object $(@F)
+ -$(Q)$(RM) $@
+ -$(Q)$(MAKEDIRS) $(@D)
+ $(Q) $(DLNTEST_LDSHARED)
diff --git a/ext/-test-/win32/dln/dlntest.c b/ext/-test-/win32/dln/dlntest.c
new file mode 100644
index 0000000000..3e6037ac07
--- /dev/null
+++ b/ext/-test-/win32/dln/dlntest.c
@@ -0,0 +1,17 @@
+#include <ruby.h>
+
+extern __declspec(dllimport) void dlntest_ordinal(void);
+
+static VALUE
+dln_dlntest(VALUE self)
+{
+ dlntest_ordinal();
+ return self;
+}
+
+void
+Init_dln(void)
+{
+ VALUE m = rb_define_module_under(rb_define_module("Bug"), "Win32");
+ rb_define_module_function(m, "dlntest", dln_dlntest, 0);
+}
diff --git a/ext/-test-/win32/dln/extconf.rb b/ext/-test-/win32/dln/extconf.rb
new file mode 100644
index 0000000000..bea52cfec3
--- /dev/null
+++ b/ext/-test-/win32/dln/extconf.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: false
+if $mingw or $mswin
+ dlntestlib = "dlntest.#{$LIBEXT}"
+ $LOCAL_LIBS << " #{dlntestlib}"
+ $srcs = ["dlntest.c"]
+ $objs = ["dlntest.o"]
+ testdll = "dlntest.dll"
+ $cleanfiles << testdll
+ $cleanfiles << "dlntest.#{$LIBEXT}"
+ $cleanfiles << "libdlntest.#{$OBJEXT}"
+ config_string('cleanobjs') {|t| $cleanfiles.concat(t.gsub(/\$\*/, 'dlntest').split)}
+
+ create_makefile("-test-/win32/dln") do |m|
+ m << "\n""DLNTESTLIB = #{dlntestlib}\n"
+ if $mingw
+ m << "\n"
+ m << "dlntest.dll: DEFFILE := $(srcdir)/libdlntest.def\n"
+ m << "dlntest.dll: DLDFLAGS += -Wl,--out-implib,$(DLNTESTLIB)\n"
+ end
+ m
+ end
+ m = File.read("Makefile")
+ m.sub!(/(.*)\$\(DLNTEST_LDSHARED\)$/) do
+ pre = $1
+ link_so = LINK_SO.gsub(/^/) {pre}
+ link_so.sub!(/\$\(LOCAL_LIBS\)/, '')
+ link_so.gsub!(/-\$\(arch\)/, '')
+ link_so.gsub!(/:.so=/, ':.dll=')
+ link_so.sub!(/\$\(OBJS\)/, "libdlntest.#{$OBJEXT}")
+ link_so.sub!(/\$\(DEFFILE\)/, "$(srcdir)/libdlntest.def")
+ link_so
+ end and File.binwrite("Makefile", m)
+ FileUtils.rm_f(RbConfig.expand(testdll.dup))
+end
diff --git a/ext/-test-/win32/dln/libdlntest.c b/ext/-test-/win32/dln/libdlntest.c
new file mode 100644
index 0000000000..5923b732c8
--- /dev/null
+++ b/ext/-test-/win32/dln/libdlntest.c
@@ -0,0 +1,4 @@
+void
+dlntest_ordinal(void)
+{
+}
diff --git a/ext/-test-/win32/dln/libdlntest.def b/ext/-test-/win32/dln/libdlntest.def
new file mode 100644
index 0000000000..85bc9c7a55
--- /dev/null
+++ b/ext/-test-/win32/dln/libdlntest.def
@@ -0,0 +1,2 @@
+EXPORTS
+dlntest_ordinal @1 NONAME
diff --git a/ext/-test-/win32/fd_setsize/depend b/ext/-test-/win32/fd_setsize/depend
new file mode 100644
index 0000000000..7d40e8d572
--- /dev/null
+++ b/ext/-test-/win32/fd_setsize/depend
@@ -0,0 +1 @@
+fd_setsize.o: $(ruby_headers) $(hdrdir)/ruby/win32.h
diff --git a/ext/-test-/win32/fd_setsize/extconf.rb b/ext/-test-/win32/fd_setsize/extconf.rb
new file mode 100644
index 0000000000..caa4b85a1b
--- /dev/null
+++ b/ext/-test-/win32/fd_setsize/extconf.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: false
+if $mingw or $mswin
+ create_makefile("-test-/win32/fd_setsize")
+end
diff --git a/ext/-test-/win32/fd_setsize/fd_setsize.c b/ext/-test-/win32/fd_setsize/fd_setsize.c
new file mode 100644
index 0000000000..e29114a0ca
--- /dev/null
+++ b/ext/-test-/win32/fd_setsize/fd_setsize.c
@@ -0,0 +1,55 @@
+#undef FD_SETSIZE
+/* redefine smaller size then default 64 */
+#define FD_SETSIZE 32
+#include <ruby.h>
+
+static VALUE
+test_select(VALUE self)
+{
+ int sd = socket(AF_INET, SOCK_DGRAM, 0);
+ struct timeval zero;
+ fd_set read;
+ fd_set write;
+ fd_set error;
+
+ zero.tv_sec = 0;
+ zero.tv_usec = 0;
+
+ FD_ZERO(&read);
+ FD_ZERO(&write);
+ FD_ZERO(&error);
+
+ FD_SET(sd, &read);
+ FD_SET(sd, &write);
+ FD_SET(sd, &error);
+
+ select(sd+1, &read, &write, &error, &zero);
+
+ return Qtrue;
+}
+
+static VALUE
+test_fdset(VALUE self)
+{
+ int i;
+ fd_set set;
+
+ FD_ZERO(&set);
+
+ for (i = 0; i < FD_SETSIZE * 2; i++) {
+ int sd = socket(AF_INET, SOCK_DGRAM, 0);
+ FD_SET(sd, &set);
+ if (set.fd_count > FD_SETSIZE) {
+ return Qfalse;
+ }
+ }
+ return Qtrue;
+}
+
+void
+Init_fd_setsize(void)
+{
+ VALUE m = rb_define_module_under(rb_define_module("Bug"), "Win32");
+ rb_define_module_function(m, "test_select", test_select, 0);
+ rb_define_module_function(m, "test_fdset", test_fdset, 0);
+}
diff --git a/ext/.cvsignore b/ext/.cvsignore
deleted file mode 100644
index ab2424ff7a..0000000000
--- a/ext/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-extinit.c
-*.log
diff --git a/ext/.document b/ext/.document
index ba8182593e..d75c5c3d35 100644
--- a/ext/.document
+++ b/ext/.document
@@ -1,11 +1,81 @@
# Add files to this as they become documented
-enumerator/enumerator.c
-iconv/iconv.c
-nkf/lib/kconv.rb
-nkf/nkf.c
-socket/socket.c
+cgi/escape/escape.c
+continuation/continuation.c
+coverage/coverage.c
+coverage/lib
+date/date_core.c
+date/date_parse.c
+date/date_strftime.c
+date/date_strptime.c
+date/lib
+digest/bubblebabble/bubblebabble.c
+digest/digest.c
+digest/lib
+digest/md5/md5init.c
+digest/rmd160/rmd160init.c
+digest/sha1/sha1init.c
+digest/sha2/sha2init.c
+digest/sha2/lib
+etc/etc.c
+fcntl/fcntl.c
+io/console/
+io/nonblock/nonblock.c
+io/wait/wait.c
+json/generator/generator.c
+json/lib
+json/parser/parser.c
+objspace/objspace.c
+objspace/objspace_dump.c
+objspace/object_tracing.c
+objspace/lib
+openssl/lib
+openssl/ossl.c
+openssl/ossl_asn1.c
+openssl/ossl_bio.c
+openssl/ossl_bn.c
+openssl/ossl_cipher.c
+openssl/ossl_config.c
+openssl/ossl_digest.c
+openssl/ossl_engine.c
+openssl/ossl_hmac.c
+openssl/ossl_kdf.c
+openssl/ossl_ns_spki.c
+openssl/ossl_ocsp.c
+openssl/ossl_pkcs12.c
+openssl/ossl_pkcs7.c
+openssl/ossl_pkey.c
+openssl/ossl_pkey_dh.c
+openssl/ossl_pkey_dsa.c
+openssl/ossl_pkey_ec.c
+openssl/ossl_pkey_rsa.c
+openssl/ossl_rand.c
+openssl/ossl_ssl.c
+openssl/ossl_ssl_session.c
+openssl/ossl_ts.c
+openssl/ossl_x509.c
+openssl/ossl_x509attr.c
+openssl/ossl_x509cert.c
+openssl/ossl_x509crl.c
+openssl/ossl_x509ext.c
+openssl/ossl_x509name.c
+openssl/ossl_x509req.c
+openssl/ossl_x509revoked.c
+openssl/ossl_x509store.c
+psych/lib
+psych/psych.c
+psych/psych_emitter.c
+psych/psych_parser.c
+psych/psych_to_ruby.c
+psych/psych_yaml_tree.c
+pty/lib
+pty/pty.c
+rbconfig/sizeof/*.c
+ripper/lib
+socket
stringio/stringio.c
+strscan/lib
strscan/strscan.c
-win32ole
+win32/lib
+win32/resolv/*.c
zlib/zlib.c
diff --git a/ext/Setup b/ext/Setup
index 7b214abde3..5cd4e95e27 100644
--- a/ext/Setup
+++ b/ext/Setup
@@ -1,33 +1,34 @@
#option nodynamic
-#Win32API
-#bigdecimal
-#curses
-#dbm
+#cgi/escape
+#continuation
+#coverage
+#date
#digest
+#digest/bubblebabble
#digest/md5
#digest/rmd160
#digest/sha1
#digest/sha2
-#dl
-#enumerator
+#erb/escape
#etc
#fcntl
-#gdbm
-#iconv
+#io/console
+#io/nonblock
#io/wait
-#nkf
-#pty
+#json
+#json/generator
+#json/parser
+#objspace
#openssl
-#racc/cparse
-#readline
-#sdbm
+#psych
+#pty
+#rbconfig/sizeof
+#ripper
+#rubyvm
#socket
#stringio
#strscan
-#syck
-#syslog
-#tcltklib
-#tk
-#win32ole
+#win32
+#win32/resolv
#zlib
diff --git a/ext/Setup.atheos b/ext/Setup.atheos
index 9b1bdecb95..73c8d5d5a8 100644
--- a/ext/Setup.atheos
+++ b/ext/Setup.atheos
@@ -1,33 +1,23 @@
option nodynamic
-#Win32API
-bigdecimal
-curses
-dbm
-digest
-digest/md5
-digest/rmd160
-digest/sha1
-digest/sha2
-dl
-enumerator
+cgi/escape
+continuation
+coverage
+date
+digest/*
+erb/escape
etc
fcntl
-gdbm
-iconv
-io/wait
-nkf
-pty
+io/*
+json
+json/*
+objspace
#openssl
-racc/parse
-readline
-sdbm
+pty
+rbconfig/sizeof
+ripper
socket
stringio
strscan
-syck
syslog
-#tcltklib
-#tk
-#win32ole
zlib
diff --git a/ext/Setup.dj b/ext/Setup.dj
deleted file mode 100644
index f2ed3a4f16..0000000000
--- a/ext/Setup.dj
+++ /dev/null
@@ -1,33 +0,0 @@
-option nodynamic
-
-#Win32API
-bigdecimal
-curses
-dbm
-digest
-digest/md5
-digest/rmd160
-digest/sha1
-digest/sha2
-#dl
-etc
-enumerator
-fcntl
-gdbm
-#iconv
-#io/wait
-nkf
-#pty
-#openssl
-racc/cparse
-readline
-sdbm
-#socket
-stringio
-strscan
-syck
-#syslog
-#tcltklib
-#tk
-#win32ole
-zlib
diff --git a/ext/Setup.emx b/ext/Setup.emx
deleted file mode 100644
index 7ea04543c5..0000000000
--- a/ext/Setup.emx
+++ /dev/null
@@ -1,33 +0,0 @@
-option nodynamic
-
-#Win32API
-bigdecimal
-curses
-#dbm
-digest
-digest/md5
-digest/rmd160
-digest/sha1
-digest/sha2
-#dl
-enumerator
-etc
-fcntl
-#gdbm
-#iconv
-#io/wait
-nkf
-#pty
-#openssl
-racc/cparse
-#readline
-#sdbm
-socket
-stringio
-strscan
-#syck
-#syslog
-#tcltklib
-#tk
-#win32ole
-#zlib
diff --git a/ext/Setup.nt b/ext/Setup.nt
index 7a330f801a..a9e87249d3 100644
--- a/ext/Setup.nt
+++ b/ext/Setup.nt
@@ -1,33 +1,23 @@
+#option platform cygwin|mingw|mswin
#option nodynamic
-Win32API
-bigdecimal
-#curses
-#dbm
-digest
-digest/md5
-digest/rmd160
-digest/sha1
-digest/sha2
-dl
-enumerator
+cgi/escape
+continuation
+coverage
+date
+digest/*
+erb/escape
etc
fcntl
-#gdbm
-#iconv
-#io/wait
-nkf
-#pty
+io/*
+json
+json/*
+objspace
#openssl
-racc/cparse
-#readline
-sdbm
+rbconfig/sizeof
+#ripper
socket
stringio
strscan
-syck
#syslog
-#tcltklib
-#tk
-win32ole
#zlib
diff --git a/ext/Setup.x68 b/ext/Setup.x68
deleted file mode 100644
index 9b9563d941..0000000000
--- a/ext/Setup.x68
+++ /dev/null
@@ -1,33 +0,0 @@
-option nodynamic
-
-#Win32API
-bigdecimal
-#curses
-dbm
-digest
-digest/md5
-digest/rmd160
-digest/sha1
-digest/sha2
-#dl
-#etc
-enumerator
-fcntl
-#gdbm
-#iconv
-#io/wait
-nkf
-#pty
-#openssl
-racc/cparse
-#readline
-#sdbm
-#socket
-stringio
-strscan
-#syck
-#syslog
-#tcltklib
-#tk
-#win32ole
-#zlib
diff --git a/ext/Win32API/.cvsignore b/ext/Win32API/.cvsignore
deleted file mode 100644
index 90c83ed9b1..0000000000
--- a/ext/Win32API/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-*.log
-*.def
diff --git a/ext/Win32API/Win32API.c b/ext/Win32API/Win32API.c
deleted file mode 100644
index 96ce8c6636..0000000000
--- a/ext/Win32API/Win32API.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- Win32API - Ruby Win32 API Import Facility
-*/
-
-#if !defined _MSC_VER && !defined _WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <stdio.h>
-#endif
-
-#define _T_VOID 0
-#define _T_NUMBER 1
-#define _T_POINTER 2
-#define _T_INTEGER 3
-
-#include "ruby.h"
-
-typedef struct {
- HANDLE dll;
- HANDLE proc;
- VALUE dllname;
- VALUE import;
- VALUE export;
-} Win32API;
-
-static void
-Win32API_FreeLibrary(hdll)
- HINSTANCE hdll;
-{
- FreeLibrary(hdll);
-}
-
-static VALUE
-Win32API_initialize(self, dllname, proc, import, export)
- VALUE self;
- VALUE dllname;
- VALUE proc;
- VALUE import;
- VALUE export;
-{
- HANDLE hproc;
- HINSTANCE hdll;
- VALUE str;
- VALUE a_import;
- VALUE *ptr;
- char *s;
- int i;
- int len;
- int ex = _T_VOID;
-
- SafeStringValue(dllname);
- SafeStringValue(proc);
- hdll = LoadLibrary(RSTRING(dllname)->ptr);
- if (!hdll)
- rb_raise(rb_eRuntimeError, "LoadLibrary: %s\n", RSTRING(dllname)->ptr);
- rb_iv_set(self, "__hdll__", Data_Wrap_Struct(rb_cData, 0, Win32API_FreeLibrary, (void*)hdll));
- hproc = (HANDLE)GetProcAddress(hdll, RSTRING(proc)->ptr);
- if (!hproc) {
- str = rb_str_new3(proc);
- str = rb_str_cat(str, "A", 1);
- hproc = (HANDLE)GetProcAddress(hdll, RSTRING(str)->ptr);
- if (!hproc)
- rb_raise(rb_eRuntimeError, "GetProcAddress: %s or %s\n",
- RSTRING(proc)->ptr, RSTRING(str)->ptr);
- }
- rb_iv_set(self, "__dll__", UINT2NUM((unsigned long)hdll));
- rb_iv_set(self, "__dllname__", dllname);
- rb_iv_set(self, "__proc__", UINT2NUM((unsigned long)hproc));
-
- a_import = rb_ary_new();
- switch (TYPE(import)) {
- case T_NIL:
- break;
- case T_ARRAY:
- ptr = RARRAY(import)->ptr;
- for (i = 0, len = RARRAY(import)->len; i < len; i++) {
- SafeStringValue(ptr[i]);
- switch (*(char *)RSTRING(ptr[i])->ptr) {
- case 'N': case 'n': case 'L': case 'l':
- rb_ary_push(a_import, INT2FIX(_T_NUMBER));
- break;
- case 'P': case 'p':
- rb_ary_push(a_import, INT2FIX(_T_POINTER));
- break;
- case 'I': case 'i':
- rb_ary_push(a_import, INT2FIX(_T_INTEGER));
- break;
- }
- }
- break;
- default:
- SafeStringValue(import);
- s = RSTRING(import)->ptr;
- for (i = 0, len = RSTRING(import)->len; i < len; i++) {
- switch (*s++) {
- case 'N': case 'n': case 'L': case 'l':
- rb_ary_push(a_import, INT2FIX(_T_NUMBER));
- break;
- case 'P': case 'p':
- rb_ary_push(a_import, INT2FIX(_T_POINTER));
- break;
- case 'I': case 'i':
- rb_ary_push(a_import, INT2FIX(_T_INTEGER));
- break;
- }
- }
- break;
- }
-
- if (16 < RARRAY(a_import)->len) {
- rb_raise(rb_eRuntimeError, "too many parameters: %d\n", RARRAY(a_import)->len);
- }
-
- rb_iv_set(self, "__import__", a_import);
-
- if (NIL_P(export)) {
- ex = _T_VOID;
- } else {
- SafeStringValue(export);
- switch (*RSTRING(export)->ptr) {
- case 'V': case 'v':
- ex = _T_VOID;
- break;
- case 'N': case 'n': case 'L': case 'l':
- ex = _T_NUMBER;
- break;
- case 'P': case 'p':
- ex = _T_POINTER;
- break;
- case 'I': case 'i':
- ex = _T_INTEGER;
- break;
- }
- }
- rb_iv_set(self, "__export__", INT2FIX(ex));
-
- return Qnil;
-}
-
-#ifdef _MSC_VER
-#pragma optimize("g", off)
-#endif
-static VALUE
-Win32API_Call(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE args;
- unsigned long ret;
- int i;
- struct {
- unsigned long params[16];
- } param;
-#define params param.params
-
- VALUE obj_proc = rb_iv_get(obj, "__proc__");
- VALUE obj_import = rb_iv_get(obj, "__import__");
- VALUE obj_export = rb_iv_get(obj, "__export__");
- FARPROC ApiFunction = (FARPROC)NUM2ULONG(obj_proc);
- int items = rb_scan_args(argc, argv, "0*", &args);
- int nimport = RARRAY(obj_import)->len;
-
-
- if (items != nimport)
- rb_raise(rb_eRuntimeError, "wrong number of parameters: expected %d, got %d",
- nimport, items);
-
- for (i = 0; i < nimport; i++) {
- unsigned long lParam = 0;
- switch (FIX2INT(rb_ary_entry(obj_import, i))) {
- VALUE str;
- case _T_NUMBER:
- case _T_INTEGER:
- default:
- lParam = NUM2ULONG(rb_ary_entry(args, i));
- break;
- case _T_POINTER:
- str = rb_ary_entry(args, i);
- if (NIL_P(str)) {
- lParam = 0;
- } else if (FIXNUM_P(str)) {
- lParam = NUM2ULONG(str);
- } else {
- StringValue(str);
- rb_str_modify(str);
- lParam = (unsigned long)StringValuePtr(str);
- }
- break;
- }
- params[i] = lParam;
- }
-
- ret = ApiFunction(param);
-
- switch (FIX2INT(obj_export)) {
- case _T_NUMBER:
- case _T_INTEGER:
- return INT2NUM(ret);
- case _T_POINTER:
- return rb_str_new2((char *)ret);
- case _T_VOID:
- default:
- return INT2NUM(0);
- }
-}
-
-void
-Init_Win32API()
-{
- VALUE cWin32API = rb_define_class("Win32API", rb_cObject);
- rb_define_method(cWin32API, "initialize", Win32API_initialize, 4);
- rb_define_method(cWin32API, "call", Win32API_Call, -1);
- rb_define_alias(cWin32API, "Call", "call");
-}
diff --git a/ext/Win32API/depend b/ext/Win32API/depend
deleted file mode 100644
index b224bb66c9..0000000000
--- a/ext/Win32API/depend
+++ /dev/null
@@ -1 +0,0 @@
-Win32API.o : Win32API.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/Win32API/extconf.rb b/ext/Win32API/extconf.rb
deleted file mode 100644
index 865788556f..0000000000
--- a/ext/Win32API/extconf.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require 'mkmf'
-
-dir_config("win32")
-if have_header("windows.h") and have_library("kernel32")
- create_makefile("Win32API")
-end
diff --git a/ext/Win32API/getch.rb b/ext/Win32API/getch.rb
deleted file mode 100644
index c015bbe9bc..0000000000
--- a/ext/Win32API/getch.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'Win32API'
-
-getch = Win32API.new("crtdll", "_getch", [], 'L')
-
-puts getch.Call.chr
diff --git a/ext/Win32API/lib/win32/registry.rb b/ext/Win32API/lib/win32/registry.rb
deleted file mode 100644
index 2671551a33..0000000000
--- a/ext/Win32API/lib/win32/registry.rb
+++ /dev/null
@@ -1,831 +0,0 @@
-=begin
-= Win32 Registry I/F
-win32/registry is registry accessor library for Win32 platform.
-It uses Win32API to call Win32 Registry APIs.
-
-== example
- Win32::Registry::HKEY_CURRENT_USER.open('SOFTWARE\foo') do |reg|
- value = reg['foo'] # read a value
- value = reg['foo', Win32::Registry::REG_SZ] # read a value with type
- type, value = reg.read('foo') # read a value
- reg['foo'] = 'bar' # write a value
- reg['foo', Win32::Registry::REG_SZ] = 'bar' # write a value with type
- reg.write('foo', Win32::Registry::REG_SZ, 'bar') # write a value
-
- reg.each_value { |name, type, data| ... } # Enumerate values
- reg.each_key { |key, wtime| ... } # Enumerate subkeys
-
- reg.delete_value(name) # Delete a value
- reg.delete_key(name) # Delete a subkey
- reg.delete_key(name, true) # Delete a subkey recursively
- end
-
-= Reference
-
-== Win32::Registry class
-
-=== including modules
-
-* Enumerable
-* Registry::Constants
-
-=== class methods
---- Registry.open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED)
---- Registry.open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) { |reg| ... }
- Open the registry key ((|subkey|)) under ((|key|)).
- ((|key|)) is Win32::Registry object of parent key.
- You can use predefined key HKEY_* (see ((<constants>)))
-
- ((|desired|)) and ((|opt|)) is access mask and key option.
- For detail, see ((<MSDN Library|URL:http://msdn.microsoft.com/library/en-us/sysinfo/base/regopenkeyex.asp>)).
-
- If block is given, the key is closed automatically.
-
---- Registry.create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED)
---- Registry.create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) { |reg| ... }
- Create or open the registry key ((|subkey|)) under ((|key|)).
- You can use predefined key HKEY_* (see ((<constants>)))
-
- If subkey is already exists, key is opened and Registry#((<created?>))
- method will return false.
-
- If block is given, the key is closed automatically.
-
---- Registry.expand_environ(str)
- Replace (({%\w+%})) into the environment value of ((|str|)).
- This method is used for REG_EXPAND_SZ.
-
- For detail, see ((<ExpandEnvironmentStrings|URL:http://msdn.microsoft.com/library/en-us/sysinfo/base/expandenvironmentstrings.asp>)) Win32 API.
-
---- Registry.type2name(type)
- Convert registry type value to readable string.
-
---- Registry.wtime2time(wtime)
- Convert 64-bit FILETIME integer into Time object.
-
---- Registry.time2wtime(time)
- Convert Time object or Integer object into 64-bit FILETIME.
-
-=== instance methods
---- open(subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED)
- Same as (({Win32::((<Registry.open>))(self, subkey, desired, opt)}))
-
---- create(subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED)
- Same as (({Win32::((<Registry.create>))(self, subkey, desired, opt)}))
-
---- close
- Close key.
-
- After closed, most method raises error.
-
---- read(name, *rtype)
- Read a registry value named ((|name|)) and return array of
- [ ((|type|)), ((|data|)) ].
- When name is nil, the `default' value is read.
-
- ((|type|)) is value type. (see ((<Win32::Registry::Constants module>)))
- ((|data|)) is value data, its class is:
- :REG_SZ, REG_EXPAND_SZ
- String
- :REG_MULTI_SZ
- Array of String
- :REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD
- Integer
- :REG_BINARY
- String (contains binary data)
-
- When ((|rtype|)) is specified, the value type must be included by
- ((|rtype|)) array, or TypeError is raised.
-
---- self[name, *rtype]
- Read a registry value named ((|name|)) and return its value data.
- The class of value is same as ((<read>)) method returns.
-
- If the value type is REG_EXPAND_SZ, returns value data whose environment
- variables are replaced.
- If the value type is neither REG_SZ, REG_MULTI_SZ, REG_DWORD,
- REG_DWORD_BIG_ENDIAN, nor REG_QWORD, TypeError is raised.
-
- The meaning of ((|rtype|)) is same as ((<read>)) method.
-
---- read_s(name)
---- read_i(name)
---- read_bin(name)
- Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin)
- registry value named ((|name|)).
-
- If the values type does not match, TypeError is raised.
-
---- read_s_expand(name)
- Read a REG_SZ or REG_EXPAND_SZ registry value named ((|name|)).
-
- If the value type is REG_EXPAND_SZ, environment variables are replaced.
- Unless the value type is REG_SZ or REG_EXPAND_SZ, TypeError is raised.
-
---- write(name, type, data)
- Write ((|data|)) to a registry value named ((|name|)).
- When name is nil, write to the `default' value.
-
- ((|type|)) is type value. (see ((<Registry::Constants module>)))
- Class of ((|data|)) must be same as which ((<read>))
- method returns.
-
---- self[name, wtype = nil] = value
- Write ((|value|)) to a registry value named ((|name|)).
-
- If ((|wtype|)) is specified, the value type is it.
- Otherwise, the value type is depend on class of ((|value|)):
- :Integer
- REG_DWORD
- :String
- REG_SZ
- :Array
- REG_MULTI_SZ
-
---- write_s(name, value)
---- write_i(name, value)
---- write_bin(name, value)
- Write ((|value|)) to a registry value named ((|name|)).
-
- The value type is REG_SZ(write_s), REG_DWORD(write_i), or
- REG_BINARY(write_bin).
-
---- each { |name, type, value| ... }
---- each_value { |name, type, value| ... }
- Enumerate values.
-
---- each_key { |subkey, wtime| ... }
- Enumerate subkeys.
-
- ((|subkey|)) is String which contains name of subkey.
- ((|wtime|)) is last write time as FILETIME (64-bit integer).
- (see ((<Registry.wtime2time>)))
-
---- delete(name)
---- delete_value(name)
- Delete a registry value named ((|name|)).
- We can not delete the `default' value.
-
---- delete_key(name, recursive = false)
- Delete a subkey named ((|name|)) and all its values.
-
- If ((|recursive|)) is false, the subkey must not have subkeys.
- Otherwise, this method deletes all subkeys and values recursively.
-
---- flush
- Write all the attributes into the registry file.
-
---- created?
- Returns if key is created ((*newly*)).
- (see ((<Registry.create>)))
-
---- open?
- Returns if key is not closed.
-
---- hkey
- Returns key handle value.
-
---- parent
- Win32::Registry object of parent key, or nil if predefeined key.
-
---- keyname
- Same as ((|subkey|)) value of ((<Registry.open>)) or
- ((<Registry.create>)) method.
-
---- disposition
- Disposition value (REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY).
-
---- name
---- to_s
- Full path of key such as (({'HKEY_CURRENT_USER\SOFTWARE\foo\bar'})).
-
---- info
- Returns key information as Array of:
- :num_keys
- The number of subkeys.
- :max_key_length
- Maximum length of name of subkeys.
- :num_values
- The number of values.
- :max_value_name_length
- Maximum length of name of values.
- :max_value_length
- Maximum length of value of values.
- :descriptor_length
- Length of security descriptor.
- :wtime
- Last write time as FILETIME(64-bit integer)
-
- For detail, see ((<RegQueryInfoKey|URL:http://msdn.microsoft.com/library/en-us/sysinfo/base/regqueryinfokey.asp>)) Win32 API.
-
---- num_keys
---- max_key_length
---- num_values
---- max_value_name_length
---- max_value_length
---- descriptor_length
---- wtime
- Returns an item of key information.
-
-=== constants
---- HKEY_CLASSES_ROOT
---- HKEY_CURRENT_USER
---- HKEY_LOCAL_MACHINE
---- HKEY_PERFORMANCE_DATA
---- HKEY_CURRENT_CONFIG
---- HKEY_DYN_DATA
- Win32::Registry object whose key is predefined key.
- For detail, see ((<MSDN Library|URL:http://msdn.microsoft.com/library/en-us/sysinfo/base/predefined_keys.asp>)).
-
-== Win32::Registry::Constants module
-
-For detail, see ((<MSDN Library|URL:http://msdn.microsoft.com/library/en-us/sysinfo/base/registry.asp>)).
-
---- HKEY_*
- Predefined key ((*handle*)).
- These are Integer, not Win32::Registry.
-
---- REG_*
- Registry value type.
-
---- KEY_*
- Security access mask.
-
---- KEY_OPTIONS_*
- Key options.
-
---- REG_CREATED_NEW_KEY
---- REG_OPENED_EXISTING_KEY
- If the key is created newly or opened existing key.
- See also Registry#((<disposition>)) method.
-
-=end
-
-require 'Win32API'
-
-module Win32
- class Registry
- module Constants
- HKEY_CLASSES_ROOT = 0x80000000
- HKEY_CURRENT_USER = 0x80000001
- HKEY_LOCAL_MACHINE = 0x80000002
- HKEY_USERS = 0x80000003
- HKEY_PERFORMANCE_DATA = 0x80000004
- HKEY_PERFORMANCE_TEXT = 0x80000050
- HKEY_PERFORMANCE_NLSTEXT = 0x80000060
- HKEY_CURRENT_CONFIG = 0x80000005
- HKEY_DYN_DATA = 0x80000006
-
- REG_NONE = 0
- REG_SZ = 1
- REG_EXPAND_SZ = 2
- REG_BINARY = 3
- REG_DWORD = 4
- REG_DWORD_LITTLE_ENDIAN = 4
- REG_DWORD_BIG_ENDIAN = 5
- REG_LINK = 6
- REG_MULTI_SZ = 7
- REG_RESOURCE_LIST = 8
- REG_FULL_RESOURCE_DESCRIPTOR = 9
- REG_RESOURCE_REQUIREMENTS_LIST = 10
- REG_QWORD = 11
- REG_QWORD_LITTLE_ENDIAN = 11
-
- STANDARD_RIGHTS_READ = 0x00020000
- STANDARD_RIGHTS_WRITE = 0x00020000
- KEY_QUERY_VALUE = 0x0001
- KEY_SET_VALUE = 0x0002
- KEY_CREATE_SUB_KEY = 0x0004
- KEY_ENUMERATE_SUB_KEYS = 0x0008
- KEY_NOTIFY = 0x0010
- KEY_CREATE_LINK = 0x0020
- KEY_READ = STANDARD_RIGHTS_READ |
- KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY
- KEY_WRITE = STANDARD_RIGHTS_WRITE |
- KEY_SET_VALUE | KEY_CREATE_SUB_KEY
- KEY_EXECUTE = KEY_READ
- KEY_ALL_ACCESS = KEY_READ | KEY_WRITE | KEY_CREATE_LINK
-
- REG_OPTION_RESERVED = 0x0000
- REG_OPTION_NON_VOLATILE = 0x0000
- REG_OPTION_VOLATILE = 0x0001
- REG_OPTION_CREATE_LINK = 0x0002
- REG_OPTION_BACKUP_RESTORE = 0x0004
- REG_OPTION_OPEN_LINK = 0x0008
- REG_LEGAL_OPTION = REG_OPTION_RESERVED |
- REG_OPTION_NON_VOLATILE | REG_OPTION_CREATE_LINK |
- REG_OPTION_BACKUP_RESTORE | REG_OPTION_OPEN_LINK
-
- REG_CREATED_NEW_KEY = 1
- REG_OPENED_EXISTING_KEY = 2
-
- REG_WHOLE_HIVE_VOLATILE = 0x0001
- REG_REFRESH_HIVE = 0x0002
- REG_NO_LAZY_FLUSH = 0x0004
- REG_FORCE_RESTORE = 0x0008
-
- MAX_KEY_LENGTH = 514
- MAX_VALUE_LENGTH = 32768
- end
- include Constants
- include Enumerable
-
- #
- # Error
- #
- class Error < ::StandardError
- FormatMessageA = Win32API.new('kernel32.dll', 'FormatMessageA', 'LPLLPLP', 'L')
- def initialize(code)
- @code = code
- msg = "\0" * 1024
- len = FormatMessageA.call(0x1200, 0, code, 0, msg, 1024, 0)
- super msg[0, len].tr("\r", '').chomp
- end
- attr_reader :code
- end
-
- #
- # Predefined Keys
- #
- class PredefinedKey < Registry
- def initialize(hkey, keyname)
- @hkey = hkey
- @parent = nil
- @keyname = keyname
- @disposition = REG_OPENED_EXISTING_KEY
- end
-
- # Predefined keys cannot be closed
- def close
- raise Error.new(5) ## ERROR_ACCESS_DENIED
- end
-
- # Fake class for Registry#open, Registry#create
- def class
- Registry
- end
-
- # Make all
- Constants.constants.grep(/^HKEY_/) do |c|
- Registry.const_set c, new(Constants.const_get(c), c)
- end
- end
-
- #
- # Win32 APIs
- #
- module API
- [
- %w/RegOpenKeyExA LPLLP L/,
- %w/RegCreateKeyExA LPLLLLPPP L/,
- %w/RegEnumValueA LLPPPPPP L/,
- %w/RegEnumKeyExA LLPPLLLP L/,
- %w/RegQueryValueExA LPLPPP L/,
- %w/RegSetValueExA LPLLPL L/,
- %w/RegDeleteValue LP L/,
- %w/RegDeleteKey LP L/,
- %w/RegFlushKey L L/,
- %w/RegCloseKey L L/,
- %w/RegQueryInfoKey LPPPPPPPPPPP L/,
- ].each do |fn|
- const_set fn[0].intern, Win32API.new('advapi32.dll', *fn)
- end
-
- module_function
-
- def check(result)
- raise Error, result, caller(2) if result != 0
- end
-
- def packdw(dw)
- [dw].pack('V')
- end
-
- def unpackdw(dw)
- dw += [0].pack('V')
- dw.unpack('V')[0]
- end
-
- def packqw(qw)
- [ qw & 0xFFFFFFFF, qw >> 32 ].pack('VV')
- end
-
- def unpackqw(qw)
- qw = qw.unpack('VV')
- (qw[1] << 32) | qw[0]
- end
-
- def OpenKey(hkey, name, opt, desired)
- result = packdw(0)
- check RegOpenKeyExA.call(hkey, name, opt, desired, result)
- unpackdw(result)
- end
-
- def CreateKey(hkey, name, opt, desired)
- result = packdw(0)
- disp = packdw(0)
- check RegCreateKeyExA.call(hkey, name, 0, 0, opt, desired,
- 0, result, disp)
- [ unpackdw(result), unpackdw(disp) ]
- end
-
- def EnumValue(hkey, index)
- name = ' ' * Constants::MAX_KEY_LENGTH
- size = packdw(Constants::MAX_KEY_LENGTH)
- check RegEnumValueA.call(hkey, index, name, size, 0, 0, 0, 0)
- name[0, unpackdw(size)]
- end
-
- def EnumKey(hkey, index)
- name = ' ' * Constants::MAX_KEY_LENGTH
- size = packdw(Constants::MAX_KEY_LENGTH)
- wtime = ' ' * 8
- check RegEnumKeyExA.call(hkey, index, name, size, 0, 0, 0, wtime)
- [ name[0, unpackdw(size)], unpackqw(wtime) ]
- end
-
- def QueryValue(hkey, name)
- type = packdw(0)
- size = packdw(0)
- check RegQueryValueExA.call(hkey, name, 0, type, 0, size)
- data = ' ' * unpackdw(size)
- check RegQueryValueExA.call(hkey, name, 0, type, data, size)
- [ unpackdw(type), data[0, unpackdw(size)] ]
- end
-
- def SetValue(hkey, name, type, data, size)
- check RegSetValueExA.call(hkey, name, 0, type, data, size)
- end
-
- def DeleteValue(hkey, name)
- check RegDeleteValue.call(hkey, name)
- end
-
- def DeleteKey(hkey, name)
- check RegDeleteKey.call(hkey, name)
- end
-
- def FlushKey(hkey)
- check RegFlushKey.call(hkey)
- end
-
- def CloseKey(hkey)
- check RegCloseKey.call(hkey)
- end
-
- def QueryInfoKey(hkey)
- subkeys = packdw(0)
- maxsubkeylen = packdw(0)
- values = packdw(0)
- maxvaluenamelen = packdw(0)
- maxvaluelen = packdw(0)
- secdescs = packdw(0)
- wtime = ' ' * 8
- check RegQueryInfoKey.call(hkey, 0, 0, 0, subkeys, maxsubkeylen, 0,
- values, maxvaluenamelen, maxvaluelen, secdescs, wtime)
- [ unpackdw(subkeys), unpackdw(maxsubkeylen), unpackdw(values),
- unpackdw(maxvaluenamelen), unpackdw(maxvaluelen),
- unpackdw(secdescs), unpackqw(wtime) ]
- end
- end
-
- #
- # utility functions
- #
- def self.expand_environ(str)
- str.gsub(/%([^%]+)%/) { ENV[$1] || $& }
- end
-
- @@type2name = { }
- %w[
- REG_NONE REG_SZ REG_EXPAND_SZ REG_BINARY REG_DWORD
- REG_DWORD_BIG_ENDIAN REG_LINK REG_MULTI_SZ
- REG_RESOURCE_LIST REG_FULL_RESOURCE_DESCRIPTOR
- REG_RESOURCE_REQUIREMENTS_LIST REG_QWORD
- ].each do |type|
- @@type2name[Constants.const_get(type)] = type
- end
-
- def self.type2name(type)
- @@type2name[type] || type.to_s
- end
-
- def self.wtime2time(wtime)
- Time.at((wtime - 116444736000000000) / 10000000)
- end
-
- def self.time2wtime(time)
- time.to_i * 10000000 + 116444736000000000
- end
-
- #
- # constructors
- #
- private_class_method :new
-
- def self.open(hkey, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED)
- subkey = subkey.chomp('\\')
- newkey = API.OpenKey(hkey.hkey, subkey, opt, desired)
- obj = new(newkey, hkey, subkey, REG_OPENED_EXISTING_KEY)
- if block_given?
- begin
- yield obj
- ensure
- obj.close
- end
- else
- obj
- end
- end
-
- def self.create(hkey, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED)
- newkey, disp = API.CreateKey(hkey.hkey, subkey, opt, desired)
- obj = new(newkey, hkey, subkey, disp)
- if block_given?
- begin
- yield obj
- ensure
- obj.close
- end
- else
- obj
- end
- end
-
- #
- # finalizer
- #
- @@final = proc { |hkey| proc { API.CloseKey(hkey[0]) if hkey[0] } }
-
- #
- # initialize
- #
- def initialize(hkey, parent, keyname, disposition)
- @hkey = hkey
- @parent = parent
- @keyname = keyname
- @disposition = disposition
- @hkeyfinal = [ hkey ]
- ObjectSpace.define_finalizer self, @@final.call(@hkeyfinal)
- end
- attr_reader :hkey, :parent, :keyname, :disposition
-
- #
- # attributes
- #
- def created?
- @disposition == REG_CREATED_NEW_KEY
- end
-
- def open?
- !@hkey.nil?
- end
-
- def name
- parent = self
- name = @keyname
- while parent = parent.parent
- name = parent.keyname + '\\' + name
- end
- name
- end
-
- def inspect
- "\#<Win32::Registry key=#{name.inspect}>"
- end
-
- #
- # marshalling
- #
- def _dump(depth)
- raise TypeError, "can't dump Win32::Registry"
- end
-
- #
- # open/close
- #
- def open(subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED, &blk)
- self.class.open(self, subkey, desired, opt, &blk)
- end
-
- def create(subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED, &blk)
- self.class.create(self, subkey, desired, opt, &blk)
- end
-
- def close
- API.CloseKey(@hkey)
- @hkey = @parent = @keyname = nil
- @hkeyfinal[0] = nil
- end
-
- #
- # iterator
- #
- def each_value
- index = 0
- while true
- begin
- subkey = API.EnumValue(@hkey, index)
- rescue Error
- break
- end
- begin
- type, data = read(subkey)
- rescue Error
- next
- end
- yield subkey, type, data
- index += 1
- end
- index
- end
- alias each each_value
-
- def each_key
- index = 0
- while true
- begin
- subkey, wtime = API.EnumKey(@hkey, index)
- rescue Error
- break
- end
- yield subkey, wtime
- index += 1
- end
- index
- end
-
- def keys
- keys_ary = []
- each_key { |key,| keys_ary << key }
- keys_ary
- end
-
- #
- # reader
- #
- def read(name, *rtype)
- type, data = API.QueryValue(@hkey, name)
- unless rtype.empty? or rtype.include?(type)
- raise TypeError, "Type mismatch (expect #{rtype.inspect} but #{type} present)"
- end
- case type
- when REG_SZ, REG_EXPAND_SZ
- [ type, data.chop ]
- when REG_MULTI_SZ
- [ type, data.split(/\0/) ]
- when REG_BINARY
- [ type, data ]
- when REG_DWORD
- [ type, API.unpackdw(data) ]
- when REG_DWORD_BIG_ENDIAN
- [ type, data.unpack('N')[0] ]
- when REG_QWORD
- [ type, API.unpackqw(data) ]
- else
- raise TypeError, "Type #{type} is not supported."
- end
- end
-
- def [](name, *rtype)
- type, data = read(name, *rtype)
- case type
- when REG_SZ, REG_DWORD, REG_QWORD, REG_MULTI_SZ
- data
- when REG_EXPAND_SZ
- Registry.expand_environ(data)
- else
- raise TypeError, "Type #{type} is not supported."
- end
- end
-
- def read_s(name)
- read(name, REG_SZ)[1]
- end
-
- def read_s_expand(name)
- type, data = read(name, REG_SZ, REG_EXPAND_SZ)
- if type == REG_EXPAND_SZ
- Registry.expand_environ(data)
- else
- data
- end
- end
-
- def read_i(name)
- read(name, REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD)[1]
- end
-
- def read_bin(name)
- read(name, REG_BINARY)[1]
- end
-
- #
- # writer
- #
- def write(name, type, data)
- case type
- when REG_SZ, REG_EXPAND_SZ
- data = data.to_s + "\0"
- when REG_MULTI_SZ
- data = data.to_a.join("\0") + "\0\0"
- when REG_BINARY
- data = data.to_s
- when REG_DWORD
- data = API.packdw(data.to_i)
- when REG_DWORD_BIG_ENDIAN
- data = [data.to_i].pack('N')
- when REG_QWORD
- data = API.packqw(data.to_i)
- else
- raise TypeError, "Unsupported type #{type}"
- end
- API.SetValue(@hkey, name, type, data, data.length)
- end
-
- def []=(name, rtype, value = nil)
- if value
- write name, rtype, value
- else
- case value = rtype
- when Integer
- write name, REG_DWORD, value
- when String
- write name, REG_SZ, value
- when Array
- write name, REG_MULTI_SZ, value
- else
- raise TypeError, "Unexpected type #{value.class}"
- end
- end
- value
- end
-
- def write_s(name, value)
- write name, REG_SZ, value.to_s
- end
-
- def write_i(name, value)
- write name, REG_DWORD, value.to_i
- end
-
- def write_bin(name, value)
- write name, REG_BINARY, value.to_s
- end
-
- #
- # delete
- #
- def delete_value(name)
- API.DeleteValue(@hkey, name)
- end
- alias delete delete_value
-
- def delete_key(name, recursive = false)
- if recursive
- open(name, KEY_ALL_ACCESS) do |reg|
- reg.keys.each do |key|
- begin
- reg.delete_key(key, true)
- rescue Error
- #
- end
- end
- end
- API.DeleteKey(@hkey, name)
- else
- begin
- API.EnumKey @hkey, 0
- rescue Error
- return API.DeleteKey(@hkey, name)
- end
- raise Error.new(5) ## ERROR_ACCESS_DENIED
- end
- end
-
- #
- # flush
- #
- def flush
- API.FlushKey @hkey
- end
-
- #
- # key information
- #
- def info
- API.QueryInfoKey(@hkey)
- end
- %w[
- num_keys max_key_length
- num_values max_value_name_length max_value_length
- descriptor_length wtime
- ].each_with_index do |s, i|
- eval <<-__END__
- def #{s}
- info[#{i}]
- end
- __END__
- end
- end
-end
diff --git a/ext/Win32API/lib/win32/resolv.rb b/ext/Win32API/lib/win32/resolv.rb
deleted file mode 100644
index 6534d20760..0000000000
--- a/ext/Win32API/lib/win32/resolv.rb
+++ /dev/null
@@ -1,366 +0,0 @@
-=begin
-= Win32 DNS and DHCP I/F
-
-=end
-
-require 'win32/registry'
-
-module Win32
- module Resolv
- API = Registry::API
-
- def self.get_hosts_path
- path = get_hosts_dir
- path = File.join(path.gsub(/\\/, File::SEPARATOR), 'hosts')
- File.exist?(path) ? path : nil
- end
-
- def self.get_resolv_info
- search, nameserver = get_info
- if search.empty?
- search = nil
- else
- search.delete("")
- search.uniq!
- end
- if nameserver.empty?
- nameserver = nil
- else
- nameserver.delete("")
- nameserver.delete("0.0.0.0")
- nameserver.uniq!
- end
- [ search, nameserver ]
- end
-
-getv = Win32API.new('kernel32.dll', 'GetVersionExA', 'P', 'L')
-info = [ 148, 0, 0, 0, 0 ].pack('V5') + "\0" * 128
-getv.call(info)
-if info.unpack('V5')[4] == 2 # VER_PLATFORM_WIN32_NT
-#====================================================================
-# Windows NT
-#====================================================================
- module_eval <<-'__EOS__', __FILE__, __LINE__+1
- TCPIP_NT = 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters'
-
- class << self
- private
- def get_hosts_dir
- Registry::HKEY_LOCAL_MACHINE.open(TCPIP_NT) do |reg|
- reg.read_s_expand('DataBasePath')
- end
- end
-
- def get_info
- search = nil
- nameserver = []
- Registry::HKEY_LOCAL_MACHINE.open(TCPIP_NT) do |reg|
- begin
- slist = reg.read_s('SearchList')
- search = slist.split(/,\s*/) unless slist.empty?
- rescue Registry::Error
- end
-
- if add_search = search.nil?
- search = []
- begin
- nvdom = reg.read_s('NV Domain')
- unless nvdom.empty?
- @search = [ nvdom ]
- if reg.read_i('UseDomainNameDevolution') != 0
- if /^[\w\d]+\./ =~ nvdom
- devo = $'
- end
- end
- end
- rescue Registry::Error
- end
- end
-
- reg.open('Interfaces') do |reg|
- reg.each_key do |iface,|
- reg.open(iface) do |regif|
- begin
- [ 'NameServer', 'DhcpNameServer' ].each do |key|
- ns = regif.read_s(key)
- unless ns.empty?
- nameserver.concat(ns.split(/[,\s]\s*/))
- break
- end
- end
- rescue Registry::Error
- end
-
- if add_search
- begin
- [ 'Domain', 'DhcpDomain' ].each do |key|
- dom = regif.read_s(key)
- unless dom.empty?
- search.concat(dom.split(/,\s*/))
- break
- end
- end
- rescue Registry::Error
- end
- end
- end
- end
- end
- search << devo if add_search and devo
- end
- [ search.uniq, nameserver.uniq ]
- end
- end
- __EOS__
-else
-#====================================================================
-# Windows 9x
-#====================================================================
- module_eval <<-'__EOS__', __FILE__, __LINE__+1
- TCPIP_9X = 'SYSTEM\CurrentControlSet\Services\VxD\MSTCP'
- DHCP_9X = 'SYSTEM\CurrentControlSet\Services\VxD\DHCP'
- WINDOWS = 'Software\Microsoft\Windows\CurrentVersion'
-
- class << self
- # private
-
- def get_hosts_dir
- Registry::HKEY_LOCAL_MACHINE.open(WINDOWS) do |reg|
- reg.read_s_expand('SystemRoot')
- end
- end
-
- def get_info
- search = []
- nameserver = []
- begin
- Registry::HKEY_LOCAL_MACHINE.open(TCPIP_9X) do |reg|
- if reg.read_s("EnableDNS") == "1"
- domain = reg.read_s("Domain")
- ns = reg.read_s("NameServer")
- slist = reg.read_s("SearchList")
- search << domain unless domain.empty?
- search.concat(slist.split(/,\s*/))
- nameserver.concat(ns.split(/[,\s]\s*/))
- end
- end
- rescue Registry::Error
- end
-
- dhcpinfo = get_dhcpinfo
- search.concat(dhcpinfo[0])
- nameserver.concat(dhcpinfo[1])
- [ search, nameserver ]
- end
-
- def get_dhcpinfo
- macaddrs = {}
- ipaddrs = {}
- WsControl.get_iflist.each do |index, macaddr, *ipaddr|
- macaddrs[macaddr] = 1
- ipaddr.each { |ipaddr| ipaddrs[ipaddr] = 1 }
- end
- iflist = [ macaddrs, ipaddrs ]
-
- search = []
- nameserver = []
- version = -1
- Registry::HKEY_LOCAL_MACHINE.open(DHCP_9X) do |reg|
- begin
- version = API.unpackdw(reg.read_bin("Version"))
- rescue Registry::Error
- end
-
- reg.each_key do |key,|
- catch(:not_used) do
- reg.open(key) do |regdi|
- dom, ns = get_dhcpinfo_key(version, regdi, iflist)
- search << dom if dom
- nameserver.concat(ns) if ns
- end
- end
- end
- end
- [ search, nameserver ]
- end
-
- def get_dhcpinfo_95(reg)
- dhcp = reg.read_bin("DhcpInfo")
- [
- API.unpackdw(dhcp[4..7]),
- API.unpackdw(dhcp[8..11]),
- 1,
- dhcp[45..50],
- reg.read_bin("OptionInfo"),
- ]
- end
-
- def get_dhcpinfo_98(reg)
- [
- API.unpackdw(reg.read_bin("DhcpIPAddress")),
- API.unpackdw(reg.read_bin("DhcpSubnetMask")),
- API.unpackdw(reg.read_bin("HardwareType")),
- reg.read_bin("HardwareAddress"),
- reg.read_bin("OptionInfo"),
- ]
- end
-
- def get_dhcpinfo_key(version, reg, iflist)
- info = case version
- when 1
- get_dhcpinfo_95(reg)
- when 2
- get_dhcpinfo_98(reg)
- else
- begin
- get_dhcpinfo_98(reg)
- rescue Registry::Error
- get_dhcpinfo_95(reg)
- end
- end
- ipaddr, netmask, hwtype, macaddr, opt = info
- throw :not_used unless
- ipaddr and ipaddr != 0 and
- netmask and netmask != 0 and
- macaddr and macaddr.size == 6 and
- hwtype == 1 and
- iflist[0][macaddr] and iflist[1][ipaddr]
-
- size = opt.size
- idx = 0
- while idx <= size
- opttype = opt[idx]
- optsize = opt[idx + 1]
- optval = opt[idx + 2, optsize]
- case opttype
- when 0xFF ## term
- break
- when 0x0F ## domain
- domain = optval.chomp("\0")
- when 0x06 ## dns
- nameserver = optval.scan(/..../).collect { |addr|
- "%d.%d.%d.%d" % addr.unpack('C4')
- }
- end
- idx += optsize + 2
- end
- [ domain, nameserver ]
- rescue Registry::Error
- throw :not_used
- end
- end
-
- module WsControl
- WsControl = Win32API.new('wsock32.dll', 'WsControl', 'LLPPPP', 'L')
- WSAGetLastError = Win32API.new('wsock32.dll', 'WSAGetLastError', 'V', 'L')
-
- MAX_TDI_ENTITIES = 512
- IPPROTO_TCP = 6
- WSCTL_TCP_QUERY_INFORMATION = 0
- INFO_CLASS_GENERIC = 0x100
- INFO_CLASS_PROTOCOL = 0x200
- INFO_TYPE_PROVIDER = 0x100
- ENTITY_LIST_ID = 0
- GENERIC_ENTITY = 0
- CL_NL_ENTITY = 0x301
- IF_ENTITY = 0x200
- ENTITY_TYPE_ID = 1
- CL_NL_IP = 0x303
- IF_MIB = 0x202
- IF_MIB_STATS_ID = 1
- IP_MIB_ADDRTABLE_ENTRY_ID = 0x102
-
- def self.wsctl(tei_entity, tei_instance,
- toi_class, toi_type, toi_id,
- buffsize)
- reqinfo = [
- ## TDIEntityID
- tei_entity, tei_instance,
- ## TDIObjectID
- toi_class, toi_type, toi_id,
- ## TCP_REQUEST_INFORMATION_EX
- ""
- ].pack('VVVVVa16')
- reqsize = API.packdw(reqinfo.size)
- buff = "\0" * buffsize
- buffsize = API.packdw(buffsize)
- result = WsControl.call(
- IPPROTO_TCP,
- WSCTL_TCP_QUERY_INFORMATION,
- reqinfo, reqsize,
- buff, buffsize)
- if result != 0
- raise RuntimeError, "WsControl failed.(#{result})"
- end
- [ buff, API.unpackdw(buffsize) ]
- end
- private_class_method :wsctl
-
- def self.get_iflist
- # Get TDI Entity List
- entities, size =
- wsctl(GENERIC_ENTITY, 0,
- INFO_CLASS_GENERIC,
- INFO_TYPE_PROVIDER,
- ENTITY_LIST_ID,
- MAX_TDI_ENTITIES * 8) # sizeof(TDIEntityID)
- entities = entities[0, size].
- scan(/.{8}/).
- collect { |e| e.unpack('VV') }
-
- # Get MIB Interface List
- iflist = []
- ifcount = 0
- entities.each do |entity, instance|
- if( (entity & IF_ENTITY)>0 )
- ifcount += 1
- etype, = wsctl(entity, instance,
- INFO_CLASS_GENERIC,
- INFO_TYPE_PROVIDER,
- ENTITY_TYPE_ID,
- 4)
- if( (API.unpackdw(etype) & IF_MIB)==IF_MIB )
- ifentry, = wsctl(entity, instance,
- INFO_CLASS_PROTOCOL,
- INFO_TYPE_PROVIDER,
- IF_MIB_STATS_ID,
- 21 * 4 + 8 + 130) # sizeof(IFEntry)
- iflist << [
- API.unpackdw(ifentry[0,4]),
- ifentry[20, 6]
- ]
- end
- end
- end
-
- # Get IP Addresses
- entities.each do |entity, instance|
- if entity == CL_NL_ENTITY
- etype, = wsctl(entity, instance,
- INFO_CLASS_GENERIC,
- INFO_TYPE_PROVIDER,
- ENTITY_TYPE_ID,
- 4)
- if API.unpackdw(etype) == CL_NL_IP
- ipentries, = wsctl(entity, instance,
- INFO_CLASS_PROTOCOL,
- INFO_TYPE_PROVIDER,
- IP_MIB_ADDRTABLE_ENTRY_ID,
- 24 * (ifcount+1)) # sizeof(IPAddrEntry)
- ipentries.scan(/.{24}/) do |ipentry|
- ipaddr, index = ipentry.unpack('VV')
- if ifitem = iflist.assoc(index)
- ifitem << ipaddr
- end
- end
- end
- end
- end
- iflist
- end
- end
- __EOS__
-end
-#====================================================================
- end
-end
diff --git a/ext/Win32API/point.rb b/ext/Win32API/point.rb
deleted file mode 100644
index 60e265f3ee..0000000000
--- a/ext/Win32API/point.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'Win32API'
-
-getCursorPos = Win32API.new("user32", "GetCursorPos", ['P'], 'V')
-
-lpPoint = " " * 8 # store two LONGs
-getCursorPos.Call(lpPoint)
-x, y = lpPoint.unpack("LL") # get the actual values
-
-print "x: ", x, "\n"
-print "y: ", y, "\n"
-
-ods = Win32API.new("kernel32", "OutputDebugString", ['P'], 'V')
-ods.Call("Hello, World\n");
-
-GetDesktopWindow = Win32API.new("user32", "GetDesktopWindow", [], 'L')
-GetActiveWindow = Win32API.new("user32", "GetActiveWindow", [], 'L')
-SendMessage = Win32API.new("user32", "SendMessage", ['L'] * 4, 'L')
-SendMessage.Call GetDesktopWindow.Call, 274, 0xf140, 0
diff --git a/ext/bigdecimal/.cvsignore b/ext/bigdecimal/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/bigdecimal/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/bigdecimal/README b/ext/bigdecimal/README
deleted file mode 100644
index a233f47f64..0000000000
--- a/ext/bigdecimal/README
+++ /dev/null
@@ -1,60 +0,0 @@
-
- Ruby BIGDECIMAL(Variable Precision) extension library.
- Copyright (C) 1999 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
-
-BigDecimal is copyrighted free software by Shigeo Kobayashi <shigeo@tinyforest.gr.jp>.
-You can redistribute it and/or modify it under either the terms of the GPL
-(see COPYING file), or the conditions below:
-
- 1. You may make and give away verbatim copies of the source form of the
- software without restriction, provided that you duplicate all of the
- original copyright notices and associated disclaimers.
-
- 2. You may modify your copy of the software in any way, provided that
- you do at least ONE of the following:
-
- a) place your modifications in the Public Domain or otherwise
- make them Freely Available, such as by posting said
- modifications to Usenet or an equivalent medium, or by allowing
- the author to include your modifications in the software.
-
- b) use the modified software only within your corporation or
- organization.
-
- c) rename any non-standard executables so the names do not conflict
- with standard executables, which must also be provided.
-
- d) make other distribution arrangements with the author.
-
- 3. You may distribute the software in object code or executable
- form, provided that you do at least ONE of the following:
-
- a) distribute the executables and library files of the software,
- together with instructions (in the manual page or equivalent)
- on where to get the original distribution.
-
- b) accompany the distribution with the machine-readable source of
- the software.
-
- c) give non-standard executables non-standard names, with
- instructions on where to get the original software distribution.
-
- d) make other distribution arrangements with the author.
-
- 4. You may modify and include the part of the software into any other
- software (possibly commercial).
-
- 5. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- PURPOSE.
-
-* The Author
-
-Feel free to send comments and bug reports to the author. Here is the
-author's latest mail address:
-
- shigeo@tinyforest.gr.jp
-
--------------------------------------------------------
-created at: Thu Dec 22 1999
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
deleted file mode 100644
index 04266b1d42..0000000000
--- a/ext/bigdecimal/bigdecimal.c
+++ /dev/null
@@ -1,4689 +0,0 @@
-/*
- *
- * Ruby BigDecimal(Variable decimal precision) extension library.
- *
- * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
- *
- * You may distribute under the terms of either the GNU General Public
- * License or the Artistic License, as specified in the README file
- * of this BigDecimal distribution.
- *
- * NOTE: Change log in this source removed to reduce source code size.
- * See rev. 1.25 if needed.
- *
- */
-
-#include "ruby.h"
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <float.h>
-#include <math.h>
-#include "math.h"
-#include "version.h"
-
-/* #define ENABLE_NUMERIC_STRING */
-
-VALUE rb_cBigDecimal;
-
-#include "bigdecimal.h"
-
-/* MACRO's to guard objects from GC by keeping them in stack */
-#define ENTER(n) volatile VALUE vStack[n];int iStack=0
-#define PUSH(x) vStack[iStack++] = (unsigned long)(x);
-#define SAVE(p) PUSH(p->obj);
-#define GUARD_OBJ(p,y) {p=y;SAVE(p);}
-
-/*
- * ================== Ruby Interface part ==========================
- */
-#define DoSomeOne(x,y) rb_num_coerce_bin(x,y)
-
-#if 0
-/* BigDecimal provides arbitrary-precision floating point decimal arithmetic.
- *
- * Copyright (C) 2002 by Shigeo Kobayashi <shigeo@tinyforest.gr.jp>.
- * You may distribute under the terms of either the GNU General Public
- * License or the Artistic License, as specified in the README file
- * of the BigDecimal distribution.
- *
- * Documented by mathew <meta@pobox.com>.
- *
- * = Introduction
- *
- * Ruby provides built-in support for arbitrary precision integer arithmetic.
- * For example:
- *
- * 42**13 -> 1265437718438866624512
- *
- * BigDecimal provides similar support for very large or very accurate floating
- * point numbers.
- *
- * Decimal arithmetic is also useful for general calculation, because it
- * provides the correct answers people expect--whereas normal binary floating
- * point arithmetic often introduces subtle errors because of the conversion
- * between base 10 and base 2. For example, try:
- *
- * sum = 0
- * for i in (1..10000)
- * sum = sum + 0.0001
- * end
- * print sum
- *
- * and contrast with the output from:
- *
- * require 'bigdecimal'
- *
- * sum = BigDecimal.new("0")
- * for i in (1..10000)
- * sum = sum + BigDecimal.new("0.0001")
- * end
- * print sum
- *
- * Similarly:
- *
- * (BigDecimal.new("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") -> true
- *
- * (1.2 - 1.0) == 0.2 -> false
- *
- * = Special features of accurate decimal arithmetic
- *
- * Because BigDecimal is more accurate than normal binary floating point
- * arithmetic, it requires some special values.
- *
- * == Infinity
- *
- * BigDecimal sometimes needs to return infinity, for example if you divide
- * a value by zero.
- *
- * BigDecimal.new("1.0") / BigDecimal.new("0.0") -> infinity
- *
- * BigDecimal.new("-1.0") / BigDecimal.new("0.0") -> -infinity
- *
- * You can represent infinite numbers to BigDecimal using the strings
- * 'Infinity', '+Infinity' and '-Infinity' (case-sensitive)
- *
- * == Not a Number
- *
- * When a computation results in an undefined value, the special value NaN
- * (for 'not a number') is returned.
- *
- * Example:
- *
- * BigDecimal.new("0.0") / BigDecimal.new("0.0") -> NaN
- *
- * You can also create undefined values. NaN is never considered to be the
- * same as any other value, even NaN itself:
- *
- * n = BigDecimal.new('NaN')
- *
- * n == 0.0 -> nil
- *
- * n == n -> nil
- *
- * == Positive and negative zero
- *
- * If a computation results in a value which is too small to be represented as
- * a BigDecimal within the currently specified limits of precision, zero must
- * be returned.
- *
- * If the value which is too small to be represented is negative, a BigDecimal
- * value of negative zero is returned. If the value is positive, a value of
- * positive zero is returned.
- *
- * BigDecimal.new("1.0") / BigDecimal.new("-Infinity") -> -0.0
- *
- * BigDecimal.new("1.0") / BigDecimal.new("Infinity") -> 0.0
- *
- * (See BigDecimal.mode for how to specify limits of precision.)
- *
- * Note that -0.0 and 0.0 are considered to be the same for the purposes of
- * comparison.
- *
- * Note also that in mathematics, there is no particular concept of negative
- * or positive zero; true mathematical zero has no sign.
- */
-void
-Init_BigDecimal()
-{
- /* This is a #if-ed out function to fool Rdoc into documenting the class. */
- /* The real init function is Init_bigdecimal() further down. */
-}
-#endif
-
-/*
- * Returns the BigDecimal version number.
- *
- * Ruby 1.8.0 returns 1.0.0.
- * Ruby 1.8.1 thru 1.8.3 return 1.0.1.
- */
-static VALUE
-BigDecimal_version(VALUE self)
-{
- /*
- * 1.0.0: Ruby 1.8.0
- * 1.0.1: Ruby 1.8.1
- */
- return rb_str_new2("1.0.1");
-}
-
-/*
- * VP routines used in BigDecimal part
- */
-static unsigned short VpGetException(void);
-static void VpSetException(unsigned short f);
-static void VpInternalRound(Real *c,int ixDigit,U_LONG vPrev,U_LONG v);
-static int VpLimitRound(Real *c,U_LONG ixDigit);
-
-/*
- * **** BigDecimal part ****
- */
-
-static void
-BigDecimal_delete(Real *pv)
-{
- VpFree(pv);
-}
-
-static VALUE
-ToValue(Real *p)
-{
- if(VpIsNaN(p)) {
- VpException(VP_EXCEPTION_NaN,"Computation results to 'NaN'(Not a Number)",0);
- } else if(VpIsPosInf(p)) {
- VpException(VP_EXCEPTION_INFINITY,"Computation results to 'Infinity'",0);
- } else if(VpIsNegInf(p)) {
- VpException(VP_EXCEPTION_INFINITY,"Computation results to '-Infinity'",0);
- }
- return p->obj;
-}
-
-static Real *
-GetVpValue(VALUE v, int must)
-{
- Real *pv;
- VALUE bg;
- char szD[128];
-
- switch(TYPE(v))
- {
- case T_DATA:
- if(RDATA(v)->dfree ==(void *) BigDecimal_delete) {
- Data_Get_Struct(v, Real, pv);
- return pv;
- } else {
- goto SomeOneMayDoIt;
- }
- break;
- case T_FIXNUM:
- sprintf(szD, "%ld", FIX2LONG(v));
- return VpCreateRbObject(VpBaseFig() * 2 + 1, szD);
-
-#ifdef ENABLE_NUMERIC_STRING
- case T_STRING:
- SafeStringValue(v);
- return VpCreateRbObject(strlen(RSTRING(v)->ptr) + VpBaseFig() + 1,
- RSTRING(v)->ptr);
-#endif /* ENABLE_NUMERIC_STRING */
-
- case T_BIGNUM:
- bg = rb_big2str(v, 10);
- return VpCreateRbObject(strlen(RSTRING(bg)->ptr) + VpBaseFig() + 1,
- RSTRING(bg)->ptr);
- default:
- goto SomeOneMayDoIt;
- }
-
-SomeOneMayDoIt:
- if(must) {
- rb_raise(rb_eTypeError, "%s can't be coerced into BigDecimal",
- rb_special_const_p(v)?
- RSTRING(rb_inspect(v))->ptr:
- rb_obj_classname(v)
- );
- }
- return NULL; /* NULL means to coerce */
-}
-
-/* call-seq:
- * BigDecimal.double_fig
- *
- * The BigDecimal.double_fig class method returns the number of digits a
- * Float number is allowed to have. The result depends upon the CPU and OS
- * in use.
- */
-static VALUE
-BigDecimal_double_fig(VALUE self)
-{
- return INT2FIX(VpDblFig());
-}
-
-/* call-seq:
- * precs
- *
- * Returns an Array of two Integer values.
- *
- * The first value is the current number of significant digits in the
- * BigDecimal. The second value is the maximum number of significant digits
- * for the BigDecimal.
- */
-static VALUE
-BigDecimal_prec(VALUE self)
-{
- ENTER(1);
- Real *p;
- VALUE obj;
-
- GUARD_OBJ(p,GetVpValue(self,1));
- obj = rb_assoc_new(INT2NUM(p->Prec*VpBaseFig()),
- INT2NUM(p->MaxPrec*VpBaseFig()));
- return obj;
-}
-
-static VALUE
-BigDecimal_hash(VALUE self)
-{
- ENTER(1);
- Real *p;
- U_LONG hash,i;
-
- GUARD_OBJ(p,GetVpValue(self,1));
- hash = (U_LONG)p->sign;
- /* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */
- if(hash==2) {
- for(i = 0; i < p->Prec;i++) {
- hash = 31 * hash + p->frac[i];
- hash ^= p->frac[i];
- }
- hash += p->exponent;
- }
- return INT2FIX(hash);
-}
-
-static VALUE
-BigDecimal_dump(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- char sz[50];
- Real *vp;
- char *psz;
- VALUE dummy;
- rb_scan_args(argc, argv, "01", &dummy);
- GUARD_OBJ(vp,GetVpValue(self,1));
- sprintf(sz,"%lu:",VpMaxPrec(vp)*VpBaseFig());
- psz = ALLOCA_N(char,(unsigned int)VpNumOfChars(vp,"E")+strlen(sz));
- sprintf(psz,"%s",sz);
- VpToString(vp, psz+strlen(psz), 0, 0);
- return rb_str_new2(psz);
-}
-
-/*
- * Internal method used to provide marshalling support. See the Marshal module.
- */
-static VALUE
-BigDecimal_load(VALUE self, VALUE str)
-{
- ENTER(2);
- Real *pv;
- unsigned char *pch;
- unsigned char ch;
- unsigned long m=0;
-
- SafeStringValue(str);
- pch = RSTRING(str)->ptr;
- /* First get max prec */
- while((*pch)!=(unsigned char)'\0' && (ch=*pch++)!=(unsigned char)':') {
- if(!ISDIGIT(ch)) {
- rb_raise(rb_eTypeError, "load failed: invalid character in the marshaled string");
- }
- m = m*10 + (unsigned long)(ch-'0');
- }
- if(m>VpBaseFig()) m -= VpBaseFig();
- GUARD_OBJ(pv,VpNewRbClass(m,pch,self));
- m /= VpBaseFig();
- if(m && pv->MaxPrec>m) pv->MaxPrec = m+1;
- return ToValue(pv);
-}
-
- /* call-seq:
- * BigDecimal.mode(mode, value)
- *
- * Controls handling of arithmetic exceptions and rounding. If no value
- * is supplied, the current value is returned.
- *
- * Six values of the mode parameter control the handling of arithmetic
- * exceptions:
- *
- * BigDecimal::EXCEPTION_NaN
- * BigDecimal::EXCEPTION_INFINITY
- * BigDecimal::EXCEPTION_UNDERFLOW
- * BigDecimal::EXCEPTION_OVERFLOW
- * BigDecimal::EXCEPTION_ZERODIVIDE
- * BigDecimal::EXCEPTION_ALL
- *
- * For each mode parameter above, if the value set is false, computation
- * continues after an arithmetic exception of the appropriate type.
- * When computation continues, results are as follows:
- *
- * EXCEPTION_NaN:: NaN
- * EXCEPTION_INFINITY:: +infinity or -infinity
- * EXCEPTION_UNDERFLOW:: 0
- * EXCEPTION_OVERFLOW:: +infinity or -infinity
- * EXCEPTION_ZERODIVIDE:: +infinity or -infinity
- *
- * One value of the mode parameter controls the rounding of numeric values:
- * BigDecimal::ROUND_MODE. The values it can take are:
- *
- * ROUND_UP:: round away from zero
- * ROUND_DOWN:: round towards zero (truncate)
- * ROUND_HALF_UP:: round up if the appropriate digit >= 5, otherwise truncate (default)
- * ROUND_HALF_DOWN:: round up if the appropriate digit >= 6, otherwise truncate
- * ROUND_HALF_EVEN:: round towards the even neighbor (Banker's rounding)
- * ROUND_CEILING:: round towards positive infinity (ceil)
- * ROUND_FLOOR:: round towards negative infinity (floor)
- *
- */
-static VALUE
-BigDecimal_mode(int argc, VALUE *argv, VALUE self)
-{
- VALUE which;
- VALUE val;
- unsigned long f,fo;
-
- if(rb_scan_args(argc,argv,"11",&which,&val)==1) val = Qnil;
-
- Check_Type(which, T_FIXNUM);
- f = (unsigned long)FIX2INT(which);
-
- if(f&VP_EXCEPTION_ALL) {
- /* Exception mode setting */
- fo = VpGetException();
- if(val==Qnil) return INT2FIX(fo);
- if(val!=Qfalse && val!=Qtrue) {
- rb_raise(rb_eTypeError, "second argument must be true or false");
- return Qnil; /* Not reached */
- }
- if(f&VP_EXCEPTION_INFINITY) {
- VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_INFINITY):
- (fo&(~VP_EXCEPTION_INFINITY))));
- }
- if(f&VP_EXCEPTION_NaN) {
- VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_NaN):
- (fo&(~VP_EXCEPTION_NaN))));
- }
- fo = VpGetException();
- return INT2FIX(fo);
- }
- if(VP_ROUND_MODE==f) {
- /* Rounding mode setting */
- fo = VpGetRoundMode();
- if(val==Qnil) return INT2FIX(fo);
- Check_Type(val, T_FIXNUM);
- if(!VpIsRoundMode(FIX2INT(val))) {
- rb_raise(rb_eTypeError, "invalid rounding mode");
- return Qnil;
- }
- fo = VpSetRoundMode((unsigned long)FIX2INT(val));
- return INT2FIX(fo);
- }
- rb_raise(rb_eTypeError, "first argument for BigDecimal#mode invalid");
- return Qnil;
-}
-
-static U_LONG
-GetAddSubPrec(Real *a, Real *b)
-{
- U_LONG mxs;
- U_LONG mx = a->Prec;
- S_INT d;
-
- if(!VpIsDef(a) || !VpIsDef(b)) return (-1L);
- if(mx < b->Prec) mx = b->Prec;
- if(a->exponent!=b->exponent) {
- mxs = mx;
- d = a->exponent - b->exponent;
- if(d<0) d = -d;
- mx = mx+(U_LONG)d;
- if(mx<mxs) {
- return VpException(VP_EXCEPTION_INFINITY,"Exponent overflow",0);
- }
- }
- return mx;
-}
-
-static S_INT
-GetPositiveInt(VALUE v)
-{
- S_INT n;
- Check_Type(v, T_FIXNUM);
- n = FIX2INT(v);
- if(n < 0) {
- rb_raise(rb_eArgError, "argument must be positive");
- }
- return n;
-}
-
-VP_EXPORT Real *
-VpNewRbClass(U_LONG mx, char *str, VALUE klass)
-{
- Real *pv = VpAlloc(mx,str);
- pv->obj = (VALUE)Data_Wrap_Struct(klass, 0, BigDecimal_delete, pv);
- return pv;
-}
-
-VP_EXPORT Real *
-VpCreateRbObject(U_LONG mx, char *str)
-{
- Real *pv = VpAlloc(mx,str);
- pv->obj = (VALUE)Data_Wrap_Struct(rb_cBigDecimal, 0, BigDecimal_delete, pv);
- return pv;
-}
-
-/* Returns True if the value is Not a Number */
-static VALUE
-BigDecimal_IsNaN(VALUE self)
-{
- Real *p = GetVpValue(self,1);
- if(VpIsNaN(p)) return Qtrue;
- return Qfalse;
-}
-
-/* Returns True if the value is infinite */
-static VALUE
-BigDecimal_IsInfinite(VALUE self)
-{
- Real *p = GetVpValue(self,1);
- if(VpIsPosInf(p)) return INT2FIX(1);
- if(VpIsNegInf(p)) return INT2FIX(-1);
- return Qnil;
-}
-
-/* Returns True if the value is finite (not NaN or infinite) */
-static VALUE
-BigDecimal_IsFinite(VALUE self)
-{
- Real *p = GetVpValue(self,1);
- if(VpIsNaN(p)) return Qfalse;
- if(VpIsInf(p)) return Qfalse;
- return Qtrue;
-}
-
-/* Returns the value as an integer (Fixnum or Bignum).
- *
- * If the BigNumber is infinity or NaN, returns nil.
- */
-static VALUE
-BigDecimal_to_i(VALUE self)
-{
- ENTER(5);
- int e,n,i,nf;
- U_LONG v,b,j;
- char *psz,*pch;
- Real *p;
-
- GUARD_OBJ(p,GetVpValue(self,1));
-
- /* Infinity or NaN not converted. */
- if(VpIsNaN(p)) {
- VpException(VP_EXCEPTION_NaN,"Computation results to 'NaN'(Not a Number)",0);
- return Qnil;
- } else if(VpIsPosInf(p)) {
- VpException(VP_EXCEPTION_INFINITY,"Computation results to 'Infinity'",0);
- return Qnil;
- } else if(VpIsNegInf(p)) {
- VpException(VP_EXCEPTION_INFINITY,"Computation results to '-Infinity'",0);
- return Qnil;
- }
-
- e = VpExponent10(p);
- if(e<=0) return INT2FIX(0);
- nf = VpBaseFig();
- if(e<=nf) {
- e = VpGetSign(p)*p->frac[0];
- return INT2FIX(e);
- }
- psz = ALLOCA_N(char,(unsigned int)(e+nf+2));
-
- n = (e+nf-1)/nf;
- pch = psz;
- if(VpGetSign(p)<0) *pch++ = '-';
- for(i=0;i<n;++i) {
- b = VpBaseVal()/10;
- if(i>=(int)p->Prec) {
- while(b) {
- *pch++ = '0';
- b /= 10;
- }
- continue;
- }
- v = p->frac[i];
- while(b) {
- j = v/b;
- *pch++ = (char)(j + '0');
- v -= j*b;
- b /= 10;
- }
- }
- *pch++ = 0;
- return rb_cstr2inum(psz,10);
-}
-
-static VALUE
-BigDecimal_induced_from(VALUE self, VALUE x)
-{
- Real *p = GetVpValue(x,1);
- return p->obj;
-}
-
-/* Returns a new Float object having approximately the same value as the
- * BigDecimal number. Normal accuracy limits and built-in errors of binary
- * Float arithmetic apply.
- */
-static VALUE
-BigDecimal_to_f(VALUE self)
-{
- ENTER(1);
- Real *p;
- double d, d2;
- S_LONG e;
-
- GUARD_OBJ(p,GetVpValue(self,1));
- if(VpVtoD(&d, &e, p)!=1) return rb_float_new(d);
- errno = 0;
- d2 = pow(10.0,(double)e);
- if((errno == ERANGE && e>0) || (d2>1.0 && (fabs(d) > (DBL_MAX / d2)))) {
- VpException(VP_EXCEPTION_OVERFLOW,"BigDecimal to Float conversion",0);
- if(d>0.0) return rb_float_new(DBL_MAX);
- else return rb_float_new(-DBL_MAX);
- }
- return rb_float_new(d*d2);
-}
-
-/* The coerce method provides support for Ruby type coercion. It is not
- * enabled by default.
- *
- * This means that binary operations like + * / or - can often be performed
- * on a BigDecimal and an object of another type, if the other object can
- * be coerced into a BigDecimal value.
- *
- * e.g.
- * a = BigDecimal.new("1.0")
- * b = a / 2.0 -> 0.5
- *
- * Note that coercing a String to a BigDecimal is not supported by default;
- * it requires a special compile-time option when building Ruby.
- */
-static VALUE
-BigDecimal_coerce(VALUE self, VALUE other)
-{
- ENTER(2);
- VALUE obj;
- Real *b;
- if(TYPE(other) == T_FLOAT) {
- obj = rb_assoc_new(other, BigDecimal_to_f(self));
- } else {
- GUARD_OBJ(b,GetVpValue(other,1));
- obj = rb_assoc_new(b->obj, self);
- }
- return obj;
-}
-
-static VALUE
-BigDecimal_uplus(VALUE self)
-{
- return self;
-}
-
- /* call-seq:
- * add(value, digits)
- *
- * Add the specified value.
- *
- * e.g.
- * c = a.add(b,n)
- * c = a + b
- *
- * digits:: If specified and less than the number of significant digits of the result, the result is rounded to that number of digits, according to BigDecimal.mode.
- */
-static VALUE
-BigDecimal_add(VALUE self, VALUE r)
-{
- ENTER(5);
- Real *c, *a, *b;
- U_LONG mx;
- GUARD_OBJ(a,GetVpValue(self,1));
- b = GetVpValue(r,0);
- if(!b) return DoSomeOne(self,r);
- SAVE(b);
- if(VpIsNaN(b)) return b->obj;
- if(VpIsNaN(a)) return a->obj;
- mx = GetAddSubPrec(a,b);
- if(mx==(-1L)) {
- GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0"));
- VpAddSub(c, a, b, 1);
- } else {
- GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
- if(!mx) {
- VpSetInf(c,VpGetSign(a));
- } else {
- VpAddSub(c, a, b, 1);
- }
- }
- return ToValue(c);
-}
-
- /* call-seq:
- * sub(value, digits)
- *
- * Subtract the specified value.
- *
- * e.g.
- * c = a.sub(b,n)
- * c = a - b
- *
- * digits:: If specified and less than the number of significant digits of the result, the result is rounded to that number of digits, according to BigDecimal.mode.
- */
-static VALUE
-BigDecimal_sub(VALUE self, VALUE r)
-{
- ENTER(5);
- Real *c, *a, *b;
- U_LONG mx;
-
- GUARD_OBJ(a,GetVpValue(self,1));
- b = GetVpValue(r,0);
- if(!b) return DoSomeOne(self,r);
- SAVE(b);
-
- if(VpIsNaN(b)) return b->obj;
- if(VpIsNaN(a)) return a->obj;
-
- mx = GetAddSubPrec(a,b);
- if(mx==(-1L)) {
- GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0"));
- VpAddSub(c, a, b, -1);
- } else {
- GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
- if(!mx) {
- VpSetInf(c,VpGetSign(a));
- } else {
- VpAddSub(c, a, b, -1);
- }
- }
- return ToValue(c);
-}
-
-static VALUE
-BigDecimalCmp(VALUE self, VALUE r,char op)
-{
- ENTER(5);
- S_INT e;
- Real *a, *b;
- GUARD_OBJ(a,GetVpValue(self,1));
- b = GetVpValue(r,0);
- if(!b) return rb_num_coerce_cmp(self,r);
- SAVE(b);
- e = VpComp(a, b);
- if(e==999) return Qnil;
- switch(op)
- {
- case '*': return INT2FIX(e); /* any op */
- case '=': if(e==0) return Qtrue ; return Qfalse;
- case '!': if(e!=0) return Qtrue ; return Qfalse;
- case 'G': if(e>=0) return Qtrue ; return Qfalse;
- case '>': if(e> 0) return Qtrue ; return Qfalse;
- case 'L': if(e<=0) return Qtrue ; return Qfalse;
- case '<': if(e< 0) return Qtrue ; return Qfalse;
- }
- rb_bug("Undefined operation in BigDecimalCmp()");
-}
-
-/* Returns True if the value is zero. */
-static VALUE
-BigDecimal_zero(VALUE self)
-{
- Real *a = GetVpValue(self,1);
- return VpIsZero(a) ? Qtrue : Qfalse;
-}
-
-/* Returns True if the value is non-zero. */
-static VALUE
-BigDecimal_nonzero(VALUE self)
-{
- Real *a = GetVpValue(self,1);
- return VpIsZero(a) ? Qnil : self;
-}
-
-/* The comparison operator.
- * a <=> b is 0 if a == b, 1 if a > b, -1 if a < b.
- */
-static VALUE
-BigDecimal_comp(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, '*');
-}
-
-/*
- * Tests for value equality; returns true if the values are equal.
- *
- * The == and === operators and the eql? method have the same implementation
- * for BigDecimal.
- *
- * Values may be coerced to perform the comparison:
- *
- * BigDecimal.new('1.0') == 1.0 -> true
- */
-static VALUE
-BigDecimal_eq(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, '=');
-}
-
-/* Returns true if the values are not equal in value. Values may be coerced
- * to perform the comparison:
- *
- * BigDecimal.new('1.0') != 1.0 -> false
- */
-static VALUE
-BigDecimal_ne(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, '!');
-}
-
-/* call-seq:
- * a < b
- *
- * Returns true if a is less than b. Values may be coerced to perform the
- * comparison (see ==, coerce).
- */
-static VALUE
-BigDecimal_lt(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, '<');
-}
-
-/* call-seq:
- * a <= b
- *
- * Returns true if a is less than or equal to b. Values may be coerced to
- * perform the comparison (see ==, coerce).
- */
-static VALUE
-BigDecimal_le(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, 'L');
-}
-
-/* call-seq:
- * a > b
- *
- * Returns true if a is greater than b. Values may be coerced to
- * perform the comparison (see ==, coerce).
- */
-static VALUE
-BigDecimal_gt(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, '>');
-}
-
-/* call-seq:
- * a >= b
- *
- * Returns true if a is greater than or equal to b. Values may be coerced to
- * perform the comparison (see ==, coerce)
- */
-static VALUE
-BigDecimal_ge(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, 'G');
-}
-
-static VALUE
-BigDecimal_neg(VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- GUARD_OBJ(a,GetVpValue(self,1));
- GUARD_OBJ(c,VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0"));
- VpAsgn(c, a, -1);
- return ToValue(c);
-}
-
- /* call-seq:
- * mult(value, digits)
- *
- * Multiply by the specified value.
- *
- * e.g.
- * c = a.mult(b,n)
- * c = a * b
- *
- * digits:: If specified and less than the number of significant digits of the result, the result is rounded to that number of digits, according to BigDecimal.mode.
- */
-static VALUE
-BigDecimal_mult(VALUE self, VALUE r)
-{
- ENTER(5);
- Real *c, *a, *b;
- U_LONG mx;
-
- GUARD_OBJ(a,GetVpValue(self,1));
- b = GetVpValue(r,0);
- if(!b) return DoSomeOne(self,r);
- SAVE(b);
-
- mx = a->Prec + b->Prec;
- GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
- VpMult(c, a, b);
- return ToValue(c);
-}
-
-static VALUE
-BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
-/* For c = self.div(r): with round operation */
-{
- ENTER(5);
- Real *a, *b;
- U_LONG mx;
-
- GUARD_OBJ(a,GetVpValue(self,1));
- b = GetVpValue(r,0);
- if(!b) return DoSomeOne(self,r);
- SAVE(b);
- *div = b;
- mx =(a->MaxPrec + b->MaxPrec + 1) * VpBaseFig();
- GUARD_OBJ((*c),VpCreateRbObject(mx, "#0"));
- GUARD_OBJ((*res),VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
- VpDivd(*c, *res, a, b);
- return (VALUE)0;
-}
-
- /* call-seq:
- * div(value, digits)
- * quo(value)
- *
- * Divide by the specified value.
- *
- * e.g.
- * c = a.div(b,n)
- *
- * digits:: If specified and less than the number of significant digits of the result, the result is rounded to that number of digits, according to BigDecimal.mode.
- *
- * If digits is 0, the result is the same as the / operator. If not, the
- * result is an integer BigDecimal, by analogy with Float#div.
- *
- * The alias quo is provided since div(value, 0) is the same as computing
- * the quotient; see divmod.
- */
-static VALUE
-BigDecimal_div(VALUE self, VALUE r)
-/* For c = self/r: with round operation */
-{
- ENTER(5);
- Real *c=NULL, *res=NULL, *div = NULL;
- r = BigDecimal_divide(&c, &res, &div, self, r);
- if(r!=(VALUE)0) return r; /* coerced by other */
- SAVE(c);SAVE(res);SAVE(div);
- /* a/b = c + r/b */
- /* c xxxxx
- r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE
- */
- /* Round */
- if(VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */
- VpInternalRound(c,0,c->frac[c->Prec-1],(VpBaseVal()*res->frac[0])/div->frac[0]);
- }
- return ToValue(c);
-}
-
-/*
- * %: mod = a%b = a - (a.to_f/b).floor * b
- * div = (a.to_f/b).floor
- */
-static VALUE
-BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
-{
- ENTER(8);
- Real *c=NULL, *d=NULL, *res=NULL;
- Real *a, *b;
- U_LONG mx;
-
- GUARD_OBJ(a,GetVpValue(self,1));
- b = GetVpValue(r,0);
- if(!b) return DoSomeOne(self,r);
- SAVE(b);
-
- if(VpIsNaN(a) || VpIsNaN(b)) goto NaN;
- if(VpIsInf(a) || VpIsInf(b)) goto NaN;
- if(VpIsZero(b)) goto NaN;
- if(VpIsZero(a)) {
- GUARD_OBJ(c,VpCreateRbObject(1, "0"));
- GUARD_OBJ(d,VpCreateRbObject(1, "0"));
- *div = d;
- *mod = c;
- return (VALUE)0;
- }
-
- mx = a->Prec;
- if(mx<b->Prec) mx = b->Prec;
- mx =(mx + 1) * VpBaseFig();
- GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
- GUARD_OBJ(res,VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
- VpDivd(c, res, a, b);
- mx = c->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(d,VpCreateRbObject(mx, "0"));
- VpActiveRound(d,c,VP_ROUND_DOWN,0);
- VpMult(res,d,b);
- VpAddSub(c,a,res,-1);
- if(!VpIsZero(c) && (VpGetSign(a)*VpGetSign(b)<0)) {
- VpAddSub(res,d,VpOne(),-1);
- VpAddSub(d ,c,b, 1);
- *div = res;
- *mod = d;
- } else {
- *div = d;
- *mod = c;
- }
- return (VALUE)0;
-
-NaN:
- GUARD_OBJ(c,VpCreateRbObject(1, "NaN"));
- GUARD_OBJ(d,VpCreateRbObject(1, "NaN"));
- *div = d;
- *mod = c;
- return (VALUE)0;
-}
-
-/* call-seq:
- * a % b
- * a.modulo(b)
- *
- * Returns the modulus from dividing by b. See divmod.
- */
-static VALUE
-BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
-{
- ENTER(3);
- VALUE obj;
- Real *div=NULL, *mod=NULL;
-
- obj = BigDecimal_DoDivmod(self,r,&div,&mod);
- if(obj!=(VALUE)0) return obj;
- SAVE(div);SAVE(mod);
- return ToValue(mod);
-}
-
-static VALUE
-BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
-{
- ENTER(10);
- U_LONG mx;
- Real *a=NULL, *b=NULL, *c=NULL, *res=NULL, *d=NULL, *rr=NULL, *ff=NULL;
- Real *f=NULL;
-
- GUARD_OBJ(a,GetVpValue(self,1));
- b = GetVpValue(r,0);
- if(!b) return DoSomeOne(self,r);
- SAVE(b);
-
- mx =(a->MaxPrec + b->MaxPrec) *VpBaseFig();
- GUARD_OBJ(c ,VpCreateRbObject(mx, "0"));
- GUARD_OBJ(res,VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
- GUARD_OBJ(rr ,VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
- GUARD_OBJ(ff ,VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
-
- VpDivd(c, res, a, b);
-
- mx = c->Prec *(VpBaseFig() + 1);
-
- GUARD_OBJ(d,VpCreateRbObject(mx, "0"));
- GUARD_OBJ(f,VpCreateRbObject(mx, "0"));
-
- VpActiveRound(d,c,VP_ROUND_DOWN,0); /* 0: round off */
-
- VpFrac(f, c);
- VpMult(rr,f,b);
- VpAddSub(ff,res,rr,1);
-
- *dv = d;
- *rv = ff;
- return (VALUE)0;
-}
-
-/* Returns the remainder from dividing by the value.
- *
- * If the values divided are of the same sign, the remainder is the same as
- * the modulus (see divmod).
- *
- * Otherwise, the remainder is the modulus minus the value divided by.
- */
-static VALUE
-BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
-{
- VALUE f;
- Real *d,*rv;
- f = BigDecimal_divremain(self,r,&d,&rv);
- if(f!=(VALUE)0) return f;
- return ToValue(rv);
-}
-
-/* Divides by the specified value, and returns the quotient and modulus
- * as BigDecimal numbers. The quotient is rounded towards negative infinity.
- *
- * For example:
- *
- * require 'bigdecimal'
- *
- * a = BigDecimal.new("42")
- * b = BigDecimal.new("9")
- *
- * q,m = a.divmod(b)
- *
- * c = q * b + m
- *
- * a == c -> true
- *
- * The quotient q is (a/b).floor, and the modulus is the amount that must be
- * added to q * b to get a.
- */
-static VALUE
-BigDecimal_divmod(VALUE self, VALUE r)
-{
- ENTER(5);
- VALUE obj;
- Real *div=NULL, *mod=NULL;
-
- obj = BigDecimal_DoDivmod(self,r,&div,&mod);
- if(obj!=(VALUE)0) return obj;
- SAVE(div);SAVE(mod);
- obj = rb_assoc_new(ToValue(div), ToValue(mod));
- return obj;
-}
-
-static VALUE
-BigDecimal_div2(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- VALUE b,n;
- int na = rb_scan_args(argc,argv,"11",&b,&n);
- if(na==1) { /* div in Float sense */
- VALUE obj;
- Real *div=NULL;
- Real *mod;
- obj = BigDecimal_DoDivmod(self,b,&div,&mod);
- if(obj!=(VALUE)0) return obj;
- return ToValue(div);
- } else { /* div in BigDecimal sense */
- U_LONG ix = (U_LONG)GetPositiveInt(n);
- if(ix==0) return BigDecimal_div(self,b);
- else {
- Real *res=NULL;
- Real *av=NULL, *bv=NULL, *cv=NULL;
- U_LONG mx = (ix+VpBaseFig()*2);
- U_LONG pl = VpSetPrecLimit(0);
-
- GUARD_OBJ(cv,VpCreateRbObject(mx,"0"));
- GUARD_OBJ(av,GetVpValue(self,1));
- GUARD_OBJ(bv,GetVpValue(b,1));
- mx = av->Prec + bv->Prec + 2;
- if(mx <= cv->MaxPrec) mx = cv->MaxPrec+1;
- GUARD_OBJ(res,VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0"));
- VpDivd(cv,res,av,bv);
- VpSetPrecLimit(pl);
- VpLeftRound(cv,VpGetRoundMode(),ix);
- return ToValue(cv);
- }
- }
-}
-
-static VALUE
-BigDecimal_add2(VALUE self, VALUE b, VALUE n)
-{
- ENTER(2);
- Real *cv;
- U_LONG mx = (U_LONG)GetPositiveInt(n);
- if(mx==0) return BigDecimal_add(self,b);
- else {
- U_LONG pl = VpSetPrecLimit(0);
- VALUE c = BigDecimal_add(self,b);
- VpSetPrecLimit(pl);
- GUARD_OBJ(cv,GetVpValue(c,1));
- VpLeftRound(cv,VpGetRoundMode(),mx);
- return ToValue(cv);
- }
-}
-
-static VALUE
-BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
-{
- ENTER(2);
- Real *cv;
- U_LONG mx = (U_LONG)GetPositiveInt(n);
- if(mx==0) return BigDecimal_sub(self,b);
- else {
- U_LONG pl = VpSetPrecLimit(0);
- VALUE c = BigDecimal_sub(self,b);
- VpSetPrecLimit(pl);
- GUARD_OBJ(cv,GetVpValue(c,1));
- VpLeftRound(cv,VpGetRoundMode(),mx);
- return ToValue(cv);
- }
-}
-
-static VALUE
-BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
-{
- ENTER(2);
- Real *cv;
- U_LONG mx = (U_LONG)GetPositiveInt(n);
- if(mx==0) return BigDecimal_mult(self,b);
- else {
- U_LONG pl = VpSetPrecLimit(0);
- VALUE c = BigDecimal_mult(self,b);
- VpSetPrecLimit(pl);
- GUARD_OBJ(cv,GetVpValue(c,1));
- VpLeftRound(cv,VpGetRoundMode(),mx);
- return ToValue(cv);
- }
-}
-
-/* Returns the absolute value.
- *
- * BigDecimal('5').abs -> 5
- *
- * BigDecimal('-3').abs -> 3
- */
-static VALUE
-BigDecimal_abs(VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- U_LONG mx;
-
- GUARD_OBJ(a,GetVpValue(self,1));
- mx = a->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
- VpAsgn(c, a, 1);
- VpChangeSign(c,(S_INT)1);
- return ToValue(c);
-}
-
-/* call-seq:
- * sqrt(n)
- *
- * Returns the square root of the value.
- *
- * If n is specified, returns at least that many significant digits.
- */
-static VALUE
-BigDecimal_sqrt(VALUE self, VALUE nFig)
-{
- ENTER(5);
- Real *c, *a;
- S_INT mx, n;
-
- GUARD_OBJ(a,GetVpValue(self,1));
- mx = a->Prec *(VpBaseFig() + 1);
-
- n = GetPositiveInt(nFig) + VpDblFig() + 1;
- if(mx <= n) mx = n;
- GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
- VpSqrt(c, a);
- return ToValue(c);
-}
-
-/* Return the integer part of the number.
- */
-static VALUE
-BigDecimal_fix(VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- U_LONG mx;
-
- GUARD_OBJ(a,GetVpValue(self,1));
- mx = a->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
- VpActiveRound(c,a,VP_ROUND_DOWN,0); /* 0: round off */
- return ToValue(c);
-}
-
-/* call-seq:
- * round(n,mode)
- *
- * Round to the nearest 1 (by default), returning the result as a BigDecimal.
- *
- * BigDecimal('3.14159').round -> 3
- *
- * BigDecimal('8.7').round -> 9
- *
- * If n is specified and positive, the fractional part of the result has no
- * more than that many digits.
- *
- * If n is specified and negative, at least that many digits to the left of the
- * decimal point will be 0 in the result.
- *
- * BigDecimal('3.14159').round(3) -> 3.142
- *
- * BigDecimal('13345.234').round(-2) -> 13300.0
- *
- * The value of the optional mode argument can be used to determine how
- * rounding is performed; see BigDecimal.mode.
- */
-static VALUE
-BigDecimal_round(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- int iLoc;
- U_LONG mx;
- VALUE vLoc;
- VALUE vRound;
- U_LONG pl;
-
- int sw = VpGetRoundMode();
-
- int na = rb_scan_args(argc,argv,"02",&vLoc,&vRound);
- switch(na) {
- case 0:
- iLoc = 0;
- break;
- case 1:
- Check_Type(vLoc, T_FIXNUM);
- iLoc = FIX2INT(vLoc);
- break;
- case 2:
- Check_Type(vLoc, T_FIXNUM);
- iLoc = FIX2INT(vLoc);
- Check_Type(vRound, T_FIXNUM);
- sw = FIX2INT(vRound);
- if(!VpIsRoundMode(sw)) {
- rb_raise(rb_eTypeError, "invalid rounding mode");
- return Qnil;
- }
- break;
- }
-
- pl = VpSetPrecLimit(0);
- GUARD_OBJ(a,GetVpValue(self,1));
- mx = a->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
- VpSetPrecLimit(pl);
- VpActiveRound(c,a,sw,iLoc);
- return ToValue(c);
-}
-
-/* call-seq:
- * truncate(n)
- *
- * Truncate to the nearest 1, returning the result as a BigDecimal.
- *
- * BigDecimal('3.14159').truncate -> 3
- *
- * BigDecimal('8.7').truncate -> 8
- *
- * If n is specified and positive, the fractional part of the result has no
- * more than that many digits.
- *
- * If n is specified and negative, at least that many digits to the left of the
- * decimal point will be 0 in the result.
- *
- * BigDecimal('3.14159').truncate(3) -> 3.141
- *
- * BigDecimal('13345.234').truncate(-2) -> 13300.0
- */
-static VALUE
-BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- int iLoc;
- U_LONG mx;
- VALUE vLoc;
- U_LONG pl = VpSetPrecLimit(0);
-
- if(rb_scan_args(argc,argv,"01",&vLoc)==0) {
- iLoc = 0;
- } else {
- Check_Type(vLoc, T_FIXNUM);
- iLoc = FIX2INT(vLoc);
- }
-
- GUARD_OBJ(a,GetVpValue(self,1));
- mx = a->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
- VpSetPrecLimit(pl);
- VpActiveRound(c,a,VP_ROUND_DOWN,iLoc); /* 0: truncate */
- return ToValue(c);
-}
-
-/* Return the fractional part of the number.
- */
-static VALUE
-BigDecimal_frac(VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- U_LONG mx;
-
- GUARD_OBJ(a,GetVpValue(self,1));
- mx = a->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
- VpFrac(c, a);
- return ToValue(c);
-}
-
-/* call-seq:
- * floor(n)
- *
- * Return the largest integer less than or equal to the value, as a BigDecimal.
- *
- * BigDecimal('3.14159').floor -> 3
- *
- * BigDecimal('-9.1').floor -> -10
- *
- * If n is specified and positive, the fractional part of the result has no
- * more than that many digits.
- *
- * If n is specified and negative, at least that
- * many digits to the left of the decimal point will be 0 in the result.
- *
- * BigDecimal('3.14159').floor(3) -> 3.141
- *
- * BigDecimal('13345.234').floor(-2) -> 13300.0
- */
-static VALUE
-BigDecimal_floor(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- U_LONG mx;
- int iLoc;
- VALUE vLoc;
- U_LONG pl = VpSetPrecLimit(0);
-
- if(rb_scan_args(argc,argv,"01",&vLoc)==0) {
- iLoc = 0;
- } else {
- Check_Type(vLoc, T_FIXNUM);
- iLoc = FIX2INT(vLoc);
- }
-
- GUARD_OBJ(a,GetVpValue(self,1));
- mx = a->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
- VpSetPrecLimit(pl);
- VpActiveRound(c,a,VP_ROUND_FLOOR,iLoc);
- return ToValue(c);
-}
-
-/* call-seq:
- * ceil(n)
- *
- * Return the smallest integer greater than or equal to the value, as a BigDecimal.
- *
- * BigDecimal('3.14159').ceil -> 4
- *
- * BigDecimal('-9.1').ceil -> -9
- *
- * If n is specified and positive, the fractional part of the result has no
- * more than that many digits.
- *
- * If n is specified and negative, at least that
- * many digits to the left of the decimal point will be 0 in the result.
- *
- * BigDecimal('3.14159').ceil(3) -> 3.142
- *
- * BigDecimal('13345.234').ceil(-2) -> 13400.0
- */
-static VALUE
-BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- U_LONG mx;
- int iLoc;
- VALUE vLoc;
- U_LONG pl = VpSetPrecLimit(0);
-
- if(rb_scan_args(argc,argv,"01",&vLoc)==0) {
- iLoc = 0;
- } else {
- Check_Type(vLoc, T_FIXNUM);
- iLoc = FIX2INT(vLoc);
- }
-
- GUARD_OBJ(a,GetVpValue(self,1));
- mx = a->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(c,VpCreateRbObject(mx, "0"));
- VpSetPrecLimit(pl);
- VpActiveRound(c,a,VP_ROUND_CEIL,iLoc);
- return ToValue(c);
-}
-
-/* call-seq:
- * to_s(s)
- *
- * Converts the value to a string.
- *
- * The default format looks like 0.xxxxEnn.
- *
- * The optional parameter s consists of either an integer; or an optional '+'
- * or ' ', followed by an optional number, followed by an optional 'E' or 'F'.
- *
- * If there is a '+' at the start of s, positive values are returned with
- * a leading '+'.
- *
- * A space at the start of s returns positive values with a leading space.
- *
- * If s contains a number, a space is inserted after each group of that many
- * fractional digits.
- *
- * If s ends with an 'E', engineering notation (0.xxxxEnn) is used.
- *
- * If s ends with an 'F', conventional floating point notation is used.
- *
- * Examples:
- *
- * BigDecimal.new('-123.45678901234567890').to_s('5F') -> '-123.45678 90123 45678 9'
- *
- * BigDecimal.new('123.45678901234567890').to_s('+8F') -> '+123.45678901 23456789'
- *
- * BigDecimal.new('123.45678901234567890').to_s(' F') -> ' 123.4567890123456789'
- */
-static VALUE
-BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- int fmt=0; /* 0:E format */
- int fPlus=0; /* =0:default,=1: set ' ' before digits ,set '+' before digits. */
- Real *vp;
- char *psz;
- char ch;
- U_LONG nc;
- S_INT mc = 0;
- VALUE f;
-
- GUARD_OBJ(vp,GetVpValue(self,1));
-
- if(rb_scan_args(argc,argv,"01",&f)==1) {
- if(TYPE(f)==T_STRING) {
- SafeStringValue(f);
- psz = RSTRING(f)->ptr;
- if(*psz==' ') {
- fPlus = 1; psz++;
- } else if(*psz=='+') {
- fPlus = 2; psz++;
- }
- while(ch=*psz++) {
- if(ISSPACE(ch)) continue;
- if(!ISDIGIT(ch)) {
- if(ch=='F' || ch=='f') fmt = 1; /* F format */
- break;
- }
- mc = mc * 10 + ch - '0';
- }
- } else {
- mc = GetPositiveInt(f);
- }
- }
- if(fmt) {
- nc = VpNumOfChars(vp,"F");
- } else {
- nc = VpNumOfChars(vp,"E");
- }
- if(mc>0) nc += (nc + mc - 1) / mc + 1;
-
- psz = ALLOCA_N(char,(unsigned int)nc);
-
- if(fmt) {
- VpToFString(vp, psz, mc, fPlus);
- } else {
- VpToString (vp, psz, mc, fPlus);
- }
- return rb_str_new2(psz);
-}
-
-/* Splits a BigDecimal number into four parts, returned as an array of values.
- *
- * The first value represents the sign of the BigDecimal, and is -1 or 1, or 0
- * if the BigDecimal is Not a Number.
- *
- * The second value is a string representing the significant digits of the
- * BigDecimal, with no leading zeros.
- *
- * The third value is the base used for arithmetic (currently always 10) as an
- * Integer.
- *
- * The fourth value is an Integer exponent.
- *
- * If the BigDecimal can be represented as 0.xxxxxx*10**n, then xxxxxx is the
- * string of significant digits with no leading zeros, and n is the exponent.
- *
- * From these values, you can translate a BigDecimal to a float as follows:
- *
- * sign, significant_digits, base, exponent = a.split
- * f = sign * "0.#{significant_digits}".to_f * (base ** exponent)
- *
- * (Note that the to_f method is provided as a more convenient way to translate
- * a BigDecimal to a Float.)
- */
-static VALUE
-BigDecimal_split(VALUE self)
-{
- ENTER(5);
- Real *vp;
- VALUE obj,obj1;
- S_LONG e;
- S_LONG s;
- char *psz1;
-
- GUARD_OBJ(vp,GetVpValue(self,1));
- psz1 = ALLOCA_N(char,(unsigned int)VpNumOfChars(vp,"E"));
- VpSzMantissa(vp,psz1);
- s = 1;
- if(psz1[0]=='-') {
- s = -1; ++psz1;
- }
- if(psz1[0]=='N') s=0; /* NaN */
- e = VpExponent10(vp);
- obj1 = rb_str_new2(psz1);
- obj = rb_ary_new2(4);
- rb_ary_push(obj, INT2FIX(s));
- rb_ary_push(obj, obj1);
- rb_ary_push(obj, INT2FIX(10));
- rb_ary_push(obj, INT2NUM(e));
- return obj;
-}
-
-/* Returns the exponent of the BigDecimal number, as an Integer.
- *
- * If the number can be represented as 0.xxxxxx*10**n where xxxxxx is a string
- * of digits with no leading zeros, then n is the exponent.
- */
-static VALUE
-BigDecimal_exponent(VALUE self)
-{
- S_LONG e = VpExponent10(GetVpValue(self,1));
- return INT2NUM(e);
-}
-
-/* Returns debugging information about the value as a string of comma-separated
- * values in angle brackets with a leading #:
- *
- * BigDecimal.new("1234.5678").inspect ->
- * "#<BigDecimal:b7ea1130,'0.12345678E4',8(12)>"
- *
- * The first part is the address, the second is the value as a string, and
- * the final part ss(mm) is the current number of significant digits and the
- * maximum number of significant digits, respectively.
- */
-static VALUE
-BigDecimal_inspect(VALUE self)
-{
- ENTER(5);
- Real *vp;
- VALUE obj;
- unsigned int nc;
- char *psz1;
- char *pszAll;
-
- GUARD_OBJ(vp,GetVpValue(self,1));
- nc = VpNumOfChars(vp,"E");
- nc +=(nc + 9) / 10;
-
- psz1 = ALLOCA_N(char,nc);
- pszAll = ALLOCA_N(char,nc+256);
- VpToString(vp, psz1, 10, 0);
- sprintf(pszAll,"#<BigDecimal:%lx,'%s',%lu(%lu)>",self,psz1,VpPrec(vp)*VpBaseFig(),VpMaxPrec(vp)*VpBaseFig());
- obj = rb_str_new2(pszAll);
- return obj;
-}
-
-/* call-seq:
- * power(n)
- *
- * Returns the value raised to the power of n. Note that n must be an Integer.
- *
- * Also available as the operator **
- */
-static VALUE
-BigDecimal_power(VALUE self, VALUE p)
-{
- ENTER(5);
- Real *x, *y;
- S_LONG mp, ma, n;
-
- Check_Type(p, T_FIXNUM);
- n = FIX2INT(p);
- ma = n;
- if(ma < 0) ma = -ma;
- if(ma == 0) ma = 1;
-
- GUARD_OBJ(x,GetVpValue(self,1));
- if(VpIsDef(x)) {
- mp = x->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(y,VpCreateRbObject(mp *(ma + 1), "0"));
- } else {
- GUARD_OBJ(y,VpCreateRbObject(1, "0"));
- }
- VpPower(y, x, n);
- return ToValue(y);
-}
-
-static VALUE
-BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- Real *pv;
- S_LONG mf;
- VALUE nFig;
- VALUE iniValue;
-
- if(rb_scan_args(argc,argv,"11",&iniValue,&nFig)==1) {
- mf = 0;
- } else {
- mf = GetPositiveInt(nFig);
- }
- SafeStringValue(iniValue);
- GUARD_OBJ(pv,VpCreateRbObject(mf, RSTRING(iniValue)->ptr));
- return ToValue(pv);
-}
-
- /* call-seq:
- * new(initial, digits)
- *
- * Create a new BigDecimal object.
- *
- * initial:: The initial value, as a String. Spaces are ignored, unrecognized characters terminate the value.
- *
- * digits:: The number of significant digits, as a Fixnum. If omitted or 0, the number of significant digits is determined from the initial value.
- *
- * The actual number of significant digits used in computation is usually
- * larger than the specified number.
- */
-static VALUE
-BigDecimal_new(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- Real *pv;
- S_LONG mf;
- VALUE nFig;
- VALUE iniValue;
-
- if(rb_scan_args(argc,argv,"11",&iniValue,&nFig)==1) {
- mf = 0;
- } else {
- mf = GetPositiveInt(nFig);
- }
- SafeStringValue(iniValue);
- GUARD_OBJ(pv,VpNewRbClass(mf, RSTRING(iniValue)->ptr,self));
- return ToValue(pv);
-}
-
- /* call-seq:
- * BigDecimal.limit(digits)
- *
- * Limit the number of significant digits in newly created BigDecimal
- * numbers to the specified value. Rounding is performed as necessary,
- * as specified by BigDecimal.mode.
- *
- * A limit of 0, the default, means no upper limit.
- *
- * The limit specified by this method takes priority over any limit
- * specified to instance methods such as ceil, floor, truncate, or round.
- */
-static VALUE
-BigDecimal_limit(int argc, VALUE *argv, VALUE self)
-{
- VALUE nFig;
- VALUE nCur = INT2NUM(VpGetPrecLimit());
-
- if(rb_scan_args(argc,argv,"01",&nFig)==1) {
- int nf;
- if(nFig==Qnil) return nCur;
- Check_Type(nFig, T_FIXNUM);
- nf = FIX2INT(nFig);
- if(nf<0) {
- rb_raise(rb_eArgError, "argument must be positive");
- }
- VpSetPrecLimit(nf);
- }
- return nCur;
-}
-
-/* Returns the sign of the value.
- *
- * Returns a positive value if > 0, a negative value if < 0, and a
- * zero if == 0.
- *
- * The specific value returned indicates the type and sign of the BigDecimal,
- * as follows:
- *
- * BigDecimal::SIGN_NaN:: value is Not a Number
- * BigDecimal::SIGN_POSITIVE_ZERO:: value is +0
- * BigDecimal::SIGN_NEGATIVE_ZERO:: value is -0
- * BigDecimal::SIGN_POSITIVE_INFINITE:: value is +infinity
- * BigDecimal::SIGN_NEGATIVE_INFINITE:: value is -infinity
- * BigDecimal::SIGN_POSITIVE_FINITE:: value is positive
- * BigDecimal::SIGN_NEGATIVE_FINITE:: value is negative
- */
-static VALUE
-BigDecimal_sign(VALUE self)
-{ /* sign */
- int s = GetVpValue(self,1)->sign;
- return INT2FIX(s);
-}
-
-void
-Init_bigdecimal(void)
-{
- /* Initialize VP routines */
- VpInit((U_LONG)0);
-
- /* Class and method registration */
- rb_cBigDecimal = rb_define_class("BigDecimal",rb_cNumeric);
-
- /* Global function */
- rb_define_global_function("BigDecimal", BigDecimal_global_new, -1);
-
- /* Class methods */
- rb_define_singleton_method(rb_cBigDecimal, "new", BigDecimal_new, -1);
- rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
- rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
- rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
- rb_define_singleton_method(rb_cBigDecimal, "induced_from",BigDecimal_induced_from, 1);
- rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1);
- rb_define_singleton_method(rb_cBigDecimal, "ver", BigDecimal_version, 0);
-
- /* Constants definition */
-
- /*
- * Base value used in internal calculations. On a 32 bit system, BASE
- * is 10000, indicating that calculation is done in groups of 4 digits.
- * (If it were larger, BASE**2 wouldn't fit in 32 bits, so you couldn't
- * guarantee that two groups could always be multiplied together without
- * overflow.)
- */
- rb_define_const(rb_cBigDecimal, "BASE", INT2FIX((S_INT)VpBaseVal()));
-
- /* Exceptions */
-
- /*
- * Determines whether overflow, underflow or zero divide result in
- * an exception being thrown. See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "EXCEPTION_ALL",INT2FIX(VP_EXCEPTION_ALL));
-
- /*
- * Determines what happens when the result of a computation is not a
- * number (NaN). See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "EXCEPTION_NaN",INT2FIX(VP_EXCEPTION_NaN));
-
- /*
- * Determines what happens when the result of a computation is infinity.
- * See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "EXCEPTION_INFINITY",INT2FIX(VP_EXCEPTION_INFINITY));
-
- /*
- * Determines what happens when the result of a computation is an underflow
- * (a result too small to be represented). See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "EXCEPTION_UNDERFLOW",INT2FIX(VP_EXCEPTION_UNDERFLOW));
-
- /*
- * Determines what happens when the result of a computation is an underflow
- * (a result too large to be represented). See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW",INT2FIX(VP_EXCEPTION_OVERFLOW));
-
- /*
- * Determines what happens when a division by zero is performed.
- * See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE",INT2FIX(VP_EXCEPTION_ZERODIVIDE));
-
- /*
- * Determines what happens when a result must be rounded in order to
- * fit in the appropriate number of significant digits. See
- * BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "ROUND_MODE",INT2FIX(VP_ROUND_MODE));
-
- /* Indicates that values should be rounded away from zero. See BigDecimal.mode. */
- rb_define_const(rb_cBigDecimal, "ROUND_UP",INT2FIX(VP_ROUND_UP));
- /* Indicates that values should be rounded towards zero. See BigDecimal.mode. */
- rb_define_const(rb_cBigDecimal, "ROUND_DOWN",INT2FIX(VP_ROUND_DOWN));
- /* Indicates that digits >= 5 should be rounded up, others rounded down. See BigDecimal.mode. */
- rb_define_const(rb_cBigDecimal, "ROUND_HALF_UP",INT2FIX(VP_ROUND_HALF_UP));
- /* Indicates that digits >= 6 should be rounded up, others rounded down. See BigDecimal.mode. */
- rb_define_const(rb_cBigDecimal, "ROUND_HALF_DOWN",INT2FIX(VP_ROUND_HALF_DOWN));
- /* Round towards +infinity. See BigDecimal.mode. */
- rb_define_const(rb_cBigDecimal, "ROUND_CEILING",INT2FIX(VP_ROUND_CEIL));
- /* Round towards -infinity. See BigDecimal.mode. */
- rb_define_const(rb_cBigDecimal, "ROUND_FLOOR",INT2FIX(VP_ROUND_FLOOR));
- /* Round towards the even neighbor. See BigDecimal.mode. */
- rb_define_const(rb_cBigDecimal, "ROUND_HALF_EVEN",INT2FIX(VP_ROUND_HALF_EVEN));
-
- /* Indicates that a value is not a number. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_NaN",INT2FIX(VP_SIGN_NaN));
- /* Indicates that a value is +0. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_ZERO",INT2FIX(VP_SIGN_POSITIVE_ZERO));
- /* Indicates that a value is -0. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_ZERO",INT2FIX(VP_SIGN_NEGATIVE_ZERO));
- /* Indicates that a value is positive and finite. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_FINITE",INT2FIX(VP_SIGN_POSITIVE_FINITE));
- /* Indicates that a value is negative and finite. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_FINITE",INT2FIX(VP_SIGN_NEGATIVE_FINITE));
- /* Indicates that a value is positive and infinite. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_INFINITE",INT2FIX(VP_SIGN_POSITIVE_INFINITE));
- /* Indicates that a value is negative and infinite. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE",INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
-
- /* instance methods */
- rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
-
- rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
- rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2);
- rb_define_method(rb_cBigDecimal, "mult", BigDecimal_mult2, 2);
- rb_define_method(rb_cBigDecimal, "div",BigDecimal_div2, -1);
- rb_define_method(rb_cBigDecimal, "hash", BigDecimal_hash, 0);
- rb_define_method(rb_cBigDecimal, "to_s", BigDecimal_to_s, -1);
- rb_define_method(rb_cBigDecimal, "to_i", BigDecimal_to_i, 0);
- rb_define_method(rb_cBigDecimal, "to_int", BigDecimal_to_i, 0);
- rb_define_method(rb_cBigDecimal, "split", BigDecimal_split, 0);
- rb_define_method(rb_cBigDecimal, "+", BigDecimal_add, 1);
- rb_define_method(rb_cBigDecimal, "-", BigDecimal_sub, 1);
- rb_define_method(rb_cBigDecimal, "+@", BigDecimal_uplus, 0);
- rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0);
- rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1);
- rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1);
- rb_define_method(rb_cBigDecimal, "quo", BigDecimal_div, 1);
- rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1);
- rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
- rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
- rb_define_method(rb_cBigDecimal, "divmod", BigDecimal_divmod, 1);
- /* rb_define_method(rb_cBigDecimal, "dup", BigDecimal_dup, 0); */
- rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_to_f, 0);
- rb_define_method(rb_cBigDecimal, "abs", BigDecimal_abs, 0);
- rb_define_method(rb_cBigDecimal, "sqrt", BigDecimal_sqrt, 1);
- rb_define_method(rb_cBigDecimal, "fix", BigDecimal_fix, 0);
- rb_define_method(rb_cBigDecimal, "round", BigDecimal_round, -1);
- rb_define_method(rb_cBigDecimal, "frac", BigDecimal_frac, 0);
- rb_define_method(rb_cBigDecimal, "floor", BigDecimal_floor, -1);
- rb_define_method(rb_cBigDecimal, "ceil", BigDecimal_ceil, -1);
- rb_define_method(rb_cBigDecimal, "power", BigDecimal_power, 1);
- rb_define_method(rb_cBigDecimal, "**", BigDecimal_power, 1);
- rb_define_method(rb_cBigDecimal, "<=>", BigDecimal_comp, 1);
- rb_define_method(rb_cBigDecimal, "==", BigDecimal_eq, 1);
- rb_define_method(rb_cBigDecimal, "===", BigDecimal_eq, 1);
- rb_define_method(rb_cBigDecimal, "eql?", BigDecimal_eq, 1);
- rb_define_method(rb_cBigDecimal, "!=", BigDecimal_ne, 1);
- rb_define_method(rb_cBigDecimal, "<", BigDecimal_lt, 1);
- rb_define_method(rb_cBigDecimal, "<=", BigDecimal_le, 1);
- rb_define_method(rb_cBigDecimal, ">", BigDecimal_gt, 1);
- rb_define_method(rb_cBigDecimal, ">=", BigDecimal_ge, 1);
- rb_define_method(rb_cBigDecimal, "zero?", BigDecimal_zero, 0);
- rb_define_method(rb_cBigDecimal, "nonzero?", BigDecimal_nonzero, 0);
- rb_define_method(rb_cBigDecimal, "coerce", BigDecimal_coerce, 1);
- rb_define_method(rb_cBigDecimal, "inspect", BigDecimal_inspect, 0);
- rb_define_method(rb_cBigDecimal, "exponent", BigDecimal_exponent, 0);
- rb_define_method(rb_cBigDecimal, "sign", BigDecimal_sign, 0);
- rb_define_method(rb_cBigDecimal, "nan?", BigDecimal_IsNaN, 0);
- rb_define_method(rb_cBigDecimal, "infinite?", BigDecimal_IsInfinite, 0);
- rb_define_method(rb_cBigDecimal, "finite?", BigDecimal_IsFinite, 0);
- rb_define_method(rb_cBigDecimal, "truncate", BigDecimal_truncate, -1);
- rb_define_method(rb_cBigDecimal, "_dump", BigDecimal_dump, -1);
-}
-
-/*
- *
- * ============================================================================
- *
- * vp_ routines begin from here.
- *
- * ============================================================================
- *
- */
-#ifdef _DEBUG
-/*static int gfDebug = 1;*/ /* Debug switch */
-static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */
-#endif /* _DEBUG */
-
-static U_LONG gnPrecLimit = 0; /* Global upper limit of the precision newly allocated */
-static U_LONG gfRoundMode = VP_ROUND_HALF_UP; /* Mode for general rounding operation */
-
-static U_LONG BASE_FIG = 4; /* =log10(BASE) */
-static U_LONG BASE = 10000L; /* Base value(value must be 10**BASE_FIG) */
- /* The value of BASE**2 + BASE must be represented */
- /* within one U_LONG. */
-static U_LONG HALF_BASE = 5000L;/* =BASE/2 */
-static S_LONG DBLE_FIG = 8; /* figure of double */
-static U_LONG BASE1 = 1000L; /* =BASE/10 */
-
-static Real *VpConstOne; /* constant 1.0 */
-static Real *VpPt5; /* constant 0.5 */
-static U_LONG maxnr = 100; /* Maximum iterations for calcurating sqrt. */
- /* used in VpSqrt() */
-
-/* ETC */
-#define MemCmp(x,y,z) memcmp(x,y,z)
-#define StrCmp(x,y) strcmp(x,y)
-
-static int VpIsDefOP(Real *c,Real *a,Real *b,int sw);
-static int AddExponent(Real *a,S_INT n);
-static U_LONG VpAddAbs(Real *a,Real *b,Real *c);
-static U_LONG VpSubAbs(Real *a,Real *b,Real *c);
-static U_LONG VpSetPTR(Real *a,Real *b,Real *c,U_LONG *a_pos,U_LONG *b_pos,U_LONG *c_pos,U_LONG *av,U_LONG *bv);
-static int VpNmlz(Real *a);
-static void VpFormatSt(char *psz,S_INT fFmt);
-static int VpRdup(Real *m,U_LONG ind_m);
-
-#ifdef _DEBUG
-static int gnAlloc=0; /* Memory allocation counter */
-#endif /* _DEBUG */
-
-VP_EXPORT void *
-VpMemAlloc(U_LONG mb)
-{
- void *p = xmalloc((unsigned int)mb);
- if(!p) {
- VpException(VP_EXCEPTION_MEMORY,"failed to allocate memory",1);
- }
- memset(p,0,mb);
-#ifdef _DEBUG
- gnAlloc++; /* Count allocation call */
-#endif /* _DEBUG */
- return p;
-}
-
-VP_EXPORT void
-VpFree(Real *pv)
-{
- if(pv != NULL) {
- xfree(pv);
-#ifdef _DEBUG
- gnAlloc--; /* Decrement allocation count */
- if(gnAlloc==0) {
- printf(" *************** All memories allocated freed ****************");
- getchar();
- }
- if(gnAlloc<0) {
- printf(" ??????????? Too many memory free calls(%d) ?????????????\n",gnAlloc);
- getchar();
- }
-#endif /* _DEBUG */
- }
-}
-
-/*
- * EXCEPTION Handling.
- */
-static unsigned short gfDoException = 0; /* Exception flag */
-
-static unsigned short
-VpGetException (void)
-{
- return gfDoException;
-}
-
-static void
-VpSetException(unsigned short f)
-{
- gfDoException = f;
-}
-
-/* These 2 functions added at v1.1.7 */
-VP_EXPORT U_LONG
-VpGetPrecLimit(void)
-{
- return gnPrecLimit;
-}
-
-VP_EXPORT U_LONG
-VpSetPrecLimit(U_LONG n)
-{
- U_LONG s = gnPrecLimit;
- gnPrecLimit = n;
- return s;
-}
-
-VP_EXPORT unsigned long
-VpGetRoundMode(void)
-{
- return gfRoundMode;
-}
-
-VP_EXPORT int
-VpIsRoundMode(unsigned long n)
-{
- if(n==VP_ROUND_UP || n!=VP_ROUND_DOWN ||
- n==VP_ROUND_HALF_UP || n!=VP_ROUND_HALF_DOWN ||
- n==VP_ROUND_CEIL || n!=VP_ROUND_FLOOR ||
- n==VP_ROUND_HALF_EVEN
- ) return 1;
- return 0;
-}
-
-VP_EXPORT unsigned long
-VpSetRoundMode(unsigned long n)
-{
- if(VpIsRoundMode(n)) gfRoundMode = n;
- return gfRoundMode;
-}
-
-/*
- * 0.0 & 1.0 generator
- * These gZero_..... and gOne_..... can be any name
- * referenced from nowhere except Zero() and One().
- * gZero_..... and gOne_..... must have global scope
- * (to let the compiler know they may be changed in outside
- * (... but not actually..)).
- */
-volatile double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
-volatile double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
-static double
-Zero(void)
-{
- return gZero_ABCED9B1_CE73__00400511F31D;
-}
-
-static double
-One(void)
-{
- return gOne_ABCED9B4_CE73__00400511F31D;
-}
-
-VP_EXPORT U_LONG
-VpBaseFig(void)
-{
- return BASE_FIG;
-}
-
-VP_EXPORT U_LONG
-VpDblFig(void)
-{
- return DBLE_FIG;
-}
-
-VP_EXPORT U_LONG
-VpBaseVal(void)
-{
- return BASE;
-}
-
-/*
- ----------------------------------------------------------------
- Value of sign in Real structure is reserved for future use.
- short sign;
- ==0 : NaN
- 1 : Positive zero
- -1 : Negative zero
- 2 : Positive number
- -2 : Negative number
- 3 : Positive infinite number
- -3 : Negative infinite number
- ----------------------------------------------------------------
-*/
-
-VP_EXPORT double
-VpGetDoubleNaN(void) /* Returns the value of NaN */
-{
- static double fNaN = 0.0;
- if(fNaN==0.0) fNaN = Zero()/Zero();
- return fNaN;
-}
-
-VP_EXPORT double
-VpGetDoublePosInf(void) /* Returns the value of +Infinity */
-{
- static double fInf = 0.0;
- if(fInf==0.0) fInf = One()/Zero();
- return fInf;
-}
-
-VP_EXPORT double
-VpGetDoubleNegInf(void) /* Returns the value of -Infinity */
-{
- static double fInf = 0.0;
- if(fInf==0.0) fInf = -(One()/Zero());
- return fInf;
-}
-
-VP_EXPORT double
-VpGetDoubleNegZero(void) /* Returns the value of -0 */
-{
- static double nzero = 1000.0;
- if(nzero!=0.0) nzero = (One()/VpGetDoubleNegInf());
- return nzero;
-}
-
-VP_EXPORT int
-VpIsNegDoubleZero(double v)
-{
- double z = VpGetDoubleNegZero();
- return MemCmp(&v,&z,sizeof(v))==0;
-}
-
-VP_EXPORT int
-VpException(unsigned short f,char *str,int always)
-{
- VALUE exc;
- int fatal=0;
-
- if(f==VP_EXCEPTION_OP || f==VP_EXCEPTION_MEMORY) always = 1;
-
- if(always||(gfDoException&f)) {
- switch(f)
- {
- /*
- case VP_EXCEPTION_ZERODIVIDE:
- case VP_EXCEPTION_OVERFLOW:
- */
- case VP_EXCEPTION_INFINITY:
- exc = rb_eFloatDomainError;
- goto raise;
- case VP_EXCEPTION_NaN:
- exc = rb_eFloatDomainError;
- goto raise;
- case VP_EXCEPTION_UNDERFLOW:
- exc = rb_eFloatDomainError;
- goto raise;
- case VP_EXCEPTION_OP:
- exc = rb_eFloatDomainError;
- goto raise;
- case VP_EXCEPTION_MEMORY:
- fatal = 1;
- goto raise;
- default:
- fatal = 1;
- goto raise;
- }
- }
- return 0; /* 0 Means VpException() raised no exception */
-
-raise:
- if(fatal) rb_fatal(str);
- else rb_raise(exc,str);
- return 0;
-}
-
-/* Throw exception or returns 0,when resulting c is Inf or NaN */
-/* sw=1:+ 2:- 3:* 4:/ */
-static int
-VpIsDefOP(Real *c,Real *a,Real *b,int sw)
-{
- if(VpIsNaN(a) || VpIsNaN(b)) {
- /* at least a or b is NaN */
- VpSetNaN(c);
- goto NaN;
- }
-
- if(VpIsInf(a)) {
- if(VpIsInf(b)) {
- switch(sw)
- {
- case 1: /* + */
- if(VpGetSign(a)==VpGetSign(b)) {
- VpSetInf(c,VpGetSign(a));
- goto Inf;
- } else {
- VpSetNaN(c);
- goto NaN;
- }
- case 2: /* - */
- if(VpGetSign(a)!=VpGetSign(b)) {
- VpSetInf(c,VpGetSign(a));
- goto Inf;
- } else {
- VpSetNaN(c);
- goto NaN;
- }
- break;
- case 3: /* * */
- VpSetInf(c,VpGetSign(a)*VpGetSign(b));
- goto Inf;
- break;
- case 4: /* / */
- VpSetNaN(c);
- goto NaN;
- }
- VpSetNaN(c);
- goto NaN;
- }
- /* Inf op Finite */
- switch(sw)
- {
- case 1: /* + */
- case 2: /* - */
- VpSetInf(c,VpGetSign(a));
- break;
- case 3: /* * */
- if(VpIsZero(b)) {
- VpSetNaN(c);
- goto NaN;
- }
- VpSetInf(c,VpGetSign(a)*VpGetSign(b));
- break;
- case 4: /* / */
- VpSetInf(c,VpGetSign(a)*VpGetSign(b));
- }
- goto Inf;
- }
-
- if(VpIsInf(b)) {
- switch(sw)
- {
- case 1: /* + */
- VpSetInf(c,VpGetSign(b));
- break;
- case 2: /* - */
- VpSetInf(c,-VpGetSign(b));
- break;
- case 3: /* * */
- if(VpIsZero(a)) {
- VpSetNaN(c);
- goto NaN;
- }
- VpSetInf(c,VpGetSign(a)*VpGetSign(b));
- break;
- case 4: /* / */
- VpSetZero(c,VpGetSign(a)*VpGetSign(b));
- }
- goto Inf;
- }
- return 1; /* Results OK */
-
-Inf:
- return VpException(VP_EXCEPTION_INFINITY,"Computation results to 'Infinity'",0);
-NaN:
- return VpException(VP_EXCEPTION_NaN,"Computation results to 'NaN'",0);
-}
-
-/*
- ----------------------------------------------------------------
-*/
-
-/*
- * returns number of chars needed to represent vp in specified format.
- */
-VP_EXPORT U_LONG
-VpNumOfChars(Real *vp,char *pszFmt)
-{
- S_INT ex;
- U_LONG nc;
-
- if(vp == NULL) return BASE_FIG*2+6;
- if(!VpIsDef(vp)) return 32; /* not sure,may be OK */
-
- switch(*pszFmt)
- {
- case 'F':
- nc = BASE_FIG*(vp->Prec + 1)+2;
- ex = vp->exponent;
- if(ex<0) {
- nc += BASE_FIG*(-ex);
- } else {
- if(ex > (S_INT)vp->Prec) {
- nc += BASE_FIG*(ex - (S_INT)vp->Prec);
- }
- }
- break;
- case 'E':
- default:
- nc = BASE_FIG*(vp->Prec + 2)+6; /* 3: sign + exponent chars */
- }
- return nc;
-}
-
-/*
- * Initializer for Vp routines and constants used.
- * [Input]
- * BaseVal: Base value(assigned to BASE) for Vp calculation.
- * It must be the form BaseVal=10**n.(n=1,2,3,...)
- * If Base <= 0L,then the BASE will be calcurated so
- * that BASE is as large as possible satisfying the
- * relation MaxVal <= BASE*(BASE+1). Where the value
- * MaxVal is the largest value which can be represented
- * by one U_LONG word(LONG) in the computer used.
- *
- * [Returns]
- * DBLE_FIG ... OK
- */
-VP_EXPORT U_LONG
-VpInit(U_LONG BaseVal)
-{
- U_LONG w;
- double v;
-
- /* Setup +/- Inf NaN -0 */
- VpGetDoubleNaN();
- VpGetDoublePosInf();
- VpGetDoubleNegInf();
- VpGetDoubleNegZero();
-
- if(BaseVal <= 0) {
- /* Base <= 0, then determine Base by calcuration. */
- BASE = 1;
- while(
- (BASE > 0) &&
- ((w = BASE *(BASE + 1)) > BASE) &&((w / BASE) ==(BASE + 1))
- ) {
- BaseVal = BASE;
- BASE = BaseVal * 10L;
- }
- }
- /* Set Base Values */
- BASE = BaseVal;
- HALF_BASE = BASE / 2;
- BASE1 = BASE / 10;
- BASE_FIG = 0;
- while(BaseVal /= 10) ++BASE_FIG;
- /* Allocates Vp constants. */
- VpConstOne = VpAlloc((U_LONG)1, "1");
- VpPt5 = VpAlloc((U_LONG)1, ".5");
-
-#ifdef _DEBUG
- gnAlloc = 0;
-#endif /* _DEBUG */
-
- /* Determine # of digits available in one 'double'. */
-
- v = 1.0;
- DBLE_FIG = 0;
- while(v + 1.0 > 1.0) {
- ++DBLE_FIG;
- v /= 10;
- }
-
-#ifdef _DEBUG
- if(gfDebug) {
- printf("VpInit: BaseVal = %lu\n", BaseVal);
- printf(" BASE = %lu\n", BASE);
- printf(" HALF_BASE = %lu\n", HALF_BASE);
- printf(" BASE1 = %lu\n", BASE1);
- printf(" BASE_FIG = %lu\n", BASE_FIG);
- printf(" DBLE_FIG = %lu\n", DBLE_FIG);
- }
-#endif /* _DEBUG */
-
- return DBLE_FIG;
-}
-
-VP_EXPORT Real *
-VpOne()
-{
- return VpConstOne;
-}
-
-/* If exponent overflows,then raise exception or returns 0 */
-static int
-AddExponent(Real *a,S_INT n)
-{
- S_INT e = a->exponent;
- S_INT m = e+n;
- S_INT eb,mb;
- if(e>0) {
- if(n>0) {
- mb = m*BASE_FIG;
- eb = e*BASE_FIG;
- if(mb<eb) goto overflow;
- }
- } else if(n<0) {
- mb = m*BASE_FIG;
- eb = e*BASE_FIG;
- if(mb>eb) goto underflow;
- }
- a->exponent = m;
- return 1;
-
-/* Overflow/Underflow ==> Raise exception or returns 0 */
-underflow:
- VpSetZero(a,VpGetSign(a));
- return VpException(VP_EXCEPTION_UNDERFLOW,"Exponent underflow",0);
-
-overflow:
- VpSetInf(a,VpGetSign(a));
- return VpException(VP_EXCEPTION_OVERFLOW,"Exponent overflow",0);
-}
-
-/*
- * Allocates variable.
- * [Input]
- * mx ... allocation unit, if zero then mx is determined by szVal.
- * The mx is the number of effective digits can to be stored.
- * szVal ... value assigned(char). If szVal==NULL,then zero is assumed.
- * If szVal[0]=='#' then Max. Prec. will not be considered(1.1.7),
- * full precision specified by szVal is allocated.
- *
- * [Returns]
- * Pointer to the newly allocated variable, or
- * NULL be returned if memory allocation is failed,or any error.
- */
-VP_EXPORT Real *
-VpAlloc(U_LONG mx, char *szVal)
-{
- U_LONG i, ni, ipn, ipf, nf, ipe, ne, nalloc;
- char v,*psz;
- int sign=1;
- Real *vp = NULL;
- U_LONG mf = VpGetPrecLimit();
-
- mx = (mx + BASE_FIG - 1) / BASE_FIG + 1; /* Determine allocation unit. */
- if(szVal) {
- while(ISSPACE(*szVal)) szVal++;
- if(*szVal!='#') {
- if(mf) {
- mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
- if(mx>mf) {
- mx = mf;
- }
- }
- } else {
- ++szVal;
- }
- } else {
- /* necessary to be able to store */
- /* at least mx digits. */
- /* szVal==NULL ==> allocate zero value. */
- vp = (Real *) VpMemAlloc(sizeof(Real) + mx * sizeof(U_LONG));
- /* xmalloc() alway returns(or throw interruption) */
- vp->MaxPrec = mx; /* set max precision */
- VpSetZero(vp,1); /* initialize vp to zero. */
- return vp;
- }
-
- /* Skip all '_' after digit: 2006-6-30 */
- ni = 0;
- psz = ALLOCA_N(char,strlen(szVal)+1);
- i = 0;
- ipn = 0;
- while(psz[i]=szVal[ipn]) {
- if(ISDIGIT(psz[i])) ++ni;
- if(psz[i]=='_') {
- if(ni>0) {ipn++;continue;}
- psz[i]=0;
- break;
- }
- ++i; ++ipn;
- }
- /* Skip trailing spaces */
- while((--i)>0) {
- if(ISSPACE(psz[i])) psz[i] = 0;
- else break;
- }
- szVal = psz;
-
- /* Check on Inf & NaN */
- if(StrCmp(szVal,SZ_PINF)==0 ||
- StrCmp(szVal,SZ_INF)==0 ) {
- vp = (Real *) VpMemAlloc(sizeof(Real) + sizeof(U_LONG));
- vp->MaxPrec = 1; /* set max precision */
- VpSetPosInf(vp);
- return vp;
- }
- if(StrCmp(szVal,SZ_NINF)==0) {
- vp = (Real *) VpMemAlloc(sizeof(Real) + sizeof(U_LONG));
- vp->MaxPrec = 1; /* set max precision */
- VpSetNegInf(vp);
- return vp;
- }
- if(StrCmp(szVal,SZ_NaN)==0) {
- vp = (Real *) VpMemAlloc(sizeof(Real) + sizeof(U_LONG));
- vp->MaxPrec = 1; /* set max precision */
- VpSetNaN(vp);
- return vp;
- }
-
- /* check on number szVal[] */
- ipn = i = 0;
- if (szVal[i] == '-') {sign=-1;++i;}
- else if(szVal[i] == '+') ++i;
- /* Skip digits */
- ni = 0; /* digits in mantissa */
- while(v = szVal[i]) {
- if(!ISDIGIT(v)) break;
- ++i;
- ++ni;
- }
- nf = 0;
- ipf = 0;
- ipe = 0;
- ne = 0;
- if(v) {
- /* other than digit nor \0 */
- if(szVal[i] == '.') { /* xxx. */
- ++i;
- ipf = i;
- while(v = szVal[i]) { /* get fraction part. */
- if(!ISDIGIT(v)) break;
- ++i;
- ++nf;
- }
- }
- ipe = 0; /* Exponent */
-
- switch(szVal[i]) {
- case '\0': break;
- case 'e':
- case 'E':
- case 'd':
- case 'D':
- ++i;
- ipe = i;
- v = szVal[i];
- if((v == '-') ||(v == '+')) ++i;
- while(v=szVal[i]) {
- if(!ISDIGIT(v)) break;
- ++i;
- ++ne;
- }
- break;
- default:
- break;
- }
- }
- nalloc =(ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
- /* units for szVal[] */
- if(mx <= 0) mx = 1;
- nalloc = Max(nalloc, mx);
- mx = nalloc;
- vp =(Real *) VpMemAlloc(sizeof(Real) + mx * sizeof(U_LONG));
- /* xmalloc() alway returns(or throw interruption) */
- vp->MaxPrec = mx; /* set max precision */
- VpSetZero(vp,sign);
- VpCtoV(vp, &(szVal[ipn]), ni, &(szVal[ipf]), nf, &(szVal[ipe]), ne);
- return vp;
-}
-
-/*
- * Assignment(c=a).
- * [Input]
- * a ... RHSV
- * isw ... switch for assignment.
- * c = a when isw > 0
- * c = -a when isw < 0
- * if c->MaxPrec < a->Prec,then round operation
- * will be performed.
- * [Output]
- * c ... LHSV
- */
-VP_EXPORT int
-VpAsgn(Real *c, Real *a, int isw)
-{
- U_LONG n;
- if(VpIsNaN(a)) {
- VpSetNaN(c);
- return 0;
- }
- if(VpIsInf(a)) {
- VpSetInf(c,isw*VpGetSign(a));
- return 0;
- }
-
- /* check if the RHS is zero */
- if(!VpIsZero(a)) {
- c->exponent = a->exponent; /* store exponent */
- VpSetSign(c,(isw*VpGetSign(a))); /* set sign */
- n =(a->Prec < c->MaxPrec) ?(a->Prec) :(c->MaxPrec);
- c->Prec = n;
- memcpy(c->frac, a->frac, n * sizeof(U_LONG));
- /* Needs round ? */
- if(isw!=10) {
- /* Not in ActiveRound */
- if(c->Prec < a->Prec) {
- VpInternalRound(c,n,(n>0)?a->frac[n-1]:0,a->frac[n]);
- } else {
- VpLimitRound(c,0);
- }
- }
- } else {
- /* The value of 'a' is zero. */
- VpSetZero(c,isw*VpGetSign(a));
- return 1;
- }
- return c->Prec*BASE_FIG;
-}
-
-/*
- * c = a + b when operation = 1 or 2
- * = a - b when operation = -1 or -2.
- * Returns number of significant digits of c
- */
-VP_EXPORT int
-VpAddSub(Real *c, Real *a, Real *b, int operation)
-{
- S_INT sw, isw;
- Real *a_ptr, *b_ptr;
- U_LONG n, na, nb, i;
- U_LONG mrv;
-
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, "VpAddSub(enter) a=% \n", a);
- VPrint(stdout, " b=% \n", b);
- printf(" operation=%d\n", operation);
- }
-#endif /* _DEBUG */
-
- if(!VpIsDefOP(c,a,b,(operation>0)?1:2)) return 0; /* No significant digits */
-
- /* check if a or b is zero */
- if(VpIsZero(a)) {
- /* a is zero,then assign b to c */
- if(!VpIsZero(b)) {
- VpAsgn(c, b, operation);
- } else {
- /* Both a and b are zero. */
- if(VpGetSign(a)<0 && operation*VpGetSign(b)<0) {
- /* -0 -0 */
- VpSetZero(c,-1);
- } else {
- VpSetZero(c,1);
- }
- return 1; /* 0: 1 significant digits */
- }
- return c->Prec*BASE_FIG;
- }
- if(VpIsZero(b)) {
- /* b is zero,then assign a to c. */
- VpAsgn(c, a, 1);
- return c->Prec*BASE_FIG;
- }
-
- if(operation < 0) sw = -1;
- else sw = 1;
-
- /* compare absolute value. As a result,|a_ptr|>=|b_ptr| */
- if(a->exponent > b->exponent) {
- a_ptr = a;
- b_ptr = b;
- } /* |a|>|b| */
- else if(a->exponent < b->exponent) {
- a_ptr = b;
- b_ptr = a;
- } /* |a|<|b| */
- else {
- /* Exponent part of a and b is the same,then compare fraction */
- /* part */
- na = a->Prec;
- nb = b->Prec;
- n = Min(na, nb);
- for(i=0;i < n; ++i) {
- if(a->frac[i] > b->frac[i]) {
- a_ptr = a;
- b_ptr = b;
- goto end_if;
- } else if(a->frac[i] < b->frac[i]) {
- a_ptr = b;
- b_ptr = a;
- goto end_if;
- }
- }
- if(na > nb) {
- a_ptr = a;
- b_ptr = b;
- goto end_if;
- } else if(na < nb) {
- a_ptr = b;
- b_ptr = a;
- goto end_if;
- }
- /* |a| == |b| */
- if(VpGetSign(a) + sw *VpGetSign(b) == 0) {
- VpSetZero(c,1); /* abs(a)=abs(b) and operation = '-' */
- return c->Prec*BASE_FIG;
- }
- a_ptr = a;
- b_ptr = b;
- }
-
-end_if:
- isw = VpGetSign(a) + sw *VpGetSign(b);
- /*
- * isw = 0 ...( 1)+(-1),( 1)-( 1),(-1)+(1),(-1)-(-1)
- * = 2 ...( 1)+( 1),( 1)-(-1)
- * =-2 ...(-1)+(-1),(-1)-( 1)
- * If isw==0, then c =(Sign a_ptr)(|a_ptr|-|b_ptr|)
- * else c =(Sign ofisw)(|a_ptr|+|b_ptr|)
- */
- if(isw) { /* addition */
- VpSetSign(c,(S_INT)1);
- mrv = VpAddAbs(a_ptr, b_ptr, c);
- VpSetSign(c,isw / 2);
- } else { /* subtraction */
- VpSetSign(c,(S_INT)1);
- mrv = VpSubAbs(a_ptr, b_ptr, c);
- if(a_ptr == a) {
- VpSetSign(c,VpGetSign(a));
- } else {
- VpSetSign(c,VpGetSign(a_ptr) * sw);
- }
- }
- VpInternalRound(c,0,(c->Prec>0)?c->frac[c->Prec-1]:0,mrv);
-
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, "VpAddSub(result) c=% \n", c);
- VPrint(stdout, " a=% \n", a);
- VPrint(stdout, " b=% \n", b);
- printf(" operation=%d\n", operation);
- }
-#endif /* _DEBUG */
- return c->Prec*BASE_FIG;
-}
-
-/*
- * Addition of two variable precisional variables
- * a and b assuming abs(a)>abs(b).
- * c = abs(a) + abs(b) ; where |a|>=|b|
- */
-static U_LONG
-VpAddAbs(Real *a, Real *b, Real *c)
-{
- U_LONG word_shift;
- U_LONG carry;
- U_LONG ap;
- U_LONG bp;
- U_LONG cp;
- U_LONG a_pos;
- U_LONG b_pos;
- U_LONG c_pos;
- U_LONG av, bv, mrv;
-
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, "VpAddAbs called: a = %\n", a);
- VPrint(stdout, " b = %\n", b);
- }
-#endif /* _DEBUG */
-
- word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
- a_pos = ap;
- b_pos = bp;
- c_pos = cp;
- if(word_shift==-1L) return 0; /* Overflow */
- if(b_pos == -1L) goto Assign_a;
-
- mrv = av + bv; /* Most right val. Used for round. */
-
- /* Just assign the last few digits of b to c because a has no */
- /* corresponding digits to be added. */
- while(b_pos + word_shift > a_pos) {
- --c_pos;
- if(b_pos > 0) {
- c->frac[c_pos] = b->frac[--b_pos];
- } else {
- --word_shift;
- c->frac[c_pos] = 0;
- }
- }
-
- /* Just assign the last few digits of a to c because b has no */
- /* corresponding digits to be added. */
- bv = b_pos + word_shift;
- while(a_pos > bv) {
- c->frac[--c_pos] = a->frac[--a_pos];
- }
- carry = 0; /* set first carry be zero */
-
- /* Now perform addition until every digits of b will be */
- /* exhausted. */
- while(b_pos > 0) {
- c->frac[--c_pos] = a->frac[--a_pos] + b->frac[--b_pos] + carry;
- if(c->frac[c_pos] >= BASE) {
- c->frac[c_pos] -= BASE;
- carry = 1;
- } else {
- carry = 0;
- }
- }
-
- /* Just assign the first few digits of a with considering */
- /* the carry obtained so far because b has been exhausted. */
- while(a_pos > 0) {
- c->frac[--c_pos] = a->frac[--a_pos] + carry;
- if(c->frac[c_pos] >= BASE) {
- c->frac[c_pos] -= BASE;
- carry = 1;
- } else {
- carry = 0;
- }
- }
- if(c_pos) c->frac[c_pos - 1] += carry;
- goto Exit;
-
-Assign_a:
- VpAsgn(c, a, 1);
- mrv = 0;
-
-Exit:
-
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, "VpAddAbs exit: c=% \n", c);
- }
-#endif /* _DEBUG */
- return mrv;
-}
-
-/*
- * c = abs(a) - abs(b)
- */
-static U_LONG
-VpSubAbs(Real *a, Real *b, Real *c)
-{
- U_LONG word_shift;
- U_LONG mrv;
- U_LONG borrow;
- U_LONG ap;
- U_LONG bp;
- U_LONG cp;
- U_LONG a_pos;
- U_LONG b_pos;
- U_LONG c_pos;
- U_LONG av, bv;
-
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, "VpSubAbs called: a = %\n", a);
- VPrint(stdout, " b = %\n", b);
- }
-#endif /* _DEBUG */
-
- word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
- a_pos = ap;
- b_pos = bp;
- c_pos = cp;
- if(word_shift==-1L) return 0; /* Overflow */
- if(b_pos == -1L) goto Assign_a;
-
- if(av >= bv) {
- mrv = av - bv;
- borrow = 0;
- } else {
- mrv = 0;
- borrow = 1;
- }
-
- /* Just assign the values which are the BASE subtracted by */
- /* each of the last few digits of the b because the a has no */
- /* corresponding digits to be subtracted. */
- if(b_pos + word_shift > a_pos) {
- while(b_pos + word_shift > a_pos) {
- --c_pos;
- if(b_pos > 0) {
- c->frac[c_pos] = BASE - b->frac[--b_pos] - borrow;
- } else {
- --word_shift;
- c->frac[c_pos] = BASE - borrow;
- }
- borrow = 1;
- }
- }
- /* Just assign the last few digits of a to c because b has no */
- /* corresponding digits to subtract. */
-
- bv = b_pos + word_shift;
- while(a_pos > bv) {
- c->frac[--c_pos] = a->frac[--a_pos];
- }
-
- /* Now perform subtraction until every digits of b will be */
- /* exhausted. */
- while(b_pos > 0) {
- --c_pos;
- if(a->frac[--a_pos] < b->frac[--b_pos] + borrow) {
- c->frac[c_pos] = BASE + a->frac[a_pos] - b->frac[b_pos] - borrow;
- borrow = 1;
- } else {
- c->frac[c_pos] = a->frac[a_pos] - b->frac[b_pos] - borrow;
- borrow = 0;
- }
- }
-
- /* Just assign the first few digits of a with considering */
- /* the borrow obtained so far because b has been exhausted. */
- while(a_pos > 0) {
- --c_pos;
- if(a->frac[--a_pos] < borrow) {
- c->frac[c_pos] = BASE + a->frac[a_pos] - borrow;
- borrow = 1;
- } else {
- c->frac[c_pos] = a->frac[a_pos] - borrow;
- borrow = 0;
- }
- }
- if(c_pos) c->frac[c_pos - 1] -= borrow;
- goto Exit;
-
-Assign_a:
- VpAsgn(c, a, 1);
- mrv = 0;
-
-Exit:
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, "VpSubAbs exit: c=% \n", c);
- }
-#endif /* _DEBUG */
- return mrv;
-}
-
-/*
- * Note: If(av+bv)>= HALF_BASE,then 1 will be added to the least significant
- * digit of c(In case of addition).
- * ------------------------- figure of output -----------------------------------
- * a = xxxxxxxxxxx
- * b = xxxxxxxxxx
- * c =xxxxxxxxxxxxxxx
- * word_shift = | |
- * right_word = | | (Total digits in RHSV)
- * left_word = | | (Total digits in LHSV)
- * a_pos = |
- * b_pos = |
- * c_pos = |
- */
-static U_LONG
-VpSetPTR(Real *a, Real *b, Real *c, U_LONG *a_pos, U_LONG *b_pos, U_LONG *c_pos, U_LONG *av, U_LONG *bv)
-{
- U_LONG left_word, right_word, word_shift;
- c->frac[0] = 0;
- *av = *bv = 0;
- word_shift =((a->exponent) -(b->exponent));
- left_word = b->Prec + word_shift;
- right_word = Max((a->Prec),left_word);
- left_word =(c->MaxPrec) - 1; /* -1 ... prepare for round up */
- /*
- * check if 'round' is needed.
- */
- if(right_word > left_word) { /* round ? */
- /*---------------------------------
- * Actual size of a = xxxxxxAxx
- * Actual size of b = xxxBxxxxx
- * Max. size of c = xxxxxx
- * Round off = |-----|
- * c_pos = |
- * right_word = |
- * a_pos = |
- */
- *c_pos = right_word = left_word + 1; /* Set resulting precision */
- /* be equal to that of c */
- if((a->Prec) >=(c->MaxPrec)) {
- /*
- * a = xxxxxxAxxx
- * c = xxxxxx
- * a_pos = |
- */
- *a_pos = left_word;
- *av = a->frac[*a_pos]; /* av is 'A' shown in above. */
- } else {
- /*
- * a = xxxxxxx
- * c = xxxxxxxxxx
- * a_pos = |
- */
- *a_pos = a->Prec;
- }
- if((b->Prec + word_shift) >= c->MaxPrec) {
- /*
- * a = xxxxxxxxx
- * b = xxxxxxxBxxx
- * c = xxxxxxxxxxx
- * b_pos = |
- */
- if(c->MaxPrec >=(word_shift + 1)) {
- *b_pos = c->MaxPrec - word_shift - 1;
- *bv = b->frac[*b_pos];
- } else {
- *b_pos = -1L;
- }
- } else {
- /*
- * a = xxxxxxxxxxxxxxxx
- * b = xxxxxx
- * c = xxxxxxxxxxxxx
- * b_pos = |
- */
- *b_pos = b->Prec;
- }
- } else { /* The MaxPrec of c - 1 > The Prec of a + b */
- /*
- * a = xxxxxxx
- * b = xxxxxx
- * c = xxxxxxxxxxx
- * c_pos = |
- */
- *b_pos = b->Prec;
- *a_pos = a->Prec;
- *c_pos = right_word + 1;
- }
- c->Prec = *c_pos;
- c->exponent = a->exponent;
- if(!AddExponent(c,(S_LONG)1)) return (-1L);
- return word_shift;
-}
-
-/*
- * Return number og significant digits
- * c = a * b , Where a = a0a1a2 ... an
- * b = b0b1b2 ... bm
- * c = c0c1c2 ... cl
- * a0 a1 ... an * bm
- * a0 a1 ... an * bm-1
- * . . .
- * . . .
- * a0 a1 .... an * b0
- * +_____________________________
- * c0 c1 c2 ...... cl
- * nc <---|
- * MaxAB |--------------------|
- */
-VP_EXPORT int
-VpMult(Real *c, Real *a, Real *b)
-{
- U_LONG MxIndA, MxIndB, MxIndAB, MxIndC;
- U_LONG ind_c, i, ii, nc;
- U_LONG ind_as, ind_ae, ind_bs, ind_be;
- U_LONG Carry, s;
- Real *w;
-
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, "VpMult(Enter): a=% \n", a);
- VPrint(stdout, " b=% \n", b);
- }
-#endif /* _DEBUG */
-
- if(!VpIsDefOP(c,a,b,3)) return 0; /* No significant digit */
-
- if(VpIsZero(a) || VpIsZero(b)) {
- /* at least a or b is zero */
- VpSetZero(c,VpGetSign(a)*VpGetSign(b));
- return 1; /* 0: 1 significant digit */
- }
-
- if(VpIsOne(a)) {
- VpAsgn(c, b, VpGetSign(a));
- goto Exit;
- }
- if(VpIsOne(b)) {
- VpAsgn(c, a, VpGetSign(b));
- goto Exit;
- }
- if((b->Prec) >(a->Prec)) {
- /* Adjust so that digits(a)>digits(b) */
- w = a;
- a = b;
- b = w;
- }
- w = NULL;
- MxIndA = a->Prec - 1;
- MxIndB = b->Prec - 1;
- MxIndC = c->MaxPrec - 1;
- MxIndAB = a->Prec + b->Prec - 1;
-
- if(MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */
- w = c;
- c = VpAlloc((U_LONG)((MxIndAB + 1) * BASE_FIG), "#0");
- MxIndC = MxIndAB;
- }
-
- /* set LHSV c info */
-
- c->exponent = a->exponent; /* set exponent */
- if(!AddExponent(c,b->exponent)) return 0;
- VpSetSign(c,VpGetSign(a)*VpGetSign(b)); /* set sign */
- Carry = 0;
- nc = ind_c = MxIndAB;
- memset(c->frac, 0, (nc + 1) * sizeof(U_LONG)); /* Initialize c */
- c->Prec = nc + 1; /* set precision */
- for(nc = 0; nc < MxIndAB; ++nc, --ind_c) {
- if(nc < MxIndB) { /* The left triangle of the Fig. */
- ind_as = MxIndA - nc;
- ind_ae = MxIndA;
- ind_bs = MxIndB;
- ind_be = MxIndB - nc;
- } else if(nc <= MxIndA) { /* The middle rectangular of the Fig. */
- ind_as = MxIndA - nc;
- ind_ae = MxIndA -(nc - MxIndB);
- ind_bs = MxIndB;
- ind_be = 0;
- } else if(nc > MxIndA) { /* The right triangle of the Fig. */
- ind_as = 0;
- ind_ae = MxIndAB - nc - 1;
- ind_bs = MxIndB -(nc - MxIndA);
- ind_be = 0;
- }
-
- for(i = ind_as; i <= ind_ae; ++i) {
- s =((a->frac[i]) *(b->frac[ind_bs--]));
- Carry = s / BASE;
- s = s -(Carry * BASE);
- c->frac[ind_c] += s;
- if(c->frac[ind_c] >= BASE) {
- s = c->frac[ind_c] / BASE;
- Carry += s;
- c->frac[ind_c] -= (s * BASE);
- }
- if(Carry) {
- ii = ind_c;
- while((--ii) >= 0) {
- c->frac[ii] += Carry;
- if(c->frac[ii] >= BASE) {
- Carry = c->frac[ii] / BASE;
- c->frac[ii] -=(Carry * BASE);
- } else {
- break;
- }
- }
- }
- }
- }
- if(w != NULL) { /* free work variable */
- VpNmlz(c);
- VpAsgn(w, c, 1);
- VpFree(c);
- c = w;
- } else {
- VpLimitRound(c,0);
- }
-
-Exit:
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, "VpMult(c=a*b): c=% \n", c);
- VPrint(stdout, " a=% \n", a);
- VPrint(stdout, " b=% \n", b);
- }
-#endif /*_DEBUG */
- return c->Prec*BASE_FIG;
-}
-
-/*
- * c = a / b, remainder = r
- */
-VP_EXPORT int
-VpDivd(Real *c, Real *r, Real *a, Real *b)
-{
- U_LONG word_a, word_b, word_c, word_r;
- U_LONG i, n, ind_a, ind_b, ind_c, ind_r;
- U_LONG nLoop;
- U_LONG q, b1, b1p1, b1b2, b1b2p1, r1r2;
- U_LONG borrow, borrow1, borrow2, qb;
-
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, " VpDivd(c=a/b) a=% \n", a);
- VPrint(stdout, " b=% \n", b);
- }
-#endif /*_DEBUG */
-
- VpSetNaN(r);
- if(!VpIsDefOP(c,a,b,4)) goto Exit;
- if(VpIsZero(a)&&VpIsZero(b)) {
- VpSetNaN(c);
- return VpException(VP_EXCEPTION_NaN,"(VpDivd) 0/0 not defined(NaN)",0);
- }
- if(VpIsZero(b)) {
- VpSetInf(c,VpGetSign(a)*VpGetSign(b));
- return VpException(VP_EXCEPTION_ZERODIVIDE,"(VpDivd) Divide by zero",0);
- }
- if(VpIsZero(a)) {
- /* numerator a is zero */
- VpSetZero(c,VpGetSign(a)*VpGetSign(b));
- VpSetZero(r,VpGetSign(a)*VpGetSign(b));
- goto Exit;
- }
- if(VpIsOne(b)) {
- /* divide by one */
- VpAsgn(c, a, VpGetSign(b));
- VpSetZero(r,VpGetSign(a));
- goto Exit;
- }
-
- word_a = a->Prec;
- word_b = b->Prec;
- word_c = c->MaxPrec;
- word_r = r->MaxPrec;
-
- ind_c = 0;
- ind_r = 1;
-
- if(word_a >= word_r) goto space_error;
-
- r->frac[0] = 0;
- while(ind_r <= word_a) {
- r->frac[ind_r] = a->frac[ind_r - 1];
- ++ind_r;
- }
-
- while(ind_r < word_r) r->frac[ind_r++] = 0;
- while(ind_c < word_c) c->frac[ind_c++] = 0;
-
- /* initial procedure */
- b1 = b1p1 = b->frac[0];
- if(b->Prec <= 1) {
- b1b2p1 = b1b2 = b1p1 * BASE;
- } else {
- b1p1 = b1 + 1;
- b1b2p1 = b1b2 = b1 * BASE + b->frac[1];
- if(b->Prec > 2) ++b1b2p1;
- }
-
- /* */
- /* loop start */
- ind_c = word_r - 1;
- nLoop = Min(word_c,ind_c);
- ind_c = 1;
- while(ind_c < nLoop) {
- if(r->frac[ind_c] == 0) {
- ++ind_c;
- continue;
- }
- r1r2 = r->frac[ind_c] * BASE + r->frac[ind_c + 1];
- if(r1r2 == b1b2) {
- /* The first two word digits is the same */
- ind_b = 2;
- ind_a = ind_c + 2;
- while(ind_b < word_b) {
- if(r->frac[ind_a] < b->frac[ind_b]) goto div_b1p1;
- if(r->frac[ind_a] > b->frac[ind_b]) break;
- ++ind_a;
- ++ind_b;
- }
- /* The first few word digits of r and b is the same and */
- /* the first different word digit of w is greater than that */
- /* of b, so quotinet is 1 and just subtract b from r. */
- borrow = 0; /* quotient=1, then just r-b */
- ind_b = b->Prec - 1;
- ind_r = ind_c + ind_b;
- if(ind_r >= word_r) goto space_error;
- n = ind_b;
- for(i = 0; i <= n; ++i) {
- if(r->frac[ind_r] < b->frac[ind_b] + borrow) {
- r->frac[ind_r] +=(BASE -(b->frac[ind_b] + borrow));
- borrow = 1;
- } else {
- r->frac[ind_r] = r->frac[ind_r] - b->frac[ind_b] - borrow;
- borrow = 0;
- }
- --ind_r;
- --ind_b;
- }
- ++(c->frac[ind_c]);
- goto carry;
- }
- /* The first two word digits is not the same, */
- /* then compare magnitude, and divide actually. */
- if(r1r2 >= b1b2p1) {
- q = r1r2 / b1b2p1;
- c->frac[ind_c] += q;
- ind_r = b->Prec + ind_c - 1;
- goto sub_mult;
- }
-
-div_b1p1:
- if(ind_c + 1 >= word_c) goto out_side;
- q = r1r2 / b1p1;
- c->frac[ind_c + 1] += q;
- ind_r = b->Prec + ind_c;
-
-sub_mult:
- borrow1 = borrow2 = 0;
- ind_b = word_b - 1;
- if(ind_r >= word_r) goto space_error;
- n = ind_b;
- for(i = 0; i <= n; ++i) {
- /* now, perform r = r - q * b */
- qb = q *(b->frac[ind_b]);
- if(qb < BASE) borrow1 = 0;
- else {
- borrow1 = qb / BASE;
- qb = qb - borrow1 * BASE;
- }
- if(r->frac[ind_r] < qb) {
- r->frac[ind_r] +=(BASE - qb);
- borrow2 = borrow2 + borrow1 + 1;
- } else {
- r->frac[ind_r] -= qb;
- borrow2 += borrow1;
- }
- if(borrow2) {
- if(r->frac[ind_r - 1] < borrow2) {
- r->frac[ind_r - 1] +=(BASE - borrow2);
- borrow2 = 1;
- } else {
- r->frac[ind_r - 1] -= borrow2;
- borrow2 = 0;
- }
- }
- --ind_r;
- --ind_b;
- }
-
- r->frac[ind_r] -= borrow2;
-carry:
- ind_r = ind_c;
- while(c->frac[ind_r] >= BASE) {
- c->frac[ind_r] -= BASE;
- --ind_r;
- ++(c->frac[ind_r]);
- }
- }
- /* End of operation, now final arrangement */
-out_side:
- c->Prec = word_c;
- c->exponent = a->exponent;
- if(!AddExponent(c,(S_LONG)2)) return 0;
- if(!AddExponent(c,-(b->exponent))) return 0;
-
- VpSetSign(c,VpGetSign(a)*VpGetSign(b));
- VpNmlz(c); /* normalize c */
- r->Prec = word_r;
- r->exponent = a->exponent;
- if(!AddExponent(r,(S_LONG)1)) return 0;
- VpSetSign(r,VpGetSign(a));
- VpNmlz(r); /* normalize r(remainder) */
- goto Exit;
-
-space_error:
-#ifdef _DEBUG
- if(gfDebug) {
- printf(" word_a=%lu\n", word_a);
- printf(" word_b=%lu\n", word_b);
- printf(" word_c=%lu\n", word_c);
- printf(" word_r=%lu\n", word_r);
- printf(" ind_r =%lu\n", ind_r);
- }
-#endif /* _DEBUG */
- rb_bug("ERROR(VpDivd): space for remainder too small.");
-
-Exit:
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, " VpDivd(c=a/b), c=% \n", c);
- VPrint(stdout, " r=% \n", r);
- }
-#endif /* _DEBUG */
- return c->Prec*BASE_FIG;
-}
-
-/*
- * Input a = 00000xxxxxxxx En(5 preceeding zeros)
- * Output a = xxxxxxxx En-5
- */
-static int
-VpNmlz(Real *a)
-{
- U_LONG ind_a, i;
-
- if(!VpIsDef(a)) goto NoVal;
- if(VpIsZero(a)) goto NoVal;
-
- ind_a = a->Prec;
- while(ind_a--) {
- if(a->frac[ind_a]) {
- a->Prec = ind_a + 1;
- i = 0;
- while(a->frac[i] == 0) ++i; /* skip the first few zeros */
- if(i) {
- a->Prec -= i;
- if(!AddExponent(a,-((S_INT)i))) return 0;
- memmove(&(a->frac[0]),&(a->frac[i]),(a->Prec)*sizeof(U_LONG));
- }
- return 1;
- }
- }
- /* a is zero(no non-zero digit) */
- VpSetZero(a,VpGetSign(a));
- return 0;
-
-NoVal:
- a->frac[0] = 0;
- a->Prec=1;
- return 0;
-}
-
-/*
- * VpComp = 0 ... if a=b,
- * Pos ... a>b,
- * Neg ... a<b.
- * 999 ... result undefined(NaN)
- */
-VP_EXPORT int
-VpComp(Real *a, Real *b)
-{
- int val;
- U_LONG mx, ind;
- int e;
- val = 0;
- if(VpIsNaN(a)||VpIsNaN(b)) return 999;
- if(!VpIsDef(a)) {
- if(!VpIsDef(b)) e = a->sign - b->sign;
- else e = a->sign;
- if(e>0) return 1;
- else if(e<0) return -1;
- else return 0;
- }
- if(!VpIsDef(b)) {
- e = -b->sign;
- if(e>0) return 1;
- else return -1;
- }
- /* Zero check */
- if(VpIsZero(a)) {
- if(VpIsZero(b)) return 0; /* both zero */
- val = -VpGetSign(b);
- goto Exit;
- }
- if(VpIsZero(b)) {
- val = VpGetSign(a);
- goto Exit;
- }
-
- /* compare sign */
- if(VpGetSign(a) > VpGetSign(b)) {
- val = 1; /* a>b */
- goto Exit;
- }
- if(VpGetSign(a) < VpGetSign(b)) {
- val = -1; /* a<b */
- goto Exit;
- }
-
- /* a and b have same sign, && signe!=0,then compare exponent */
- if((a->exponent) >(b->exponent)) {
- val = VpGetSign(a);
- goto Exit;
- }
- if((a->exponent) <(b->exponent)) {
- val = -VpGetSign(b);
- goto Exit;
- }
-
- /* a and b have same exponent, then compare significand. */
- mx =((a->Prec) <(b->Prec)) ?(a->Prec) :(b->Prec);
- ind = 0;
- while(ind < mx) {
- if((a->frac[ind]) >(b->frac[ind])) {
- val = VpGetSign(a);
- goto Exit;
- }
- if((a->frac[ind]) <(b->frac[ind])) {
- val = -VpGetSign(b);
- goto Exit;
- }
- ++ind;
- }
- if((a->Prec) >(b->Prec)) {
- val = VpGetSign(a);
- } else if((a->Prec) <(b->Prec)) {
- val = -VpGetSign(b);
- }
-
-Exit:
- if (val> 1) val = 1;
- else if(val<-1) val = -1;
-
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, " VpComp a=%\n", a);
- VPrint(stdout, " b=%\n", b);
- printf(" ans=%d\n", val);
- }
-#endif /* _DEBUG */
- return (int)val;
-}
-
-#ifdef _DEBUG
-/*
- * cntl_chr ... ASCIIZ Character, print control characters
- * Available control codes:
- * % ... VP variable. To print '%', use '%%'.
- * \n ... new line
- * \b ... backspace
- * ... tab
- * Note: % must must not appear more than once
- * a ... VP variable to be printed
- */
-VP_EXPORT int
-VPrint(FILE *fp, char *cntl_chr, Real *a)
-{
- U_LONG i, j, nc, nd, ZeroSup;
- U_LONG n, m, e, nn;
-
- /* Check if NaN & Inf. */
- if(VpIsNaN(a)) {
- fprintf(fp,SZ_NaN);
- return 8;
- }
- if(VpIsPosInf(a)) {
- fprintf(fp,SZ_INF);
- return 8;
- }
- if(VpIsNegInf(a)) {
- fprintf(fp,SZ_NINF);
- return 9;
- }
- if(VpIsZero(a)) {
- fprintf(fp,"0.0");
- return 3;
- }
-
- j = 0;
- nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
- /* nd<=10). */
- /* nc : number of caracters printed */
- ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
- while(*(cntl_chr + j)) {
- if((*(cntl_chr + j) == '%') &&(*(cntl_chr + j + 1) != '%')) {
- nc = 0;
- if(!VpIsZero(a)) {
- if(VpGetSign(a) < 0) {
- fprintf(fp, "-");
- ++nc;
- }
- nc += fprintf(fp, "0.");
- n = a->Prec;
- for(i=0;i < n;++i) {
- m = BASE1;
- e = a->frac[i];
- while(m) {
- nn = e / m;
- if((!ZeroSup) || nn) {
- nc += fprintf(fp, "%lu", nn); /* The reading zero(s) */
- /* as 0.00xx will not */
- /* be printed. */
- ++nd;
- ZeroSup = 0; /* Set to print succeeding zeros */
- }
- if(nd >= 10) { /* print ' ' after every 10 digits */
- nd = 0;
- nc += fprintf(fp, " ");
- }
- e = e - nn * m;
- m /= 10;
- }
- }
- nc += fprintf(fp, "E%ld", VpExponent10(a));
- } else {
- nc += fprintf(fp, "0.0");
- }
- } else {
- ++nc;
- if(*(cntl_chr + j) == '\\') {
- switch(*(cntl_chr + j + 1)) {
- case 'n':
- fprintf(fp, "\n");
- ++j;
- break;
- case 't':
- fprintf(fp, "\t");
- ++j;
- break;
- case 'b':
- fprintf(fp, "\n");
- ++j;
- break;
- default:
- fprintf(fp, "%c", *(cntl_chr + j));
- break;
- }
- } else {
- fprintf(fp, "%c", *(cntl_chr + j));
- if(*(cntl_chr + j) == '%') ++j;
- }
- }
- j++;
- }
- return (int)nc;
-}
-#endif /* _DEBUG */
-
-static void
-VpFormatSt(char *psz,S_INT fFmt)
-{
- U_LONG ie;
- U_LONG i;
- S_INT nf = 0;
- char ch;
-
- if(fFmt<=0) return;
-
- ie = strlen(psz);
- for(i = 0; i < ie; ++i) {
- ch = psz[i];
- if(!ch) break;
- if(ISSPACE(ch) || ch=='-' || ch=='+') continue;
- if(ch == '.') { nf = 0;continue;}
- if(ch == 'E') break;
- nf++;
- if(nf > fFmt) {
- memmove(psz + i + 1, psz + i, ie - i + 1);
- ++ie;
- nf = 0;
- psz[i] = ' ';
- }
- }
-}
-
-VP_EXPORT S_LONG
-VpExponent10(Real *a)
-{
- S_LONG ex;
- U_LONG n;
-
- if(!VpHasVal(a)) return 0;
-
- ex =(a->exponent) * BASE_FIG;
- n = BASE1;
- while((a->frac[0] / n) == 0) {
- --ex;
- n /= 10;
- }
- return ex;
-}
-
-VP_EXPORT void
-VpSzMantissa(Real *a,char *psz)
-{
- U_LONG i, ZeroSup;
- U_LONG n, m, e, nn;
-
- if(VpIsNaN(a)) {
- sprintf(psz,SZ_NaN);
- return;
- }
- if(VpIsPosInf(a)) {
- sprintf(psz,SZ_INF);
- return;
- }
- if(VpIsNegInf(a)) {
- sprintf(psz,SZ_NINF);
- return;
- }
-
- ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
- if(!VpIsZero(a)) {
- if(VpGetSign(a) < 0) *psz++ = '-';
- n = a->Prec;
- for(i=0;i < n;++i) {
- m = BASE1;
- e = a->frac[i];
- while(m) {
- nn = e / m;
- if((!ZeroSup) || nn) {
- sprintf(psz, "%lu", nn); /* The reading zero(s) */
- psz += strlen(psz);
- /* as 0.00xx will be ignored. */
- ZeroSup = 0; /* Set to print succeeding zeros */
- }
- e = e - nn * m;
- m /= 10;
- }
- }
- *psz = 0;
- while(psz[-1]=='0') *(--psz) = 0;
- } else {
- if(VpIsPosZero(a)) sprintf(psz, "0");
- else sprintf(psz, "-0");
- }
-}
-
-VP_EXPORT int
-VpToSpecialString(Real *a,char *psz,int fPlus)
-/* fPlus =0:default, =1: set ' ' before digits , =2: set '+' before digits. */
-{
- if(VpIsNaN(a)) {
- sprintf(psz,SZ_NaN);
- return 1;
- }
-
- if(VpIsPosInf(a)) {
- if(fPlus==1) {
- *psz++ = ' ';
- } else if(fPlus==2) {
- *psz++ = '+';
- }
- sprintf(psz,SZ_INF);
- return 1;
- }
- if(VpIsNegInf(a)) {
- sprintf(psz,SZ_NINF);
- return 1;
- }
- if(VpIsZero(a)) {
- if(VpIsPosZero(a)) {
- if(fPlus==1) sprintf(psz, " 0.0");
- else if(fPlus==2) sprintf(psz, "+0.0");
- else sprintf(psz, "0.0");
- } else sprintf(psz, "-0.0");
- return 1;
- }
- return 0;
-}
-
-VP_EXPORT void
-VpToString(Real *a,char *psz,int fFmt,int fPlus)
-/* fPlus =0:default, =1: set ' ' before digits , =2:set '+' before digits. */
-{
- U_LONG i, ZeroSup;
- U_LONG n, m, e, nn;
- char *pszSav = psz;
- S_LONG ex;
-
- if(VpToSpecialString(a,psz,fPlus)) return;
-
- ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
-
- if(VpGetSign(a) < 0) *psz++ = '-';
- else if(fPlus==1) *psz++ = ' ';
- else if(fPlus==2) *psz++ = '+';
-
- *psz++ = '0';
- *psz++ = '.';
- n = a->Prec;
- for(i=0;i < n;++i) {
- m = BASE1;
- e = a->frac[i];
- while(m) {
- nn = e / m;
- if((!ZeroSup) || nn) {
- sprintf(psz, "%lu", nn); /* The reading zero(s) */
- psz += strlen(psz);
- /* as 0.00xx will be ignored. */
- ZeroSup = 0; /* Set to print succeeding zeros */
- }
- e = e - nn * m;
- m /= 10;
- }
- }
- ex =(a->exponent) * BASE_FIG;
- n = BASE1;
- while((a->frac[0] / n) == 0) {
- --ex;
- n /= 10;
- }
- while(psz[-1]=='0') *(--psz) = 0;
- sprintf(psz, "E%ld", ex);
- if(fFmt) VpFormatSt(pszSav, fFmt);
-}
-
-VP_EXPORT void
-VpToFString(Real *a,char *psz,int fFmt,int fPlus)
-/* fPlus =0:default,=1: set ' ' before digits ,set '+' before digits. */
-{
- U_LONG i;
- U_LONG n, m, e, nn;
- char *pszSav = psz;
- S_LONG ex;
-
- if(VpToSpecialString(a,psz,fPlus)) return;
-
- if(VpGetSign(a) < 0) *psz++ = '-';
- else if(fPlus==1) *psz++ = ' ';
- else if(fPlus==2) *psz++ = '+';
-
- n = a->Prec;
- ex = a->exponent;
- if(ex<=0) {
- *psz++ = '0';*psz++ = '.';
- while(ex<0) {
- for(i=0;i<BASE_FIG;++i) *psz++ = '0';
- ++ex;
- }
- ex = -1;
- }
-
- for(i=0;i < n;++i) {
- --ex;
- if(i==0 && ex >= 0) {
- sprintf(psz, "%lu", a->frac[i]);
- psz += strlen(psz);
- } else {
- m = BASE1;
- e = a->frac[i];
- while(m) {
- nn = e / m;
- *psz++ = (char)(nn + '0');
- e = e - nn * m;
- m /= 10;
- }
- }
- if(ex == 0) *psz++ = '.';
- }
- while(--ex>=0) {
- m = BASE;
- while(m/=10) *psz++ = '0';
- if(ex == 0) *psz++ = '.';
- }
- *psz = 0;
- while(psz[-1]=='0') *(--psz) = 0;
- if(psz[-1]=='.') sprintf(psz, "0");
- if(fFmt) VpFormatSt(pszSav, fFmt);
-}
-
-/*
- * [Output]
- * a[] ... variable to be assigned the value.
- * [Input]
- * int_chr[] ... integer part(may include '+/-').
- * ni ... number of characters in int_chr[],not including '+/-'.
- * frac[] ... fraction part.
- * nf ... number of characters in frac[].
- * exp_chr[] ... exponent part(including '+/-').
- * ne ... number of characters in exp_chr[],not including '+/-'.
- */
-VP_EXPORT int
-VpCtoV(Real *a, char *int_chr, U_LONG ni, char *frac, U_LONG nf, char *exp_chr, U_LONG ne)
-{
- U_LONG i, j, ind_a, ma, mi, me;
- U_LONG loc;
- S_INT e,es, eb, ef;
- S_INT sign, signe;
- /* get exponent part */
- e = 0;
- ma = a->MaxPrec;
- mi = ni;
- me = ne;
- signe = 1;
- memset(a->frac, 0, ma * sizeof(U_LONG));
- if(ne > 0) {
- i = 0;
- if(exp_chr[0] == '-') {
- signe = -1;
- ++i;
- ++me;
- } else if(exp_chr[0] == '+') {
- ++i;
- ++me;
- }
- while(i < me) {
- es = e*((S_INT)BASE_FIG);
- e = e * 10 + exp_chr[i] - '0';
- if(es>e*((S_INT)BASE_FIG)) {
- return VpException(VP_EXCEPTION_INFINITY,"exponent overflow",0);
- }
- ++i;
- }
- }
-
- /* get integer part */
- i = 0;
- sign = 1;
- if(ni > 0) {
- if(int_chr[0] == '-') {
- sign = -1;
- ++i;
- ++mi;
- } else if(int_chr[0] == '+') {
- ++i;
- ++mi;
- }
- }
-
- e = signe * e; /* e: The value of exponent part. */
- e = e + ni; /* set actual exponent size. */
-
- if(e > 0) signe = 1;
- else signe = -1;
-
- /* Adjust the exponent so that it is the multiple of BASE_FIG. */
- j = 0;
- ef = 1;
- while(ef) {
- if(e>=0) eb = e;
- else eb = -e;
- ef = eb / ((S_INT)BASE_FIG);
- ef = eb - ef * ((S_INT)BASE_FIG);
- if(ef) {
- ++j; /* Means to add one more preceeding zero */
- ++e;
- }
- }
-
- eb = e / ((S_INT)BASE_FIG);
-
- ind_a = 0;
- while(i < mi) {
- a->frac[ind_a] = 0;
- while((j < (U_LONG)BASE_FIG) &&(i < mi)) {
- a->frac[ind_a] = a->frac[ind_a] * 10 + int_chr[i] - '0';
- ++j;
- ++i;
- }
- if(i < mi) {
- ++ind_a;
- if(ind_a >= ma) goto over_flow;
- j = 0;
- }
- }
- loc = 1;
-
- /* get fraction part */
-
- i = 0;
- while(i < nf) {
- while((j < (U_LONG)BASE_FIG) &&(i < nf)) {
- a->frac[ind_a] = a->frac[ind_a] * 10 + frac[i] - '0';
- ++j;
- ++i;
- }
- if(i < nf) {
- ++ind_a;
- if(ind_a >= ma) goto over_flow;
- j = 0;
- }
- }
- goto Final;
-
-over_flow:
- rb_warn("Conversion from String to BigDecimal overflow (last few digits discarded).");
-
-Final:
- if(ind_a >= ma) ind_a = ma - 1;
- while(j < (U_LONG)BASE_FIG) {
- a->frac[ind_a] = a->frac[ind_a] * 10;
- ++j;
- }
- a->Prec = ind_a + 1;
- a->exponent = eb;
- VpSetSign(a,sign);
- VpNmlz(a);
- return 1;
-}
-
-/*
- * [Input]
- * *m ... Real
- * [Output]
- * *d ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig.
- * *e ... U_LONG,exponent of m.
- * DBLE_FIG ... Number of digits in a double variable.
- *
- * m -> d*10**e, 0<d<BASE
- * [Returns]
- * 0 ... Zero
- * 1 ... Normal
- * 2 ... Infinity
- * -1 ... NaN
- */
-VP_EXPORT int
-VpVtoD(double *d, S_LONG *e, Real *m)
-{
- U_LONG ind_m, mm, fig;
- double div;
- int f = 1;
-
- if(VpIsNaN(m)) {
- *d = VpGetDoubleNaN();
- *e = 0;
- f = -1; /* NaN */
- goto Exit;
- } else
- if(VpIsPosZero(m)) {
- *d = 0.0;
- *e = 0;
- f = 0;
- goto Exit;
- } else
- if(VpIsNegZero(m)) {
- *d = VpGetDoubleNegZero();
- *e = 0;
- f = 0;
- goto Exit;
- } else
- if(VpIsPosInf(m)) {
- *d = VpGetDoublePosInf();
- *e = 0;
- f = 2;
- goto Exit;
- } else
- if(VpIsNegInf(m)) {
- *d = VpGetDoubleNegInf();
- *e = 0;
- f = 2;
- goto Exit;
- }
- /* Normal number */
- fig =(DBLE_FIG + BASE_FIG - 1) / BASE_FIG;
- ind_m = 0;
- mm = Min(fig,(m->Prec));
- *d = 0.0;
- div = 1.;
- while(ind_m < mm) {
- div /=(double)((S_INT)BASE);
- *d = *d +((double) ((S_INT)m->frac[ind_m++])) * div;
- }
- *e = m->exponent * ((S_INT)BASE_FIG);
- *d *= VpGetSign(m);
-
-Exit:
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, " VpVtoD: m=%\n", m);
- printf(" d=%e * 10 **%ld\n", *d, *e);
- printf(" DBLE_FIG = %ld\n", DBLE_FIG);
- }
-#endif /*_DEBUG */
- return f;
-}
-
-/*
- * m <- d
- */
-VP_EXPORT void
-VpDtoV(Real *m, double d)
-{
- U_LONG i, ind_m, mm;
- U_LONG ne;
- double val, val2;
-
- if(isnan(d)) {
- VpSetNaN(m);
- goto Exit;
- }
- if(isinf(d)) {
- if(d>0.0) VpSetPosInf(m);
- else VpSetNegInf(m);
- goto Exit;
- }
-
- if(d == 0.0) {
- VpSetZero(m,1);
- goto Exit;
- }
- val =(d > 0.) ? d :(-d);
- ne = 0;
- if(val >= 1.0) {
- while(val >= 1.0) {
- val /=(double)((S_INT)BASE);
- ++ne;
- }
- } else {
- val2 = 1.0 /(double)((S_INT)BASE);
- while(val < val2) {
- val *=(double)((S_INT)BASE);
- --ne;
- }
- }
- /* Now val = 0.xxxxx*BASE**ne */
-
- mm = m->MaxPrec;
- memset(m->frac, 0, mm * sizeof(U_LONG));
- for(ind_m = 0;val > 0.0 && ind_m < mm;ind_m++) {
- val *=(double)((S_INT)BASE);
- i =(U_LONG) val;
- val -=(double)((S_INT)i);
- m->frac[ind_m] = i;
- }
- if(ind_m >= mm) ind_m = mm - 1;
- if(d > 0.0) {
- VpSetSign(m, (S_INT)1);
- } else {
- VpSetSign(m,-(S_INT)1);
- }
- m->Prec = ind_m + 1;
- m->exponent = ne;
-
- VpInternalRound(m,0,(m->Prec>0)?m->frac[m->Prec-1]:0,
- (U_LONG)(val*((double)((S_INT)BASE))));
-
-Exit:
-#ifdef _DEBUG
- if(gfDebug) {
- printf("VpDtoV d=%30.30e\n", d);
- VPrint(stdout, " m=%\n", m);
- }
-#endif /* _DEBUG */
- return;
-}
-
-/*
- * m <- ival
- */
-VP_EXPORT void
-VpItoV(Real *m, S_INT ival)
-{
- U_LONG mm, ind_m;
- U_LONG val, v1, v2, v;
- int isign;
- S_INT ne;
-
- if(ival == 0) {
- VpSetZero(m,1);
- goto Exit;
- }
- isign = 1;
- val = ival;
- if(ival < 0) {
- isign = -1;
- val =(U_LONG)(-ival);
- }
- ne = 0;
- ind_m = 0;
- mm = m->MaxPrec;
- while(ind_m < mm) {
- m->frac[ind_m] = 0;
- ++ind_m;
- }
- ind_m = 0;
- while(val > 0) {
- if(val) {
- v1 = val;
- v2 = 1;
- while(v1 >= BASE) {
- v1 /= BASE;
- v2 *= BASE;
- }
- val = val - v2 * v1;
- v = v1;
- } else {
- v = 0;
- }
- m->frac[ind_m] = v;
- ++ind_m;
- ++ne;
- }
- m->Prec = ind_m - 1;
- m->exponent = ne;
- VpSetSign(m,isign);
- VpNmlz(m);
-
-Exit:
-#ifdef _DEBUG
- if(gfDebug) {
- printf(" VpItoV i=%d\n", ival);
- VPrint(stdout, " m=%\n", m);
- }
-#endif /* _DEBUG */
- return;
-}
-
-/*
- * y = SQRT(x), y*y - x =>0
- */
-VP_EXPORT int
-VpSqrt(Real *y, Real *x)
-{
- Real *f = NULL;
- Real *r = NULL;
- S_LONG y_prec, f_prec;
- S_LONG n;
- S_LONG e;
- S_LONG prec;
- S_LONG nr;
- double val;
-
- /* Zero, NaN or Infinity ? */
- if(!VpHasVal(x)) {
- if(VpIsZero(x)||VpGetSign(x)>0) {
- VpAsgn(y,x,1);
- goto Exit;
- }
- VpSetNaN(y);
- return VpException(VP_EXCEPTION_OP,"(VpSqrt) SQRT(NaN or negative value)",0);
- goto Exit;
- }
-
- /* Negative ? */
- if(VpGetSign(x) < 0) {
- VpSetNaN(y);
- return VpException(VP_EXCEPTION_OP,"(VpSqrt) SQRT(negative value)",0);
- }
-
- /* One ? */
- if(VpIsOne(x)) {
- VpSetOne(y);
- goto Exit;
- }
-
- n = (S_LONG)y->MaxPrec;
- if((S_LONG)x->MaxPrec > n) n = (S_LONG)x->MaxPrec;
- /* allocate temporally variables */
- f = VpAlloc(y->MaxPrec *(BASE_FIG + 2), "#1");
- r = VpAlloc((n + n) *(BASE_FIG + 2), "#1");
-
- nr = 0;
- y_prec = (S_LONG)y->MaxPrec;
- f_prec = (S_LONG)f->MaxPrec;
-
- prec = x->exponent;
- if(prec > 0) ++prec;
- else --prec;
- prec = prec - (S_LONG)y->MaxPrec;
- VpVtoD(&val, &e, x); /* val <- x */
- e /= ((S_LONG)BASE_FIG);
- n = e / 2;
- if(e - n * 2 != 0) {
- val /=(double)((S_INT)BASE);
- n =(e + 1) / 2;
- }
- VpDtoV(y, sqrt(val)); /* y <- sqrt(val) */
- y->exponent += n;
- n = (DBLE_FIG + BASE_FIG - 1) / BASE_FIG;
- y->MaxPrec = (U_LONG)Min(n , y_prec);
- f->MaxPrec = y->MaxPrec + 1;
- n = y_prec*((S_LONG)BASE_FIG);
- if((U_LONG)n<maxnr) n = (U_LONG)maxnr;
- do {
- y->MaxPrec *= 2;
- if(y->MaxPrec > (U_LONG)y_prec) y->MaxPrec = (U_LONG)y_prec;
- f->MaxPrec = y->MaxPrec;
- VpDivd(f, r, x, y); /* f = x/y */
- VpAddSub(r, f, y, -1); /* r = f - y */
- VpMult(f, VpPt5, r); /* f = 0.5*r */
- if(VpIsZero(f)) goto converge;
- VpAddSub(r, f, y, 1); /* r = y + f */
- VpAsgn(y, r, 1); /* y = r */
- if(f->exponent <= prec) goto converge;
- } while(++nr < n);
- /* */
-#ifdef _DEBUG
- if(gfDebug) {
- printf("ERROR(VpSqrt): did not converge within %ld iterations.\n",
- nr);
- }
-#endif /* _DEBUG */
- y->MaxPrec = y_prec;
-
-converge:
- VpChangeSign(y,(S_INT)1);
-#ifdef _DEBUG
- if(gfDebug) {
- VpMult(r, y, y);
- VpAddSub(f, x, r, -1);
- printf("VpSqrt: iterations = %lu\n", nr);
- VPrint(stdout, " y =% \n", y);
- VPrint(stdout, " x =% \n", x);
- VPrint(stdout, " x-y*y = % \n", f);
- }
-#endif /* _DEBUG */
- y->MaxPrec = y_prec;
-
-Exit:
- VpFree(f);
- VpFree(r);
- return 1;
-}
-
-/*
- *
- * f = 0: Round off/Truncate, 1: round up, 2:ceil, 3: floor, 4: Banker's rounding
- * nf: digit position for operation.
- *
- */
-VP_EXPORT int
-VpMidRound(Real *y, int f, int nf)
-/*
- * Round reletively from the decimal point.
- * f: rounding mode
- * nf: digit location to round from the the decimal point.
- */
-{
- /* fracf: any positive digit under rounding position? */
- /* exptoadd: number of digits needed to compensate negative nf */
- int n,i,ix,ioffset,fracf,exptoadd;
- U_LONG v,shifter;
- U_LONG div;
-
- nf += y->exponent*((int)BASE_FIG);
- exptoadd=0;
- if (nf < 0) {
- exptoadd = -nf;
- nf = 0;
- }
- /* ix: x->fraq[ix] contains round position */
- ix = nf/(int)BASE_FIG;
- if(((U_LONG)ix)>=y->Prec) return 0; /* Unable to round */
- ioffset = nf - ix*((int)BASE_FIG);
-
- v = y->frac[ix];
- /* drop digits after pointed digit */
- n = BASE_FIG - ioffset - 1;
- for(shifter=1,i=0;i<n;++i) shifter *= 10;
- fracf = (v%(shifter*10) > 0);
- v /= shifter;
- div = v/10;
- v = v - div*10;
- if (fracf == 0) {
- for(i=ix+1;i<y->Prec;i++) {
- if (y->frac[i]%BASE) {
- fracf = 1;
- break;
- }
- }
- }
- memset(y->frac+ix+1, 0, (y->Prec - (ix+1)) * sizeof(U_LONG));
- switch(f) {
- case VP_ROUND_DOWN: /* Truncate */
- break;
- case VP_ROUND_UP: /* Roundup */
- if(fracf) ++div;
- break;
- case VP_ROUND_HALF_UP: /* Round half up */
- if(v>=5) ++div;
- break;
- case VP_ROUND_HALF_DOWN: /* Round half down */
- if(v>=6) ++div;
- break;
- case VP_ROUND_CEIL: /* ceil */
- if(fracf && (VpGetSign(y)>0)) ++div;
- break;
- case VP_ROUND_FLOOR: /* floor */
- if(fracf && (VpGetSign(y)<0)) ++div;
- break;
- case VP_ROUND_HALF_EVEN: /* Banker's rounding */
- if(v>5) ++div;
- else if(v==5) {
- if((U_LONG)i==(BASE_FIG-1)) {
- if(ix && (y->frac[ix-1]%2)) ++div;
- } else {
- if(div%2) ++div;
- }
- }
- break;
- }
- for(i=0;i<=n;++i) div *= 10;
- if(div>=BASE) {
- if(ix) {
- y->frac[ix] = 0;
- VpRdup(y,ix);
- } else {
- S_INT s = VpGetSign(y);
- int e = y->exponent;
- VpSetOne(y);
- VpSetSign(y,s);
- y->exponent = e+1;
- }
- } else {
- y->frac[ix] = div;
- VpNmlz(y);
- }
- if (exptoadd > 0) {
- y->exponent += exptoadd/BASE_FIG;
- exptoadd %= BASE_FIG;
- for(i=0;i<exptoadd;i++) {
- y->frac[0] *= 10;
- if (y->frac[0] >= BASE) {
- y->frac[0] /= BASE;
- y->exponent++;
- }
- }
- }
- return 1;
-}
-
-VP_EXPORT int
-VpLeftRound(Real *y, int f, int nf)
-/*
- * Round from the left hand side of the digits.
- */
-{
- U_LONG v;
- if(!VpHasVal(y)) return 0; /* Unable to round */
- v = y->frac[0];
- nf -= VpExponent(y)*BASE_FIG;
- while(v=v/10) nf--;
- nf += (BASE_FIG-1);
- return VpMidRound(y,f,nf);
-}
-
-VP_EXPORT int
-VpActiveRound(Real *y, Real *x, int f, int nf)
-{
- /* First,assign whole value in truncation mode */
- if(VpAsgn(y, x, 10)<=1) return 0; /* Zero,NaN,or Infinity */
- return VpMidRound(y,f,nf);
-}
-
-static int
-VpLimitRound(Real *c,U_LONG ixDigit)
-{
- U_LONG ix = VpGetPrecLimit();
- if(!VpNmlz(c)) return -1;
- if(!ix) return 0;
- if(!ixDigit) ixDigit = c->Prec-1;
- if((ix+BASE_FIG-1)/BASE_FIG > ixDigit+1) return 0;
- return VpLeftRound(c,VpGetRoundMode(),ix);
-}
-
-static void
-VpInternalRound(Real *c,int ixDigit,U_LONG vPrev,U_LONG v)
-{
- int f = 0;
-
- if(VpLimitRound(c,ixDigit)) return;
- if(!v) return;
-
- v /= BASE1;
- switch(gfRoundMode) {
- case VP_ROUND_DOWN:
- break;
- case VP_ROUND_UP:
- if(v) f = 1;
- break;
- case VP_ROUND_HALF_UP:
- if(v >= 5) f = 1;
- break;
- case VP_ROUND_HALF_DOWN:
- if(v >= 6) f = 1;
- break;
- case VP_ROUND_CEIL: /* ceil */
- if(v && (VpGetSign(c)>0)) f = 1;
- break;
- case VP_ROUND_FLOOR: /* floor */
- if(v && (VpGetSign(c)<0)) f = 1;
- break;
- case VP_ROUND_HALF_EVEN: /* Banker's rounding */
- if(v>5) f = 1;
- else if(v==5 && vPrev%2) f = 1;
- break;
- }
- if(f) {
- VpRdup(c,ixDigit); /* round up */
- VpNmlz(c);
- }
-}
-
-/*
- * Rounds up m(plus one to final digit of m).
- */
-static int
-VpRdup(Real *m,U_LONG ind_m)
-{
- U_LONG carry;
-
- if(!ind_m) ind_m = m->Prec;
-
- carry = 1;
- while(carry > 0 && (ind_m--)) {
- m->frac[ind_m] += carry;
- if(m->frac[ind_m] >= BASE) m->frac[ind_m] -= BASE;
- else carry = 0;
- }
- if(carry > 0) { /* Overflow,count exponent and set fraction part be 1 */
- if(!AddExponent(m,(S_LONG)1)) return 0;
- m->Prec = m->frac[0] = 1;
- } else {
- VpNmlz(m);
- }
- return 1;
-}
-
-/*
- * y = x - fix(x)
- */
-VP_EXPORT void
-VpFrac(Real *y, Real *x)
-{
- U_LONG my, ind_y, ind_x;
-
- if(!VpHasVal(x)) {
- VpAsgn(y,x,1);
- goto Exit;
- }
-
- if(x->exponent > 0 && (U_LONG)x->exponent >= x->Prec) {
- VpSetZero(y,VpGetSign(x));
- goto Exit;
- } else if(x->exponent <= 0) {
- VpAsgn(y, x, 1);
- goto Exit;
- }
-
- y->Prec = x->Prec -(U_LONG) x->exponent;
- y->Prec = Min(y->Prec, y->MaxPrec);
- y->exponent = 0;
- VpSetSign(y,VpGetSign(x));
- ind_y = 0;
- my = y->Prec;
- ind_x = x->exponent;
- while(ind_y < my) {
- y->frac[ind_y] = x->frac[ind_x];
- ++ind_y;
- ++ind_x;
- }
- VpNmlz(y);
-
-Exit:
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, "VpFrac y=%\n", y);
- VPrint(stdout, " x=%\n", x);
- }
-#endif /* _DEBUG */
- return;
-}
-
-/*
- * y = x ** n
- */
-VP_EXPORT int
-VpPower(Real *y, Real *x, S_INT n)
-{
- U_LONG s, ss;
- S_LONG sign;
- Real *w1 = NULL;
- Real *w2 = NULL;
-
- if(VpIsZero(x)) {
- if(n==0) {
- VpSetOne(y);
- goto Exit;
- }
- sign = VpGetSign(x);
- if(n<0) {
- n = -n;
- if(sign<0) sign = (n%2)?(-1):(1);
- VpSetInf (y,sign);
- } else {
- if(sign<0) sign = (n%2)?(-1):(1);
- VpSetZero(y,sign);
- }
- goto Exit;
- }
- if(!VpIsDef(x)) {
- VpSetNaN(y); /* Not sure !!! */
- goto Exit;
- }
-
- if((x->exponent == 1) &&(x->Prec == 1) &&(x->frac[0] == 1)) {
- /* abs(x) = 1 */
- VpSetOne(y);
- if(VpGetSign(x) > 0) goto Exit;
- if((n % 2) == 0) goto Exit;
- VpSetSign(y,-(S_INT)1);
- goto Exit;
- }
-
- if(n > 0) sign = 1;
- else if(n < 0) {
- sign = -1;
- n = -n;
- } else {
- VpSetOne(y);
- goto Exit;
- }
-
- /* Allocate working variables */
-
- w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0");
- w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0");
- /* calculation start */
-
- VpAsgn(y, x, 1);
- --n;
- while(n > 0) {
- VpAsgn(w1, x, 1);
- s = 1;
-loop1: ss = s;
- s += s;
- if(s >(U_LONG) n) goto out_loop1;
- VpMult(w2, w1, w1);
- VpAsgn(w1, w2, 1);
- goto loop1;
-out_loop1:
- n -= ss;
- VpMult(w2, y, w1);
- VpAsgn(y, w2, 1);
- }
- if(sign < 0) {
- VpDivd(w1, w2, VpConstOne, y);
- VpAsgn(y, w1, 1);
- }
-
-Exit:
-#ifdef _DEBUG
- if(gfDebug) {
- VPrint(stdout, "VpPower y=%\n", y);
- VPrint(stdout, "VpPower x=%\n", x);
- printf(" n=%d\n", n);
- }
-#endif /* _DEBUG */
- VpFree(w2);
- VpFree(w1);
- return 1;
-}
-
-#ifdef _DEBUG
-int
-VpVarCheck(Real * v)
-/*
- * Checks the validity of the Real variable v.
- * [Input]
- * v ... Real *, variable to be checked.
- * [Returns]
- * 0 ... correct v.
- * other ... error
- */
-{
- U_LONG i;
-
- if(v->MaxPrec <= 0) {
- printf("ERROR(VpVarCheck): Illegal Max. Precision(=%lu)\n",
- v->MaxPrec);
- return 1;
- }
- if((v->Prec <= 0) ||((v->Prec) >(v->MaxPrec))) {
- printf("ERROR(VpVarCheck): Illegal Precision(=%lu)\n", v->Prec);
- printf(" Max. Prec.=%lu\n", v->MaxPrec);
- return 2;
- }
- for(i = 0; i < v->Prec; ++i) {
- if((v->frac[i] >= BASE)) {
- printf("ERROR(VpVarCheck): Illegal fraction\n");
- printf(" Frac[%ld]=%lu\n", i, v->frac[i]);
- printf(" Prec. =%lu\n", v->Prec);
- printf(" Exp. =%d\n", v->exponent);
- printf(" BASE =%lu\n", BASE);
- return 3;
- }
- }
- return 0;
-}
-#endif /* _DEBUG */
diff --git a/ext/bigdecimal/bigdecimal.def b/ext/bigdecimal/bigdecimal.def
deleted file mode 100644
index 8450e164e6..0000000000
--- a/ext/bigdecimal/bigdecimal.def
+++ /dev/null
@@ -1,2 +0,0 @@
-EXPORTS
-Init_bigdecimal
diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h
deleted file mode 100644
index aabc551a76..0000000000
--- a/ext/bigdecimal/bigdecimal.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- *
- * Ruby BigDecimal(Variable decimal precision) extension library.
- *
- * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
- *
- * You may distribute under the terms of either the GNU General Public
- * License or the Artistic License, as specified in the README file
- * of this BigDecimal distribution.
- *
- * NOTES:
- * 2003-03-28 V1.0 checked in.
- *
- */
-
-#ifndef ____BIG_DECIMAL__H____
-#define ____BIG_DECIMAL__H____
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/*
- * NaN & Infinity
- */
-#define SZ_NaN "NaN"
-#define SZ_INF "Infinity"
-#define SZ_PINF "+Infinity"
-#define SZ_NINF "-Infinity"
-
-/*
- * #define VP_EXPORT other than static to let VP_ routines
- * be called from outside of this module.
- */
-#define VP_EXPORT static
-
-#define U_LONG unsigned long
-#define S_LONG long
-#define U_INT unsigned int
-#define S_INT int
-
-/* Exception codes */
-#define VP_EXCEPTION_ALL ((unsigned short)0x00FF)
-#define VP_EXCEPTION_INFINITY ((unsigned short)0x0001)
-#define VP_EXCEPTION_NaN ((unsigned short)0x0002)
-#define VP_EXCEPTION_UNDERFLOW ((unsigned short)0x0004)
-#define VP_EXCEPTION_OVERFLOW ((unsigned short)0x0001) /* 0x0008) */
-#define VP_EXCEPTION_ZERODIVIDE ((unsigned short)0x0001) /* 0x0010) */
-
-/* Following 2 exceptions cann't controlled by user */
-#define VP_EXCEPTION_OP ((unsigned short)0x0020)
-#define VP_EXCEPTION_MEMORY ((unsigned short)0x0040)
-
-/* Computation mode */
-#define VP_ROUND_MODE ((unsigned short)0x0100)
-#define VP_ROUND_UP 1
-#define VP_ROUND_DOWN 2
-#define VP_ROUND_HALF_UP 3
-#define VP_ROUND_HALF_DOWN 4
-#define VP_ROUND_CEIL 5
-#define VP_ROUND_FLOOR 6
-#define VP_ROUND_HALF_EVEN 7
-
-#define VP_SIGN_NaN 0 /* NaN */
-#define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */
-#define VP_SIGN_NEGATIVE_ZERO -1 /* Negative zero */
-#define VP_SIGN_POSITIVE_FINITE 2 /* Positive finite number */
-#define VP_SIGN_NEGATIVE_FINITE -2 /* Negative finite number */
-#define VP_SIGN_POSITIVE_INFINITE 3 /* Positive infinite number */
-#define VP_SIGN_NEGATIVE_INFINITE -3 /* Negative infinite number */
-
-/*
- * VP representation
- * r = 0.xxxxxxxxx *BASE**exponent
- */
-typedef struct {
- VALUE obj; /* Back pointer(VALUE) for Ruby object. */
- U_LONG MaxPrec; /* Maximum precision size */
- /* This is the actual size of pfrac[] */
- /*(frac[0] to frac[MaxPrec] are available). */
- U_LONG Prec; /* Current precision size. */
- /* This indicates how much the. */
- /* the array frac[] is actually used. */
- S_INT exponent;/* Exponent part. */
- short sign; /* Attributes of the value. */
- /*
- * ==0 : NaN
- * 1 : Positive zero
- * -1 : Negative zero
- * 2 : Positive number
- * -2 : Negative number
- * 3 : Positive infinite number
- * -3 : Negative infinite number
- */
- short flag; /* Not used in vp_routines,space for user. */
- U_LONG frac[1]; /* Pointer to array of fraction part. */
-} Real;
-
-/*
- * ------------------
- * EXPORTables.
- * ------------------
- */
-
-VP_EXPORT Real *
-VpNewRbClass(U_LONG mx,char *str,VALUE klass);
-
-VP_EXPORT Real *VpCreateRbObject(U_LONG mx,char *str);
-
-VP_EXPORT U_LONG VpBaseFig(void);
-VP_EXPORT U_LONG VpDblFig(void);
-VP_EXPORT U_LONG VpBaseVal(void);
-
-/* Zero,Inf,NaN (isinf(),isnan() used to check) */
-VP_EXPORT double VpGetDoubleNaN(void);
-VP_EXPORT double VpGetDoublePosInf(void);
-VP_EXPORT double VpGetDoubleNegInf(void);
-VP_EXPORT double VpGetDoubleNegZero(void);
-
-/* These 2 functions added at v1.1.7 */
-VP_EXPORT U_LONG VpGetPrecLimit(void);
-VP_EXPORT U_LONG VpSetPrecLimit(U_LONG n);
-
-/* Round mode */
-VP_EXPORT int VpIsRoundMode(unsigned long n);
-VP_EXPORT unsigned long VpGetRoundMode(void);
-VP_EXPORT unsigned long VpSetRoundMode(unsigned long n);
-
-VP_EXPORT int VpException(unsigned short f,char *str,int always);
-VP_EXPORT int VpIsNegDoubleZero(double v);
-VP_EXPORT U_LONG VpNumOfChars(Real *vp,char *pszFmt);
-VP_EXPORT U_LONG VpInit(U_LONG BaseVal);
-VP_EXPORT void *VpMemAlloc(U_LONG mb);
-VP_EXPORT void VpFree(Real *pv);
-VP_EXPORT Real *VpAlloc(U_LONG mx, char *szVal);
-VP_EXPORT int VpAsgn(Real *c,Real *a,int isw);
-VP_EXPORT int VpAddSub(Real *c,Real *a,Real *b,int operation);
-VP_EXPORT int VpMult(Real *c,Real *a,Real *b);
-VP_EXPORT int VpDivd(Real *c,Real *r,Real *a,Real *b);
-VP_EXPORT int VpComp(Real *a,Real *b);
-VP_EXPORT S_LONG VpExponent10(Real *a);
-VP_EXPORT void VpSzMantissa(Real *a,char *psz);
-VP_EXPORT int VpToSpecialString(Real *a,char *psz,int fPlus);
-VP_EXPORT void VpToString(Real *a,char *psz,int fFmt,int fPlus);
-VP_EXPORT void VpToFString(Real *a,char *psz,int fFmt,int fPlus);
-VP_EXPORT int VpCtoV(Real *a,char *int_chr,U_LONG ni,char *frac,U_LONG nf,char *exp_chr,U_LONG ne);
-VP_EXPORT int VpVtoD(double *d,S_LONG *e,Real *m);
-VP_EXPORT void VpDtoV(Real *m,double d);
-VP_EXPORT void VpItoV(Real *m,S_INT ival);
-VP_EXPORT int VpSqrt(Real *y,Real *x);
-VP_EXPORT int VpActiveRound(Real *y,Real *x,int f,int il);
-VP_EXPORT int VpMidRound(Real *y, int f, int nf);
-VP_EXPORT int VpLeftRound(Real *y, int f, int nf);
-VP_EXPORT void VpFrac(Real *y,Real *x);
-VP_EXPORT int VpPower(Real *y,Real *x,S_INT n);
-
-/* VP constants */
-VP_EXPORT Real *VpOne();
-
-/*
- * ------------------
- * MACRO definitions.
- * ------------------
- */
-#define Abs(a) (((a)>= 0)?(a):(-(a)))
-#define Max(a, b) (((a)>(b))?(a):(b))
-#define Min(a, b) (((a)>(b))?(b):(a))
-
-#define VpMaxPrec(a) ((a)->MaxPrec)
-#define VpPrec(a) ((a)->Prec)
-#define VpGetFlag(a) ((a)->flag)
-
-/* Sign */
-
-/* VpGetSign(a) returns 1,-1 if a>0,a<0 respectively */
-#define VpGetSign(a) (((a)->sign>0)?1:(-1))
-/* Change sign of a to a>0,a<0 if s = 1,-1 respectively */
-#define VpChangeSign(a,s) {if((s)>0) (a)->sign=(short)Abs((S_LONG)(a)->sign);else (a)->sign=-(short)Abs((S_LONG)(a)->sign);}
-/* Sets sign of a to a>0,a<0 if s = 1,-1 respectively */
-#define VpSetSign(a,s) {if((s)>0) (a)->sign=(short)VP_SIGN_POSITIVE_FINITE;else (a)->sign=(short)VP_SIGN_NEGATIVE_FINITE;}
-
-/* 1 */
-#define VpSetOne(a) {(a)->frac[0]=(a)->exponent=(a)->Prec=1;(a)->sign=VP_SIGN_POSITIVE_FINITE;}
-
-/* ZEROs */
-#define VpIsPosZero(a) ((a)->sign==VP_SIGN_POSITIVE_ZERO)
-#define VpIsNegZero(a) ((a)->sign==VP_SIGN_NEGATIVE_ZERO)
-#define VpIsZero(a) (VpIsPosZero(a) || VpIsNegZero(a))
-#define VpSetPosZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_ZERO)
-#define VpSetNegZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_ZERO)
-#define VpSetZero(a,s) ( ((s)>0)?VpSetPosZero(a):VpSetNegZero(a) )
-
-/* NaN */
-#define VpIsNaN(a) ((a)->sign==VP_SIGN_NaN)
-#define VpSetNaN(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NaN)
-
-/* Infinity */
-#define VpIsPosInf(a) ((a)->sign==VP_SIGN_POSITIVE_INFINITE)
-#define VpIsNegInf(a) ((a)->sign==VP_SIGN_NEGATIVE_INFINITE)
-#define VpIsInf(a) (VpIsPosInf(a) || VpIsNegInf(a))
-#define VpIsDef(a) ( !(VpIsNaN(a)||VpIsInf(a)) )
-#define VpSetPosInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_INFINITE)
-#define VpSetNegInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_INFINITE)
-#define VpSetInf(a,s) ( ((s)>0)?VpSetPosInf(a):VpSetNegInf(a) )
-#define VpHasVal(a) (a->frac[0])
-#define VpIsOne(a) ((a->Prec==1)&&(a->frac[0]==1)&&(a->exponent==1))
-#define VpExponent(a) (a->exponent)
-#ifdef _DEBUG
-int VpVarCheck(Real * v);
-VP_EXPORT int VPrint(FILE *fp,char *cntl_chr,Real *a);
-#endif /* _DEBUG */
-
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
-#endif /* ____BIG_DECIMAL__H____ */
diff --git a/ext/bigdecimal/bigdecimal_en.html b/ext/bigdecimal/bigdecimal_en.html
deleted file mode 100644
index 02c88df43e..0000000000
--- a/ext/bigdecimal/bigdecimal_en.html
+++ /dev/null
@@ -1,797 +0,0 @@
-<!-- saved from url=(0022)http://internet.e-mail -->
-<HTML>
-<HEAD>
-<META HTTP-EQUIV="Content-Type" CONTENT="text/html">
-<style type="text/css"><!--
-body { color: #3f0f0f; background: #fefeff; margin-left: 2em; margin-right: 2em;}
-h1 { color: #ffffff; background-color: #3939AD; border-color: #FF00FF; width: 100%; border-style: solid;
- border-top-width: 0.1em; border-bottom-width: 0.1em; border-right: none; border-left: none;
- padding: 0.1em; font-weight: bold; font-size: 160%; text-align: center;}
-h2 { color: #00007f; background-color: #e7e7ff; border-color: #000094; width: 100%; border-style: solid; border-le ft: none; border-right: none; border-top-width: 0.1em; border-bottom-width: 0.1em; padding: 0.1em;
- font-weight: bold; font-size: 110%;
-}
-h3 { color: #00007f; padding: 0.2em; font-size: 110%;}
-h4, h5 { color: #000000; padding: 0.2em; font-size: 100%;}
-table { margin-top: 0.2em; margin-bottom: 0.2em; margin-left: 2em; margin-right: 2em;}
-caption { color: #7f0000; font-weight: bold;}
-th { background: #e7e7ff; padding-left: 0.2em; padding-right: 0.2em;}
-td { background: #f3f7ff; padding-left: 0.2em; padding-right: 0.2em;}
-code { color: #0000df;}
-dt { margin-top: 0.2em;}
-li { margin-top: 0.2em;}
-pre
-{ BACKGROUND-COLOR: #d0d0d0; BORDER-BOTTOM: medium none; BORDER-LEFT: medium none;
- BORDER-RIGHT: medium none; BORDER-TOP: medium none; LINE-HEIGHT: 100%; MARGIN: 12px 12px 12px 12px;
- PADDING-BOTTOM: 12px; PADDING-LEFT: 12px; PADDING-RIGHT: 12px; PADDING-TOP: 12px;
- WHITE-SPACE: pre; WIDTH: 100%
-}
---></style>
-
-<TITLE>BigDecimal:An extension library for Ruby</TITLE>
-</HEAD>
-<BODY BGCOLOR=#FFFFE0>
-<H1>BigDecimal(Variable Precision Floating Library for Ruby)</H1>
-<DIV align="right"><A HREF="./bigdecimal_ja.html">Japanese</A></DIV><BR>
-BigDecimal is an extension library for the Ruby interpreter.
-Using BigDecimal class, you can obtain any number of significant digits in computation.
-For the details about Ruby see:<BR>
-<UL>
-<LI><A HREF="http://www.ruby-lang.org/en/">http://www.ruby-lang.org/en/</A>:Official Ruby page(English).</LI>
-<LI><A HREF="http://kahori.com/ruby/ring/">http://kahori.com/ruby/ring/</A>:Mutually linked pages relating to Ruby(Japanese).
-</LI>
-</UL>
-NOTE:<BR>
- This software is provided "AS IS" and without any express or
- implied warranties,including,without limitation,the implied
- warranties of merchantibility and fitness for a particular
- purpose. For the details,see COPYING and README included in this
- distribution.
-<BR>
-<hr>
-
-<H2>Contents</H2>
-<UL>
-<LI><A HREF="#INTRO">Introduction</LI>
-<LI><A HREF="#SPEC">Usage and methods</A></LI>
-<LI><A HREF="#UNDEF">Infinity,NaN,Zero</A></LI>
-<LI><A HREF="#STRUCT">Internal structure</A></LI>
-<LI><A HREF="#BASE">Binary or decimal number representation</A></LI>
-<LI><A HREF="#PREC">Resulting number of significant digits</A></LI>
-</UL>
-<HR>
-
-<A NAME="#INTRO">
-<H2>Introduction</H2>
-Ruby already has builtin (variable length integer number) class Bignum. Using Bignum class,you can obtain
- any integer value in magnitude. But, variable length decimal number class is not yet built in.
-This is why I made variable length floating class BigDecimal.
-Feel free to send any comments or bug reports to me.
-<A HREF="mailto:shigeo@tinyforest.gr.jp">shigeo@tinyforest.gr.jp</A>
-I will try(but can't promise) to fix bugs reported.
-<hr>
-<H2>Installation</H2>
-The Ruby latest version can be downloaded from <A HREF="http://www.ruby-lang.org/en/">Official Ruby page</A>.
-Once decompress the downloaded Ruby archive,follow the normal installation procedures according to the
-documents included.
-
-<A NAME="#SPEC">
-<H2>Usage and methods</H2>
-Suppose you already know Ruby programming,
-to create BigDecimal objects,the program would like:<BR>
-
-<CODE><PRE>
- require 'bigdecimal'
- a=BigDecimal::new("0.123456789123456789")
- b=BigDecimal("123456.78912345678",40)
- c=a+b
-</PRE></CODE>
-
-<H3>List of methods</H3>
-In 32 bits integer system,every 4 digits(in decimal) are computed simultaneously.
-This means the number of significant digits in BigDecimal is always a multiple of 4.
-<P>
-Some more methods are available in Ruby code (not C code).
-Functions such as sin,cos ...,are in math.rb in bigdecimal directory.
-To use them,require math.rb as:
-<CODE><PRE>
-require "bigdecimal/math.rb"
-</PRE></CODE>
-For details,see the math.rb code and comments.
-Other utility methods are in util.rb.
-To use util.rb, require it as:
-<CODE><PRE>
-require "bigdecimal/util.rb"
-</PRE></CODE>
-For details,see the util.rb code.
-
-<H4><U>Class methods</U></H4>
-<UL>
-<LI><B>new</B></LI><BLOCKQUOTE>
-"new" method creates a new BigDecimal object.<BR>
-a=BigDecimal::new(s[,n]) or<BR>
-a=BigDecimal(s[,n]) or<BR>
-where:<BR>
-s: Initial value string. Spaces will be ignored. Any unrecognizable character for
-representing initial value terminates the string.<BR>
-n: Maximum number of significant digits of a. n must be a Fixnum object.
-If n is omitted or is equal to 0,then the maximum number of significant digits of a is determined from the length of s.
-Actual number of digits handled in computations are usually gretaer than n.<BR>
-n is useful when performing divisions like
-<CODE><PRE>
-BigDecimal("1") / BigDecimal("3") # => 0.3333333333 33E0
-BigDecimal("1",10) / BigDecimal("3",10) # => 0.3333333333 3333333333 33333333E0
-</PRE></CODE>
-but the resulting digits obtained may differ in future version.
-</BLOCKQUOTE>
-
-<LI><B>mode</B></LI><BLOCKQUOTE>
-f = BigDecimal.mode(s[,v])<BR>
-mode method controls BigDecimal computation. If the second argument is not given or is nil,then the value
-of current setting is returned.
-Following usage are defined.<BR>
-<P><B>[EXCEPTION control]</B><P>
-Actions when computation results NaN or Infinity can be defined as follows.
-<P>
-<BLOCKQUOTE>
-f = BigDecimal::mode(BigDecimal::EXCEPTION_NaN,flag)<BR>
-f = BigDecimal::mode(BigDecimal::EXCEPTION_INFINITY,flag)<BR>
-f = BigDecimal::mode(BigDecimal::EXCEPTION_UNDERFLOW,flag)<BR>
-f = BigDecimal::mode(BigDecimal::EXCEPTION_OVERFLOW,flag)<BR>
-f = BigDecimal::mode(BigDecimal::EXCEPTION_ZERODIVIDE,flag)<BR>
-f = BigDecimal::mode(BigDecimal::EXCEPTION_ALL,flag)<BR>
-</BLOCKQUOTE>
-EXCEPTION_NaN controls the execution when computation results to NaN.<BR>
-EXCEPTION_INFINITY controls the execution when computation results to Infinity(}Infinity).<BR>
-EXCEPTION_UNDERFLOW controls the execution when computation underflows.<BR>
-EXCEPTION_OVERFLOW controls the execution when computation overflows.<BR>
-EXCEPTION_ZERODIVIDE controls the execution when zero-division occures.<BR>
-EXCEPTION_ALL controls the execution for any exception defined occures.<BR>
-If the flag is true,then the relating exception is thrown.<BR>
-No exception is thrown when the flag is false(default) and computation
-continues with the result:<BR>
-<BLOCKQUOTE>
-EXCEPTION_NaN results to NaN<BR>
-EXCEPTION_INFINITY results to +Infinity or -Infinity<BR>
-EXCEPTION_UNDERFLOW results to 0.<BR>
-EXCEPTION_OVERFLOW results to +Infinity or -Infinity<BR>
-EXCEPTION_ZERODIVIDE results to +Infinity or -Infinity<BR>
-</BLOCKQUOTE>
-EXCEPTION_INFINITY,EXCEPTION_OVERFLOW, and EXCEPTION_ZERODIVIDE are
- currently the same.<BR>
-The return value of mode method is the value set.<BR>
-If nil is specified for the second argument,then current setting is returned.<BR>
-Suppose the return value of the mode method is f,then
- f &amp; BigDecimal::EXCEPTION_NaN !=0 means EXCEPTION_NaN is set to on.
-<P>
-<B>[ROUND error control]</B><P>
-Rounding operation can be controlled as:
-<BLOCKQUOTE>
-f = BigDecimal::mode(BigDecimal::ROUND_MODE,flag)
-</BLOCKQUOTE>
-where flag must be one of:
-<TABLE>
-
-<TR><TD>ROUND_UP</TD><TD>round away from zero.</TD></TR>
-<TR><TD>ROUND_DOWN</TD><TD>round towards zero(truncate).</TD></TR>
-<TR><TD>ROUND_HALF_UP</TD><TD>round up if the digit &gt;= 5 otherwise truncated(default).</TD></TR>
-<TR><TD>ROUND_HALF_DOWN</TD><TD>round up if the digit &gt;= 6 otherwise truncated.</TD></TR>
-<TR><TD>ROUND_HALF_EVEN</TD><TD>round towards the even neighbor(Banker's rounding).
-<TR><TD>ROUND_CEILING</TD><TD>round towards positive infinity(ceil).</TD></TR>
-<TR><TD>ROUND_FLOOR</TD><TD>round towards negative infinity(floor).</TD></TR>
-</TABLE>
-New rounding mode is returned. If nil is specified for the second argument,then current setting is returned.<BR>
-The digit location for rounding operation can not be specified by this mode method,
-use truncate/round/ceil/floor/add/sub/mult/div mthods for each instance instead.
-</BLOCKQUOTE>
-
-<LI><B>limit[(n)]</B></LI><BLOCKQUOTE>
-Limits the maximum digits that the newly created BigDecimal objects can hold never exceed n.
-This means the rounding operation specified by BigDecimal.mode is
-performed if necessary.
-limit returns the value before set if n is nil or is not specified.
-Zero,the default value,means no upper limit.<BR>
-The limit has no more priority than instance methods such as truncate,round,ceil,floor,add,sub,mult,and div. <BR>
-mf = BigDecimal::limit(n)<BR>
-</BLOCKQUOTE>
-
-<LI><B>double_fig</B></LI><BLOCKQUOTE>
-double_fig is a class method which returns the number of digits
-the Float class can have.
-<CODE><PRE>
- p BigDecimal::double_fig # ==> 20 (depends on the CPU etc.)
-</PRE></CODE>
-The equivalent C programs which calculates the value of
-double_fig is:
-<CODE><PRE>
- double v = 1.0;
- int double_fig = 0;
- while(v + 1.0 > 1.0) {
- ++double_fig;
- v /= 10;
- }
-</PRE></CODE>
-</BLOCKQUOTE>
-
-<LI><B>BASE</B></LI><BLOCKQUOTE>
-Base value used in the BigDecimal calculation.
-On 32 bits integer system,the value of BASE is 10000.<BR>
-b = BigDecimal::BASE<BR>
-</BLOCKQUOTE>
-</UL>
-
-<H4><U>Instance methods</U></H4>
-<UL>
-<LI><B>+</B></LI><BLOCKQUOTE>
-addition(c = a + b)<BR>
-For the resulting number of significant digits of c,see <A HREF="#PREC">Resulting number of significant digits</A>.
-
-</BLOCKQUOTE>
-<LI><B>-</B></LI><BLOCKQUOTE>
-subtraction (c = a - b) or negation (c = -a)<BR>
-For the resulting number of significant digits of c,see <A HREF="#PREC">Resulting number of significant digits</A>.
-
-</BLOCKQUOTE>
-<LI><B>*</B></LI><BLOCKQUOTE>
-multiplication(c = a * b)<BR>
-For the resulting number of significant digits of c,see <A HREF="#PREC">Resulting number of significant digits</A>.
-
-</BLOCKQUOTE>
-<LI><B>/</B></LI><BLOCKQUOTE>
-division(c = a / b)<BR>
-For the resulting number of significant digits of c,see <A HREF="#PREC">Resulting number of significant digits</A>.
-</BLOCKQUOTE>
-
-<LI><B>add(b,n)</B></LI><BLOCKQUOTE>
-c = a.add(b,n)<BR>
-c = a.add(b,n) performs c = a + b.<BR>
-If n is less than the actual significant digits of a + b,
-then c is rounded properly according to the BigDecimal.limit.<BR>
-If n is zero,then the result is the same as +'s.
-</BLOCKQUOTE>
-<LI><B>sub(b,n)</B></LI><BLOCKQUOTE>
-c = a.sub(b,n)<BR>
-c = a.sub(b,n) performs c = a - b.<BR>
-If n is less than the actual significant digits of a - b,
-then c is rounded properly according to the BigDecimal.limit.<BR>
-If n is zero,then the result is the same as -'s.
-
-</BLOCKQUOTE>
-<LI><B>mult(b,n)</B></LI><BLOCKQUOTE>
-c = a.mult(b,n)<BR>
-c = a.mult(b,n) performs c = a * b.<BR>
-If n is less than the actual significant digits of a * b,
-then c is rounded properly according to the BigDecimal.limit.<BR>
-If n is zero,then the result is the same as *'s.
-
-</BLOCKQUOTE>
-<LI><B>div(b[,n])</B></LI><BLOCKQUOTE>
-c = a.div(b,n)<BR>
-c = a.div(b,n) performs c = a / b.<BR>
-If n is less than the actual significant digits of a / b,
-then c is rounded properly according to the BigDecimal.limit.<BR>
-If n is zero,then the result is the same as /'s.
-If n is not given,then the result will be an integer(BigDecimal) like Float#div.
-</BLOCKQUOTE>
-
-<LI><B>fix</B></LI><BLOCKQUOTE>
-c = a.fix<BR>
-returns integer part of a.<BR>
-
-</BLOCKQUOTE>
-<LI><B>frac</B></LI><BLOCKQUOTE>
-c = a.frac<BR>
-returns fraction part of a.<BR>
-
-</BLOCKQUOTE>
-<LI><B>floor[(n)]</B></LI><BLOCKQUOTE>
-c = a.floor<BR>
-returns the maximum integer value (in BigDecimal) which is less than or equal to a.
-<CODE><PRE>
- c = BigDecimal("1.23456").floor # ==> 1
- c = BigDecimal("-1.23456").floor # ==> -2
-</PRE></CODE>
-
-As shown in the following example,an optional integer argument (n) specifying the position
-of the target digit can be given.<BR>
-If n> 0,then the (n+1)th digit counted from the decimal point in fraction part is processed(resulting number of fraction part digits is less than or equal to n).<BR>
-If n<0,then the n-th digit counted from the decimal point in integer part is processed(at least n 0's are placed from the decimal point to left).
-<CODE><PRE>
- c = BigDecimal("1.23456").floor(4) # ==> 1.2345
- c = BigDecimal("15.23456").floor(-1) # ==> 10.0
-</PRE></CODE>
-
-</BLOCKQUOTE>
-<LI><B>ceil[(n)]</B></LI><BLOCKQUOTE>
-c = a.ceil<BR>
-returns the minimum integer value (in BigDecimal) which is greater than or equal to a.
-<CODE><PRE>
- c = BigDecimal("1.23456").ceil # ==> 2
- c = BigDecimal("-1.23456").ceil # ==> -1
-</PRE></CODE>
-
-As shown in the following example,an optional integer argument (n) specifying the position
-of the target digit can be given.<BR>
-If n>0,then the (n+1)th digit counted from the decimal point in fraction part is processed(resulting number of fraction part digits is less than or equal to n).<BR>
-If n<0,then the n-th digit counted from the decimal point in integer part is processed(at least n 0's are placed from the decimal point to left).
-<CODE><PRE>
- c = BigDecimal("1.23456").ceil(4) # ==> 1.2346
- c = BigDecimal("15.23456").ceil(-1) # ==> 20.0
-</PRE></CODE>
-
-</BLOCKQUOTE>
-<LI><B>round[(n[,b])]</B></LI><BLOCKQUOTE>
-c = a.round<BR>
-round a to the nearest 1(default)D<BR>
-<CODE><PRE>
- c = BigDecimal("1.23456").round # ==> 1
- c = BigDecimal("-1.23456").round # ==> -1
-</PRE></CODE>
-The rounding operation changes according to BigDecimal::mode(BigDecimal::ROUND_MODE,flag) if specified.
-
-As shown in the following example,an optional integer argument (n) specifying the position
-of the target digit can be given.<BR>
-If n>0,then the (n+1)th digit counted from the decimal point in fraction part is processed(resulting number of fraction part digits is less than or equal to n).<BR>
-If n<0,then the n-th digit counted from the decimal point in integer part is processed(at least n 0's are placed from the decimal point to left).
-<CODE><PRE>
-c = BigDecimal::new("1.23456").round(4) # ==> 1.2346
-c = BigDecimal::new("15.23456").round(-1) # ==> 20.0
-</PRE></CODE>
-
-Rounding operation can be specified by setting the second optional argument b with the valid ROUND_MODE.<BR>
-<CODE><PRE>
-c = BigDecimal::new("1.23456").round(3,BigDecimal::ROUND_HALF_EVEN) # ==> 1.234
-c = BigDecimal::new("1.23356").round(3,BigDecimal::ROUND_HALF_EVEN) # ==> 1.234
-</PRE></CODE>
-
-</BLOCKQUOTE>
-<LI><B>truncate[(n)]</B></LI><BLOCKQUOTE>
-c = a.truncate<BR>
-truncate a to the nearest 1D<BR>
-As shown in the following example,an optional integer argument (n) specifying the position
-of the target digit can be given.<BR>
-If n>0,then the (n+1)th digit counted from the decimal point in fraction part is processed(resulting number of fraction part digits is less than or equal to n).<BR>
-If n<0,then the n-th digit counted from the decimal point in integer part is processed(at least n 0's are placed from the decimal point to left).
-
-<CODE><PRE>
-c = BigDecimal::new("1.23456").truncate(4) # ==> 1.2345
-c = BigDecimal::new("15.23456").truncate(-1) # ==> 10.0
-</PRE></CODE>
-</BLOCKQUOTE>
-<LI><B>abs</B></LI><BLOCKQUOTE>
-c = a.abs<BR>
-returns an absolute value of a.<BR>
-
-</BLOCKQUOTE>
-<LI><B>to_i</B></LI><BLOCKQUOTE>
-changes a to an integer.<BR>
-i = a.to_i<BR>
-i becomes to Fixnum or Bignum.
-If a is Infinity or NaN,then i becomes to nil.
-
-</BLOCKQUOTE>
-<LI><B>to_s[(n)]</B></LI><BLOCKQUOTE>
-converts to string(default results look like "0.xxxxxEn").
-<CODE><PRE>
-BigDecimal("1.23456").to_s # ==> "0.123456E1"
-</PRE></CODE>
-If n(>0) is given,then a space is inserted to each of two parts divided by the decimal point
-after every n digits for readability.
-<CODE><PRE>
-BigDecimal("0.1234567890123456789").to_s(10) # ==> "0.1234567890 123456789E0"
-</PRE></CODE>
-n can be an string representing a positive integer number.
-<CODE><PRE>
-BigDecimal("0.1234567890123456789").to_s("10") # ==> "0.1234567890 123456789E0"
-</PRE></CODE>
-If the first character is '+'(or ' '),then '+'(or ' ') will be set before value string
-when the value is positive.
-<CODE><PRE>
-BigDecimal("0.1234567890123456789").to_s(" 10") # ==> " 0.1234567890 123456789E0"
-BigDecimal("0.1234567890123456789").to_s("+10") # ==> "+0.1234567890 123456789E0"
-BigDecimal("-0.1234567890123456789").to_s("10") # ==> "-0.1234567890 123456789E0"
-</PRE></CODE>
-
-At the end of the string,'E'(or 'e') or 'F'(or 'f') can be specified to change
-number representation.
-<CODE><PRE>
-BigDecimal("1234567890.123456789").to_s("E") # ==> "0.1234567890123456789E10"
-BigDecimal("1234567890.123456789").to_s("F") # ==> "1234567890.123456789"
-BigDecimal("1234567890.123456789").to_s("5E") # ==> "0.12345 67890 12345 6789E10"
-BigDecimal("1234567890.123456789").to_s("5F") # ==> "12345 67890.12345 6789"
-</PRE></CODE>
-
-</BLOCKQUOTE>
-<LI><B>exponent</B></LI><BLOCKQUOTE>
-returns an integer holding exponent value of a.<BR>
-n = a.exponent <BR>
-means a = 0.xxxxxxx*10**n.
-</BLOCKQUOTE>
-
-<LI><B>precs</B></LI><BLOCKQUOTE>
-n,m = a.precs <BR>
-prec returns number of significant digits (n) and maximum number of
-significant digits (m) of a.
-</BLOCKQUOTE>
-
-<LI><B>to_f</B></LI><BLOCKQUOTE>
-Creates a new Float object having (nearly) the same value.
-Use split method if you want to convert by yourself.
-</BLOCKQUOTE>
-
-</BLOCKQUOTE>
-<LI><B>sign</B></LI><BLOCKQUOTE>
-n = a.sign <BR>
-returns positive value if a &gt; 0,negative value if a &lt; 0,
-otherwise zero if a == 0.<BR>
-where the value of n means that a is:<BR>
-n = BigDecimal::SIGN_NaN(0) : a is NaN<BR>
-n = BigDecimal::SIGN_POSITIVE_ZERO(1) : a is +0<BR>
-n = BigDecimal::SIGN_NEGATIVE_ZERO(-1) : a is -0<BR>
-n = BigDecimal::SIGN_POSITIVE_FINITE(2) : a is positive<BR>
-n = BigDecimal::SIGN_NEGATIVE_FINITE(-2) : a is negative<BR>
-n = BigDecimal::SIGN_POSITIVE_INFINITE(3) : a is +Infinity<BR>
-n = BigDecimal::SIGN_NEGATIVE_INFINITE(-3) : a is -Infinity<BR>
-The value in () is the actual value,see (<A HREF="#STRUCT">Internal structure</A>.<BR>
-
-</BLOCKQUOTE>
-<LI><B>nan?</B></LI><BLOCKQUOTE>
-a.nan? returns True when a is NaN.
-
-</BLOCKQUOTE>
-<LI><B>infinite?</B></LI><BLOCKQUOTE>
-a.infinite? returns 1 when a is +‡,-1 when a is -‡, nil otherwise.
-
-</BLOCKQUOTE>
-<LI><B>finite?</B></LI><BLOCKQUOTE>
-a.finite? returns true when a is neither ‡ nor NaN.
-</BLOCKQUOTE>
-
-<LI><B>zero?</B></LI><BLOCKQUOTE>
-c = a.zero?<BR>
-returns true if a is equal to 0,otherwise returns false<BR>
-</BLOCKQUOTE>
-<LI><B>nonzero?</B></LI><BLOCKQUOTE>
-c = a.nonzero?<BR>
-returns nil if a is 0,otherwise returns a itself.<BR>
-</BLOCKQUOTE>
-
-<LI><B>split</B></LI><BLOCKQUOTE>
-decomposes a BigDecimal value to 4 parts.
-All 4 parts are returned as an array.<BR>
-Parts consist of a sign(0 when the value is NaN,+1 for positive and
- -1 for negative value), a string representing fraction part,base value(always 10 currently),and an integer(Fixnum) for exponent respectively.
-a=BigDecimal::new("3.14159265")<BR>
-f,x,y,z = a.split<BR>
-where f=+1,x="314159265",y=10 and z=1<BR>
-therefore,you can translate BigDecimal value to Float as:<BR>
-s = "0."+x<BR>
-b = f*(s.to_f)*(y**z)<BR>
-
-</BLOCKQUOTE>
-<LI><B>inspect</B></LI><BLOCKQUOTE>
-is used for debugging output.<BR>
-p a=BigDecimal::new("3.14",10)<BR>
-should produce output like "#&lt;0x112344:'0.314E1',4(12)%gt;".
-where "0x112344" is the address,
-'0.314E1' is the value,4 is the number of the significant digits,
-and 12 is the maximum number of the significant digits
-the object can hold.
-</BLOCKQUOTE>
-
-<LI><B>sqrt</B></LI><BLOCKQUOTE>
-c = a.sqrt(n)<BR>
-computes square root value of a with significant digit number n at least.<BR>
-</BLOCKQUOTE>
-
-<LI><B>**</B></LI><BLOCKQUOTE>
-c = a ** n<BR>
-returns the value of a powered by n.
-n must be an integer.<BR>
-
-</BLOCKQUOTE>
-<LI><B>power</B></LI><BLOCKQUOTE>
-The same as ** method.<BR>
-c = a.power(n)<BR>
-returns the value of a powered by n(c=a**n).
-n must be an integer.<BR>
-</BLOCKQUOTE>
-
-<LI><B>divmod,quo,modulo,%,remainder</B></LI><BLOCKQUOTE>
-See,corresponding methods in Float class.
-</BLOCKQUOTE>
-
-</BLOCKQUOTE>
-<LI><B>&lt;=&gt;</B></LI><BLOCKQUOTE>
-c = a &lt;=&gt; b <BR>
-returns 0 if a==b,1 if a &gt b,and returns -1 if a &lt b.<BR>
-</BLOCKQUOTE>
-</UL>
-
-Following methods need no explanation.<BR>
-<UL>
-<LI>==</LI>
-<LI>===</LI>
-same as ==,used in case statement.
-<LI>!=</LI>
-<LI>&lt;</LI>
-<LI>&lt;=</LI>
-<LI>&gt;</LI>
-<LI>&gt;=</LI>
-</UL>
-
-<HR>
-<H3>About 'coerce'</H3>
-<B>For the binary operation like A op B:</B>
-<DL>
-<DT> 1.Both A and B are BigDecimal objects</DT>
-<DD> A op B is normally performed.</DD>
-<DT> 2.A is the BigDecimal object but B is other than BigDecimal object</DT>
-<DD> Operation is performed,after B is translated to correcponding BigDecimal object(because BigDecimal supports coerce method).</DD>
-<DT> 3.A is not the BigDecimal object but B is BigDecimal object</DT>
-<DD>If A has coerce mthod,then B will translate A to corresponding
-BigDecimal object and the operation is performed,otherwise an error occures.</DD>
-</DL>
-
-String is not translated to BigDecimal in default.
-Uncomment /* #define ENABLE_NUMERIC_STRING */ in bigdecimal.c, compile and install
-again if you want to enable string to BigDecimal conversion.
-Translation stops without error at the character representing non digit.
-For instance,"10XX" is translated to 10,"XXXX" is translated to 0.<BR>
-String representing zero or infinity such as "Infinity","+Infinity","-Infinity",and "NaN" can also be translated to BigDecimal unless false is specified by mode method.<BR>
-
-BigDecimal class supports coerce method(for the details about coerce method,see Ruby documentations). This means the most binary operation can be performed if the BigDecimal object is at the left hand side of the operation.<BR><BR>
-
- For example:
-<CODE><PRE>
- a = BigDecimal.E(20)
- c = a * "0.123456789123456789123456789" # A String is changed to BigDecimal object.
-</PRE></CODE>
-is performed normally.<BR>
- But,because String does not have coerce method,the following example can not be performed.<BR>
-
-<CODE><PRE>
- a = BigDecimal.E(20)
- c = "0.123456789123456789123456789" * a # ERROR
-</PRE></CODE>
-
-If you actually have any inconvenience about the error above.
-You can define a new class derived from String class,
-and define coerce method within the new class.<BR>
-
-<hr>
-<A NAME="#UNDEF">
-<H2>Infinity,Not a Number(NaN),Zero</H2>
-Infinite numbers and NaN can be represented by string writing "+Infinity"(or "Infinity"),"-Infinity",and "NaN" respectively in your program.
-Infinite numbers can be obtained by 1.0/0.0(=Infinity) or -1.0/0.0(=-Infinity).
-<BR><BR>
-NaN(Not a number) can be obtained by undefined computation like 0.0/0.0
-or Infinity-Infinity.
-Any computation including NaN results to NaN.
-Comparisons with NaN never become true,including comparison with NaN itself.
-<BR><BR>
-Zero has two different variations as +0.0 and -0.0.
-But,still, +0.0==-0.0 is true.
-<BR><BR>
-Computation results including Infinity,NaN,+0.0 or -0.0 become complicated.
-Run following program and comfirm the results.
-Send me any incorrect result if you find.
-
-<CODE><PRE>
- require "bigdecimal"
- aa = %w(1 -1 +0.0 -0.0 +Infinity -Infinity NaN)
- ba = %w(1 -1 +0.0 -0.0 +Infinity -Infinity NaN)
- opa = %w(+ - * / <=> > >= < == != <=)
- for a in aa
- for b in ba
- for op in opa
- x = BigDecimal::new(a)
- y = BigDecimal::new(b)
- eval("ans= x #{op} y;print a,' ',op,' ',b,' ==> ',ans.to_s,\"\n\"")
- end
- end
- end
-</PRE></CODE>
-<hr>
-
-<A NAME="#STRUCT">
-<H2>Internal structure</H2>
-BigDecimal number is defined by the structure Real in BigDecimal.h.
-Digits representing a float number are kept in the array frac[] defined in the structure.
-In the program,any floating number(BigDecimal number) is represented as:<BR>
- <BigDecimal number> = 0.xxxxxxxxx*BASE**n<BR><BR>
-where 'x' is any digit representing mantissa(kept in the array frac[]),
-BASE is base value(=10000 in 32 bit integer system),
-and n is the exponent value.<BR>
-Larger BASE value enables smaller size of the array frac[],and increases computation speed.
-The value of BASE is defined ind VpInit(). In 32 bit integer system,this value is
-10000. In 64 bit integer system,the value becomes larger.
-BigDecimal has not yet been compiled and tested on 64 bit integer system.
-It will be very nice if anyone try to run BigDecimal on 64 bit system and
- inform me the results.
-When BASE is 10000,an element of the array frac[] can have vale of from 0 to 9999.
-(up to 4 digits).<BR>
-The structure Real is defined in bigdecimal.h as:<BR>
-<CODE><PRE>
- typedef struct {
- VALUE obj; /* Back pointer(VALUE) for Ruby object. */
- unsigned long MaxPrec; /* The size of the array frac[] */
- unsigned long Prec; /* Current size of frac[] actually used. */
- short sign; /* Attribute of the value. */
- /* ==0 : NaN */
- /* 1 : +0 */
- /* -1 : -0 */
- /* 2 : Positive number */
- /* -2 : Negative number */
- /* 3 : +Infinity */
- /* -3 : -Infinity */
- unsigned short flag; /* Control flag */
- int exponent; /* Exponent value(0.xxxx*BASE**exponent) */
- unsigned long frac[1]; /* An araay holding mantissa(Variable) */
- } Real;
-</CODE></PRE>
-The decimal value 1234.56784321 is represented as(BASE=10000):<BR>
-<PRE>
- 0.1234 5678 4321*(10000)**1
-</PRE>
-where frac[0]=1234,frac[1]=5678,frac[2]=4321,
-Prec=3,sign=2,exponent=1. MaxPrec can be any value greater than or equal to
-Prec.
-<hr>
-
-<A NAME="#BASE">
-<H2>Binary or decimal number representation</H2>
-I adopted decimal number representation for BigDecimal implementation.
-Of cource,binary number representation is common on the most computers.
-
-<H3>Advantages using decimal representation</H3>
-The reason why I adopted decimal number representation for BigDecimal is:<BR>
-<DL>
-<DT>Easy for debugging
-<DD>The floating number 1234.56784321 can be easily represented as:<BR>
- frac[0]=1234,frac[1]=5678,frac[2]=4321,exponent=1,and sign=2.
-<DT>Exact representation
-<DD>Following program can add all numbers(in decimal) in a file
- without any error(no round operation).<BR>
-
-<CODE><PRE>
- file = File::open(....,"r")
- s = BigDecimal::new("0")
- while line = file.gets
- s = s + line
- end
-</PRE></CODE>
-
-If the internal representation is binary,translation from decimal to
-binary is required and the translation error is inevitable.
-For example, 0.1 can not exactly be represented in binary.<BR>
-0.1 => b1*2**(-1)+b1*2**(-2)+b3*2**(-3)+b4*2**(-4)....<BR>
-where b1=0,b2=0,b3=0,b4=1...<BR>
-bn(n=1,2,3,...) is infinite series of digit with value of 0 or 1,
-and rounding operation is necessary but where we should round the series ?
-Of cource,exact "0.1" is printed if the rouding operation is properly done,
-<DT>Significant digit we can have is automatically determined
-<DD>In binary representation,0.1 can not be represented in finite series of digit.
-
-But we only need one element(frac[0]=1) in decimal representation.
-This means that we can always determine the size of the array frac[] in Real
-structure.
-</DL>
-
-<H3>Disadvantage of decimal representation</H3>
-Advantages stated so far can also be disadvantages if the input from outside is
- represented in binary.
-Translation error from decimal to binary or vice versa is inevitable.
-So,translation from Float(binary) to BigDecimal(decimal) is not alway done exactly.
-
-<H4>Which is the first input?</H4>
-Because most people uses decimal notatin for numeric data representation,
-BigDecimal can handle numeric data without loss of translation error.
-<hr>
-
-<A NAME="#PREC">
-<H2>Resulting number of significant digits</H2>
-For the fundamental arithmetics such as addition,subtraction,
-multiplication,and division,I prepared 2 group of methods<BR>
-
-<H3>1. +,-,*,/</H3>
-For the operation + - * /,you can not specify the resulting
-number of significant digits.<BR>
-Resulting number of significant digits are defined as:<BR>
-1.1 For *,resulting number of significant digits is the sum of the
-significant digits of both side of the operator. For / ,resulting number of significant digits is the sum of the
-maximum significant digits of both side of the operator.<BR>
-1.2 For + and -,resulting number of significant digits is determined so that
- no round operation is needed. <br>
-For example, c has more than 100 siginificant digits if c is computed as:<BR>
-c = 0.1+0.1*10**(-100)<br>
-<BR>
-As +,-,and * are always exact(no round operation is performed unless BigDecimal.limit is specified),
-which means more momories are required to keep computation results.
-But,the division such as c=1.0/3.0 will always be rounded.<BR>
-
-<H3>2. add,sub,mult,div</H3>
-The length of the significant digits obtained from +,-,*,/
-is always defined by that of right and left side of the operator.
-To specify the length of the significant digits by your self,
-use methos add,sub,mult,div.
-<CODE><PRE>
- BigDecimal("2").div(3,12) # 2.0/3.0 => 0.6666666666 67E0
-</PRE></CODE>
-</BLOCKQUOTE>
-
-<H3>3. truncate,round,ceil,floor</H3>
-Using these methods,you can specify rounding location relatively from
-decimal point.
-<CODE><PRE>
- BigDecimal("6.66666666666666").round(12) # => 0.6666666666 667E1
-</PRE></CODE>
-</BLOCKQUOTE>
-
-
-<H3>4. Example</H3>
-Following example compute the ratio of the circumference of a circle to
-its dirmeter(pi=3.14159265358979....) using J.Machin's formula.
-<BR><BR>
-<CODE><PRE>
-#!/usr/local/bin/ruby
-
-require "bigdecimal"
-#
-# Calculates 3.1415.... (the number of times that a circle's diameter
-# will fit around the circle) using J. Machin's formula.
-#
-def big_pi(sig) # sig: Number of significant figures
- exp = -sig
- pi = BigDecimal::new("0")
- two = BigDecimal::new("2")
- m25 = BigDecimal::new("-0.04")
- m57121 = BigDecimal::new("-57121")
-
- u = BigDecimal::new("1")
- k = BigDecimal::new("1")
- w = BigDecimal::new("1")
- t = BigDecimal::new("-80")
- while (u.nonzero? && u.exponent >= exp)
- t = t*m25
- u = t.div(k,sig)
- pi = pi + u
- k = k+two
- end
-
- u = BigDecimal::new("1")
- k = BigDecimal::new("1")
- w = BigDecimal::new("1")
- t = BigDecimal::new("956")
- while (u.nonzero? && u.exponent >= exp )
- t = t.div(m57121,sig)
- u = t.div(k,sig)
- pi = pi + u
- k = k+two
- end
- pi
-end
-
-if $0 == __FILE__
- if ARGV.size == 1
- print "PI("+ARGV[0]+"):\n"
- p big_pi(ARGV[0].to_i)
- else
- print "TRY: ruby pi.rb 1000 \n"
- end
-end
-
-</PRE></CODE>
-<HR>
-<FONT size=2>
-<I>
-<A HREF="http://www.tinyforest.gr.jp">
-Shigeo Kobayashi
-</A>
-(E-Mail:<A HREF="mailto:shigeo@tinyforest.gr.jp">&lt;shigeo@tinyforest.gr.jp&gt;</U></A>)
-</I>
-</FONT>
-</TD>
-</TR>
-</TABLE>
-</BODY>
-</HTML>
diff --git a/ext/bigdecimal/bigdecimal_ja.html b/ext/bigdecimal/bigdecimal_ja.html
deleted file mode 100644
index 8fd95a6fe3..0000000000
--- a/ext/bigdecimal/bigdecimal_ja.html
+++ /dev/null
@@ -1,798 +0,0 @@
-<!-- saved from url=(0022)http://internet.e-mail -->
-<HTML>
-<HEAD>
-<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=Shift_JIS">
-<style type="text/css"><!--
-body { color: #3f0f0f; background: #fefeff; margin-left: 2em; margin-right: 2em;}
-h1 { color: #ffffff; background-color: #3939AD; border-color: #FF00FF; width: 100%;
- border-style: solid; border-top-width: 0.1em; border-bottom-width: 0.1em; border-right: none;
- border-left: none; padding: 0.1em; font-weight: bold; font-size: 160%; text-align: center;
-}
-h2 { color: #00007f; background-color: #e7e7ff; border-color: #000094; width: 100%;
- border-style: solid; border-left: none; border-right: none; border-top-width: 0.1em; border-bottom-width: 0.1em;
- padding: 0.1em;
- font-weight: bold; font-size: 110%;
-}
-h3 { color: #00007f; padding: 0.2em; font-size: 110%;}
-h4, h5 { color: #000000; padding: 0.2em; font-size: 100%;}
-table { margin-top: 0.2em; margin-bottom: 0.2em; margin-left: 2em; margin-right: 2em;}
-caption { color: #7f0000; font-weight: bold;}
-th { background: #e7e7ff; padding-left: 0.2em; padding-right: 0.2em;}
-td { background: #f3f7ff; padding-left: 0.2em; padding-right: 0.2em;}
-code { color: #0000df;}
-dt { margin-top: 0.2em;}
-li { margin-top: 0.2em;}
-pre
-{ BACKGROUND-COLOR: #d0d0d0; BORDER-BOTTOM: medium none; BORDER-LEFT: medium none;
- BORDER-RIGHT: medium none; BORDER-TOP: medium none; LINE-HEIGHT: 100%; MARGIN: 12px 12px 12px 12px;
- PADDING-BOTTOM: 12px; PADDING-LEFT: 12px; PADDING-RIGHT: 12px; PADDING-TOP: 12px;
- WHITE-SPACE: pre; WIDTH: 100%
-}
---></style>
-
-<TITLE>BigDecimal:An extension library for Ruby</TITLE>
-</HEAD>
-<BODY BGCOLOR=#FFFFE0>
-<H1>BigDecimal(‰Â•Ï’·•‚“®­”“_‰‰ŽZ—pŠg’£ƒ‰ƒCƒuƒ‰ƒŠ)</H1>
-<DIV align="right"><A HREF="./bigdecimal_en.html">English</A></DIV><BR>
-BigDecimal ‚̓IƒuƒWƒFƒNƒgŽwŒü‚Ì‹­—͂ȃXƒNƒŠƒvƒgŒ¾Œê‚Å‚ ‚é Ruby ‚ɉ•ϒ·•‚“®¬”“_
-ŒvŽZ‹@”\‚ð’ljÁ‚·‚邽‚߂̊g’£ƒ‰ƒCƒuƒ‰ƒŠ‚Å‚·B
-Ruby ‚ɂ‚¢‚Ä‚ÌÚ‚µ‚¢“à—e‚͈ȉº‚ÌURL‚ðŽQÆ‚µ‚Ä‚­‚¾‚³‚¢B
-<UL>
-<LI><A HREF="http://www.ruby-lang.org/ja/">http://www.ruby-lang.org/ja/</A>FRubyŒöŽ®ƒy[ƒW</LI>
-<LI><A HREF="http://kahori.com/ruby/ring/">http://kahori.com/ruby/ring/</A>FRuby‚ÉŠÖ‚·‚éƒy[ƒW‚ð’H‚ê‚Ü‚·</LI>
-</UL>
-<hr>
-<H2>–ÚŽŸ</H2>
-<UL>
-<LI><A HREF="#INTRO">‚Í‚¶‚ß‚É</LI>
-<LI><A HREF="#SPEC">Žg—p•û–@‚ƃƒ\ƒbƒh‚̈ꗗ</A></LI>
-<LI><A HREF="#UNDEF">–³ŒÀA”ñ”Aƒ[ƒ‚̈µ‚¢</A></LI>
-<LI><A HREF="#STRUCT">“à•”\‘¢</A></LI>
-<LI><A HREF="#BASE">2i‚Æ10i</A></LI>
-<LI><A HREF="#PREC">ŒvŽZ¸“x‚ɂ‚¢‚Ä</A></LI>
-</UL>
-
-<HR>
-<A NAME="#INTRO">
-<H2>‚Í‚¶‚ß‚É</H2>
-Ruby ‚É‚Í Bignum ‚Æ‚¢‚¤ƒNƒ‰ƒX‚ª‚ ‚èA”•SŒ…‚Ì®”‚Å‚àŒvŽZ‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B
-‚½‚¾A”CˆÓŒ…‚Ì•‚“®­”“_‰‰ŽZ—pƒNƒ‰ƒX‚ª–³‚¢‚悤‚Å‚·B‚»‚±‚ÅA
-”CˆÓŒ…‚Ì•‚“®­”“_‰‰ŽZ—pŠg’£ƒ‰ƒCƒuƒ‰ƒŠ BigDecimal ‚ð쬂µ‚Ü‚µ‚½B
-•s‹ï‡‚╌¾E’ñˆÄ‚ª‚ ‚éꇂǂµ‚Ç‚µA
-<A HREF="mailto:shigeo@tinyforest.gr.jp">shigeo@tinyforest.gr.jp</A>
-‚܂ł¨’m‚点‚­‚¾‚³‚¢B•s‹ï‡‚𒼂·‹C‚͑傢‚É‚ ‚è‚Ü‚·B‚½‚¾AŽžŠÔ‚Ȃǂ̊֌W‚Å–ñ‘©
-‚͂ł«‚Ü‚¹‚ñB‚Ü‚½AŒ‹‰Ê‚ɂ‚¢‚Ä‚à•ÛØ‚Å‚«‚é‚à‚̂ł͂ ‚è‚Ü‚¹‚ñB
-—\‚ßA‚²—¹³‚­‚¾‚³‚¢B
-<BR><BR>
-‚±‚̃vƒƒOƒ‰ƒ€‚ÍAŽ©—R‚É”z•zE‰ü•Ï‚µ‚Ä\‚¢‚Ü‚¹‚ñB‚½‚¾‚µA’˜ìŒ ‚Í•úŠü‚µ‚Ä‚¢‚Ü‚¹‚ñB
-”z•zE‰ü•Ï“™‚ÌŒ —˜‚Í Ruby ‚Ì‚»‚ê‚É€‚¶‚Ü‚·BÚ‚µ‚­‚Í README ‚ð“Ç‚ñ‚Å‚­‚¾‚³‚¢B
-
-<hr>
-<H2>ƒCƒ“ƒXƒg[ƒ‹‚ɂ‚¢‚Ä</H2>
-BigDecimal ‚ðŠÜ‚Þ Ruby ‚ÌÅV”Å‚Í<A HREF="http://www.ruby-lang.org/ja/">RubyŒöŽ®ƒy[ƒW</A>‚©‚çƒ_ƒEƒ“ƒ[ƒh‚Å‚«‚Ü‚·B
-ƒ_ƒEƒ“ƒ[ƒh‚µ‚½ÅV”Å‚ð‰ð“€‚µ‚½‚çA’Êí‚̃Cƒ“ƒXƒg[ƒ‹Žè‡‚ðŽÀs‚µ‚ĉº‚³‚¢B
-Ruby ‚ª³‚µ‚­ƒCƒ“ƒXƒg[ƒ‹‚³‚ê‚ê‚ÎA“¯Žž‚É BigDecimal ‚à—˜—p‚Å‚«‚邿‚¤‚ɂȂé‚Í‚¸‚Å‚·B
-ƒ\[ƒXƒtƒ@ƒCƒ‹‚Í
-bigdecimal.c,bigdecimal.h
-‚Ì‚QŒÂ‚݂̂ł·B<BR>
-
-<hr>
-<A NAME="#SPEC">
-<H2>Žg—p•û–@‚ƃƒ\ƒbƒh‚̈ꗗ</H2>
-uRuby‚ÍŠù‚É‘‚¯‚év‚Æ‚¢‚¤‘O’ñ‚ÅA
-<CODE><PRE>
-require 'bigdecimal'
-a=BigDecimal::new("0.123456789123456789")
-b=BigDecimal("123456.78912345678",40)
-c=a+b
-</PRE></CODE>
-<br>
-‚Æ‚¢‚¤‚悤‚ÈŠ´‚¶‚ÅŽg—p‚µ‚Ü‚·B
-
-<H3>ƒƒ\ƒbƒhˆê——</H3>
-ˆÈ‰º‚̃ƒ\ƒbƒh‚ª—˜—p‰Â”\‚Å‚·B
-u—LŒøŒ…”v‚Æ‚Í BigDecimal ‚ª¸“x‚ð•ÛØ‚·‚錅”‚Å‚·B
-‚Ò‚Á‚½‚è‚ł͂ ‚è‚Ü‚¹‚ñAŽáб‚Ì—]—T‚ðŽ‚Á‚ÄŒvŽZ‚³‚ê‚Ü‚·B
-‚Ü‚½A—Ⴆ‚΂R‚Qƒrƒbƒg‚̃VƒXƒeƒ€‚ł͂P‚Oi‚Å‚SŒ…–ˆ‚ÉŒvŽZ‚µ‚Ü‚·B]‚Á‚ÄAŒ»ó‚Å‚ÍA
-“à•”‚Ìu—LŒøŒ…”v‚Í‚S‚Ì”{”‚ƂȂÁ‚Ä‚¢‚Ü‚·B
-<P>
-ˆÈ‰º‚̃ƒ\ƒbƒhˆÈŠO‚É‚àA(C ‚ł͂Ȃ¢) Ruby ƒ\[ƒX‚ÌŒ`‚Å
-’ñ‹Ÿ‚³‚ê‚Ä‚¢‚é‚à‚Ì‚à‚ ‚è‚Ü‚·B—Ⴆ‚ÎA
-<CODE><PRE>
-require "bigdecimal/math.rb"
-</PRE></CODE>
-‚Æ‚·‚邱‚Æ‚ÅAsin ‚â cos ‚Æ‚¢‚Á‚½ŠÖ”‚ªŽg—p‚Å‚«‚邿‚¤‚ɂȂè‚Ü‚·B
-Žg—p•û–@‚È‚ÇAÚ×‚Í math.rb ‚Ì“à—e‚ðŽQÆ‚µ‚ĉº‚³‚¢B
-
-‚»‚Ì‘¼AFloat ‚Æ‚Ì‘ŠŒÝ•ÏŠ·‚Ȃǂ̃ƒ\ƒbƒh‚ª util.rb ‚ŃTƒ|[ƒg‚³‚ê‚Ä‚¢‚Ü‚·B
-—˜—p‚·‚é‚É‚Í
-<CODE><PRE>
-require "bigdecimal/util.rb"
-</PRE></CODE>
-‚̂悤‚É‚µ‚Ü‚·BÚ×‚Í util.rb ‚Ì“à—e‚ðŽQÆ‚µ‚ĉº‚³‚¢B
-
-<H4><U>ƒNƒ‰ƒXƒƒ\ƒbƒh</U></H4>
-<UL>
-<LI><B>new</B></LI><BLOCKQUOTE>
-V‚µ‚¢ BigDecimal ƒIƒuƒWƒFƒNƒg‚𶬂µ‚Ü‚·B<BR>
-a=BigDecimal::new(s[,n]) ‚Ü‚½‚Í<BR>
-a=BigDecimal(s[,n])<BR>
-s ‚Í”Žš‚ð•\Œ»‚·‚鉊ú’l‚ð•¶Žš—ñ‚ÅŽw’肵‚Ü‚·B
-ƒXƒy[ƒX‚Í–³Ž‹‚³‚ê‚Ü‚·B‚Ü‚½A”»’f‚Å‚«‚È‚¢•¶Žš‚ªoŒ»‚µ‚½Žž“_‚Å
-•¶Žš—ñ‚ÍI—¹‚µ‚½‚à‚̂Ƃ݂Ȃ³‚ê‚Ü‚·B
-n ‚Í•K—v‚È—LŒøŒ…”ia ‚ÌÅ‘å—LŒøŒ…”j‚ð®”‚ÅŽw’肵‚Ü‚·B
-n ‚ª 0 ‚Ü‚½‚ÍÈ—ª‚³‚ꂽ‚Æ‚«‚ÍAn ‚Ì’l‚Í s ‚Ì—LŒøŒ…”‚Ƃ݂Ȃ³‚ê‚Ü‚·B
-s ‚Ì—LŒøŒ…”‚æ‚è n ‚ª¬‚³‚¢‚Æ‚«‚à n=0 ‚̂Ƃ«‚Æ“¯‚¶‚Å‚·B
-a ‚ÌÅ‘å—LŒøŒ…”‚Í n ‚æ‚èŽáб‘å‚¢’l‚ªÌ—p‚³‚ê‚Ü‚·B
-Å‘å—LŒøŒ…”‚͈ȉº‚̂悤‚ÈŠ„‚èŽZ‚ðŽÀs‚·‚邯‚«“™‚ɈӖ¡‚ðŽ‚¿‚Ü‚·B
-<CODE><PRE>
-BigDecimal("1") / BigDecimal("3") # => 0.3333333333 33E0
-BigDecimal("1",10) / BigDecimal("3",10) # => 0.3333333333 3333333333 33333333E0
-</PRE></CODE>
-‚½‚¾‚µAŒÂX‚̉‰ŽZ‚É‚¨‚¯‚éÅ‘å—LŒøŒ…” n ‚ÌŽæ‚舵‚¢‚Í«—ˆ‚̃o[ƒWƒ‡ƒ“‚Å
-Žáб•ÏX‚³‚ê‚é‰Â”\«‚ª‚ ‚è‚Ü‚·B
-</BLOCKQUOTE>
-
-<LI><B>mode</B></LI><BLOCKQUOTE>
-f = BigDecimal.mode(s[,v])<BR>
-BigDecimal‚ÌŽÀsŒ‹‰Ê‚ð§Œä‚µ‚Ü‚·B‘æ‚Qˆø”‚ðÈ—ªA‚Ü‚½‚Í nil ‚ðŽw’è‚·‚邯
-Œ»ó‚ÌÝ’è’l‚ª–ß‚è‚Ü‚·B<BR>
-ˆÈ‰º‚ÌŽg—p•û–@‚ª’è‹`‚³‚ê‚Ä‚¢‚Ü‚·B
-<P>
-<B>[—áŠOˆ—]</B><P>
-ŒvŽZŒ‹‰Ê‚ª”ñ”(NaN)‚âƒ[ƒ‚É‚æ‚霎Z‚ɂȂÁ‚½‚Æ‚«‚̈—‚ð’è‹`‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B
-<BLOCKQUOTE>
-f = BigDecimal::mode(BigDecimal::EXCEPTION_NaN,flag)<BR>
-f = BigDecimal::mode(BigDecimal::EXCEPTION_INFINITY,flag)<BR>
-f = BigDecimal::mode(BigDecimal::EXCEPTION_UNDERFLOW,flag)<BR>
-f = BigDecimal::mode(BigDecimal::EXCEPTION_OVERFLOW,flag)<BR>
-f = BigDecimal::mode(BigDecimal::EXCEPTION_ZERODIVIDE,flag)<BR>
-f = BigDecimal::mode(BigDecimal::EXCEPTION_ALL,flag)<BR>
-</BLOCKQUOTE>
-
-EXCEPTION_NaN ‚ÍŒ‹‰Ê‚ª NaN ‚ɂȂÁ‚½‚Æ‚«‚ÌŽw’è‚Å‚·B<BR>
-EXCEPTION_INFINITY ‚ÍŒ‹‰Ê‚ª–³ŒÀ‘å(}Infinity)‚ɂȂÁ‚½‚Æ‚«‚ÌŽw’è‚Å‚·B<BR>
-EXCEPTION_UNDERFLOW ‚ÍŽw”•”‚ªƒAƒ“ƒ_[ƒtƒ[‚·‚邯‚«‚ÌŽw’è‚Å‚·B<BR>
-EXCEPTION_OVERFLOW ‚ÍŽw”•”‚ªƒI[ƒo[ƒtƒ[‚·‚邯‚«‚ÌŽw’è‚Å‚·B<BR>
-EXCEPTION_ZERODIVIDE ‚̓[ƒ‚É‚æ‚銄‚èŽZ‚ðŽÀs‚µ‚½‚Æ‚«‚ÌŽw’è‚Å‚·B<BR>
-EXCEPTION_ALL ‚ÍA‰Â”\‚È‘S‚Ăɑ΂µ‚Ĉꊇ‚µ‚ÄÝ’è‚·‚邯‚«‚ÉŽg—p‚µ‚Ü‚·B<BR><BR>
-
-flag ‚ª true ‚̂Ƃ«‚ÍAŽw’肵‚½ó‘ԂɂȂÁ‚½‚Æ‚«‚É—áŠO‚ð”­s‚·‚邿‚¤‚ɂȂè‚Ü‚·B<BR>
-flag ‚ª falseiƒfƒtƒHƒ‹ƒgj‚È‚çA—áŠO‚Í”­s‚³‚ê‚Ü‚¹‚ñBŒvŽZŒ‹‰Ê‚͈ȉº‚̂悤‚ɂȂè‚Ü‚·B<BR>
-<BLOCKQUOTE>
-EXCEPTION_NaN ‚̂Ƃ«A”ñ”(NaN)<BR>
-EXCEPTION_INFINITY ‚̂Ƃ«A–³ŒÀ(+ or -Infinity)<BR>
-EXCEPTION_UNDERFLOW ‚̂Ƃ«Aƒ[ƒ<BR>
-EXCEPTION_OVERFLOW ‚̂Ƃ«A+Infinity ‚© -Infinity<BR>
-EXCEPTION_ZERODIVIDE ‚̂Ƃ«A+Infinity ‚© -Infinity<BR>
-</BLOCKQUOTE>
-EXCEPTION_INFINITYAEXCEPTION_OVERFLOWAEXCEPTION_ZERODIVIDE
-‚Í¡‚̂Ƃ±‚듯‚¶‚Å‚·B<BR>
-–ß‚è’l‚ÍAÝ’èŒã‚Ì’l‚Å‚·Bu’lv‚̈Ӗ¡‚ÍA—Ⴆ‚Î
-BigDecimal::EXCEPTION_NaN‚Æu’lv‚Ì & ‚ª ƒ[ƒˆÈŠO‚È‚ç‚Î
-EXCEPTION_NaN‚ªÝ’肳‚ê‚Ä‚¢‚邯‚¢‚¤ˆÓ–¡‚Å‚·B
-
-<P>
-<B>[ŠÛ‚߈—Žw’è]</B><P>
-ŒvŽZ“r’†‚ÌŠÛ‚ß‘€ì‚ÌŽw’肪‚Å‚«‚Ü‚·B
-<BLOCKQUOTE>
-f = BigDecimal::mode(BigDecimal::ROUND_MODE,flag)
-</BLOCKQUOTE>
-‚ÌŒ`Ž®‚ÅŽw’肵‚Ü‚·B<BR>
-‚±‚±‚ÅAflag ‚͈ȉº(ЇŒÊ“à‚͑Ήž‚·‚éƒCƒ“ƒXƒ^ƒ“ƒXƒƒ\ƒbƒh)‚̈ê‚‚ðŽw’肵‚Ü‚·B
-<TABLE>
-<TR><TD>ROUND_UP</TD><TD>‘S‚ÄØ‚èã‚°‚Ü‚·B</TD></TR>
-<TR><TD>ROUND_DOWN</TD><TD>‘S‚ÄØ‚èŽÌ‚Ă܂·(truncate)B</TD></TR>
-<TR><TD>ROUND_HALF_UP</TD><TD>ŽlŽÌŒÜ“ü‚µ‚Ü‚·(ƒfƒtƒHƒ‹ƒg)B</TD></TR>
-<TR><TD>ROUND_HALF_DOWN</TD><TD>ŒÜŽÌ˜Z“ü‚µ‚Ü‚·B</TD></TR>
-<TR><TD>ROUND_HALF_EVEN</TD><TD>ŽlŽÌ˜Z“ü‚µ‚Ü‚·B‚T‚ÌŽž‚ÍãˆÊ‚PŒ…‚ªŠï”‚ÌŽž‚̂݌J‚èã‚°‚Ü‚·(Banker's rounding)B</TD></TR>
-<TR><TD>ROUND_CEILING</TD><TD>”’l‚̑傫‚¢•û‚ÉŒJ‚èã‚°‚Ü‚·(ceil)B</TD></TR>
-<TR><TD>ROUND_FLOOR</TD><TD>”’l‚̬‚³‚¢•û‚ÉŒJ‚艺‚°‚Ü‚·(floor)B</TD></TR>
-
-</TABLE>
-–ß‚è’l‚ÍŽw’èŒã‚Ì flag ‚Ì’l‚Å‚·B
-‘æ‚Qˆø”‚É nil ‚ðŽw’è‚·‚邯AŒ»ó‚ÌÝ’è’l‚ª•Ô‚è‚Ü‚·B
-mode ƒƒ\ƒbƒh‚ł͊ۂߑ€ì‚̈ʒu‚ðƒ†[ƒU‚ªŽw’è‚·‚邱‚Ƃ͂ł«‚Ü‚¹‚ñB
-ŠÛ‚ß‘€ì‚ƈʒu‚ðŽ©•ª‚ŧŒä‚µ‚½‚¢ê‡‚Í BigDecimal::limit ‚â truncate/round/ceil/floorA
-add/sub/mult/div ‚Æ‚¢‚Á‚½ƒCƒ“ƒXƒ^ƒ“ƒXƒƒ\ƒbƒh‚ðŽg—p‚µ‚ĉº‚³‚¢B
-</BLOCKQUOTE>
-<LI><B>limit([n])</B></LI><BLOCKQUOTE>
-¶¬‚³‚ê‚éBigDecimalƒIƒuƒWƒFƒNƒg‚Ìő包”‚ðnŒ…‚ɧŒÀ‚µ‚Ü‚·B
-–ß‚è’l‚ÍÝ’è‚·‚é‘O‚Ì’l‚Å‚·BÝ’è’l‚̃fƒtƒHƒ‹ƒg’l‚Í‚O‚ÅAŒ…”–³§ŒÀ‚Æ‚¢‚¤ˆÓ–¡‚Å‚·B
-n ‚ðŽw’肵‚È‚¢A‚Ü‚½‚Í n ‚ª nil ‚ÌꇂÍAŒ»ó‚Ìő包”‚ª•Ô‚è‚Ü‚·B<BR>
-ŒvŽZ‚ð‘±s‚·‚éŠÔ‚ÉA”Žš‚ÌŒ…”‚ª–³§ŒÀ‚É‘‚¦‚Ä‚µ‚Ü‚¤‚悤‚Èê‡
- limit ‚Å—\‚ߌ…”‚ð§ŒÀ‚Å‚«‚Ü‚·B‚±‚Ìê‡ BigDecimal.mode ‚ÅŽw’肳‚ꂽ
-ŠÛ‚߈—‚ªŽÀs‚³‚ê‚Ü‚·B
-‚½‚¾‚µAƒCƒ“ƒXƒ^ƒ“ƒXƒƒ\ƒbƒh (truncate/round/ceil/floor/add/sub/mult/div) ‚Ì
-Œ…”§ŒÀ‚Í limit ‚æ‚è—D悳‚ê‚Ü‚·B<BR>
-mf = BigDecimal::limit(n)<BR>
-</BLOCKQUOTE>
-
-<LI><B>double_fig</B></LI><BLOCKQUOTE>
-Ruby ‚Ì Float ƒNƒ‰ƒX‚ª•ÛŽ‚Å‚«‚é—LŒø”Žš‚Ì”‚ð•Ô‚µ‚Ü‚·B
-<CODE><PRE>
- p BigDecimal::double_fig # ==> 20 (depends on the CPU etc.)
-</PRE></CODE>
-double_fig‚͈ȉº‚Ì C ƒvƒƒOƒ‰ƒ€‚ÌŒ‹‰Ê‚Æ“¯‚¶‚Å‚·B
-<CODE><PRE>
- double v = 1.0;
- int double_fig = 0;
- while(v + 1.0 > 1.0) {
- ++double_fig;
- v /= 10;
- }
-</PRE></CODE>
-</BLOCKQUOTE>
-
-<LI><B>BASE</B></LI><BLOCKQUOTE>
-“à•”‚ÅŽg—p‚³‚ê‚éŠî”‚Ì’l‚Å‚·B®”‚ª 32 ƒrƒbƒg‚̈—Œn‚Å‚Í10000‚Å‚·B<BR>
-b = BigDecimal::BASE<BR>
-</BLOCKQUOTE>
-</UL>
-
-<H4><U>ƒCƒ“ƒXƒ^ƒ“ƒXƒƒ\ƒbƒh</U></H4>
-<UL>
-<LI><B>+</B></LI><BLOCKQUOTE>
-‰ÁŽZic = a + bj<BR>
-c ‚̸“x‚ɂ‚¢‚Ä‚Íu<A HREF="#PREC">ŒvŽZ¸“x‚ɂ‚¢‚Ä</A>v‚ðŽQÆ‚µ‚Ä‚­‚¾‚³‚¢B
-</BLOCKQUOTE>
-
-<LI><B>-</B></LI><BLOCKQUOTE>
-Œ¸ŽZic = a - bjA‚Ü‚½‚Í•„†”½“]ic = -aj<BR>
-c ‚̸“x‚ɂ‚¢‚Ä‚Íu<A HREF="#PREC">ŒvŽZ¸“x‚ɂ‚¢‚Ä</A>v‚ðŽQÆ‚µ‚Ä‚­‚¾‚³‚¢B
-
-</BLOCKQUOTE>
-<LI><B>*</B></LI><BLOCKQUOTE>
-æŽZ(c = a * b)<BR>
-c‚̸“x‚Í(a‚̸“x)+(b‚̸“x)’ö“x‚Å‚·B<br>
-Ú‚µ‚­‚Íu<A HREF="#PREC">ŒvŽZ¸“x‚ɂ‚¢‚Ä</A>v‚ðŽQÆ‚µ‚Ä‚­‚¾‚³‚¢B
-
-</BLOCKQUOTE>
-<LI><B>/</B></LI><BLOCKQUOTE>
-œŽZ(c = a / b)<BR>
-c ‚̸“x‚ɂ‚¢‚Ä‚Íu<A HREF="#PREC">ŒvŽZ¸“x‚ɂ‚¢‚Ä</A>v‚ðŽQÆ‚µ‚Ä‚­‚¾‚³‚¢B
-
-</BLOCKQUOTE>
-
-<LI><B>add(b,n)</B></LI><BLOCKQUOTE>
-ˆÈ‰º‚̂悤‚ÉŽg—p‚µ‚Ü‚·B<BR>
-c = a.add(b,n)<BR>
-c = a + b ‚ðÅ‘å‚Å n Œ…‚܂ŌvŽZ‚µ‚Ü‚·B<BR>
-a + b ‚̸“x‚ª n ‚æ‚è‘å‚«‚¢‚Æ‚«‚Í BigDecimal.mode ‚ÅŽw’肳‚ꂽ•û–@‚ÅŠÛ‚ß‚ç‚ê‚Ü‚·B<BR>
-n ‚ªƒ[ƒ‚È‚ç + ‚Æ“¯‚¶‚Å‚·B
-</BLOCKQUOTE>
-<LI><B>sub(b,n)</B></LI><BLOCKQUOTE>
-ˆÈ‰º‚̂悤‚ÉŽg—p‚µ‚Ü‚·B<BR>
-c = a.sub(b,n)<BR>
-c = a - b ‚ðÅ‘å‚Å n Œ…‚܂ŌvŽZ‚µ‚Ü‚·B<BR>
-a - b ‚̸“x‚ª n ‚æ‚è‘å‚«‚¢‚Æ‚«‚Í BigDecimal.mode ‚ÅŽw’肳‚ꂽ•û–@‚ÅŠÛ‚ß‚ç‚ê‚Ü‚·B<BR>
-n ‚ªƒ[ƒ‚È‚ç - ‚Æ“¯‚¶‚Å‚·B
-
-</BLOCKQUOTE>
-<LI><B>mult(b,n)</B></LI><BLOCKQUOTE>
-ˆÈ‰º‚̂悤‚ÉŽg—p‚µ‚Ü‚·B<BR>
-c = a.mult(b,n)<BR>
-c = a * b ‚ðÅ‘å‚Å n Œ…‚܂ŌvŽZ‚µ‚Ü‚·B<BR>
-a * b ‚̸“x‚ª n ‚æ‚è‘å‚«‚¢‚Æ‚«‚Í BigDecimal.mode ‚ÅŽw’肳‚ꂽ•û–@‚ÅŠÛ‚ß‚ç‚ê‚Ü‚·B<BR>
-n ‚ªƒ[ƒ‚È‚ç * ‚Æ“¯‚¶‚Å‚·B
-
-</BLOCKQUOTE>
-<LI><B>div(b[,n])</B></LI><BLOCKQUOTE>
-ˆÈ‰º‚̂悤‚ÉŽg—p‚µ‚Ü‚·B<BR>
-c = a.div(b,n)<BR>
-c = a / b ‚ðÅ‘å‚Å n Œ…‚܂ŌvŽZ‚µ‚Ü‚·B
-a / b ‚̸“x‚ª n ‚æ‚è‘å‚«‚¢‚Æ‚«‚Í BigDecimal.mode ‚ÅŽw’肳‚ꂽ•û–@‚ÅŠÛ‚ß‚ç‚ê‚Ü‚·B<BR>
-n ‚ªƒ[ƒ‚È‚ç / ‚Æ“¯‚¶‚Å‚·B<BR>
-n ‚ªÈ—ª‚³‚ꂽ‚Æ‚«‚Í Float#div ‚Æ“¯—l‚ÉŒ‹‰Ê‚ª®”(BigDecimal)‚ɂȂè‚Ü‚·B
-</BLOCKQUOTE>
-
-<LI><B>fix</B></LI><BLOCKQUOTE>
-a ‚̬”“_ˆÈ‰º‚ÌØ‚èŽÌ‚ÄB<BR>
-c = a.fix
-</BLOCKQUOTE>
-<LI><B>frac</B></LI><BLOCKQUOTE>
-a ‚Ì®”•”•ª‚ÌØ‚èŽÌ‚ÄB<BR>
-c = a.frac
-</BLOCKQUOTE>
-
-<LI><B>floor[(n)]</B></LI><BLOCKQUOTE>
-c = a.floor<BR>
-a ˆÈ‰º‚Ìő宔iBigDecimal ’lj‚ð•Ô‚µ‚Ü‚·B
-<CODE><PRE>
-c = BigDecimal("1.23456").floor # ==> 1
-c = BigDecimal("-1.23456").floor # ==> -2
-</PRE></CODE>
-ˆÈ‰º‚̂悤‚Ɉø” n ‚ð—^‚¦‚邱‚Æ‚à‚Å‚«‚Ü‚·B<BR>
-n>=0 ‚È‚çA¬”“_ˆÈ‰º n+1 ˆÊ‚Ì”Žš‚ð‘€ì‚µ‚Ü‚·(­”“_ˆÈ‰º‚ðAÅ‘å n Œ…‚É‚µ‚Ü‚·)B<BR>
-n ‚ª•‰‚̂Ƃ«‚ͬ”“_ˆÈã n Œ…–Ú‚ð‘€ì‚µ‚Ü‚·(¬”“_ˆÊ’u‚©‚ç¶‚É­‚È‚­‚Æ‚à n ŒÂ‚Ì 0 ‚ª•À‚т܂·)B<BR>
-<CODE><PRE>
- c = BigDecimal("1.23456").floor(4) # ==> 1.2345
- c = BigDecimal("15.23456").floor(-1) # ==> 10.0
-</PRE></CODE>
-
-</BLOCKQUOTE>
-<LI><B>ceil[(n)]</B></LI><BLOCKQUOTE>
-c = a.ceil<BR>
-a ˆÈã‚Ì®”‚Ì‚¤‚¿Ałଂ³‚¢®”‚ðŒvŽZ‚µA‚»‚Ì’liBigDecimal ’lj‚ð•Ô‚µ‚Ü‚·B
-<CODE><PRE>
-c = BigDecimal("1.23456").ceil # ==> 2
-c = BigDecimal("-1.23456").ceil # ==> -1
-</PRE></CODE>
-
-ˆÈ‰º‚̂悤‚Ɉø”‚ð—^‚¦‚ÄA¬”“_ˆÈ‰º n+1 ˆÊ‚Ì”Žš‚ð‘€ì‚·‚邱‚Æ‚à‚Å‚«‚Ü‚·B<BR>
-n>=0 ‚È‚çA¬”“_ˆÈ‰º n+1 ˆÊ‚Ì”Žš‚ð‘€ì‚µ‚Ü‚·(­”“_ˆÈ‰º‚ðAÅ‘å n Œ…‚É‚µ‚Ü‚·)B<BR>
- n ‚ª•‰‚̂Ƃ«‚ͬ”“_ˆÈã n Œ…–Ú‚ð‚ð‘€ì‚µ‚Ü‚·(¬”“_ˆÊ’u‚©‚ç¶‚É­‚È‚­‚Æ‚à n ŒÂ‚Ì 0 ‚ª•À‚т܂·)B<BR>
-<CODE><PRE>
- c = BigDecimal("1.23456").ceil(4) # ==> 1.2346
- c = BigDecimal("15.23456").ceil(-1) # ==> 20.0
-</PRE></CODE>
-
-</BLOCKQUOTE>
-<LI><B>round[(n[,b])]</B></LI><BLOCKQUOTE>
-c = a.round<BR>
-
-ƒNƒ‰ƒXƒƒ\ƒbƒh BigDecimal::mode(BigDecimal::ROUND_MODE,flag) ‚ÅŽw’肵‚½
-ROUND_MODE ‚É]‚Á‚ÄŠÛ‚ß‘€ì‚ðŽÀs‚µ‚Ü‚·B
-BigDecimal::mode(BigDecimal::ROUND_MODE,flag) ‚ʼn½‚àŽw’肹‚¸A‚©‚ÂAˆø”
-‚ðŽw’肵‚È‚¢ê‡‚Íu¬”“_ˆÈ‰º‘æˆêˆÊ‚Ì”‚ðŽlŽÌŒÜ“ü‚µ‚Ä®”iBigDecimal ’ljv‚É‚µ‚Ü‚·B<BR>
-<CODE><PRE>
- c = BigDecimal("1.23456").round # ==> 1
- c = BigDecimal("-1.23456").round # ==> -1
-</PRE></CODE>
-
-ˆÈ‰º‚̂悤‚Ɉø”‚ð—^‚¦‚ÄA¬”“_ˆÈ‰º n+1 ˆÊ‚Ì”Žš‚ð‘€ì‚·‚邱‚Æ‚à‚Å‚«‚Ü‚·B<BR>
-n ‚ª³‚ÌŽž‚ÍA¬”“_ˆÈ‰º n+1 ˆÊ‚Ì”Žš‚ðŠÛ‚߂܂·(­”“_ˆÈ‰º‚ðAÅ‘å n Œ…‚É‚µ‚Ü‚·)B<BR>
-n ‚ª•‰‚̂Ƃ«‚ͬ”“_ˆÈã n Œ…–Ú‚ðŠÛ‚߂܂·(¬”“_ˆÊ’u‚©‚ç¶‚É­‚È‚­‚Æ‚à n ŒÂ‚Ì 0 ‚ª•À‚т܂·)B
-<CODE><PRE>
-c = BigDecimal("1.23456").round(4) # ==> 1.2346
-c = BigDecimal("15.23456").round(-1) # ==> 20.0
-</PRE></CODE>
-‚Q”Ԗڂ̈ø”‚ðŽw’è‚·‚邯ABigDecimal#mode ‚ÌŽw’è‚𖳎‹‚µ‚ÄAŽw’肳‚ꂽ•û–@‚Å
-ŠÛ‚ß‘€ì‚ðŽÀs‚µ‚Ü‚·B
-<CODE><PRE>
-c = BigDecimal("1.23456").round(3,BigDecimal::ROUND_HALF_EVEN) # ==> 1.234
-c = BigDecimal("1.23356").round(3,BigDecimal::ROUND_HALF_EVEN) # ==> 1.234
-</PRE></CODE>
-
-</BLOCKQUOTE>
-<LI><B>truncate</B></LI><BLOCKQUOTE>
-c = a.truncate<BR>
-¬”“_ˆÈ‰º‚Ì”‚ðØ‚èŽÌ‚ĂĮ”iBigDecimal ’lj‚É‚µ‚Ü‚·B<BR>
-ˆÈ‰º‚̂悤‚Ɉø”‚ð—^‚¦‚ÄA¬”“_ˆÈ‰º n+1 ˆÊ‚Ì”Žš‚ð‘€ì‚·‚邱‚Æ‚à‚Å‚«‚Ü‚·B<BR>
-n ‚ª³‚ÌŽž‚ÍA¬”“_ˆÈ‰º n+1 ˆÊ‚Ì”Žš‚ðØ‚èŽÌ‚Ă܂·(­”“_ˆÈ‰º‚ðAÅ‘å n Œ…‚É‚µ‚Ü‚·)B
-n ‚ª•‰‚̂Ƃ«‚ͬ”“_ˆÈã n Œ…–Ú‚ð‚ð‘€ì‚µ‚Ü‚·(¬”“_ˆÊ’u‚©‚ç¶‚É­‚È‚­‚Æ‚à n ŒÂ‚Ì 0 ‚ª•À‚т܂·)B<BR>
-<CODE><PRE>
-c = BigDecimal("1.23456").truncate(4) # ==> 1.2345
-c = BigDecimal("15.23456").truncate(-1) # ==> 10.0
-</PRE></CODE>
-</BLOCKQUOTE>
-
-</BLOCKQUOTE>
-<LI><B>abs</B></LI><BLOCKQUOTE>
-‚‚Ìâ‘Î’l<BR>
-c = a.abs<BR>
-
-</BLOCKQUOTE>
-<LI><B>to_i</B></LI><BLOCKQUOTE>
-­”“_ˆÈ‰º‚ðØ‚èŽÌ‚ĂĮ”‚ɕϊ·‚µ‚Ü‚·B<BR>
-i = a.to_i<BR>
-i ‚Í’l‚ɉž‚¶‚Ä Fixnum ‚© Bignum ‚ɂȂè‚Ü‚·B
-a ‚ª Infinity ‚â NaN ‚̂Ƃ«Ai ‚Í nil ‚ɂȂè‚Ü‚·B
-</BLOCKQUOTE>
-<LI><B>to_f</B></LI><BLOCKQUOTE>
-Float ƒIƒuƒWƒFƒNƒg‚ɕϊ·‚µ‚Ü‚·B
-‚æ‚è‚«‚ßׂ©‚¢’l‚ª•K—v‚È‚ç‚Î split ƒƒ\ƒbƒh‚ð—˜—p‚µ‚Ä
-‚­‚¾‚³‚¢B
-</BLOCKQUOTE>
-<LI><B>to_s[(n)]</B></LI><BLOCKQUOTE>
-•¶Žš—ñ‚ɕϊ·‚µ‚Ü‚·(ƒfƒtƒHƒ‹ƒg‚Í "0.xxxxxEn" ‚ÌŒ`‚ɂȂè‚Ü‚·jB
-<CODE><PRE>
-BigDecimal("1.23456").to_s # ==> "0.123456E1"
-</PRE></CODE>
-ˆø” n ‚ɳ‚Ì®”‚ªŽw’肳‚ꂽ‚Æ‚«‚ÍA­”“_‚Å•ª‚¯‚ç‚ê‚鶉E•”•ª‚ðA‚»‚ꂼ‚ê n Œ…–ˆ
-‚É‹ó”’‚Å‹æØ‚è‚Ü‚·B
-<CODE><PRE>
-BigDecimal("0.1234567890123456789").to_s(10) # ==> "0.1234567890 123456789E0"
-</PRE></CODE>
-ˆø” n ‚ɳ‚Ì®”‚ð•\‚·•¶Žš—ñ‚ðŽw’è‚·‚邱‚Æ‚à‚Å‚«‚Ü‚·B
-<CODE><PRE>
-BigDecimal("0.1234567890123456789").to_s("10") # ==> "0.1234567890 123456789E0"
-</PRE></CODE>
-•¶Žš—ñ‚Ìʼn‚É '+'i‚Ü‚½‚Í ' 'j‚ð•t‚¯‚邯A’l‚ª³‚Ìê‡A擪‚É '+'i‚Ü‚½‚Í ' 'j‚ª•t‚«‚Ü‚·
-i•‰‚ÌꇂÍAí‚É '-' ‚ª•t‚«‚Ü‚·BjB
-<CODE><PRE>
-BigDecimal("0.1234567890123456789").to_s(" 10") # ==> " 0.1234567890 123456789E0"
-BigDecimal("0.1234567890123456789").to_s("+10") # ==> "+0.1234567890 123456789E0"
-BigDecimal("-0.1234567890123456789").to_s("10") # ==> "-0.1234567890 123456789E0"
-</PRE></CODE>
-
-‚³‚ç‚É•¶Žš—ñ‚ÌÅŒã‚É E(‚Ü‚½‚Í e) ‚© F(‚Ü‚½‚Í f) ‚ðŽw’è‚·‚邱‚Æ‚ÅAˆÈ‰º‚̂悤‚É
-•\ަŒ`Ž®‚ð•ÏX‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B
-<CODE><PRE>
-BigDecimal("1234567890.123456789").to_s("E") # ==> "0.1234567890123456789E10"
-BigDecimal("1234567890.123456789").to_s("F") # ==> "1234567890.123456789"
-BigDecimal("1234567890.123456789").to_s("5E") # ==> "0.12345 67890 12345 6789E10"
-BigDecimal("1234567890.123456789").to_s("5F") # ==> "12345 67890.12345 6789"
-</PRE></CODE>
-
-</BLOCKQUOTE>
-<LI><B>exponent</B></LI><BLOCKQUOTE>
-Žw”•”‚ð®”’l‚ŕԂµ‚Ü‚·B
-n = a.exponent <BR>
-‚Í a ‚Ì’l‚ª 0.xxxxxxx*10**n ‚ðˆÓ–¡‚µ‚Ü‚·B
-</BLOCKQUOTE>
-
-<LI><B>precs</B></LI><BLOCKQUOTE>
-n,m = a.precs<BR>
-a ‚Ì—LŒø”Žš (n) ‚ÆÅ‘å—LŒø”Žš (m) ‚Ì”z—ñ‚ð•Ô‚µ‚Ü‚·B
-
-</BLOCKQUOTE>
-
-<LI><B>sign</B></LI><BLOCKQUOTE>
-’l‚ª³(sign &gt; 0)A•‰(sign &lt; 0)A‚»‚Ì‘¼(sigh==0)‚Å‚ ‚é‚©‚Ìî•ñ‚ð•Ô‚µ‚Ü‚·B
-n = a.sign <BR>
-‚Æ‚µ‚½‚Æ‚« n ‚Ì’l‚Í a ‚ªˆÈ‰º‚̂Ƃ«‚ðˆÓ–¡‚µ‚Ü‚·B<BR>
-() ‚Ì’†‚Ì”Žš‚ÍAŽÀÛ‚Ì’l‚Å‚·(<A HREF="#STRUCT">u“à•”\‘¢v</A>‚ðŽQÆ)B<BR>
-n = BigDecimal::SIGN_NaN(0) : a ‚Í NaN<BR>
-n = BigDecimal::SIGN_POSITIVE_ZERO(1) : a ‚Í +0<BR>
-n = BigDecimal::SIGN_NEGATIVE_ZERO(-1) : a ‚Í -0<BR>
-n = BigDecimal::SIGN_POSITIVE_FINITE(2) : a ‚ͳ‚Ì’l<BR>
-n = BigDecimal::SIGN_NEGATIVE_FINITE(-2) : a ‚Í•‰‚Ì’l<BR>
-n = BigDecimal::SIGN_POSITIVE_INFINITE(3) : a ‚Í+Infinity<BR>
-n = BigDecimal::SIGN_NEGATIVE_INFINITE(-3) : a ‚Í-Infinity<BR>
-
-</BLOCKQUOTE>
-<LI><B>nan?</B></LI><BLOCKQUOTE>
-a.nan? ‚Í a ‚ªNaN‚̂Ƃ«^‚ð•Ô‚µ‚Ü‚·B
-</BLOCKQUOTE>
-<LI><B>infinite?</B></LI><BLOCKQUOTE>
-a.infinite? ‚Í a ‚ª+‡‚̂Ƃ« 1 A-‡‚̂Ƃ«‚Í -1A‚»‚êˆÈŠO‚̂Ƃ«‚Í nil ‚ð•Ô‚µ‚Ü‚·B
-</BLOCKQUOTE>
-<LI><B>finite?</B></LI><BLOCKQUOTE>
-a.finite? ‚Í a ‚ª‡‚Ü‚½‚Í NaN ‚łȂ¢‚Æ‚«^‚ð•Ô‚µ‚Ü‚·B
-</BLOCKQUOTE>
-
-<LI><B>zero?</B></LI><BLOCKQUOTE>
-a ‚ª 0 ‚È‚ç true ‚ɂȂè‚Ü‚·B<BR>
-c = a.zero?
-</BLOCKQUOTE>
-<LI><B>nonzero?</B></LI><BLOCKQUOTE>
-a ‚ª 0 ‚È‚ç nilA0 ˆÈŠO‚È‚ç a ‚»‚Ì‚à‚Ì‚ª•Ô‚è‚Ü‚·B<BR>
-c = a.nonzero?
-
-</BLOCKQUOTE>
-<LI><B>split</B></LI><BLOCKQUOTE>
-BigDecimal ’l‚ð 0.xxxxxxx*10**n ‚Æ•\Œ»‚µ‚½‚Æ‚«‚ÉA•„†iNaN‚̂Ƃ«‚Í
-0A‚»‚êˆÈŠO‚Í+1‚©-1‚ɂȂè‚Ü‚·jA
-‰¼”•”•ª‚Ì•¶Žš—ñi"xxxxxxx"j‚ÆAŠî”i10jAX‚ÉŽw” n ‚ð”z—ñ‚Å
-•Ô‚µ‚Ü‚·B<BR>
-a=BigDecimal::new("3.14159265")<BR>
-f,x,y,z = a.split<BR>
-‚Æ‚·‚邯Af=+1Ax="314159265"Ay=10Az=1‚ɂȂè‚Ü‚·B<BR>
-]‚Á‚ÄA<BR>
-s = "0."+x<BR>
-b = f*(s.to_f)*(y**z)<BR>
-‚Å Float ‚ɕϊ·‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B
-</BLOCKQUOTE>
-<LI><B>inspect</B></LI><BLOCKQUOTE>
-ƒfƒoƒbƒOo—͂Ɏg—p‚³‚ê‚Ü‚·B<BR>
-p a=BigDecimal::new("3.14",10)<BR>
-‚Æ‚·‚邯A[0x112344:'0.314E1',4(12)]‚̂悤‚Éo—Í‚³‚ê‚Ü‚·B
-ʼn‚Ì16i”‚̓IƒuƒWƒFƒNƒg‚̃AƒhƒŒƒXAŽŸ‚Ì '0.314E1' ‚Í’lA
-ŽŸ‚Ì4‚ÍŒ»Ý‚Ì—LŒøŒ…”(•\ަ‚æ‚èŽáб‘å‚«‚¢‚±‚Æ‚ª‚ ‚è‚Ü‚·)A
-ÅŒã‚̓IƒuƒWƒFƒNƒg‚ªŽæ‚蓾‚éő包”‚ɂȂè‚Ü‚·B
-</BLOCKQUOTE>
-<LI><B>**</B></LI><BLOCKQUOTE>
-a ‚Ì n æ‚ðŒvŽZ‚µ‚Ü‚·B‚Ž‚Í®”B<BR>
-c = a ** n<BR>
-Œ‹‰Ê‚Æ‚µ‚Ä c ‚Ì—LŒøŒ…‚Í a ‚Ì n ”{ˆÈã‚ɂȂé‚̂ŒˆÓB
-</BLOCKQUOTE>
-<LI><B>power</B></LI><BLOCKQUOTE>
-** ‚Æ“¯‚¶‚ÅAa ‚Ì n æ‚ðŒvŽZ‚µ‚Ü‚·B‚Ž‚Í®”B<BR>
-c = a.power(n)<BR>
-Œ‹‰Ê‚Æ‚µ‚Ä c ‚Ì—LŒøŒ…‚Í a ‚Ì n ”{ˆÈã‚ɂȂé‚̂ŒˆÓB
-</BLOCKQUOTE>
-<LI><B>sqrt</B></LI><BLOCKQUOTE>
-a‚Ì—LŒøŒ… n Œ…‚Ì•½•ûªin ‚Ì•½•ûª‚ł͂ ‚è‚Ü‚¹‚ñj‚ð
-ƒjƒ…[ƒgƒ“–@‚ÅŒvŽZ‚µ‚Ü‚·B<BR>
-c = a.sqrt(n)<BR>
-</BLOCKQUOTE>
-
-<LI><B>divmod,quo,modulo,%,remainder</B></LI><BLOCKQUOTE>
-Úׂ͑Ήž‚·‚é Float ‚ÌŠeƒƒ\ƒbƒh‚ðŽQÆ‚µ‚ĉº‚³‚¢B
-</BLOCKQUOTE>
-
-<LI><B>&lt=&gt</B></LI><BLOCKQUOTE>
-a==b ‚È‚ç 0Aa &gt b ‚È‚ç 1Aa &lt b ‚È‚ç -1 ‚ɂȂè‚Ü‚·B<BR>
-c = a &lt=&gt b
-</BLOCKQUOTE>
-</UL>
-Œã‚ÍA“Ç‚ñ‚ÅŽš‚Ì”@‚­‚Å‚·B<BR>
-<UL>
-<LI><B>==</B></LI>
-<LI><B>===</B></LI>
-u==v‚Æ“¯‚¶‚Å‚·‚ª case •¶‚ÅŽg—p‚³‚ê‚Ü‚·B
-<LI><B>!=</B></LI>
-<LI><B>&lt</B></LI>
-<LI><B>&lt=</B></LI>
-<LI><B>&gt</B></LI>
-<LI><B>&gt=</B></LI>
-</UL>
-
-<H3>coerce‚ɂ‚¢‚Ä</H3>
-BigDecimal ƒIƒuƒWƒFƒNƒg‚ªŽZp‰‰ŽZŽq‚̶‚É‚ ‚邯‚«‚ÍABigDecimal ƒIƒuƒWƒFƒNƒg‚ª
-‰E‚É‚ ‚éƒIƒuƒWƒFƒNƒg‚ð(•K—v‚È‚ç) BigDecimal ‚ɕϊ·‚µ‚Ä‚©‚çŒvŽZ‚µ‚Ü‚·B
-]‚Á‚ÄABigDecimal ƒIƒuƒWƒFƒNƒgˆÈŠO‚Å‚à”’l‚ðˆÓ–¡‚·‚é‚à‚̂Ȃç‰E‚É’u‚¯‚Î
-‰‰ŽZ‚͉”\‚Å‚·B<BR>
-‚½‚¾‚µA•¶Žš—ñ‚Íi’Êíj”’l‚ÉŽ©“®•ÏŠ·‚·‚邱‚Ƃ͂ł«‚Ü‚¹‚ñB
-•¶Žš—ñ‚ð”’l‚ÉŽ©“®•ÏŠ·‚µ‚½‚¢ê‡‚Í bigfloat.c ‚Ì
-u/* #define ENABLE_NUMERIC_STRING */v‚̃Rƒƒ“ƒg‚ðŠO‚µ‚Ä‚©‚çA
-ăRƒ“ƒpƒCƒ‹AăCƒ“ƒXƒg[ƒ‹‚·‚é•K—v‚ª‚ ‚è‚Ü‚·B
-•¶Žš—ñ‚Å”’l‚ð—^‚¦‚éꇂ͒ˆÓ‚ª•K—v‚Å‚·B”’l‚ɕϊ·‚Å‚«‚È‚¢•¶Žš‚ª‚ ‚邯A
-’P‚ɕϊ·‚ðŽ~‚߂邾‚¯‚ŃGƒ‰[‚ɂ͂Ȃè‚Ü‚¹‚ñB"10XX"‚È‚ç‚P‚OA"XXXX"‚Í‚O
-‚ƈµ‚í‚ê‚Ü‚·B<BR>
-<CODE><PRE>
- a = BigDecimal.E(20)
- c = a * "0.123456789123456789123456789" # •¶Žš‚ð BigDecimal ‚ɕϊ·‚µ‚Ä‚©‚çŒvŽZ
-</PRE></CODE>
-–³ŒÀ‘å‚â”ñ”‚ð•\‚·•¶Žš‚Æ‚µ‚ÄA"Infinity"A"+Infinity"A"-Infinity"A"NaN"
-‚àŽg—p‚Å‚«‚Ü‚·(‘å•¶ŽšE¬•¶Žš‚ð‹æ•Ê‚µ‚Ü‚·)B‚½‚¾‚µAmode ƒƒ\ƒbƒh‚Å false ‚ð
-Žw’肵‚½ê‡‚Í—áŠO‚ª”­¶‚µ‚Ü‚·B
-<BR>
-‚Ü‚½ABigDecimalƒNƒ‰ƒX‚Í coerceiRuby–{ŽQÆj‚ðƒTƒ|[ƒg‚µ‚Ä‚¢‚Ü‚·B
-]‚Á‚ÄABigDecimal ƒIƒuƒWƒFƒNƒg‚ª‰E‚É‚ ‚éꇂà‘å’ï‚Í‘åä•v‚Å‚·B
-‚½‚¾AŒ»Ý‚Ì Ruby ƒCƒ“ƒ^ƒvƒŠƒ^‚ÌŽd—lãA•¶Žš—ñ‚ª¶‚É‚ ‚邯ŒvŽZ‚Å‚«‚Ü‚¹‚ñB<BR>
-<CODE><PRE>
- a = BigDecimal.E(20)
- c = "0.123456789123456789123456789" * a # ƒGƒ‰[
-</PRE></CODE>
-•K—v«‚ª‚ ‚邯‚ÍŽv‚¢‚Ü‚¹‚ñ‚ªA‚Ç‚¤‚µ‚Ä‚à‚ÆŒ¾‚¤l‚Í
- String ƒIƒuƒWƒFƒNƒg‚ðŒp³‚µ‚½V‚½‚ȃNƒ‰ƒX‚ð쬂µ‚Ä‚©‚çA
-‚»‚̃Nƒ‰ƒX‚Å coerce ‚ðƒTƒ|[ƒg‚µ‚Ä‚­‚¾‚³‚¢B
-
-<hr>
-<A NAME="#UNDEF">
-<H2>–³ŒÀA”ñ”Aƒ[ƒ‚̈µ‚¢</H2>
-u–³ŒÀv‚Ƃ͕\Œ»‚Å‚«‚È‚¢‚­‚ç‚¢‘å‚«‚È”‚Å‚·B“Á•ʂɈµ‚¤‚½‚ß‚É
- +Infinityi³‚Ì–³ŒÀ‘åj‚â -Infinityi•‰‚Ì–³ŒÀ‘åj‚Æ‚¢‚¤
-‚悤‚É•\‹L‚³‚ê‚Ü‚·B
-–³ŒÀ‚Í 1.0/0.0 ‚̂悤‚Ƀ[ƒ‚ÅŠ„‚邿‚¤‚ÈŒvŽZ‚ð‚µ‚½‚Æ‚«‚ɶ¬‚³‚ê‚Ü‚·B
-<BR><BR>
-u”ñ”v‚Í 0.0/0.0 ‚â Infinity-Infinity “™‚ÌŒ‹‰Ê‚ª’è‹`‚Å‚«‚È‚¢
-ŒvŽZ‚ð‚µ‚½‚Æ‚«‚ɶ¬‚³‚ê‚Ü‚·B”ñ”‚Í NaNiNot a Numberj‚Æ•\‹L‚³‚ê‚Ü‚·B
-NaN ‚ðŠÜ‚ÞŒvŽZ‚Í‘S‚Ä NaN ‚ɂȂè‚Ü‚·B‚Ü‚½ NaN ‚ÍŽ©•ª‚àŠÜ‚ß‚ÄA‚Ç‚ñ‚È”
-‚Æ‚àˆê’v‚µ‚Ü‚¹‚ñB
-<BR><BR>
-ƒ[ƒ‚Í +0.0 ‚Æ -0.0 ‚ª‘¶Ý‚µ‚Ü‚·B‚½‚¾‚µA+0.0==-0.0 ‚Í true ‚Å‚·B
-<BR><BR>
-InfinityANaNA +0.0 ‚Æ -0.0 “™‚ðŠÜ‚ñ‚¾ŒvŽZŒ‹‰Ê‚Í‘g‚݇‚킹‚É
-‚æ‚è•¡ŽG‚Å‚·B‹»–¡‚Ì‚ ‚él‚ÍAˆÈ‰º‚̃vƒƒOƒ‰ƒ€‚ðŽÀs‚µ‚ÄŒ‹‰Ê‚ð
-Šm”F‚µ‚Ä‚­‚¾‚³‚¢iŒ‹‰Ê‚ɂ‚¢‚ÄA‹^–â‚âŠÔˆá‚¢‚ð”­Œ©‚³‚ꂽ•û‚Í
-‚¨’m‚点Šè‚¢‚Ü‚·jB
-
-<PRE>
-<CODE>
-require "bigdecimal"
-
-aa = %w(1 -1 +0.0 -0.0 +Infinity -Infinity NaN)
-ba = %w(1 -1 +0.0 -0.0 +Infinity -Infinity NaN)
-opa = %w(+ - * / <=> > >= < == != <=)
-
-for a in aa
- for b in ba
- for op in opa
- x = BigDecimal::new(a)
- y = BigDecimal::new(b)
- eval("ans= x #{op} y;print a,' ',op,' ',b,' ==> ',ans.to_s,\"\n\"")
- end
- end
-end
-</CODE>
-</PRE>
-
-<hr>
-<A NAME="#STRUCT">
-<H2>“à•”\‘¢</H2>
-BigDecimal“à•”‚Å•‚“®¬”“_‚Í\‘¢‘Ì(Real)‚Å•\Œ»‚³‚ê‚Ü‚·B
-‚»‚Ì‚¤‚¿‰¼”•”‚Í unsigned long ‚Ì”z—ñ(ˆÈ‰º‚Ì\‘¢‘Ì—v‘ffrac)‚ÅŠÇ—‚³‚ê‚Ü‚·B
-ŠT”O“I‚É‚ÍAˆÈ‰º‚̂悤‚ɂȂè‚Ü‚·B<BR><BR>
- <•‚“®¬”“_”> = 0.xxxxxxxxx*BASE**n<BR><BR>
-‚±‚±‚ÅAx‚͉¼”•”‚ð•\‚·”ŽšABASE‚ÍŠî”i‚P‚Oi‚È‚ç‚P‚OjAn‚ÍŽw”•”‚ð•\‚·
-®”’l‚Å‚·BBASE‚ª‘å‚«‚¢‚Ù‚ÇA‘å‚«‚È”’l‚ª•\Œ»‚Å‚«‚Ü‚·B‚‚܂èA”z—ñ‚̃TƒCƒY‚ð
-­‚È‚­‚Å‚«‚Ü‚·BBASE‚͑傫‚¢‚Ù‚Ç“s‡‚ª‚æ‚¢‚킯‚Å‚·‚ªAƒfƒoƒbƒO‚Ì‚â‚è‚â‚·‚³‚Ȃǂð
-l—¶‚µ‚ÄA10000‚ɂȂÁ‚Ä‚¢‚Ü‚·iBASE‚ÍVpInit()ŠÖ”‚ÅŽ©“®“I‚ÉŒvŽZ‚µ‚Ü‚·jB
-‚±‚ê‚ÍA32ƒrƒbƒg®”‚Ìꇂł·B64ƒrƒbƒg®”‚Ìꇂ͂à‚Á‚Ƒ傫‚È’l‚ɂȂè‚Ü‚·B
-Žc”O‚È‚ª‚çA64ƒrƒbƒg®”‚ł̃eƒXƒg‚͂܂¾‚â‚Á‚Ä‚¢‚Ü‚¹‚ñi‚à‚µA‚â‚ç‚ꂽ•û‚ª‚¢‚ê‚Î
-Œ‹‰Ê‚ð‹³‚¦‚Ä‚¢‚½‚¾‚¯‚ê‚΂ ‚肪‚½‚¢‚Å‚·jB
-BASE‚ª10000‚̂Ƃ«‚ÍAˆÈ‰º‚̉¼”•”‚Ì”z—ñ(frac)‚ÌŠe—v‘f‚É‚ÍÅ‘å‚Å‚SŒ…‚Ì
-”Žš‚ªŠi”[‚³‚ê‚Ü‚·B<BR><BR>
-•‚“®¬”“_\‘¢‘Ì(Real)‚͈ȉº‚̂悤‚ɂȂÁ‚Ä‚¢‚Ü‚·B
-<BR>
-<CODE><PRE>
- typedef struct {
- unsigned long MaxPrec; // ő帓x(frac[]‚Ì”z—ñƒTƒCƒY)
- unsigned long Prec; // ¸“x(frac[]‚ÌŽg—pƒTƒCƒY)
- short sign; // ˆÈ‰º‚̂悤‚É•„†“™‚Ìó‘Ô‚ð’è‹`‚µ‚Ü‚·B
- // ==0 : NaN
- // 1 : +0
- // -1 : -0
- // 2 : ³‚Ì’l
- // -2 : •‰‚Ì’l
- // 3 : +Infinity
- // -3 : -Infinity
- unsigned short flag; // ŠeŽí‚̧Œäƒtƒ‰ƒbƒO
- int exponent; // Žw”•”‚Ì’l(‰¼”•”*BASE**exponent)
- unsigned long frac[1]; // ‰¼”•”‚Ì”z—ñ(‰Â•Ï)
- } Real;
-</CODE></PRE>
-—Ⴆ‚Î 1234.56784321 ‚Æ‚¢‚¤”Žš‚Í(BASE=10000‚È‚ç)<BR>
-<PRE>
- 0.1234 5678 4321*(10000)**1
-</PRE>
-‚Å‚·‚©‚ç frac[0]=1234Afrac[1]=5678Afrac[2]=4321A
-Prec=3Asign=2Aexponent=1 ‚ƂȂè‚Ü‚·BMaxPrec‚Í
-Prec ‚æ‚è‘å‚«‚¯‚ê‚΂¢‚­‚Â‚Å‚à‚©‚Ü‚¢‚Ü‚¹‚ñBflag ‚Ì
-Žg—p•û–@‚ÍŽÀ‘•‚Ɉˑ¶‚µ‚Ä“à•”‚ÅŽg—p‚³‚ê‚Ü‚·B
-
-<hr>
-<A NAME="#BASE">
-<H2>2i‚Æ10i</H2>
-BigDecimal ‚Í <•‚“®¬”“_”> = 0.xxxxxxxxx*10**n ‚Æ‚¢‚¤10iŒ`Ž®‚Å”’l‚ð•ÛŽ‚µ‚Ü‚·B
-‚µ‚©‚µAŒvŽZ‹@‚Ì•‚“®¬”“_”‚Ì“à•”•\Œ»‚ÍAŒ¾‚¤‚܂łà‚È‚­ <•‚“®¬”“_”> = 0.bbbbbbbb*2**n ‚Æ‚¢‚¤
-2iŒ`Ž®‚ª•’ʂł·(x ‚Í 0 ‚©‚ç 9 ‚Ü‚ÅAb ‚Í 0 ‚© 1 ‚Ì”Žš)B
-BigDecimal ‚ª‚È‚º10i‚Ì“à•”•\Œ»Œ`Ž®‚ðÌ—p‚µ‚½‚Ì‚©‚ðˆÈ‰º‚Éà–¾‚µ‚Ü‚·B
-<H4>10i‚̃ƒŠƒbƒg</H4>
-<DL>
-<DT>ƒfƒoƒbƒO‚Ì‚µ‚â‚·‚³
-<DD>‚Ü‚¸AƒvƒƒOƒ‰ƒ€ì¬‚ªŠy‚Å‚·Bfrac[0]=1234Afrac[1]=5678Afrac[2]=4321A
-exponent=1Asign=2 ‚Ȃ甒l‚ª 1234.56784321 ‚Å‚ ‚é‚̂͌©‚ê‚Î’¼‚®‚É•ª‚©‚è‚Ü‚·B
-
-<DT>10i•\‹L‚³‚ꂽ”’l‚È‚çŠmŽÀ‚É“à•”•\Œ»‚ɕϊ·‚Å‚«‚é
-<DD>—Ⴆ‚ÎAˆÈ‰º‚̂悤‚ȃvƒƒOƒ‰ƒ€‚Í‘S‚­Œë·–³‚µ‚Å
-ŒvŽZ‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·BˆÈ‰º‚Ì—á‚ÍAˆês‚Ɉê‚‚̔’l
-‚ª‘‚¢‚Ä‚ ‚éƒtƒ@ƒCƒ‹ file ‚̇Œv”’l‚ð‹‚ß‚é‚à‚̂ł·B
-<CODE><PRE>
- file = File::open(....,"r")
- s = BigDecimal::new("0")
- while line = file.gets
- s = s + line
- end
-</PRE></CODE>
-‚±‚Ì—á‚ð2i”‚Å‚â‚邯Œë·‚ª“ü‚螂މ”\«‚ª‚ ‚è‚Ü‚·B
-—Ⴆ‚Î 0.1 ‚ð2i‚Å•\Œ»‚·‚邯 0.1 = b1*2**(-1)+b1*2**(-2)+b3*2**(-3)+b4*2**(-4)....
-‚Æ–³ŒÀ‚É‘±‚¢‚Ä‚µ‚Ü‚¢‚Ü‚·(b1=0,b2=0,b3=0,b4=1...)B‚±‚±‚Å bn(n=1,2,3,...) ‚Í
-2i‚ð•\Œ»‚·‚é 0 ‚© 1 ‚Ì”Žš—ñ‚Å‚·B]‚Á‚ÄA‚Ç‚±‚©‚őł¿Ø‚é•K—v‚ª‚ ‚è‚Ü‚·B
-‚±‚±‚ŕϊ·Œë·‚ª“ü‚è‚Ü‚·B‚à‚¿‚ë‚ñA‚±‚ê‚ðÄ“x10i•\‹L‚É‚µ‚Ĉóü‚·‚邿‚¤‚È
-ꇂ͓K؂Ȋۂߑ€ìiŽlŽÌŒÜ“üj‚É‚æ‚Á‚ÄÄ‚Ñ "0.1" ‚Æ•\ަ‚³‚ê‚Ü‚·B‚µ‚©‚µA
-“à•”‚łͳŠm‚È 0.1 ‚ł͂ ‚è‚Ü‚¹‚ñB
-
-<DT>—LŒøŒ…”‚Í—LŒÀ‚Å‚ ‚éi‚‚܂莩“®Œˆ’è‚Å‚«‚éj
-<DD>0.1 ‚ð•\Œ»‚·‚邽‚߂̗̈æ‚Í‚½‚Á‚½ˆê‚‚̔z—ñ—v‘fi frac[0]=1 j‚Åς݂܂·B
-”z—ñ—v‘f‚Ì”‚Í10i”’l‚©‚玩“®“I‚ÉŒˆ’è‚Å‚«‚Ü‚·B‚±‚ê‚ÍA‰Â•Ï’·•‚“®¬”“_‰‰ŽZ‚Å‚Í
-‘厖‚È‚±‚Ƃł·B‹t‚É 0.1 ‚ð2i•\Œ»‚µ‚½‚Æ‚«‚É‚Í2i‚Ì—LŒøŒ…‚ð‚¢‚­‚‚ɂ·‚é‚Ì‚© 0.1 ‚ð
-Œ©‚½‚¾‚¯‚ł͌ˆ’è‚Å‚«‚Ü‚¹‚ñB
-</DL>
-
-<H3>10i‚̃fƒƒŠƒbƒg</H3>
-ŽÀ‚Í¡‚܂ł̃ƒŠƒbƒg‚ÍA‚»‚̂܂܃fƒƒŠƒbƒg‚É‚à‚È‚è‚Ü‚·B
-‚»‚à‚»‚àA10i‚ð2iA2i‚ð10i‚ɕϊ·‚·‚邿‚¤‚È‘€ì‚͕ϊ·Œë·
-‚𔺂¤ê‡‚ð‰ñ”ð‚·‚é‚±‚Ƃ͂ł«‚Ü‚¹‚ñB
-Šù‚ÉŒvŽZ‹@“à•”‚ÉŽæ‚螂܂ꂽ2i”’l‚ð BigDecimal ‚Ì“à•”•\Œ»‚É
-•ÏŠ·‚·‚邯‚«‚ɂ͌뷂ª”ð‚¯‚ç‚ê‚È‚¢ê‡‚ª‚ ‚è‚Ü‚·B
-
-<H3>ʼn‚͉½‚©H</H3>
-Ž©•ª‚ÅŒvŽZ‚·‚邯‚«‚ɂ킴‚í‚´2i”‚ðŽg‚¤l‚͋ɂ߂Ă܂ê‚Å‚·B
-ŒvŽZ‹@‚Ƀf[ƒ^‚ð“ü—Í‚·‚邯‚«‚à‚Ù‚Æ‚ñ‚Ç‚Ìê‡A
-10i”‚Å“ü—Í‚µ‚Ü‚·B‚»‚ÌŒ‹‰ÊAdouble “™‚ÌŒvŽZ‹@“à•”
-•\Œ»‚Íʼn‚©‚çŒë·‚ª“ü‚Á‚Ä‚¢‚éꇂª‚ ‚è‚Ü‚·B
-BigDecimal ‚̓†[ƒU“ü—Í‚ðŒë·–³‚µ‚ÅŽæ‚螂ނ±‚Æ‚ª‚Å‚«‚Ü‚·B
-ƒfƒoƒbƒO‚ª‚µ‚â‚·‚¢‚Ì‚ÆAƒf[ƒ^“ǂ݂±‚ÝŽž‚Ɍ뷂ª“ü‚ç‚È‚¢
-‚Æ‚¢‚¤‚Ì‚ªŽÀۂ̃ƒŠƒbƒg‚Å‚·B
-
-<hr>
-<A NAME="#PREC">
-<H2>ŒvŽZ¸“x‚ɂ‚¢‚Ä</H2>
-c = a op b ‚Æ‚¢‚¤ŒvŽZ(op ‚Í + - * /)‚ð‚µ‚½‚Æ‚«‚Ì“®ì‚Í
-ˆÈ‰º‚̂悤‚ɂȂè‚Ü‚·B<BR><BR>
-‚PDæŽZ‚Í(a ‚Ì—LŒøŒ…”)+(b ‚Ì—LŒøŒ…”)A
-œŽZ‚Í(a ‚ÌÅ‘å—LŒøŒ…”)+(b ‚ÌÅ‘å—LŒøŒ…”)•ª‚Ìő包”iŽÀÛ‚ÍA—]—T‚ðŽ‚Á‚ÄA
-‚à‚¤­‚µ‘å‚«‚­‚È‚è‚Ü‚·j‚ðŽ‚Â•Ï” c ‚ðV‚½‚ɶ¬‚µ‚Ü‚·B
-‰ÁŒ¸ŽZ‚ÌꇂÍAŒë·‚ªo‚È‚¢‚¾‚¯‚̸“x‚ðŽ‚Â c ‚𶬂µ‚Ü‚·B—Ⴆ‚Î
- c = 0.1+0.1*10**(-100) ‚̂悤‚Èê‡Ac ‚̸“x‚Í‚P‚O‚OŒ…ˆÈã‚̸“x‚ð
-Ž‚Â‚æ‚¤‚ɂȂè‚Ü‚·B
-<BR><BR>
-‚QDŽŸ‚É c = a op b ‚ÌŒvŽZ‚ðŽÀs‚µ‚Ü‚·B<BR><BR>
-‚±‚̂悤‚ÉA‰ÁŒ¸ŽZ‚ÆæŽZ‚Å‚Ì c ‚Í•K‚¸uŒë·‚ªo‚È‚¢v‚¾‚¯‚̸“x‚ð
-Ž‚Á‚ͬ‚³‚ê‚Ü‚·(BigDecimal.limit ‚ðŽw’肵‚È‚¢ê‡)B
-œŽZ‚Í(a ‚ÌÅ‘å—LŒøŒ…”)+(b ‚ÌÅ‘å—LŒøŒ…”)•ª‚Ìő包”
-‚ðŽ‚Â c ‚ª¶¬‚³‚ê‚Ü‚·‚ªAc = 1.0/3.0 ‚̂悤‚ÈŒvŽZ‚Å–¾‚ç‚©‚Ȃ悤‚ÉA
- c ‚Ìő帓x‚ð’´‚¦‚邯‚±‚ë‚ÅŒvŽZ‚ª‘Å‚¿Ø‚ç‚ê‚éꇂª‚ ‚è‚Ü‚·B<BR><BR>
-‚¢‚¸‚ê‚É‚¹‚æAc ‚Ìő帓x‚Í a ‚â b ‚æ‚è‘å‚«‚­‚È‚è‚Ü‚·‚̂Šc ‚ª•K—v‚Æ‚·‚é
-ƒƒ‚ƒŠ[—̈æ‚͑傫‚­‚Ȃ邱‚ƂɒˆÓ‚µ‚ĉº‚³‚¢B
-<BR><BR>
-’ˆÓFu+,-,*,/v‚ł͌‹‰Ê‚̸“xi—LŒøŒ…”j‚ðŽ©•ª‚ÅŽw’è‚Å‚«‚Ü‚¹‚ñB
-¸“x‚ðƒRƒ“ƒgƒ[ƒ‹‚µ‚½‚¢ê‡‚ÍAˆÈ‰º‚̃Cƒ“ƒXƒ^ƒ“ƒXƒƒ\ƒbƒh‚ðŽg—p‚µ‚Ü‚·B<BR>
-<UL>
-<LI>add,sub,mult,div</LI><BLOCKQUOTE>
-‚±‚ê‚ç‚̃ƒ\ƒbƒh‚Íæ“ª(Ŷ)‚Ì”Žš‚©‚ç‚ÌŒ…”‚ðŽw’è‚Å‚«‚Ü‚·B
-<CODE><PRE>
- BigDecimal("2").div(3,12) # 2.0/3.0 => 0.6666666666 67E0
-</PRE></CODE>
-</BLOCKQUOTE>
-<LI>truncate,round,ceil,floor</LI><BLOCKQUOTE>
-‚±‚ê‚ç‚̃ƒ\ƒbƒh‚ͬ”“_‚©‚ç‚Ì‘Š‘ÎˆÊ’u‚ðŽw’肵‚ÄŒ…”‚ðŒˆ’è‚µ‚Ü‚·B
-<CODE><PRE>
- BigDecimal("6.66666666666666").round(12) # => 0.6666666666 667E1
-</PRE></CODE>
-</BLOCKQUOTE>
-</UL>
-<H3>Ž©•ª‚Ÿ“x‚ðƒRƒ“ƒgƒ[ƒ‹‚µ‚½‚¢ê‡</H3>
-Ž©•ª‚Ÿ“x(—LŒøŒ…”)‚ðƒRƒ“ƒgƒ[ƒ‹‚µ‚½‚¢ê‡‚Í addAsubAmultAdiv “™‚̃ƒ\ƒbƒh
-‚ªŽg—p‚Å‚«‚Ü‚·B
-ˆÈ‰º‚̉~Žü—¦‚ðŒvŽZ‚·‚éƒvƒƒOƒ‰ƒ€—á‚̂悤‚ÉA
-‹‚߂錅”‚ÍŽ©•ª‚ÅŽw’è‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B
-<BR><BR>
-<CODE><PRE>
-#!/usr/local/bin/ruby
-
-require "bigdecimal"
-#
-# Calculates 3.1415.... (the number of times that a circle's diameter
-# will fit around the circle) using J. Machin's formula.
-#
-def big_pi(sig) # sig: Number of significant figures
- exp = -sig
- pi = BigDecimal::new("0")
- two = BigDecimal::new("2")
- m25 = BigDecimal::new("-0.04")
- m57121 = BigDecimal::new("-57121")
-
- u = BigDecimal::new("1")
- k = BigDecimal::new("1")
- w = BigDecimal::new("1")
- t = BigDecimal::new("-80")
- while (u.nonzero? && u.exponent >= exp)
- t = t*m25
- u = t.div(k,sig)
- pi = pi + u
- k = k+two
- end
-
- u = BigDecimal::new("1")
- k = BigDecimal::new("1")
- w = BigDecimal::new("1")
- t = BigDecimal::new("956")
- while (u.nonzero? && u.exponent >= exp )
- t = t.div(m57121,sig)
- u = t.div(k,sig)
- pi = pi + u
- k = k+two
- end
- pi
-end
-
-if $0 == __FILE__
- if ARGV.size == 1
- print "PI("+ARGV[0]+"):\n"
- p big_pi(ARGV[0].to_i)
- else
- print "TRY: ruby pi.rb 1000 \n"
- end
-end
-
-</PRE></CODE>
-<HR>
-<FONT size=2>
-<I>
-<A HREF="http://www.tinyforest.gr.jp">
-¬—Ñ –ΗY
-</A>
-(E-Mail:<A HREF="mailto:shigeo@tinyforest.gr.jp">&ltshigeo@tinyforest.gr.jp&gt</U></A>)
-</I>
-</FONT>
-</TD>
-</TR>
-</TABLE>
-</BODY>
-</HTML>
diff --git a/ext/bigdecimal/depend b/ext/bigdecimal/depend
deleted file mode 100644
index 402cae95dd..0000000000
--- a/ext/bigdecimal/depend
+++ /dev/null
@@ -1 +0,0 @@
-bigdecimal.o: bigdecimal.c bigdecimal.h $(hdrdir)/ruby.h
diff --git a/ext/bigdecimal/extconf.rb b/ext/bigdecimal/extconf.rb
deleted file mode 100644
index a68a656044..0000000000
--- a/ext/bigdecimal/extconf.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require 'mkmf'
-create_makefile('bigdecimal')
diff --git a/ext/bigdecimal/lib/bigdecimal/jacobian.rb b/ext/bigdecimal/lib/bigdecimal/jacobian.rb
deleted file mode 100644
index d80eeab901..0000000000
--- a/ext/bigdecimal/lib/bigdecimal/jacobian.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-#
-# require 'bigdecimal/jacobian'
-#
-# Provides methods to compute the Jacobian matrix of a set of equations at a
-# point x. In the methods below:
-#
-# f is an Object which is used to compute the Jacobian matrix of the equations.
-# It must provide the following methods:
-#
-# f.values(x):: returns the values of all functions at x
-#
-# f.zero:: returns 0.0
-# f.one:: returns 1.0
-# f.two:: returns 1.0
-# f.ten:: returns 10.0
-#
-# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
-#
-# x is the point at which to compute the Jacobian.
-#
-# fx is f.values(x).
-#
-module Jacobian
- #--
- def isEqual(a,b,zero=0.0,e=1.0e-8)
- aa = a.abs
- bb = b.abs
- if aa == zero && bb == zero then
- true
- else
- if ((a-b)/(aa+bb)).abs < e then
- true
- else
- false
- end
- end
- end
- #++
-
- # Computes the derivative of f[i] at x[i].
- # fx is the value of f at x.
- def dfdxi(f,fx,x,i)
- nRetry = 0
- n = x.size
- xSave = x[i]
- ok = 0
- ratio = f.ten*f.ten*f.ten
- dx = x[i].abs/ratio
- dx = fx[i].abs/ratio if isEqual(dx,f.zero,f.zero,f.eps)
- dx = f.one/f.ten if isEqual(dx,f.zero,f.zero,f.eps)
- until ok>0 do
- s = f.zero
- deriv = []
- if(nRetry>100) then
- raize "Singular Jacobian matrix. No change at x[" + i.to_s + "]"
- end
- dx = dx*f.two
- x[i] += dx
- fxNew = f.values(x)
- for j in 0...n do
- if !isEqual(fxNew[j],fx[j],f.zero,f.eps) then
- ok += 1
- deriv <<= (fxNew[j]-fx[j])/dx
- else
- deriv <<= f.zero
- end
- end
- x[i] = xSave
- end
- deriv
- end
-
- # Computes the Jacobian of f at x. fx is the value of f at x.
- def jacobian(f,fx,x)
- n = x.size
- dfdx = Array::new(n*n)
- for i in 0...n do
- df = dfdxi(f,fx,x,i)
- for j in 0...n do
- dfdx[j*n+i] = df[j]
- end
- end
- dfdx
- end
-end
diff --git a/ext/bigdecimal/lib/bigdecimal/ludcmp.rb b/ext/bigdecimal/lib/bigdecimal/ludcmp.rb
deleted file mode 100644
index 8f4888725e..0000000000
--- a/ext/bigdecimal/lib/bigdecimal/ludcmp.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-#
-# Solves a*x = b for x, using LU decomposition.
-#
-module LUSolve
- # Performs LU decomposition of the n by n matrix a.
- def ludecomp(a,n,zero=0,one=1)
- prec = BigDecimal.limit(nil)
- ps = []
- scales = []
- for i in 0...n do # pick up largest(abs. val.) element in each row.
- ps <<= i
- nrmrow = zero
- ixn = i*n
- for j in 0...n do
- biggst = a[ixn+j].abs
- nrmrow = biggst if biggst>nrmrow
- end
- if nrmrow>zero then
- scales <<= one.div(nrmrow,prec)
- else
- raise "Singular matrix"
- end
- end
- n1 = n - 1
- for k in 0...n1 do # Gaussian elimination with partial pivoting.
- biggst = zero;
- for i in k...n do
- size = a[ps[i]*n+k].abs*scales[ps[i]]
- if size>biggst then
- biggst = size
- pividx = i
- end
- end
- raise "Singular matrix" if biggst<=zero
- if pividx!=k then
- j = ps[k]
- ps[k] = ps[pividx]
- ps[pividx] = j
- end
- pivot = a[ps[k]*n+k]
- for i in (k+1)...n do
- psin = ps[i]*n
- a[psin+k] = mult = a[psin+k].div(pivot,prec)
- if mult!=zero then
- pskn = ps[k]*n
- for j in (k+1)...n do
- a[psin+j] -= mult.mult(a[pskn+j],prec)
- end
- end
- end
- end
- raise "Singular matrix" if a[ps[n1]*n+n1] == zero
- ps
- end
-
- # Solves a*x = b for x, using LU decomposition.
- #
- # a is a matrix, b is a constant vector, x is the solution vector.
- #
- # ps is the pivot, a vector which indicates the permutation of rows performed
- # during LU decomposition.
- def lusolve(a,b,ps,zero=0.0)
- prec = BigDecimal.limit(nil)
- n = ps.size
- x = []
- for i in 0...n do
- dot = zero
- psin = ps[i]*n
- for j in 0...i do
- dot = a[psin+j].mult(x[j],prec) + dot
- end
- x <<= b[ps[i]] - dot
- end
- (n-1).downto(0) do |i|
- dot = zero
- psin = ps[i]*n
- for j in (i+1)...n do
- dot = a[psin+j].mult(x[j],prec) + dot
- end
- x[i] = (x[i]-dot).div(a[psin+i],prec)
- end
- x
- end
-end
diff --git a/ext/bigdecimal/lib/bigdecimal/math.rb b/ext/bigdecimal/lib/bigdecimal/math.rb
deleted file mode 100644
index f3248a3c5c..0000000000
--- a/ext/bigdecimal/lib/bigdecimal/math.rb
+++ /dev/null
@@ -1,235 +0,0 @@
-#
-#--
-# Contents:
-# sqrt(x, prec)
-# sin (x, prec)
-# cos (x, prec)
-# atan(x, prec) Note: |x|<1, x=0.9999 may not converge.
-# exp (x, prec)
-# log (x, prec)
-# PI (prec)
-# E (prec) == exp(1.0,prec)
-#
-# where:
-# x ... BigDecimal number to be computed.
-# |x| must be small enough to get convergence.
-# prec ... Number of digits to be obtained.
-#++
-#
-# Provides mathematical functions.
-#
-# Example:
-#
-# require "bigdecimal"
-# require "bigdecimal/math"
-#
-# include BigMath
-#
-# a = BigDecimal((PI(100)/2).to_s)
-# puts sin(a,100) # -> 0.10000000000000000000......E1
-#
-module BigMath
-
- # Computes the square root of x to the specified number of digits of
- # precision.
- #
- # BigDecimal.new('2').sqrt(16).to_s
- # -> "0.14142135623730950488016887242096975E1"
- #
- def sqrt(x,prec)
- x.sqrt(prec)
- end
-
- # Computes the sine of x to the specified number of digits of precision.
- #
- # If x is infinite or NaN, returns NaN.
- def sin(x, prec)
- raise ArgumentError, "Zero or negative precision for sin" if prec <= 0
- return BigDecimal("NaN") if x.infinite? || x.nan?
- n = prec + BigDecimal.double_fig
- one = BigDecimal("1")
- two = BigDecimal("2")
- x1 = x
- x2 = x.mult(x,n)
- sign = 1
- y = x
- d = y
- i = one
- z = one
- while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- sign = -sign
- x1 = x2.mult(x1,n)
- i += two
- z *= (i-one) * i
- d = sign * x1.div(z,m)
- y += d
- end
- y
- end
-
- # Computes the cosine of x to the specified number of digits of precision.
- #
- # If x is infinite or NaN, returns NaN.
- def cos(x, prec)
- raise ArgumentError, "Zero or negative precision for cos" if prec <= 0
- return BigDecimal("NaN") if x.infinite? || x.nan?
- n = prec + BigDecimal.double_fig
- one = BigDecimal("1")
- two = BigDecimal("2")
- x1 = one
- x2 = x.mult(x,n)
- sign = 1
- y = one
- d = y
- i = BigDecimal("0")
- z = one
- while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- sign = -sign
- x1 = x2.mult(x1,n)
- i += two
- z *= (i-one) * i
- d = sign * x1.div(z,m)
- y += d
- end
- y
- end
-
- # Computes the arctangent of x to the specified number of digits of precision.
- #
- # If x is infinite or NaN, returns NaN.
- # Raises an argument error if x > 1.
- def atan(x, prec)
- raise ArgumentError, "Zero or negative precision for atan" if prec <= 0
- return BigDecimal("NaN") if x.infinite? || x.nan?
- raise ArgumentError, "x.abs must be less than 1.0" if x.abs>=1
- n = prec + BigDecimal.double_fig
- y = x
- d = y
- t = x
- r = BigDecimal("3")
- x2 = x.mult(x,n)
- while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- t = -t.mult(x2,n)
- d = t.div(r,m)
- y += d
- r += 2
- end
- y
- end
-
- # Computes the value of e (the base of natural logarithms) raised to the
- # power of x, to the specified number of digits of precision.
- #
- # If x is infinite or NaN, returns NaN.
- #
- # BigMath::exp(BigDecimal.new('1'), 10).to_s
- # -> "0.271828182845904523536028752390026306410273E1"
- def exp(x, prec)
- raise ArgumentError, "Zero or negative precision for exp" if prec <= 0
- return BigDecimal("NaN") if x.infinite? || x.nan?
- n = prec + BigDecimal.double_fig
- one = BigDecimal("1")
- x1 = one
- y = one
- d = y
- z = one
- i = 0
- while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- x1 = x1.mult(x,n)
- i += 1
- z *= i
- d = x1.div(z,m)
- y += d
- end
- y
- end
-
- # Computes the natural logarithm of x to the specified number of digits
- # of precision.
- #
- # Returns x if x is infinite or NaN.
- #
- def log(x, prec)
- raise ArgumentError, "Zero or negative argument for log" if x <= 0 || prec <= 0
- return x if x.infinite? || x.nan?
- one = BigDecimal("1")
- two = BigDecimal("2")
- n = prec + BigDecimal.double_fig
- x = (x - one).div(x + one,n)
- x2 = x.mult(x,n)
- y = x
- d = y
- i = one
- while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- x = x2.mult(x,n)
- i += two
- d = x.div(i,m)
- y += d
- end
- y*two
- end
-
- # Computes the value of pi to the specified number of digits of precision.
- def PI(prec)
- raise ArgumentError, "Zero or negative argument for PI" if prec <= 0
- n = prec + BigDecimal.double_fig
- zero = BigDecimal("0")
- one = BigDecimal("1")
- two = BigDecimal("2")
-
- m25 = BigDecimal("-0.04")
- m57121 = BigDecimal("-57121")
-
- pi = zero
-
- d = one
- k = one
- w = one
- t = BigDecimal("-80")
- while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- t = t*m25
- d = t.div(k,m)
- k = k+two
- pi = pi + d
- end
-
- d = one
- k = one
- w = one
- t = BigDecimal("956")
- while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- t = t.div(m57121,n)
- d = t.div(k,m)
- pi = pi + d
- k = k+two
- end
- pi
- end
-
- # Computes e (the base of natural logarithms) to the specified number of
- # digits of precision.
- def E(prec)
- raise ArgumentError, "Zero or negative precision for E" if prec <= 0
- n = prec + BigDecimal.double_fig
- one = BigDecimal("1")
- y = one
- d = y
- z = one
- i = 0
- while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- i += 1
- z *= i
- d = one.div(z,m)
- y += d
- end
- y
- end
-end
diff --git a/ext/bigdecimal/lib/bigdecimal/newton.rb b/ext/bigdecimal/lib/bigdecimal/newton.rb
deleted file mode 100644
index 59ac0f7f04..0000000000
--- a/ext/bigdecimal/lib/bigdecimal/newton.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-#
-# newton.rb
-#
-# Solves the nonlinear algebraic equation system f = 0 by Newton's method.
-# This program is not dependent on BigDecimal.
-#
-# To call:
-# n = nlsolve(f,x)
-# where n is the number of iterations required,
-# x is the initial value vector
-# f is an Object which is used to compute the values of the equations to be solved.
-# It must provide the following methods:
-#
-# f.values(x):: returns the values of all functions at x
-#
-# f.zero:: returns 0.0
-# f.one:: returns 1.0
-# f.two:: returns 1.0
-# f.ten:: returns 10.0
-#
-# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
-#
-# On exit, x is the solution vector.
-#
-require "bigdecimal/ludcmp"
-require "bigdecimal/jacobian"
-
-module Newton
- include LUSolve
- include Jacobian
-
- def norm(fv,zero=0.0)
- s = zero
- n = fv.size
- for i in 0...n do
- s += fv[i]*fv[i]
- end
- s
- end
-
- def nlsolve(f,x)
- nRetry = 0
- n = x.size
-
- f0 = f.values(x)
- zero = f.zero
- one = f.one
- two = f.two
- p5 = one/two
- d = norm(f0,zero)
- minfact = f.ten*f.ten*f.ten
- minfact = one/minfact
- e = f.eps
- while d >= e do
- nRetry += 1
- # Not yet converged. => Compute Jacobian matrix
- dfdx = jacobian(f,f0,x)
- # Solve dfdx*dx = -f0 to estimate dx
- dx = lusolve(dfdx,f0,ludecomp(dfdx,n,zero,one),zero)
- fact = two
- xs = x.dup
- begin
- fact *= p5
- if fact < minfact then
- raise "Failed to reduce function values."
- end
- for i in 0...n do
- x[i] = xs[i] - dx[i]*fact
- end
- f0 = f.values(x)
- dn = norm(f0,zero)
- end while(dn>=d)
- d = dn
- end
- nRetry
- end
-end
diff --git a/ext/bigdecimal/lib/bigdecimal/util.rb b/ext/bigdecimal/lib/bigdecimal/util.rb
deleted file mode 100644
index 09e926acd5..0000000000
--- a/ext/bigdecimal/lib/bigdecimal/util.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-#
-# BigDecimal utility library.
-#
-# To use these functions, require 'bigdecimal/util'
-#
-# The following methods are provided to convert other types to BigDecimals:
-#
-# String#to_d -> BigDecimal
-# Float#to_d -> BigDecimal
-# Rational#to_d -> BigDecimal
-#
-# The following method is provided to convert BigDecimals to other types:
-#
-# BigDecimal#to_r -> Rational
-#
-# ----------------------------------------------------------------------
-#
-class Float < Numeric
- def to_d
- BigDecimal(self.to_s)
- end
-end
-
-class String
- def to_d
- BigDecimal(self)
- end
-end
-
-class BigDecimal < Numeric
- # Converts a BigDecimal to a String of the form "nnnnnn.mmm".
- # This method is deprecated; use BigDecimal#to_s("F") instead.
- def to_digits
- if self.nan? || self.infinite? || self.zero?
- self.to_s
- else
- i = self.to_i.to_s
- s,f,y,z = self.frac.split
- i + "." + ("0"*(-z)) + f
- end
- end
-
- # Converts a BigDecimal to a Rational.
- def to_r
- sign,digits,base,power = self.split
- numerator = sign*digits.to_i
- denomi_power = power - digits.size # base is always 10
- if denomi_power < 0
- Rational(numerator,base ** (-denomi_power))
- else
- Rational(numerator * (base ** denomi_power),1)
- end
- end
-end
-
-class Rational < Numeric
- # Converts a Rational to a BigDecimal
- def to_d(nFig=0)
- num = self.numerator.to_s
- if nFig<=0
- nFig = BigDecimal.double_fig*2+1
- end
- BigDecimal.new(num).div(self.denominator,nFig)
- end
-end
diff --git a/ext/bigdecimal/sample/linear.rb b/ext/bigdecimal/sample/linear.rb
deleted file mode 100644
index 88a62ffa71..0000000000
--- a/ext/bigdecimal/sample/linear.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/local/bin/ruby
-
-#
-# linear.rb
-#
-# Solves linear equation system(A*x = b) by LU decomposition method.
-# where A is a coefficient matrix,x is an answer vector,b is a constant vector.
-#
-# USAGE:
-# ruby linear.rb [input file solved]
-#
-
-require "bigdecimal"
-require "bigdecimal/ludcmp"
-
-#
-# NOTE:
-# Change following BigDecimal::limit() if needed.
-BigDecimal::limit(100)
-#
-
-include LUSolve
-def rd_order(na)
- printf("Number of equations ?") if(na <= 0)
- n = ARGF.gets().to_i
-end
-
-na = ARGV.size
-zero = BigDecimal::new("0.0")
-one = BigDecimal::new("1.0")
-
-while (n=rd_order(na))>0
- a = []
- as= []
- b = []
- if na <= 0
- # Read data from console.
- printf("\nEnter coefficient matrix element A[i,j]\n");
- for i in 0...n do
- for j in 0...n do
- printf("A[%d,%d]? ",i,j); s = ARGF.gets
- a << BigDecimal::new(s);
- as << BigDecimal::new(s);
- end
- printf("Contatant vector element b[%d] ? ",i); b << BigDecimal::new(ARGF.gets);
- end
- else
- # Read data from specified file.
- printf("Coefficient matrix and constant vector.\n");
- for i in 0...n do
- s = ARGF.gets
- printf("%d) %s",i,s)
- s = s.split
- for j in 0...n do
- a << BigDecimal::new(s[j]);
- as << BigDecimal::new(s[j]);
- end
- b << BigDecimal::new(s[n]);
- end
- end
- x = lusolve(a,b,ludecomp(a,n,zero,one),zero)
- printf("Answer(x[i] & (A*x-b)[i]) follows\n")
- for i in 0...n do
- printf("x[%d]=%s ",i,x[i].to_s)
- s = zero
- for j in 0...n do
- s = s + as[i*n+j]*x[j]
- end
- printf(" & %s\n",(s-b[i]).to_s)
- end
-end
diff --git a/ext/bigdecimal/sample/nlsolve.rb b/ext/bigdecimal/sample/nlsolve.rb
deleted file mode 100644
index 7f729e6aaa..0000000000
--- a/ext/bigdecimal/sample/nlsolve.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/local/bin/ruby
-
-#
-# nlsolve.rb
-# An example for solving nonlinear algebraic equation system.
-#
-
-require "bigdecimal"
-require "bigdecimal/newton"
-include Newton
-
-class Function
- def initialize()
- @zero = BigDecimal::new("0.0")
- @one = BigDecimal::new("1.0")
- @two = BigDecimal::new("2.0")
- @ten = BigDecimal::new("10.0")
- @eps = BigDecimal::new("1.0e-16")
- end
- def zero;@zero;end
- def one ;@one ;end
- def two ;@two ;end
- def ten ;@ten ;end
- def eps ;@eps ;end
- def values(x) # <= defines functions solved
- f = []
- f1 = x[0]*x[0] + x[1]*x[1] - @two # f1 = x**2 + y**2 - 2 => 0
- f2 = x[0] - x[1] # f2 = x - y => 0
- f <<= f1
- f <<= f2
- f
- end
-end
- f = BigDecimal::limit(100)
- f = Function.new
- x = [f.zero,f.zero] # Initial values
- n = nlsolve(f,x)
- p x
diff --git a/ext/bigdecimal/sample/pi.rb b/ext/bigdecimal/sample/pi.rb
deleted file mode 100644
index 2f7dd27d60..0000000000
--- a/ext/bigdecimal/sample/pi.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/local/bin/ruby
-
-#
-# pi.rb
-#
-# Calculates 3.1415.... (the number of times that a circle's diameter
-# will fit around the circle) using J. Machin's formula.
-#
-
-require "bigdecimal"
-require "bigdecimal/math.rb"
-
-include BigMath
-
-if ARGV.size == 1
- print "PI("+ARGV[0]+"):\n"
- p PI(ARGV[0].to_i)
-else
- print "TRY: ruby pi.rb 1000 \n"
-end
diff --git a/ext/cgi/escape/depend b/ext/cgi/escape/depend
new file mode 100644
index 0000000000..05b59bfdea
--- /dev/null
+++ b/ext/cgi/escape/depend
@@ -0,0 +1,175 @@
+# AUTOGENERATED DEPENDENCIES START
+escape.o: $(RUBY_EXTCONF_H)
+escape.o: $(arch_hdrdir)/ruby/config.h
+escape.o: $(hdrdir)/ruby.h
+escape.o: $(hdrdir)/ruby/assert.h
+escape.o: $(hdrdir)/ruby/backward.h
+escape.o: $(hdrdir)/ruby/backward/2/assume.h
+escape.o: $(hdrdir)/ruby/backward/2/attributes.h
+escape.o: $(hdrdir)/ruby/backward/2/bool.h
+escape.o: $(hdrdir)/ruby/backward/2/inttypes.h
+escape.o: $(hdrdir)/ruby/backward/2/limits.h
+escape.o: $(hdrdir)/ruby/backward/2/long_long.h
+escape.o: $(hdrdir)/ruby/backward/2/stdalign.h
+escape.o: $(hdrdir)/ruby/backward/2/stdarg.h
+escape.o: $(hdrdir)/ruby/defines.h
+escape.o: $(hdrdir)/ruby/encoding.h
+escape.o: $(hdrdir)/ruby/intern.h
+escape.o: $(hdrdir)/ruby/internal/abi.h
+escape.o: $(hdrdir)/ruby/internal/anyargs.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+escape.o: $(hdrdir)/ruby/internal/assume.h
+escape.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+escape.o: $(hdrdir)/ruby/internal/attr/artificial.h
+escape.o: $(hdrdir)/ruby/internal/attr/cold.h
+escape.o: $(hdrdir)/ruby/internal/attr/const.h
+escape.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+escape.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+escape.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+escape.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+escape.o: $(hdrdir)/ruby/internal/attr/error.h
+escape.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+escape.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+escape.o: $(hdrdir)/ruby/internal/attr/format.h
+escape.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+escape.o: $(hdrdir)/ruby/internal/attr/noalias.h
+escape.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+escape.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+escape.o: $(hdrdir)/ruby/internal/attr/noinline.h
+escape.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+escape.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+escape.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+escape.o: $(hdrdir)/ruby/internal/attr/pure.h
+escape.o: $(hdrdir)/ruby/internal/attr/restrict.h
+escape.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+escape.o: $(hdrdir)/ruby/internal/attr/warning.h
+escape.o: $(hdrdir)/ruby/internal/attr/weakref.h
+escape.o: $(hdrdir)/ruby/internal/cast.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+escape.o: $(hdrdir)/ruby/internal/compiler_since.h
+escape.o: $(hdrdir)/ruby/internal/config.h
+escape.o: $(hdrdir)/ruby/internal/constant_p.h
+escape.o: $(hdrdir)/ruby/internal/core.h
+escape.o: $(hdrdir)/ruby/internal/core/rarray.h
+escape.o: $(hdrdir)/ruby/internal/core/rbasic.h
+escape.o: $(hdrdir)/ruby/internal/core/rbignum.h
+escape.o: $(hdrdir)/ruby/internal/core/rclass.h
+escape.o: $(hdrdir)/ruby/internal/core/rdata.h
+escape.o: $(hdrdir)/ruby/internal/core/rfile.h
+escape.o: $(hdrdir)/ruby/internal/core/rhash.h
+escape.o: $(hdrdir)/ruby/internal/core/robject.h
+escape.o: $(hdrdir)/ruby/internal/core/rregexp.h
+escape.o: $(hdrdir)/ruby/internal/core/rstring.h
+escape.o: $(hdrdir)/ruby/internal/core/rstruct.h
+escape.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+escape.o: $(hdrdir)/ruby/internal/ctype.h
+escape.o: $(hdrdir)/ruby/internal/dllexport.h
+escape.o: $(hdrdir)/ruby/internal/dosish.h
+escape.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+escape.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+escape.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+escape.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+escape.o: $(hdrdir)/ruby/internal/encoding/re.h
+escape.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+escape.o: $(hdrdir)/ruby/internal/encoding/string.h
+escape.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+escape.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+escape.o: $(hdrdir)/ruby/internal/error.h
+escape.o: $(hdrdir)/ruby/internal/eval.h
+escape.o: $(hdrdir)/ruby/internal/event.h
+escape.o: $(hdrdir)/ruby/internal/fl_type.h
+escape.o: $(hdrdir)/ruby/internal/gc.h
+escape.o: $(hdrdir)/ruby/internal/glob.h
+escape.o: $(hdrdir)/ruby/internal/globals.h
+escape.o: $(hdrdir)/ruby/internal/has/attribute.h
+escape.o: $(hdrdir)/ruby/internal/has/builtin.h
+escape.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+escape.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+escape.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+escape.o: $(hdrdir)/ruby/internal/has/extension.h
+escape.o: $(hdrdir)/ruby/internal/has/feature.h
+escape.o: $(hdrdir)/ruby/internal/has/warning.h
+escape.o: $(hdrdir)/ruby/internal/intern/array.h
+escape.o: $(hdrdir)/ruby/internal/intern/bignum.h
+escape.o: $(hdrdir)/ruby/internal/intern/class.h
+escape.o: $(hdrdir)/ruby/internal/intern/compar.h
+escape.o: $(hdrdir)/ruby/internal/intern/complex.h
+escape.o: $(hdrdir)/ruby/internal/intern/cont.h
+escape.o: $(hdrdir)/ruby/internal/intern/dir.h
+escape.o: $(hdrdir)/ruby/internal/intern/enum.h
+escape.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+escape.o: $(hdrdir)/ruby/internal/intern/error.h
+escape.o: $(hdrdir)/ruby/internal/intern/eval.h
+escape.o: $(hdrdir)/ruby/internal/intern/file.h
+escape.o: $(hdrdir)/ruby/internal/intern/hash.h
+escape.o: $(hdrdir)/ruby/internal/intern/io.h
+escape.o: $(hdrdir)/ruby/internal/intern/load.h
+escape.o: $(hdrdir)/ruby/internal/intern/marshal.h
+escape.o: $(hdrdir)/ruby/internal/intern/numeric.h
+escape.o: $(hdrdir)/ruby/internal/intern/object.h
+escape.o: $(hdrdir)/ruby/internal/intern/parse.h
+escape.o: $(hdrdir)/ruby/internal/intern/proc.h
+escape.o: $(hdrdir)/ruby/internal/intern/process.h
+escape.o: $(hdrdir)/ruby/internal/intern/random.h
+escape.o: $(hdrdir)/ruby/internal/intern/range.h
+escape.o: $(hdrdir)/ruby/internal/intern/rational.h
+escape.o: $(hdrdir)/ruby/internal/intern/re.h
+escape.o: $(hdrdir)/ruby/internal/intern/ruby.h
+escape.o: $(hdrdir)/ruby/internal/intern/select.h
+escape.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+escape.o: $(hdrdir)/ruby/internal/intern/set.h
+escape.o: $(hdrdir)/ruby/internal/intern/signal.h
+escape.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+escape.o: $(hdrdir)/ruby/internal/intern/string.h
+escape.o: $(hdrdir)/ruby/internal/intern/struct.h
+escape.o: $(hdrdir)/ruby/internal/intern/thread.h
+escape.o: $(hdrdir)/ruby/internal/intern/time.h
+escape.o: $(hdrdir)/ruby/internal/intern/variable.h
+escape.o: $(hdrdir)/ruby/internal/intern/vm.h
+escape.o: $(hdrdir)/ruby/internal/interpreter.h
+escape.o: $(hdrdir)/ruby/internal/iterator.h
+escape.o: $(hdrdir)/ruby/internal/memory.h
+escape.o: $(hdrdir)/ruby/internal/method.h
+escape.o: $(hdrdir)/ruby/internal/module.h
+escape.o: $(hdrdir)/ruby/internal/newobj.h
+escape.o: $(hdrdir)/ruby/internal/scan_args.h
+escape.o: $(hdrdir)/ruby/internal/special_consts.h
+escape.o: $(hdrdir)/ruby/internal/static_assert.h
+escape.o: $(hdrdir)/ruby/internal/stdalign.h
+escape.o: $(hdrdir)/ruby/internal/stdbool.h
+escape.o: $(hdrdir)/ruby/internal/stdckdint.h
+escape.o: $(hdrdir)/ruby/internal/symbol.h
+escape.o: $(hdrdir)/ruby/internal/value.h
+escape.o: $(hdrdir)/ruby/internal/value_type.h
+escape.o: $(hdrdir)/ruby/internal/variable.h
+escape.o: $(hdrdir)/ruby/internal/warning_push.h
+escape.o: $(hdrdir)/ruby/internal/xmalloc.h
+escape.o: $(hdrdir)/ruby/missing.h
+escape.o: $(hdrdir)/ruby/onigmo.h
+escape.o: $(hdrdir)/ruby/oniguruma.h
+escape.o: $(hdrdir)/ruby/ruby.h
+escape.o: $(hdrdir)/ruby/st.h
+escape.o: $(hdrdir)/ruby/subst.h
+escape.o: escape.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/cgi/escape/escape.c b/ext/cgi/escape/escape.c
new file mode 100644
index 0000000000..4773186603
--- /dev/null
+++ b/ext/cgi/escape/escape.c
@@ -0,0 +1,487 @@
+#include "ruby.h"
+#include "ruby/encoding.h"
+
+RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow);
+RUBY_EXTERN const char ruby_hexdigits[];
+RUBY_EXTERN const signed char ruby_digit36_to_number_table[];
+#define lower_hexdigits (ruby_hexdigits+0)
+#define upper_hexdigits (ruby_hexdigits+16)
+#define char_to_number(c) ruby_digit36_to_number_table[(unsigned char)(c)]
+
+static VALUE rb_cCGI, rb_mEscape, rb_mEscapeExt;
+static ID id_accept_charset;
+
+#define HTML_ESCAPE_MAX_LEN 6
+
+static const struct {
+ uint8_t len;
+ char str[HTML_ESCAPE_MAX_LEN+1];
+} html_escape_table[UCHAR_MAX+1] = {
+#define HTML_ESCAPE(c, str) [c] = {rb_strlen_lit(str), str}
+ HTML_ESCAPE('\'', "&#39;"),
+ HTML_ESCAPE('&', "&amp;"),
+ HTML_ESCAPE('"', "&quot;"),
+ HTML_ESCAPE('<', "&lt;"),
+ HTML_ESCAPE('>', "&gt;"),
+#undef HTML_ESCAPE
+};
+
+static inline void
+preserve_original_state(VALUE orig, VALUE dest)
+{
+ rb_enc_associate(dest, rb_enc_get(orig));
+}
+
+static inline long
+escaped_length(VALUE str)
+{
+ const long len = RSTRING_LEN(str);
+ if (len >= LONG_MAX / HTML_ESCAPE_MAX_LEN) {
+ ruby_malloc_size_overflow(len, HTML_ESCAPE_MAX_LEN);
+ }
+ return len * HTML_ESCAPE_MAX_LEN;
+}
+
+static VALUE
+optimized_escape_html(VALUE str)
+{
+ VALUE escaped;
+ VALUE vbuf;
+ char *buf = ALLOCV_N(char, vbuf, escaped_length(str));
+ const char *cstr = RSTRING_PTR(str);
+ const char *end = cstr + RSTRING_LEN(str);
+
+ char *dest = buf;
+ while (cstr < end) {
+ const unsigned char c = *cstr++;
+ uint8_t len = html_escape_table[c].len;
+ if (len) {
+ memcpy(dest, html_escape_table[c].str, len);
+ dest += len;
+ }
+ else {
+ *dest++ = c;
+ }
+ }
+
+ if (RSTRING_LEN(str) < (dest - buf)) {
+ escaped = rb_str_new(buf, dest - buf);
+ preserve_original_state(str, escaped);
+ }
+ else {
+ escaped = rb_str_dup(str);
+ }
+ ALLOCV_END(vbuf);
+ return escaped;
+}
+
+static VALUE
+optimized_unescape_html(VALUE str)
+{
+ enum {UNICODE_MAX = 0x10ffff};
+ rb_encoding *enc = rb_enc_get(str);
+ unsigned long charlimit = (strcasecmp(rb_enc_name(enc), "UTF-8") == 0 ? UNICODE_MAX :
+ strcasecmp(rb_enc_name(enc), "ISO-8859-1") == 0 ? 256 :
+ 128);
+ long i, j, len, beg = 0;
+ size_t clen, plen;
+ int overflow;
+ const char *cstr;
+ char buf[6];
+ VALUE dest = 0;
+
+ len = RSTRING_LEN(str);
+ cstr = RSTRING_PTR(str);
+
+ for (i = 0; i < len; i++) {
+ unsigned long cc;
+ char c = cstr[i];
+ if (c != '&') continue;
+ plen = i - beg;
+ if (++i >= len) break;
+ c = (unsigned char)cstr[i];
+ j = i;
+#define MATCH(s) (len - i >= (int)rb_strlen_lit(s) && \
+ memcmp(&cstr[i], s, rb_strlen_lit(s)) == 0 && \
+ (i += rb_strlen_lit(s) - 1, 1))
+ switch (c) {
+ case 'a':
+ ++i;
+ if (MATCH("pos;")) {
+ c = '\'';
+ }
+ else if (MATCH("mp;")) {
+ c = '&';
+ }
+ else {
+ i = j;
+ continue;
+ }
+ break;
+ case 'q':
+ ++i;
+ if (MATCH("uot;")) {
+ c = '"';
+ }
+ else {
+ i = j;
+ continue;
+ }
+ break;
+ case 'g':
+ ++i;
+ if (MATCH("t;")) {
+ c = '>';
+ }
+ else {
+ i = j;
+ continue;
+ }
+ break;
+ case 'l':
+ ++i;
+ if (MATCH("t;")) {
+ c = '<';
+ }
+ else {
+ i = j;
+ continue;
+ }
+ break;
+ case '#':
+ if (len - ++i >= 2 && ISDIGIT(cstr[i])) {
+ cc = ruby_scan_digits(&cstr[i], len-i, 10, &clen, &overflow);
+ }
+ else if ((cstr[i] == 'x' || cstr[i] == 'X') && len - ++i >= 2 && ISXDIGIT(cstr[i])) {
+ cc = ruby_scan_digits(&cstr[i], len-i, 16, &clen, &overflow);
+ }
+ else {
+ i = j;
+ continue;
+ }
+ i += clen;
+ if (overflow || cc >= charlimit || cstr[i] != ';') {
+ i = j;
+ continue;
+ }
+ if (!dest) {
+ dest = rb_str_buf_new(len);
+ }
+ rb_str_cat(dest, cstr + beg, plen);
+ if (charlimit > 256) {
+ rb_str_cat(dest, buf, rb_enc_mbcput((OnigCodePoint)cc, buf, enc));
+ }
+ else {
+ c = (unsigned char)cc;
+ rb_str_cat(dest, &c, 1);
+ }
+ beg = i + 1;
+ continue;
+ default:
+ --i;
+ continue;
+ }
+ if (!dest) {
+ dest = rb_str_buf_new(len);
+ }
+ rb_str_cat(dest, cstr + beg, plen);
+ rb_str_cat(dest, &c, 1);
+ beg = i + 1;
+ }
+
+ if (dest) {
+ rb_str_cat(dest, cstr + beg, len - beg);
+ preserve_original_state(str, dest);
+ return dest;
+ }
+ else {
+ return rb_str_dup(str);
+ }
+}
+
+static unsigned char
+url_unreserved_char(unsigned char c)
+{
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':
+ case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
+ case '-': case '.': case '_': case '~':
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static VALUE
+optimized_escape(VALUE str, int plus_escape)
+{
+ long i, len, beg = 0;
+ VALUE dest = 0;
+ const char *cstr;
+ char buf[4] = {'%'};
+
+ len = RSTRING_LEN(str);
+ cstr = RSTRING_PTR(str);
+
+ for (i = 0; i < len; ++i) {
+ const unsigned char c = (unsigned char)cstr[i];
+ if (!url_unreserved_char(c)) {
+ if (!dest) {
+ dest = rb_str_buf_new(len);
+ }
+
+ rb_str_cat(dest, cstr + beg, i - beg);
+ beg = i + 1;
+
+ if (plus_escape && c == ' ') {
+ rb_str_cat_cstr(dest, "+");
+ }
+ else {
+ buf[1] = upper_hexdigits[(c >> 4) & 0xf];
+ buf[2] = upper_hexdigits[c & 0xf];
+ rb_str_cat(dest, buf, 3);
+ }
+ }
+ }
+
+ if (dest) {
+ rb_str_cat(dest, cstr + beg, len - beg);
+ preserve_original_state(str, dest);
+ return dest;
+ }
+ else {
+ return rb_str_dup(str);
+ }
+}
+
+static VALUE
+optimized_unescape(VALUE str, VALUE encoding, int unescape_plus)
+{
+ long i, len, beg = 0;
+ VALUE dest = 0;
+ const char *cstr;
+ rb_encoding *enc = rb_to_encoding(encoding);
+ int cr, origenc, encidx = rb_enc_to_index(enc);
+
+ len = RSTRING_LEN(str);
+ cstr = RSTRING_PTR(str);
+
+ for (i = 0; i < len; ++i) {
+ char buf[1];
+ const char c = cstr[i];
+ int clen = 0;
+ if (c == '%') {
+ if (i + 3 > len) break;
+ if (!ISXDIGIT(cstr[i+1])) continue;
+ if (!ISXDIGIT(cstr[i+2])) continue;
+ buf[0] = ((char_to_number(cstr[i+1]) << 4)
+ | char_to_number(cstr[i+2]));
+ clen = 2;
+ }
+ else if (unescape_plus && c == '+') {
+ buf[0] = ' ';
+ }
+ else {
+ continue;
+ }
+
+ if (!dest) {
+ dest = rb_str_buf_new(len);
+ }
+
+ rb_str_cat(dest, cstr + beg, i - beg);
+ i += clen;
+ beg = i + 1;
+
+ rb_str_cat(dest, buf, 1);
+ }
+
+ if (dest) {
+ rb_str_cat(dest, cstr + beg, len - beg);
+ preserve_original_state(str, dest);
+ cr = ENC_CODERANGE_UNKNOWN;
+ }
+ else {
+ dest = rb_str_dup(str);
+ cr = ENC_CODERANGE(str);
+ }
+ origenc = rb_enc_get_index(str);
+ if (origenc != encidx) {
+ rb_enc_associate_index(dest, encidx);
+ if (!ENC_CODERANGE_CLEAN_P(rb_enc_str_coderange(dest))) {
+ rb_enc_associate_index(dest, origenc);
+ if (cr != ENC_CODERANGE_UNKNOWN)
+ ENC_CODERANGE_SET(dest, cr);
+ }
+ }
+ return dest;
+}
+
+/*
+ * call-seq:
+ * CGI.escapeHTML(string) -> string
+ *
+ * Returns HTML-escaped string.
+ *
+ */
+static VALUE
+cgiesc_escape_html(VALUE self, VALUE str)
+{
+ StringValue(str);
+
+ if (rb_enc_str_asciicompat_p(str)) {
+ return optimized_escape_html(str);
+ }
+ else {
+ return rb_call_super(1, &str);
+ }
+}
+
+/*
+ * call-seq:
+ * CGI.unescapeHTML(string) -> string
+ *
+ * Returns HTML-unescaped string.
+ *
+ */
+static VALUE
+cgiesc_unescape_html(VALUE self, VALUE str)
+{
+ StringValue(str);
+
+ if (rb_enc_str_asciicompat_p(str)) {
+ return optimized_unescape_html(str);
+ }
+ else {
+ return rb_call_super(1, &str);
+ }
+}
+
+/*
+ * call-seq:
+ * CGI.escape(string) -> string
+ *
+ * Returns URL-escaped string (+application/x-www-form-urlencoded+).
+ *
+ */
+static VALUE
+cgiesc_escape(VALUE self, VALUE str)
+{
+ StringValue(str);
+
+ if (rb_enc_str_asciicompat_p(str)) {
+ return optimized_escape(str, 1);
+ }
+ else {
+ return rb_call_super(1, &str);
+ }
+}
+
+static VALUE
+accept_charset(int argc, VALUE *argv, VALUE self)
+{
+ if (argc > 0)
+ return argv[0];
+ return rb_cvar_get(CLASS_OF(self), id_accept_charset);
+}
+
+/*
+ * call-seq:
+ * CGI.unescape(string, encoding=@@accept_charset) -> string
+ *
+ * Returns URL-unescaped string (+application/x-www-form-urlencoded+).
+ *
+ */
+static VALUE
+cgiesc_unescape(int argc, VALUE *argv, VALUE self)
+{
+ VALUE str = (rb_check_arity(argc, 1, 2), argv[0]);
+
+ StringValue(str);
+
+ if (rb_enc_str_asciicompat_p(str)) {
+ VALUE enc = accept_charset(argc-1, argv+1, self);
+ return optimized_unescape(str, enc, 1);
+ }
+ else {
+ return rb_call_super(argc, argv);
+ }
+}
+
+/*
+ * call-seq:
+ * CGI.escapeURIComponent(string) -> string
+ *
+ * Returns URL-escaped string following RFC 3986.
+ *
+ */
+static VALUE
+cgiesc_escape_uri_component(VALUE self, VALUE str)
+{
+ StringValue(str);
+
+ if (rb_enc_str_asciicompat_p(str)) {
+ return optimized_escape(str, 0);
+ }
+ else {
+ return rb_call_super(1, &str);
+ }
+}
+
+/*
+ * call-seq:
+ * CGI.unescapeURIComponent(string, encoding=@@accept_charset) -> string
+ *
+ * Returns URL-unescaped string following RFC 3986.
+ *
+ */
+static VALUE
+cgiesc_unescape_uri_component(int argc, VALUE *argv, VALUE self)
+{
+ VALUE str = (rb_check_arity(argc, 1, 2), argv[0]);
+
+ StringValue(str);
+
+ if (rb_enc_str_asciicompat_p(str)) {
+ VALUE enc = accept_charset(argc-1, argv+1, self);
+ return optimized_unescape(str, enc, 0);
+ }
+ else {
+ return rb_call_super(argc, argv);
+ }
+}
+
+void
+Init_escape(void)
+{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
+ id_accept_charset = rb_intern_const("@@accept_charset");
+ InitVM(escape);
+}
+
+void
+InitVM_escape(void)
+{
+ rb_cCGI = rb_define_class("CGI", rb_cObject);
+ rb_mEscapeExt = rb_define_module_under(rb_cCGI, "EscapeExt");
+ rb_mEscape = rb_define_module_under(rb_cCGI, "Escape");
+ rb_define_method(rb_mEscapeExt, "escapeHTML", cgiesc_escape_html, 1);
+ rb_define_method(rb_mEscapeExt, "unescapeHTML", cgiesc_unescape_html, 1);
+ rb_define_method(rb_mEscapeExt, "escapeURIComponent", cgiesc_escape_uri_component, 1);
+ rb_define_alias(rb_mEscapeExt, "escape_uri_component", "escapeURIComponent");
+ rb_define_method(rb_mEscapeExt, "unescapeURIComponent", cgiesc_unescape_uri_component, -1);
+ rb_define_alias(rb_mEscapeExt, "unescape_uri_component", "unescapeURIComponent");
+ rb_define_method(rb_mEscapeExt, "escape", cgiesc_escape, 1);
+ rb_define_method(rb_mEscapeExt, "unescape", cgiesc_unescape, -1);
+ rb_prepend_module(rb_mEscape, rb_mEscapeExt);
+ rb_extend_object(rb_cCGI, rb_mEscapeExt);
+}
diff --git a/ext/cgi/escape/extconf.rb b/ext/cgi/escape/extconf.rb
new file mode 100644
index 0000000000..73acd89ca8
--- /dev/null
+++ b/ext/cgi/escape/extconf.rb
@@ -0,0 +1,7 @@
+require 'mkmf'
+
+if RUBY_ENGINE == 'truffleruby'
+ File.write("Makefile", dummy_makefile($srcdir).join(""))
+else
+ create_makefile 'cgi/escape'
+end
diff --git a/ext/continuation/continuation.c b/ext/continuation/continuation.c
new file mode 100644
index 0000000000..c678371cca
--- /dev/null
+++ b/ext/continuation/continuation.c
@@ -0,0 +1,13 @@
+
+#include "ruby/ruby.h"
+
+void ruby_Init_Continuation_body(void);
+
+void
+Init_continuation(void)
+{
+#ifndef RUBY_EXPORT
+ rb_warn("callcc is obsolete; use Fiber instead");
+#endif
+ ruby_Init_Continuation_body();
+}
diff --git a/ext/continuation/depend b/ext/continuation/depend
new file mode 100644
index 0000000000..b395d3d4d7
--- /dev/null
+++ b/ext/continuation/depend
@@ -0,0 +1,162 @@
+# AUTOGENERATED DEPENDENCIES START
+continuation.o: $(RUBY_EXTCONF_H)
+continuation.o: $(arch_hdrdir)/ruby/config.h
+continuation.o: $(hdrdir)/ruby/assert.h
+continuation.o: $(hdrdir)/ruby/backward.h
+continuation.o: $(hdrdir)/ruby/backward/2/assume.h
+continuation.o: $(hdrdir)/ruby/backward/2/attributes.h
+continuation.o: $(hdrdir)/ruby/backward/2/bool.h
+continuation.o: $(hdrdir)/ruby/backward/2/inttypes.h
+continuation.o: $(hdrdir)/ruby/backward/2/limits.h
+continuation.o: $(hdrdir)/ruby/backward/2/long_long.h
+continuation.o: $(hdrdir)/ruby/backward/2/stdalign.h
+continuation.o: $(hdrdir)/ruby/backward/2/stdarg.h
+continuation.o: $(hdrdir)/ruby/defines.h
+continuation.o: $(hdrdir)/ruby/intern.h
+continuation.o: $(hdrdir)/ruby/internal/abi.h
+continuation.o: $(hdrdir)/ruby/internal/anyargs.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+continuation.o: $(hdrdir)/ruby/internal/assume.h
+continuation.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+continuation.o: $(hdrdir)/ruby/internal/attr/artificial.h
+continuation.o: $(hdrdir)/ruby/internal/attr/cold.h
+continuation.o: $(hdrdir)/ruby/internal/attr/const.h
+continuation.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+continuation.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+continuation.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+continuation.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+continuation.o: $(hdrdir)/ruby/internal/attr/error.h
+continuation.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+continuation.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+continuation.o: $(hdrdir)/ruby/internal/attr/format.h
+continuation.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+continuation.o: $(hdrdir)/ruby/internal/attr/noalias.h
+continuation.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+continuation.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+continuation.o: $(hdrdir)/ruby/internal/attr/noinline.h
+continuation.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+continuation.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+continuation.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+continuation.o: $(hdrdir)/ruby/internal/attr/pure.h
+continuation.o: $(hdrdir)/ruby/internal/attr/restrict.h
+continuation.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+continuation.o: $(hdrdir)/ruby/internal/attr/warning.h
+continuation.o: $(hdrdir)/ruby/internal/attr/weakref.h
+continuation.o: $(hdrdir)/ruby/internal/cast.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_since.h
+continuation.o: $(hdrdir)/ruby/internal/config.h
+continuation.o: $(hdrdir)/ruby/internal/constant_p.h
+continuation.o: $(hdrdir)/ruby/internal/core.h
+continuation.o: $(hdrdir)/ruby/internal/core/rarray.h
+continuation.o: $(hdrdir)/ruby/internal/core/rbasic.h
+continuation.o: $(hdrdir)/ruby/internal/core/rbignum.h
+continuation.o: $(hdrdir)/ruby/internal/core/rclass.h
+continuation.o: $(hdrdir)/ruby/internal/core/rdata.h
+continuation.o: $(hdrdir)/ruby/internal/core/rfile.h
+continuation.o: $(hdrdir)/ruby/internal/core/rhash.h
+continuation.o: $(hdrdir)/ruby/internal/core/robject.h
+continuation.o: $(hdrdir)/ruby/internal/core/rregexp.h
+continuation.o: $(hdrdir)/ruby/internal/core/rstring.h
+continuation.o: $(hdrdir)/ruby/internal/core/rstruct.h
+continuation.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+continuation.o: $(hdrdir)/ruby/internal/ctype.h
+continuation.o: $(hdrdir)/ruby/internal/dllexport.h
+continuation.o: $(hdrdir)/ruby/internal/dosish.h
+continuation.o: $(hdrdir)/ruby/internal/error.h
+continuation.o: $(hdrdir)/ruby/internal/eval.h
+continuation.o: $(hdrdir)/ruby/internal/event.h
+continuation.o: $(hdrdir)/ruby/internal/fl_type.h
+continuation.o: $(hdrdir)/ruby/internal/gc.h
+continuation.o: $(hdrdir)/ruby/internal/glob.h
+continuation.o: $(hdrdir)/ruby/internal/globals.h
+continuation.o: $(hdrdir)/ruby/internal/has/attribute.h
+continuation.o: $(hdrdir)/ruby/internal/has/builtin.h
+continuation.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+continuation.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+continuation.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+continuation.o: $(hdrdir)/ruby/internal/has/extension.h
+continuation.o: $(hdrdir)/ruby/internal/has/feature.h
+continuation.o: $(hdrdir)/ruby/internal/has/warning.h
+continuation.o: $(hdrdir)/ruby/internal/intern/array.h
+continuation.o: $(hdrdir)/ruby/internal/intern/bignum.h
+continuation.o: $(hdrdir)/ruby/internal/intern/class.h
+continuation.o: $(hdrdir)/ruby/internal/intern/compar.h
+continuation.o: $(hdrdir)/ruby/internal/intern/complex.h
+continuation.o: $(hdrdir)/ruby/internal/intern/cont.h
+continuation.o: $(hdrdir)/ruby/internal/intern/dir.h
+continuation.o: $(hdrdir)/ruby/internal/intern/enum.h
+continuation.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+continuation.o: $(hdrdir)/ruby/internal/intern/error.h
+continuation.o: $(hdrdir)/ruby/internal/intern/eval.h
+continuation.o: $(hdrdir)/ruby/internal/intern/file.h
+continuation.o: $(hdrdir)/ruby/internal/intern/hash.h
+continuation.o: $(hdrdir)/ruby/internal/intern/io.h
+continuation.o: $(hdrdir)/ruby/internal/intern/load.h
+continuation.o: $(hdrdir)/ruby/internal/intern/marshal.h
+continuation.o: $(hdrdir)/ruby/internal/intern/numeric.h
+continuation.o: $(hdrdir)/ruby/internal/intern/object.h
+continuation.o: $(hdrdir)/ruby/internal/intern/parse.h
+continuation.o: $(hdrdir)/ruby/internal/intern/proc.h
+continuation.o: $(hdrdir)/ruby/internal/intern/process.h
+continuation.o: $(hdrdir)/ruby/internal/intern/random.h
+continuation.o: $(hdrdir)/ruby/internal/intern/range.h
+continuation.o: $(hdrdir)/ruby/internal/intern/rational.h
+continuation.o: $(hdrdir)/ruby/internal/intern/re.h
+continuation.o: $(hdrdir)/ruby/internal/intern/ruby.h
+continuation.o: $(hdrdir)/ruby/internal/intern/select.h
+continuation.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+continuation.o: $(hdrdir)/ruby/internal/intern/set.h
+continuation.o: $(hdrdir)/ruby/internal/intern/signal.h
+continuation.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+continuation.o: $(hdrdir)/ruby/internal/intern/string.h
+continuation.o: $(hdrdir)/ruby/internal/intern/struct.h
+continuation.o: $(hdrdir)/ruby/internal/intern/thread.h
+continuation.o: $(hdrdir)/ruby/internal/intern/time.h
+continuation.o: $(hdrdir)/ruby/internal/intern/variable.h
+continuation.o: $(hdrdir)/ruby/internal/intern/vm.h
+continuation.o: $(hdrdir)/ruby/internal/interpreter.h
+continuation.o: $(hdrdir)/ruby/internal/iterator.h
+continuation.o: $(hdrdir)/ruby/internal/memory.h
+continuation.o: $(hdrdir)/ruby/internal/method.h
+continuation.o: $(hdrdir)/ruby/internal/module.h
+continuation.o: $(hdrdir)/ruby/internal/newobj.h
+continuation.o: $(hdrdir)/ruby/internal/scan_args.h
+continuation.o: $(hdrdir)/ruby/internal/special_consts.h
+continuation.o: $(hdrdir)/ruby/internal/static_assert.h
+continuation.o: $(hdrdir)/ruby/internal/stdalign.h
+continuation.o: $(hdrdir)/ruby/internal/stdbool.h
+continuation.o: $(hdrdir)/ruby/internal/stdckdint.h
+continuation.o: $(hdrdir)/ruby/internal/symbol.h
+continuation.o: $(hdrdir)/ruby/internal/value.h
+continuation.o: $(hdrdir)/ruby/internal/value_type.h
+continuation.o: $(hdrdir)/ruby/internal/variable.h
+continuation.o: $(hdrdir)/ruby/internal/warning_push.h
+continuation.o: $(hdrdir)/ruby/internal/xmalloc.h
+continuation.o: $(hdrdir)/ruby/missing.h
+continuation.o: $(hdrdir)/ruby/ruby.h
+continuation.o: $(hdrdir)/ruby/st.h
+continuation.o: $(hdrdir)/ruby/subst.h
+continuation.o: continuation.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/continuation/extconf.rb b/ext/continuation/extconf.rb
new file mode 100644
index 0000000000..6d54ec01a5
--- /dev/null
+++ b/ext/continuation/extconf.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: false
+require 'mkmf'
+create_makefile('continuation')
+
diff --git a/ext/coverage/coverage.c b/ext/coverage/coverage.c
new file mode 100644
index 0000000000..1b0280b460
--- /dev/null
+++ b/ext/coverage/coverage.c
@@ -0,0 +1,710 @@
+/************************************************
+
+ coverage.c -
+
+ $Author: $
+
+ Copyright (c) 2008 Yusuke Endoh
+
+************************************************/
+
+#include "internal/gc.h"
+#include "internal/hash.h"
+#include "internal/thread.h"
+#include "internal/sanitizers.h"
+#include "ruby.h"
+#include "vm_core.h"
+
+static enum {
+ IDLE,
+ SUSPENDED,
+ RUNNING
+} current_state = IDLE;
+static int current_mode;
+static VALUE me2counter = Qnil;
+
+/*
+ * call-seq: Coverage.supported?(mode) -> true or false
+ *
+ * Returns true if coverage measurement is supported for the given mode.
+ *
+ * The mode should be one of the following symbols:
+ * +:lines+, +:oneshot_lines+, +:branches+, +:methods+, +:eval+.
+ *
+ * Example:
+ *
+ * Coverage.supported?(:lines) #=> true
+ * Coverage.supported?(:all) #=> false
+ */
+static VALUE
+rb_coverage_supported(VALUE self, VALUE _mode)
+{
+ ID mode = RB_SYM2ID(_mode);
+
+ return RBOOL(
+ mode == rb_intern("lines") ||
+ mode == rb_intern("oneshot_lines") ||
+ mode == rb_intern("branches") ||
+ mode == rb_intern("methods") ||
+ mode == rb_intern("eval")
+ );
+}
+
+/*
+ * call-seq:
+ * Coverage.setup -> nil
+ * Coverage.setup(type) -> nil
+ * Coverage.setup(lines: false, branches: false, methods: false, eval: false, oneshot_lines: false) -> nil
+ *
+ * Performs setup for coverage measurement, but does not start coverage measurement.
+ * To start coverage measurement, use Coverage.resume.
+ *
+ * To perform both setup and start coverage measurement, Coverage.start can be used.
+ *
+ * With argument +type+ given and +type+ is symbol +:all+, enables all types of coverage
+ * (lines, branches, methods, and eval).
+ *
+ * Keyword arguments or hash +type+ can be given with each of the following keys:
+ *
+ * - +lines+: Enables line coverage that records the number of times each line was executed.
+ * If +lines+ is enabled, +oneshot_lines+ cannot be enabled.
+ * See {Lines Coverage}[rdoc-ref:Coverage@Lines+Coverage].
+ * - +branches+: Enables branch coverage that records the number of times each
+ * branch in each conditional was executed. See {Branches Coverage}[rdoc-ref:Coverage@Branches+Coverage].
+ * - +methods+: Enables method coverage that records the number of times each method was exectued.
+ * See {Methods Coverage}[rdoc-ref:Coverage@Methods+Coverage].
+ * - +eval+: Enables coverage for evaluations (e.g. Kernel#eval, Module#class_eval).
+ * See {Eval Coverage}[rdoc-ref:Coverage@Eval+Coverage].
+ */
+static VALUE
+rb_coverage_setup(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE coverages, opt;
+ int mode;
+
+ if (current_state != IDLE) {
+ rb_raise(rb_eRuntimeError, "coverage measurement is already setup");
+ }
+
+ rb_scan_args(argc, argv, "01", &opt);
+
+ if (argc == 0) {
+ mode = 0; /* compatible mode */
+ }
+ else if (opt == ID2SYM(rb_intern("all"))) {
+ mode = COVERAGE_TARGET_LINES | COVERAGE_TARGET_BRANCHES | COVERAGE_TARGET_METHODS | COVERAGE_TARGET_EVAL;
+ }
+ else {
+ mode = 0;
+ opt = rb_convert_type(opt, T_HASH, "Hash", "to_hash");
+
+ if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("lines")))))
+ mode |= COVERAGE_TARGET_LINES;
+ if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("branches")))))
+ mode |= COVERAGE_TARGET_BRANCHES;
+ if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("methods")))))
+ mode |= COVERAGE_TARGET_METHODS;
+ if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("oneshot_lines"))))) {
+ if (mode & COVERAGE_TARGET_LINES)
+ rb_raise(rb_eRuntimeError, "cannot enable lines and oneshot_lines simultaneously");
+ mode |= COVERAGE_TARGET_LINES;
+ mode |= COVERAGE_TARGET_ONESHOT_LINES;
+ }
+ if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("eval")))))
+ mode |= COVERAGE_TARGET_EVAL;
+ }
+
+ if (mode & COVERAGE_TARGET_METHODS) {
+ me2counter = rb_ident_hash_new();
+ }
+ else {
+ me2counter = Qnil;
+ }
+
+ coverages = rb_get_coverages();
+ if (!RTEST(coverages)) {
+ coverages = rb_hash_new();
+ rb_obj_hide(coverages);
+ current_mode = mode;
+ if (mode == 0) mode = COVERAGE_TARGET_LINES;
+ rb_set_coverages(coverages, mode, me2counter);
+ current_state = SUSPENDED;
+ }
+ else if (current_mode != mode) {
+ rb_raise(rb_eRuntimeError, "cannot change the measuring target during coverage measurement");
+ }
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Coverage.resume => nil
+ *
+ * Start/resume the coverage measurement.
+ *
+ * Caveat: Currently, only process-global coverage measurement is supported.
+ * You cannot measure per-thread coverage. If your process has multiple thread,
+ * using Coverage.resume/suspend to capture code coverage executed from only
+ * a limited code block, may yield misleading results.
+ */
+VALUE
+rb_coverage_resume(VALUE klass)
+{
+ if (current_state == IDLE) {
+ rb_raise(rb_eRuntimeError, "coverage measurement is not set up yet");
+ }
+ if (current_state == RUNNING) {
+ rb_raise(rb_eRuntimeError, "coverage measurement is already running");
+ }
+ rb_resume_coverages();
+ current_state = RUNNING;
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Coverage.start -> nil
+ * Coverage.start(type) -> nil
+ * Coverage.start(lines: false, branches: false, methods: false, eval: false, oneshot_lines: false) -> nil
+ *
+ * Enables coverage measurement.
+ * This method is equivalent to calling Coverage.setup with the arguments provided,
+ * and then calling Coverage.resume. See their respective documentation for more
+ * details.
+ */
+static VALUE
+rb_coverage_start(int argc, VALUE *argv, VALUE klass)
+{
+ rb_coverage_setup(argc, argv, klass);
+ rb_coverage_resume(klass);
+ return Qnil;
+}
+
+struct branch_coverage_result_builder
+{
+ int id;
+ VALUE result;
+ VALUE children;
+ VALUE counters;
+};
+
+static int
+branch_coverage_ii(VALUE _key, VALUE branch, VALUE v)
+{
+ struct branch_coverage_result_builder *b = (struct branch_coverage_result_builder *) v;
+
+ VALUE target_label = RARRAY_AREF(branch, 0);
+ VALUE target_first_lineno = RARRAY_AREF(branch, 1);
+ VALUE target_first_column = RARRAY_AREF(branch, 2);
+ VALUE target_last_lineno = RARRAY_AREF(branch, 3);
+ VALUE target_last_column = RARRAY_AREF(branch, 4);
+ long counter_idx = FIX2LONG(RARRAY_AREF(branch, 5));
+ rb_hash_aset(b->children, rb_ary_new_from_args(6, target_label, LONG2FIX(b->id++), target_first_lineno, target_first_column, target_last_lineno, target_last_column), RARRAY_AREF(b->counters, counter_idx));
+
+ return ST_CONTINUE;
+}
+
+static int
+branch_coverage_i(VALUE _key, VALUE branch_base, VALUE v)
+{
+ struct branch_coverage_result_builder *b = (struct branch_coverage_result_builder *) v;
+
+ VALUE base_type = RARRAY_AREF(branch_base, 0);
+ VALUE base_first_lineno = RARRAY_AREF(branch_base, 1);
+ VALUE base_first_column = RARRAY_AREF(branch_base, 2);
+ VALUE base_last_lineno = RARRAY_AREF(branch_base, 3);
+ VALUE base_last_column = RARRAY_AREF(branch_base, 4);
+ VALUE branches = RARRAY_AREF(branch_base, 5);
+ VALUE children = rb_hash_new();
+ rb_hash_aset(b->result, rb_ary_new_from_args(6, base_type, LONG2FIX(b->id++), base_first_lineno, base_first_column, base_last_lineno, base_last_column), children);
+ b->children = children;
+ rb_hash_foreach(branches, branch_coverage_ii, v);
+
+ return ST_CONTINUE;
+}
+
+static VALUE
+branch_coverage(VALUE branches)
+{
+ VALUE structure = RARRAY_AREF(branches, 0);
+
+ struct branch_coverage_result_builder b;
+ b.id = 0;
+ b.result = rb_hash_new();
+ b.counters = RARRAY_AREF(branches, 1);
+
+ rb_hash_foreach(structure, branch_coverage_i, (VALUE)&b);
+
+ return b.result;
+}
+
+static int
+method_coverage_i(void *vstart, void *vend, size_t stride, void *data)
+{
+ /*
+ * ObjectSpace.each_object(Module){|mod|
+ * mod.instance_methods.each{|mid|
+ * m = mod.instance_method(mid)
+ * if loc = m.source_location
+ * p [m.name, loc, $g_method_cov_counts[m]]
+ * end
+ * }
+ * }
+ */
+ VALUE ncoverages = *(VALUE*)data, v;
+
+ for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
+ void *poisoned = rb_asan_poisoned_object_p(v);
+ rb_asan_unpoison_object(v, false);
+
+ if (RB_TYPE_P(v, T_IMEMO) && imemo_type(v) == imemo_ment) {
+ const rb_method_entry_t *me = (rb_method_entry_t *) v;
+ VALUE path, first_lineno, first_column, last_lineno, last_column;
+ VALUE data[5], ncoverage, methods;
+ VALUE methods_id = ID2SYM(rb_intern("methods"));
+ VALUE klass;
+ const rb_method_entry_t *me2 = rb_resolve_me_location(me, data);
+ if (me != me2) continue;
+ klass = me->owner;
+ if (RB_TYPE_P(klass, T_ICLASS)) {
+ rb_bug("T_ICLASS");
+ }
+ path = data[0];
+ first_lineno = data[1];
+ first_column = data[2];
+ last_lineno = data[3];
+ last_column = data[4];
+ if (FIX2LONG(first_lineno) <= 0) continue;
+ ncoverage = rb_hash_aref(ncoverages, path);
+ if (NIL_P(ncoverage)) continue;
+ methods = rb_hash_aref(ncoverage, methods_id);
+
+ {
+ VALUE method_id = ID2SYM(me->def->original_id);
+ VALUE rcount = rb_hash_aref(me2counter, (VALUE) me);
+ VALUE key = rb_ary_new_from_args(6, klass, method_id, first_lineno, first_column, last_lineno, last_column);
+ VALUE rcount2 = rb_hash_aref(methods, key);
+
+ if (NIL_P(rcount)) rcount = LONG2FIX(0);
+ if (NIL_P(rcount2)) rcount2 = LONG2FIX(0);
+ if (!POSFIXABLE(FIX2LONG(rcount) + FIX2LONG(rcount2))) {
+ rcount = LONG2FIX(FIXNUM_MAX);
+ }
+ else {
+ rcount = LONG2FIX(FIX2LONG(rcount) + FIX2LONG(rcount2));
+ }
+ rb_hash_aset(methods, key, rcount);
+ }
+ }
+
+ if (poisoned) {
+ rb_asan_poison_object(v);
+ }
+ }
+ return 0;
+}
+
+static int
+coverage_peek_result_i(st_data_t key, st_data_t val, st_data_t h)
+{
+ VALUE path = (VALUE)key;
+ VALUE coverage = (VALUE)val;
+ VALUE coverages = (VALUE)h;
+ if (current_mode == 0) {
+ /* compatible mode */
+ VALUE lines = rb_ary_dup(RARRAY_AREF(coverage, COVERAGE_INDEX_LINES));
+ rb_ary_freeze(lines);
+ coverage = lines;
+ }
+ else {
+ VALUE h = rb_hash_new();
+
+ if (current_mode & COVERAGE_TARGET_LINES) {
+ VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
+ const char *kw = (current_mode & COVERAGE_TARGET_ONESHOT_LINES) ? "oneshot_lines" : "lines";
+ lines = rb_ary_dup(lines);
+ rb_ary_freeze(lines);
+ rb_hash_aset(h, ID2SYM(rb_intern(kw)), lines);
+ }
+
+ if (current_mode & COVERAGE_TARGET_BRANCHES) {
+ VALUE branches = RARRAY_AREF(coverage, COVERAGE_INDEX_BRANCHES);
+ rb_hash_aset(h, ID2SYM(rb_intern("branches")), branch_coverage(branches));
+ }
+
+ if (current_mode & COVERAGE_TARGET_METHODS) {
+ rb_hash_aset(h, ID2SYM(rb_intern("methods")), rb_hash_new());
+ }
+
+ coverage = h;
+ }
+
+ rb_hash_aset(coverages, path, coverage);
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * Coverage.peek_result => hash
+ *
+ * Returns a hash that contains filename as key and coverage array as value.
+ * This is the same as <tt>Coverage.result(stop: false, clear: false)</tt>.
+ *
+ * {
+ * "file.rb" => [1, 2, nil],
+ * ...
+ * }
+ */
+static VALUE
+rb_coverage_peek_result(VALUE klass)
+{
+ VALUE coverages = rb_get_coverages();
+ VALUE ncoverages = rb_hash_new();
+ if (!RTEST(coverages)) {
+ rb_raise(rb_eRuntimeError, "coverage measurement is not enabled");
+ }
+
+ rb_hash_foreach(coverages, coverage_peek_result_i, ncoverages);
+
+ if (current_mode & COVERAGE_TARGET_METHODS) {
+ rb_objspace_each_objects(method_coverage_i, &ncoverages);
+ }
+
+ rb_hash_freeze(ncoverages);
+ return ncoverages;
+}
+
+
+static int
+clear_me2counter_i(VALUE key, VALUE value, VALUE unused)
+{
+ rb_hash_aset(me2counter, key, INT2FIX(0));
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * Coverage.suspend => nil
+ *
+ * Suspend the coverage measurement.
+ * You can use Coverage.resume to restart the measurement.
+ */
+VALUE
+rb_coverage_suspend(VALUE klass)
+{
+ if (current_state != RUNNING) {
+ rb_raise(rb_eRuntimeError, "coverage measurement is not running");
+ }
+ rb_suspend_coverages();
+ current_state = SUSPENDED;
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Coverage.result(stop: true, clear: true) => hash
+ *
+ * Returns a hash that contains filename as key and coverage array as value.
+ * If +clear+ is true, it clears the counters to zero.
+ * If +stop+ is true, it disables coverage measurement.
+ */
+static VALUE
+rb_coverage_result(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE ncoverages;
+ VALUE opt;
+ int stop = 1, clear = 1;
+
+ if (current_state == IDLE) {
+ rb_raise(rb_eRuntimeError, "coverage measurement is not enabled");
+ }
+
+ rb_scan_args(argc, argv, "01", &opt);
+
+ if (argc == 1) {
+ opt = rb_convert_type(opt, T_HASH, "Hash", "to_hash");
+ stop = RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("stop"))));
+ clear = RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("clear"))));
+ }
+
+ ncoverages = rb_coverage_peek_result(klass);
+ if (stop && !clear) {
+ rb_warn("stop implies clear");
+ clear = 1;
+ }
+ if (clear) {
+ rb_clear_coverages();
+ if (!NIL_P(me2counter)) rb_hash_foreach(me2counter, clear_me2counter_i, Qnil);
+ }
+ if (stop) {
+ if (current_state == RUNNING) {
+ rb_coverage_suspend(klass);
+ }
+ rb_reset_coverages();
+ me2counter = Qnil;
+ current_state = IDLE;
+ }
+ return ncoverages;
+}
+
+
+/*
+ * call-seq:
+ * Coverage.state => :idle, :suspended, :running
+ *
+ * Returns the state of the coverage measurement.
+ */
+static VALUE
+rb_coverage_state(VALUE klass)
+{
+ switch (current_state) {
+ case IDLE: return ID2SYM(rb_intern("idle"));
+ case SUSPENDED: return ID2SYM(rb_intern("suspended"));
+ case RUNNING: return ID2SYM(rb_intern("running"));
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Coverage.running? => bool
+ *
+ * Returns true if coverage stats are currently being collected (after
+ * Coverage.start call, but before Coverage.result call)
+ */
+static VALUE
+rb_coverage_running(VALUE klass)
+{
+ return current_state == RUNNING ? Qtrue : Qfalse;
+}
+
+/* \Coverage provides coverage measurement feature for Ruby.
+ *
+ * Only process-global coverage measurement is supported, meaning
+ * that coverage cannot be measure on a per-thread basis.
+ *
+ * = Quick Start
+ *
+ * 1. Load coverage using <tt>require "coverage"</tt>.
+ * 2. Call Coverage.start to set up and begin coverage measurement.
+ * 3. All Ruby code loaded following the call to Coverage.start will have
+ * coverage measurement.
+ * 4. Coverage results can be fetched by calling Coverage.result, which returns a
+ * hash that contains filenames as the keys and coverage arrays as the values.
+ * Each element of the coverage array gives the number of times each line was
+ * executed. A +nil+ value means coverage was disabled for that line (e.g.
+ * lines like +else+ and +end+).
+ *
+ * = Examples
+ *
+ * In file +fib.rb+:
+ *
+ * def fibonacci(n)
+ * if n == 0
+ * 0
+ * elsif n == 1
+ * 1
+ * else
+ * fibonacci(n - 1) + fibonacci(n - 2)
+ * end
+ * end
+ *
+ * puts fibonacci(10)
+ *
+ * In another file, coverage can be measured:
+ *
+ * require "coverage"
+ * Coverage.start
+ * require "fib.rb"
+ * Coverage.result # => {"fib.rb" => [1, 177, 34, 143, 55, nil, 88, nil, nil, nil, 1]}
+ *
+ * == Lines \Coverage
+ *
+ * Lines coverage reports the number of line executions for each line.
+ * If the coverage mode is not explicitly specified when starting coverage,
+ * lines coverage is used as the default.
+ *
+ * require "coverage"
+ * Coverage.start(lines: true)
+ * require "fib"
+ * Coverage.result # => {"fib.rb" => {lines: [1, 177, 34, 143, 55, nil, 88, nil, nil, nil, 1]}}
+ *
+ * The returned hash differs depending on how Coverage.setup or Coverage.start
+ * was executed.
+ *
+ * If Coverage.start or Coverage.setup was called with no arguments, it returns a
+ * hash which contains filenames as the keys and coverage arrays as the values.
+ *
+ * If Coverage.start or Coverage.setup was called with <tt>line: true</tt>, it
+ * returns a hash which contains filenames as the keys and hashes as the values.
+ * The value hash has a key +:lines+ where the value is a coverage array.
+ *
+ * Each element of the coverage array gives the number of times the line was
+ * executed. A +nil+ value in the coverage array means coverage was disabled
+ * for that line (e.g. lines like +else+ and +end+).
+ *
+ * == Oneshot Lines \Coverage
+ *
+ * Oneshot lines coverage is similar to lines coverage, but instead of reporting
+ * the number of times a line was executed, it only reports the lines that were
+ * executed.
+ *
+ * require "coverage"
+ * Coverage.start(oneshot_lines: true)
+ * require "fib"
+ * Coverage.result # => {"fib.rb" => {oneshot_lines: [1, 11, 2, 4, 7, 5, 3]}}
+ *
+ * The value of the oneshot lines coverage result is an array containing the
+ * line numbers that were executed.
+ *
+ * == Branches \Coverage
+ *
+ * Branches coverage reports the number of times each branch within each conditional
+ * was executed.
+ *
+ * require "coverage"
+ * Coverage.start(branches: true)
+ * require "fib"
+ * Coverage.result
+ * # => {"fib.rb" => {
+ * # branches: {
+ * # [:if, 0, 2, 2, 8, 5] => {
+ * # [:then, 1, 3, 4, 3, 5] => 34,
+ * # [:else, 2, 4, 2, 8, 5] => 143},
+ * # [:if, 3, 4, 2, 8, 5] => {
+ * # [:then, 4, 5, 4, 5, 5] => 55,
+ * # [:else, 5, 7, 4, 7, 39] => 88}}}}
+ *
+ * Each entry within the branches hash is a conditional, the value of which is
+ * another hash where each entry is a branch in that conditional. The keys are
+ * arrays containing information about the branch and the values are the number
+ * of times the branch was executed.
+ *
+ * The information that makes up the array that are the keys for conditional or
+ * branches are the following, from left to right:
+ *
+ * 1. A label for the type of branch or conditional (e.g. +:if+, +:then+, +:else+).
+ * 2. A unique identifier.
+ * 3. Starting line number.
+ * 4. Starting column number.
+ * 5. Ending line number.
+ * 6. Ending column number.
+ *
+ * == Methods \Coverage
+ *
+ * Methods coverage reports how many times each method was executed.
+ *
+ * require "coverage"
+ * Coverage.start(methods: true)
+ * require "fib"
+ * p Coverage.result #=> {"fib.rb" => {methods: {[Object, :fibonacci, 1, 0, 9, 3] => 177}}}
+ *
+ * Each entry within the methods hash represents a method. The keys are arrays
+ * containing hash are the number of times the method was executed, and the keys are
+ * identifying information about the method.
+ *
+ * The information that makes up each key identifying a method is the following,
+ * from left to right:
+ *
+ * 1. Class that the method was defined in.
+ * 2. Method name as a Symbol.
+ * 3. Starting line number of the method.
+ * 4. Starting column number of the method.
+ * 5. Ending line number of the method.
+ * 6. Ending column number of the method.
+ *
+ * == Eval \Coverage
+ *
+ * Eval coverage can be combined with the coverage types above to track
+ * coverage for eval.
+ *
+ * require "coverage"
+ * Coverage.start(eval: true, lines: true)
+ *
+ * eval(<<~RUBY, nil, "eval 1")
+ * ary = []
+ * 10.times do |i|
+ * ary << "hello" * i
+ * end
+ * RUBY
+ *
+ * Coverage.result # => {"eval 1" => {lines: [1, 1, 10, nil]}}
+ *
+ * Note that the eval must have a filename assigned, otherwise coverage
+ * will not be measured.
+ *
+ * require "coverage"
+ * Coverage.start(eval: true, lines: true)
+ *
+ * eval(<<~RUBY)
+ * ary = []
+ * 10.times do |i|
+ * ary << "hello" * i
+ * end
+ * RUBY
+ *
+ * Coverage.result # => {"(eval)" => {lines: [nil, nil, nil, nil]}}
+ *
+ * Also note that if a line number is assigned to the eval and it is not 1,
+ * then the resulting coverage will be padded with +nil+ if the line number is
+ * greater than 1, and truncated if the line number is less than 1.
+ *
+ * require "coverage"
+ * Coverage.start(eval: true, lines: true)
+ *
+ * eval(<<~RUBY, nil, "eval 1", 3)
+ * ary = []
+ * 10.times do |i|
+ * ary << "hello" * i
+ * end
+ * RUBY
+ *
+ * eval(<<~RUBY, nil, "eval 2", -1)
+ * ary = []
+ * 10.times do |i|
+ * ary << "hello" * i
+ * end
+ * RUBY
+ *
+ * Coverage.result
+ * # => {"eval 1" => {lines: [nil, nil, 1, 1, 10, nil]}, "eval 2" => {lines: [10, nil]}}
+ *
+ * == All \Coverage Modes
+ *
+ * All modes of coverage can be enabled simultaneously using the Symbol +:all+.
+ * However, note that this mode runs lines coverage and not oneshot lines since
+ * they cannot be ran simultaneously.
+ *
+ * require "coverage"
+ * Coverage.start(:all)
+ * require "fib"
+ * Coverage.result
+ * # => {"fib.rb" => {
+ * # lines: [1, 177, 34, 143, 55, nil, 88, nil, nil, nil, 1],
+ * # branches: {
+ * # [:if, 0, 2, 2, 8, 5] => {
+ * # [:then, 1, 3, 4, 3, 5] => 34,
+ * # [:else, 2, 4, 2, 8, 5] => 143},
+ * # [:if, 3, 4, 2, 8, 5] => {
+ * # [:then, 4, 5, 4, 5, 5] => 55,
+ * # [:else, 5, 7, 4, 7, 39] => 88}}}},
+ * # methods: {[Object, :fibonacci, 1, 0, 9, 3] => 177}}}
+ */
+void
+Init_coverage(void)
+{
+ VALUE rb_mCoverage = rb_define_module("Coverage");
+
+ rb_define_singleton_method(rb_mCoverage, "supported?", rb_coverage_supported, 1);
+
+ rb_define_module_function(rb_mCoverage, "setup", rb_coverage_setup, -1);
+ rb_define_module_function(rb_mCoverage, "start", rb_coverage_start, -1);
+ rb_define_module_function(rb_mCoverage, "resume", rb_coverage_resume, 0);
+ rb_define_module_function(rb_mCoverage, "suspend", rb_coverage_suspend, 0);
+ rb_define_module_function(rb_mCoverage, "result", rb_coverage_result, -1);
+ rb_define_module_function(rb_mCoverage, "peek_result", rb_coverage_peek_result, 0);
+ rb_define_module_function(rb_mCoverage, "state", rb_coverage_state, 0);
+ rb_define_module_function(rb_mCoverage, "running?", rb_coverage_running, 0);
+ rb_global_variable(&me2counter);
+}
diff --git a/ext/coverage/depend b/ext/coverage/depend
new file mode 100644
index 0000000000..fb7f9a95af
--- /dev/null
+++ b/ext/coverage/depend
@@ -0,0 +1,210 @@
+# AUTOGENERATED DEPENDENCIES START
+coverage.o: $(RUBY_EXTCONF_H)
+coverage.o: $(arch_hdrdir)/ruby/config.h
+coverage.o: $(hdrdir)/ruby.h
+coverage.o: $(hdrdir)/ruby/assert.h
+coverage.o: $(hdrdir)/ruby/atomic.h
+coverage.o: $(hdrdir)/ruby/backward.h
+coverage.o: $(hdrdir)/ruby/backward/2/assume.h
+coverage.o: $(hdrdir)/ruby/backward/2/attributes.h
+coverage.o: $(hdrdir)/ruby/backward/2/bool.h
+coverage.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+coverage.o: $(hdrdir)/ruby/backward/2/inttypes.h
+coverage.o: $(hdrdir)/ruby/backward/2/limits.h
+coverage.o: $(hdrdir)/ruby/backward/2/long_long.h
+coverage.o: $(hdrdir)/ruby/backward/2/stdalign.h
+coverage.o: $(hdrdir)/ruby/backward/2/stdarg.h
+coverage.o: $(hdrdir)/ruby/defines.h
+coverage.o: $(hdrdir)/ruby/encoding.h
+coverage.o: $(hdrdir)/ruby/intern.h
+coverage.o: $(hdrdir)/ruby/internal/abi.h
+coverage.o: $(hdrdir)/ruby/internal/anyargs.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+coverage.o: $(hdrdir)/ruby/internal/assume.h
+coverage.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+coverage.o: $(hdrdir)/ruby/internal/attr/artificial.h
+coverage.o: $(hdrdir)/ruby/internal/attr/cold.h
+coverage.o: $(hdrdir)/ruby/internal/attr/const.h
+coverage.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+coverage.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+coverage.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+coverage.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+coverage.o: $(hdrdir)/ruby/internal/attr/error.h
+coverage.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+coverage.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+coverage.o: $(hdrdir)/ruby/internal/attr/format.h
+coverage.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+coverage.o: $(hdrdir)/ruby/internal/attr/noalias.h
+coverage.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+coverage.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+coverage.o: $(hdrdir)/ruby/internal/attr/noinline.h
+coverage.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+coverage.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+coverage.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+coverage.o: $(hdrdir)/ruby/internal/attr/pure.h
+coverage.o: $(hdrdir)/ruby/internal/attr/restrict.h
+coverage.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+coverage.o: $(hdrdir)/ruby/internal/attr/warning.h
+coverage.o: $(hdrdir)/ruby/internal/attr/weakref.h
+coverage.o: $(hdrdir)/ruby/internal/cast.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_since.h
+coverage.o: $(hdrdir)/ruby/internal/config.h
+coverage.o: $(hdrdir)/ruby/internal/constant_p.h
+coverage.o: $(hdrdir)/ruby/internal/core.h
+coverage.o: $(hdrdir)/ruby/internal/core/rarray.h
+coverage.o: $(hdrdir)/ruby/internal/core/rbasic.h
+coverage.o: $(hdrdir)/ruby/internal/core/rbignum.h
+coverage.o: $(hdrdir)/ruby/internal/core/rclass.h
+coverage.o: $(hdrdir)/ruby/internal/core/rdata.h
+coverage.o: $(hdrdir)/ruby/internal/core/rfile.h
+coverage.o: $(hdrdir)/ruby/internal/core/rhash.h
+coverage.o: $(hdrdir)/ruby/internal/core/robject.h
+coverage.o: $(hdrdir)/ruby/internal/core/rregexp.h
+coverage.o: $(hdrdir)/ruby/internal/core/rstring.h
+coverage.o: $(hdrdir)/ruby/internal/core/rstruct.h
+coverage.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+coverage.o: $(hdrdir)/ruby/internal/ctype.h
+coverage.o: $(hdrdir)/ruby/internal/dllexport.h
+coverage.o: $(hdrdir)/ruby/internal/dosish.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/re.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/string.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+coverage.o: $(hdrdir)/ruby/internal/error.h
+coverage.o: $(hdrdir)/ruby/internal/eval.h
+coverage.o: $(hdrdir)/ruby/internal/event.h
+coverage.o: $(hdrdir)/ruby/internal/fl_type.h
+coverage.o: $(hdrdir)/ruby/internal/gc.h
+coverage.o: $(hdrdir)/ruby/internal/glob.h
+coverage.o: $(hdrdir)/ruby/internal/globals.h
+coverage.o: $(hdrdir)/ruby/internal/has/attribute.h
+coverage.o: $(hdrdir)/ruby/internal/has/builtin.h
+coverage.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+coverage.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+coverage.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+coverage.o: $(hdrdir)/ruby/internal/has/extension.h
+coverage.o: $(hdrdir)/ruby/internal/has/feature.h
+coverage.o: $(hdrdir)/ruby/internal/has/warning.h
+coverage.o: $(hdrdir)/ruby/internal/intern/array.h
+coverage.o: $(hdrdir)/ruby/internal/intern/bignum.h
+coverage.o: $(hdrdir)/ruby/internal/intern/class.h
+coverage.o: $(hdrdir)/ruby/internal/intern/compar.h
+coverage.o: $(hdrdir)/ruby/internal/intern/complex.h
+coverage.o: $(hdrdir)/ruby/internal/intern/cont.h
+coverage.o: $(hdrdir)/ruby/internal/intern/dir.h
+coverage.o: $(hdrdir)/ruby/internal/intern/enum.h
+coverage.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+coverage.o: $(hdrdir)/ruby/internal/intern/error.h
+coverage.o: $(hdrdir)/ruby/internal/intern/eval.h
+coverage.o: $(hdrdir)/ruby/internal/intern/file.h
+coverage.o: $(hdrdir)/ruby/internal/intern/hash.h
+coverage.o: $(hdrdir)/ruby/internal/intern/io.h
+coverage.o: $(hdrdir)/ruby/internal/intern/load.h
+coverage.o: $(hdrdir)/ruby/internal/intern/marshal.h
+coverage.o: $(hdrdir)/ruby/internal/intern/numeric.h
+coverage.o: $(hdrdir)/ruby/internal/intern/object.h
+coverage.o: $(hdrdir)/ruby/internal/intern/parse.h
+coverage.o: $(hdrdir)/ruby/internal/intern/proc.h
+coverage.o: $(hdrdir)/ruby/internal/intern/process.h
+coverage.o: $(hdrdir)/ruby/internal/intern/random.h
+coverage.o: $(hdrdir)/ruby/internal/intern/range.h
+coverage.o: $(hdrdir)/ruby/internal/intern/rational.h
+coverage.o: $(hdrdir)/ruby/internal/intern/re.h
+coverage.o: $(hdrdir)/ruby/internal/intern/ruby.h
+coverage.o: $(hdrdir)/ruby/internal/intern/select.h
+coverage.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+coverage.o: $(hdrdir)/ruby/internal/intern/set.h
+coverage.o: $(hdrdir)/ruby/internal/intern/signal.h
+coverage.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+coverage.o: $(hdrdir)/ruby/internal/intern/string.h
+coverage.o: $(hdrdir)/ruby/internal/intern/struct.h
+coverage.o: $(hdrdir)/ruby/internal/intern/thread.h
+coverage.o: $(hdrdir)/ruby/internal/intern/time.h
+coverage.o: $(hdrdir)/ruby/internal/intern/variable.h
+coverage.o: $(hdrdir)/ruby/internal/intern/vm.h
+coverage.o: $(hdrdir)/ruby/internal/interpreter.h
+coverage.o: $(hdrdir)/ruby/internal/iterator.h
+coverage.o: $(hdrdir)/ruby/internal/memory.h
+coverage.o: $(hdrdir)/ruby/internal/method.h
+coverage.o: $(hdrdir)/ruby/internal/module.h
+coverage.o: $(hdrdir)/ruby/internal/newobj.h
+coverage.o: $(hdrdir)/ruby/internal/scan_args.h
+coverage.o: $(hdrdir)/ruby/internal/special_consts.h
+coverage.o: $(hdrdir)/ruby/internal/static_assert.h
+coverage.o: $(hdrdir)/ruby/internal/stdalign.h
+coverage.o: $(hdrdir)/ruby/internal/stdbool.h
+coverage.o: $(hdrdir)/ruby/internal/stdckdint.h
+coverage.o: $(hdrdir)/ruby/internal/symbol.h
+coverage.o: $(hdrdir)/ruby/internal/value.h
+coverage.o: $(hdrdir)/ruby/internal/value_type.h
+coverage.o: $(hdrdir)/ruby/internal/variable.h
+coverage.o: $(hdrdir)/ruby/internal/warning_push.h
+coverage.o: $(hdrdir)/ruby/internal/xmalloc.h
+coverage.o: $(hdrdir)/ruby/missing.h
+coverage.o: $(hdrdir)/ruby/onigmo.h
+coverage.o: $(hdrdir)/ruby/oniguruma.h
+coverage.o: $(hdrdir)/ruby/ruby.h
+coverage.o: $(hdrdir)/ruby/st.h
+coverage.o: $(hdrdir)/ruby/subst.h
+coverage.o: $(hdrdir)/ruby/thread_native.h
+coverage.o: $(top_srcdir)/ccan/check_type/check_type.h
+coverage.o: $(top_srcdir)/ccan/container_of/container_of.h
+coverage.o: $(top_srcdir)/ccan/list/list.h
+coverage.o: $(top_srcdir)/ccan/str/str.h
+coverage.o: $(top_srcdir)/constant.h
+coverage.o: $(top_srcdir)/id_table.h
+coverage.o: $(top_srcdir)/internal.h
+coverage.o: $(top_srcdir)/internal/array.h
+coverage.o: $(top_srcdir)/internal/basic_operators.h
+coverage.o: $(top_srcdir)/internal/box.h
+coverage.o: $(top_srcdir)/internal/compilers.h
+coverage.o: $(top_srcdir)/internal/gc.h
+coverage.o: $(top_srcdir)/internal/hash.h
+coverage.o: $(top_srcdir)/internal/imemo.h
+coverage.o: $(top_srcdir)/internal/sanitizers.h
+coverage.o: $(top_srcdir)/internal/serial.h
+coverage.o: $(top_srcdir)/internal/set_table.h
+coverage.o: $(top_srcdir)/internal/static_assert.h
+coverage.o: $(top_srcdir)/internal/thread.h
+coverage.o: $(top_srcdir)/internal/variable.h
+coverage.o: $(top_srcdir)/internal/vm.h
+coverage.o: $(top_srcdir)/internal/warnings.h
+coverage.o: $(top_srcdir)/method.h
+coverage.o: $(top_srcdir)/node.h
+coverage.o: $(top_srcdir)/ruby_assert.h
+coverage.o: $(top_srcdir)/ruby_atomic.h
+coverage.o: $(top_srcdir)/rubyparser.h
+coverage.o: $(top_srcdir)/shape.h
+coverage.o: $(top_srcdir)/thread_pthread.h
+coverage.o: $(top_srcdir)/vm_core.h
+coverage.o: $(top_srcdir)/vm_opts.h
+coverage.o: coverage.c
+coverage.o: {$(VPATH)}id.h
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/coverage/extconf.rb b/ext/coverage/extconf.rb
new file mode 100644
index 0000000000..3a6f530a92
--- /dev/null
+++ b/ext/coverage/extconf.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: false
+require 'mkmf'
+$VPATH << '$(topdir)' << '$(top_srcdir)'
+$INCFLAGS << " -I$(topdir) -I$(top_srcdir)"
+create_makefile('coverage')
diff --git a/ext/coverage/lib/coverage.rb b/ext/coverage/lib/coverage.rb
new file mode 100644
index 0000000000..4bd20e22cb
--- /dev/null
+++ b/ext/coverage/lib/coverage.rb
@@ -0,0 +1,19 @@
+require "coverage.so"
+
+module Coverage
+ # call-seq:
+ # line_stub(file) -> array
+ #
+ # A simple helper function that creates the "stub" of line coverage
+ # from a given source code.
+ def self.line_stub(file)
+ lines = File.foreach(file).map { nil }
+ iseqs = [RubyVM::InstructionSequence.compile_file(file)]
+ until iseqs.empty?
+ iseq = iseqs.pop
+ iseq.trace_points.each {|n, type| lines[n - 1] = 0 if type == :line }
+ iseq.each_child {|child| iseqs << child }
+ end
+ lines
+ end
+end
diff --git a/ext/curses/.cvsignore b/ext/curses/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/curses/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/curses/curses.c b/ext/curses/curses.c
deleted file mode 100644
index 70a4b415bf..0000000000
--- a/ext/curses/curses.c
+++ /dev/null
@@ -1,2102 +0,0 @@
-/* -*- C -*-
- * $Id$
- *
- * ext/curses/curses.c
- *
- * by MAEDA Shugo (ender@pic-internet.or.jp)
- * modified by Yukihiro Matsumoto (matz@netlab.co.jp),
- * Toki Yoshinori,
- * Hitoshi Takahashi,
- * and Takaaki Tateishi (ttate@kt.jaist.ac.jp)
- *
- * maintainers:
- * - Takaaki Tateishi (ttate@kt.jaist.ac.jp)
- */
-
-#include "ruby.h"
-#include "rubyio.h"
-
-#if defined(HAVE_NCURSES_H)
-# include <ncurses.h>
-#elif defined(HAVE_NCURSES_CURSES_H)
-# include <ncurses/curses.h>
-#elif defined(HAVE_CURSES_COLR_CURSES_H)
-# ifdef HAVE_STDARG_PROTOTYPES
-# include <stdarg.h>
-# else
-# include <varargs.h>
-# endif
-# include <curses_colr/curses.h>
-#else
-# include <curses.h>
-# if defined(__bsdi__) || defined(__NetBSD__) || defined(__APPLE__)
-# if !defined(_maxx)
-# define _maxx maxx
-# endif
-# if !defined(_maxy)
-# define _maxy maxy
-# endif
-# if !defined(_begx)
-# define _begx begx
-# endif
-# if !defined(_begy)
-# define _begy begy
-# endif
-# endif
-#endif
-
-#ifdef HAVE_INIT_COLOR
-# define USE_COLOR 1
-#endif
-
-/* supports only ncurses mouse routines */
-#ifdef NCURSES_MOUSE_VERSION
-# define USE_MOUSE 1
-#endif
-
-#define NUM2CH NUM2LONG
-#define CH2FIX LONG2FIX
-
-static VALUE mCurses;
-static VALUE mKey;
-static VALUE cWindow;
-#ifdef USE_MOUSE
-static VALUE cMouseEvent;
-#endif
-
-static VALUE rb_stdscr;
-
-struct windata {
- WINDOW *window;
-};
-
-#define CHECK(c) c
-
-static VALUE window_attroff();
-static VALUE window_attron();
-static VALUE window_attrset();
-
-static void
-no_window()
-{
- rb_raise(rb_eRuntimeError, "already closed window");
-}
-
-#define GetWINDOW(obj, winp) do {\
- if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
- rb_raise(rb_eSecurityError, "Insecure: operation on untainted window");\
- Data_Get_Struct(obj, struct windata, winp);\
- if (winp->window == 0) no_window();\
-} while (0)
-
-static void
-free_window(winp)
- struct windata *winp;
-{
- if (winp->window && winp->window != stdscr) delwin(winp->window);
- winp->window = 0;
- free(winp);
-}
-
-static VALUE
-prep_window(class, window)
- VALUE class;
- WINDOW *window;
-{
- VALUE obj;
- struct windata *winp;
-
- if (window == NULL) {
- rb_raise(rb_eRuntimeError, "failed to create window");
- }
-
- obj = rb_obj_alloc(class);
- Data_Get_Struct(obj, struct windata, winp);
- winp->window = window;
-
- return obj;
-}
-
-/*-------------------------- module Curses --------------------------*/
-
-/* def init_screen */
-static VALUE
-curses_init_screen()
-{
- rb_secure(4);
- if (rb_stdscr) return rb_stdscr;
- initscr();
- if (stdscr == 0) {
- rb_raise(rb_eRuntimeError, "can't initialize curses");
- }
- clear();
- rb_stdscr = prep_window(cWindow, stdscr);
- return rb_stdscr;
-}
-
-/* def stdscr */
-#define curses_stdscr curses_init_screen
-
-/* def close_screen */
-static VALUE
-curses_close_screen()
-{
-#ifdef HAVE_ISENDWIN
- if (!isendwin())
-#endif
- endwin();
- rb_stdscr = 0;
- return Qnil;
-}
-
-static void
-curses_finalize(VALUE dummy)
-{
- if (stdscr
-#ifdef HAVE_ISENDWIN
- && !isendwin()
-#endif
- )
- endwin();
- rb_stdscr = 0;
- rb_gc_unregister_address(&rb_stdscr);
-}
-
-/* def closed? */
-static VALUE
-curses_closed()
-{
-#ifdef HAVE_ISENDWIN
- if (isendwin()) {
- return Qtrue;
- }
- return Qfalse;
-#else
- rb_notimplement();
-#endif
-}
-
-/* def clear */
-static VALUE
-curses_clear(obj)
- VALUE obj;
-{
- curses_stdscr();
- wclear(stdscr);
- return Qnil;
-}
-
-/* def clrtoeol */
-static VALUE
-curses_clrtoeol()
-{
- curses_stdscr();
- clrtoeol();
- return Qnil;
-}
-
-/* def refresh */
-static VALUE
-curses_refresh(obj)
- VALUE obj;
-{
- curses_stdscr();
- refresh();
- return Qnil;
-}
-
-/* def doupdate */
-static VALUE
-curses_doupdate(obj)
- VALUE obj;
-{
- curses_stdscr();
-#ifdef HAVE_DOUPDATE
- doupdate();
-#else
- refresh();
-#endif
- return Qnil;
-}
-
-/* def echo */
-static VALUE
-curses_echo(obj)
- VALUE obj;
-{
- curses_stdscr();
- echo();
- return Qnil;
-}
-
-/* def noecho */
-static VALUE
-curses_noecho(obj)
- VALUE obj;
-{
- curses_stdscr();
- noecho();
- return Qnil;
-}
-
-/* def raw */
-static VALUE
-curses_raw(obj)
- VALUE obj;
-{
- curses_stdscr();
- raw();
- return Qnil;
-}
-
-/* def noraw */
-static VALUE
-curses_noraw(obj)
- VALUE obj;
-{
- curses_stdscr();
- noraw();
- return Qnil;
-}
-
-/* def cbreak */
-static VALUE
-curses_cbreak(obj)
- VALUE obj;
-{
- curses_stdscr();
- cbreak();
- return Qnil;
-}
-
-/* def nocbreak */
-static VALUE
-curses_nocbreak(obj)
- VALUE obj;
-{
- curses_stdscr();
- nocbreak();
- return Qnil;
-}
-
-/* def nl */
-static VALUE
-curses_nl(obj)
- VALUE obj;
-{
- curses_stdscr();
- nl();
- return Qnil;
-}
-
-/* def nonl */
-static VALUE
-curses_nonl(obj)
- VALUE obj;
-{
- curses_stdscr();
- nonl();
- return Qnil;
-}
-
-/* def beep */
-static VALUE
-curses_beep(obj)
- VALUE obj;
-{
-#ifdef HAVE_BEEP
- curses_stdscr();
- beep();
-#endif
- return Qnil;
-}
-
-/* def flash */
-static VALUE
-curses_flash(obj)
- VALUE obj;
-{
-#ifdef HAVE_FLASH
- curses_stdscr();
- flash();
-#endif
- return Qnil;
-}
-
-/* def ungetch */
-static VALUE
-curses_ungetch(obj, ch)
- VALUE obj;
- VALUE ch;
-{
-#ifdef HAVE_UNGETCH
- curses_stdscr();
- ungetch(NUM2INT(ch));
-#else
- rb_notimplement();
-#endif
- return Qnil;
-}
-
-/* def setpos(y, x) */
-static VALUE
-curses_setpos(obj, y, x)
- VALUE obj;
- VALUE y;
- VALUE x;
-{
- curses_stdscr();
- move(NUM2INT(y), NUM2INT(x));
- return Qnil;
-}
-
-/* def standout */
-static VALUE
-curses_standout(obj)
- VALUE obj;
-{
- standout();
- return Qnil;
-}
-
-/* def standend */
-static VALUE
-curses_standend(obj)
- VALUE obj;
-{
- standend();
- return Qnil;
-}
-
-/* def inch */
-static VALUE
-curses_inch(obj)
- VALUE obj;
-{
- curses_stdscr();
- return CH2FIX(inch());
-}
-
-/* def addch(ch) */
-static VALUE
-curses_addch(obj, ch)
- VALUE obj;
- VALUE ch;
-{
- curses_stdscr();
- addch(NUM2CH(ch));
- return Qnil;
-}
-
-/* def insch(ch) */
-static VALUE
-curses_insch(obj, ch)
- VALUE obj;
- VALUE ch;
-{
- curses_stdscr();
- insch(NUM2CH(ch));
- return Qnil;
-}
-
-/* def addstr(str) */
-static VALUE
-curses_addstr(obj, str)
- VALUE obj;
- VALUE str;
-{
- curses_stdscr();
- if (!NIL_P(str)) {
- addstr(STR2CSTR(str));
- }
- return Qnil;
-}
-
-/* def getch */
-static VALUE
-curses_getch(obj)
- VALUE obj;
-{
- rb_read_check(stdin);
- curses_stdscr();
- return UINT2NUM(getch());
-}
-
-/* def getstr */
-static VALUE
-curses_getstr(obj)
- VALUE obj;
-{
- char rtn[1024]; /* This should be big enough.. I hope */
-
- rb_read_check(stdin);
-#if defined(HAVE_GETNSTR)
- getnstr(rtn,1023);
-#else
- getstr(rtn);
-#endif
- return rb_tainted_str_new2(rtn);
-}
-
-/* def delch */
-static VALUE
-curses_delch(obj)
- VALUE obj;
-{
- delch();
- return Qnil;
-}
-
-/* def delelteln */
-static VALUE
-curses_deleteln(obj)
- VALUE obj;
-{
-#if defined(HAVE_DELETELN) || defined(deleteln)
- deleteln();
-#endif
- return Qnil;
-}
-
-/* def insertln */
-static VALUE
-curses_insertln(obj)
- VALUE obj;
-{
-#if defined(HAVE_INSERTLN) || defined(insertln)
- insertln();
-#endif
- return Qnil;
-}
-
-/* def keyname */
-static VALUE
-curses_keyname(obj, c)
- VALUE obj;
- VALUE c;
-{
-#ifdef HAVE_KEYNAME
- const char *name;
-
- name = keyname(NUM2INT(c));
- if (name) {
- return rb_str_new2(name);
- } else {
- return Qnil;
- }
-#else
- return Qnil;
-#endif
-}
-
-static VALUE
-curses_lines()
-{
- return INT2FIX(LINES);
-}
-
-static VALUE
-curses_cols()
-{
- return INT2FIX(COLS);
-}
-
-static VALUE
-curses_curs_set(VALUE obj, VALUE visibility)
-{
-#ifdef HAVE_CURS_SET
- int n;
- return (n = curs_set(NUM2INT(visibility)) != ERR) ? INT2FIX(n) : Qnil;
-#else
- return Qnil;
-#endif
-}
-
-static VALUE
-curses_scrl(VALUE obj, VALUE n)
-{
- /* may have to raise exception on ERR */
-#ifdef HAVE_SCRL
- return (scrl(NUM2INT(n)) == OK) ? Qtrue : Qfalse;
-#else
- return Qfalse;
-#endif
-}
-
-static VALUE
-curses_setscrreg(VALUE obj, VALUE top, VALUE bottom)
-{
- /* may have to raise exception on ERR */
-#ifdef HAVE_SETSCRREG
- return (setscrreg(NUM2INT(top), NUM2INT(bottom)) == OK) ? Qtrue : Qfalse;
-#else
- return Qfalse;
-#endif
-}
-
-static VALUE
-curses_attroff(VALUE obj, VALUE attrs)
-{
- return window_attroff(rb_stdscr,attrs);
- /* return INT2FIX(attroff(NUM2INT(attrs))); */
-}
-
-static VALUE
-curses_attron(VALUE obj, VALUE attrs)
-{
- return window_attron(rb_stdscr,attrs);
- /* return INT2FIX(attroff(NUM2INT(attrs))); */
-}
-
-static VALUE
-curses_attrset(VALUE obj, VALUE attrs)
-{
- return window_attrset(rb_stdscr,attrs);
- /* return INT2FIX(attroff(NUM2INT(attrs))); */
-}
-
-static VALUE
-curses_bkgdset(VALUE obj, VALUE ch)
-{
-#ifdef HAVE_BKGDSET
- bkgdset(NUM2CH(ch));
-#endif
- return Qnil;
-}
-
-static VALUE
-curses_bkgd(VALUE obj, VALUE ch)
-{
-#ifdef HAVE_BKGD
- return (bkgd(NUM2CH(ch)) == OK) ? Qtrue : Qfalse;
-#else
- return Qfalse;
-#endif
-}
-
-static VALUE
-curses_resizeterm(VALUE obj, VALUE lin, VALUE col)
-{
-#if defined(HAVE_RESIZETERM)
- return (resizeterm(NUM2INT(lin),NUM2INT(col)) == OK) ? Qtrue : Qfalse;
-#else
- return Qnil;
-#endif
-}
-
-#ifdef USE_COLOR
-static VALUE
-curses_start_color(VALUE obj)
-{
- /* may have to raise exception on ERR */
- return (start_color() == OK) ? Qtrue : Qfalse;
-}
-
-static VALUE
-curses_init_pair(VALUE obj, VALUE pair, VALUE f, VALUE b)
-{
- /* may have to raise exception on ERR */
- return (init_pair(NUM2INT(pair),NUM2INT(f),NUM2INT(b)) == OK) ? Qtrue : Qfalse;
-}
-
-static VALUE
-curses_init_color(VALUE obj, VALUE color, VALUE r, VALUE g, VALUE b)
-{
- /* may have to raise exception on ERR */
- return (init_color(NUM2INT(color),NUM2INT(r),
- NUM2INT(g),NUM2INT(b)) == OK) ? Qtrue : Qfalse;
-}
-
-static VALUE
-curses_has_colors(VALUE obj)
-{
- return has_colors() ? Qtrue : Qfalse;
-}
-
-static VALUE
-curses_can_change_color(VALUE obj)
-{
- return can_change_color() ? Qtrue : Qfalse;
-}
-
-static VALUE
-curses_color_content(VALUE obj, VALUE color)
-{
- short r,g,b;
-
- color_content(NUM2INT(color),&r,&g,&b);
- return rb_ary_new3(3,INT2FIX(r),INT2FIX(g),INT2FIX(b));
-}
-
-static VALUE
-curses_pair_content(VALUE obj, VALUE pair)
-{
- short f,b;
-
- pair_content(NUM2INT(pair),&f,&b);
- return rb_ary_new3(2,INT2FIX(f),INT2FIX(b));
-}
-
-static VALUE
-curses_color_pair(VALUE obj, VALUE attrs)
-{
- return INT2FIX(COLOR_PAIR(NUM2INT(attrs)));
-}
-
-static VALUE
-curses_pair_number(VALUE obj, VALUE attrs)
-{
- return INT2FIX(PAIR_NUMBER(NUM2INT(attrs)));
-}
-#endif /* USE_COLOR */
-
-#ifdef USE_MOUSE
-struct mousedata {
- MEVENT *mevent;
-};
-
-static void
-no_mevent()
-{
- rb_raise(rb_eRuntimeError, "no such mouse event");
-}
-
-#define GetMOUSE(obj, data) do {\
- if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)\
- rb_raise(rb_eSecurityError, "Insecure: operation on untainted mouse");\
- Data_Get_Struct(obj, struct mousedata, data);\
- if (data->mevent == 0) no_mevent();\
-} while (0)
-
-static void
-curses_mousedata_free(struct mousedata *mdata)
-{
- if (mdata->mevent)
- free(mdata->mevent);
-}
-
-static VALUE
-curses_getmouse(VALUE obj)
-{
- struct mousedata *mdata;
- VALUE val;
-
- val = Data_Make_Struct(cMouseEvent,struct mousedata,
- 0,curses_mousedata_free,mdata);
- mdata->mevent = (MEVENT*)xmalloc(sizeof(MEVENT));
- return (getmouse(mdata->mevent) == OK) ? val : Qnil;
-}
-
-static VALUE
-curses_ungetmouse(VALUE obj, VALUE mevent)
-{
- struct mousedata *mdata;
-
- GetMOUSE(mevent,mdata);
- return (ungetmouse(mdata->mevent) == OK) ? Qtrue : Qfalse;
-}
-
-static VALUE
-curses_mouseinterval(VALUE obj, VALUE interval)
-{
- return mouseinterval(NUM2INT(interval)) ? Qtrue : Qfalse;
-}
-
-static VALUE
-curses_mousemask(VALUE obj, VALUE mask)
-{
- return INT2NUM(mousemask(NUM2UINT(mask),NULL));
-}
-
-#define DEFINE_MOUSE_GET_MEMBER(func_name,mem) \
-static VALUE func_name (VALUE mouse) \
-{ \
- struct mousedata *mdata; \
- GetMOUSE(mouse, mdata); \
- return (UINT2NUM(mdata->mevent -> mem)); \
-}
-
-DEFINE_MOUSE_GET_MEMBER(curs_mouse_id, id)
-DEFINE_MOUSE_GET_MEMBER(curs_mouse_x, x)
-DEFINE_MOUSE_GET_MEMBER(curs_mouse_y, y)
-DEFINE_MOUSE_GET_MEMBER(curs_mouse_z, z)
-DEFINE_MOUSE_GET_MEMBER(curs_mouse_bstate, bstate)
-#undef define_curs_mouse_member
-#endif /* USE_MOUSE */
-
-static VALUE
-curses_timeout(VALUE obj, VALUE delay)
-{
-#ifdef HAVE_TIMEOUT
- timeout(NUM2INT(delay));
- return Qnil;
-#else
- rb_notimplement();
-#endif
-}
-
-static VALUE
-curses_def_prog_mode(VALUE obj)
-{
-#ifdef HAVE_DEF_PROG_MODE
- return def_prog_mode() == OK ? Qtrue : Qfalse;
-#else
- rb_notimplement();
-#endif
-}
-
-static VALUE
-curses_reset_prog_mode(VALUE obj)
-{
-#ifdef HAVE_RESET_PROG_MODE
- return reset_prog_mode() == OK ? Qtrue : Qfalse;
-#else
- rb_notimplement();
-#endif
-}
-
-/*-------------------------- class Window --------------------------*/
-
-/* def self.allocate */
-static VALUE
-window_s_allocate(VALUE class)
-{
- struct windata *winp;
-
- return Data_Make_Struct(class, struct windata, 0, free_window, winp);
-}
-
-/* def initialize(h, w, top, left) */
-static VALUE
-window_initialize(obj, h, w, top, left)
- VALUE obj;
- VALUE h;
- VALUE w;
- VALUE top;
- VALUE left;
-{
- struct windata *winp;
- WINDOW *window;
-
- rb_secure(4);
- curses_init_screen();
- Data_Get_Struct(obj, struct windata, winp);
- if (winp->window) delwin(winp->window);
- window = newwin(NUM2INT(h), NUM2INT(w), NUM2INT(top), NUM2INT(left));
- wclear(window);
- winp->window = window;
-
- return obj;
-}
-
-/* def subwin(height, width, top, left) */
-static VALUE
-window_subwin(obj, height, width, top, left)
- VALUE obj;
- VALUE height;
- VALUE width;
- VALUE top;
- VALUE left;
-{
- struct windata *winp;
- WINDOW *window;
- VALUE win;
- int h, w, t, l;
-
- h = NUM2INT(height);
- w = NUM2INT(width);
- t = NUM2INT(top);
- l = NUM2INT(left);
- GetWINDOW(obj, winp);
- window = subwin(winp->window, h, w, t, l);
- win = prep_window(rb_obj_class(obj), window);
-
- return win;
-}
-
-/* def close */
-static VALUE
-window_close(obj)
- VALUE obj;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- delwin(winp->window);
- winp->window = 0;
-
- return Qnil;
-}
-
-/* def clear */
-static VALUE
-window_clear(obj)
- VALUE obj;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- wclear(winp->window);
-
- return Qnil;
-}
-
-/* def clrtoeol */
-static VALUE
-window_clrtoeol(obj)
- VALUE obj;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- wclrtoeol(winp->window);
-
- return Qnil;
-}
-
-/* def refresh */
-static VALUE
-window_refresh(obj)
- VALUE obj;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- wrefresh(winp->window);
-
- return Qnil;
-}
-
-/* def noutrefresh */
-static VALUE
-window_noutrefresh(obj)
- VALUE obj;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
-#ifdef HAVE_DOUPDATE
- wnoutrefresh(winp->window);
-#else
- wrefresh(winp->window);
-#endif
-
- return Qnil;
-}
-
-/* def move(y, x) */
-static VALUE
-window_move(obj, y, x)
- VALUE obj;
- VALUE y;
- VALUE x;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- mvwin(winp->window, NUM2INT(y), NUM2INT(x));
-
- return Qnil;
-}
-
-/* def setpos(y, x) */
-static VALUE
-window_setpos(obj, y, x)
- VALUE obj;
- VALUE y;
- VALUE x;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- wmove(winp->window, NUM2INT(y), NUM2INT(x));
- return Qnil;
-}
-
-/* def cury */
-static VALUE
-window_cury(obj)
- VALUE obj;
-{
- struct windata *winp;
- int x, y;
-
- GetWINDOW(obj, winp);
- getyx(winp->window, y, x);
- return INT2FIX(y);
-}
-
-/* def curx */
-static VALUE
-window_curx(obj)
- VALUE obj;
-{
- struct windata *winp;
- int x, y;
-
- GetWINDOW(obj, winp);
- getyx(winp->window, y, x);
- return INT2FIX(x);
-}
-
-/* def maxy */
-static VALUE
-window_maxy(obj)
- VALUE obj;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
-#if defined(getmaxy)
- return INT2FIX(getmaxy(winp->window));
-#elif defined(getmaxyx)
- {
- int x, y;
- getmaxyx(winp->window, y, x);
- return INT2FIX(y);
- }
-#else
- return INT2FIX(winp->window->_maxy+1);
-#endif
-}
-
-/* def maxx */
-static VALUE
-window_maxx(obj)
- VALUE obj;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
-#if defined(getmaxx)
- return INT2FIX(getmaxx(winp->window));
-#elif defined(getmaxyx)
- {
- int x, y;
- getmaxyx(winp->window, y, x);
- return INT2FIX(x);
- }
-#else
- return INT2FIX(winp->window->_maxx+1);
-#endif
-}
-
-/* def begy */
-static VALUE
-window_begy(obj)
- VALUE obj;
-{
- struct windata *winp;
- int x, y;
-
- GetWINDOW(obj, winp);
-#ifdef getbegyx
- getbegyx(winp->window, y, x);
- return INT2FIX(y);
-#else
- return INT2FIX(winp->window->_begy);
-#endif
-}
-
-/* def begx */
-static VALUE
-window_begx(obj)
- VALUE obj;
-{
- struct windata *winp;
- int x, y;
-
- GetWINDOW(obj, winp);
-#ifdef getbegyx
- getbegyx(winp->window, y, x);
- return INT2FIX(x);
-#else
- return INT2FIX(winp->window->_begx);
-#endif
-}
-
-/* def box(vert, hor) */
-static VALUE
-window_box(argc, argv, self)
- int argc;
- VALUE argv[], self;
-{
- struct windata *winp;
- VALUE vert, hor, corn;
-
- rb_scan_args(argc, argv, "21", &vert, &hor, &corn);
-
- GetWINDOW(self, winp);
- box(winp->window, NUM2CH(vert), NUM2CH(hor));
-
- if (!NIL_P(corn)) {
- int cur_x, cur_y, x, y;
- chtype c;
-
- c = NUM2CH(corn);
- getyx(winp->window, cur_y, cur_x);
- x = NUM2INT(window_maxx(self)) - 1;
- y = NUM2INT(window_maxy(self)) - 1;
- wmove(winp->window, 0, 0);
- waddch(winp->window, c);
- wmove(winp->window, y, 0);
- waddch(winp->window, c);
- wmove(winp->window, y, x);
- waddch(winp->window, c);
- wmove(winp->window, 0, x);
- waddch(winp->window, c);
- wmove(winp->window, cur_y, cur_x);
- }
-
- return Qnil;
-}
-
-/* def standout */
-static VALUE
-window_standout(obj)
- VALUE obj;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- wstandout(winp->window);
- return Qnil;
-}
-
-/* def standend */
-static VALUE
-window_standend(obj)
- VALUE obj;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- wstandend(winp->window);
- return Qnil;
-}
-
-/* def inch */
-static VALUE
-window_inch(obj)
- VALUE obj;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- return CH2FIX(winch(winp->window));
-}
-
-/* def addch(ch) */
-static VALUE
-window_addch(obj, ch)
- VALUE obj;
- VALUE ch;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- waddch(winp->window, NUM2CH(ch));
-
- return Qnil;
-}
-
-/* def insch(ch) */
-static VALUE
-window_insch(obj, ch)
- VALUE obj;
- VALUE ch;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- winsch(winp->window, NUM2CH(ch));
-
- return Qnil;
-}
-
-/* def addstr(str) */
-static VALUE
-window_addstr(obj, str)
- VALUE obj;
- VALUE str;
-{
- if (!NIL_P(str)) {
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- waddstr(winp->window, STR2CSTR(str));
- }
- return Qnil;
-}
-
-/* def <<(str) */
-static VALUE
-window_addstr2(obj, str)
- VALUE obj;
- VALUE str;
-{
- window_addstr(obj, str);
- return obj;
-}
-
-/* def getch */
-static VALUE
-window_getch(obj)
- VALUE obj;
-{
- struct windata *winp;
-
- rb_read_check(stdin);
- GetWINDOW(obj, winp);
- return UINT2NUM(wgetch(winp->window));
-}
-
-/* def getstr */
-static VALUE
-window_getstr(obj)
- VALUE obj;
-{
- struct windata *winp;
- char rtn[1024]; /* This should be big enough.. I hope */
-
- GetWINDOW(obj, winp);
- rb_read_check(stdin);
-#if defined(HAVE_WGETNSTR)
- wgetnstr(winp->window, rtn, 1023);
-#else
- wgetstr(winp->window, rtn);
-#endif
- return rb_tainted_str_new2(rtn);
-}
-
-/* def delch */
-static VALUE
-window_delch(obj)
- VALUE obj;
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- wdelch(winp->window);
- return Qnil;
-}
-
-/* def delelteln */
-static VALUE
-window_deleteln(obj)
- VALUE obj;
-{
-#if defined(HAVE_WDELETELN) || defined(wdeleteln)
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- wdeleteln(winp->window);
-#endif
- return Qnil;
-}
-
-/* def insertln */
-static VALUE
-window_insertln(obj)
- VALUE obj;
-{
-#if defined(HAVE_WINSERTLN) || defined(winsertln)
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- winsertln(winp->window);
-#endif
- return Qnil;
-}
-
-static VALUE
-window_scrollok(VALUE obj, VALUE bf)
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- scrollok(winp->window, RTEST(bf) ? TRUE : FALSE);
- return Qnil;
-}
-
-static VALUE
-window_idlok(VALUE obj, VALUE bf)
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- idlok(winp->window, RTEST(bf) ? TRUE : FALSE);
- return Qnil;
-}
-
-static VALUE
-window_setscrreg(VALUE obj, VALUE top, VALUE bottom)
-{
-#ifdef HAVE_WSETSCRREG
- struct windata *winp;
- int res;
-
- GetWINDOW(obj, winp);
- res = wsetscrreg(winp->window, NUM2INT(top), NUM2INT(bottom));
- /* may have to raise exception on ERR */
- return (res == OK) ? Qtrue : Qfalse;
-#else
- return Qfalse;
-#endif
-}
-
-#if defined(USE_COLOR) && defined(HAVE_WCOLOR_SET)
-static VALUE
-window_color_set(VALUE obj, VALUE col)
-{
- struct windata *winp;
- int res;
-
- GetWINDOW(obj, winp);
- res = wcolor_set(winp->window, NUM2INT(col), NULL);
- return (res == OK) ? Qtrue : Qfalse;
- return Qfalse;
-}
-#endif /* USE_COLOR */
-
-static VALUE
-window_scroll(VALUE obj)
-{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- /* may have to raise exception on ERR */
- return (scroll(winp->window) == OK) ? Qtrue : Qfalse;
-}
-
-static VALUE
-window_scrl(VALUE obj, VALUE n)
-{
-#ifdef HAVE_WSCRL
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- /* may have to raise exception on ERR */
- return (wscrl(winp->window,NUM2INT(n)) == OK) ? Qtrue : Qfalse;
-#else
- return Qfalse;
-#endif
-}
-
-static VALUE
-window_attroff(VALUE obj, VALUE attrs)
-{
-#ifdef HAVE_WATTROFF
- struct windata *winp;
-
- GetWINDOW(obj,winp);
- return INT2FIX(wattroff(winp->window,NUM2INT(attrs)));
-#else
- return Qtrue;
-#endif
-}
-
-static VALUE
-window_attron(VALUE obj, VALUE attrs)
-{
-#ifdef HAVE_WATTRON
- struct windata *winp;
- VALUE val;
-
- GetWINDOW(obj,winp);
- val = INT2FIX(wattron(winp->window,NUM2INT(attrs)));
- if( rb_block_given_p() ){
- rb_yield(val);
- wattroff(winp->window,NUM2INT(attrs));
- return val;
- }
- else{
- return val;
- }
-#else
- return Qtrue;
-#endif
-}
-
-static VALUE
-window_attrset(VALUE obj, VALUE attrs)
-{
-#ifdef HAVE_WATTRSET
- struct windata *winp;
-
- GetWINDOW(obj,winp);
- return INT2FIX(wattrset(winp->window,NUM2INT(attrs)));
-#else
- return Qtrue;
-#endif
-}
-
-static VALUE
-window_bkgdset(VALUE obj, VALUE ch)
-{
-#ifdef HAVE_WBKGDSET
- struct windata *winp;
-
- GetWINDOW(obj,winp);
- wbkgdset(winp->window, NUM2CH(ch));
-#endif
- return Qnil;
-}
-
-static VALUE
-window_bkgd(VALUE obj, VALUE ch)
-{
-#ifdef HAVE_WBKGD
- struct windata *winp;
-
- GetWINDOW(obj,winp);
- return (wbkgd(winp->window, NUM2CH(ch)) == OK) ? Qtrue : Qfalse;
-#else
- return Qfalse;
-#endif
-}
-
-static VALUE
-window_getbkgd(VALUE obj)
-{
-#ifdef HAVE_WGETBKGD
- chtype c;
- struct windata *winp;
-
- GetWINDOW(obj,winp);
- return (c = getbkgd(winp->window) != ERR) ? CH2FIX(c) : Qnil;
-#else
- return Qnil;
-#endif
-}
-
-static VALUE
-window_resize(VALUE obj, VALUE lin, VALUE col)
-{
-#if defined(HAVE_WRESIZE)
- struct windata *winp;
-
- GetWINDOW(obj,winp);
- return wresize(winp->window, NUM2INT(lin), NUM2INT(col)) == OK ? Qtrue : Qfalse;
-#else
- return Qnil;
-#endif
-}
-
-
-static VALUE
-window_keypad(VALUE obj, VALUE val)
-{
-#ifdef HAVE_KEYPAD
- struct windata *winp;
-
- GetWINDOW(obj,winp);
- /* keypad() of NetBSD's libcurses returns no value */
-#if defined(__NetBSD__) && !defined(NCURSES_VERSION)
- keypad(winp->window,(RTEST(val) ? TRUE : FALSE));
- return Qnil;
-#else
- /* may have to raise exception on ERR */
- return (keypad(winp->window,RTEST(val) ? TRUE : FALSE)) == OK ?
- Qtrue : Qfalse;
-#endif
-#else
- rb_notimplement();
-#endif /* HAVE_KEYPAD */
-}
-
-static VALUE
-window_nodelay(VALUE obj, VALUE val)
-{
-#ifdef HAVE_NODELAY
- struct windata *winp;
- GetWINDOW(obj,winp);
-
- /* nodelay() of NetBSD's libcurses returns no value */
-#if defined(__NetBSD__) && !defined(NCURSES_VERSION)
- nodelay(winp->window, RTEST(val) ? TRUE : FALSE);
- return Qnil;
-#else
- return nodelay(winp->window,RTEST(val) ? TRUE : FALSE) == OK ? Qtrue : Qfalse;
-#endif
-#else
- rb_notimplement();
-#endif
-}
-
-static VALUE
-window_timeout(VALUE obj, VALUE delay)
-{
-#ifdef HAVE_WTIMEOUT
- struct windata *winp;
- GetWINDOW(obj,winp);
-
- wtimeout(winp->window,NUM2INT(delay));
- return Qnil;
-#else
- rb_notimplement();
-#endif
-}
-
-/*------------------------- Initialization -------------------------*/
-void
-Init_curses()
-{
- mCurses = rb_define_module("Curses");
- mKey = rb_define_module_under(mCurses, "Key");
-
- rb_gc_register_address(&rb_stdscr);
-
-#ifdef USE_MOUSE
- cMouseEvent = rb_define_class_under(mCurses,"MouseEvent",rb_cObject);
- rb_undef_method(CLASS_OF(cMouseEvent),"new");
- rb_define_method(cMouseEvent, "eid", curs_mouse_id, 0);
- rb_define_method(cMouseEvent, "x", curs_mouse_x, 0);
- rb_define_method(cMouseEvent, "y", curs_mouse_y, 0);
- rb_define_method(cMouseEvent, "z", curs_mouse_z, 0);
- rb_define_method(cMouseEvent, "bstate", curs_mouse_bstate, 0);
-#endif /* USE_MOUSE */
-
- rb_define_module_function(mCurses, "init_screen", curses_init_screen, 0);
- rb_define_module_function(mCurses, "close_screen", curses_close_screen, 0);
- rb_define_module_function(mCurses, "closed?", curses_closed, 0);
- rb_define_module_function(mCurses, "stdscr", curses_stdscr, 0);
- rb_define_module_function(mCurses, "refresh", curses_refresh, 0);
- rb_define_module_function(mCurses, "doupdate", curses_doupdate, 0);
- rb_define_module_function(mCurses, "clear", curses_clear, 0);
- rb_define_module_function(mCurses, "clrtoeol", curses_clrtoeol, 0);
- rb_define_module_function(mCurses, "echo", curses_echo, 0);
- rb_define_module_function(mCurses, "noecho", curses_noecho, 0);
- rb_define_module_function(mCurses, "raw", curses_raw, 0);
- rb_define_module_function(mCurses, "noraw", curses_noraw, 0);
- rb_define_module_function(mCurses, "cbreak", curses_cbreak, 0);
- rb_define_module_function(mCurses, "nocbreak", curses_nocbreak, 0);
- rb_define_alias(mCurses, "crmode", "cbreak");
- rb_define_alias(mCurses, "nocrmode", "nocbreak");
- rb_define_module_function(mCurses, "nl", curses_nl, 0);
- rb_define_module_function(mCurses, "nonl", curses_nonl, 0);
- rb_define_module_function(mCurses, "beep", curses_beep, 0);
- rb_define_module_function(mCurses, "flash", curses_flash, 0);
- rb_define_module_function(mCurses, "ungetch", curses_ungetch, 1);
- rb_define_module_function(mCurses, "setpos", curses_setpos, 2);
- rb_define_module_function(mCurses, "standout", curses_standout, 0);
- rb_define_module_function(mCurses, "standend", curses_standend, 0);
- rb_define_module_function(mCurses, "inch", curses_inch, 0);
- rb_define_module_function(mCurses, "addch", curses_addch, 1);
- rb_define_module_function(mCurses, "insch", curses_insch, 1);
- rb_define_module_function(mCurses, "addstr", curses_addstr, 1);
- rb_define_module_function(mCurses, "getch", curses_getch, 0);
- rb_define_module_function(mCurses, "getstr", curses_getstr, 0);
- rb_define_module_function(mCurses, "delch", curses_delch, 0);
- rb_define_module_function(mCurses, "deleteln", curses_deleteln, 0);
- rb_define_module_function(mCurses, "insertln", curses_insertln, 0);
- rb_define_module_function(mCurses, "keyname", curses_keyname, 1);
- rb_define_module_function(mCurses, "lines", curses_lines, 0);
- rb_define_module_function(mCurses, "cols", curses_cols, 0);
- rb_define_module_function(mCurses, "curs_set", curses_curs_set, 1);
- rb_define_module_function(mCurses, "scrl", curses_scrl, 1);
- rb_define_module_function(mCurses, "setscrreg", curses_setscrreg, 2);
- rb_define_module_function(mCurses, "attroff", curses_attroff, 1);
- rb_define_module_function(mCurses, "attron", curses_attron, 1);
- rb_define_module_function(mCurses, "attrset", curses_attrset, 1);
- rb_define_module_function(mCurses, "bkgdset", curses_bkgdset, 1);
- rb_define_module_function(mCurses, "bkgd", curses_bkgd, 1);
- rb_define_module_function(mCurses, "resizeterm", curses_resizeterm, 2);
- rb_define_module_function(mCurses, "resize", curses_resizeterm, 2);
-#ifdef USE_COLOR
- rb_define_module_function(mCurses, "start_color", curses_start_color, 0);
- rb_define_module_function(mCurses, "init_pair", curses_init_pair, 3);
- rb_define_module_function(mCurses, "init_color", curses_init_color, 4);
- rb_define_module_function(mCurses, "has_colors?", curses_has_colors, 0);
- rb_define_module_function(mCurses, "can_change_color?",
- curses_can_change_color, 0);
- rb_define_module_function(mCurses, "color_content", curses_color_content, 1);
- rb_define_module_function(mCurses, "pair_content", curses_pair_content, 1);
- rb_define_module_function(mCurses, "color_pair", curses_color_pair, 1);
- rb_define_module_function(mCurses, "pair_number", curses_pair_number, 1);
-#endif /* USE_COLOR */
-#ifdef USE_MOUSE
- rb_define_module_function(mCurses, "getmouse", curses_getmouse, 0);
- rb_define_module_function(mCurses, "ungetmouse", curses_ungetmouse, 1);
- rb_define_module_function(mCurses, "mouseinterval", curses_mouseinterval, 1);
- rb_define_module_function(mCurses, "mousemask", curses_mousemask, 1);
-#endif /* USE_MOUSE */
-
- rb_define_module_function(mCurses, "timeout=", curses_timeout, 1);
- rb_define_module_function(mCurses, "def_prog_mode", curses_def_prog_mode, 0);
- rb_define_module_function(mCurses, "reset_prog_mode", curses_reset_prog_mode, 0);
-
- cWindow = rb_define_class_under(mCurses, "Window", rb_cData);
- rb_define_alloc_func(cWindow, window_s_allocate);
- rb_define_method(cWindow, "initialize", window_initialize, 4);
- rb_define_method(cWindow, "subwin", window_subwin, 4);
- rb_define_method(cWindow, "close", window_close, 0);
- rb_define_method(cWindow, "clear", window_clear, 0);
- rb_define_method(cWindow, "clrtoeol", window_clrtoeol, 0);
- rb_define_method(cWindow, "refresh", window_refresh, 0);
- rb_define_method(cWindow, "noutrefresh", window_noutrefresh, 0);
- rb_define_method(cWindow, "box", window_box, -1);
- rb_define_method(cWindow, "move", window_move, 2);
- rb_define_method(cWindow, "setpos", window_setpos, 2);
-#if defined(USE_COLOR) && defined(HAVE_WCOLOR_SET)
- rb_define_method(cWindow, "color_set", window_color_set, 1);
-#endif /* USE_COLOR && HAVE_WCOLOR_SET */
- rb_define_method(cWindow, "cury", window_cury, 0);
- rb_define_method(cWindow, "curx", window_curx, 0);
- rb_define_method(cWindow, "maxy", window_maxy, 0);
- rb_define_method(cWindow, "maxx", window_maxx, 0);
- rb_define_method(cWindow, "begy", window_begy, 0);
- rb_define_method(cWindow, "begx", window_begx, 0);
- rb_define_method(cWindow, "standout", window_standout, 0);
- rb_define_method(cWindow, "standend", window_standend, 0);
- rb_define_method(cWindow, "inch", window_inch, 0);
- rb_define_method(cWindow, "addch", window_addch, 1);
- rb_define_method(cWindow, "insch", window_insch, 1);
- rb_define_method(cWindow, "addstr", window_addstr, 1);
- rb_define_method(cWindow, "<<", window_addstr2, 1);
- rb_define_method(cWindow, "getch", window_getch, 0);
- rb_define_method(cWindow, "getstr", window_getstr, 0);
- rb_define_method(cWindow, "delch", window_delch, 0);
- rb_define_method(cWindow, "deleteln", window_deleteln, 0);
- rb_define_method(cWindow, "insertln", window_insertln, 0);
- rb_define_method(cWindow, "scroll", window_scroll, 0);
- rb_define_method(cWindow, "scrollok", window_scrollok, 1);
- rb_define_method(cWindow, "idlok", window_idlok, 1);
- rb_define_method(cWindow, "setscrreg", window_setscrreg, 2);
- rb_define_method(cWindow, "scrl", window_scrl, 1);
- rb_define_method(cWindow, "resize", window_resize, 2);
- rb_define_method(cWindow, "keypad", window_keypad, 1);
- rb_define_method(cWindow, "keypad=", window_keypad, 1);
-
- rb_define_method(cWindow, "attroff", window_attroff, 1);
- rb_define_method(cWindow, "attron", window_attron, 1);
- rb_define_method(cWindow, "attrset", window_attrset, 1);
- rb_define_method(cWindow, "bkgdset", window_bkgdset, 1);
- rb_define_method(cWindow, "bkgd", window_bkgd, 1);
- rb_define_method(cWindow, "getbkgd", window_getbkgd, 0);
-
- rb_define_method(cWindow, "nodelay=", window_nodelay, 1);
- rb_define_method(cWindow, "timeout=", window_timeout, 1);
-
-#define rb_curses_define_const(c) rb_define_const(mCurses,#c,UINT2NUM(c))
-
-#ifdef USE_COLOR
- rb_curses_define_const(A_ATTRIBUTES);
-#ifdef A_NORMAL
- rb_curses_define_const(A_NORMAL);
-#endif
- rb_curses_define_const(A_STANDOUT);
- rb_curses_define_const(A_UNDERLINE);
- rb_curses_define_const(A_REVERSE);
- rb_curses_define_const(A_BLINK);
- rb_curses_define_const(A_DIM);
- rb_curses_define_const(A_BOLD);
- rb_curses_define_const(A_PROTECT);
-#ifdef A_INVIS /* for NetBSD */
- rb_curses_define_const(A_INVIS);
-#endif
- rb_curses_define_const(A_ALTCHARSET);
- rb_curses_define_const(A_CHARTEXT);
-#ifdef A_HORIZONTAL
- rb_curses_define_const(A_HORIZONTAL);
-#endif
-#ifdef A_LEFT
- rb_curses_define_const(A_LEFT);
-#endif
-#ifdef A_LOW
- rb_curses_define_const(A_LOW);
-#endif
-#ifdef A_RIGHT
- rb_curses_define_const(A_RIGHT);
-#endif
-#ifdef A_TOP
- rb_curses_define_const(A_TOP);
-#endif
-#ifdef A_VERTICAL
- rb_curses_define_const(A_VERTICAL);
-#endif
- rb_curses_define_const(A_COLOR);
-
-#ifdef COLORS
- rb_curses_define_const(COLORS);
-#endif
- rb_curses_define_const(COLOR_BLACK);
- rb_curses_define_const(COLOR_RED);
- rb_curses_define_const(COLOR_GREEN);
- rb_curses_define_const(COLOR_YELLOW);
- rb_curses_define_const(COLOR_BLUE);
- rb_curses_define_const(COLOR_MAGENTA);
- rb_curses_define_const(COLOR_CYAN);
- rb_curses_define_const(COLOR_WHITE);
-#endif /* USE_COLOR */
-#ifdef USE_MOUSE
-#ifdef BUTTON1_PRESSED
- rb_curses_define_const(BUTTON1_PRESSED);
-#endif
-#ifdef BUTTON1_RELEASED
- rb_curses_define_const(BUTTON1_RELEASED);
-#endif
-#ifdef BUTTON1_CLICKED
- rb_curses_define_const(BUTTON1_CLICKED);
-#endif
-#ifdef BUTTON1_DOUBLE_CLICKED
- rb_curses_define_const(BUTTON1_DOUBLE_CLICKED);
-#endif
-#ifdef BUTTON1_TRIPLE_CLICKED
- rb_curses_define_const(BUTTON1_TRIPLE_CLICKED);
-#endif
-#ifdef BUTTON2_PRESSED
- rb_curses_define_const(BUTTON2_PRESSED);
-#endif
-#ifdef BUTTON2_RELEASED
- rb_curses_define_const(BUTTON2_RELEASED);
-#endif
-#ifdef BUTTON2_CLICKED
- rb_curses_define_const(BUTTON2_CLICKED);
-#endif
-#ifdef BUTTON2_DOUBLE_CLICKED
- rb_curses_define_const(BUTTON2_DOUBLE_CLICKED);
-#endif
-#ifdef BUTTON2_TRIPLE_CLICKED
- rb_curses_define_const(BUTTON2_TRIPLE_CLICKED);
-#endif
-#ifdef BUTTON3_PRESSED
- rb_curses_define_const(BUTTON3_PRESSED);
-#endif
-#ifdef BUTTON3_RELEASED
- rb_curses_define_const(BUTTON3_RELEASED);
-#endif
-#ifdef BUTTON3_CLICKED
- rb_curses_define_const(BUTTON3_CLICKED);
-#endif
-#ifdef BUTTON3_DOUBLE_CLICKED
- rb_curses_define_const(BUTTON3_DOUBLE_CLICKED);
-#endif
-#ifdef BUTTON3_TRIPLE_CLICKED
- rb_curses_define_const(BUTTON3_TRIPLE_CLICKED);
-#endif
-#ifdef BUTTON4_PRESSED
- rb_curses_define_const(BUTTON4_PRESSED);
-#endif
-#ifdef BUTTON4_RELEASED
- rb_curses_define_const(BUTTON4_RELEASED);
-#endif
-#ifdef BUTTON4_CLICKED
- rb_curses_define_const(BUTTON4_CLICKED);
-#endif
-#ifdef BUTTON4_DOUBLE_CLICKED
- rb_curses_define_const(BUTTON4_DOUBLE_CLICKED);
-#endif
-#ifdef BUTTON4_TRIPLE_CLICKED
- rb_curses_define_const(BUTTON4_TRIPLE_CLICKED);
-#endif
-#ifdef BUTTON_SHIFT
- rb_curses_define_const(BUTTON_SHIFT);
-#endif
-#ifdef BUTTON_CTRL
- rb_curses_define_const(BUTTON_CTRL);
-#endif
-#ifdef BUTTON_ALT
- rb_curses_define_const(BUTTON_ALT);
-#endif
-#ifdef ALL_MOUSE_EVENTS
- rb_curses_define_const(ALL_MOUSE_EVENTS);
-#endif
-#ifdef REPORT_MOUSE_POSITION
- rb_curses_define_const(REPORT_MOUSE_POSITION);
-#endif
-#endif /* USE_MOUSE */
-
-#if defined(KEY_MOUSE) && defined(USE_MOUSE)
- rb_curses_define_const(KEY_MOUSE);
- rb_define_const(mKey, "MOUSE", INT2NUM(KEY_MOUSE));
-#endif
-#ifdef KEY_MIN
- rb_curses_define_const(KEY_MIN);
- rb_define_const(mKey, "MIN", INT2NUM(KEY_MIN));
-#endif
-#ifdef KEY_BREAK
- rb_curses_define_const(KEY_BREAK);
- rb_define_const(mKey, "BREAK", INT2NUM(KEY_BREAK));
-#endif
-#ifdef KEY_DOWN
- rb_curses_define_const(KEY_DOWN);
- rb_define_const(mKey, "DOWN", INT2NUM(KEY_DOWN));
-#endif
-#ifdef KEY_UP
- rb_curses_define_const(KEY_UP);
- rb_define_const(mKey, "UP", INT2NUM(KEY_UP));
-#endif
-#ifdef KEY_LEFT
- rb_curses_define_const(KEY_LEFT);
- rb_define_const(mKey, "LEFT", INT2NUM(KEY_LEFT));
-#endif
-#ifdef KEY_RIGHT
- rb_curses_define_const(KEY_RIGHT);
- rb_define_const(mKey, "RIGHT", INT2NUM(KEY_RIGHT));
-#endif
-#ifdef KEY_HOME
- rb_curses_define_const(KEY_HOME);
- rb_define_const(mKey, "HOME", INT2NUM(KEY_HOME));
-#endif
-#ifdef KEY_BACKSPACE
- rb_curses_define_const(KEY_BACKSPACE);
- rb_define_const(mKey, "BACKSPACE", INT2NUM(KEY_BACKSPACE));
-#endif
-#ifdef KEY_F
- /* KEY_F(n) : 0 <= n <= 63 */
- {
- int i;
- char c[8];
- for( i=0; i<64; i++ ){
- sprintf(c, "KEY_F%d", i);
- rb_define_const(mCurses, c, INT2NUM(KEY_F(i)));
- sprintf(c, "F%d", i);
- rb_define_const(mKey, c, INT2NUM(KEY_F(i)));
- }
- }
-#endif
-#ifdef KEY_DL
- rb_curses_define_const(KEY_DL);
- rb_define_const(mKey, "DL", INT2NUM(KEY_DL));
-#endif
-#ifdef KEY_IL
- rb_curses_define_const(KEY_IL);
- rb_define_const(mKey, "IL", INT2NUM(KEY_IL));
-#endif
-#ifdef KEY_DC
- rb_curses_define_const(KEY_DC);
- rb_define_const(mKey, "DC", INT2NUM(KEY_DC));
-#endif
-#ifdef KEY_IC
- rb_curses_define_const(KEY_IC);
- rb_define_const(mKey, "IC", INT2NUM(KEY_IC));
-#endif
-#ifdef KEY_EIC
- rb_curses_define_const(KEY_EIC);
- rb_define_const(mKey, "EIC", INT2NUM(KEY_EIC));
-#endif
-#ifdef KEY_CLEAR
- rb_curses_define_const(KEY_CLEAR);
- rb_define_const(mKey, "CLEAR", INT2NUM(KEY_CLEAR));
-#endif
-#ifdef KEY_EOS
- rb_curses_define_const(KEY_EOS);
- rb_define_const(mKey, "EOS", INT2NUM(KEY_EOS));
-#endif
-#ifdef KEY_EOL
- rb_curses_define_const(KEY_EOL);
- rb_define_const(mKey, "EOL", INT2NUM(KEY_EOL));
-#endif
-#ifdef KEY_SF
- rb_curses_define_const(KEY_SF);
- rb_define_const(mKey, "SF", INT2NUM(KEY_SF));
-#endif
-#ifdef KEY_SR
- rb_curses_define_const(KEY_SR);
- rb_define_const(mKey, "SR", INT2NUM(KEY_SR));
-#endif
-#ifdef KEY_NPAGE
- rb_curses_define_const(KEY_NPAGE);
- rb_define_const(mKey, "NPAGE", INT2NUM(KEY_NPAGE));
-#endif
-#ifdef KEY_PPAGE
- rb_curses_define_const(KEY_PPAGE);
- rb_define_const(mKey, "PPAGE", INT2NUM(KEY_PPAGE));
-#endif
-#ifdef KEY_STAB
- rb_curses_define_const(KEY_STAB);
- rb_define_const(mKey, "STAB", INT2NUM(KEY_STAB));
-#endif
-#ifdef KEY_CTAB
- rb_curses_define_const(KEY_CTAB);
- rb_define_const(mKey, "CTAB", INT2NUM(KEY_CTAB));
-#endif
-#ifdef KEY_CATAB
- rb_curses_define_const(KEY_CATAB);
- rb_define_const(mKey, "CATAB", INT2NUM(KEY_CATAB));
-#endif
-#ifdef KEY_ENTER
- rb_curses_define_const(KEY_ENTER);
- rb_define_const(mKey, "ENTER", INT2NUM(KEY_ENTER));
-#endif
-#ifdef KEY_SRESET
- rb_curses_define_const(KEY_SRESET);
- rb_define_const(mKey, "SRESET", INT2NUM(KEY_SRESET));
-#endif
-#ifdef KEY_RESET
- rb_curses_define_const(KEY_RESET);
- rb_define_const(mKey, "RESET", INT2NUM(KEY_RESET));
-#endif
-#ifdef KEY_PRINT
- rb_curses_define_const(KEY_PRINT);
- rb_define_const(mKey, "PRINT", INT2NUM(KEY_PRINT));
-#endif
-#ifdef KEY_LL
- rb_curses_define_const(KEY_LL);
- rb_define_const(mKey, "LL", INT2NUM(KEY_LL));
-#endif
-#ifdef KEY_A1
- rb_curses_define_const(KEY_A1);
- rb_define_const(mKey, "A1", INT2NUM(KEY_A1));
-#endif
-#ifdef KEY_A3
- rb_curses_define_const(KEY_A3);
- rb_define_const(mKey, "A3", INT2NUM(KEY_A3));
-#endif
-#ifdef KEY_B2
- rb_curses_define_const(KEY_B2);
- rb_define_const(mKey, "B2", INT2NUM(KEY_B2));
-#endif
-#ifdef KEY_C1
- rb_curses_define_const(KEY_C1);
- rb_define_const(mKey, "C1", INT2NUM(KEY_C1));
-#endif
-#ifdef KEY_C3
- rb_curses_define_const(KEY_C3);
- rb_define_const(mKey, "C3", INT2NUM(KEY_C3));
-#endif
-#ifdef KEY_BTAB
- rb_curses_define_const(KEY_BTAB);
- rb_define_const(mKey, "BTAB", INT2NUM(KEY_BTAB));
-#endif
-#ifdef KEY_BEG
- rb_curses_define_const(KEY_BEG);
- rb_define_const(mKey, "BEG", INT2NUM(KEY_BEG));
-#endif
-#ifdef KEY_CANCEL
- rb_curses_define_const(KEY_CANCEL);
- rb_define_const(mKey, "CANCEL", INT2NUM(KEY_CANCEL));
-#endif
-#ifdef KEY_CLOSE
- rb_curses_define_const(KEY_CLOSE);
- rb_define_const(mKey, "CLOSE", INT2NUM(KEY_CLOSE));
-#endif
-#ifdef KEY_COMMAND
- rb_curses_define_const(KEY_COMMAND);
- rb_define_const(mKey, "COMMAND", INT2NUM(KEY_COMMAND));
-#endif
-#ifdef KEY_COPY
- rb_curses_define_const(KEY_COPY);
- rb_define_const(mKey, "COPY", INT2NUM(KEY_COPY));
-#endif
-#ifdef KEY_CREATE
- rb_curses_define_const(KEY_CREATE);
- rb_define_const(mKey, "CREATE", INT2NUM(KEY_CREATE));
-#endif
-#ifdef KEY_END
- rb_curses_define_const(KEY_END);
- rb_define_const(mKey, "END", INT2NUM(KEY_END));
-#endif
-#ifdef KEY_EXIT
- rb_curses_define_const(KEY_EXIT);
- rb_define_const(mKey, "EXIT", INT2NUM(KEY_EXIT));
-#endif
-#ifdef KEY_FIND
- rb_curses_define_const(KEY_FIND);
- rb_define_const(mKey, "FIND", INT2NUM(KEY_FIND));
-#endif
-#ifdef KEY_HELP
- rb_curses_define_const(KEY_HELP);
- rb_define_const(mKey, "HELP", INT2NUM(KEY_HELP));
-#endif
-#ifdef KEY_MARK
- rb_curses_define_const(KEY_MARK);
- rb_define_const(mKey, "MARK", INT2NUM(KEY_MARK));
-#endif
-#ifdef KEY_MESSAGE
- rb_curses_define_const(KEY_MESSAGE);
- rb_define_const(mKey, "MESSAGE", INT2NUM(KEY_MESSAGE));
-#endif
-#ifdef KEY_MOVE
- rb_curses_define_const(KEY_MOVE);
- rb_define_const(mKey, "MOVE", INT2NUM(KEY_MOVE));
-#endif
-#ifdef KEY_NEXT
- rb_curses_define_const(KEY_NEXT);
- rb_define_const(mKey, "NEXT", INT2NUM(KEY_NEXT));
-#endif
-#ifdef KEY_OPEN
- rb_curses_define_const(KEY_OPEN);
- rb_define_const(mKey, "OPEN", INT2NUM(KEY_OPEN));
-#endif
-#ifdef KEY_OPTIONS
- rb_curses_define_const(KEY_OPTIONS);
- rb_define_const(mKey, "OPTIONS", INT2NUM(KEY_OPTIONS));
-#endif
-#ifdef KEY_PREVIOUS
- rb_curses_define_const(KEY_PREVIOUS);
- rb_define_const(mKey, "PREVIOUS", INT2NUM(KEY_PREVIOUS));
-#endif
-#ifdef KEY_REDO
- rb_curses_define_const(KEY_REDO);
- rb_define_const(mKey, "REDO", INT2NUM(KEY_REDO));
-#endif
-#ifdef KEY_REFERENCE
- rb_curses_define_const(KEY_REFERENCE);
- rb_define_const(mKey, "REFERENCE", INT2NUM(KEY_REFERENCE));
-#endif
-#ifdef KEY_REFRESH
- rb_curses_define_const(KEY_REFRESH);
- rb_define_const(mKey, "REFRESH", INT2NUM(KEY_REFRESH));
-#endif
-#ifdef KEY_REPLACE
- rb_curses_define_const(KEY_REPLACE);
- rb_define_const(mKey, "REPLACE", INT2NUM(KEY_REPLACE));
-#endif
-#ifdef KEY_RESTART
- rb_curses_define_const(KEY_RESTART);
- rb_define_const(mKey, "RESTART", INT2NUM(KEY_RESTART));
-#endif
-#ifdef KEY_RESUME
- rb_curses_define_const(KEY_RESUME);
- rb_define_const(mKey, "RESUME", INT2NUM(KEY_RESUME));
-#endif
-#ifdef KEY_SAVE
- rb_curses_define_const(KEY_SAVE);
- rb_define_const(mKey, "SAVE", INT2NUM(KEY_SAVE));
-#endif
-#ifdef KEY_SBEG
- rb_curses_define_const(KEY_SBEG);
- rb_define_const(mKey, "SBEG", INT2NUM(KEY_SBEG));
-#endif
-#ifdef KEY_SCANCEL
- rb_curses_define_const(KEY_SCANCEL);
- rb_define_const(mKey, "SCANCEL", INT2NUM(KEY_SCANCEL));
-#endif
-#ifdef KEY_SCOMMAND
- rb_curses_define_const(KEY_SCOMMAND);
- rb_define_const(mKey, "SCOMMAND", INT2NUM(KEY_SCOMMAND));
-#endif
-#ifdef KEY_SCOPY
- rb_curses_define_const(KEY_SCOPY);
- rb_define_const(mKey, "SCOPY", INT2NUM(KEY_SCOPY));
-#endif
-#ifdef KEY_SCREATE
- rb_curses_define_const(KEY_SCREATE);
- rb_define_const(mKey, "SCREATE", INT2NUM(KEY_SCREATE));
-#endif
-#ifdef KEY_SDC
- rb_curses_define_const(KEY_SDC);
- rb_define_const(mKey, "SDC", INT2NUM(KEY_SDC));
-#endif
-#ifdef KEY_SDL
- rb_curses_define_const(KEY_SDL);
- rb_define_const(mKey, "SDL", INT2NUM(KEY_SDL));
-#endif
-#ifdef KEY_SELECT
- rb_curses_define_const(KEY_SELECT);
- rb_define_const(mKey, "SELECT", INT2NUM(KEY_SELECT));
-#endif
-#ifdef KEY_SEND
- rb_curses_define_const(KEY_SEND);
- rb_define_const(mKey, "SEND", INT2NUM(KEY_SEND));
-#endif
-#ifdef KEY_SEOL
- rb_curses_define_const(KEY_SEOL);
- rb_define_const(mKey, "SEOL", INT2NUM(KEY_SEOL));
-#endif
-#ifdef KEY_SEXIT
- rb_curses_define_const(KEY_SEXIT);
- rb_define_const(mKey, "SEXIT", INT2NUM(KEY_SEXIT));
-#endif
-#ifdef KEY_SFIND
- rb_curses_define_const(KEY_SFIND);
- rb_define_const(mKey, "SFIND", INT2NUM(KEY_SFIND));
-#endif
-#ifdef KEY_SHELP
- rb_curses_define_const(KEY_SHELP);
- rb_define_const(mKey, "SHELP", INT2NUM(KEY_SHELP));
-#endif
-#ifdef KEY_SHOME
- rb_curses_define_const(KEY_SHOME);
- rb_define_const(mKey, "SHOME", INT2NUM(KEY_SHOME));
-#endif
-#ifdef KEY_SIC
- rb_curses_define_const(KEY_SIC);
- rb_define_const(mKey, "SIC", INT2NUM(KEY_SIC));
-#endif
-#ifdef KEY_SLEFT
- rb_curses_define_const(KEY_SLEFT);
- rb_define_const(mKey, "SLEFT", INT2NUM(KEY_SLEFT));
-#endif
-#ifdef KEY_SMESSAGE
- rb_curses_define_const(KEY_SMESSAGE);
- rb_define_const(mKey, "SMESSAGE", INT2NUM(KEY_SMESSAGE));
-#endif
-#ifdef KEY_SMOVE
- rb_curses_define_const(KEY_SMOVE);
- rb_define_const(mKey, "SMOVE", INT2NUM(KEY_SMOVE));
-#endif
-#ifdef KEY_SNEXT
- rb_curses_define_const(KEY_SNEXT);
- rb_define_const(mKey, "SNEXT", INT2NUM(KEY_SNEXT));
-#endif
-#ifdef KEY_SOPTIONS
- rb_curses_define_const(KEY_SOPTIONS);
- rb_define_const(mKey, "SOPTIONS", INT2NUM(KEY_SOPTIONS));
-#endif
-#ifdef KEY_SPREVIOUS
- rb_curses_define_const(KEY_SPREVIOUS);
- rb_define_const(mKey, "SPREVIOUS", INT2NUM(KEY_SPREVIOUS));
-#endif
-#ifdef KEY_SPRINT
- rb_curses_define_const(KEY_SPRINT);
- rb_define_const(mKey, "SPRINT", INT2NUM(KEY_SPRINT));
-#endif
-#ifdef KEY_SREDO
- rb_curses_define_const(KEY_SREDO);
- rb_define_const(mKey, "SREDO", INT2NUM(KEY_SREDO));
-#endif
-#ifdef KEY_SREPLACE
- rb_curses_define_const(KEY_SREPLACE);
- rb_define_const(mKey, "SREPLACE", INT2NUM(KEY_SREPLACE));
-#endif
-#ifdef KEY_SRIGHT
- rb_curses_define_const(KEY_SRIGHT);
- rb_define_const(mKey, "SRIGHT", INT2NUM(KEY_SRIGHT));
-#endif
-#ifdef KEY_SRSUME
- rb_curses_define_const(KEY_SRSUME);
- rb_define_const(mKey, "SRSUME", INT2NUM(KEY_SRSUME));
-#endif
-#ifdef KEY_SSAVE
- rb_curses_define_const(KEY_SSAVE);
- rb_define_const(mKey, "SSAVE", INT2NUM(KEY_SSAVE));
-#endif
-#ifdef KEY_SSUSPEND
- rb_curses_define_const(KEY_SSUSPEND);
- rb_define_const(mKey, "SSUSPEND", INT2NUM(KEY_SSUSPEND));
-#endif
-#ifdef KEY_SUNDO
- rb_curses_define_const(KEY_SUNDO);
- rb_define_const(mKey, "SUNDO", INT2NUM(KEY_SUNDO));
-#endif
-#ifdef KEY_SUSPEND
- rb_curses_define_const(KEY_SUSPEND);
- rb_define_const(mKey, "SUSPEND", INT2NUM(KEY_SUSPEND));
-#endif
-#ifdef KEY_UNDO
- rb_curses_define_const(KEY_UNDO);
- rb_define_const(mKey, "UNDO", INT2NUM(KEY_UNDO));
-#endif
-#ifdef KEY_RESIZE
- rb_curses_define_const(KEY_RESIZE);
- rb_define_const(mKey, "RESIZE", INT2NUM(KEY_RESIZE));
-#endif
-#ifdef KEY_MAX
- rb_curses_define_const(KEY_MAX);
- rb_define_const(mKey, "MAX", INT2NUM(KEY_MAX));
-#endif
- {
- int c;
- char name[] = "KEY_CTRL_x";
- for( c = 'A'; c <= 'Z'; c++ ){
- sprintf(name, "KEY_CTRL_%c", c);
- rb_define_const(mCurses, name, INT2FIX(c - 'A' + 1));
- }
- }
-#undef rb_curses_define_const
-
- rb_set_end_proc(curses_finalize, 0);
-}
diff --git a/ext/curses/depend b/ext/curses/depend
deleted file mode 100644
index ecb79e512d..0000000000
--- a/ext/curses/depend
+++ /dev/null
@@ -1 +0,0 @@
-curses.o: curses.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/curses/extconf.rb b/ext/curses/extconf.rb
deleted file mode 100644
index 01fe971093..0000000000
--- a/ext/curses/extconf.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require 'mkmf'
-
-dir_config('curses')
-dir_config('ncurses')
-dir_config('termcap')
-
-make=false
-have_library("mytinfo", "tgetent") if /bow/ =~ RUBY_PLATFORM
-have_library("tinfo", "tgetent") or have_library("termcap", "tgetent")
-if have_header(*curses=%w"ncurses.h") and have_library("ncurses", "initscr")
- make=true
-elsif have_header(*curses=%w"ncurses/curses.h") and have_library("ncurses", "initscr")
- make=true
-elsif have_header(*curses=%w"curses_colr/curses.h") and have_library("cur_colr", "initscr")
- curses.unshift("varargs.h")
- make=true
-elsif have_header(*curses=%w"curses.h") and have_library("curses", "initscr")
- make=true
-end
-
-if make
- for f in %w(beep bkgd bkgdset curs_set deleteln doupdate flash getbkgd getnstr init isendwin keyname keypad resizeterm scrl set setscrreg ungetch wattroff wattron wattrset wbkgd wbkgdset wdeleteln wgetnstr wresize wscrl wsetscrreg def_prog_mode reset_prog_mode timeout wtimeout nodelay init_color wcolor_set)
- have_func(f)
- end
- flag = "-D_XOPEN_SOURCE_EXTENDED"
- src = "int test_var[(sizeof(char*)>sizeof(int))*2-1];"
- if try_compile(cpp_include(%w[stdio.h stdlib.h]+curses)+src , flag)
- $defs << flag
- end
- create_makefile("curses")
-end
diff --git a/ext/curses/hello.rb b/ext/curses/hello.rb
deleted file mode 100644
index 7f57d801a3..0000000000
--- a/ext/curses/hello.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/local/bin/ruby
-
-require "curses"
-include Curses
-
-def show_message(message)
- width = message.length + 6
- win = Window.new(5, width,
- (lines - 5) / 2, (cols - width) / 2)
- win.box(?|, ?-)
- win.setpos(2, 3)
- win.addstr(message)
- win.refresh
- win.getch
- win.close
-end
-
-init_screen
-begin
- crmode
-# show_message("Hit any key")
- setpos((lines - 5) / 2, (cols - 10) / 2)
- addstr("Hit any key")
- refresh
- getch
- show_message("Hello, World!")
- refresh
-ensure
- close_screen
-end
diff --git a/ext/curses/mouse.rb b/ext/curses/mouse.rb
deleted file mode 100644
index c42bc31f33..0000000000
--- a/ext/curses/mouse.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/local/bin/ruby
-
-require "curses"
-include Curses
-
-def show_message(*msgs)
- message = msgs.join
- width = message.length + 6
- win = Window.new(5, width,
- (lines - 5) / 2, (cols - width) / 2)
- win.keypad = true
- win.attron(color_pair(COLOR_RED)){
- win.box(?|, ?-, ?+)
- }
- win.setpos(2, 3)
- win.addstr(message)
- win.refresh
- win.getch
- win.close
-end
-
-init_screen
-start_color
-init_pair(COLOR_BLUE,COLOR_BLUE,COLOR_WHITE)
-init_pair(COLOR_RED,COLOR_RED,COLOR_WHITE)
-crmode
-noecho
-stdscr.keypad(true)
-
-begin
- mousemask(BUTTON1_CLICKED|BUTTON2_CLICKED|BUTTON3_CLICKED|BUTTON4_CLICKED)
- setpos((lines - 5) / 2, (cols - 10) / 2)
- attron(color_pair(COLOR_BLUE)|A_BOLD){
- addstr("click")
- }
- refresh
- while( true )
- c = getch
- case c
- when KEY_MOUSE
- m = getmouse
- if( m )
- show_message("getch = #{c.inspect}, ",
- "mouse event = #{'0x%x' % m.bstate}, ",
- "axis = (#{m.x},#{m.y},#{m.z})")
- end
- break
- end
- end
- refresh
-ensure
- close_screen
-end
diff --git a/ext/curses/rain.rb b/ext/curses/rain.rb
deleted file mode 100644
index 36f0f84de2..0000000000
--- a/ext/curses/rain.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/local/bin/ruby
-# rain for a curses test
-
-require "curses"
-include Curses
-
-def onsig(sig)
- close_screen
- exit sig
-end
-
-def ranf
- rand(32767).to_f / 32767
-end
-
-# main #
-for i in 1 .. 15 # SIGHUP .. SIGTERM
- if trap(i, "SIG_IGN") != 0 then # 0 for SIG_IGN
- trap(i) {|sig| onsig(sig) }
- end
-end
-
-init_screen
-nl
-noecho
-srand
-
-xpos = {}
-ypos = {}
-r = lines - 4
-c = cols - 4
-for i in 0 .. 4
- xpos[i] = (c * ranf).to_i + 2
- ypos[i] = (r * ranf).to_i + 2
-end
-
-i = 0
-while TRUE
- x = (c * ranf).to_i + 2
- y = (r * ranf).to_i + 2
-
-
- setpos(y, x); addstr(".")
-
- setpos(ypos[i], xpos[i]); addstr("o")
-
- i = if i == 0 then 4 else i - 1 end
- setpos(ypos[i], xpos[i]); addstr("O")
-
- i = if i == 0 then 4 else i - 1 end
- setpos(ypos[i] - 1, xpos[i]); addstr("-")
- setpos(ypos[i], xpos[i] - 1); addstr("|.|")
- setpos(ypos[i] + 1, xpos[i]); addstr("-")
-
- i = if i == 0 then 4 else i - 1 end
- setpos(ypos[i] - 2, xpos[i]); addstr("-")
- setpos(ypos[i] - 1, xpos[i] - 1); addstr("/ \\")
- setpos(ypos[i], xpos[i] - 2); addstr("| O |")
- setpos(ypos[i] + 1, xpos[i] - 1); addstr("\\ /")
- setpos(ypos[i] + 2, xpos[i]); addstr("-")
-
- i = if i == 0 then 4 else i - 1 end
- setpos(ypos[i] - 2, xpos[i]); addstr(" ")
- setpos(ypos[i] - 1, xpos[i] - 1); addstr(" ")
- setpos(ypos[i], xpos[i] - 2); addstr(" ")
- setpos(ypos[i] + 1, xpos[i] - 1); addstr(" ")
- setpos(ypos[i] + 2, xpos[i]); addstr(" ")
-
-
- xpos[i] = x
- ypos[i] = y
- refresh
- sleep(0.5)
-end
-
-# end of main
diff --git a/ext/curses/view.rb b/ext/curses/view.rb
deleted file mode 100644
index d9a82a57db..0000000000
--- a/ext/curses/view.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/usr/local/bin/ruby
-
-require "curses"
-include Curses
-
-#
-# main
-#
-
-if ARGV.size != 1 then
- printf("usage: view file\n");
- exit
-end
-begin
- fp = open(ARGV[0], "r")
-rescue
- raise "cannot open file: #{ARGV[1]}"
-end
-
-# signal(SIGINT, finish)
-
-init_screen
-#keypad(stdscr, TRUE)
-nonl
-cbreak
-noecho
-#scrollok(stdscr, TRUE)
-
-# slurp the file
-data_lines = []
-fp.each_line { |l|
- data_lines.push(l)
-}
-fp.close
-
-
-lptr = 0
-while TRUE
- i = 0
- while i < lines
- setpos(i, 0)
- #clrtoeol
- addstr(data_lines[lptr + i]) #if data_lines[lptr + i]
- i += 1
- end
- refresh
-
- explicit = FALSE
- n = 0
- while TRUE
- c = getch.chr
- if c =~ /[0-9]/
- n = 10 * n + c.to_i
- else
- break
- end
- end
-
- n = 1 if !explicit && n == 0
-
- case c
- when "n" #when KEY_DOWN
- i = 0
- while i < n
- if lptr + lines < data_lines.size then
- lptr += 1
- else
- break
- end
- i += 1
- end
- #wscrl(i)
-
- when "p" #when KEY_UP
- i = 0
- while i < n
- if lptr > 0 then
- lptr -= 1
- else
- break
- end
- i += 1
- end
- #wscrl(-i)
-
- when "q"
- break
- end
-
-end
-close_screen
diff --git a/ext/curses/view2.rb b/ext/curses/view2.rb
deleted file mode 100644
index 18d9619216..0000000000
--- a/ext/curses/view2.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/local/bin/ruby
-
-require "curses"
-
-if ARGV.size != 1 then
- printf("usage: view file\n");
- exit
-end
-begin
- fp = open(ARGV[0], "r")
-rescue
- raise "cannot open file: #{ARGV[1]}"
-end
-
-# signal(SIGINT, finish)
-
-Curses.init_screen
-Curses.nonl
-Curses.cbreak
-Curses.noecho
-
-$screen = Curses.stdscr
-
-$screen.scrollok(true)
-#$screen.keypad(true)
-
-# slurp the file
-$data_lines = []
-fp.each_line { |l|
- $data_lines.push(l.chop)
-}
-fp.close
-
-$top = 0
-$data_lines[0..$screen.maxy-1].each_with_index{|line, idx|
- $screen.setpos(idx, 0)
- $screen.addstr(line)
-}
-$screen.setpos(0,0)
-$screen.refresh
-
-def scroll_up
- if( $top > 0 )
- $screen.scrl(-1)
- $top -= 1
- str = $data_lines[$top]
- if( str )
- $screen.setpos(0, 0)
- $screen.addstr(str)
- end
- return true
- else
- return false
- end
-end
-
-def scroll_down
- if( $top + $screen.maxy < $data_lines.length )
- $screen.scrl(1)
- $top += 1
- str = $data_lines[$top + $screen.maxy - 1]
- if( str )
- $screen.setpos($screen.maxy - 1, 0)
- $screen.addstr(str)
- end
- return true
- else
- return false
- end
-end
-
-while true
- result = true
- c = Curses.getch
- case c
- when Curses::KEY_DOWN, Curses::KEY_CTRL_N
- result = scroll_down
- when Curses::KEY_UP, Curses::KEY_CTRL_P
- result = scroll_up
- when Curses::KEY_NPAGE, ?\s # white space
- for i in 0..($screen.maxy - 2)
- if( ! scroll_down )
- if( i == 0 )
- result = false
- end
- break
- end
- end
- when Curses::KEY_PPAGE
- for i in 0..($screen.maxy - 2)
- if( ! scroll_up )
- if( i == 0 )
- result = false
- end
- break
- end
- end
- when Curses::KEY_LEFT, Curses::KEY_CTRL_T
- while( scroll_up )
- end
- when Curses::KEY_RIGHT, Curses::KEY_CTRL_B
- while( scroll_down )
- end
- when ?q
- break
- else
- $screen.setpos(0,0)
- $screen.addstr("[unknown key `#{Curses.keyname(c)}'=#{c}] ")
- end
- if( !result )
- Curses.beep
- end
- $screen.setpos(0,0)
-end
-Curses.close_screen
diff --git a/ext/date/date.gemspec b/ext/date/date.gemspec
new file mode 100644
index 0000000000..cb439bd0a5
--- /dev/null
+++ b/ext/date/date.gemspec
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+version = File.foreach(File.expand_path("../lib/date.rb", __FILE__)).find do |line|
+ /^\s*VERSION\s*=\s*["'](.*)["']/ =~ line and break $1
+end
+
+Gem::Specification.new do |s|
+ s.name = "date"
+ s.version = version
+ s.summary = "The official date library for Ruby."
+ s.description = "The official date library for Ruby."
+
+ if Gem::Platform === s.platform and s.platform =~ 'java' or RUBY_ENGINE == 'jruby'
+ s.platform = 'java'
+ # No files shipped, no require path, no-op for now on JRuby
+ else
+ s.require_path = %w{lib}
+
+ s.files = [
+ "README.md", "COPYING", "BSDL",
+ "lib/date.rb", "ext/date/date_core.c", "ext/date/date_parse.c", "ext/date/date_strftime.c",
+ "ext/date/date_strptime.c", "ext/date/date_tmx.h", "ext/date/extconf.rb", "ext/date/prereq.mk",
+ "ext/date/zonetab.h", "ext/date/zonetab.list"
+ ]
+ s.extensions = "ext/date/extconf.rb"
+ end
+
+ s.required_ruby_version = ">= 2.6.0"
+
+ s.authors = ["Tadayoshi Funaba"]
+ s.email = [nil]
+ s.homepage = "https://github.com/ruby/date"
+ s.licenses = ["Ruby", "BSD-2-Clause"]
+
+ s.metadata["changelog_uri"] = s.homepage + "/releases"
+end
diff --git a/ext/date/date_core.c b/ext/date/date_core.c
new file mode 100644
index 0000000000..72d697c8ea
--- /dev/null
+++ b/ext/date/date_core.c
@@ -0,0 +1,10258 @@
+/*
+ date_core.c: Coded by Tadayoshi Funaba 2010-2014
+*/
+
+#include "ruby.h"
+#include "ruby/encoding.h"
+#include "ruby/util.h"
+#include <math.h>
+#include <time.h>
+#if defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#undef NDEBUG
+#define NDEBUG
+#include <assert.h>
+
+#ifdef RUBY_EXTCONF_H
+#include RUBY_EXTCONF_H
+#endif
+
+#define USE_PACK
+
+static ID id_cmp, id_le_p, id_ge_p, id_eqeq_p;
+static VALUE cDate, cDateTime;
+static VALUE eDateError;
+static VALUE half_days_in_day, day_in_nanoseconds;
+static double positive_inf, negative_inf;
+
+/* used by deconstruct_keys */
+static VALUE sym_year, sym_month, sym_day, sym_yday, sym_wday;
+static VALUE sym_hour, sym_min, sym_sec, sym_sec_fraction, sym_zone;
+
+#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
+
+#define f_abs(x) rb_funcall(x, rb_intern("abs"), 0)
+#define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
+#define f_add(x,y) rb_funcall(x, '+', 1, y)
+#define f_sub(x,y) rb_funcall(x, '-', 1, y)
+#define f_mul(x,y) rb_funcall(x, '*', 1, y)
+#define f_div(x,y) rb_funcall(x, '/', 1, y)
+#define f_quo(x,y) rb_funcall(x, rb_intern("quo"), 1, y)
+#define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
+#define f_mod(x,y) rb_funcall(x, '%', 1, y)
+#define f_remainder(x,y) rb_funcall(x, rb_intern("remainder"), 1, y)
+#define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
+#define f_floor(x) rb_funcall(x, rb_intern("floor"), 0)
+#define f_ceil(x) rb_funcall(x, rb_intern("ceil"), 0)
+#define f_truncate(x) rb_funcall(x, rb_intern("truncate"), 0)
+#define f_round(x) rb_funcall(x, rb_intern("round"), 0)
+
+#define f_to_i(x) rb_funcall(x, rb_intern("to_i"), 0)
+#define f_to_r(x) rb_funcall(x, rb_intern("to_r"), 0)
+#define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
+#define f_inspect(x) rb_funcall(x, rb_intern("inspect"), 0)
+
+#define f_add3(x,y,z) f_add(f_add(x, y), z)
+#define f_sub3(x,y,z) f_sub(f_sub(x, y), z)
+
+#define f_frozen_ary(...) rb_ary_freeze(rb_ary_new3(__VA_ARGS__))
+
+static VALUE date_initialize(int argc, VALUE *argv, VALUE self);
+static VALUE datetime_initialize(int argc, VALUE *argv, VALUE self);
+
+#define RETURN_FALSE_UNLESS_NUMERIC(obj) if(!RTEST(rb_obj_is_kind_of((obj), rb_cNumeric))) return Qfalse
+inline static void
+check_numeric(VALUE obj, const char* field)
+{
+ if(!RTEST(rb_obj_is_kind_of(obj, rb_cNumeric))) {
+ rb_raise(rb_eTypeError, "invalid %s (not numeric)", field);
+ }
+}
+
+inline static int
+f_cmp(VALUE x, VALUE y)
+{
+ if (FIXNUM_P(x) && FIXNUM_P(y)) {
+ long c = FIX2LONG(x) - FIX2LONG(y);
+ if (c > 0)
+ return 1;
+ else if (c < 0)
+ return -1;
+ return 0;
+ }
+ return rb_cmpint(rb_funcallv(x, id_cmp, 1, &y), x, y);
+}
+
+inline static VALUE
+f_lt_p(VALUE x, VALUE y)
+{
+ if (FIXNUM_P(x) && FIXNUM_P(y))
+ return f_boolcast(FIX2LONG(x) < FIX2LONG(y));
+ return rb_funcall(x, '<', 1, y);
+}
+
+inline static VALUE
+f_gt_p(VALUE x, VALUE y)
+{
+ if (FIXNUM_P(x) && FIXNUM_P(y))
+ return f_boolcast(FIX2LONG(x) > FIX2LONG(y));
+ return rb_funcall(x, '>', 1, y);
+}
+
+inline static VALUE
+f_le_p(VALUE x, VALUE y)
+{
+ if (FIXNUM_P(x) && FIXNUM_P(y))
+ return f_boolcast(FIX2LONG(x) <= FIX2LONG(y));
+ return rb_funcall(x, id_le_p, 1, y);
+}
+
+inline static VALUE
+f_ge_p(VALUE x, VALUE y)
+{
+ if (FIXNUM_P(x) && FIXNUM_P(y))
+ return f_boolcast(FIX2LONG(x) >= FIX2LONG(y));
+ return rb_funcall(x, id_ge_p, 1, y);
+}
+
+inline static VALUE
+f_eqeq_p(VALUE x, VALUE y)
+{
+ if (FIXNUM_P(x) && FIXNUM_P(y))
+ return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
+ return rb_funcall(x, id_eqeq_p, 1, y);
+}
+
+inline static VALUE
+f_zero_p(VALUE x)
+{
+ switch (TYPE(x)) {
+ case T_FIXNUM:
+ return f_boolcast(FIX2LONG(x) == 0);
+ case T_BIGNUM:
+ return Qfalse;
+ case T_RATIONAL:
+ {
+ VALUE num = rb_rational_num(x);
+ return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
+ }
+ }
+ return rb_funcall(x, id_eqeq_p, 1, INT2FIX(0));
+}
+
+#define f_nonzero_p(x) (!f_zero_p(x))
+
+inline static VALUE
+f_negative_p(VALUE x)
+{
+ if (FIXNUM_P(x))
+ return f_boolcast(FIX2LONG(x) < 0);
+ return rb_funcall(x, '<', 1, INT2FIX(0));
+}
+
+#define f_positive_p(x) (!f_negative_p(x))
+
+#define f_ajd(x) rb_funcall(x, rb_intern("ajd"), 0)
+#define f_jd(x) rb_funcall(x, rb_intern("jd"), 0)
+#define f_year(x) rb_funcall(x, rb_intern("year"), 0)
+#define f_mon(x) rb_funcall(x, rb_intern("mon"), 0)
+#define f_mday(x) rb_funcall(x, rb_intern("mday"), 0)
+#define f_wday(x) rb_funcall(x, rb_intern("wday"), 0)
+#define f_hour(x) rb_funcall(x, rb_intern("hour"), 0)
+#define f_min(x) rb_funcall(x, rb_intern("min"), 0)
+#define f_sec(x) rb_funcall(x, rb_intern("sec"), 0)
+
+/* copied from time.c */
+#define NDIV(x,y) (-(-((x)+1)/(y))-1)
+#define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
+#define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
+#define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d))
+
+#define HAVE_JD (1 << 0)
+#define HAVE_DF (1 << 1)
+#define HAVE_CIVIL (1 << 2)
+#define HAVE_TIME (1 << 3)
+#define COMPLEX_DAT (1 << 7)
+
+#define have_jd_p(x) ((x)->flags & HAVE_JD)
+#define have_df_p(x) ((x)->flags & HAVE_DF)
+#define have_civil_p(x) ((x)->flags & HAVE_CIVIL)
+#define have_time_p(x) ((x)->flags & HAVE_TIME)
+#define complex_dat_p(x) ((x)->flags & COMPLEX_DAT)
+#define simple_dat_p(x) (!complex_dat_p(x))
+
+#define ITALY 2299161 /* 1582-10-15 */
+#define ENGLAND 2361222 /* 1752-09-14 */
+#define JULIAN positive_inf
+#define GREGORIAN negative_inf
+#define DEFAULT_SG ITALY
+
+#define UNIX_EPOCH_IN_CJD INT2FIX(2440588) /* 1970-01-01 */
+
+#define MINUTE_IN_SECONDS 60
+#define HOUR_IN_SECONDS 3600
+#define DAY_IN_SECONDS 86400
+#define SECOND_IN_MILLISECONDS 1000
+#define SECOND_IN_NANOSECONDS 1000000000
+
+#define JC_PERIOD0 1461 /* 365.25 * 4 */
+#define GC_PERIOD0 146097 /* 365.2425 * 400 */
+#define CM_PERIOD0 71149239 /* (lcm 7 1461 146097) */
+#define CM_PERIOD (0xfffffff / CM_PERIOD0 * CM_PERIOD0)
+#define CM_PERIOD_JCY (CM_PERIOD / JC_PERIOD0 * 4)
+#define CM_PERIOD_GCY (CM_PERIOD / GC_PERIOD0 * 400)
+
+#define REFORM_BEGIN_YEAR 1582
+#define REFORM_END_YEAR 1930
+#define REFORM_BEGIN_JD 2298874 /* ns 1582-01-01 */
+#define REFORM_END_JD 2426355 /* os 1930-12-31 */
+
+#ifdef USE_PACK
+#define SEC_WIDTH 6
+#define MIN_WIDTH 6
+#define HOUR_WIDTH 5
+#define MDAY_WIDTH 5
+#define MON_WIDTH 4
+
+#define SEC_SHIFT 0
+#define MIN_SHIFT SEC_WIDTH
+#define HOUR_SHIFT (MIN_WIDTH + SEC_WIDTH)
+#define MDAY_SHIFT (HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH)
+#define MON_SHIFT (MDAY_WIDTH + HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH)
+
+#define PK_MASK(x) ((1 << (x)) - 1)
+
+#define EX_SEC(x) (((x) >> SEC_SHIFT) & PK_MASK(SEC_WIDTH))
+#define EX_MIN(x) (((x) >> MIN_SHIFT) & PK_MASK(MIN_WIDTH))
+#define EX_HOUR(x) (((x) >> HOUR_SHIFT) & PK_MASK(HOUR_WIDTH))
+#define EX_MDAY(x) (((x) >> MDAY_SHIFT) & PK_MASK(MDAY_WIDTH))
+#define EX_MON(x) (((x) >> MON_SHIFT) & PK_MASK(MON_WIDTH))
+
+#define PACK5(m,d,h,min,s) \
+ (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT) |\
+ ((h) << HOUR_SHIFT) | ((min) << MIN_SHIFT) | ((s) << SEC_SHIFT))
+
+#define PACK2(m,d) \
+ (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT))
+#endif
+
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#endif
+
+#if defined(FLT_RADIX) && defined(FLT_MANT_DIG) && FLT_RADIX == 2 && FLT_MANT_DIG > 22
+#define date_sg_t float
+#else
+#define date_sg_t double
+#endif
+
+#define JULIAN_EPOCH_DATE "-4712-01-01"
+#define JULIAN_EPOCH_DATETIME JULIAN_EPOCH_DATE "T00:00:00+00:00"
+#define JULIAN_EPOCH_DATETIME_RFC3339 "Mon, 1 Jan -4712 00:00:00 +0000"
+#define JULIAN_EPOCH_DATETIME_HTTPDATE "Mon, 01 Jan -4712 00:00:00 GMT"
+
+/* A set of nth, jd, df and sf denote ajd + 1/2. Each ajd begin at
+ * noon of GMT (assume equal to UTC). However, this begins at
+ * midnight.
+ */
+
+struct SimpleDateData
+{
+ unsigned flags;
+ int jd; /* as utc */
+ VALUE nth; /* not always canonicalized */
+ date_sg_t sg; /* 2298874..2426355 or -/+oo -- at most 22 bits */
+ /* decoded as utc=local */
+ int year; /* truncated */
+#ifndef USE_PACK
+ int mon;
+ int mday;
+ /* hour is zero */
+ /* min is zero */
+ /* sec is zero */
+#else
+ /* packed civil */
+ unsigned pc;
+#endif
+};
+
+struct ComplexDateData
+{
+ unsigned flags;
+ int jd; /* as utc */
+ VALUE nth; /* not always canonicalized */
+ date_sg_t sg; /* 2298874..2426355 or -/+oo -- at most 22 bits */
+ /* decoded as local */
+ int year; /* truncated */
+#ifndef USE_PACK
+ int mon;
+ int mday;
+ int hour;
+ int min;
+ int sec;
+#else
+ /* packed civil */
+ unsigned pc;
+#endif
+ int df; /* as utc, in secs */
+ int of; /* in secs */
+ VALUE sf; /* in nano secs */
+};
+
+union DateData {
+ unsigned flags;
+ struct SimpleDateData s;
+ struct ComplexDateData c;
+};
+
+#define get_d1(x)\
+ union DateData *dat;\
+ TypedData_Get_Struct(x, union DateData, &d_lite_type, dat);
+
+#define get_d1a(x)\
+ union DateData *adat;\
+ TypedData_Get_Struct(x, union DateData, &d_lite_type, adat);
+
+#define get_d1b(x)\
+ union DateData *bdat;\
+ TypedData_Get_Struct(x, union DateData, &d_lite_type, bdat);
+
+#define get_d2(x,y)\
+ union DateData *adat, *bdat;\
+ TypedData_Get_Struct(x, union DateData, &d_lite_type, adat);\
+ TypedData_Get_Struct(y, union DateData, &d_lite_type, bdat);
+
+inline static VALUE
+canon(VALUE x)
+{
+ if (RB_TYPE_P(x, T_RATIONAL)) {
+ VALUE den = rb_rational_den(x);
+ if (FIXNUM_P(den) && FIX2LONG(den) == 1)
+ return rb_rational_num(x);
+ }
+ return x;
+}
+
+#ifndef USE_PACK
+#define set_to_simple(obj, x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
+do {\
+ RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth)); \
+ (x)->jd = _jd;\
+ (x)->sg = (date_sg_t)(_sg);\
+ (x)->year = _year;\
+ (x)->mon = _mon;\
+ (x)->mday = _mday;\
+ (x)->flags = (_flags) & ~COMPLEX_DAT;\
+} while (0)
+#else
+#define set_to_simple(obj, x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
+do {\
+ RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth)); \
+ (x)->jd = _jd;\
+ (x)->sg = (date_sg_t)(_sg);\
+ (x)->year = _year;\
+ (x)->pc = PACK2(_mon, _mday);\
+ (x)->flags = (_flags) & ~COMPLEX_DAT;\
+} while (0)
+#endif
+
+#ifndef USE_PACK
+#define set_to_complex(obj, x, _nth, _jd ,_df, _sf, _of, _sg,\
+_year, _mon, _mday, _hour, _min, _sec, _flags) \
+do {\
+ RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth));\
+ (x)->jd = _jd;\
+ (x)->df = _df;\
+ RB_OBJ_WRITE((obj), &(x)->sf, canon(_sf));\
+ (x)->of = _of;\
+ (x)->sg = (date_sg_t)(_sg);\
+ (x)->year = _year;\
+ (x)->mon = _mon;\
+ (x)->mday = _mday;\
+ (x)->hour = _hour;\
+ (x)->min = _min;\
+ (x)->sec = _sec;\
+ (x)->flags = (_flags) | COMPLEX_DAT;\
+} while (0)
+#else
+#define set_to_complex(obj, x, _nth, _jd ,_df, _sf, _of, _sg,\
+_year, _mon, _mday, _hour, _min, _sec, _flags) \
+do {\
+ RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth));\
+ (x)->jd = _jd;\
+ (x)->df = _df;\
+ RB_OBJ_WRITE((obj), &(x)->sf, canon(_sf));\
+ (x)->of = _of;\
+ (x)->sg = (date_sg_t)(_sg);\
+ (x)->year = _year;\
+ (x)->pc = PACK5(_mon, _mday, _hour, _min, _sec);\
+ (x)->flags = (_flags) | COMPLEX_DAT;\
+} while (0)
+#endif
+
+#ifndef USE_PACK
+#define copy_simple_to_complex(obj, x, y) \
+do {\
+ RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
+ (x)->jd = (y)->jd;\
+ (x)->df = 0;\
+ (x)->sf = INT2FIX(0);\
+ (x)->of = 0;\
+ (x)->sg = (date_sg_t)((y)->sg);\
+ (x)->year = (y)->year;\
+ (x)->mon = (y)->mon;\
+ (x)->mday = (y)->mday;\
+ (x)->hour = 0;\
+ (x)->min = 0;\
+ (x)->sec = 0;\
+ (x)->flags = (y)->flags;\
+} while (0)
+#else
+#define copy_simple_to_complex(obj, x, y) \
+do {\
+ RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
+ (x)->jd = (y)->jd;\
+ (x)->df = 0;\
+ RB_OBJ_WRITE((obj), &(x)->sf, INT2FIX(0));\
+ (x)->of = 0;\
+ (x)->sg = (date_sg_t)((y)->sg);\
+ (x)->year = (y)->year;\
+ (x)->pc = PACK5(EX_MON((y)->pc), EX_MDAY((y)->pc), 0, 0, 0);\
+ (x)->flags = (y)->flags;\
+} while (0)
+#endif
+
+#ifndef USE_PACK
+#define copy_complex_to_simple(obj, x, y) \
+do {\
+ RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
+ (x)->jd = (y)->jd;\
+ (x)->sg = (date_sg_t)((y)->sg);\
+ (x)->year = (y)->year;\
+ (x)->mon = (y)->mon;\
+ (x)->mday = (y)->mday;\
+ (x)->flags = (y)->flags;\
+} while (0)
+#else
+#define copy_complex_to_simple(obj, x, y) \
+do {\
+ RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
+ (x)->jd = (y)->jd;\
+ (x)->sg = (date_sg_t)((y)->sg);\
+ (x)->year = (y)->year;\
+ (x)->pc = PACK2(EX_MON((y)->pc), EX_MDAY((y)->pc));\
+ (x)->flags = (y)->flags;\
+} while (0)
+#endif
+
+/* base */
+
+static int c_valid_civil_p(int, int, int, double,
+ int *, int *, int *, int *);
+
+/* Check if using pure Gregorian calendar (sg == -Infinity) */
+#define c_gregorian_only_p(sg) (isinf(sg) && (sg) < 0)
+
+/*
+ * Fast path macros for pure Gregorian calendar.
+ * Sets *rjd to the JD value, *ns to 1 (new style), and returns.
+ */
+#define GREGORIAN_JD_FAST_PATH_RET(sg, jd_expr, rjd, ns) \
+ if (c_gregorian_only_p(sg)) { \
+ *(rjd) = (jd_expr); \
+ *(ns) = 1; \
+ return 1; \
+ }
+
+#define GREGORIAN_JD_FAST_PATH(sg, jd_expr, rjd, ns) \
+ if (c_gregorian_only_p(sg)) { \
+ *(rjd) = (jd_expr); \
+ *(ns) = 1; \
+ return; \
+ }
+
+/* Forward declarations for Neri-Schneider optimized functions */
+static int c_gregorian_civil_to_jd(int y, int m, int d);
+static void c_gregorian_jd_to_civil(int jd, int *ry, int *rm, int *rd);
+static int c_gregorian_fdoy(int y);
+static int c_gregorian_ldoy(int y);
+static int c_gregorian_ldom_jd(int y, int m);
+static int ns_jd_in_range(int jd);
+
+static int
+c_find_fdoy(int y, double sg, int *rjd, int *ns)
+{
+ int d, rm, rd;
+
+ GREGORIAN_JD_FAST_PATH_RET(sg, c_gregorian_fdoy(y), rjd, ns);
+
+ /* Keep existing loop for Julian/reform period */
+ for (d = 1; d < 31; d++)
+ if (c_valid_civil_p(y, 1, d, sg, &rm, &rd, rjd, ns))
+ return 1;
+ return 0;
+}
+
+static int
+c_find_ldoy(int y, double sg, int *rjd, int *ns)
+{
+ int i, rm, rd;
+
+ GREGORIAN_JD_FAST_PATH_RET(sg, c_gregorian_ldoy(y), rjd, ns);
+
+ /* Keep existing loop for Julian/reform period */
+ for (i = 0; i < 30; i++)
+ if (c_valid_civil_p(y, 12, 31 - i, sg, &rm, &rd, rjd, ns))
+ return 1;
+ return 0;
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static int
+c_find_fdom(int y, int m, double sg, int *rjd, int *ns)
+{
+ int d, rm, rd;
+
+ for (d = 1; d < 31; d++)
+ if (c_valid_civil_p(y, m, d, sg, &rm, &rd, rjd, ns))
+ return 1;
+ return 0;
+}
+#endif
+
+static int
+c_find_ldom(int y, int m, double sg, int *rjd, int *ns)
+{
+ int i, rm, rd;
+
+ GREGORIAN_JD_FAST_PATH_RET(sg, c_gregorian_ldom_jd(y, m), rjd, ns);
+
+ /* Keep existing loop for Julian/reform period */
+ for (i = 0; i < 30; i++)
+ if (c_valid_civil_p(y, m, 31 - i, sg, &rm, &rd, rjd, ns))
+ return 1;
+ return 0;
+}
+
+static void
+c_civil_to_jd(int y, int m, int d, double sg, int *rjd, int *ns)
+{
+ int jd;
+
+ GREGORIAN_JD_FAST_PATH(sg, c_gregorian_civil_to_jd(y, m, d), rjd, ns);
+
+ /* Calculate Gregorian JD using optimized algorithm */
+ jd = c_gregorian_civil_to_jd(y, m, d);
+
+ if (jd < sg) {
+ /* Before Gregorian switchover - use Julian calendar */
+ int y2 = y, m2 = m;
+ if (m2 <= 2) {
+ y2 -= 1;
+ m2 += 12;
+ }
+ jd = (int)(floor(365.25 * (y2 + 4716)) +
+ floor(30.6001 * (m2 + 1)) +
+ d - 1524);
+ *ns = 0;
+ }
+ else {
+ *ns = 1;
+ }
+
+ *rjd = jd;
+}
+
+static void
+c_jd_to_civil(int jd, double sg, int *ry, int *rm, int *rdom)
+{
+ /* Fast path: pure Gregorian or date after switchover, within safe range */
+ if ((c_gregorian_only_p(sg) || jd >= sg) && ns_jd_in_range(jd)) {
+ c_gregorian_jd_to_civil(jd, ry, rm, rdom);
+ return;
+ }
+
+ /* Original algorithm for Julian calendar or extreme dates */
+ {
+ double x, a, b, c, d, e, y, m, dom;
+
+ if (jd < sg)
+ a = jd;
+ else {
+ x = floor((jd - 1867216.25) / 36524.25);
+ a = jd + 1 + x - floor(x / 4.0);
+ }
+ b = a + 1524;
+ c = floor((b - 122.1) / 365.25);
+ d = floor(365.25 * c);
+ e = floor((b - d) / 30.6001);
+ dom = b - d - floor(30.6001 * e);
+ if (e <= 13) {
+ m = e - 1;
+ y = c - 4716;
+ }
+ else {
+ m = e - 13;
+ y = c - 4715;
+ }
+
+ *ry = (int)y;
+ *rm = (int)m;
+ *rdom = (int)dom;
+ }
+}
+
+static void
+c_ordinal_to_jd(int y, int d, double sg, int *rjd, int *ns)
+{
+ int ns2;
+
+ c_find_fdoy(y, sg, rjd, &ns2);
+ *rjd += d - 1;
+ *ns = (*rjd < sg) ? 0 : 1;
+}
+
+static void
+c_jd_to_ordinal(int jd, double sg, int *ry, int *rd)
+{
+ int rm2, rd2, rjd, ns;
+
+ c_jd_to_civil(jd, sg, ry, &rm2, &rd2);
+ c_find_fdoy(*ry, sg, &rjd, &ns);
+ *rd = (jd - rjd) + 1;
+}
+
+static void
+c_commercial_to_jd(int y, int w, int d, double sg, int *rjd, int *ns)
+{
+ int rjd2, ns2;
+
+ c_find_fdoy(y, sg, &rjd2, &ns2);
+ rjd2 += 3;
+ *rjd =
+ (rjd2 - MOD((rjd2 - 1) + 1, 7)) +
+ 7 * (w - 1) +
+ (d - 1);
+ *ns = (*rjd < sg) ? 0 : 1;
+}
+
+static void
+c_jd_to_commercial(int jd, double sg, int *ry, int *rw, int *rd)
+{
+ int ry2, rm2, rd2, a, rjd2, ns2;
+
+ c_jd_to_civil(jd - 3, sg, &ry2, &rm2, &rd2);
+ a = ry2;
+ c_commercial_to_jd(a + 1, 1, 1, sg, &rjd2, &ns2);
+ if (jd >= rjd2)
+ *ry = a + 1;
+ else {
+ c_commercial_to_jd(a, 1, 1, sg, &rjd2, &ns2);
+ *ry = a;
+ }
+ *rw = 1 + DIV(jd - rjd2, 7);
+ *rd = MOD(jd + 1, 7);
+ if (*rd == 0)
+ *rd = 7;
+}
+
+static void
+c_weeknum_to_jd(int y, int w, int d, int f, double sg, int *rjd, int *ns)
+{
+ int rjd2, ns2;
+
+ c_find_fdoy(y, sg, &rjd2, &ns2);
+ rjd2 += 6;
+ *rjd = (rjd2 - MOD(((rjd2 - f) + 1), 7) - 7) + 7 * w + d;
+ *ns = (*rjd < sg) ? 0 : 1;
+}
+
+static void
+c_jd_to_weeknum(int jd, int f, double sg, int *ry, int *rw, int *rd)
+{
+ int rm, rd2, rjd, ns, j;
+
+ c_jd_to_civil(jd, sg, ry, &rm, &rd2);
+ c_find_fdoy(*ry, sg, &rjd, &ns);
+ rjd += 6;
+ j = jd - (rjd - MOD((rjd - f) + 1, 7)) + 7;
+ *rw = (int)DIV(j, 7);
+ *rd = (int)MOD(j, 7);
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static void
+c_nth_kday_to_jd(int y, int m, int n, int k, double sg, int *rjd, int *ns)
+{
+ int rjd2, ns2;
+
+ if (n > 0) {
+ c_find_fdom(y, m, sg, &rjd2, &ns2);
+ rjd2 -= 1;
+ }
+ else {
+ c_find_ldom(y, m, sg, &rjd2, &ns2);
+ rjd2 += 7;
+ }
+ *rjd = (rjd2 - MOD((rjd2 - k) + 1, 7)) + 7 * n;
+ *ns = (*rjd < sg) ? 0 : 1;
+}
+#endif
+
+inline static int
+c_jd_to_wday(int jd)
+{
+ return MOD(jd + 1, 7);
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static void
+c_jd_to_nth_kday(int jd, double sg, int *ry, int *rm, int *rn, int *rk)
+{
+ int rd, rjd, ns2;
+
+ c_jd_to_civil(jd, sg, ry, rm, &rd);
+ c_find_fdom(*ry, *rm, sg, &rjd, &ns2);
+ *rn = DIV(jd - rjd, 7) + 1;
+ *rk = c_jd_to_wday(jd);
+}
+#endif
+
+static int
+c_valid_ordinal_p(int y, int d, double sg,
+ int *rd, int *rjd, int *ns)
+{
+ int ry2, rd2;
+
+ if (d < 0) {
+ int rjd2, ns2;
+
+ if (!c_find_ldoy(y, sg, &rjd2, &ns2))
+ return 0;
+ c_jd_to_ordinal(rjd2 + d + 1, sg, &ry2, &rd2);
+ if (ry2 != y)
+ return 0;
+ d = rd2;
+ }
+ c_ordinal_to_jd(y, d, sg, rjd, ns);
+ c_jd_to_ordinal(*rjd, sg, &ry2, &rd2);
+ if (ry2 != y || rd2 != d)
+ return 0;
+ return 1;
+}
+
+static const int monthtab[2][13] = {
+ { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+inline static int
+c_julian_leap_p(int y)
+{
+ return MOD(y, 4) == 0;
+}
+
+inline static int
+c_gregorian_leap_p(int y)
+{
+ return (MOD(y, 4) == 0 && y % 100 != 0) || MOD(y, 400) == 0;
+}
+
+static int
+c_julian_last_day_of_month(int y, int m)
+{
+ assert(m >= 1 && m <= 12);
+ return monthtab[c_julian_leap_p(y) ? 1 : 0][m];
+}
+
+static int
+c_gregorian_last_day_of_month(int y, int m)
+{
+ assert(m >= 1 && m <= 12);
+ return monthtab[c_gregorian_leap_p(y) ? 1 : 0][m];
+}
+
+/*
+ * Neri-Schneider algorithm for optimized Gregorian date conversion.
+ * Reference: Neri & Schneider, "Euclidean Affine Functions and Applications
+ * to Calendar Algorithms", Software: Practice and Experience, 2023.
+ * https://arxiv.org/abs/2102.06959
+ *
+ * This algorithm provides ~2-3x speedup over traditional floating-point
+ * implementations by using pure integer arithmetic with multiplication
+ * and bit-shifts instead of expensive division operations.
+ */
+
+/* JDN of March 1, Year 0 in proleptic Gregorian calendar */
+#define NS_EPOCH 1721120
+
+/* Days in a 4-year cycle (3 normal years + 1 leap year) */
+#define NS_DAYS_IN_4_YEARS 1461
+
+/* Days in a 400-year Gregorian cycle (97 leap years in 400 years) */
+#define NS_DAYS_IN_400_YEARS 146097
+
+/* Years per century */
+#define NS_YEARS_PER_CENTURY 100
+
+/*
+ * Multiplier for extracting year within century using fixed-point arithmetic.
+ * This is ceil(2^32 / NS_DAYS_IN_4_YEARS) for the Euclidean affine function.
+ */
+#define NS_YEAR_MULTIPLIER 2939745
+
+/*
+ * Coefficients for month calculation from day-of-year.
+ * Maps day-of-year to month using: month = (NS_MONTH_COEFF * doy + NS_MONTH_OFFSET) >> 16
+ */
+#define NS_MONTH_COEFF 2141
+#define NS_MONTH_OFFSET 197913
+
+/*
+ * Coefficients for civil date to JDN month contribution.
+ * Maps month to accumulated days: days = (NS_CIVIL_MONTH_COEFF * m - NS_CIVIL_MONTH_OFFSET) / 32
+ */
+#define NS_CIVIL_MONTH_COEFF 979
+#define NS_CIVIL_MONTH_OFFSET 2919
+#define NS_CIVIL_MONTH_DIVISOR 32
+
+/* Days from March 1 to December 31 (for Jan/Feb year adjustment) */
+#define NS_DAYS_BEFORE_NEW_YEAR 306
+
+/*
+ * Safe bounds for Neri-Schneider algorithm to avoid integer overflow.
+ * These correspond to approximately years -1,000,000 to +1,000,000.
+ */
+#define NS_JD_MIN -364000000
+#define NS_JD_MAX 538000000
+
+inline static int
+ns_jd_in_range(int jd)
+{
+ return jd >= NS_JD_MIN && jd <= NS_JD_MAX;
+}
+
+/* Optimized: Gregorian date -> Julian Day Number */
+static int
+c_gregorian_civil_to_jd(int y, int m, int d)
+{
+ /* Shift epoch to March 1 of year 0 (Jan/Feb belong to previous year) */
+ int j = (m < 3) ? 1 : 0;
+ int y0 = y - j;
+ int m0 = j ? m + 12 : m;
+ int d0 = d - 1;
+
+ /* Calculate year contribution with leap year correction */
+ int q1 = DIV(y0, NS_YEARS_PER_CENTURY);
+ int yc = DIV(NS_DAYS_IN_4_YEARS * y0, 4) - q1 + DIV(q1, 4);
+
+ /* Calculate month contribution using integer arithmetic */
+ int mc = (NS_CIVIL_MONTH_COEFF * m0 - NS_CIVIL_MONTH_OFFSET) / NS_CIVIL_MONTH_DIVISOR;
+
+ /* Combine and add epoch offset to get JDN */
+ return yc + mc + d0 + NS_EPOCH;
+}
+
+/* Optimized: Julian Day Number -> Gregorian date */
+static void
+c_gregorian_jd_to_civil(int jd, int *ry, int *rm, int *rd)
+{
+ int r0, n1, q1, r1, n2, q2, r2, n3, q3, r3, y0, j;
+ uint64_t u2;
+
+ /* Convert JDN to rata die (March 1, Year 0 epoch) */
+ r0 = jd - NS_EPOCH;
+
+ /* Extract century and day within 400-year cycle */
+ /* Use Euclidean (floor) division for negative values */
+ n1 = 4 * r0 + 3;
+ q1 = DIV(n1, NS_DAYS_IN_400_YEARS);
+ r1 = MOD(n1, NS_DAYS_IN_400_YEARS) / 4;
+
+ /* Calculate year within century and day of year */
+ n2 = 4 * r1 + 3;
+ /* Use 64-bit arithmetic to avoid overflow */
+ u2 = (uint64_t)NS_YEAR_MULTIPLIER * (uint64_t)n2;
+ q2 = (int)(u2 >> 32);
+ r2 = (int)((uint32_t)u2 / NS_YEAR_MULTIPLIER / 4);
+
+ /* Calculate month and day using integer arithmetic */
+ n3 = NS_MONTH_COEFF * r2 + NS_MONTH_OFFSET;
+ q3 = n3 >> 16;
+ r3 = (n3 & 0xFFFF) / NS_MONTH_COEFF;
+
+ /* Combine century and year */
+ y0 = NS_YEARS_PER_CENTURY * q1 + q2;
+
+ /* Adjust for January/February (shift from fiscal year) */
+ j = (r2 >= NS_DAYS_BEFORE_NEW_YEAR) ? 1 : 0;
+
+ *ry = y0 + j;
+ *rm = j ? q3 - 12 : q3;
+ *rd = r3 + 1;
+}
+
+/* O(1) first day of year for Gregorian calendar */
+inline static int
+c_gregorian_fdoy(int y)
+{
+ return c_gregorian_civil_to_jd(y, 1, 1);
+}
+
+/* O(1) last day of year for Gregorian calendar */
+inline static int
+c_gregorian_ldoy(int y)
+{
+ return c_gregorian_civil_to_jd(y, 12, 31);
+}
+
+/* O(1) last day of month (JDN) for Gregorian calendar */
+inline static int
+c_gregorian_ldom_jd(int y, int m)
+{
+ return c_gregorian_civil_to_jd(y, m, c_gregorian_last_day_of_month(y, m));
+}
+
+static int
+c_valid_julian_p(int y, int m, int d, int *rm, int *rd)
+{
+ int last;
+
+ if (m < 0)
+ m += 13;
+ if (m < 1 || m > 12)
+ return 0;
+ last = c_julian_last_day_of_month(y, m);
+ if (d < 0)
+ d = last + d + 1;
+ if (d < 1 || d > last)
+ return 0;
+ *rm = m;
+ *rd = d;
+ return 1;
+}
+
+static int
+c_valid_gregorian_p(int y, int m, int d, int *rm, int *rd)
+{
+ int last;
+
+ if (m < 0)
+ m += 13;
+ if (m < 1 || m > 12)
+ return 0;
+ last = c_gregorian_last_day_of_month(y, m);
+ if (d < 0)
+ d = last + d + 1;
+ if (d < 1 || d > last)
+ return 0;
+ *rm = m;
+ *rd = d;
+ return 1;
+}
+
+static int
+c_valid_civil_p(int y, int m, int d, double sg,
+ int *rm, int *rd, int *rjd, int *ns)
+{
+ int ry;
+
+ if (m < 0)
+ m += 13;
+ if (m < 1 || m > 12)
+ return 0;
+ if (d < 0) {
+ if (!c_find_ldom(y, m, sg, rjd, ns))
+ return 0;
+ c_jd_to_civil(*rjd + d + 1, sg, &ry, rm, rd);
+ if (ry != y || *rm != m)
+ return 0;
+ d = *rd;
+ }
+ c_civil_to_jd(y, m, d, sg, rjd, ns);
+ c_jd_to_civil(*rjd, sg, &ry, rm, rd);
+ if (ry != y || *rm != m || *rd != d)
+ return 0;
+ return 1;
+}
+
+static int
+c_valid_commercial_p(int y, int w, int d, double sg,
+ int *rw, int *rd, int *rjd, int *ns)
+{
+ int ns2, ry2, rw2, rd2;
+
+ if (d < 0)
+ d += 8;
+ if (w < 0) {
+ int rjd2;
+
+ c_commercial_to_jd(y + 1, 1, 1, sg, &rjd2, &ns2);
+ c_jd_to_commercial(rjd2 + w * 7, sg, &ry2, &rw2, &rd2);
+ if (ry2 != y)
+ return 0;
+ w = rw2;
+ }
+ c_commercial_to_jd(y, w, d, sg, rjd, ns);
+ c_jd_to_commercial(*rjd, sg, &ry2, rw, rd);
+ if (y != ry2 || w != *rw || d != *rd)
+ return 0;
+ return 1;
+}
+
+static int
+c_valid_weeknum_p(int y, int w, int d, int f, double sg,
+ int *rw, int *rd, int *rjd, int *ns)
+{
+ int ns2, ry2, rw2, rd2;
+
+ if (d < 0)
+ d += 7;
+ if (w < 0) {
+ int rjd2;
+
+ c_weeknum_to_jd(y + 1, 1, f, f, sg, &rjd2, &ns2);
+ c_jd_to_weeknum(rjd2 + w * 7, f, sg, &ry2, &rw2, &rd2);
+ if (ry2 != y)
+ return 0;
+ w = rw2;
+ }
+ c_weeknum_to_jd(y, w, d, f, sg, rjd, ns);
+ c_jd_to_weeknum(*rjd, f, sg, &ry2, rw, rd);
+ if (y != ry2 || w != *rw || d != *rd)
+ return 0;
+ return 1;
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static int
+c_valid_nth_kday_p(int y, int m, int n, int k, double sg,
+ int *rm, int *rn, int *rk, int *rjd, int *ns)
+{
+ int ns2, ry2, rm2, rn2, rk2;
+
+ if (k < 0)
+ k += 7;
+ if (n < 0) {
+ int t, ny, nm, rjd2;
+
+ t = y * 12 + m;
+ ny = DIV(t, 12);
+ nm = MOD(t, 12) + 1;
+
+ c_nth_kday_to_jd(ny, nm, 1, k, sg, &rjd2, &ns2);
+ c_jd_to_nth_kday(rjd2 + n * 7, sg, &ry2, &rm2, &rn2, &rk2);
+ if (ry2 != y || rm2 != m)
+ return 0;
+ n = rn2;
+ }
+ c_nth_kday_to_jd(y, m, n, k, sg, rjd, ns);
+ c_jd_to_nth_kday(*rjd, sg, &ry2, rm, rn, rk);
+ if (y != ry2 || m != *rm || n != *rn || k != *rk)
+ return 0;
+ return 1;
+}
+#endif
+
+static int
+c_valid_time_p(int h, int min, int s, int *rh, int *rmin, int *rs)
+{
+ if (h < 0)
+ h += 24;
+ if (min < 0)
+ min += 60;
+ if (s < 0)
+ s += 60;
+ *rh = h;
+ *rmin = min;
+ *rs = s;
+ return !(h < 0 || h > 24 ||
+ min < 0 || min > 59 ||
+ s < 0 || s > 59 ||
+ (h == 24 && (min > 0 || s > 0)));
+}
+
+inline static int
+c_valid_start_p(double sg)
+{
+ if (isnan(sg))
+ return 0;
+ if (isinf(sg))
+ return 1;
+ if (sg < REFORM_BEGIN_JD || sg > REFORM_END_JD)
+ return 0;
+ return 1;
+}
+
+inline static int
+df_local_to_utc(int df, int of)
+{
+ df -= of;
+ if (df < 0)
+ df += DAY_IN_SECONDS;
+ else if (df >= DAY_IN_SECONDS)
+ df -= DAY_IN_SECONDS;
+ return df;
+}
+
+inline static int
+df_utc_to_local(int df, int of)
+{
+ df += of;
+ if (df < 0)
+ df += DAY_IN_SECONDS;
+ else if (df >= DAY_IN_SECONDS)
+ df -= DAY_IN_SECONDS;
+ return df;
+}
+
+inline static int
+jd_local_to_utc(int jd, int df, int of)
+{
+ df -= of;
+ if (df < 0)
+ jd -= 1;
+ else if (df >= DAY_IN_SECONDS)
+ jd += 1;
+ return jd;
+}
+
+inline static int
+jd_utc_to_local(int jd, int df, int of)
+{
+ df += of;
+ if (df < 0)
+ jd -= 1;
+ else if (df >= DAY_IN_SECONDS)
+ jd += 1;
+ return jd;
+}
+
+inline static int
+time_to_df(int h, int min, int s)
+{
+ return h * HOUR_IN_SECONDS + min * MINUTE_IN_SECONDS + s;
+}
+
+inline static void
+df_to_time(int df, int *h, int *min, int *s)
+{
+ *h = df / HOUR_IN_SECONDS;
+ df %= HOUR_IN_SECONDS;
+ *min = df / MINUTE_IN_SECONDS;
+ *s = df % MINUTE_IN_SECONDS;
+}
+
+static VALUE
+sec_to_day(VALUE s)
+{
+ if (FIXNUM_P(s))
+ return rb_rational_new2(s, INT2FIX(DAY_IN_SECONDS));
+ return f_quo(s, INT2FIX(DAY_IN_SECONDS));
+}
+
+inline static VALUE
+isec_to_day(int s)
+{
+ return sec_to_day(INT2FIX(s));
+}
+
+static VALUE
+ns_to_day(VALUE n)
+{
+ if (FIXNUM_P(n))
+ return rb_rational_new2(n, day_in_nanoseconds);
+ return f_quo(n, day_in_nanoseconds);
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+ms_to_sec(VALUE m)
+{
+ if (FIXNUM_P(m))
+ return rb_rational_new2(m, INT2FIX(SECOND_IN_MILLISECONDS));
+ return f_quo(m, INT2FIX(SECOND_IN_MILLISECONDS));
+}
+#endif
+
+static VALUE
+ns_to_sec(VALUE n)
+{
+ if (FIXNUM_P(n))
+ return rb_rational_new2(n, INT2FIX(SECOND_IN_NANOSECONDS));
+ return f_quo(n, INT2FIX(SECOND_IN_NANOSECONDS));
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+inline static VALUE
+ins_to_day(int n)
+{
+ return ns_to_day(INT2FIX(n));
+}
+#endif
+
+static int
+safe_mul_p(VALUE x, long m)
+{
+ long ix;
+
+ if (!FIXNUM_P(x))
+ return 0;
+ ix = FIX2LONG(x);
+ if (ix < 0) {
+ if (ix <= (FIXNUM_MIN / m))
+ return 0;
+ }
+ else {
+ if (ix >= (FIXNUM_MAX / m))
+ return 0;
+ }
+ return 1;
+}
+
+static VALUE
+day_to_sec(VALUE d)
+{
+ if (safe_mul_p(d, DAY_IN_SECONDS))
+ return LONG2FIX(FIX2LONG(d) * DAY_IN_SECONDS);
+ return f_mul(d, INT2FIX(DAY_IN_SECONDS));
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+day_to_ns(VALUE d)
+{
+ return f_mul(d, day_in_nanoseconds);
+}
+#endif
+
+static VALUE
+sec_to_ms(VALUE s)
+{
+ if (safe_mul_p(s, SECOND_IN_MILLISECONDS))
+ return LONG2FIX(FIX2LONG(s) * SECOND_IN_MILLISECONDS);
+ return f_mul(s, INT2FIX(SECOND_IN_MILLISECONDS));
+}
+
+static VALUE
+sec_to_ns(VALUE s)
+{
+ if (safe_mul_p(s, SECOND_IN_NANOSECONDS))
+ return LONG2FIX(FIX2LONG(s) * SECOND_IN_NANOSECONDS);
+ return f_mul(s, INT2FIX(SECOND_IN_NANOSECONDS));
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+isec_to_ns(int s)
+{
+ return sec_to_ns(INT2FIX(s));
+}
+#endif
+
+static VALUE
+div_day(VALUE d, VALUE *f)
+{
+ if (f)
+ *f = f_mod(d, INT2FIX(1));
+ return f_floor(d);
+}
+
+static VALUE
+div_df(VALUE d, VALUE *f)
+{
+ VALUE s = day_to_sec(d);
+
+ if (f)
+ *f = f_mod(s, INT2FIX(1));
+ return f_floor(s);
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+div_sf(VALUE s, VALUE *f)
+{
+ VALUE n = sec_to_ns(s);
+
+ if (f)
+ *f = f_mod(n, INT2FIX(1));
+ return f_floor(n);
+}
+#endif
+
+static void
+decode_day(VALUE d, VALUE *jd, VALUE *df, VALUE *sf)
+{
+ VALUE f;
+
+ *jd = div_day(d, &f);
+ *df = div_df(f, &f);
+ *sf = sec_to_ns(f);
+}
+
+inline static double
+s_virtual_sg(union DateData *x)
+{
+ if (isinf(x->s.sg))
+ return x->s.sg;
+ if (f_zero_p(x->s.nth))
+ return x->s.sg;
+ else if (f_negative_p(x->s.nth))
+ return positive_inf;
+ return negative_inf;
+}
+
+inline static double
+c_virtual_sg(union DateData *x)
+{
+ if (isinf(x->c.sg))
+ return x->c.sg;
+ if (f_zero_p(x->c.nth))
+ return x->c.sg;
+ else if (f_negative_p(x->c.nth))
+ return positive_inf;
+ return negative_inf;
+}
+
+inline static double
+m_virtual_sg(union DateData *x)
+{
+ if (simple_dat_p(x))
+ return s_virtual_sg(x);
+ else
+ return c_virtual_sg(x);
+}
+
+#define canonicalize_jd(_nth, _jd) \
+do {\
+ if (_jd < 0) {\
+ _nth = f_sub(_nth, INT2FIX(1));\
+ _jd += CM_PERIOD;\
+ }\
+ if (_jd >= CM_PERIOD) {\
+ _nth = f_add(_nth, INT2FIX(1));\
+ _jd -= CM_PERIOD;\
+ }\
+} while (0)
+
+inline static void
+canonicalize_s_jd(VALUE obj, union DateData *x)
+{
+ int j = x->s.jd;
+ VALUE nth = x->s.nth;
+ assert(have_jd_p(x));
+ canonicalize_jd(nth, x->s.jd);
+ RB_OBJ_WRITE(obj, &x->s.nth, nth);
+ if (x->s.jd != j)
+ x->flags &= ~HAVE_CIVIL;
+}
+
+inline static void
+get_s_jd(union DateData *x)
+{
+ assert(simple_dat_p(x));
+ if (!have_jd_p(x)) {
+ int jd, ns;
+
+ assert(have_civil_p(x));
+#ifndef USE_PACK
+ c_civil_to_jd(x->s.year, x->s.mon, x->s.mday,
+ s_virtual_sg(x), &jd, &ns);
+#else
+ c_civil_to_jd(x->s.year, EX_MON(x->s.pc), EX_MDAY(x->s.pc),
+ s_virtual_sg(x), &jd, &ns);
+#endif
+ x->s.jd = jd;
+ x->s.flags |= HAVE_JD;
+ }
+}
+
+inline static void
+get_s_civil(union DateData *x)
+{
+ assert(simple_dat_p(x));
+ if (!have_civil_p(x)) {
+ int y, m, d;
+
+ assert(have_jd_p(x));
+ c_jd_to_civil(x->s.jd, s_virtual_sg(x), &y, &m, &d);
+ x->s.year = y;
+#ifndef USE_PACK
+ x->s.mon = m;
+ x->s.mday = d;
+#else
+ x->s.pc = PACK2(m, d);
+#endif
+ x->s.flags |= HAVE_CIVIL;
+ }
+}
+
+inline static void
+get_c_df(union DateData *x)
+{
+ assert(complex_dat_p(x));
+ if (!have_df_p(x)) {
+ assert(have_time_p(x));
+#ifndef USE_PACK
+ x->c.df = df_local_to_utc(time_to_df(x->c.hour, x->c.min, x->c.sec),
+ x->c.of);
+#else
+ x->c.df = df_local_to_utc(time_to_df(EX_HOUR(x->c.pc),
+ EX_MIN(x->c.pc),
+ EX_SEC(x->c.pc)),
+ x->c.of);
+#endif
+ x->c.flags |= HAVE_DF;
+ }
+}
+
+inline static void
+get_c_time(union DateData *x)
+{
+ assert(complex_dat_p(x));
+ if (!have_time_p(x)) {
+#ifndef USE_PACK
+ int r;
+ assert(have_df_p(x));
+ r = df_utc_to_local(x->c.df, x->c.of);
+ df_to_time(r, &x->c.hour, &x->c.min, &x->c.sec);
+ x->c.flags |= HAVE_TIME;
+#else
+ int r, m, d, h, min, s;
+
+ assert(have_df_p(x));
+ m = EX_MON(x->c.pc);
+ d = EX_MDAY(x->c.pc);
+ r = df_utc_to_local(x->c.df, x->c.of);
+ df_to_time(r, &h, &min, &s);
+ x->c.pc = PACK5(m, d, h, min, s);
+ x->c.flags |= HAVE_TIME;
+#endif
+ }
+}
+
+inline static void
+canonicalize_c_jd(VALUE obj, union DateData *x)
+{
+ int j = x->c.jd;
+ VALUE nth = x->c.nth;
+ assert(have_jd_p(x));
+ canonicalize_jd(nth, x->c.jd);
+ RB_OBJ_WRITE(obj, &x->c.nth, nth);
+ if (x->c.jd != j)
+ x->flags &= ~HAVE_CIVIL;
+}
+
+inline static void
+get_c_jd(union DateData *x)
+{
+ assert(complex_dat_p(x));
+ if (!have_jd_p(x)) {
+ int jd, ns;
+
+ assert(have_civil_p(x));
+#ifndef USE_PACK
+ c_civil_to_jd(x->c.year, x->c.mon, x->c.mday,
+ c_virtual_sg(x), &jd, &ns);
+#else
+ c_civil_to_jd(x->c.year, EX_MON(x->c.pc), EX_MDAY(x->c.pc),
+ c_virtual_sg(x), &jd, &ns);
+#endif
+
+ get_c_time(x);
+#ifndef USE_PACK
+ x->c.jd = jd_local_to_utc(jd,
+ time_to_df(x->c.hour, x->c.min, x->c.sec),
+ x->c.of);
+#else
+ x->c.jd = jd_local_to_utc(jd,
+ time_to_df(EX_HOUR(x->c.pc),
+ EX_MIN(x->c.pc),
+ EX_SEC(x->c.pc)),
+ x->c.of);
+#endif
+ x->c.flags |= HAVE_JD;
+ }
+}
+
+inline static void
+get_c_civil(union DateData *x)
+{
+ assert(complex_dat_p(x));
+ if (!have_civil_p(x)) {
+#ifndef USE_PACK
+ int jd, y, m, d;
+#else
+ int jd, y, m, d, h, min, s;
+#endif
+
+ assert(have_jd_p(x));
+ get_c_df(x);
+ jd = jd_utc_to_local(x->c.jd, x->c.df, x->c.of);
+ c_jd_to_civil(jd, c_virtual_sg(x), &y, &m, &d);
+ x->c.year = y;
+#ifndef USE_PACK
+ x->c.mon = m;
+ x->c.mday = d;
+#else
+ h = EX_HOUR(x->c.pc);
+ min = EX_MIN(x->c.pc);
+ s = EX_SEC(x->c.pc);
+ x->c.pc = PACK5(m, d, h, min, s);
+#endif
+ x->c.flags |= HAVE_CIVIL;
+ }
+}
+
+inline static int
+local_jd(union DateData *x)
+{
+ assert(complex_dat_p(x));
+ assert(have_jd_p(x));
+ assert(have_df_p(x));
+ return jd_utc_to_local(x->c.jd, x->c.df, x->c.of);
+}
+
+inline static int
+local_df(union DateData *x)
+{
+ assert(complex_dat_p(x));
+ assert(have_df_p(x));
+ return df_utc_to_local(x->c.df, x->c.of);
+}
+
+static void
+decode_year(VALUE y, double style,
+ VALUE *nth, int *ry)
+{
+ int period;
+ VALUE t;
+
+ period = (style < 0) ?
+ CM_PERIOD_GCY :
+ CM_PERIOD_JCY;
+ if (FIXNUM_P(y)) {
+ long iy, it, inth;
+
+ iy = FIX2LONG(y);
+ if (iy >= (FIXNUM_MAX - 4712))
+ goto big;
+ it = iy + 4712; /* shift */
+ inth = DIV(it, ((long)period));
+ *nth = LONG2FIX(inth);
+ if (inth)
+ it = MOD(it, ((long)period));
+ *ry = (int)it - 4712; /* unshift */
+ return;
+ }
+ big:
+ t = f_add(y, INT2FIX(4712)); /* shift */
+ *nth = f_idiv(t, INT2FIX(period));
+ if (f_nonzero_p(*nth))
+ t = f_mod(t, INT2FIX(period));
+ *ry = FIX2INT(t) - 4712; /* unshift */
+}
+
+static void
+encode_year(VALUE nth, int y, double style,
+ VALUE *ry)
+{
+ int period;
+ VALUE t;
+
+ period = (style < 0) ?
+ CM_PERIOD_GCY :
+ CM_PERIOD_JCY;
+ if (f_zero_p(nth))
+ *ry = INT2FIX(y);
+ else {
+ t = f_mul(INT2FIX(period), nth);
+ t = f_add(t, INT2FIX(y));
+ *ry = t;
+ }
+}
+
+static void
+decode_jd(VALUE jd, VALUE *nth, int *rjd)
+{
+ *nth = f_idiv(jd, INT2FIX(CM_PERIOD));
+ if (f_zero_p(*nth)) {
+ *rjd = FIX2INT(jd);
+ return;
+ }
+ *rjd = FIX2INT(f_mod(jd, INT2FIX(CM_PERIOD)));
+}
+
+static void
+encode_jd(VALUE nth, int jd, VALUE *rjd)
+{
+ if (f_zero_p(nth)) {
+ *rjd = INT2FIX(jd);
+ return;
+ }
+ *rjd = f_add(f_mul(INT2FIX(CM_PERIOD), nth), INT2FIX(jd));
+}
+
+inline static double
+guess_style(VALUE y, double sg) /* -/+oo or zero */
+{
+ double style = 0;
+
+ if (isinf(sg))
+ style = sg;
+ else if (!FIXNUM_P(y))
+ style = f_positive_p(y) ? negative_inf : positive_inf;
+ else {
+ long iy = FIX2LONG(y);
+
+ assert(FIXNUM_P(y));
+ if (iy < REFORM_BEGIN_YEAR)
+ style = positive_inf;
+ else if (iy > REFORM_END_YEAR)
+ style = negative_inf;
+ }
+ return style;
+}
+
+inline static void
+m_canonicalize_jd(VALUE obj, union DateData *x)
+{
+ if (simple_dat_p(x)) {
+ get_s_jd(x);
+ canonicalize_s_jd(obj, x);
+ }
+ else {
+ get_c_jd(x);
+ canonicalize_c_jd(obj, x);
+ }
+}
+
+inline static VALUE
+m_nth(union DateData *x)
+{
+ if (simple_dat_p(x))
+ return x->s.nth;
+ else {
+ get_c_civil(x);
+ return x->c.nth;
+ }
+}
+
+inline static int
+m_jd(union DateData *x)
+{
+ if (simple_dat_p(x)) {
+ get_s_jd(x);
+ return x->s.jd;
+ }
+ else {
+ get_c_jd(x);
+ return x->c.jd;
+ }
+}
+
+static VALUE
+m_real_jd(union DateData *x)
+{
+ VALUE nth, rjd;
+ int jd;
+
+ nth = m_nth(x);
+ jd = m_jd(x);
+
+ encode_jd(nth, jd, &rjd);
+ return rjd;
+}
+
+static int
+m_local_jd(union DateData *x)
+{
+ if (simple_dat_p(x)) {
+ get_s_jd(x);
+ return x->s.jd;
+ }
+ else {
+ get_c_jd(x);
+ get_c_df(x);
+ return local_jd(x);
+ }
+}
+
+static VALUE
+m_real_local_jd(union DateData *x)
+{
+ VALUE nth, rjd;
+ int jd;
+
+ nth = m_nth(x);
+ jd = m_local_jd(x);
+
+ encode_jd(nth, jd, &rjd);
+ return rjd;
+}
+
+inline static int
+m_df(union DateData *x)
+{
+ if (simple_dat_p(x))
+ return 0;
+ else {
+ get_c_df(x);
+ return x->c.df;
+ }
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+m_df_in_day(union DateData *x)
+{
+ return isec_to_day(m_df(x));
+}
+#endif
+
+static int
+m_local_df(union DateData *x)
+{
+ if (simple_dat_p(x))
+ return 0;
+ else {
+ get_c_df(x);
+ return local_df(x);
+ }
+}
+
+#ifndef NDEBUG
+static VALUE
+m_local_df_in_day(union DateData *x)
+{
+ return isec_to_day(m_local_df(x));
+}
+#endif
+
+inline static VALUE
+m_sf(union DateData *x)
+{
+ if (simple_dat_p(x))
+ return INT2FIX(0);
+ else
+ return x->c.sf;
+}
+
+#ifndef NDEBUG
+static VALUE
+m_sf_in_day(union DateData *x)
+{
+ return ns_to_day(m_sf(x));
+}
+#endif
+
+static VALUE
+m_sf_in_sec(union DateData *x)
+{
+ return ns_to_sec(m_sf(x));
+}
+
+static VALUE
+m_fr(union DateData *x)
+{
+ if (simple_dat_p(x))
+ return INT2FIX(0);
+ else {
+ int df;
+ VALUE sf, fr;
+
+ df = m_local_df(x);
+ sf = m_sf(x);
+ fr = isec_to_day(df);
+ if (f_nonzero_p(sf))
+ fr = f_add(fr, ns_to_day(sf));
+ return fr;
+ }
+}
+
+#define HALF_DAYS_IN_SECONDS (DAY_IN_SECONDS / 2)
+
+static VALUE
+m_ajd(union DateData *x)
+{
+ VALUE r, sf;
+ int df;
+
+ if (simple_dat_p(x)) {
+ r = m_real_jd(x);
+ if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2) && FIX2LONG(r) >= (FIXNUM_MIN + 1) / 2) {
+ long ir = FIX2LONG(r);
+ ir = ir * 2 - 1;
+ return rb_rational_new2(LONG2FIX(ir), INT2FIX(2));
+ }
+ else
+ return rb_rational_new2(f_sub(f_mul(r,
+ INT2FIX(2)),
+ INT2FIX(1)),
+ INT2FIX(2));
+ }
+
+ r = m_real_jd(x);
+ df = m_df(x);
+ df -= HALF_DAYS_IN_SECONDS;
+ if (df)
+ r = f_add(r, isec_to_day(df));
+ sf = m_sf(x);
+ if (f_nonzero_p(sf))
+ r = f_add(r, ns_to_day(sf));
+
+ return r;
+}
+
+static VALUE
+m_amjd(union DateData *x)
+{
+ VALUE r, sf;
+ int df;
+
+ r = m_real_jd(x);
+ if (FIXNUM_P(r) && FIX2LONG(r) >= (FIXNUM_MIN + 2400001)) {
+ long ir = FIX2LONG(r);
+ ir -= 2400001;
+ r = rb_rational_new1(LONG2FIX(ir));
+ }
+ else
+ r = rb_rational_new1(f_sub(m_real_jd(x),
+ INT2FIX(2400001)));
+
+ if (simple_dat_p(x))
+ return r;
+
+ df = m_df(x);
+ if (df)
+ r = f_add(r, isec_to_day(df));
+ sf = m_sf(x);
+ if (f_nonzero_p(sf))
+ r = f_add(r, ns_to_day(sf));
+
+ return r;
+}
+
+inline static int
+m_of(union DateData *x)
+{
+ if (simple_dat_p(x))
+ return 0;
+ else {
+ get_c_jd(x);
+ return x->c.of;
+ }
+}
+
+static VALUE
+m_of_in_day(union DateData *x)
+{
+ return isec_to_day(m_of(x));
+}
+
+inline static double
+m_sg(union DateData *x)
+{
+ if (simple_dat_p(x))
+ return x->s.sg;
+ else {
+ get_c_jd(x);
+ return x->c.sg;
+ }
+}
+
+static int
+m_julian_p(union DateData *x)
+{
+ int jd;
+ double sg;
+
+ if (simple_dat_p(x)) {
+ get_s_jd(x);
+ jd = x->s.jd;
+ sg = s_virtual_sg(x);
+ }
+ else {
+ get_c_jd(x);
+ jd = x->c.jd;
+ sg = c_virtual_sg(x);
+ }
+ if (isinf(sg))
+ return sg == positive_inf;
+ return jd < sg;
+}
+
+inline static int
+m_gregorian_p(union DateData *x)
+{
+ return !m_julian_p(x);
+}
+
+inline static int
+m_proleptic_julian_p(union DateData *x)
+{
+ double sg;
+
+ sg = m_sg(x);
+ if (isinf(sg) && sg > 0)
+ return 1;
+ return 0;
+}
+
+inline static int
+m_proleptic_gregorian_p(union DateData *x)
+{
+ double sg;
+
+ sg = m_sg(x);
+ if (isinf(sg) && sg < 0)
+ return 1;
+ return 0;
+}
+
+inline static int
+m_year(union DateData *x)
+{
+ if (simple_dat_p(x)) {
+ get_s_civil(x);
+ return x->s.year;
+ }
+ else {
+ get_c_civil(x);
+ return x->c.year;
+ }
+}
+
+static VALUE
+m_real_year(union DateData *x)
+{
+ VALUE nth, ry;
+ int year;
+
+ nth = m_nth(x);
+ year = m_year(x);
+
+ if (f_zero_p(nth))
+ return INT2FIX(year);
+
+ encode_year(nth, year,
+ m_gregorian_p(x) ? -1 : +1,
+ &ry);
+ return ry;
+}
+
+inline static int
+m_mon(union DateData *x)
+{
+ if (simple_dat_p(x)) {
+ get_s_civil(x);
+#ifndef USE_PACK
+ return x->s.mon;
+#else
+ return EX_MON(x->s.pc);
+#endif
+ }
+ else {
+ get_c_civil(x);
+#ifndef USE_PACK
+ return x->c.mon;
+#else
+ return EX_MON(x->c.pc);
+#endif
+ }
+}
+
+inline static int
+m_mday(union DateData *x)
+{
+ if (simple_dat_p(x)) {
+ get_s_civil(x);
+#ifndef USE_PACK
+ return x->s.mday;
+#else
+ return EX_MDAY(x->s.pc);
+#endif
+ }
+ else {
+ get_c_civil(x);
+#ifndef USE_PACK
+ return x->c.mday;
+#else
+ return EX_MDAY(x->c.pc);
+#endif
+ }
+}
+
+static const int yeartab[2][13] = {
+ { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
+ { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
+};
+
+static int
+c_julian_to_yday(int y, int m, int d)
+{
+ assert(m >= 1 && m <= 12);
+ return yeartab[c_julian_leap_p(y) ? 1 : 0][m] + d;
+}
+
+static int
+c_gregorian_to_yday(int y, int m, int d)
+{
+ assert(m >= 1 && m <= 12);
+ return yeartab[c_gregorian_leap_p(y) ? 1 : 0][m] + d;
+}
+
+static int
+m_yday(union DateData *x)
+{
+ int jd, ry, rd;
+ double sg;
+
+ jd = m_local_jd(x);
+ sg = m_virtual_sg(x); /* !=m_sg() */
+
+ if (m_proleptic_gregorian_p(x) ||
+ (jd - sg) > 366)
+ return c_gregorian_to_yday(m_year(x), m_mon(x), m_mday(x));
+ if (m_proleptic_julian_p(x))
+ return c_julian_to_yday(m_year(x), m_mon(x), m_mday(x));
+ c_jd_to_ordinal(jd, sg, &ry, &rd);
+ return rd;
+}
+
+static int
+m_wday(union DateData *x)
+{
+ return c_jd_to_wday(m_local_jd(x));
+}
+
+static int
+m_cwyear(union DateData *x)
+{
+ int ry, rw, rd;
+
+ c_jd_to_commercial(m_local_jd(x), m_virtual_sg(x), /* !=m_sg() */
+ &ry, &rw, &rd);
+ return ry;
+}
+
+static VALUE
+m_real_cwyear(union DateData *x)
+{
+ VALUE nth, ry;
+ int year;
+
+ nth = m_nth(x);
+ year = m_cwyear(x);
+
+ if (f_zero_p(nth))
+ return INT2FIX(year);
+
+ encode_year(nth, year,
+ m_gregorian_p(x) ? -1 : +1,
+ &ry);
+ return ry;
+}
+
+static int
+m_cweek(union DateData *x)
+{
+ int ry, rw, rd;
+
+ c_jd_to_commercial(m_local_jd(x), m_virtual_sg(x), /* !=m_sg() */
+ &ry, &rw, &rd);
+ return rw;
+}
+
+static int
+m_cwday(union DateData *x)
+{
+ int w;
+
+ w = m_wday(x);
+ if (w == 0)
+ w = 7;
+ return w;
+}
+
+static int
+m_wnumx(union DateData *x, int f)
+{
+ int ry, rw, rd;
+
+ c_jd_to_weeknum(m_local_jd(x), f, m_virtual_sg(x), /* !=m_sg() */
+ &ry, &rw, &rd);
+ return rw;
+}
+
+static int
+m_wnum0(union DateData *x)
+{
+ return m_wnumx(x, 0);
+}
+
+static int
+m_wnum1(union DateData *x)
+{
+ return m_wnumx(x, 1);
+}
+
+inline static int
+m_hour(union DateData *x)
+{
+ if (simple_dat_p(x))
+ return 0;
+ else {
+ get_c_time(x);
+#ifndef USE_PACK
+ return x->c.hour;
+#else
+ return EX_HOUR(x->c.pc);
+#endif
+ }
+}
+
+inline static int
+m_min(union DateData *x)
+{
+ if (simple_dat_p(x))
+ return 0;
+ else {
+ get_c_time(x);
+#ifndef USE_PACK
+ return x->c.min;
+#else
+ return EX_MIN(x->c.pc);
+#endif
+ }
+}
+
+inline static int
+m_sec(union DateData *x)
+{
+ if (simple_dat_p(x))
+ return 0;
+ else {
+ get_c_time(x);
+#ifndef USE_PACK
+ return x->c.sec;
+#else
+ return EX_SEC(x->c.pc);
+#endif
+ }
+}
+
+#define decode_offset(of,s,h,m)\
+do {\
+ int a;\
+ s = (of < 0) ? '-' : '+';\
+ a = (of < 0) ? -of : of;\
+ h = a / HOUR_IN_SECONDS;\
+ m = a % HOUR_IN_SECONDS / MINUTE_IN_SECONDS;\
+} while (0)
+
+static VALUE
+of2str(int of)
+{
+ int s, h, m;
+
+ decode_offset(of, s, h, m);
+ return rb_enc_sprintf(rb_usascii_encoding(), "%c%02d:%02d", s, h, m);
+}
+
+static VALUE
+m_zone(union DateData *x)
+{
+ if (simple_dat_p(x))
+ return rb_usascii_str_new2("+00:00");
+ return of2str(m_of(x));
+}
+
+inline static VALUE
+f_kind_of_p(VALUE x, VALUE c)
+{
+ return rb_obj_is_kind_of(x, c);
+}
+
+inline static VALUE
+k_date_p(VALUE x)
+{
+ return f_kind_of_p(x, cDate);
+}
+
+inline static VALUE
+k_numeric_p(VALUE x)
+{
+ return f_kind_of_p(x, rb_cNumeric);
+}
+
+inline static VALUE
+k_rational_p(VALUE x)
+{
+ return f_kind_of_p(x, rb_cRational);
+}
+
+static inline void
+expect_numeric(VALUE x)
+{
+ if (!k_numeric_p(x))
+ rb_raise(rb_eTypeError, "expected numeric");
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static void
+civil_to_jd(VALUE y, int m, int d, double sg,
+ VALUE *nth, int *ry,
+ int *rjd,
+ int *ns)
+{
+ double style = guess_style(y, sg);
+
+ if (style == 0) {
+ int jd;
+
+ c_civil_to_jd(FIX2INT(y), m, d, sg, &jd, ns);
+ decode_jd(INT2FIX(jd), nth, rjd);
+ if (f_zero_p(*nth))
+ *ry = FIX2INT(y);
+ else {
+ VALUE nth2;
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
+ }
+ }
+ else {
+ decode_year(y, style, nth, ry);
+ c_civil_to_jd(*ry, m, d, style, rjd, ns);
+ }
+}
+
+static void
+jd_to_civil(VALUE jd, double sg,
+ VALUE *nth, int *rjd,
+ int *ry, int *rm, int *rd)
+{
+ decode_jd(jd, nth, rjd);
+ c_jd_to_civil(*rjd, sg, ry, rm, rd);
+}
+
+static void
+ordinal_to_jd(VALUE y, int d, double sg,
+ VALUE *nth, int *ry,
+ int *rjd,
+ int *ns)
+{
+ double style = guess_style(y, sg);
+
+ if (style == 0) {
+ int jd;
+
+ c_ordinal_to_jd(FIX2INT(y), d, sg, &jd, ns);
+ decode_jd(INT2FIX(jd), nth, rjd);
+ if (f_zero_p(*nth))
+ *ry = FIX2INT(y);
+ else {
+ VALUE nth2;
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
+ }
+ }
+ else {
+ decode_year(y, style, nth, ry);
+ c_ordinal_to_jd(*ry, d, style, rjd, ns);
+ }
+}
+
+static void
+jd_to_ordinal(VALUE jd, double sg,
+ VALUE *nth, int *rjd,
+ int *ry, int *rd)
+{
+ decode_jd(jd, nth, rjd);
+ c_jd_to_ordinal(*rjd, sg, ry, rd);
+}
+
+static void
+commercial_to_jd(VALUE y, int w, int d, double sg,
+ VALUE *nth, int *ry,
+ int *rjd,
+ int *ns)
+{
+ double style = guess_style(y, sg);
+
+ if (style == 0) {
+ int jd;
+
+ c_commercial_to_jd(FIX2INT(y), w, d, sg, &jd, ns);
+ decode_jd(INT2FIX(jd), nth, rjd);
+ if (f_zero_p(*nth))
+ *ry = FIX2INT(y);
+ else {
+ VALUE nth2;
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
+ }
+ }
+ else {
+ decode_year(y, style, nth, ry);
+ c_commercial_to_jd(*ry, w, d, style, rjd, ns);
+ }
+}
+
+static void
+jd_to_commercial(VALUE jd, double sg,
+ VALUE *nth, int *rjd,
+ int *ry, int *rw, int *rd)
+{
+ decode_jd(jd, nth, rjd);
+ c_jd_to_commercial(*rjd, sg, ry, rw, rd);
+}
+
+static void
+weeknum_to_jd(VALUE y, int w, int d, int f, double sg,
+ VALUE *nth, int *ry,
+ int *rjd,
+ int *ns)
+{
+ double style = guess_style(y, sg);
+
+ if (style == 0) {
+ int jd;
+
+ c_weeknum_to_jd(FIX2INT(y), w, d, f, sg, &jd, ns);
+ decode_jd(INT2FIX(jd), nth, rjd);
+ if (f_zero_p(*nth))
+ *ry = FIX2INT(y);
+ else {
+ VALUE nth2;
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
+ }
+ }
+ else {
+ decode_year(y, style, nth, ry);
+ c_weeknum_to_jd(*ry, w, d, f, style, rjd, ns);
+ }
+}
+
+static void
+jd_to_weeknum(VALUE jd, int f, double sg,
+ VALUE *nth, int *rjd,
+ int *ry, int *rw, int *rd)
+{
+ decode_jd(jd, nth, rjd);
+ c_jd_to_weeknum(*rjd, f, sg, ry, rw, rd);
+}
+
+static void
+nth_kday_to_jd(VALUE y, int m, int n, int k, double sg,
+ VALUE *nth, int *ry,
+ int *rjd,
+ int *ns)
+{
+ double style = guess_style(y, sg);
+
+ if (style == 0) {
+ int jd;
+
+ c_nth_kday_to_jd(FIX2INT(y), m, n, k, sg, &jd, ns);
+ decode_jd(INT2FIX(jd), nth, rjd);
+ if (f_zero_p(*nth))
+ *ry = FIX2INT(y);
+ else {
+ VALUE nth2;
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
+ }
+ }
+ else {
+ decode_year(y, style, nth, ry);
+ c_nth_kday_to_jd(*ry, m, n, k, style, rjd, ns);
+ }
+}
+
+static void
+jd_to_nth_kday(VALUE jd, double sg,
+ VALUE *nth, int *rjd,
+ int *ry, int *rm, int *rn, int *rk)
+{
+ decode_jd(jd, nth, rjd);
+ c_jd_to_nth_kday(*rjd, sg, ry, rm, rn, rk);
+}
+#endif
+
+static int
+valid_ordinal_p(VALUE y, int d, double sg,
+ VALUE *nth, int *ry,
+ int *rd, int *rjd,
+ int *ns)
+{
+ double style = guess_style(y, sg);
+ int r;
+
+ if (style == 0) {
+ int jd;
+
+ r = c_valid_ordinal_p(FIX2INT(y), d, sg, rd, &jd, ns);
+ if (!r)
+ return 0;
+ decode_jd(INT2FIX(jd), nth, rjd);
+ if (f_zero_p(*nth))
+ *ry = FIX2INT(y);
+ else {
+ VALUE nth2;
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
+ }
+ }
+ else {
+ decode_year(y, style, nth, ry);
+ r = c_valid_ordinal_p(*ry, d, style, rd, rjd, ns);
+ }
+ return r;
+}
+
+static int
+valid_gregorian_p(VALUE y, int m, int d,
+ VALUE *nth, int *ry,
+ int *rm, int *rd)
+{
+ decode_year(y, -1, nth, ry);
+ return c_valid_gregorian_p(*ry, m, d, rm, rd);
+}
+
+static int
+valid_civil_p(VALUE y, int m, int d, double sg,
+ VALUE *nth, int *ry,
+ int *rm, int *rd, int *rjd,
+ int *ns)
+{
+ double style = guess_style(y, sg);
+ int r;
+
+ if (style == 0) {
+ int jd;
+
+ r = c_valid_civil_p(FIX2INT(y), m, d, sg, rm, rd, &jd, ns);
+ if (!r)
+ return 0;
+ decode_jd(INT2FIX(jd), nth, rjd);
+ if (f_zero_p(*nth))
+ *ry = FIX2INT(y);
+ else {
+ VALUE nth2;
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
+ }
+ }
+ else {
+ decode_year(y, style, nth, ry);
+ if (style < 0)
+ r = c_valid_gregorian_p(*ry, m, d, rm, rd);
+ else
+ r = c_valid_julian_p(*ry, m, d, rm, rd);
+ if (!r)
+ return 0;
+ c_civil_to_jd(*ry, *rm, *rd, style, rjd, ns);
+ }
+ return r;
+}
+
+static int
+valid_commercial_p(VALUE y, int w, int d, double sg,
+ VALUE *nth, int *ry,
+ int *rw, int *rd, int *rjd,
+ int *ns)
+{
+ double style = guess_style(y, sg);
+ int r;
+
+ if (style == 0) {
+ int jd;
+
+ r = c_valid_commercial_p(FIX2INT(y), w, d, sg, rw, rd, &jd, ns);
+ if (!r)
+ return 0;
+ decode_jd(INT2FIX(jd), nth, rjd);
+ if (f_zero_p(*nth))
+ *ry = FIX2INT(y);
+ else {
+ VALUE nth2;
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
+ }
+ }
+ else {
+ decode_year(y, style, nth, ry);
+ r = c_valid_commercial_p(*ry, w, d, style, rw, rd, rjd, ns);
+ }
+ return r;
+}
+
+static int
+valid_weeknum_p(VALUE y, int w, int d, int f, double sg,
+ VALUE *nth, int *ry,
+ int *rw, int *rd, int *rjd,
+ int *ns)
+{
+ double style = guess_style(y, sg);
+ int r;
+
+ if (style == 0) {
+ int jd;
+
+ r = c_valid_weeknum_p(FIX2INT(y), w, d, f, sg, rw, rd, &jd, ns);
+ if (!r)
+ return 0;
+ decode_jd(INT2FIX(jd), nth, rjd);
+ if (f_zero_p(*nth))
+ *ry = FIX2INT(y);
+ else {
+ VALUE nth2;
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
+ }
+ }
+ else {
+ decode_year(y, style, nth, ry);
+ r = c_valid_weeknum_p(*ry, w, d, f, style, rw, rd, rjd, ns);
+ }
+ return r;
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static int
+valid_nth_kday_p(VALUE y, int m, int n, int k, double sg,
+ VALUE *nth, int *ry,
+ int *rm, int *rn, int *rk, int *rjd,
+ int *ns)
+{
+ double style = guess_style(y, sg);
+ int r;
+
+ if (style == 0) {
+ int jd;
+
+ r = c_valid_nth_kday_p(FIX2INT(y), m, n, k, sg, rm, rn, rk, &jd, ns);
+ if (!r)
+ return 0;
+ decode_jd(INT2FIX(jd), nth, rjd);
+ if (f_zero_p(*nth))
+ *ry = FIX2INT(y);
+ else {
+ VALUE nth2;
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
+ }
+ }
+ else {
+ decode_year(y, style, nth, ry);
+ r = c_valid_nth_kday_p(*ry, m, n, k, style, rm, rn, rk, rjd, ns);
+ }
+ return r;
+}
+#endif
+
+VALUE date_zone_to_diff(VALUE);
+
+static int
+offset_to_sec(VALUE vof, int *rof)
+{
+ int try_rational = 1;
+
+ again:
+ switch (TYPE(vof)) {
+ case T_FIXNUM:
+ {
+ long n;
+
+ n = FIX2LONG(vof);
+ if (n != -1 && n != 0 && n != 1)
+ return 0;
+ *rof = (int)n * DAY_IN_SECONDS;
+ return 1;
+ }
+ case T_FLOAT:
+ {
+ double n;
+
+ n = RFLOAT_VALUE(vof) * DAY_IN_SECONDS;
+ if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
+ return 0;
+ *rof = (int)round(n);
+ if (*rof != n)
+ rb_warning("fraction of offset is ignored");
+ return 1;
+ }
+ default:
+ expect_numeric(vof);
+ vof = f_to_r(vof);
+ if (!k_rational_p(vof)) {
+ if (!try_rational) Check_Type(vof, T_RATIONAL);
+ try_rational = 0;
+ goto again;
+ }
+ /* fall through */
+ case T_RATIONAL:
+ {
+ VALUE vs, vn, vd;
+ long n;
+
+ vs = day_to_sec(vof);
+
+ if (!k_rational_p(vs)) {
+ vn = vs;
+ goto rounded;
+ }
+ vn = rb_rational_num(vs);
+ vd = rb_rational_den(vs);
+
+ if (FIXNUM_P(vn) && FIXNUM_P(vd) && (FIX2LONG(vd) == 1))
+ n = FIX2LONG(vn);
+ else {
+ vn = f_round(vs);
+ if (!f_eqeq_p(vn, vs))
+ rb_warning("fraction of offset is ignored");
+ rounded:
+ if (!FIXNUM_P(vn))
+ return 0;
+ n = FIX2LONG(vn);
+ if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
+ return 0;
+ }
+ *rof = (int)n;
+ return 1;
+ }
+ case T_STRING:
+ {
+ VALUE vs = date_zone_to_diff(vof);
+ long n;
+
+ if (!FIXNUM_P(vs))
+ return 0;
+ n = FIX2LONG(vs);
+ if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
+ return 0;
+ *rof = (int)n;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* date */
+
+#define valid_sg(sg) \
+do {\
+ if (!c_valid_start_p(sg)) {\
+ sg = 0;\
+ rb_warning("invalid start is ignored");\
+ }\
+} while (0)
+
+static VALUE
+valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
+{
+ double sg = NUM2DBL(argv[1]);
+ valid_sg(sg);
+ return argv[0];
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vjd, vsg;
+ VALUE argv2[2];
+
+ rb_scan_args(argc, argv, "11", &vjd, &vsg);
+
+ argv2[0] = vjd;
+ if (argc < 2)
+ argv2[1] = DBL2NUM(GREGORIAN);
+ else
+ argv2[1] = vsg;
+
+ return valid_jd_sub(2, argv2, klass, 1);
+}
+#endif
+
+/*
+ * call-seq:
+ * Date.valid_jd?(jd, start = Date::ITALY) -> true
+ *
+ * Implemented for compatibility;
+ * returns +true+ unless +jd+ is invalid (i.e., not a Numeric).
+ *
+ * Date.valid_jd?(2451944) # => true
+ *
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ *
+ * Related: Date.jd.
+ */
+static VALUE
+date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vjd, vsg;
+ VALUE argv2[2];
+
+ rb_scan_args(argc, argv, "11", &vjd, &vsg);
+
+ RETURN_FALSE_UNLESS_NUMERIC(vjd);
+ argv2[0] = vjd;
+ if (argc < 2)
+ argv2[1] = INT2FIX(DEFAULT_SG);
+ else
+ argv2[1] = vsg;
+
+ if (NIL_P(valid_jd_sub(2, argv2, klass, 0)))
+ return Qfalse;
+ return Qtrue;
+}
+
+static VALUE
+valid_civil_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
+{
+ VALUE nth, y;
+ int m, d, ry, rm, rd;
+ double sg;
+
+ y = argv[0];
+ m = NUM2INT(argv[1]);
+ d = NUM2INT(argv[2]);
+ sg = NUM2DBL(argv[3]);
+
+ valid_sg(sg);
+
+ if (!need_jd && (guess_style(y, sg) < 0)) {
+ if (!valid_gregorian_p(y, m, d,
+ &nth, &ry,
+ &rm, &rd))
+ return Qnil;
+ return INT2FIX(0); /* dummy */
+ }
+ else {
+ int rjd, ns;
+ VALUE rjd2;
+
+ if (!valid_civil_p(y, m, d, sg,
+ &nth, &ry,
+ &rm, &rd, &rjd,
+ &ns))
+ return Qnil;
+ if (!need_jd)
+ return INT2FIX(0); /* dummy */
+ encode_jd(nth, rjd, &rjd2);
+ return rjd2;
+ }
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vm, vd, vsg;
+ VALUE argv2[4];
+
+ rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg);
+
+ argv2[0] = vy;
+ argv2[1] = vm;
+ argv2[2] = vd;
+ if (argc < 4)
+ argv2[3] = DBL2NUM(GREGORIAN);
+ else
+ argv2[3] = vsg;
+
+ return valid_civil_sub(4, argv2, klass, 1);
+}
+#endif
+
+/*
+ * call-seq:
+ * Date.valid_civil?(year, month, mday, start = Date::ITALY) -> true or false
+ *
+ * Returns +true+ if the arguments define a valid ordinal date,
+ * +false+ otherwise:
+ *
+ * Date.valid_date?(2001, 2, 3) # => true
+ * Date.valid_date?(2001, 2, 29) # => false
+ * Date.valid_date?(2001, 2, -1) # => true
+ *
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ *
+ * Related: Date.jd, Date.new.
+ */
+static VALUE
+date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vm, vd, vsg;
+ VALUE argv2[4];
+
+ rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg);
+
+ RETURN_FALSE_UNLESS_NUMERIC(vy);
+ RETURN_FALSE_UNLESS_NUMERIC(vm);
+ RETURN_FALSE_UNLESS_NUMERIC(vd);
+ argv2[0] = vy;
+ argv2[1] = vm;
+ argv2[2] = vd;
+ if (argc < 4)
+ argv2[3] = INT2FIX(DEFAULT_SG);
+ else
+ argv2[3] = vsg;
+
+ if (NIL_P(valid_civil_sub(4, argv2, klass, 0)))
+ return Qfalse;
+ return Qtrue;
+}
+
+static VALUE
+valid_ordinal_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
+{
+ VALUE nth, y;
+ int d, ry, rd;
+ double sg;
+
+ y = argv[0];
+ d = NUM2INT(argv[1]);
+ sg = NUM2DBL(argv[2]);
+
+ valid_sg(sg);
+
+ {
+ int rjd, ns;
+ VALUE rjd2;
+
+ if (!valid_ordinal_p(y, d, sg,
+ &nth, &ry,
+ &rd, &rjd,
+ &ns))
+ return Qnil;
+ if (!need_jd)
+ return INT2FIX(0); /* dummy */
+ encode_jd(nth, rjd, &rjd2);
+ return rjd2;
+ }
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vd, vsg;
+ VALUE argv2[3];
+
+ rb_scan_args(argc, argv, "21", &vy, &vd, &vsg);
+
+ argv2[0] = vy;
+ argv2[1] = vd;
+ if (argc < 3)
+ argv2[2] = DBL2NUM(GREGORIAN);
+ else
+ argv2[2] = vsg;
+
+ return valid_ordinal_sub(3, argv2, klass, 1);
+}
+#endif
+
+/*
+ * call-seq:
+ * Date.valid_ordinal?(year, yday, start = Date::ITALY) -> true or false
+ *
+ * Returns +true+ if the arguments define a valid ordinal date,
+ * +false+ otherwise:
+ *
+ * Date.valid_ordinal?(2001, 34) # => true
+ * Date.valid_ordinal?(2001, 366) # => false
+ *
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ *
+ * Related: Date.jd, Date.ordinal.
+ */
+static VALUE
+date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vd, vsg;
+ VALUE argv2[3];
+
+ rb_scan_args(argc, argv, "21", &vy, &vd, &vsg);
+
+ RETURN_FALSE_UNLESS_NUMERIC(vy);
+ RETURN_FALSE_UNLESS_NUMERIC(vd);
+ argv2[0] = vy;
+ argv2[1] = vd;
+ if (argc < 3)
+ argv2[2] = INT2FIX(DEFAULT_SG);
+ else
+ argv2[2] = vsg;
+
+ if (NIL_P(valid_ordinal_sub(3, argv2, klass, 0)))
+ return Qfalse;
+ return Qtrue;
+}
+
+static VALUE
+valid_commercial_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
+{
+ VALUE nth, y;
+ int w, d, ry, rw, rd;
+ double sg;
+
+ y = argv[0];
+ w = NUM2INT(argv[1]);
+ d = NUM2INT(argv[2]);
+ sg = NUM2DBL(argv[3]);
+
+ valid_sg(sg);
+
+ {
+ int rjd, ns;
+ VALUE rjd2;
+
+ if (!valid_commercial_p(y, w, d, sg,
+ &nth, &ry,
+ &rw, &rd, &rjd,
+ &ns))
+ return Qnil;
+ if (!need_jd)
+ return INT2FIX(0); /* dummy */
+ encode_jd(nth, rjd, &rjd2);
+ return rjd2;
+ }
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vw, vd, vsg;
+ VALUE argv2[4];
+
+ rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg);
+
+ argv2[0] = vy;
+ argv2[1] = vw;
+ argv2[2] = vd;
+ if (argc < 4)
+ argv2[3] = DBL2NUM(GREGORIAN);
+ else
+ argv2[3] = vsg;
+
+ return valid_commercial_sub(4, argv2, klass, 1);
+}
+#endif
+
+/*
+ * call-seq:
+ * Date.valid_commercial?(cwyear, cweek, cwday, start = Date::ITALY) -> true or false
+ *
+ * Returns +true+ if the arguments define a valid commercial date,
+ * +false+ otherwise:
+ *
+ * Date.valid_commercial?(2001, 5, 6) # => true
+ * Date.valid_commercial?(2001, 5, 8) # => false
+ *
+ * See Date.commercial.
+ *
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ *
+ * Related: Date.jd, Date.commercial.
+ */
+static VALUE
+date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vw, vd, vsg;
+ VALUE argv2[4];
+
+ rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg);
+
+ RETURN_FALSE_UNLESS_NUMERIC(vy);
+ RETURN_FALSE_UNLESS_NUMERIC(vw);
+ RETURN_FALSE_UNLESS_NUMERIC(vd);
+ argv2[0] = vy;
+ argv2[1] = vw;
+ argv2[2] = vd;
+ if (argc < 4)
+ argv2[3] = INT2FIX(DEFAULT_SG);
+ else
+ argv2[3] = vsg;
+
+ if (NIL_P(valid_commercial_sub(4, argv2, klass, 0)))
+ return Qfalse;
+ return Qtrue;
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+valid_weeknum_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
+{
+ VALUE nth, y;
+ int w, d, f, ry, rw, rd;
+ double sg;
+
+ y = argv[0];
+ w = NUM2INT(argv[1]);
+ d = NUM2INT(argv[2]);
+ f = NUM2INT(argv[3]);
+ sg = NUM2DBL(argv[4]);
+
+ valid_sg(sg);
+
+ {
+ int rjd, ns;
+ VALUE rjd2;
+
+ if (!valid_weeknum_p(y, w, d, f, sg,
+ &nth, &ry,
+ &rw, &rd, &rjd,
+ &ns))
+ return Qnil;
+ if (!need_jd)
+ return INT2FIX(0); /* dummy */
+ encode_jd(nth, rjd, &rjd2);
+ return rjd2;
+ }
+}
+
+/* :nodoc: */
+static VALUE
+date_s__valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vw, vd, vf, vsg;
+ VALUE argv2[5];
+
+ rb_scan_args(argc, argv, "41", &vy, &vw, &vd, &vf, &vsg);
+
+ argv2[0] = vy;
+ argv2[1] = vw;
+ argv2[2] = vd;
+ argv2[3] = vf;
+ if (argc < 5)
+ argv2[4] = DBL2NUM(GREGORIAN);
+ else
+ argv2[4] = vsg;
+
+ return valid_weeknum_sub(5, argv2, klass, 1);
+}
+
+/* :nodoc: */
+static VALUE
+date_s_valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vw, vd, vf, vsg;
+ VALUE argv2[5];
+
+ rb_scan_args(argc, argv, "41", &vy, &vw, &vd, &vf, &vsg);
+
+ argv2[0] = vy;
+ argv2[1] = vw;
+ argv2[2] = vd;
+ argv2[3] = vf;
+ if (argc < 5)
+ argv2[4] = INT2FIX(DEFAULT_SG);
+ else
+ argv2[4] = vsg;
+
+ if (NIL_P(valid_weeknum_sub(5, argv2, klass, 0)))
+ return Qfalse;
+ return Qtrue;
+}
+
+static VALUE
+valid_nth_kday_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
+{
+ VALUE nth, y;
+ int m, n, k, ry, rm, rn, rk;
+ double sg;
+
+ y = argv[0];
+ m = NUM2INT(argv[1]);
+ n = NUM2INT(argv[2]);
+ k = NUM2INT(argv[3]);
+ sg = NUM2DBL(argv[4]);
+
+ {
+ int rjd, ns;
+ VALUE rjd2;
+
+ if (!valid_nth_kday_p(y, m, n, k, sg,
+ &nth, &ry,
+ &rm, &rn, &rk, &rjd,
+ &ns))
+ return Qnil;
+ if (!need_jd)
+ return INT2FIX(0); /* dummy */
+ encode_jd(nth, rjd, &rjd2);
+ return rjd2;
+ }
+}
+
+/* :nodoc: */
+static VALUE
+date_s__valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vm, vn, vk, vsg;
+ VALUE argv2[5];
+
+ rb_scan_args(argc, argv, "41", &vy, &vm, &vn, &vk, &vsg);
+
+ argv2[0] = vy;
+ argv2[1] = vm;
+ argv2[2] = vn;
+ argv2[3] = vk;
+ if (argc < 5)
+ argv2[4] = DBL2NUM(GREGORIAN);
+ else
+ argv2[4] = vsg;
+
+ return valid_nth_kday_sub(5, argv2, klass, 1);
+}
+
+/* :nodoc: */
+static VALUE
+date_s_valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vm, vn, vk, vsg;
+ VALUE argv2[5];
+
+ rb_scan_args(argc, argv, "41", &vy, &vm, &vn, &vk, &vsg);
+
+ argv2[0] = vy;
+ argv2[1] = vm;
+ argv2[2] = vn;
+ argv2[3] = vk;
+ if (argc < 5)
+ argv2[4] = INT2FIX(DEFAULT_SG);
+ else
+ argv2[4] = vsg;
+
+ if (NIL_P(valid_nth_kday_sub(5, argv2, klass, 0)))
+ return Qfalse;
+ return Qtrue;
+}
+
+/* :nodoc: */
+static VALUE
+date_s_zone_to_diff(VALUE klass, VALUE str)
+{
+ return date_zone_to_diff(str);
+}
+#endif
+
+/*
+ * call-seq:
+ * Date.julian_leap?(year) -> true or false
+ *
+ * Returns +true+ if the given year is a leap year
+ * in the {proleptic Julian calendar}[https://en.wikipedia.org/wiki/Proleptic_Julian_calendar], +false+ otherwise:
+ *
+ * Date.julian_leap?(1900) # => true
+ * Date.julian_leap?(1901) # => false
+ *
+ * Related: Date.gregorian_leap?.
+ */
+static VALUE
+date_s_julian_leap_p(VALUE klass, VALUE y)
+{
+ VALUE nth;
+ int ry;
+
+ check_numeric(y, "year");
+ decode_year(y, +1, &nth, &ry);
+ return f_boolcast(c_julian_leap_p(ry));
+}
+
+/*
+ * call-seq:
+ * Date.gregorian_leap?(year) -> true or false
+ *
+ * Returns +true+ if the given year is a leap year
+ * in the {proleptic Gregorian calendar}[https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar], +false+ otherwise:
+ *
+ * Date.gregorian_leap?(2000) # => true
+ * Date.gregorian_leap?(2001) # => false
+ *
+ * Related: Date.julian_leap?.
+ */
+static VALUE
+date_s_gregorian_leap_p(VALUE klass, VALUE y)
+{
+ VALUE nth;
+ int ry;
+
+ check_numeric(y, "year");
+ decode_year(y, -1, &nth, &ry);
+ return f_boolcast(c_gregorian_leap_p(ry));
+}
+
+static void
+d_lite_gc_mark(void *ptr)
+{
+ union DateData *dat = ptr;
+ if (simple_dat_p(dat))
+ rb_gc_mark(dat->s.nth);
+ else {
+ rb_gc_mark(dat->c.nth);
+ rb_gc_mark(dat->c.sf);
+ }
+}
+
+static size_t
+d_lite_memsize(const void *ptr)
+{
+ const union DateData *dat = ptr;
+ return complex_dat_p(dat) ? sizeof(struct ComplexDateData) : sizeof(struct SimpleDateData);
+}
+
+#ifndef HAVE_RB_EXT_RACTOR_SAFE
+# define RUBY_TYPED_FROZEN_SHAREABLE 0
+#endif
+
+static const rb_data_type_t d_lite_type = {
+ "Date",
+ {d_lite_gc_mark, RUBY_TYPED_DEFAULT_FREE, d_lite_memsize,},
+ 0, 0,
+ RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED|RUBY_TYPED_FROZEN_SHAREABLE,
+};
+
+inline static VALUE
+d_simple_new_internal(VALUE klass,
+ VALUE nth, int jd,
+ double sg,
+ int y, int m, int d,
+ unsigned flags)
+{
+ struct SimpleDateData *dat;
+ VALUE obj;
+
+ obj = TypedData_Make_Struct(klass, struct SimpleDateData,
+ &d_lite_type, dat);
+ set_to_simple(obj, dat, nth, jd, sg, y, m, d, flags);
+
+ assert(have_jd_p(dat) || have_civil_p(dat));
+
+ return obj;
+}
+
+inline static VALUE
+d_complex_new_internal(VALUE klass,
+ VALUE nth, int jd,
+ int df, VALUE sf,
+ int of, double sg,
+ int y, int m, int d,
+ int h, int min, int s,
+ unsigned flags)
+{
+ struct ComplexDateData *dat;
+ VALUE obj;
+
+ obj = TypedData_Make_Struct(klass, struct ComplexDateData,
+ &d_lite_type, dat);
+ set_to_complex(obj, dat, nth, jd, df, sf, of, sg,
+ y, m, d, h, min, s, flags);
+
+ assert(have_jd_p(dat) || have_civil_p(dat));
+ assert(have_df_p(dat) || have_time_p(dat));
+
+ return obj;
+}
+
+static VALUE
+d_lite_s_alloc_simple(VALUE klass)
+{
+ return d_simple_new_internal(klass,
+ INT2FIX(0), 0,
+ DEFAULT_SG,
+ 0, 0, 0,
+ HAVE_JD);
+}
+
+static VALUE
+d_lite_s_alloc_complex(VALUE klass)
+{
+ return d_complex_new_internal(klass,
+ INT2FIX(0), 0,
+ 0, INT2FIX(0),
+ 0, DEFAULT_SG,
+ 0, 0, 0,
+ 0, 0, 0,
+ HAVE_JD | HAVE_DF);
+}
+
+static VALUE
+d_lite_s_alloc(VALUE klass)
+{
+ return d_lite_s_alloc_complex(klass);
+}
+
+static void
+old_to_new(VALUE ajd, VALUE of, VALUE sg,
+ VALUE *rnth, int *rjd, int *rdf, VALUE *rsf,
+ int *rof, double *rsg)
+{
+ VALUE jd, df, sf, of2, t;
+
+ decode_day(f_add(ajd, half_days_in_day),
+ &jd, &df, &sf);
+ t = day_to_sec(of);
+ of2 = f_round(t);
+
+ if (!f_eqeq_p(of2, t))
+ rb_warning("fraction of offset is ignored");
+
+ decode_jd(jd, rnth, rjd);
+
+ *rdf = NUM2INT(df);
+ *rsf = sf;
+ *rof = NUM2INT(of2);
+ *rsg = NUM2DBL(sg);
+
+ if (*rdf < 0 || *rdf >= DAY_IN_SECONDS)
+ rb_raise(eDateError, "invalid day fraction");
+
+ if (f_lt_p(*rsf, INT2FIX(0)) ||
+ f_ge_p(*rsf, INT2FIX(SECOND_IN_NANOSECONDS)))
+
+ if (*rof < -DAY_IN_SECONDS || *rof > DAY_IN_SECONDS) {
+ *rof = 0;
+ rb_warning("invalid offset is ignored");
+ }
+
+ if (!c_valid_start_p(*rsg)) {
+ *rsg = DEFAULT_SG;
+ rb_warning("invalid start is ignored");
+ }
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+date_s_new_bang(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE ajd, of, sg, nth, sf;
+ int jd, df, rof;
+ double rsg;
+
+ rb_scan_args(argc, argv, "03", &ajd, &of, &sg);
+
+ switch (argc) {
+ case 0:
+ ajd = INT2FIX(0);
+ case 1:
+ of = INT2FIX(0);
+ case 2:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ old_to_new(ajd, of, sg,
+ &nth, &jd, &df, &sf, &rof, &rsg);
+
+ if (!df && f_zero_p(sf) && !rof)
+ return d_simple_new_internal(klass,
+ nth, jd,
+ rsg,
+ 0, 0, 0,
+ HAVE_JD);
+ else
+ return d_complex_new_internal(klass,
+ nth, jd,
+ df, sf,
+ rof, rsg,
+ 0, 0, 0,
+ 0, 0, 0,
+ HAVE_JD | HAVE_DF);
+}
+#endif
+
+inline static int
+wholenum_p(VALUE x)
+{
+ if (FIXNUM_P(x))
+ return 1;
+ switch (TYPE(x)) {
+ case T_BIGNUM:
+ return 1;
+ case T_FLOAT:
+ {
+ double d = RFLOAT_VALUE(x);
+ return round(d) == d;
+ }
+ break;
+ case T_RATIONAL:
+ {
+ VALUE den = rb_rational_den(x);
+ return FIXNUM_P(den) && FIX2LONG(den) == 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+inline static VALUE
+to_integer(VALUE x)
+{
+ if (RB_INTEGER_TYPE_P(x))
+ return x;
+ return f_to_i(x);
+}
+
+inline static VALUE
+d_trunc(VALUE d, VALUE *fr)
+{
+ VALUE rd;
+
+ if (wholenum_p(d)) {
+ rd = to_integer(d);
+ *fr = INT2FIX(0);
+ }
+ else {
+ rd = f_idiv(d, INT2FIX(1));
+ *fr = f_mod(d, INT2FIX(1));
+ }
+ return rd;
+}
+
+#define jd_trunc d_trunc
+#define k_trunc d_trunc
+
+inline static VALUE
+h_trunc(VALUE h, VALUE *fr)
+{
+ VALUE rh;
+
+ if (wholenum_p(h)) {
+ rh = to_integer(h);
+ *fr = INT2FIX(0);
+ }
+ else {
+ rh = f_idiv(h, INT2FIX(1));
+ *fr = f_mod(h, INT2FIX(1));
+ *fr = f_quo(*fr, INT2FIX(24));
+ }
+ return rh;
+}
+
+inline static VALUE
+min_trunc(VALUE min, VALUE *fr)
+{
+ VALUE rmin;
+
+ if (wholenum_p(min)) {
+ rmin = to_integer(min);
+ *fr = INT2FIX(0);
+ }
+ else {
+ rmin = f_idiv(min, INT2FIX(1));
+ *fr = f_mod(min, INT2FIX(1));
+ *fr = f_quo(*fr, INT2FIX(1440));
+ }
+ return rmin;
+}
+
+inline static VALUE
+s_trunc(VALUE s, VALUE *fr)
+{
+ VALUE rs;
+
+ if (wholenum_p(s)) {
+ rs = to_integer(s);
+ *fr = INT2FIX(0);
+ }
+ else {
+ rs = f_idiv(s, INT2FIX(1));
+ *fr = f_mod(s, INT2FIX(1));
+ *fr = f_quo(*fr, INT2FIX(86400));
+ }
+ return rs;
+}
+
+#define num2num_with_frac(s,n) \
+do {\
+ s = s##_trunc(v##s, &fr);\
+ if (f_nonzero_p(fr)) {\
+ if (argc > n)\
+ rb_raise(eDateError, "invalid fraction");\
+ fr2 = fr;\
+ }\
+} while (0)
+
+#define num2int_with_frac(s,n) \
+do {\
+ s = NUM2INT(s##_trunc(v##s, &fr));\
+ if (f_nonzero_p(fr)) {\
+ if (argc > n)\
+ rb_raise(eDateError, "invalid fraction");\
+ fr2 = fr;\
+ }\
+} while (0)
+
+#define canon24oc() \
+do {\
+ if (rh == 24) {\
+ rh = 0;\
+ fr2 = f_add(fr2, INT2FIX(1));\
+ }\
+} while (0)
+
+#define add_frac() \
+do {\
+ if (f_nonzero_p(fr2))\
+ ret = d_lite_plus(ret, fr2);\
+} while (0)
+
+#define val2sg(vsg,dsg) \
+do {\
+ dsg = NUM2DBL(vsg);\
+ if (!c_valid_start_p(dsg)) {\
+ dsg = DEFAULT_SG;\
+ rb_warning("invalid start is ignored");\
+ }\
+} while (0)
+
+static VALUE d_lite_plus(VALUE, VALUE);
+
+/*
+ * call-seq:
+ * Date.jd(jd = 0, start = Date::ITALY) -> date
+ *
+ * Returns a new \Date object formed from the arguments:
+ *
+ * Date.jd(2451944).to_s # => "2001-02-03"
+ * Date.jd(2451945).to_s # => "2001-02-04"
+ * Date.jd(0).to_s # => "-4712-01-01"
+ *
+ * The returned date is:
+ *
+ * - Gregorian, if the argument is greater than or equal to +start+:
+ *
+ * Date::ITALY # => 2299161
+ * Date.jd(Date::ITALY).gregorian? # => true
+ * Date.jd(Date::ITALY + 1).gregorian? # => true
+ *
+ * - Julian, otherwise
+ *
+ * Date.jd(Date::ITALY - 1).julian? # => true
+ *
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ *
+ * Related: Date.new.
+ */
+static VALUE
+date_s_jd(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vjd, vsg, jd, fr, fr2, ret;
+ double sg;
+
+ rb_scan_args(argc, argv, "02", &vjd, &vsg);
+
+ jd = INT2FIX(0);
+ fr2 = INT2FIX(0);
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 2:
+ val2sg(vsg, sg);
+ case 1:
+ check_numeric(vjd, "jd");
+ num2num_with_frac(jd, positive_inf);
+ }
+
+ {
+ VALUE nth;
+ int rjd;
+
+ decode_jd(jd, &nth, &rjd);
+ ret = d_simple_new_internal(klass,
+ nth, rjd,
+ sg,
+ 0, 0, 0,
+ HAVE_JD);
+ }
+ add_frac();
+ return ret;
+}
+
+/*
+ * call-seq:
+ * Date.ordinal(year = -4712, yday = 1, start = Date::ITALY) -> date
+ *
+ * Returns a new \Date object formed fom the arguments.
+ *
+ * With no arguments, returns the date for January 1, -4712:
+ *
+ * Date.ordinal.to_s # => "-4712-01-01"
+ *
+ * With argument +year+, returns the date for January 1 of that year:
+ *
+ * Date.ordinal(2001).to_s # => "2001-01-01"
+ * Date.ordinal(-2001).to_s # => "-2001-01-01"
+ *
+ * With positive argument +yday+ == +n+,
+ * returns the date for the +nth+ day of the given year:
+ *
+ * Date.ordinal(2001, 14).to_s # => "2001-01-14"
+ *
+ * With negative argument +yday+, counts backward from the end of the year:
+ *
+ * Date.ordinal(2001, -14).to_s # => "2001-12-18"
+ *
+ * Raises an exception if +yday+ is zero or out of range.
+ *
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ *
+ * Related: Date.jd, Date.new.
+ */
+static VALUE
+date_s_ordinal(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vd, vsg, y, fr, fr2, ret;
+ int d;
+ double sg;
+
+ rb_scan_args(argc, argv, "03", &vy, &vd, &vsg);
+
+ y = INT2FIX(-4712);
+ d = 1;
+ fr2 = INT2FIX(0);
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 3:
+ val2sg(vsg, sg);
+ case 2:
+ check_numeric(vd, "yday");
+ num2int_with_frac(d, positive_inf);
+ case 1:
+ check_numeric(vy, "year");
+ y = vy;
+ }
+
+ {
+ VALUE nth;
+ int ry, rd, rjd, ns;
+
+ if (!valid_ordinal_p(y, d, sg,
+ &nth, &ry,
+ &rd, &rjd,
+ &ns))
+ rb_raise(eDateError, "invalid date");
+
+ ret = d_simple_new_internal(klass,
+ nth, rjd,
+ sg,
+ 0, 0, 0,
+ HAVE_JD);
+ }
+ add_frac();
+ return ret;
+}
+
+/*
+ * Same as Date.new.
+ */
+static VALUE
+date_s_civil(int argc, VALUE *argv, VALUE klass)
+{
+ return date_initialize(argc, argv, d_lite_s_alloc_simple(klass));
+}
+
+/*
+ * call-seq:
+ * Date.new(year = -4712, month = 1, mday = 1, start = Date::ITALY) -> date
+ *
+ * Returns a new \Date object constructed from the given arguments:
+ *
+ * Date.new(2022).to_s # => "2022-01-01"
+ * Date.new(2022, 2).to_s # => "2022-02-01"
+ * Date.new(2022, 2, 4).to_s # => "2022-02-04"
+ *
+ * Argument +month+ should be in range (1..12) or range (-12..-1);
+ * when the argument is negative, counts backward from the end of the year:
+ *
+ * Date.new(2022, -11, 4).to_s # => "2022-02-04"
+ *
+ * Argument +mday+ should be in range (1..n) or range (-n..-1)
+ * where +n+ is the number of days in the month;
+ * when the argument is negative, counts backward from the end of the month.
+ *
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ *
+ * Related: Date.jd.
+ */
+static VALUE
+date_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE vy, vm, vd, vsg, y, fr, fr2, ret;
+ int m, d;
+ double sg;
+ struct SimpleDateData *dat = rb_check_typeddata(self, &d_lite_type);
+
+ if (!simple_dat_p(dat)) {
+ rb_raise(rb_eTypeError, "Date expected");
+ }
+
+ rb_scan_args(argc, argv, "04", &vy, &vm, &vd, &vsg);
+
+ y = INT2FIX(-4712);
+ m = 1;
+ d = 1;
+ fr2 = INT2FIX(0);
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 4:
+ val2sg(vsg, sg);
+ case 3:
+ check_numeric(vd, "day");
+ num2int_with_frac(d, positive_inf);
+ case 2:
+ check_numeric(vm, "month");
+ m = NUM2INT(vm);
+ case 1:
+ check_numeric(vy, "year");
+ y = vy;
+ }
+
+ if (guess_style(y, sg) < 0) {
+ VALUE nth;
+ int ry, rm, rd;
+
+ if (!valid_gregorian_p(y, m, d,
+ &nth, &ry,
+ &rm, &rd))
+ rb_raise(eDateError, "invalid date");
+
+ set_to_simple(self, dat, nth, 0, sg, ry, rm, rd, HAVE_CIVIL);
+ }
+ else {
+ VALUE nth;
+ int ry, rm, rd, rjd, ns;
+
+ if (!valid_civil_p(y, m, d, sg,
+ &nth, &ry,
+ &rm, &rd, &rjd,
+ &ns))
+ rb_raise(eDateError, "invalid date");
+
+ set_to_simple(self, dat, nth, rjd, sg, ry, rm, rd, HAVE_JD | HAVE_CIVIL);
+ }
+ ret = self;
+ add_frac();
+ return ret;
+}
+
+/*
+ * call-seq:
+ * Date.commercial(cwyear = -4712, cweek = 1, cwday = 1, start = Date::ITALY) -> date
+ *
+ * Returns a new \Date object constructed from the arguments.
+ *
+ * Argument +cwyear+ gives the year, and should be an integer.
+ *
+ * Argument +cweek+ gives the index of the week within the year,
+ * and should be in range (1..53) or (-53..-1);
+ * in some years, 53 or -53 will be out-of-range;
+ * if negative, counts backward from the end of the year:
+ *
+ * Date.commercial(2022, 1, 1).to_s # => "2022-01-03"
+ * Date.commercial(2022, 52, 1).to_s # => "2022-12-26"
+ *
+ * Argument +cwday+ gives the indes of the weekday within the week,
+ * and should be in range (1..7) or (-7..-1);
+ * 1 or -7 is Monday;
+ * if negative, counts backward from the end of the week:
+ *
+ * Date.commercial(2022, 1, 1).to_s # => "2022-01-03"
+ * Date.commercial(2022, 1, -7).to_s # => "2022-01-03"
+ *
+ * When +cweek+ is 1:
+ *
+ * - If January 1 is a Friday, Saturday, or Sunday,
+ * the first week begins in the week after:
+ *
+ * Date::ABBR_DAYNAMES[Date.new(2023, 1, 1).wday] # => "Sun"
+ * Date.commercial(2023, 1, 1).to_s # => "2023-01-02"
+ Date.commercial(2023, 1, 7).to_s # => "2023-01-08"
+ *
+ * - Otherwise, the first week is the week of January 1,
+ * which may mean some of the days fall on the year before:
+ *
+ * Date::ABBR_DAYNAMES[Date.new(2020, 1, 1).wday] # => "Wed"
+ * Date.commercial(2020, 1, 1).to_s # => "2019-12-30"
+ Date.commercial(2020, 1, 7).to_s # => "2020-01-05"
+ *
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ *
+ * Related: Date.jd, Date.new, Date.ordinal.
+ */
+static VALUE
+date_s_commercial(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vw, vd, vsg, y, fr, fr2, ret;
+ int w, d;
+ double sg;
+
+ rb_scan_args(argc, argv, "04", &vy, &vw, &vd, &vsg);
+
+ y = INT2FIX(-4712);
+ w = 1;
+ d = 1;
+ fr2 = INT2FIX(0);
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 4:
+ val2sg(vsg, sg);
+ case 3:
+ check_numeric(vd, "cwday");
+ num2int_with_frac(d, positive_inf);
+ case 2:
+ check_numeric(vw, "cweek");
+ w = NUM2INT(vw);
+ case 1:
+ check_numeric(vy, "year");
+ y = vy;
+ }
+
+ {
+ VALUE nth;
+ int ry, rw, rd, rjd, ns;
+
+ if (!valid_commercial_p(y, w, d, sg,
+ &nth, &ry,
+ &rw, &rd, &rjd,
+ &ns))
+ rb_raise(eDateError, "invalid date");
+
+ ret = d_simple_new_internal(klass,
+ nth, rjd,
+ sg,
+ 0, 0, 0,
+ HAVE_JD);
+ }
+ add_frac();
+ return ret;
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+date_s_weeknum(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vw, vd, vf, vsg, y, fr, fr2, ret;
+ int w, d, f;
+ double sg;
+
+ rb_scan_args(argc, argv, "05", &vy, &vw, &vd, &vf, &vsg);
+
+ y = INT2FIX(-4712);
+ w = 0;
+ d = 1;
+ f = 0;
+ fr2 = INT2FIX(0);
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 5:
+ val2sg(vsg, sg);
+ case 4:
+ f = NUM2INT(vf);
+ case 3:
+ num2int_with_frac(d, positive_inf);
+ case 2:
+ w = NUM2INT(vw);
+ case 1:
+ y = vy;
+ }
+
+ {
+ VALUE nth;
+ int ry, rw, rd, rjd, ns;
+
+ if (!valid_weeknum_p(y, w, d, f, sg,
+ &nth, &ry,
+ &rw, &rd, &rjd,
+ &ns))
+ rb_raise(eDateError, "invalid date");
+
+ ret = d_simple_new_internal(klass,
+ nth, rjd,
+ sg,
+ 0, 0, 0,
+ HAVE_JD);
+ }
+ add_frac();
+ return ret;
+}
+
+/* :nodoc: */
+static VALUE
+date_s_nth_kday(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vm, vn, vk, vsg, y, fr, fr2, ret;
+ int m, n, k;
+ double sg;
+
+ rb_scan_args(argc, argv, "05", &vy, &vm, &vn, &vk, &vsg);
+
+ y = INT2FIX(-4712);
+ m = 1;
+ n = 1;
+ k = 1;
+ fr2 = INT2FIX(0);
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 5:
+ val2sg(vsg, sg);
+ case 4:
+ num2int_with_frac(k, positive_inf);
+ case 3:
+ n = NUM2INT(vn);
+ case 2:
+ m = NUM2INT(vm);
+ case 1:
+ y = vy;
+ }
+
+ {
+ VALUE nth;
+ int ry, rm, rn, rk, rjd, ns;
+
+ if (!valid_nth_kday_p(y, m, n, k, sg,
+ &nth, &ry,
+ &rm, &rn, &rk, &rjd,
+ &ns))
+ rb_raise(eDateError, "invalid date");
+
+ ret = d_simple_new_internal(klass,
+ nth, rjd,
+ sg,
+ 0, 0, 0,
+ HAVE_JD);
+ }
+ add_frac();
+ return ret;
+}
+#endif
+
+#if !defined(HAVE_GMTIME_R)
+static struct tm*
+gmtime_r(const time_t *t, struct tm *tm)
+{
+ auto struct tm *tmp = gmtime(t);
+ if (tmp)
+ *tm = *tmp;
+ return tmp;
+}
+
+static struct tm*
+localtime_r(const time_t *t, struct tm *tm)
+{
+ auto struct tm *tmp = localtime(t);
+ if (tmp)
+ *tm = *tmp;
+ return tmp;
+}
+#endif
+
+static void set_sg(union DateData *, double);
+
+/*
+ * call-seq:
+ * Date.today(start = Date::ITALY) -> date
+ *
+ * Returns a new \Date object constructed from the present date:
+ *
+ * Date.today.to_s # => "2022-07-06"
+ *
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ *
+ */
+static VALUE
+date_s_today(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vsg, nth, ret;
+ double sg;
+ time_t t;
+ struct tm tm;
+ int y, ry, m, d;
+
+ rb_scan_args(argc, argv, "01", &vsg);
+
+ if (argc < 1)
+ sg = DEFAULT_SG;
+ else
+ val2sg(vsg, sg);
+
+ if (time(&t) == -1)
+ rb_sys_fail("time");
+ tzset();
+ if (!localtime_r(&t, &tm))
+ rb_sys_fail("localtime");
+
+ y = tm.tm_year + 1900;
+ m = tm.tm_mon + 1;
+ d = tm.tm_mday;
+
+ decode_year(INT2FIX(y), -1, &nth, &ry);
+
+ ret = d_simple_new_internal(klass,
+ nth, 0,
+ GREGORIAN,
+ ry, m, d,
+ HAVE_CIVIL);
+ {
+ get_d1(ret);
+ set_sg(dat, sg);
+ }
+ return ret;
+}
+
+#define set_hash0(k,v) rb_hash_aset(hash, k, v)
+#define ref_hash0(k) rb_hash_aref(hash, k)
+#define del_hash0(k) rb_hash_delete(hash, k)
+
+#define sym(x) ID2SYM(rb_intern(x""))
+
+#define set_hash(k,v) set_hash0(sym(k), v)
+#define ref_hash(k) ref_hash0(sym(k))
+#define del_hash(k) del_hash0(sym(k))
+
+static VALUE
+rt_rewrite_frags(VALUE hash)
+{
+ VALUE seconds;
+
+ seconds = del_hash("seconds");
+ if (!NIL_P(seconds)) {
+ VALUE offset, d, h, min, s, fr;
+
+ offset = ref_hash("offset");
+ if (!NIL_P(offset))
+ seconds = f_add(seconds, offset);
+
+ d = f_idiv(seconds, INT2FIX(DAY_IN_SECONDS));
+ fr = f_mod(seconds, INT2FIX(DAY_IN_SECONDS));
+
+ h = f_idiv(fr, INT2FIX(HOUR_IN_SECONDS));
+ fr = f_mod(fr, INT2FIX(HOUR_IN_SECONDS));
+
+ min = f_idiv(fr, INT2FIX(MINUTE_IN_SECONDS));
+ fr = f_mod(fr, INT2FIX(MINUTE_IN_SECONDS));
+
+ s = f_idiv(fr, INT2FIX(1));
+ fr = f_mod(fr, INT2FIX(1));
+
+ set_hash("jd", f_add(UNIX_EPOCH_IN_CJD, d));
+ set_hash("hour", h);
+ set_hash("min", min);
+ set_hash("sec", s);
+ set_hash("sec_fraction", fr);
+ }
+ return hash;
+}
+
+static VALUE d_lite_year(VALUE);
+static VALUE d_lite_wday(VALUE);
+static VALUE d_lite_jd(VALUE);
+
+static VALUE
+rt_complete_frags(VALUE klass, VALUE hash)
+{
+ static VALUE tab = Qnil;
+ long e;
+ VALUE k, a, d;
+
+ if (NIL_P(tab)) {
+ tab = f_frozen_ary(11,
+ f_frozen_ary(2,
+ sym("time"),
+ f_frozen_ary(3,
+ sym("hour"),
+ sym("min"),
+ sym("sec"))),
+ f_frozen_ary(2,
+ Qnil,
+ f_frozen_ary(1,
+ sym("jd"))),
+ f_frozen_ary(2,
+ sym("ordinal"),
+ f_frozen_ary(5,
+ sym("year"),
+ sym("yday"),
+ sym("hour"),
+ sym("min"),
+ sym("sec"))),
+ f_frozen_ary(2,
+ sym("civil"),
+ f_frozen_ary(6,
+ sym("year"),
+ sym("mon"),
+ sym("mday"),
+ sym("hour"),
+ sym("min"),
+ sym("sec"))),
+ f_frozen_ary(2,
+ sym("commercial"),
+ f_frozen_ary(6,
+ sym("cwyear"),
+ sym("cweek"),
+ sym("cwday"),
+ sym("hour"),
+ sym("min"),
+ sym("sec"))),
+ f_frozen_ary(2,
+ sym("wday"),
+ f_frozen_ary(4,
+ sym("wday"),
+ sym("hour"),
+ sym("min"),
+ sym("sec"))),
+ f_frozen_ary(2,
+ sym("wnum0"),
+ f_frozen_ary(6,
+ sym("year"),
+ sym("wnum0"),
+ sym("wday"),
+ sym("hour"),
+ sym("min"),
+ sym("sec"))),
+ f_frozen_ary(2,
+ sym("wnum1"),
+ f_frozen_ary(6,
+ sym("year"),
+ sym("wnum1"),
+ sym("wday"),
+ sym("hour"),
+ sym("min"),
+ sym("sec"))),
+ f_frozen_ary(2,
+ Qnil,
+ f_frozen_ary(6,
+ sym("cwyear"),
+ sym("cweek"),
+ sym("wday"),
+ sym("hour"),
+ sym("min"),
+ sym("sec"))),
+ f_frozen_ary(2,
+ Qnil,
+ f_frozen_ary(6,
+ sym("year"),
+ sym("wnum0"),
+ sym("cwday"),
+ sym("hour"),
+ sym("min"),
+ sym("sec"))),
+ f_frozen_ary(2,
+ Qnil,
+ f_frozen_ary(6,
+ sym("year"),
+ sym("wnum1"),
+ sym("cwday"),
+ sym("hour"),
+ sym("min"),
+ sym("sec"))));
+ rb_gc_register_mark_object(tab);
+ }
+
+ k = a = Qnil;
+
+ {
+ long i, eno = 0;
+ VALUE t = Qnil;
+
+ e = 0;
+ for (i = 0; i < RARRAY_LEN(tab); i++) {
+ VALUE x, a;
+
+ x = RARRAY_AREF(tab, i);
+ a = RARRAY_AREF(x, 1);
+
+ {
+ long j, n = 0;
+
+ for (j = 0; j < RARRAY_LEN(a); j++)
+ if (!NIL_P(ref_hash0(RARRAY_AREF(a, j))))
+ n++;
+ if (n > eno) {
+ eno = n;
+ t = x;
+ }
+ }
+ }
+ if (eno > 0) {
+ k = RARRAY_AREF(t, 0);
+ a = RARRAY_AREF(t, 1);
+ }
+ e = eno;
+ }
+
+ d = Qnil;
+
+ if (!NIL_P(k) && (RARRAY_LEN(a) > e)) {
+ if (k == sym("ordinal")) {
+ if (NIL_P(ref_hash("year"))) {
+ if (NIL_P(d))
+ d = date_s_today(0, (VALUE *)0, cDate);
+ set_hash("year", d_lite_year(d));
+ }
+ if (NIL_P(ref_hash("yday")))
+ set_hash("yday", INT2FIX(1));
+ }
+ else if (k == sym("civil")) {
+ long i;
+
+ for (i = 0; i < RARRAY_LEN(a); i++) {
+ VALUE e = RARRAY_AREF(a, i);
+
+ if (!NIL_P(ref_hash0(e)))
+ break;
+ if (NIL_P(d))
+ d = date_s_today(0, (VALUE *)0, cDate);
+ set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
+ }
+ if (NIL_P(ref_hash("mon")))
+ set_hash("mon", INT2FIX(1));
+ if (NIL_P(ref_hash("mday")))
+ set_hash("mday", INT2FIX(1));
+ }
+ else if (k == sym("commercial")) {
+ long i;
+
+ for (i = 0; i < RARRAY_LEN(a); i++) {
+ VALUE e = RARRAY_AREF(a, i);
+
+ if (!NIL_P(ref_hash0(e)))
+ break;
+ if (NIL_P(d))
+ d = date_s_today(0, (VALUE *)0, cDate);
+ set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
+ }
+ if (NIL_P(ref_hash("cweek")))
+ set_hash("cweek", INT2FIX(1));
+ if (NIL_P(ref_hash("cwday")))
+ set_hash("cwday", INT2FIX(1));
+ }
+ else if (k == sym("wday")) {
+ if (NIL_P(d))
+ d = date_s_today(0, (VALUE *)0, cDate);
+ set_hash("jd", d_lite_jd(f_add(f_sub(d,
+ d_lite_wday(d)),
+ ref_hash("wday"))));
+ }
+ else if (k == sym("wnum0")) {
+ long i;
+
+ for (i = 0; i < RARRAY_LEN(a); i++) {
+ VALUE e = RARRAY_AREF(a, i);
+
+ if (!NIL_P(ref_hash0(e)))
+ break;
+ if (NIL_P(d))
+ d = date_s_today(0, (VALUE *)0, cDate);
+ set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
+ }
+ if (NIL_P(ref_hash("wnum0")))
+ set_hash("wnum0", INT2FIX(0));
+ if (NIL_P(ref_hash("wday")))
+ set_hash("wday", INT2FIX(0));
+ }
+ else if (k == sym("wnum1")) {
+ long i;
+
+ for (i = 0; i < RARRAY_LEN(a); i++) {
+ VALUE e = RARRAY_AREF(a, i);
+
+ if (!NIL_P(ref_hash0(e)))
+ break;
+ if (NIL_P(d))
+ d = date_s_today(0, (VALUE *)0, cDate);
+ set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
+ }
+ if (NIL_P(ref_hash("wnum1")))
+ set_hash("wnum1", INT2FIX(0));
+ if (NIL_P(ref_hash("wday")))
+ set_hash("wday", INT2FIX(1));
+ }
+ }
+
+ if (k == sym("time")) {
+ if (f_le_p(klass, cDateTime)) {
+ if (NIL_P(d))
+ d = date_s_today(0, (VALUE *)0, cDate);
+ if (NIL_P(ref_hash("jd")))
+ set_hash("jd", d_lite_jd(d));
+ }
+ }
+
+ if (NIL_P(ref_hash("hour")))
+ set_hash("hour", INT2FIX(0));
+ if (NIL_P(ref_hash("min")))
+ set_hash("min", INT2FIX(0));
+ if (NIL_P(ref_hash("sec")))
+ set_hash("sec", INT2FIX(0));
+ else if (f_gt_p(ref_hash("sec"), INT2FIX(59)))
+ set_hash("sec", INT2FIX(59));
+
+ return hash;
+}
+
+static VALUE
+rt__valid_jd_p(VALUE jd, VALUE sg)
+{
+ return jd;
+}
+
+static VALUE
+rt__valid_ordinal_p(VALUE y, VALUE d, VALUE sg)
+{
+ VALUE nth, rjd2;
+ int ry, rd, rjd, ns;
+
+ if (!valid_ordinal_p(y, NUM2INT(d), NUM2DBL(sg),
+ &nth, &ry,
+ &rd, &rjd,
+ &ns))
+ return Qnil;
+ encode_jd(nth, rjd, &rjd2);
+ return rjd2;
+}
+
+static VALUE
+rt__valid_civil_p(VALUE y, VALUE m, VALUE d, VALUE sg)
+{
+ VALUE nth, rjd2;
+ int ry, rm, rd, rjd, ns;
+
+ if (!valid_civil_p(y, NUM2INT(m), NUM2INT(d), NUM2DBL(sg),
+ &nth, &ry,
+ &rm, &rd, &rjd,
+ &ns))
+ return Qnil;
+ encode_jd(nth, rjd, &rjd2);
+ return rjd2;
+}
+
+static VALUE
+rt__valid_commercial_p(VALUE y, VALUE w, VALUE d, VALUE sg)
+{
+ VALUE nth, rjd2;
+ int ry, rw, rd, rjd, ns;
+
+ if (!valid_commercial_p(y, NUM2INT(w), NUM2INT(d), NUM2DBL(sg),
+ &nth, &ry,
+ &rw, &rd, &rjd,
+ &ns))
+ return Qnil;
+ encode_jd(nth, rjd, &rjd2);
+ return rjd2;
+}
+
+static VALUE
+rt__valid_weeknum_p(VALUE y, VALUE w, VALUE d, VALUE f, VALUE sg)
+{
+ VALUE nth, rjd2;
+ int ry, rw, rd, rjd, ns;
+
+ if (!valid_weeknum_p(y, NUM2INT(w), NUM2INT(d), NUM2INT(f), NUM2DBL(sg),
+ &nth, &ry,
+ &rw, &rd, &rjd,
+ &ns))
+ return Qnil;
+ encode_jd(nth, rjd, &rjd2);
+ return rjd2;
+}
+
+static VALUE
+rt__valid_date_frags_p(VALUE hash, VALUE sg)
+{
+ {
+ VALUE vjd;
+
+ if (!NIL_P(vjd = ref_hash("jd"))) {
+ VALUE jd = rt__valid_jd_p(vjd, sg);
+ if (!NIL_P(jd))
+ return jd;
+ }
+ }
+
+ {
+ VALUE year, yday;
+
+ if (!NIL_P(yday = ref_hash("yday")) &&
+ !NIL_P(year = ref_hash("year"))) {
+ VALUE jd = rt__valid_ordinal_p(year, yday, sg);
+ if (!NIL_P(jd))
+ return jd;
+ }
+ }
+
+ {
+ VALUE year, mon, mday;
+
+ if (!NIL_P(mday = ref_hash("mday")) &&
+ !NIL_P(mon = ref_hash("mon")) &&
+ !NIL_P(year = ref_hash("year"))) {
+ VALUE jd = rt__valid_civil_p(year, mon, mday, sg);
+ if (!NIL_P(jd))
+ return jd;
+ }
+ }
+
+ {
+ VALUE year, week, wday;
+
+ wday = ref_hash("cwday");
+ if (NIL_P(wday)) {
+ wday = ref_hash("wday");
+ if (!NIL_P(wday))
+ if (f_zero_p(wday))
+ wday = INT2FIX(7);
+ }
+
+ if (!NIL_P(wday) &&
+ !NIL_P(week = ref_hash("cweek")) &&
+ !NIL_P(year = ref_hash("cwyear"))) {
+ VALUE jd = rt__valid_commercial_p(year, week, wday, sg);
+ if (!NIL_P(jd))
+ return jd;
+ }
+ }
+
+ {
+ VALUE year, week, wday;
+
+ wday = ref_hash("wday");
+ if (NIL_P(wday)) {
+ wday = ref_hash("cwday");
+ if (!NIL_P(wday))
+ if (f_eqeq_p(wday, INT2FIX(7)))
+ wday = INT2FIX(0);
+ }
+
+ if (!NIL_P(wday) &&
+ !NIL_P(week = ref_hash("wnum0")) &&
+ !NIL_P(year = ref_hash("year"))) {
+ VALUE jd = rt__valid_weeknum_p(year, week, wday, INT2FIX(0), sg);
+ if (!NIL_P(jd))
+ return jd;
+ }
+ }
+
+ {
+ VALUE year, week, wday;
+
+ wday = ref_hash("wday");
+ if (NIL_P(wday))
+ wday = ref_hash("cwday");
+ if (!NIL_P(wday))
+ wday = f_mod(f_sub(wday, INT2FIX(1)),
+ INT2FIX(7));
+
+ if (!NIL_P(wday) &&
+ !NIL_P(week = ref_hash("wnum1")) &&
+ !NIL_P(year = ref_hash("year"))) {
+ VALUE jd = rt__valid_weeknum_p(year, week, wday, INT2FIX(1), sg);
+ if (!NIL_P(jd))
+ return jd;
+ }
+ }
+ return Qnil;
+}
+
+static VALUE
+d_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
+{
+ VALUE jd;
+
+ if (!c_valid_start_p(NUM2DBL(sg))) {
+ sg = INT2FIX(DEFAULT_SG);
+ rb_warning("invalid start is ignored");
+ }
+
+ if (NIL_P(hash))
+ rb_raise(eDateError, "invalid date");
+
+ if (NIL_P(ref_hash("jd")) &&
+ NIL_P(ref_hash("yday")) &&
+ !NIL_P(ref_hash("year")) &&
+ !NIL_P(ref_hash("mon")) &&
+ !NIL_P(ref_hash("mday")))
+ jd = rt__valid_civil_p(ref_hash("year"),
+ ref_hash("mon"),
+ ref_hash("mday"), sg);
+ else {
+ hash = rt_rewrite_frags(hash);
+ hash = rt_complete_frags(klass, hash);
+ jd = rt__valid_date_frags_p(hash, sg);
+ }
+
+ if (NIL_P(jd))
+ rb_raise(eDateError, "invalid date");
+ {
+ VALUE nth;
+ int rjd;
+
+ decode_jd(jd, &nth, &rjd);
+ return d_simple_new_internal(klass,
+ nth, rjd,
+ NUM2DBL(sg),
+ 0, 0, 0,
+ HAVE_JD);
+ }
+}
+
+VALUE date__strptime(const char *str, size_t slen,
+ const char *fmt, size_t flen, VALUE hash);
+
+static VALUE
+date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
+ const char *default_fmt)
+{
+ VALUE vstr, vfmt, hash;
+ const char *str, *fmt;
+ size_t slen, flen;
+
+ rb_scan_args(argc, argv, "11", &vstr, &vfmt);
+
+ StringValue(vstr);
+ if (argc > 1) StringValue(vfmt);
+ if (!rb_enc_str_asciicompat_p(vstr))
+ rb_raise(rb_eArgError,
+ "string should have ASCII compatible encoding");
+ str = RSTRING_PTR(vstr);
+ slen = RSTRING_LEN(vstr);
+ if (argc < 2) {
+ fmt = default_fmt;
+ flen = strlen(default_fmt);
+ }
+ else {
+ if (!rb_enc_str_asciicompat_p(vfmt))
+ rb_raise(rb_eArgError,
+ "format should have ASCII compatible encoding");
+ fmt = RSTRING_PTR(vfmt);
+ flen = RSTRING_LEN(vfmt);
+ }
+ hash = rb_hash_new();
+ if (NIL_P(date__strptime(str, slen, fmt, flen, hash)))
+ return Qnil;
+
+ {
+ VALUE zone = ref_hash("zone");
+ VALUE left = ref_hash("leftover");
+
+ if (!NIL_P(zone)) {
+ rb_enc_copy(zone, vstr);
+ set_hash("zone", zone);
+ }
+ if (!NIL_P(left)) {
+ rb_enc_copy(left, vstr);
+ set_hash("leftover", left);
+ }
+ }
+
+ return hash;
+}
+
+/*
+ * call-seq:
+ * Date._strptime(string, format = '%F') -> hash
+ *
+ * Returns a hash of values parsed from +string+
+ * according to the given +format+:
+ *
+ * Date._strptime('2001-02-03', '%Y-%m-%d') # => {:year=>2001, :mon=>2, :mday=>3}
+ *
+ * For other formats, see
+ * {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc].
+ * (Unlike Date.strftime, does not support flags and width.)
+ *
+ * See also {strptime(3)}[https://man7.org/linux/man-pages/man3/strptime.3.html].
+ *
+ * Related: Date.strptime (returns a \Date object).
+ */
+static VALUE
+date_s__strptime(int argc, VALUE *argv, VALUE klass)
+{
+ return date_s__strptime_internal(argc, argv, klass, "%F");
+}
+
+/*
+ * call-seq:
+ * Date.strptime(string = '-4712-01-01', format = '%F', start = Date::ITALY) -> date
+ *
+ * Returns a new \Date object with values parsed from +string+,
+ * according to the given +format+:
+ *
+ * Date.strptime('2001-02-03', '%Y-%m-%d') # => #<Date: 2001-02-03>
+ * Date.strptime('03-02-2001', '%d-%m-%Y') # => #<Date: 2001-02-03>
+ * Date.strptime('2001-034', '%Y-%j') # => #<Date: 2001-02-03>
+ * Date.strptime('2001-W05-6', '%G-W%V-%u') # => #<Date: 2001-02-03>
+ * Date.strptime('2001 04 6', '%Y %U %w') # => #<Date: 2001-02-03>
+ * Date.strptime('2001 05 6', '%Y %W %u') # => #<Date: 2001-02-03>
+ * Date.strptime('sat3feb01', '%a%d%b%y') # => #<Date: 2001-02-03>
+ *
+ * For other formats, see
+ * {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc].
+ * (Unlike Date.strftime, does not support flags and width.)
+ *
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ *
+ * See also {strptime(3)}[https://man7.org/linux/man-pages/man3/strptime.3.html].
+ *
+ * Related: Date._strptime (returns a hash).
+ */
+static VALUE
+date_s_strptime(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, fmt, sg;
+
+ rb_scan_args(argc, argv, "03", &str, &fmt, &sg);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATE);
+ case 1:
+ fmt = rb_str_new2("%F");
+ case 2:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ VALUE argv2[2], hash;
+
+ argv2[0] = str;
+ argv2[1] = fmt;
+ hash = date_s__strptime(2, argv2, klass);
+ return d_new_by_frags(klass, hash, sg);
+ }
+}
+
+VALUE date__parse(VALUE str, VALUE comp);
+
+static size_t
+get_limit(VALUE opt)
+{
+ if (!NIL_P(opt)) {
+ VALUE limit = rb_hash_aref(opt, ID2SYM(rb_intern("limit")));
+ if (NIL_P(limit)) return SIZE_MAX;
+ return NUM2SIZET(limit);
+ }
+ return 128;
+}
+
+#ifndef HAVE_RB_CATEGORY_WARN
+#define rb_category_warn(category, fmt) rb_warn(fmt)
+#endif
+
+static VALUE
+check_limit(VALUE str, VALUE opt)
+{
+ size_t slen, limit;
+ StringValue(str);
+ slen = RSTRING_LEN(str);
+ limit = get_limit(opt);
+ if (slen > limit) {
+ rb_raise(rb_eArgError,
+ "string length (%"PRI_SIZE_PREFIX"u) exceeds the limit %"PRI_SIZE_PREFIX"u", slen, limit);
+ }
+ return str;
+}
+
+static VALUE
+date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vstr, vcomp, hash, opt;
+
+ argc = rb_scan_args(argc, argv, "11:", &vstr, &vcomp, &opt);
+ vstr = check_limit(vstr, opt);
+ if (!rb_enc_str_asciicompat_p(vstr))
+ rb_raise(rb_eArgError,
+ "string should have ASCII compatible encoding");
+ if (argc < 2)
+ vcomp = Qtrue;
+
+ hash = date__parse(vstr, vcomp);
+
+ return hash;
+}
+
+/*
+ * call-seq:
+ * Date._parse(string, comp = true, limit: 128) -> hash
+ *
+ * <b>Note</b>:
+ * This method recognizes many forms in +string+,
+ * but it is not a validator.
+ * For formats, see
+ * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc@Specialized+Format+Strings]
+ *
+ * If +string+ does not specify a valid date,
+ * the result is unpredictable;
+ * consider using Date._strptime instead.
+ *
+ * Returns a hash of values parsed from +string+:
+ *
+ * Date._parse('2001-02-03') # => {:year=>2001, :mon=>2, :mday=>3}
+ *
+ * If +comp+ is +true+ and the given year is in the range <tt>(0..99)</tt>,
+ * the current century is supplied;
+ * otherwise, the year is taken as given:
+ *
+ * Date._parse('01-02-03', true) # => {:year=>2001, :mon=>2, :mday=>3}
+ * Date._parse('01-02-03', false) # => {:year=>1, :mon=>2, :mday=>3}
+ *
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date.parse(returns a \Date object).
+ */
+static VALUE
+date_s__parse(int argc, VALUE *argv, VALUE klass)
+{
+ return date_s__parse_internal(argc, argv, klass);
+}
+
+/*
+ * call-seq:
+ * Date.parse(string = '-4712-01-01', comp = true, start = Date::ITALY, limit: 128) -> date
+ *
+ * <b>Note</b>:
+ * This method recognizes many forms in +string+,
+ * but it is not a validator.
+ * For formats, see
+ * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc@Specialized+Format+Strings]
+ * If +string+ does not specify a valid date,
+ * the result is unpredictable;
+ * consider using Date._strptime instead.
+ *
+ * Returns a new \Date object with values parsed from +string+:
+ *
+ * Date.parse('2001-02-03') # => #<Date: 2001-02-03>
+ * Date.parse('20010203') # => #<Date: 2001-02-03>
+ * Date.parse('3rd Feb 2001') # => #<Date: 2001-02-03>
+ *
+ * If +comp+ is +true+ and the given year is in the range <tt>(0..99)</tt>,
+ * the current century is supplied;
+ * otherwise, the year is taken as given:
+ *
+ * Date.parse('01-02-03', true) # => #<Date: 2001-02-03>
+ * Date.parse('01-02-03', false) # => #<Date: 0001-02-03>
+ *
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._parse (returns a hash).
+ */
+static VALUE
+date_s_parse(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, comp, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATE);
+ case 1:
+ comp = Qtrue;
+ case 2:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 2;
+ VALUE argv2[3], hash;
+ argv2[0] = str;
+ argv2[1] = comp;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__parse(argc2, argv2, klass);
+ return d_new_by_frags(klass, hash, sg);
+ }
+}
+
+VALUE date__iso8601(VALUE);
+VALUE date__rfc3339(VALUE);
+VALUE date__xmlschema(VALUE);
+VALUE date__rfc2822(VALUE);
+VALUE date__httpdate(VALUE);
+VALUE date__jisx0301(VALUE);
+
+/*
+ * call-seq:
+ * Date._iso8601(string, limit: 128) -> hash
+ *
+ * Returns a hash of values parsed from +string+, which should contain
+ * an {ISO 8601 formatted date}[rdoc-ref:language/strftime_formatting.rdoc@ISO+8601+Format+Specifications]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.iso8601 # => "2001-02-03"
+ * Date._iso8601(s) # => {:mday=>3, :year=>2001, :mon=>2}
+ *
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date.iso8601 (returns a \Date object).
+ */
+static VALUE
+date_s__iso8601(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ if (!NIL_P(str)) str = check_limit(str, opt);
+
+ return date__iso8601(str);
+}
+
+/*
+ * call-seq:
+ * Date.iso8601(string = '-4712-01-01', start = Date::ITALY, limit: 128) -> date
+ *
+ * Returns a new \Date object with values parsed from +string+,
+ * which should contain
+ * an {ISO 8601 formatted date}[rdoc-ref:language/strftime_formatting.rdoc@ISO+8601+Format+Specifications]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.iso8601 # => "2001-02-03"
+ * Date.iso8601(s) # => #<Date: 2001-02-03>
+ *
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._iso8601 (returns a hash).
+ */
+static VALUE
+date_s_iso8601(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATE);
+ case 1:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__iso8601(argc2, argv2, klass);
+ return d_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * Date._rfc3339(string, limit: 128) -> hash
+ *
+ * Returns a hash of values parsed from +string+, which should be a valid
+ * {RFC 3339 format}[rdoc-ref:language/strftime_formatting.rdoc@RFC+3339+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.rfc3339 # => "2001-02-03T00:00:00+00:00"
+ * Date._rfc3339(s)
+ * # => {:year=>2001, :mon=>2, :mday=>3, :hour=>0, :min=>0, :sec=>0, :zone=>"+00:00", :offset=>0}
+ *
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date.rfc3339 (returns a \Date object).
+ */
+static VALUE
+date_s__rfc3339(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ if (!NIL_P(str)) str = check_limit(str, opt);
+
+ return date__rfc3339(str);
+}
+
+/*
+ * call-seq:
+ * Date.rfc3339(string = '-4712-01-01T00:00:00+00:00', start = Date::ITALY, limit: 128) -> date
+ *
+ * Returns a new \Date object with values parsed from +string+,
+ * which should be a valid
+ * {RFC 3339 format}[rdoc-ref:language/strftime_formatting.rdoc@RFC+3339+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.rfc3339 # => "2001-02-03T00:00:00+00:00"
+ * Date.rfc3339(s) # => #<Date: 2001-02-03>
+ *
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._rfc3339 (returns a hash).
+ */
+static VALUE
+date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
+ case 1:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__rfc3339(argc2, argv2, klass);
+ return d_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * Date._xmlschema(string, limit: 128) -> hash
+ *
+ * Returns a hash of values parsed from +string+, which should be a valid
+ * XML date format:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.xmlschema # => "2001-02-03"
+ * Date._xmlschema(s) # => {:year=>2001, :mon=>2, :mday=>3}
+ *
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date.xmlschema (returns a \Date object).
+ */
+static VALUE
+date_s__xmlschema(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ if (!NIL_P(str)) str = check_limit(str, opt);
+
+ return date__xmlschema(str);
+}
+
+/*
+ * call-seq:
+ * Date.xmlschema(string = '-4712-01-01', start = Date::ITALY, limit: 128) -> date
+ *
+ * Returns a new \Date object with values parsed from +string+,
+ * which should be a valid XML date format:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.xmlschema # => "2001-02-03"
+ * Date.xmlschema(s) # => #<Date: 2001-02-03>
+ *
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._xmlschema (returns a hash).
+ */
+static VALUE
+date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATE);
+ case 1:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__xmlschema(argc2, argv2, klass);
+ return d_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * Date._rfc2822(string, limit: 128) -> hash
+ *
+ * Returns a hash of values parsed from +string+, which should be a valid
+ * {RFC 2822 date format}[rdoc-ref:language/strftime_formatting.rdoc@RFC+2822+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
+ * Date._rfc2822(s)
+ * # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"+0000", :offset=>0}
+ *
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date.rfc2822 (returns a \Date object).
+ */
+static VALUE
+date_s__rfc2822(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ if (!NIL_P(str)) str = check_limit(str, opt);
+
+ return date__rfc2822(str);
+}
+
+/*
+ * call-seq:
+ * Date.rfc2822(string = 'Mon, 1 Jan -4712 00:00:00 +0000', start = Date::ITALY, limit: 128) -> date
+ *
+ * Returns a new \Date object with values parsed from +string+,
+ * which should be a valid
+ * {RFC 2822 date format}[rdoc-ref:language/strftime_formatting.rdoc@RFC+2822+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
+ * Date.rfc2822(s) # => #<Date: 2001-02-03>
+ *
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._rfc2822 (returns a hash).
+ */
+static VALUE
+date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME_RFC3339);
+ case 1:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__rfc2822(argc2, argv2, klass);
+ return d_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * Date._httpdate(string, limit: 128) -> hash
+ *
+ * Returns a hash of values parsed from +string+, which should be a valid
+ * {HTTP date format}[rdoc-ref:language/strftime_formatting.rdoc@HTTP+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
+ * Date._httpdate(s)
+ * # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"GMT", :offset=>0}
+ *
+ * Related: Date.httpdate (returns a \Date object).
+ */
+static VALUE
+date_s__httpdate(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ if (!NIL_P(str)) str = check_limit(str, opt);
+
+ return date__httpdate(str);
+}
+
+/*
+ * call-seq:
+ * Date.httpdate(string = 'Mon, 01 Jan -4712 00:00:00 GMT', start = Date::ITALY, limit: 128) -> date
+ *
+ * Returns a new \Date object with values parsed from +string+,
+ * which should be a valid
+ * {HTTP date format}[rdoc-ref:language/strftime_formatting.rdoc@HTTP+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ s = d.httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
+ Date.httpdate(s) # => #<Date: 2001-02-03>
+ *
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._httpdate (returns a hash).
+ */
+static VALUE
+date_s_httpdate(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME_HTTPDATE);
+ case 1:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__httpdate(argc2, argv2, klass);
+ return d_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * Date._jisx0301(string, limit: 128) -> hash
+ *
+ * Returns a hash of values parsed from +string+, which should be a valid
+ * {JIS X 0301 date format}[rdoc-ref:language/strftime_formatting.rdoc@JIS+X+0301+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.jisx0301 # => "H13.02.03"
+ * Date._jisx0301(s) # => {:year=>2001, :mon=>2, :mday=>3}
+ *
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date.jisx0301 (returns a \Date object).
+ */
+static VALUE
+date_s__jisx0301(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ if (!NIL_P(str)) str = check_limit(str, opt);
+
+ return date__jisx0301(str);
+}
+
+/*
+ * call-seq:
+ * Date.jisx0301(string = '-4712-01-01', start = Date::ITALY, limit: 128) -> date
+ *
+ * Returns a new \Date object with values parsed from +string+,
+ * which should be a valid {JIS X 0301 format}[rdoc-ref:language/strftime_formatting.rdoc@JIS+X+0301+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.jisx0301 # => "H13.02.03"
+ * Date.jisx0301(s) # => #<Date: 2001-02-03>
+ *
+ * For no-era year, legacy format, Heisei is assumed.
+ *
+ * Date.jisx0301('13.02.03') # => #<Date: 2001-02-03>
+ *
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._jisx0301 (returns a hash).
+ */
+static VALUE
+date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATE);
+ case 1:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__jisx0301(argc2, argv2, klass);
+ return d_new_by_frags(klass, hash, sg);
+ }
+}
+
+static VALUE
+dup_obj(VALUE self)
+{
+ get_d1a(self);
+
+ if (simple_dat_p(adat)) {
+ VALUE new = d_lite_s_alloc_simple(rb_obj_class(self));
+ {
+ get_d1b(new);
+ bdat->s = adat->s;
+ RB_OBJ_WRITTEN(new, Qundef, bdat->s.nth);
+ return new;
+ }
+ }
+ else {
+ VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
+ {
+ get_d1b(new);
+ bdat->c = adat->c;
+ RB_OBJ_WRITTEN(new, Qundef, bdat->c.nth);
+ RB_OBJ_WRITTEN(new, Qundef, bdat->c.sf);
+ return new;
+ }
+ }
+}
+
+static VALUE
+dup_obj_as_complex(VALUE self)
+{
+ get_d1a(self);
+
+ if (simple_dat_p(adat)) {
+ VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
+ {
+ get_d1b(new);
+ copy_simple_to_complex(new, &bdat->c, &adat->s);
+ bdat->c.flags |= HAVE_DF | COMPLEX_DAT;
+ return new;
+ }
+ }
+ else {
+ VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
+ {
+ get_d1b(new);
+ bdat->c = adat->c;
+ RB_OBJ_WRITTEN(new, Qundef, bdat->c.nth);
+ RB_OBJ_WRITTEN(new, Qundef, bdat->c.sf);
+ return new;
+ }
+ }
+}
+
+#define val2off(vof,iof) \
+do {\
+ if (!offset_to_sec(vof, &iof)) {\
+ iof = 0;\
+ rb_warning("invalid offset is ignored");\
+ }\
+} while (0)
+
+#if 0
+static VALUE
+d_lite_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE jd, vjd, vdf, sf, vsf, vof, vsg;
+ int df, of;
+ double sg;
+
+ rb_check_frozen(self);
+
+ rb_scan_args(argc, argv, "05", &vjd, &vdf, &vsf, &vof, &vsg);
+
+ jd = INT2FIX(0);
+ df = 0;
+ sf = INT2FIX(0);
+ of = 0;
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 5:
+ val2sg(vsg, sg);
+ case 4:
+ val2off(vof, of);
+ case 3:
+ sf = vsf;
+ if (f_lt_p(sf, INT2FIX(0)) ||
+ f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS)))
+ rb_raise(eDateError, "invalid second fraction");
+ case 2:
+ df = NUM2INT(vdf);
+ if (df < 0 || df >= DAY_IN_SECONDS)
+ rb_raise(eDateError, "invalid day fraction");
+ case 1:
+ jd = vjd;
+ }
+
+ {
+ VALUE nth;
+ int rjd;
+
+ get_d1(self);
+
+ decode_jd(jd, &nth, &rjd);
+ if (!df && f_zero_p(sf) && !of) {
+ set_to_simple(self, &dat->s, nth, rjd, sg, 0, 0, 0, HAVE_JD);
+ }
+ else {
+ if (!complex_dat_p(dat))
+ rb_raise(rb_eArgError,
+ "cannot load complex into simple");
+
+ set_to_complex(self, &dat->c, nth, rjd, df, sf, of, sg,
+ 0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF);
+ }
+ }
+ return self;
+}
+#endif
+
+/* :nodoc: */
+static VALUE
+d_lite_initialize_copy(VALUE copy, VALUE date)
+{
+ rb_check_frozen(copy);
+
+ if (copy == date)
+ return copy;
+ {
+ get_d2(copy, date);
+ if (simple_dat_p(bdat)) {
+ if (simple_dat_p(adat)) {
+ adat->s = bdat->s;
+ }
+ else {
+ adat->c.flags = bdat->s.flags | COMPLEX_DAT;
+ adat->c.nth = bdat->s.nth;
+ adat->c.jd = bdat->s.jd;
+ adat->c.df = 0;
+ adat->c.sf = INT2FIX(0);
+ adat->c.of = 0;
+ adat->c.sg = bdat->s.sg;
+ adat->c.year = bdat->s.year;
+#ifndef USE_PACK
+ adat->c.mon = bdat->s.mon;
+ adat->c.mday = bdat->s.mday;
+ adat->c.hour = bdat->s.hour;
+ adat->c.min = bdat->s.min;
+ adat->c.sec = bdat->s.sec;
+#else
+ adat->c.pc = bdat->s.pc;
+#endif
+ }
+ }
+ else {
+ if (!complex_dat_p(adat))
+ rb_raise(rb_eArgError,
+ "cannot load complex into simple");
+
+ adat->c = bdat->c;
+ }
+ }
+ return copy;
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+d_lite_fill(VALUE self)
+{
+ get_d1(self);
+
+ if (simple_dat_p(dat)) {
+ get_s_jd(dat);
+ get_s_civil(dat);
+ }
+ else {
+ get_c_jd(dat);
+ get_c_civil(dat);
+ get_c_df(dat);
+ get_c_time(dat);
+ }
+ return self;
+}
+#endif
+
+/*
+ * call-seq:
+ * d.ajd -> rational
+ *
+ * Returns the astronomical Julian day number. This is a fractional
+ * number, which is not adjusted by the offset.
+ *
+ * DateTime.new(2001,2,3,4,5,6,'+7').ajd #=> (11769328217/4800)
+ * DateTime.new(2001,2,2,14,5,6,'-7').ajd #=> (11769328217/4800)
+ */
+static VALUE
+d_lite_ajd(VALUE self)
+{
+ get_d1(self);
+ return m_ajd(dat);
+}
+
+/*
+ * call-seq:
+ * d.amjd -> rational
+ *
+ * Returns the astronomical modified Julian day number. This is
+ * a fractional number, which is not adjusted by the offset.
+ *
+ * DateTime.new(2001,2,3,4,5,6,'+7').amjd #=> (249325817/4800)
+ * DateTime.new(2001,2,2,14,5,6,'-7').amjd #=> (249325817/4800)
+ */
+static VALUE
+d_lite_amjd(VALUE self)
+{
+ get_d1(self);
+ return m_amjd(dat);
+}
+
+/*
+ * call-seq:
+ * d.jd -> integer
+ *
+ * Returns the Julian day number. This is a whole number, which is
+ * adjusted by the offset as the local time.
+ *
+ * DateTime.new(2001,2,3,4,5,6,'+7').jd #=> 2451944
+ * DateTime.new(2001,2,3,4,5,6,'-7').jd #=> 2451944
+ */
+static VALUE
+d_lite_jd(VALUE self)
+{
+ get_d1(self);
+ return m_real_local_jd(dat);
+}
+
+/*
+ * call-seq:
+ * d.mjd -> integer
+ *
+ * Returns the modified Julian day number. This is a whole number,
+ * which is adjusted by the offset as the local time.
+ *
+ * DateTime.new(2001,2,3,4,5,6,'+7').mjd #=> 51943
+ * DateTime.new(2001,2,3,4,5,6,'-7').mjd #=> 51943
+ */
+static VALUE
+d_lite_mjd(VALUE self)
+{
+ get_d1(self);
+ return f_sub(m_real_local_jd(dat), INT2FIX(2400001));
+}
+
+/*
+ * call-seq:
+ * ld -> integer
+ *
+ * Returns the
+ * {Lilian day number}[https://en.wikipedia.org/wiki/Lilian_date],
+ * which is the number of days since the beginning of the Gregorian
+ * calendar, October 15, 1582.
+ *
+ * Date.new(2001, 2, 3).ld # => 152784
+ *
+ */
+static VALUE
+d_lite_ld(VALUE self)
+{
+ get_d1(self);
+ return f_sub(m_real_local_jd(dat), INT2FIX(2299160));
+}
+
+/*
+ * call-seq:
+ * year -> integer
+ *
+ * Returns the year:
+ *
+ * Date.new(2001, 2, 3).year # => 2001
+ * (Date.new(1, 1, 1) - 1).year # => 0
+ *
+ */
+static VALUE
+d_lite_year(VALUE self)
+{
+ get_d1(self);
+ return m_real_year(dat);
+}
+
+/*
+ * call-seq:
+ * yday -> integer
+ *
+ * Returns the day of the year, in range (1..366):
+ *
+ * Date.new(2001, 2, 3).yday # => 34
+ *
+ */
+static VALUE
+d_lite_yday(VALUE self)
+{
+ get_d1(self);
+ return INT2FIX(m_yday(dat));
+}
+
+/*
+ * call-seq:
+ * mon -> integer
+ *
+ * Returns the month in range (1..12):
+ *
+ * Date.new(2001, 2, 3).mon # => 2
+ *
+ */
+static VALUE
+d_lite_mon(VALUE self)
+{
+ get_d1(self);
+ return INT2FIX(m_mon(dat));
+}
+
+/*
+ * call-seq:
+ * mday -> integer
+ *
+ * Returns the day of the month in range (1..31):
+ *
+ * Date.new(2001, 2, 3).mday # => 3
+ *
+ */
+static VALUE
+d_lite_mday(VALUE self)
+{
+ get_d1(self);
+ return INT2FIX(m_mday(dat));
+}
+
+/*
+ * call-seq:
+ * day_fraction -> rational
+ *
+ * Returns the fractional part of the day in range (Rational(0, 1)...Rational(1, 1)):
+ *
+ * DateTime.new(2001,2,3,12).day_fraction # => (1/2)
+ *
+ */
+static VALUE
+d_lite_day_fraction(VALUE self)
+{
+ get_d1(self);
+ if (simple_dat_p(dat))
+ return INT2FIX(0);
+ return m_fr(dat);
+}
+
+/*
+ * call-seq:
+ * cwyear -> integer
+ *
+ * Returns commercial-date year for +self+
+ * (see Date.commercial):
+ *
+ * Date.new(2001, 2, 3).cwyear # => 2001
+ * Date.new(2000, 1, 1).cwyear # => 1999
+ *
+ */
+static VALUE
+d_lite_cwyear(VALUE self)
+{
+ get_d1(self);
+ return m_real_cwyear(dat);
+}
+
+/*
+ * call-seq:
+ * cweek -> integer
+ *
+ * Returns commercial-date week index for +self+
+ * (see Date.commercial):
+ *
+ * Date.new(2001, 2, 3).cweek # => 5
+ *
+ */
+static VALUE
+d_lite_cweek(VALUE self)
+{
+ get_d1(self);
+ return INT2FIX(m_cweek(dat));
+}
+
+/*
+ * call-seq:
+ * cwday -> integer
+ *
+ * Returns the commercial-date weekday index for +self+
+ * (see Date.commercial);
+ * 1 is Monday:
+ *
+ * Date.new(2001, 2, 3).cwday # => 6
+ *
+ */
+static VALUE
+d_lite_cwday(VALUE self)
+{
+ get_d1(self);
+ return INT2FIX(m_cwday(dat));
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+d_lite_wnum0(VALUE self)
+{
+ get_d1(self);
+ return INT2FIX(m_wnum0(dat));
+}
+
+/* :nodoc: */
+static VALUE
+d_lite_wnum1(VALUE self)
+{
+ get_d1(self);
+ return INT2FIX(m_wnum1(dat));
+}
+#endif
+
+/*
+ * call-seq:
+ * wday -> integer
+ *
+ * Returns the day of week in range (0..6); Sunday is 0:
+ *
+ * Date.new(2001, 2, 3).wday # => 6
+ *
+ */
+static VALUE
+d_lite_wday(VALUE self)
+{
+ get_d1(self);
+ return INT2FIX(m_wday(dat));
+}
+
+/*
+ * call-seq:
+ * sunday? -> true or false
+ *
+ * Returns +true+ if +self+ is a Sunday, +false+ otherwise.
+ */
+static VALUE
+d_lite_sunday_p(VALUE self)
+{
+ get_d1(self);
+ return f_boolcast(m_wday(dat) == 0);
+}
+
+/*
+ * call-seq:
+ * monday? -> true or false
+ *
+ * Returns +true+ if +self+ is a Monday, +false+ otherwise.
+ */
+static VALUE
+d_lite_monday_p(VALUE self)
+{
+ get_d1(self);
+ return f_boolcast(m_wday(dat) == 1);
+}
+
+/*
+ * call-seq:
+ * tuesday? -> true or false
+ *
+ * Returns +true+ if +self+ is a Tuesday, +false+ otherwise.
+ */
+static VALUE
+d_lite_tuesday_p(VALUE self)
+{
+ get_d1(self);
+ return f_boolcast(m_wday(dat) == 2);
+}
+
+/*
+ * call-seq:
+ * wednesday? -> true or false
+ *
+ * Returns +true+ if +self+ is a Wednesday, +false+ otherwise.
+ */
+static VALUE
+d_lite_wednesday_p(VALUE self)
+{
+ get_d1(self);
+ return f_boolcast(m_wday(dat) == 3);
+}
+
+/*
+ * call-seq:
+ * thursday? -> true or false
+ *
+ * Returns +true+ if +self+ is a Thursday, +false+ otherwise.
+ */
+static VALUE
+d_lite_thursday_p(VALUE self)
+{
+ get_d1(self);
+ return f_boolcast(m_wday(dat) == 4);
+}
+
+/*
+ * call-seq:
+ * friday? -> true or false
+ *
+ * Returns +true+ if +self+ is a Friday, +false+ otherwise.
+ */
+static VALUE
+d_lite_friday_p(VALUE self)
+{
+ get_d1(self);
+ return f_boolcast(m_wday(dat) == 5);
+}
+
+/*
+ * call-seq:
+ * saturday? -> true or false
+ *
+ * Returns +true+ if +self+ is a Saturday, +false+ otherwise.
+ */
+static VALUE
+d_lite_saturday_p(VALUE self)
+{
+ get_d1(self);
+ return f_boolcast(m_wday(dat) == 6);
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+d_lite_nth_kday_p(VALUE self, VALUE n, VALUE k)
+{
+ int rjd, ns;
+
+ get_d1(self);
+
+ if (NUM2INT(k) != m_wday(dat))
+ return Qfalse;
+
+ c_nth_kday_to_jd(m_year(dat), m_mon(dat),
+ NUM2INT(n), NUM2INT(k), m_virtual_sg(dat), /* !=m_sg() */
+ &rjd, &ns);
+ if (m_local_jd(dat) != rjd)
+ return Qfalse;
+ return Qtrue;
+}
+#endif
+
+/*
+ * call-seq:
+ * hour -> integer
+ *
+ * Returns the hour in range (0..23):
+ *
+ * DateTime.new(2001, 2, 3, 4, 5, 6).hour # => 4
+ *
+ */
+static VALUE
+d_lite_hour(VALUE self)
+{
+ get_d1(self);
+ return INT2FIX(m_hour(dat));
+}
+
+/*
+ * call-seq:
+ * min -> integer
+ *
+ * Returns the minute in range (0..59):
+ *
+ * DateTime.new(2001, 2, 3, 4, 5, 6).min # => 5
+ *
+ */
+static VALUE
+d_lite_min(VALUE self)
+{
+ get_d1(self);
+ return INT2FIX(m_min(dat));
+}
+
+/*
+ * call-seq:
+ * sec -> integer
+ *
+ * Returns the second in range (0..59):
+ *
+ * DateTime.new(2001, 2, 3, 4, 5, 6).sec # => 6
+ *
+ */
+static VALUE
+d_lite_sec(VALUE self)
+{
+ get_d1(self);
+ return INT2FIX(m_sec(dat));
+}
+
+/*
+ * call-seq:
+ * sec_fraction -> rational
+ *
+ * Returns the fractional part of the second in range
+ * (Rational(0, 1)...Rational(1, 1)):
+ *
+ * DateTime.new(2001, 2, 3, 4, 5, 6.5).sec_fraction # => (1/2)
+ *
+ */
+static VALUE
+d_lite_sec_fraction(VALUE self)
+{
+ get_d1(self);
+ return m_sf_in_sec(dat);
+}
+
+/*
+ * call-seq:
+ * d.offset -> rational
+ *
+ * Returns the offset.
+ *
+ * DateTime.parse('04pm+0730').offset #=> (5/16)
+ */
+static VALUE
+d_lite_offset(VALUE self)
+{
+ get_d1(self);
+ return m_of_in_day(dat);
+}
+
+/*
+ * call-seq:
+ * d.zone -> string
+ *
+ * Returns the timezone.
+ *
+ * DateTime.parse('04pm+0730').zone #=> "+07:30"
+ */
+static VALUE
+d_lite_zone(VALUE self)
+{
+ get_d1(self);
+ return m_zone(dat);
+}
+
+/*
+ * call-seq:
+ * d.julian? -> true or false
+ *
+ * Returns +true+ if the date is before the date of calendar reform,
+ * +false+ otherwise:
+ *
+ * (Date.new(1582, 10, 15) - 1).julian? # => true
+ * Date.new(1582, 10, 15).julian? # => false
+ *
+ */
+static VALUE
+d_lite_julian_p(VALUE self)
+{
+ get_d1(self);
+ return f_boolcast(m_julian_p(dat));
+}
+
+/*
+ * call-seq:
+ * gregorian? -> true or false
+ *
+ * Returns +true+ if the date is on or after
+ * the date of calendar reform, +false+ otherwise:
+ *
+ * Date.new(1582, 10, 15).gregorian? # => true
+ * (Date.new(1582, 10, 15) - 1).gregorian? # => false
+ *
+ */
+static VALUE
+d_lite_gregorian_p(VALUE self)
+{
+ get_d1(self);
+ return f_boolcast(m_gregorian_p(dat));
+}
+
+/*
+ * call-seq:
+ * leap? -> true or false
+ *
+ * Returns +true+ if the year is a leap year, +false+ otherwise:
+ *
+ * Date.new(2000).leap? # => true
+ * Date.new(2001).leap? # => false
+ *
+ */
+static VALUE
+d_lite_leap_p(VALUE self)
+{
+ int rjd, ns, ry, rm, rd;
+
+ get_d1(self);
+ if (m_gregorian_p(dat))
+ return f_boolcast(c_gregorian_leap_p(m_year(dat)));
+
+ c_civil_to_jd(m_year(dat), 3, 1, m_virtual_sg(dat),
+ &rjd, &ns);
+ c_jd_to_civil(rjd - 1, m_virtual_sg(dat), &ry, &rm, &rd);
+ return f_boolcast(rd == 29);
+}
+
+/*
+ * call-seq:
+ * start -> float
+ *
+ * Returns the Julian start date for calendar reform;
+ * if not an infinity, the returned value is suitable
+ * for passing to Date#jd:
+ *
+ * d = Date.new(2001, 2, 3, Date::ITALY)
+ * s = d.start # => 2299161.0
+ * Date.jd(s).to_s # => "1582-10-15"
+ *
+ * d = Date.new(2001, 2, 3, Date::ENGLAND)
+ * s = d.start # => 2361222.0
+ * Date.jd(s).to_s # => "1752-09-14"
+ *
+ * Date.new(2001, 2, 3, Date::GREGORIAN).start # => -Infinity
+ * Date.new(2001, 2, 3, Date::JULIAN).start # => Infinity
+ *
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ *
+ */
+static VALUE
+d_lite_start(VALUE self)
+{
+ get_d1(self);
+ return DBL2NUM(m_sg(dat));
+}
+
+static void
+clear_civil(union DateData *x)
+{
+ if (simple_dat_p(x)) {
+ x->s.year = 0;
+#ifndef USE_PACK
+ x->s.mon = 0;
+ x->s.mday = 0;
+#else
+ x->s.pc = 0;
+#endif
+ x->s.flags &= ~HAVE_CIVIL;
+ }
+ else {
+ x->c.year = 0;
+#ifndef USE_PACK
+ x->c.mon = 0;
+ x->c.mday = 0;
+ x->c.hour = 0;
+ x->c.min = 0;
+ x->c.sec = 0;
+#else
+ x->c.pc = 0;
+#endif
+ x->c.flags &= ~(HAVE_CIVIL | HAVE_TIME);
+ }
+}
+
+static void
+set_sg(union DateData *x, double sg)
+{
+ if (simple_dat_p(x)) {
+ get_s_jd(x);
+ clear_civil(x);
+ x->s.sg = (date_sg_t)sg;
+ } else {
+ get_c_jd(x);
+ get_c_df(x);
+ clear_civil(x);
+ x->c.sg = (date_sg_t)sg;
+ }
+}
+
+static VALUE
+dup_obj_with_new_start(VALUE obj, double sg)
+{
+ volatile VALUE dup = dup_obj(obj);
+ {
+ get_d1(dup);
+ set_sg(dat, sg);
+ }
+ return dup;
+}
+
+/*
+ * call-seq:
+ * new_start(start = Date::ITALY) -> new_date
+ *
+ * Returns a copy of +self+ with the given +start+ value:
+ *
+ * d0 = Date.new(2000, 2, 3)
+ * d0.julian? # => false
+ * d1 = d0.new_start(Date::JULIAN)
+ * d1.julian? # => true
+ *
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
+ *
+ */
+static VALUE
+d_lite_new_start(int argc, VALUE *argv, VALUE self)
+{
+ VALUE vsg;
+ double sg;
+
+ rb_scan_args(argc, argv, "01", &vsg);
+
+ sg = DEFAULT_SG;
+ if (argc >= 1)
+ val2sg(vsg, sg);
+
+ return dup_obj_with_new_start(self, sg);
+}
+
+/*
+ * call-seq:
+ * italy -> new_date
+ *
+ * Equivalent to Date#new_start with argument Date::ITALY.
+ *
+ */
+static VALUE
+d_lite_italy(VALUE self)
+{
+ return dup_obj_with_new_start(self, ITALY);
+}
+
+/*
+ * call-seq:
+ * england -> new_date
+ *
+ * Equivalent to Date#new_start with argument Date::ENGLAND.
+ */
+static VALUE
+d_lite_england(VALUE self)
+{
+ return dup_obj_with_new_start(self, ENGLAND);
+}
+
+/*
+ * call-seq:
+ * julian -> new_date
+ *
+ * Equivalent to Date#new_start with argument Date::JULIAN.
+ */
+static VALUE
+d_lite_julian(VALUE self)
+{
+ return dup_obj_with_new_start(self, JULIAN);
+}
+
+/*
+ * call-seq:
+ * gregorian -> new_date
+ *
+ * Equivalent to Date#new_start with argument Date::GREGORIAN.
+ */
+static VALUE
+d_lite_gregorian(VALUE self)
+{
+ return dup_obj_with_new_start(self, GREGORIAN);
+}
+
+static void
+set_of(union DateData *x, int of)
+{
+ assert(complex_dat_p(x));
+ get_c_jd(x);
+ get_c_df(x);
+ clear_civil(x);
+ x->c.of = of;
+}
+
+static VALUE
+dup_obj_with_new_offset(VALUE obj, int of)
+{
+ volatile VALUE dup = dup_obj_as_complex(obj);
+ {
+ get_d1(dup);
+ set_of(dat, of);
+ }
+ return dup;
+}
+
+/*
+ * call-seq:
+ * d.new_offset([offset=0]) -> date
+ *
+ * Duplicates self and resets its offset.
+ *
+ * d = DateTime.new(2001,2,3,4,5,6,'-02:00')
+ * #=> #<DateTime: 2001-02-03T04:05:06-02:00 ...>
+ * d.new_offset('+09:00') #=> #<DateTime: 2001-02-03T15:05:06+09:00 ...>
+ */
+static VALUE
+d_lite_new_offset(int argc, VALUE *argv, VALUE self)
+{
+ VALUE vof;
+ int rof;
+
+ rb_scan_args(argc, argv, "01", &vof);
+
+ rof = 0;
+ if (argc >= 1)
+ val2off(vof, rof);
+
+ return dup_obj_with_new_offset(self, rof);
+}
+
+/*
+ * call-seq:
+ * d + other -> date
+ *
+ * Returns a date object pointing +other+ days after self. The other
+ * should be a numeric value. If the other is a fractional number,
+ * assumes its precision is at most nanosecond.
+ *
+ * Date.new(2001,2,3) + 1 #=> #<Date: 2001-02-04 ...>
+ * DateTime.new(2001,2,3) + Rational(1,2)
+ * #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...>
+ * DateTime.new(2001,2,3) + Rational(-1,2)
+ * #=> #<DateTime: 2001-02-02T12:00:00+00:00 ...>
+ * DateTime.jd(0,12) + DateTime.new(2001,2,3).ajd
+ * #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
+ */
+static VALUE
+d_lite_plus(VALUE self, VALUE other)
+{
+ int try_rational = 1;
+ get_d1(self);
+
+ again:
+ switch (TYPE(other)) {
+ case T_FIXNUM:
+ {
+ VALUE nth;
+ long t;
+ int jd;
+
+ nth = m_nth(dat);
+ t = FIX2LONG(other);
+ if (DIV(t, CM_PERIOD)) {
+ nth = f_add(nth, INT2FIX(DIV(t, CM_PERIOD)));
+ t = MOD(t, CM_PERIOD);
+ }
+
+ if (!t)
+ jd = m_jd(dat);
+ else {
+ jd = m_jd(dat) + (int)t;
+ canonicalize_jd(nth, jd);
+ }
+
+ if (simple_dat_p(dat))
+ return d_simple_new_internal(rb_obj_class(self),
+ nth, jd,
+ dat->s.sg,
+ 0, 0, 0,
+ (dat->s.flags | HAVE_JD) &
+ ~HAVE_CIVIL);
+ else
+ return d_complex_new_internal(rb_obj_class(self),
+ nth, jd,
+ dat->c.df, dat->c.sf,
+ dat->c.of, dat->c.sg,
+ 0, 0, 0,
+#ifndef USE_PACK
+ dat->c.hour,
+ dat->c.min,
+ dat->c.sec,
+#else
+ EX_HOUR(dat->c.pc),
+ EX_MIN(dat->c.pc),
+ EX_SEC(dat->c.pc),
+#endif
+ (dat->c.flags | HAVE_JD) &
+ ~HAVE_CIVIL);
+ }
+ break;
+ case T_BIGNUM:
+ {
+ VALUE nth;
+ int jd, s;
+
+ if (f_positive_p(other))
+ s = +1;
+ else {
+ s = -1;
+ other = f_negate(other);
+ }
+
+ nth = f_idiv(other, INT2FIX(CM_PERIOD));
+ jd = FIX2INT(f_mod(other, INT2FIX(CM_PERIOD)));
+
+ if (s < 0) {
+ nth = f_negate(nth);
+ jd = -jd;
+ }
+
+ if (!jd)
+ jd = m_jd(dat);
+ else {
+ jd = m_jd(dat) + jd;
+ canonicalize_jd(nth, jd);
+ }
+
+ if (f_zero_p(nth))
+ nth = m_nth(dat);
+ else
+ nth = f_add(m_nth(dat), nth);
+
+ if (simple_dat_p(dat))
+ return d_simple_new_internal(rb_obj_class(self),
+ nth, jd,
+ dat->s.sg,
+ 0, 0, 0,
+ (dat->s.flags | HAVE_JD) &
+ ~HAVE_CIVIL);
+ else
+ return d_complex_new_internal(rb_obj_class(self),
+ nth, jd,
+ dat->c.df, dat->c.sf,
+ dat->c.of, dat->c.sg,
+ 0, 0, 0,
+#ifndef USE_PACK
+ dat->c.hour,
+ dat->c.min,
+ dat->c.sec,
+#else
+ EX_HOUR(dat->c.pc),
+ EX_MIN(dat->c.pc),
+ EX_SEC(dat->c.pc),
+#endif
+ (dat->c.flags | HAVE_JD) &
+ ~HAVE_CIVIL);
+ }
+ break;
+ case T_FLOAT:
+ {
+ double jd, o, tmp;
+ int s, df;
+ VALUE nth, sf;
+
+ o = RFLOAT_VALUE(other);
+
+ if (o > 0)
+ s = +1;
+ else {
+ s = -1;
+ o = -o;
+ }
+
+ o = modf(o, &tmp);
+
+ if (!floor(tmp / CM_PERIOD)) {
+ nth = INT2FIX(0);
+ jd = (int)tmp;
+ }
+ else {
+ double i, f;
+
+ f = modf(tmp / CM_PERIOD, &i);
+ nth = f_floor(DBL2NUM(i));
+ jd = (int)(f * CM_PERIOD);
+ }
+
+ o *= DAY_IN_SECONDS;
+ o = modf(o, &tmp);
+ df = (int)tmp;
+ o *= SECOND_IN_NANOSECONDS;
+ sf = INT2FIX((int)round(o));
+
+ if (s < 0) {
+ jd = -jd;
+ df = -df;
+ sf = f_negate(sf);
+ }
+
+ if (f_zero_p(sf))
+ sf = m_sf(dat);
+ else {
+ sf = f_add(m_sf(dat), sf);
+ if (f_lt_p(sf, INT2FIX(0))) {
+ df -= 1;
+ sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
+ }
+ else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
+ df += 1;
+ sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
+ }
+ }
+
+ if (!df)
+ df = m_df(dat);
+ else {
+ df = m_df(dat) + df;
+ if (df < 0) {
+ jd -= 1;
+ df += DAY_IN_SECONDS;
+ }
+ else if (df >= DAY_IN_SECONDS) {
+ jd += 1;
+ df -= DAY_IN_SECONDS;
+ }
+ }
+
+ if (!jd)
+ jd = m_jd(dat);
+ else {
+ jd = m_jd(dat) + jd;
+ canonicalize_jd(nth, jd);
+ }
+
+ if (f_zero_p(nth))
+ nth = m_nth(dat);
+ else
+ nth = f_add(m_nth(dat), nth);
+
+ if (!df && f_zero_p(sf) && !m_of(dat))
+ return d_simple_new_internal(rb_obj_class(self),
+ nth, (int)jd,
+ m_sg(dat),
+ 0, 0, 0,
+ (dat->s.flags | HAVE_JD) &
+ ~(HAVE_CIVIL | HAVE_TIME |
+ COMPLEX_DAT));
+ else
+ return d_complex_new_internal(rb_obj_class(self),
+ nth, (int)jd,
+ df, sf,
+ m_of(dat), m_sg(dat),
+ 0, 0, 0,
+ 0, 0, 0,
+ (dat->c.flags |
+ HAVE_JD | HAVE_DF) &
+ ~(HAVE_CIVIL | HAVE_TIME));
+ }
+ break;
+ default:
+ expect_numeric(other);
+ other = f_to_r(other);
+ if (!k_rational_p(other)) {
+ if (!try_rational) Check_Type(other, T_RATIONAL);
+ try_rational = 0;
+ goto again;
+ }
+ /* fall through */
+ case T_RATIONAL:
+ {
+ VALUE nth, sf, t;
+ int jd, df, s;
+
+ if (wholenum_p(other)) {
+ other = rb_rational_num(other);
+ goto again;
+ }
+
+ if (f_positive_p(other))
+ s = +1;
+ else {
+ s = -1;
+ other = f_negate(other);
+ }
+
+ nth = f_idiv(other, INT2FIX(CM_PERIOD));
+ t = f_mod(other, INT2FIX(CM_PERIOD));
+
+ jd = FIX2INT(f_idiv(t, INT2FIX(1)));
+ t = f_mod(t, INT2FIX(1));
+
+ t = f_mul(t, INT2FIX(DAY_IN_SECONDS));
+ df = FIX2INT(f_idiv(t, INT2FIX(1)));
+ t = f_mod(t, INT2FIX(1));
+
+ sf = f_mul(t, INT2FIX(SECOND_IN_NANOSECONDS));
+
+ if (s < 0) {
+ nth = f_negate(nth);
+ jd = -jd;
+ df = -df;
+ sf = f_negate(sf);
+ }
+
+ if (f_zero_p(sf))
+ sf = m_sf(dat);
+ else {
+ sf = f_add(m_sf(dat), sf);
+ if (f_lt_p(sf, INT2FIX(0))) {
+ df -= 1;
+ sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
+ }
+ else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
+ df += 1;
+ sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
+ }
+ }
+
+ if (!df)
+ df = m_df(dat);
+ else {
+ df = m_df(dat) + df;
+ if (df < 0) {
+ jd -= 1;
+ df += DAY_IN_SECONDS;
+ }
+ else if (df >= DAY_IN_SECONDS) {
+ jd += 1;
+ df -= DAY_IN_SECONDS;
+ }
+ }
+
+ if (!jd)
+ jd = m_jd(dat);
+ else {
+ jd = m_jd(dat) + jd;
+ canonicalize_jd(nth, jd);
+ }
+
+ if (f_zero_p(nth))
+ nth = m_nth(dat);
+ else
+ nth = f_add(m_nth(dat), nth);
+
+ if (!df && f_zero_p(sf) && !m_of(dat))
+ return d_simple_new_internal(rb_obj_class(self),
+ nth, jd,
+ m_sg(dat),
+ 0, 0, 0,
+ (dat->s.flags | HAVE_JD) &
+ ~(HAVE_CIVIL | HAVE_TIME |
+ COMPLEX_DAT));
+ else
+ return d_complex_new_internal(rb_obj_class(self),
+ nth, jd,
+ df, sf,
+ m_of(dat), m_sg(dat),
+ 0, 0, 0,
+ 0, 0, 0,
+ (dat->c.flags |
+ HAVE_JD | HAVE_DF) &
+ ~(HAVE_CIVIL | HAVE_TIME));
+ }
+ break;
+ }
+}
+
+static VALUE
+minus_dd(VALUE self, VALUE other)
+{
+ get_d2(self, other);
+
+ {
+ int d, df;
+ VALUE n, sf, r;
+
+ n = f_sub(m_nth(adat), m_nth(bdat));
+ d = m_jd(adat) - m_jd(bdat);
+ df = m_df(adat) - m_df(bdat);
+ sf = f_sub(m_sf(adat), m_sf(bdat));
+ canonicalize_jd(n, d);
+
+ if (df < 0) {
+ d -= 1;
+ df += DAY_IN_SECONDS;
+ }
+ else if (df >= DAY_IN_SECONDS) {
+ d += 1;
+ df -= DAY_IN_SECONDS;
+ }
+
+ if (f_lt_p(sf, INT2FIX(0))) {
+ df -= 1;
+ sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
+ }
+ else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
+ df += 1;
+ sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
+ }
+
+ if (f_zero_p(n))
+ r = INT2FIX(0);
+ else
+ r = f_mul(n, INT2FIX(CM_PERIOD));
+
+ if (d)
+ r = f_add(r, rb_rational_new1(INT2FIX(d)));
+ if (df)
+ r = f_add(r, isec_to_day(df));
+ if (f_nonzero_p(sf))
+ r = f_add(r, ns_to_day(sf));
+
+ if (RB_TYPE_P(r, T_RATIONAL))
+ return r;
+ return rb_rational_new1(r);
+ }
+}
+
+/*
+ * call-seq:
+ * d - other -> date or rational
+ *
+ * If the other is a date object, returns a Rational
+ * whose value is the difference between the two dates in days.
+ * If the other is a numeric value, returns a date object
+ * pointing +other+ days before self.
+ * If the other is a fractional number,
+ * assumes its precision is at most nanosecond.
+ *
+ * Date.new(2001,2,3) - 1 #=> #<Date: 2001-02-02 ...>
+ * DateTime.new(2001,2,3) - Rational(1,2)
+ * #=> #<DateTime: 2001-02-02T12:00:00+00:00 ...>
+ * Date.new(2001,2,3) - Date.new(2001)
+ * #=> (33/1)
+ * DateTime.new(2001,2,3) - DateTime.new(2001,2,2,12)
+ * #=> (1/2)
+ */
+static VALUE
+d_lite_minus(VALUE self, VALUE other)
+{
+ if (k_date_p(other))
+ return minus_dd(self, other);
+
+ switch (TYPE(other)) {
+ case T_FIXNUM:
+ return d_lite_plus(self, LONG2NUM(-FIX2LONG(other)));
+ case T_FLOAT:
+ return d_lite_plus(self, DBL2NUM(-RFLOAT_VALUE(other)));
+ default:
+ expect_numeric(other);
+ /* fall through */
+ case T_BIGNUM:
+ case T_RATIONAL:
+ return d_lite_plus(self, f_negate(other));
+ }
+}
+
+/*
+ * call-seq:
+ * next_day(n = 1) -> new_date
+ *
+ * Equivalent to Date#+ with argument +n+.
+ */
+static VALUE
+d_lite_next_day(int argc, VALUE *argv, VALUE self)
+{
+ VALUE n;
+
+ rb_scan_args(argc, argv, "01", &n);
+ if (argc < 1)
+ n = INT2FIX(1);
+ return d_lite_plus(self, n);
+}
+
+/*
+ * call-seq:
+ * prev_day(n = 1) -> new_date
+ *
+ * Equivalent to Date#- with argument +n+.
+ */
+static VALUE
+d_lite_prev_day(int argc, VALUE *argv, VALUE self)
+{
+ VALUE n;
+
+ rb_scan_args(argc, argv, "01", &n);
+ if (argc < 1)
+ n = INT2FIX(1);
+ return d_lite_minus(self, n);
+}
+
+/*
+ * call-seq:
+ * d.next -> new_date
+ *
+ * Returns a new \Date object representing the following day:
+ *
+ * d = Date.new(2001, 2, 3)
+ * d.to_s # => "2001-02-03"
+ * d.next.to_s # => "2001-02-04"
+ *
+ */
+static VALUE
+d_lite_next(VALUE self)
+{
+ return d_lite_next_day(0, (VALUE *)NULL, self);
+}
+
+/*
+ * call-seq:
+ * d >> n -> new_date
+ *
+ * Returns a new \Date object representing the date
+ * +n+ months later; +n+ should be a numeric:
+ *
+ * (Date.new(2001, 2, 3) >> 1).to_s # => "2001-03-03"
+ * (Date.new(2001, 2, 3) >> -2).to_s # => "2000-12-03"
+ *
+ * When the same day does not exist for the new month,
+ * the last day of that month is used instead:
+ *
+ * (Date.new(2001, 1, 31) >> 1).to_s # => "2001-02-28"
+ * (Date.new(2001, 1, 31) >> -4).to_s # => "2000-09-30"
+ *
+ * This results in the following, possibly unexpected, behaviors:
+ *
+ * d0 = Date.new(2001, 1, 31)
+ * d1 = d0 >> 1 # => #<Date: 2001-02-28>
+ * d2 = d1 >> 1 # => #<Date: 2001-03-28>
+ *
+ * d0 = Date.new(2001, 1, 31)
+ * d1 = d0 >> 1 # => #<Date: 2001-02-28>
+ * d2 = d1 >> -1 # => #<Date: 2001-01-28>
+ *
+ */
+static VALUE
+d_lite_rshift(VALUE self, VALUE other)
+{
+ VALUE t, y, nth, rjd2;
+ int m, d, rjd;
+ double sg;
+
+ get_d1(self);
+ t = f_add3(f_mul(m_real_year(dat), INT2FIX(12)),
+ INT2FIX(m_mon(dat) - 1),
+ other);
+ if (FIXNUM_P(t)) {
+ long it = FIX2LONG(t);
+ y = LONG2NUM(DIV(it, 12));
+ it = MOD(it, 12);
+ m = (int)it + 1;
+ }
+ else {
+ y = f_idiv(t, INT2FIX(12));
+ t = f_mod(t, INT2FIX(12));
+ m = FIX2INT(t) + 1;
+ }
+ d = m_mday(dat);
+ sg = m_sg(dat);
+
+ while (1) {
+ int ry, rm, rd, ns;
+
+ if (valid_civil_p(y, m, d, sg,
+ &nth, &ry,
+ &rm, &rd, &rjd, &ns))
+ break;
+ if (--d < 1)
+ rb_raise(eDateError, "invalid date");
+ }
+ encode_jd(nth, rjd, &rjd2);
+ return d_lite_plus(self, f_sub(rjd2, m_real_local_jd(dat)));
+}
+
+/*
+ * call-seq:
+ * d << n -> date
+ *
+ * Returns a new \Date object representing the date
+ * +n+ months earlier; +n+ should be a numeric:
+ *
+ * (Date.new(2001, 2, 3) << 1).to_s # => "2001-01-03"
+ * (Date.new(2001, 2, 3) << -2).to_s # => "2001-04-03"
+ *
+ * When the same day does not exist for the new month,
+ * the last day of that month is used instead:
+ *
+ * (Date.new(2001, 3, 31) << 1).to_s # => "2001-02-28"
+ * (Date.new(2001, 3, 31) << -6).to_s # => "2001-09-30"
+ *
+ * This results in the following, possibly unexpected, behaviors:
+ *
+ * d0 = Date.new(2001, 3, 31)
+ * d0 << 2 # => #<Date: 2001-01-31>
+ * d0 << 1 << 1 # => #<Date: 2001-01-28>
+ *
+ * d0 = Date.new(2001, 3, 31)
+ * d1 = d0 << 1 # => #<Date: 2001-02-28>
+ * d2 = d1 << -1 # => #<Date: 2001-03-28>
+ *
+ */
+static VALUE
+d_lite_lshift(VALUE self, VALUE other)
+{
+ expect_numeric(other);
+ return d_lite_rshift(self, f_negate(other));
+}
+
+/*
+ * call-seq:
+ * next_month(n = 1) -> new_date
+ *
+ * Equivalent to #>> with argument +n+.
+ */
+static VALUE
+d_lite_next_month(int argc, VALUE *argv, VALUE self)
+{
+ VALUE n;
+
+ rb_scan_args(argc, argv, "01", &n);
+ if (argc < 1)
+ n = INT2FIX(1);
+ return d_lite_rshift(self, n);
+}
+
+/*
+ * call-seq:
+ * prev_month(n = 1) -> new_date
+ *
+ * Equivalent to #<< with argument +n+.
+ */
+static VALUE
+d_lite_prev_month(int argc, VALUE *argv, VALUE self)
+{
+ VALUE n;
+
+ rb_scan_args(argc, argv, "01", &n);
+ if (argc < 1)
+ n = INT2FIX(1);
+ return d_lite_lshift(self, n);
+}
+
+/*
+ * call-seq:
+ * next_year(n = 1) -> new_date
+ *
+ * Equivalent to #>> with argument <tt>n * 12</tt>.
+ */
+static VALUE
+d_lite_next_year(int argc, VALUE *argv, VALUE self)
+{
+ VALUE n;
+
+ rb_scan_args(argc, argv, "01", &n);
+ if (argc < 1)
+ n = INT2FIX(1);
+ return d_lite_rshift(self, f_mul(n, INT2FIX(12)));
+}
+
+/*
+ * call-seq:
+ * prev_year(n = 1) -> new_date
+ *
+ * Equivalent to #<< with argument <tt>n * 12</tt>.
+ */
+static VALUE
+d_lite_prev_year(int argc, VALUE *argv, VALUE self)
+{
+ VALUE n;
+
+ rb_scan_args(argc, argv, "01", &n);
+ if (argc < 1)
+ n = INT2FIX(1);
+ return d_lite_lshift(self, f_mul(n, INT2FIX(12)));
+}
+
+static VALUE d_lite_cmp(VALUE, VALUE);
+
+/*
+ * call-seq:
+ * step(limit, step = 1){|date| ... } -> self
+ *
+ * Calls the block with specified dates;
+ * returns +self+.
+ *
+ * - The first +date+ is +self+.
+ * - Each successive +date+ is <tt>date + step</tt>,
+ * where +step+ is the numeric step size in days.
+ * - The last date is the last one that is before or equal to +limit+,
+ * which should be a \Date object.
+ *
+ * Example:
+ *
+ * limit = Date.new(2001, 12, 31)
+ * Date.new(2001).step(limit){|date| p date.to_s if date.mday == 31 }
+ *
+ * Output:
+ *
+ * "2001-01-31"
+ * "2001-03-31"
+ * "2001-05-31"
+ * "2001-07-31"
+ * "2001-08-31"
+ * "2001-10-31"
+ * "2001-12-31"
+ *
+ * Returns an Enumerator if no block is given.
+ */
+static VALUE
+d_lite_step(int argc, VALUE *argv, VALUE self)
+{
+ VALUE limit, step, date;
+ int c;
+
+ rb_scan_args(argc, argv, "11", &limit, &step);
+
+ if (argc < 2)
+ step = INT2FIX(1);
+
+#if 0
+ if (f_zero_p(step))
+ rb_raise(rb_eArgError, "step can't be 0");
+#endif
+
+ RETURN_ENUMERATOR(self, argc, argv);
+
+ date = self;
+ c = f_cmp(step, INT2FIX(0));
+ if (c < 0) {
+ while (FIX2INT(d_lite_cmp(date, limit)) >= 0) {
+ rb_yield(date);
+ date = d_lite_plus(date, step);
+ }
+ }
+ else if (c == 0) {
+ while (1)
+ rb_yield(date);
+ }
+ else /* if (c > 0) */ {
+ while (FIX2INT(d_lite_cmp(date, limit)) <= 0) {
+ rb_yield(date);
+ date = d_lite_plus(date, step);
+ }
+ }
+ return self;
+}
+
+/*
+ * call-seq:
+ * upto(max){|date| ... } -> self
+ *
+ * Equivalent to #step with arguments +max+ and +1+.
+ */
+static VALUE
+d_lite_upto(VALUE self, VALUE max)
+{
+ VALUE date;
+
+ RETURN_ENUMERATOR(self, 1, &max);
+
+ date = self;
+ while (FIX2INT(d_lite_cmp(date, max)) <= 0) {
+ rb_yield(date);
+ date = d_lite_plus(date, INT2FIX(1));
+ }
+ return self;
+}
+
+/*
+ * call-seq:
+ * downto(min){|date| ... } -> self
+ *
+ * Equivalent to #step with arguments +min+ and <tt>-1</tt>.
+ */
+static VALUE
+d_lite_downto(VALUE self, VALUE min)
+{
+ VALUE date;
+
+ RETURN_ENUMERATOR(self, 1, &min);
+
+ date = self;
+ while (FIX2INT(d_lite_cmp(date, min)) >= 0) {
+ rb_yield(date);
+ date = d_lite_plus(date, INT2FIX(-1));
+ }
+ return self;
+}
+
+static VALUE
+cmp_gen(VALUE self, VALUE other)
+{
+ get_d1(self);
+
+ if (k_numeric_p(other))
+ return INT2FIX(f_cmp(m_ajd(dat), other));
+ else if (k_date_p(other))
+ return INT2FIX(f_cmp(m_ajd(dat), f_ajd(other)));
+ return rb_num_coerce_cmp(self, other, id_cmp);
+}
+
+static VALUE
+cmp_dd(VALUE self, VALUE other)
+{
+ get_d2(self, other);
+
+ {
+ VALUE a_nth, b_nth,
+ a_sf, b_sf;
+ int a_jd, b_jd,
+ a_df, b_df;
+
+ m_canonicalize_jd(self, adat);
+ m_canonicalize_jd(other, bdat);
+ a_nth = m_nth(adat);
+ b_nth = m_nth(bdat);
+ if (f_eqeq_p(a_nth, b_nth)) {
+ a_jd = m_jd(adat);
+ b_jd = m_jd(bdat);
+ if (a_jd == b_jd) {
+ a_df = m_df(adat);
+ b_df = m_df(bdat);
+ if (a_df == b_df) {
+ a_sf = m_sf(adat);
+ b_sf = m_sf(bdat);
+ if (f_eqeq_p(a_sf, b_sf)) {
+ return INT2FIX(0);
+ }
+ else if (f_lt_p(a_sf, b_sf)) {
+ return INT2FIX(-1);
+ }
+ else {
+ return INT2FIX(1);
+ }
+ }
+ else if (a_df < b_df) {
+ return INT2FIX(-1);
+ }
+ else {
+ return INT2FIX(1);
+ }
+ }
+ else if (a_jd < b_jd) {
+ return INT2FIX(-1);
+ }
+ else {
+ return INT2FIX(1);
+ }
+ }
+ else if (f_lt_p(a_nth, b_nth)) {
+ return INT2FIX(-1);
+ }
+ else {
+ return INT2FIX(1);
+ }
+ }
+}
+
+/*
+ * call-seq:
+ * self <=> other -> -1, 0, 1 or nil
+ *
+ * Compares +self+ and +other+, returning:
+ *
+ * - <tt>-1</tt> if +other+ is larger.
+ * - <tt>0</tt> if the two are equal.
+ * - <tt>1</tt> if +other+ is smaller.
+ * - +nil+ if the two are incomparable.
+ *
+ * Argument +other+ may be:
+ *
+ * - Another \Date object:
+ *
+ * d = Date.new(2022, 7, 27) # => #<Date: 2022-07-27 ((2459788j,0s,0n),+0s,2299161j)>
+ * prev_date = d.prev_day # => #<Date: 2022-07-26 ((2459787j,0s,0n),+0s,2299161j)>
+ * next_date = d.next_day # => #<Date: 2022-07-28 ((2459789j,0s,0n),+0s,2299161j)>
+ * d <=> next_date # => -1
+ * d <=> d # => 0
+ * d <=> prev_date # => 1
+ *
+ * - A DateTime object:
+ *
+ * d <=> DateTime.new(2022, 7, 26) # => 1
+ * d <=> DateTime.new(2022, 7, 27) # => 0
+ * d <=> DateTime.new(2022, 7, 28) # => -1
+ *
+ * - A numeric (compares <tt>self.ajd</tt> to +other+):
+ *
+ * d <=> 2459788 # => -1
+ * d <=> 2459787 # => 1
+ * d <=> 2459786 # => 1
+ * d <=> d.ajd # => 0
+ *
+ * - Any other object:
+ *
+ * d <=> Object.new # => nil
+ *
+ */
+static VALUE
+d_lite_cmp(VALUE self, VALUE other)
+{
+ if (!k_date_p(other))
+ return cmp_gen(self, other);
+
+ {
+ get_d2(self, other);
+
+ if (!(simple_dat_p(adat) && simple_dat_p(bdat) &&
+ m_gregorian_p(adat) == m_gregorian_p(bdat)))
+ return cmp_dd(self, other);
+
+ {
+ VALUE a_nth, b_nth;
+ int a_jd, b_jd;
+
+ m_canonicalize_jd(self, adat);
+ m_canonicalize_jd(other, bdat);
+ a_nth = m_nth(adat);
+ b_nth = m_nth(bdat);
+ if (f_eqeq_p(a_nth, b_nth)) {
+ a_jd = m_jd(adat);
+ b_jd = m_jd(bdat);
+ if (a_jd == b_jd) {
+ return INT2FIX(0);
+ }
+ else if (a_jd < b_jd) {
+ return INT2FIX(-1);
+ }
+ else {
+ return INT2FIX(1);
+ }
+ }
+ else if (f_lt_p(a_nth, b_nth)) {
+ return INT2FIX(-1);
+ }
+ else {
+ return INT2FIX(1);
+ }
+ }
+ }
+}
+
+static VALUE
+equal_gen(VALUE self, VALUE other)
+{
+ get_d1(self);
+
+ if (k_numeric_p(other))
+ return f_eqeq_p(m_real_local_jd(dat), other);
+ else if (k_date_p(other))
+ return f_eqeq_p(m_real_local_jd(dat), f_jd(other));
+ return rb_num_coerce_cmp(self, other, id_eqeq_p);
+}
+
+/*
+ * call-seq:
+ * self === other -> true, false, or nil.
+ *
+ * Returns +true+ if +self+ and +other+ represent the same date,
+ * +false+ if not, +nil+ if the two are not comparable.
+ *
+ * Argument +other+ may be:
+ *
+ * - Another \Date object:
+ *
+ * d = Date.new(2022, 7, 27) # => #<Date: 2022-07-27 ((2459788j,0s,0n),+0s,2299161j)>
+ * prev_date = d.prev_day # => #<Date: 2022-07-26 ((2459787j,0s,0n),+0s,2299161j)>
+ * next_date = d.next_day # => #<Date: 2022-07-28 ((2459789j,0s,0n),+0s,2299161j)>
+ * d === prev_date # => false
+ * d === d # => true
+ * d === next_date # => false
+ *
+ * - A DateTime object:
+ *
+ * d === DateTime.new(2022, 7, 26) # => false
+ * d === DateTime.new(2022, 7, 27) # => true
+ * d === DateTime.new(2022, 7, 28) # => false
+ *
+ * - A numeric (compares <tt>self.jd</tt> to +other+):
+ *
+ * d === 2459788 # => true
+ * d === 2459787 # => false
+ * d === 2459786 # => false
+ * d === d.jd # => true
+ *
+ * - An object not comparable:
+ *
+ * d === Object.new # => nil
+ *
+ */
+static VALUE
+d_lite_equal(VALUE self, VALUE other)
+{
+ if (!k_date_p(other))
+ return equal_gen(self, other);
+
+ {
+ get_d2(self, other);
+
+ if (!(m_gregorian_p(adat) == m_gregorian_p(bdat)))
+ return equal_gen(self, other);
+
+ {
+ VALUE a_nth, b_nth;
+ int a_jd, b_jd;
+
+ m_canonicalize_jd(self, adat);
+ m_canonicalize_jd(other, bdat);
+ a_nth = m_nth(adat);
+ b_nth = m_nth(bdat);
+ a_jd = m_local_jd(adat);
+ b_jd = m_local_jd(bdat);
+ if (f_eqeq_p(a_nth, b_nth) &&
+ a_jd == b_jd)
+ return Qtrue;
+ return Qfalse;
+ }
+ }
+}
+
+/* :nodoc: */
+static VALUE
+d_lite_eql_p(VALUE self, VALUE other)
+{
+ if (!k_date_p(other))
+ return Qfalse;
+ return f_zero_p(d_lite_cmp(self, other));
+}
+
+/* :nodoc: */
+static VALUE
+d_lite_hash(VALUE self)
+{
+ st_index_t v, h[5];
+ VALUE nth;
+
+ get_d1(self);
+ nth = m_nth(dat);
+
+ if (FIXNUM_P(nth)) {
+ h[0] = 0;
+ h[1] = (st_index_t)nth;
+ } else {
+ h[0] = 1;
+ h[1] = (st_index_t)FIX2LONG(rb_hash(nth));
+ }
+
+ h[2] = m_jd(dat);
+ h[3] = m_df(dat);
+ h[4] = m_sf(dat);
+
+ v = rb_memhash(h, sizeof(h));
+ return ST2FIX(v);
+}
+
+#include "date_tmx.h"
+static void set_tmx(VALUE, struct tmx *);
+static VALUE strftimev(const char *, VALUE,
+ void (*)(VALUE, struct tmx *));
+
+/*
+ * call-seq:
+ * to_s -> string
+ *
+ * Returns a string representation of the date in +self+
+ * in {ISO 8601 extended date format}[rdoc-ref:language/strftime_formatting.rdoc@ISO+8601+Format+Specifications]
+ * (<tt>'%Y-%m-%d'</tt>):
+ *
+ * Date.new(2001, 2, 3).to_s # => "2001-02-03"
+ *
+ */
+static VALUE
+d_lite_to_s(VALUE self)
+{
+ return strftimev("%Y-%m-%d", self, set_tmx);
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+mk_inspect_raw(union DateData *x, VALUE klass)
+{
+ char flags[6];
+
+ flags[0] = (x->flags & COMPLEX_DAT) ? 'C' : 'S';
+ flags[1] = (x->flags & HAVE_JD) ? 'j' : '-';
+ flags[2] = (x->flags & HAVE_DF) ? 'd' : '-';
+ flags[3] = (x->flags & HAVE_CIVIL) ? 'c' : '-';
+ flags[4] = (x->flags & HAVE_TIME) ? 't' : '-';
+ flags[5] = '\0';
+
+ if (simple_dat_p(x)) {
+ return rb_enc_sprintf(rb_usascii_encoding(),
+ "#<%"PRIsVALUE": "
+ "(%+"PRIsVALUE"th,%dj),+0s,%.0fj; "
+ "%dy%dm%dd; %s>",
+ klass,
+ x->s.nth, x->s.jd, x->s.sg,
+#ifndef USE_PACK
+ x->s.year, x->s.mon, x->s.mday,
+#else
+ x->s.year,
+ EX_MON(x->s.pc), EX_MDAY(x->s.pc),
+#endif
+ flags);
+ }
+ else {
+ return rb_enc_sprintf(rb_usascii_encoding(),
+ "#<%"PRIsVALUE": "
+ "(%+"PRIsVALUE"th,%dj,%ds,%+"PRIsVALUE"n),"
+ "%+ds,%.0fj; "
+ "%dy%dm%dd %dh%dm%ds; %s>",
+ klass,
+ x->c.nth, x->c.jd, x->c.df, x->c.sf,
+ x->c.of, x->c.sg,
+#ifndef USE_PACK
+ x->c.year, x->c.mon, x->c.mday,
+ x->c.hour, x->c.min, x->c.sec,
+#else
+ x->c.year,
+ EX_MON(x->c.pc), EX_MDAY(x->c.pc),
+ EX_HOUR(x->c.pc), EX_MIN(x->c.pc),
+ EX_SEC(x->c.pc),
+#endif
+ flags);
+ }
+}
+
+/* :nodoc: */
+static VALUE
+d_lite_inspect_raw(VALUE self)
+{
+ get_d1(self);
+ return mk_inspect_raw(dat, rb_obj_class(self));
+}
+#endif
+
+static VALUE
+mk_inspect(union DateData *x, VALUE klass, VALUE to_s)
+{
+ return rb_enc_sprintf(rb_usascii_encoding(),
+ "#<%"PRIsVALUE": %"PRIsVALUE" "
+ "((%+"PRIsVALUE"j,%ds,%+"PRIsVALUE"n),%+ds,%.0fj)>",
+ klass, to_s,
+ m_real_jd(x), m_df(x), m_sf(x),
+ m_of(x), m_sg(x));
+}
+
+/*
+ * call-seq:
+ * inspect -> string
+ *
+ * Returns a string representation of +self+:
+ *
+ * Date.new(2001, 2, 3).inspect
+ * # => "#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>"
+ *
+ */
+static VALUE
+d_lite_inspect(VALUE self)
+{
+ get_d1(self);
+ return mk_inspect(dat, rb_obj_class(self), self);
+}
+
+#include <errno.h>
+#include "date_tmx.h"
+
+size_t date_strftime(char *s, size_t maxsize, const char *format,
+ const struct tmx *tmx);
+
+#define SMALLBUF 100
+static size_t
+date_strftime_alloc(char **buf, const char *format,
+ struct tmx *tmx)
+{
+ size_t size, len, flen;
+
+ (*buf)[0] = '\0';
+ flen = strlen(format);
+ if (flen == 0) {
+ return 0;
+ }
+ errno = 0;
+ len = date_strftime(*buf, SMALLBUF, format, tmx);
+ if (len != 0 || (**buf == '\0' && errno != ERANGE)) return len;
+ for (size=1024; ; size*=2) {
+ *buf = xmalloc(size);
+ (*buf)[0] = '\0';
+ len = date_strftime(*buf, size, format, tmx);
+ /*
+ * buflen can be zero EITHER because there's not enough
+ * room in the string, or because the control command
+ * goes to the empty string. Make a reasonable guess that
+ * if the buffer is 1024 times bigger than the length of the
+ * format string, it's not failing for lack of room.
+ */
+ if (len > 0) break;
+ xfree(*buf);
+ if (size >= 1024 * flen) {
+ rb_sys_fail(format);
+ break;
+ }
+ }
+ return len;
+}
+
+static VALUE
+tmx_m_secs(union DateData *x)
+{
+ VALUE s;
+ int df;
+
+ s = day_to_sec(f_sub(m_real_jd(x),
+ UNIX_EPOCH_IN_CJD));
+ if (simple_dat_p(x))
+ return s;
+ df = m_df(x);
+ if (df)
+ s = f_add(s, INT2FIX(df));
+ return s;
+}
+
+#define MILLISECOND_IN_NANOSECONDS 1000000
+
+static VALUE
+tmx_m_msecs(union DateData *x)
+{
+ VALUE s, sf;
+
+ s = sec_to_ms(tmx_m_secs(x));
+ if (simple_dat_p(x))
+ return s;
+ sf = m_sf(x);
+ if (f_nonzero_p(sf))
+ s = f_add(s, f_div(sf, INT2FIX(MILLISECOND_IN_NANOSECONDS)));
+ return s;
+}
+
+static int
+tmx_m_of(union DateData *x)
+{
+ return m_of(x);
+}
+
+static char *
+tmx_m_zone(union DateData *x)
+{
+ VALUE zone = m_zone(x);
+ /* TODO: fix potential dangling pointer */
+ return RSTRING_PTR(zone);
+}
+
+static const struct tmx_funcs tmx_funcs = {
+ (VALUE (*)(void *))m_real_year,
+ (int (*)(void *))m_yday,
+ (int (*)(void *))m_mon,
+ (int (*)(void *))m_mday,
+ (VALUE (*)(void *))m_real_cwyear,
+ (int (*)(void *))m_cweek,
+ (int (*)(void *))m_cwday,
+ (int (*)(void *))m_wnum0,
+ (int (*)(void *))m_wnum1,
+ (int (*)(void *))m_wday,
+ (int (*)(void *))m_hour,
+ (int (*)(void *))m_min,
+ (int (*)(void *))m_sec,
+ (VALUE (*)(void *))m_sf_in_sec,
+ (VALUE (*)(void *))tmx_m_secs,
+ (VALUE (*)(void *))tmx_m_msecs,
+ (int (*)(void *))tmx_m_of,
+ (char *(*)(void *))tmx_m_zone
+};
+
+static void
+set_tmx(VALUE self, struct tmx *tmx)
+{
+ get_d1(self);
+ tmx->dat = (void *)dat;
+ tmx->funcs = &tmx_funcs;
+}
+
+static VALUE
+date_strftime_internal(int argc, VALUE *argv, VALUE self,
+ const char *default_fmt,
+ void (*func)(VALUE, struct tmx *))
+{
+ VALUE vfmt;
+ const char *fmt;
+ long len;
+ char buffer[SMALLBUF], *buf = buffer;
+ struct tmx tmx;
+ VALUE str;
+
+ rb_scan_args(argc, argv, "01", &vfmt);
+
+ if (argc < 1)
+ vfmt = rb_usascii_str_new2(default_fmt);
+ else {
+ StringValue(vfmt);
+ if (!rb_enc_str_asciicompat_p(vfmt)) {
+ rb_raise(rb_eArgError,
+ "format should have ASCII compatible encoding");
+ }
+ }
+ fmt = RSTRING_PTR(vfmt);
+ len = RSTRING_LEN(vfmt);
+ (*func)(self, &tmx);
+ if (memchr(fmt, '\0', len)) {
+ /* Ruby string may contain \0's. */
+ const char *p = fmt, *pe = fmt + len;
+
+ str = rb_str_new(0, 0);
+ while (p < pe) {
+ len = date_strftime_alloc(&buf, p, &tmx);
+ rb_str_cat(str, buf, len);
+ p += strlen(p);
+ if (buf != buffer) {
+ xfree(buf);
+ buf = buffer;
+ }
+ for (fmt = p; p < pe && !*p; ++p);
+ if (p > fmt) rb_str_cat(str, fmt, p - fmt);
+ }
+ rb_enc_copy(str, vfmt);
+ return str;
+ }
+ else
+ len = date_strftime_alloc(&buf, fmt, &tmx);
+
+ str = rb_str_new(buf, len);
+ if (buf != buffer) xfree(buf);
+ rb_enc_copy(str, vfmt);
+ return str;
+}
+
+/*
+ * call-seq:
+ * strftime(format = '%F') -> string
+ *
+ * Returns a string representation of the date in +self+,
+ * formatted according the given +format+:
+ *
+ * Date.new(2001, 2, 3).strftime # => "2001-02-03"
+ *
+ * For other formats, see
+ * {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc].
+ *
+ */
+static VALUE
+d_lite_strftime(int argc, VALUE *argv, VALUE self)
+{
+ return date_strftime_internal(argc, argv, self,
+ "%Y-%m-%d", set_tmx);
+}
+
+static VALUE
+strftimev(const char *fmt, VALUE self,
+ void (*func)(VALUE, struct tmx *))
+{
+ char buffer[SMALLBUF], *buf = buffer;
+ struct tmx tmx;
+ long len;
+ VALUE str;
+
+ (*func)(self, &tmx);
+ len = date_strftime_alloc(&buf, fmt, &tmx);
+ RB_GC_GUARD(self);
+ str = rb_usascii_str_new(buf, len);
+ if (buf != buffer) xfree(buf);
+ return str;
+}
+
+/*
+ * call-seq:
+ * asctime -> string
+ *
+ * Equivalent to #strftime with argument <tt>'%a %b %e %T %Y'</tt>
+ * (or its {shorthand form}[rdoc-ref:language/strftime_formatting.rdoc@Shorthand+Conversion+Specifiers]
+ * <tt>'%c'</tt>):
+ *
+ * Date.new(2001, 2, 3).asctime # => "Sat Feb 3 00:00:00 2001"
+ *
+ * See {asctime}[https://man7.org/linux/man-pages/man3/asctime.3p.html].
+ *
+ */
+static VALUE
+d_lite_asctime(VALUE self)
+{
+ return strftimev("%a %b %e %H:%M:%S %Y", self, set_tmx);
+}
+
+/*
+ * call-seq:
+ * iso8601 -> string
+ *
+ * Equivalent to #strftime with argument <tt>'%Y-%m-%d'</tt>
+ * (or its {shorthand form}[rdoc-ref:language/strftime_formatting.rdoc@Shorthand+Conversion+Specifiers]
+ * <tt>'%F'</tt>);
+ *
+ * Date.new(2001, 2, 3).iso8601 # => "2001-02-03"
+ *
+ */
+static VALUE
+d_lite_iso8601(VALUE self)
+{
+ return strftimev("%Y-%m-%d", self, set_tmx);
+}
+
+/*
+ * call-seq:
+ * rfc3339 -> string
+ *
+ * Equivalent to #strftime with argument <tt>'%FT%T%:z'</tt>;
+ * see {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]:
+ *
+ * Date.new(2001, 2, 3).rfc3339 # => "2001-02-03T00:00:00+00:00"
+ *
+ */
+static VALUE
+d_lite_rfc3339(VALUE self)
+{
+ return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx);
+}
+
+/*
+ * call-seq:
+ * rfc2822 -> string
+ *
+ * Equivalent to #strftime with argument <tt>'%a, %-d %b %Y %T %z'</tt>;
+ * see {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]:
+ *
+ * Date.new(2001, 2, 3).rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
+ *
+ */
+static VALUE
+d_lite_rfc2822(VALUE self)
+{
+ return strftimev("%a, %-d %b %Y %T %z", self, set_tmx);
+}
+
+/*
+ * call-seq:
+ * httpdate -> string
+ *
+ * Equivalent to #strftime with argument <tt>'%a, %d %b %Y %T GMT'</tt>;
+ * see {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]:
+ *
+ * Date.new(2001, 2, 3).httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
+ *
+ */
+static VALUE
+d_lite_httpdate(VALUE self)
+{
+ volatile VALUE dup = dup_obj_with_new_offset(self, 0);
+ return strftimev("%a, %d %b %Y %T GMT", dup, set_tmx);
+}
+
+enum {
+ DECIMAL_SIZE_OF_LONG = DECIMAL_SIZE_OF_BITS(CHAR_BIT*sizeof(long)),
+ JISX0301_DATE_SIZE = DECIMAL_SIZE_OF_LONG+8
+};
+
+static const char *
+jisx0301_date_format(char *fmt, size_t size, VALUE jd, VALUE y)
+{
+ if (FIXNUM_P(jd)) {
+ long d = FIX2INT(jd);
+ long s;
+ char c;
+ if (d < 2405160)
+ return "%Y-%m-%d";
+ if (d < 2419614) {
+ c = 'M';
+ s = 1867;
+ }
+ else if (d < 2424875) {
+ c = 'T';
+ s = 1911;
+ }
+ else if (d < 2447535) {
+ c = 'S';
+ s = 1925;
+ }
+ else if (d < 2458605) {
+ c = 'H';
+ s = 1988;
+ }
+ else {
+ c = 'R';
+ s = 2018;
+ }
+ snprintf(fmt, size, "%c%02ld" ".%%m.%%d", c, FIX2INT(y) - s);
+ return fmt;
+ }
+ return "%Y-%m-%d";
+}
+
+/*
+ * call-seq:
+ * jisx0301 -> string
+ *
+ * Returns a string representation of the date in +self+
+ * in JIS X 0301 format.
+ *
+ * Date.new(2001, 2, 3).jisx0301 # => "H13.02.03"
+ *
+ */
+static VALUE
+d_lite_jisx0301(VALUE self)
+{
+ char fmtbuf[JISX0301_DATE_SIZE];
+ const char *fmt;
+
+ get_d1(self);
+ fmt = jisx0301_date_format(fmtbuf, sizeof(fmtbuf),
+ m_real_local_jd(dat),
+ m_real_year(dat));
+ return strftimev(fmt, self, set_tmx);
+}
+
+static VALUE
+deconstruct_keys(VALUE self, VALUE keys, int is_datetime)
+{
+ VALUE h = rb_hash_new();
+ long i;
+
+ get_d1(self);
+
+ if (NIL_P(keys)) {
+ rb_hash_aset(h, sym_year, m_real_year(dat));
+ rb_hash_aset(h, sym_month, INT2FIX(m_mon(dat)));
+ rb_hash_aset(h, sym_day, INT2FIX(m_mday(dat)));
+ rb_hash_aset(h, sym_yday, INT2FIX(m_yday(dat)));
+ rb_hash_aset(h, sym_wday, INT2FIX(m_wday(dat)));
+ if (is_datetime) {
+ rb_hash_aset(h, sym_hour, INT2FIX(m_hour(dat)));
+ rb_hash_aset(h, sym_min, INT2FIX(m_min(dat)));
+ rb_hash_aset(h, sym_sec, INT2FIX(m_sec(dat)));
+ rb_hash_aset(h, sym_sec_fraction, m_sf_in_sec(dat));
+ rb_hash_aset(h, sym_zone, m_zone(dat));
+ }
+
+ return h;
+ }
+ if (!RB_TYPE_P(keys, T_ARRAY)) {
+ rb_raise(rb_eTypeError,
+ "wrong argument type %"PRIsVALUE" (expected Array or nil)",
+ rb_obj_class(keys));
+
+ }
+
+ for (i=0; i<RARRAY_LEN(keys); i++) {
+ VALUE key = RARRAY_AREF(keys, i);
+
+ if (sym_year == key) rb_hash_aset(h, key, m_real_year(dat));
+ if (sym_month == key) rb_hash_aset(h, key, INT2FIX(m_mon(dat)));
+ if (sym_day == key) rb_hash_aset(h, key, INT2FIX(m_mday(dat)));
+ if (sym_yday == key) rb_hash_aset(h, key, INT2FIX(m_yday(dat)));
+ if (sym_wday == key) rb_hash_aset(h, key, INT2FIX(m_wday(dat)));
+ if (is_datetime) {
+ if (sym_hour == key) rb_hash_aset(h, key, INT2FIX(m_hour(dat)));
+ if (sym_min == key) rb_hash_aset(h, key, INT2FIX(m_min(dat)));
+ if (sym_sec == key) rb_hash_aset(h, key, INT2FIX(m_sec(dat)));
+ if (sym_sec_fraction == key) rb_hash_aset(h, key, m_sf_in_sec(dat));
+ if (sym_zone == key) rb_hash_aset(h, key, m_zone(dat));
+ }
+ }
+ return h;
+}
+
+/*
+ * call-seq:
+ * deconstruct_keys(array_of_names_or_nil) -> hash
+ *
+ * Returns a hash of the name/value pairs, to use in pattern matching.
+ * Possible keys are: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
+ * <tt>:wday</tt>, <tt>:yday</tt>.
+ *
+ * Possible usages:
+ *
+ * d = Date.new(2022, 10, 5)
+ *
+ * if d in wday: 3, day: ..7 # uses deconstruct_keys underneath
+ * puts "first Wednesday of the month"
+ * end
+ * #=> prints "first Wednesday of the month"
+ *
+ * case d
+ * in year: ...2022
+ * puts "too old"
+ * in month: ..9
+ * puts "quarter 1-3"
+ * in wday: 1..5, month:
+ * puts "working day in month #{month}"
+ * end
+ * #=> prints "working day in month 10"
+ *
+ * Note that deconstruction by pattern can also be combined with class check:
+ *
+ * if d in Date(wday: 3, day: ..7)
+ * puts "first Wednesday of the month"
+ * end
+ *
+ */
+static VALUE
+d_lite_deconstruct_keys(VALUE self, VALUE keys)
+{
+ return deconstruct_keys(self, keys, /* is_datetime=false */ 0);
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+d_lite_marshal_dump_old(VALUE self)
+{
+ VALUE a;
+
+ get_d1(self);
+
+ a = rb_ary_new3(3,
+ m_ajd(dat),
+ m_of_in_day(dat),
+ DBL2NUM(m_sg(dat)));
+
+ rb_copy_generic_ivar(a, self);
+
+ return a;
+}
+#endif
+
+/* :nodoc: */
+static VALUE
+d_lite_marshal_dump(VALUE self)
+{
+ VALUE a;
+
+ get_d1(self);
+
+ a = rb_ary_new3(6,
+ m_nth(dat),
+ INT2FIX(m_jd(dat)),
+ INT2FIX(m_df(dat)),
+ m_sf(dat),
+ INT2FIX(m_of(dat)),
+ DBL2NUM(m_sg(dat)));
+
+
+ rb_copy_generic_ivar(a, self);
+
+ return a;
+}
+
+/* :nodoc: */
+static VALUE
+d_lite_marshal_load(VALUE self, VALUE a)
+{
+ VALUE nth, sf;
+ int jd, df, of;
+ double sg;
+
+ get_d1(self);
+
+ rb_check_frozen(self);
+
+ if (!RB_TYPE_P(a, T_ARRAY))
+ rb_raise(rb_eTypeError, "expected an array");
+
+ switch (RARRAY_LEN(a)) {
+ case 2: /* 1.6.x */
+ case 3: /* 1.8.x, 1.9.2 */
+ {
+ VALUE ajd, vof, vsg;
+
+ if (RARRAY_LEN(a) == 2) {
+ ajd = f_sub(RARRAY_AREF(a, 0), half_days_in_day);
+ vof = INT2FIX(0);
+ vsg = RARRAY_AREF(a, 1);
+ if (!k_numeric_p(vsg))
+ vsg = DBL2NUM(RTEST(vsg) ? GREGORIAN : JULIAN);
+ }
+ else {
+ ajd = RARRAY_AREF(a, 0);
+ vof = RARRAY_AREF(a, 1);
+ vsg = RARRAY_AREF(a, 2);
+ }
+
+ old_to_new(ajd, vof, vsg,
+ &nth, &jd, &df, &sf, &of, &sg);
+ }
+ break;
+ case 6:
+ {
+ nth = RARRAY_AREF(a, 0);
+ jd = NUM2INT(RARRAY_AREF(a, 1));
+ df = NUM2INT(RARRAY_AREF(a, 2));
+ sf = RARRAY_AREF(a, 3);
+ of = NUM2INT(RARRAY_AREF(a, 4));
+ sg = NUM2DBL(RARRAY_AREF(a, 5));
+ }
+ break;
+ default:
+ rb_raise(rb_eTypeError, "invalid size");
+ break;
+ }
+
+ if (simple_dat_p(dat)) {
+ if (df || !f_zero_p(sf) || of) {
+ /* loading a fractional date; promote to complex */
+ dat = ruby_xrealloc(dat, sizeof(struct ComplexDateData));
+ RTYPEDDATA(self)->data = dat;
+ goto complex_data;
+ }
+ set_to_simple(self, &dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
+ } else {
+ complex_data:
+ set_to_complex(self, &dat->c, nth, jd, df, sf, of, sg,
+ 0, 0, 0, 0, 0, 0,
+ HAVE_JD | HAVE_DF);
+ }
+
+ rb_copy_generic_ivar(self, a);
+
+ return self;
+}
+
+/* :nodoc: */
+static VALUE
+date_s__load(VALUE klass, VALUE s)
+{
+ VALUE a, obj;
+
+ a = rb_marshal_load(s);
+ obj = d_lite_s_alloc(klass);
+ return d_lite_marshal_load(obj, a);
+}
+
+/* datetime */
+
+/*
+ * call-seq:
+ * DateTime.jd([jd=0[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]) -> datetime
+ *
+ * Creates a DateTime object denoting the given chronological Julian
+ * day number.
+ *
+ * DateTime.jd(2451944) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
+ * DateTime.jd(2451945) #=> #<DateTime: 2001-02-04T00:00:00+00:00 ...>
+ * DateTime.jd(Rational('0.5'))
+ * #=> #<DateTime: -4712-01-01T12:00:00+00:00 ...>
+ */
+static VALUE
+datetime_s_jd(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vjd, vh, vmin, vs, vof, vsg, jd, fr, fr2, ret;
+ int h, min, s, rof;
+ double sg;
+
+ rb_scan_args(argc, argv, "06", &vjd, &vh, &vmin, &vs, &vof, &vsg);
+
+ jd = INT2FIX(0);
+
+ h = min = s = 0;
+ fr2 = INT2FIX(0);
+ rof = 0;
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 6:
+ val2sg(vsg, sg);
+ case 5:
+ val2off(vof, rof);
+ case 4:
+ check_numeric(vs, "second");
+ num2int_with_frac(s, positive_inf);
+ case 3:
+ check_numeric(vmin, "minute");
+ num2int_with_frac(min, 3);
+ case 2:
+ check_numeric(vh, "hour");
+ num2int_with_frac(h, 2);
+ case 1:
+ check_numeric(vjd, "jd");
+ num2num_with_frac(jd, 1);
+ }
+
+ {
+ VALUE nth;
+ int rh, rmin, rs, rjd, rjd2;
+
+ if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
+ rb_raise(eDateError, "invalid date");
+ canon24oc();
+
+ decode_jd(jd, &nth, &rjd);
+ rjd2 = jd_local_to_utc(rjd,
+ time_to_df(rh, rmin, rs),
+ rof);
+
+ ret = d_complex_new_internal(klass,
+ nth, rjd2,
+ 0, INT2FIX(0),
+ rof, sg,
+ 0, 0, 0,
+ rh, rmin, rs,
+ HAVE_JD | HAVE_TIME);
+ }
+ add_frac();
+ return ret;
+}
+
+/*
+ * call-seq:
+ * DateTime.ordinal([year=-4712[, yday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]) -> datetime
+ *
+ * Creates a DateTime object denoting the given ordinal date.
+ *
+ * DateTime.ordinal(2001,34) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
+ * DateTime.ordinal(2001,34,4,5,6,'+7')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ * DateTime.ordinal(2001,-332,-20,-55,-54,'+7')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ */
+static VALUE
+datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
+ int d, h, min, s, rof;
+ double sg;
+
+ rb_scan_args(argc, argv, "07", &vy, &vd, &vh, &vmin, &vs, &vof, &vsg);
+
+ y = INT2FIX(-4712);
+ d = 1;
+
+ h = min = s = 0;
+ fr2 = INT2FIX(0);
+ rof = 0;
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 7:
+ val2sg(vsg, sg);
+ case 6:
+ val2off(vof, rof);
+ case 5:
+ check_numeric(vs, "second");
+ num2int_with_frac(s, positive_inf);
+ case 4:
+ check_numeric(vmin, "minute");
+ num2int_with_frac(min, 4);
+ case 3:
+ check_numeric(vh, "hour");
+ num2int_with_frac(h, 3);
+ case 2:
+ check_numeric(vd, "yday");
+ num2int_with_frac(d, 2);
+ case 1:
+ check_numeric(vy, "year");
+ y = vy;
+ }
+
+ {
+ VALUE nth;
+ int ry, rd, rh, rmin, rs, rjd, rjd2, ns;
+
+ if (!valid_ordinal_p(y, d, sg,
+ &nth, &ry,
+ &rd, &rjd,
+ &ns))
+ rb_raise(eDateError, "invalid date");
+ if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
+ rb_raise(eDateError, "invalid date");
+ canon24oc();
+
+ rjd2 = jd_local_to_utc(rjd,
+ time_to_df(rh, rmin, rs),
+ rof);
+
+ ret = d_complex_new_internal(klass,
+ nth, rjd2,
+ 0, INT2FIX(0),
+ rof, sg,
+ 0, 0, 0,
+ rh, rmin, rs,
+ HAVE_JD | HAVE_TIME);
+ }
+ add_frac();
+ return ret;
+}
+
+/*
+ * Same as DateTime.new.
+ */
+static VALUE
+datetime_s_civil(int argc, VALUE *argv, VALUE klass)
+{
+ return datetime_initialize(argc, argv, d_lite_s_alloc_complex(klass));
+}
+
+static VALUE
+datetime_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE vy, vm, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
+ int m, d, h, min, s, rof;
+ double sg;
+ struct ComplexDateData *dat = rb_check_typeddata(self, &d_lite_type);
+
+ if (!complex_dat_p(dat)) {
+ rb_raise(rb_eTypeError, "DateTime expected");
+ }
+
+ rb_scan_args(argc, argv, "08", &vy, &vm, &vd, &vh, &vmin, &vs, &vof, &vsg);
+
+ y = INT2FIX(-4712);
+ m = 1;
+ d = 1;
+
+ h = min = s = 0;
+ fr2 = INT2FIX(0);
+ rof = 0;
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 8:
+ val2sg(vsg, sg);
+ case 7:
+ val2off(vof, rof);
+ case 6:
+ check_numeric(vs, "second");
+ num2int_with_frac(s, positive_inf);
+ case 5:
+ check_numeric(vmin, "minute");
+ num2int_with_frac(min, 5);
+ case 4:
+ check_numeric(vh, "hour");
+ num2int_with_frac(h, 4);
+ case 3:
+ check_numeric(vd, "day");
+ num2int_with_frac(d, 3);
+ case 2:
+ check_numeric(vm, "month");
+ m = NUM2INT(vm);
+ case 1:
+ check_numeric(vy, "year");
+ y = vy;
+ }
+
+ if (guess_style(y, sg) < 0) {
+ VALUE nth;
+ int ry, rm, rd, rh, rmin, rs;
+
+ if (!valid_gregorian_p(y, m, d,
+ &nth, &ry,
+ &rm, &rd))
+ rb_raise(eDateError, "invalid date");
+ if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
+ rb_raise(eDateError, "invalid date");
+ canon24oc();
+
+ set_to_complex(self, dat,
+ nth, 0,
+ 0, INT2FIX(0),
+ rof, sg,
+ ry, rm, rd,
+ rh, rmin, rs,
+ HAVE_CIVIL | HAVE_TIME);
+ }
+ else {
+ VALUE nth;
+ int ry, rm, rd, rh, rmin, rs, rjd, rjd2, ns;
+
+ if (!valid_civil_p(y, m, d, sg,
+ &nth, &ry,
+ &rm, &rd, &rjd,
+ &ns))
+ rb_raise(eDateError, "invalid date");
+ if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
+ rb_raise(eDateError, "invalid date");
+ canon24oc();
+
+ rjd2 = jd_local_to_utc(rjd,
+ time_to_df(rh, rmin, rs),
+ rof);
+
+ set_to_complex(self, dat,
+ nth, rjd2,
+ 0, INT2FIX(0),
+ rof, sg,
+ ry, rm, rd,
+ rh, rmin, rs,
+ HAVE_JD | HAVE_CIVIL | HAVE_TIME);
+ }
+ ret = self;
+ add_frac();
+ return ret;
+}
+
+/*
+ * call-seq:
+ * DateTime.commercial([cwyear=-4712[, cweek=1[, cwday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime
+ *
+ * Creates a DateTime object denoting the given week date.
+ *
+ * DateTime.commercial(2001) #=> #<DateTime: 2001-01-01T00:00:00+00:00 ...>
+ * DateTime.commercial(2002) #=> #<DateTime: 2001-12-31T00:00:00+00:00 ...>
+ * DateTime.commercial(2001,5,6,4,5,6,'+7')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ */
+static VALUE
+datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vw, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
+ int w, d, h, min, s, rof;
+ double sg;
+
+ rb_scan_args(argc, argv, "08", &vy, &vw, &vd, &vh, &vmin, &vs, &vof, &vsg);
+
+ y = INT2FIX(-4712);
+ w = 1;
+ d = 1;
+
+ h = min = s = 0;
+ fr2 = INT2FIX(0);
+ rof = 0;
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 8:
+ val2sg(vsg, sg);
+ case 7:
+ val2off(vof, rof);
+ case 6:
+ check_numeric(vs, "second");
+ num2int_with_frac(s, positive_inf);
+ case 5:
+ check_numeric(vmin, "minute");
+ num2int_with_frac(min, 5);
+ case 4:
+ check_numeric(vh, "hour");
+ num2int_with_frac(h, 4);
+ case 3:
+ check_numeric(vd, "cwday");
+ num2int_with_frac(d, 3);
+ case 2:
+ check_numeric(vw, "cweek");
+ w = NUM2INT(vw);
+ case 1:
+ check_numeric(vy, "year");
+ y = vy;
+ }
+
+ {
+ VALUE nth;
+ int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns;
+
+ if (!valid_commercial_p(y, w, d, sg,
+ &nth, &ry,
+ &rw, &rd, &rjd,
+ &ns))
+ rb_raise(eDateError, "invalid date");
+ if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
+ rb_raise(eDateError, "invalid date");
+ canon24oc();
+
+ rjd2 = jd_local_to_utc(rjd,
+ time_to_df(rh, rmin, rs),
+ rof);
+
+ ret = d_complex_new_internal(klass,
+ nth, rjd2,
+ 0, INT2FIX(0),
+ rof, sg,
+ 0, 0, 0,
+ rh, rmin, rs,
+ HAVE_JD | HAVE_TIME);
+ }
+ add_frac();
+ return ret;
+}
+
+#ifndef NDEBUG
+/* :nodoc: */
+static VALUE
+datetime_s_weeknum(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vw, vd, vf, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
+ int w, d, f, h, min, s, rof;
+ double sg;
+
+ rb_scan_args(argc, argv, "09", &vy, &vw, &vd, &vf,
+ &vh, &vmin, &vs, &vof, &vsg);
+
+ y = INT2FIX(-4712);
+ w = 0;
+ d = 1;
+ f = 0;
+
+ h = min = s = 0;
+ fr2 = INT2FIX(0);
+ rof = 0;
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 9:
+ val2sg(vsg, sg);
+ case 8:
+ val2off(vof, rof);
+ case 7:
+ num2int_with_frac(s, positive_inf);
+ case 6:
+ num2int_with_frac(min, 6);
+ case 5:
+ num2int_with_frac(h, 5);
+ case 4:
+ f = NUM2INT(vf);
+ case 3:
+ num2int_with_frac(d, 4);
+ case 2:
+ w = NUM2INT(vw);
+ case 1:
+ y = vy;
+ }
+
+ {
+ VALUE nth;
+ int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns;
+
+ if (!valid_weeknum_p(y, w, d, f, sg,
+ &nth, &ry,
+ &rw, &rd, &rjd,
+ &ns))
+ rb_raise(eDateError, "invalid date");
+ if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
+ rb_raise(eDateError, "invalid date");
+ canon24oc();
+
+ rjd2 = jd_local_to_utc(rjd,
+ time_to_df(rh, rmin, rs),
+ rof);
+ ret = d_complex_new_internal(klass,
+ nth, rjd2,
+ 0, INT2FIX(0),
+ rof, sg,
+ 0, 0, 0,
+ rh, rmin, rs,
+ HAVE_JD | HAVE_TIME);
+ }
+ add_frac();
+ return ret;
+}
+
+/* :nodoc: */
+static VALUE
+datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vm, vn, vk, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
+ int m, n, k, h, min, s, rof;
+ double sg;
+
+ rb_scan_args(argc, argv, "09", &vy, &vm, &vn, &vk,
+ &vh, &vmin, &vs, &vof, &vsg);
+
+ y = INT2FIX(-4712);
+ m = 1;
+ n = 1;
+ k = 1;
+
+ h = min = s = 0;
+ fr2 = INT2FIX(0);
+ rof = 0;
+ sg = DEFAULT_SG;
+
+ switch (argc) {
+ case 9:
+ val2sg(vsg, sg);
+ case 8:
+ val2off(vof, rof);
+ case 7:
+ num2int_with_frac(s, positive_inf);
+ case 6:
+ num2int_with_frac(min, 6);
+ case 5:
+ num2int_with_frac(h, 5);
+ case 4:
+ num2int_with_frac(k, 4);
+ case 3:
+ n = NUM2INT(vn);
+ case 2:
+ m = NUM2INT(vm);
+ case 1:
+ y = vy;
+ }
+
+ {
+ VALUE nth;
+ int ry, rm, rn, rk, rh, rmin, rs, rjd, rjd2, ns;
+
+ if (!valid_nth_kday_p(y, m, n, k, sg,
+ &nth, &ry,
+ &rm, &rn, &rk, &rjd,
+ &ns))
+ rb_raise(eDateError, "invalid date");
+ if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
+ rb_raise(eDateError, "invalid date");
+ canon24oc();
+
+ rjd2 = jd_local_to_utc(rjd,
+ time_to_df(rh, rmin, rs),
+ rof);
+ ret = d_complex_new_internal(klass,
+ nth, rjd2,
+ 0, INT2FIX(0),
+ rof, sg,
+ 0, 0, 0,
+ rh, rmin, rs,
+ HAVE_JD | HAVE_TIME);
+ }
+ add_frac();
+ return ret;
+}
+#endif
+
+/*
+ * call-seq:
+ * DateTime.now([start=Date::ITALY]) -> datetime
+ *
+ * Creates a DateTime object denoting the present time.
+ *
+ * DateTime.now #=> #<DateTime: 2011-06-11T21:20:44+09:00 ...>
+ */
+static VALUE
+datetime_s_now(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vsg, nth, ret;
+ double sg;
+#ifdef HAVE_CLOCK_GETTIME
+ struct timespec ts;
+#else
+ struct timeval tv;
+#endif
+ time_t sec;
+ struct tm tm;
+ long sf, of;
+ int y, ry, m, d, h, min, s;
+
+ rb_scan_args(argc, argv, "01", &vsg);
+
+ if (argc < 1)
+ sg = DEFAULT_SG;
+ else
+ sg = NUM2DBL(vsg);
+
+#ifdef HAVE_CLOCK_GETTIME
+ if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
+ rb_sys_fail("clock_gettime");
+ sec = ts.tv_sec;
+#else
+ if (gettimeofday(&tv, NULL) == -1)
+ rb_sys_fail("gettimeofday");
+ sec = tv.tv_sec;
+#endif
+ tzset();
+ if (!localtime_r(&sec, &tm))
+ rb_sys_fail("localtime");
+
+ y = tm.tm_year + 1900;
+ m = tm.tm_mon + 1;
+ d = tm.tm_mday;
+ h = tm.tm_hour;
+ min = tm.tm_min;
+ s = tm.tm_sec;
+ if (s == 60)
+ s = 59;
+#ifdef HAVE_STRUCT_TM_TM_GMTOFF
+ of = tm.tm_gmtoff;
+#elif defined(HAVE_TIMEZONE)
+#if defined(HAVE_ALTZONE) && !defined(_AIX)
+ of = (long)-((tm.tm_isdst > 0) ? altzone : timezone);
+#else
+ of = (long)-timezone;
+ if (tm.tm_isdst) {
+ time_t sec2;
+
+ tm.tm_isdst = 0;
+ sec2 = mktime(&tm);
+ of += (long)difftime(sec2, sec);
+ }
+#endif
+#elif defined(HAVE_TIMEGM)
+ {
+ time_t sec2;
+
+ sec2 = timegm(&tm);
+ of = (long)difftime(sec2, sec);
+ }
+#else
+ {
+ struct tm tm2;
+ time_t sec2;
+
+ if (!gmtime_r(&sec, &tm2))
+ rb_sys_fail("gmtime");
+ tm2.tm_isdst = tm.tm_isdst;
+ sec2 = mktime(&tm2);
+ of = (long)difftime(sec, sec2);
+ }
+#endif
+#ifdef HAVE_CLOCK_GETTIME
+ sf = ts.tv_nsec;
+#else
+ sf = tv.tv_usec * 1000;
+#endif
+
+ if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) {
+ of = 0;
+ rb_warning("invalid offset is ignored");
+ }
+
+ decode_year(INT2FIX(y), -1, &nth, &ry);
+
+ ret = d_complex_new_internal(klass,
+ nth, 0,
+ 0, LONG2NUM(sf),
+ (int)of, GREGORIAN,
+ ry, m, d,
+ h, min, s,
+ HAVE_CIVIL | HAVE_TIME);
+ {
+ get_d1(ret);
+ set_sg(dat, sg);
+ }
+ return ret;
+}
+
+static VALUE
+dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
+{
+ VALUE jd, sf, t;
+ int df, of;
+
+ if (!c_valid_start_p(NUM2DBL(sg))) {
+ sg = INT2FIX(DEFAULT_SG);
+ rb_warning("invalid start is ignored");
+ }
+
+ if (NIL_P(hash))
+ rb_raise(eDateError, "invalid date");
+
+ if (NIL_P(ref_hash("jd")) &&
+ NIL_P(ref_hash("yday")) &&
+ !NIL_P(ref_hash("year")) &&
+ !NIL_P(ref_hash("mon")) &&
+ !NIL_P(ref_hash("mday"))) {
+ jd = rt__valid_civil_p(ref_hash("year"),
+ ref_hash("mon"),
+ ref_hash("mday"), sg);
+
+ if (NIL_P(ref_hash("hour")))
+ set_hash("hour", INT2FIX(0));
+ if (NIL_P(ref_hash("min")))
+ set_hash("min", INT2FIX(0));
+ if (NIL_P(ref_hash("sec")))
+ set_hash("sec", INT2FIX(0));
+ else if (f_eqeq_p(ref_hash("sec"), INT2FIX(60)))
+ set_hash("sec", INT2FIX(59));
+ }
+ else {
+ hash = rt_rewrite_frags(hash);
+ hash = rt_complete_frags(klass, hash);
+ jd = rt__valid_date_frags_p(hash, sg);
+ }
+
+ if (NIL_P(jd))
+ rb_raise(eDateError, "invalid date");
+
+ {
+ int rh, rmin, rs;
+
+ if (!c_valid_time_p(NUM2INT(ref_hash("hour")),
+ NUM2INT(ref_hash("min")),
+ NUM2INT(ref_hash("sec")),
+ &rh, &rmin, &rs))
+ rb_raise(eDateError, "invalid date");
+
+ df = time_to_df(rh, rmin, rs);
+ }
+
+ t = ref_hash("sec_fraction");
+ if (NIL_P(t))
+ sf = INT2FIX(0);
+ else
+ sf = sec_to_ns(t);
+
+ t = ref_hash("offset");
+ if (NIL_P(t))
+ of = 0;
+ else {
+ of = NUM2INT(t);
+ if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) {
+ of = 0;
+ rb_warning("invalid offset is ignored");
+ }
+ }
+ {
+ VALUE nth;
+ int rjd, rjd2;
+
+ decode_jd(jd, &nth, &rjd);
+ rjd2 = jd_local_to_utc(rjd, df, of);
+ df = df_local_to_utc(df, of);
+
+ return d_complex_new_internal(klass,
+ nth, rjd2,
+ df, sf,
+ of, NUM2DBL(sg),
+ 0, 0, 0,
+ 0, 0, 0,
+ HAVE_JD | HAVE_DF);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime._strptime(string[, format='%FT%T%z']) -> hash
+ *
+ * Parses the given representation of date and time with the given
+ * template, and returns a hash of parsed elements. _strptime does
+ * not support specification of flags and width unlike strftime.
+ *
+ * See also strptime(3) and #strftime.
+ */
+static VALUE
+datetime_s__strptime(int argc, VALUE *argv, VALUE klass)
+{
+ return date_s__strptime_internal(argc, argv, klass, "%FT%T%z");
+}
+
+/*
+ * call-seq:
+ * DateTime.strptime([string='-4712-01-01T00:00:00+00:00'[, format='%FT%T%z'[ ,start=Date::ITALY]]]) -> datetime
+ *
+ * Parses the given representation of date and time with the given
+ * template, and creates a DateTime object. strptime does not support
+ * specification of flags and width unlike strftime.
+ *
+ * DateTime.strptime('2001-02-03T04:05:06+07:00', '%Y-%m-%dT%H:%M:%S%z')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ * DateTime.strptime('03-02-2001 04:05:06 PM', '%d-%m-%Y %I:%M:%S %p')
+ * #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
+ * DateTime.strptime('2001-W05-6T04:05:06+07:00', '%G-W%V-%uT%H:%M:%S%z')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ * DateTime.strptime('2001 04 6 04 05 06 +7', '%Y %U %w %H %M %S %z')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ * DateTime.strptime('2001 05 6 04 05 06 +7', '%Y %W %u %H %M %S %z')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ * DateTime.strptime('-1', '%s')
+ * #=> #<DateTime: 1969-12-31T23:59:59+00:00 ...>
+ * DateTime.strptime('-1000', '%Q')
+ * #=> #<DateTime: 1969-12-31T23:59:59+00:00 ...>
+ * DateTime.strptime('sat3feb014pm+7', '%a%d%b%y%H%p%z')
+ * #=> #<DateTime: 2001-02-03T16:00:00+07:00 ...>
+ *
+ * See also strptime(3) and #strftime.
+ */
+static VALUE
+datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, fmt, sg;
+
+ rb_scan_args(argc, argv, "03", &str, &fmt, &sg);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
+ case 1:
+ fmt = rb_str_new2("%FT%T%z");
+ case 2:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ VALUE argv2[2], hash;
+
+ argv2[0] = str;
+ argv2[1] = fmt;
+ hash = date_s__strptime(2, argv2, klass);
+ return dt_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]], limit: 128) -> datetime
+ *
+ * Parses the given representation of date and time, and creates a
+ * DateTime object.
+ *
+ * This method *does* *not* function as a validator. If the input
+ * string does not match valid formats strictly, you may get a cryptic
+ * result. Should consider to use DateTime.strptime instead of this
+ * method as possible.
+ *
+ * If the optional second argument is true and the detected year is in
+ * the range "00" to "99", makes it full.
+ *
+ * DateTime.parse('2001-02-03T04:05:06+07:00')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ * DateTime.parse('20010203T040506+0700')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ * DateTime.parse('3rd Feb 2001 04:05:06 PM')
+ * #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
+ */
+static VALUE
+datetime_s_parse(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, comp, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
+ case 1:
+ comp = Qtrue;
+ case 2:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 2;
+ VALUE argv2[3], hash;
+ argv2[0] = str;
+ argv2[1] = comp;
+ argv2[2] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__parse(argc2, argv2, klass);
+ return dt_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
+ *
+ * Creates a new DateTime object by parsing from a string according to
+ * some typical ISO 8601 formats.
+ *
+ * DateTime.iso8601('2001-02-03T04:05:06+07:00')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ * DateTime.iso8601('20010203T040506+0700')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ * DateTime.iso8601('2001-W05-6T04:05:06+07:00')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
+ */
+static VALUE
+datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
+ case 1:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ argv2[1] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__iso8601(argc2, argv2, klass);
+ return dt_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
+ *
+ * Creates a new DateTime object by parsing from a string according to
+ * some typical RFC 3339 formats.
+ *
+ * DateTime.rfc3339('2001-02-03T04:05:06+07:00')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
+ */
+static VALUE
+datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
+ case 1:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ argv2[1] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__rfc3339(argc2, argv2, klass);
+ return dt_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
+ *
+ * Creates a new DateTime object by parsing from a string according to
+ * some typical XML Schema formats.
+ *
+ * DateTime.xmlschema('2001-02-03T04:05:06+07:00')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
+ */
+static VALUE
+datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
+ case 1:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ argv2[1] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__xmlschema(argc2, argv2, klass);
+ return dt_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> datetime
+ * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> datetime
+ *
+ * Creates a new DateTime object by parsing from a string according to
+ * some typical RFC 2822 formats.
+ *
+ * DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
+ */
+static VALUE
+datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME_RFC3339);
+ case 1:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ argv2[1] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__rfc2822(argc2, argv2, klass);
+ return dt_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY]) -> datetime
+ *
+ * Creates a new DateTime object by parsing from a string according to
+ * some RFC 2616 format.
+ *
+ * DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT')
+ * #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
+ */
+static VALUE
+datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME_HTTPDATE);
+ case 1:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ argv2[1] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__httpdate(argc2, argv2, klass);
+ return dt_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
+ *
+ * Creates a new DateTime object by parsing from a string according to
+ * some typical JIS X 0301 formats.
+ *
+ * DateTime.jisx0301('H13.02.03T04:05:06+07:00')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * For no-era year, legacy format, Heisei is assumed.
+ *
+ * DateTime.jisx0301('13.02.03T04:05:06+07:00')
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
+ */
+static VALUE
+datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE str, sg, opt;
+
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+
+ switch (argc) {
+ case 0:
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
+ case 1:
+ sg = INT2FIX(DEFAULT_SG);
+ }
+
+ {
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ argv2[1] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__jisx0301(argc2, argv2, klass);
+ return dt_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * dt.to_s -> string
+ *
+ * Returns a string in an ISO 8601 format. (This method doesn't use the
+ * expanded representations.)
+ *
+ * DateTime.new(2001,2,3,4,5,6,'-7').to_s
+ * #=> "2001-02-03T04:05:06-07:00"
+ */
+static VALUE
+dt_lite_to_s(VALUE self)
+{
+ return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx);
+}
+
+/*
+ * call-seq:
+ * strftime(format = '%FT%T%:z') -> string
+ *
+ * Returns a string representation of +self+,
+ * formatted according the given +format:
+ *
+ * DateTime.now.strftime # => "2022-07-01T11:03:19-05:00"
+ *
+ * For other formats,
+ * see {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]:
+ *
+ */
+static VALUE
+dt_lite_strftime(int argc, VALUE *argv, VALUE self)
+{
+ return date_strftime_internal(argc, argv, self,
+ "%Y-%m-%dT%H:%M:%S%:z", set_tmx);
+}
+
+static VALUE
+iso8601_timediv(VALUE self, long n)
+{
+ static const char timefmt[] = "T%H:%M:%S";
+ static const char zone[] = "%:z";
+ char fmt[sizeof(timefmt) + sizeof(zone) + rb_strlen_lit(".%N") +
+ DECIMAL_SIZE_OF_LONG];
+ char *p = fmt;
+
+ memcpy(p, timefmt, sizeof(timefmt)-1);
+ p += sizeof(timefmt)-1;
+ if (n > 0) p += snprintf(p, fmt+sizeof(fmt)-p, ".%%%ldN", n);
+ memcpy(p, zone, sizeof(zone));
+ return strftimev(fmt, self, set_tmx);
+}
+
+/*
+ * call-seq:
+ * dt.iso8601([n=0]) -> string
+ * dt.xmlschema([n=0]) -> string
+ *
+ * This method is equivalent to strftime('%FT%T%:z').
+ * The optional argument +n+ is the number of digits for fractional seconds.
+ *
+ * DateTime.parse('2001-02-03T04:05:06.123456789+07:00').iso8601(9)
+ * #=> "2001-02-03T04:05:06.123456789+07:00"
+ */
+static VALUE
+dt_lite_iso8601(int argc, VALUE *argv, VALUE self)
+{
+ long n = 0;
+
+ rb_check_arity(argc, 0, 1);
+ if (argc >= 1)
+ n = NUM2LONG(argv[0]);
+
+ return rb_str_append(strftimev("%Y-%m-%d", self, set_tmx),
+ iso8601_timediv(self, n));
+}
+
+/*
+ * call-seq:
+ * dt.rfc3339([n=0]) -> string
+ *
+ * This method is equivalent to strftime('%FT%T%:z').
+ * The optional argument +n+ is the number of digits for fractional seconds.
+ *
+ * DateTime.parse('2001-02-03T04:05:06.123456789+07:00').rfc3339(9)
+ * #=> "2001-02-03T04:05:06.123456789+07:00"
+ */
+static VALUE
+dt_lite_rfc3339(int argc, VALUE *argv, VALUE self)
+{
+ return dt_lite_iso8601(argc, argv, self);
+}
+
+/*
+ * call-seq:
+ * dt.jisx0301([n=0]) -> string
+ *
+ * Returns a string in a JIS X 0301 format.
+ * The optional argument +n+ is the number of digits for fractional seconds.
+ *
+ * DateTime.parse('2001-02-03T04:05:06.123456789+07:00').jisx0301(9)
+ * #=> "H13.02.03T04:05:06.123456789+07:00"
+ */
+static VALUE
+dt_lite_jisx0301(int argc, VALUE *argv, VALUE self)
+{
+ long n = 0;
+
+ rb_check_arity(argc, 0, 1);
+ if (argc >= 1)
+ n = NUM2LONG(argv[0]);
+
+ return rb_str_append(d_lite_jisx0301(self),
+ iso8601_timediv(self, n));
+}
+
+/*
+ * call-seq:
+ * deconstruct_keys(array_of_names_or_nil) -> hash
+ *
+ * Returns a hash of the name/value pairs, to use in pattern matching.
+ * Possible keys are: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
+ * <tt>:wday</tt>, <tt>:yday</tt>, <tt>:hour</tt>, <tt>:min</tt>,
+ * <tt>:sec</tt>, <tt>:sec_fraction</tt>, <tt>:zone</tt>.
+ *
+ * Possible usages:
+ *
+ * dt = DateTime.new(2022, 10, 5, 13, 30)
+ *
+ * if d in wday: 1..5, hour: 10..18 # uses deconstruct_keys underneath
+ * puts "Working time"
+ * end
+ * #=> prints "Working time"
+ *
+ * case dt
+ * in year: ...2022
+ * puts "too old"
+ * in month: ..9
+ * puts "quarter 1-3"
+ * in wday: 1..5, month:
+ * puts "working day in month #{month}"
+ * end
+ * #=> prints "working day in month 10"
+ *
+ * Note that deconstruction by pattern can also be combined with class check:
+ *
+ * if d in DateTime(wday: 1..5, hour: 10..18, day: ..7)
+ * puts "Working time, first week of the month"
+ * end
+ *
+ */
+static VALUE
+dt_lite_deconstruct_keys(VALUE self, VALUE keys)
+{
+ return deconstruct_keys(self, keys, /* is_datetime=true */ 1);
+}
+
+/* conversions */
+
+#define f_subsec(x) rb_funcall(x, rb_intern("subsec"), 0)
+#define f_utc_offset(x) rb_funcall(x, rb_intern("utc_offset"), 0)
+#define f_local3(x,y,m,d) rb_funcall(x, rb_intern("local"), 3, y, m, d)
+
+/*
+ * call-seq:
+ * t.to_time -> time
+ *
+ * Returns self.
+ */
+static VALUE
+time_to_time(VALUE self)
+{
+ return self;
+}
+
+/*
+ * call-seq:
+ * t.to_date -> date
+ *
+ * Returns a Date object which denotes self.
+ */
+static VALUE
+time_to_date(VALUE self)
+{
+ VALUE y, nth, ret;
+ int ry, m, d;
+
+ y = f_year(self);
+ m = FIX2INT(f_mon(self));
+ d = FIX2INT(f_mday(self));
+
+ decode_year(y, -1, &nth, &ry);
+
+ ret = d_simple_new_internal(cDate,
+ nth, 0,
+ GREGORIAN,
+ ry, m, d,
+ HAVE_CIVIL);
+ {
+ get_d1(ret);
+ set_sg(dat, DEFAULT_SG);
+ }
+ return ret;
+}
+
+/*
+ * call-seq:
+ * t.to_datetime -> datetime
+ *
+ * Returns a DateTime object which denotes self.
+ */
+static VALUE
+time_to_datetime(VALUE self)
+{
+ VALUE y, sf, nth, ret;
+ int ry, m, d, h, min, s, of;
+
+ y = f_year(self);
+ m = FIX2INT(f_mon(self));
+ d = FIX2INT(f_mday(self));
+
+ h = FIX2INT(f_hour(self));
+ min = FIX2INT(f_min(self));
+ s = FIX2INT(f_sec(self));
+ if (s == 60)
+ s = 59;
+
+ sf = sec_to_ns(f_subsec(self));
+ of = FIX2INT(f_utc_offset(self));
+
+ decode_year(y, -1, &nth, &ry);
+
+ ret = d_complex_new_internal(cDateTime,
+ nth, 0,
+ 0, sf,
+ of, GREGORIAN,
+ ry, m, d,
+ h, min, s,
+ HAVE_CIVIL | HAVE_TIME);
+ {
+ get_d1(ret);
+ set_sg(dat, DEFAULT_SG);
+ }
+ return ret;
+}
+
+/*
+ * call-seq:
+ * to_time -> time
+ *
+ * Returns a new Time object with the same value as +self+;
+ * if +self+ is a Julian date, derives its Gregorian date
+ * for conversion to the \Time object:
+ *
+ * Date.new(2001, 2, 3).to_time # => 2001-02-03 00:00:00 -0600
+ * Date.new(2001, 2, 3, Date::JULIAN).to_time # => 2001-02-16 00:00:00 -0600
+ *
+ */
+static VALUE
+date_to_time(VALUE self)
+{
+ VALUE t;
+
+ get_d1a(self);
+
+ if (m_julian_p(adat)) {
+ VALUE g = d_lite_gregorian(self);
+ get_d1b(g);
+ adat = bdat;
+ self = g;
+ }
+
+ t = f_local3(rb_cTime,
+ m_real_year(adat),
+ INT2FIX(m_mon(adat)),
+ INT2FIX(m_mday(adat)));
+ RB_GC_GUARD(self); /* may be the converted gregorian */
+ return t;
+}
+
+/*
+ * call-seq:
+ * to_date -> self
+ *
+ * Returns +self+.
+ */
+static VALUE
+date_to_date(VALUE self)
+{
+ return self;
+}
+
+/*
+ * call-seq:
+ * d.to_datetime -> datetime
+ *
+ * Returns a DateTime whose value is the same as +self+:
+ *
+ * Date.new(2001, 2, 3).to_datetime # => #<DateTime: 2001-02-03T00:00:00+00:00>
+ *
+ */
+static VALUE
+date_to_datetime(VALUE self)
+{
+ get_d1a(self);
+
+ if (simple_dat_p(adat)) {
+ VALUE new = d_lite_s_alloc_simple(cDateTime);
+ {
+ get_d1b(new);
+ bdat->s = adat->s;
+ return new;
+ }
+ }
+ else {
+ VALUE new = d_lite_s_alloc_complex(cDateTime);
+ {
+ get_d1b(new);
+ bdat->c = adat->c;
+ bdat->c.df = 0;
+ RB_OBJ_WRITE(new, &bdat->c.sf, INT2FIX(0));
+#ifndef USE_PACK
+ bdat->c.hour = 0;
+ bdat->c.min = 0;
+ bdat->c.sec = 0;
+#else
+ bdat->c.pc = PACK5(EX_MON(adat->c.pc), EX_MDAY(adat->c.pc),
+ 0, 0, 0);
+ bdat->c.flags |= HAVE_DF | HAVE_TIME;
+#endif
+ return new;
+ }
+ }
+}
+
+/*
+ * call-seq:
+ * dt.to_time -> time
+ *
+ * Returns a Time object which denotes self.
+ */
+static VALUE
+datetime_to_time(VALUE self)
+{
+ get_d1(self);
+
+ if (m_julian_p(dat)) {
+ VALUE g = d_lite_gregorian(self);
+ get_d1a(g);
+ dat = adat;
+ self = g;
+ }
+
+ {
+ VALUE t;
+
+ t = rb_funcall(rb_cTime,
+ rb_intern("new"),
+ 7,
+ m_real_year(dat),
+ INT2FIX(m_mon(dat)),
+ INT2FIX(m_mday(dat)),
+ INT2FIX(m_hour(dat)),
+ INT2FIX(m_min(dat)),
+ f_add(INT2FIX(m_sec(dat)),
+ m_sf_in_sec(dat)),
+ INT2FIX(m_of(dat)));
+ RB_GC_GUARD(self); /* may be the converted gregorian */
+ return t;
+ }
+}
+
+/*
+ * call-seq:
+ * dt.to_date -> date
+ *
+ * Returns a Date object which denotes self.
+ */
+static VALUE
+datetime_to_date(VALUE self)
+{
+ get_d1a(self);
+
+ if (simple_dat_p(adat)) {
+ VALUE new = d_lite_s_alloc_simple(cDate);
+ {
+ get_d1b(new);
+ bdat->s = adat->s;
+ bdat->s.jd = m_local_jd(adat);
+ return new;
+ }
+ }
+ else {
+ VALUE new = d_lite_s_alloc_simple(cDate);
+ {
+ get_d1b(new);
+ copy_complex_to_simple(new, &bdat->s, &adat->c);
+ bdat->s.jd = m_local_jd(adat);
+ bdat->s.flags &= ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT);
+ return new;
+ }
+ }
+}
+
+/*
+ * call-seq:
+ * dt.to_datetime -> self
+ *
+ * Returns self.
+ */
+static VALUE
+datetime_to_datetime(VALUE self)
+{
+ return self;
+}
+
+#ifndef NDEBUG
+/* tests */
+
+#define MIN_YEAR -4713
+#define MAX_YEAR 1000000
+#define MIN_JD -327
+#define MAX_JD 366963925
+
+/* :nodoc: */
+static int
+test_civil(int from, int to, double sg)
+{
+ int j;
+
+ fprintf(stderr, "test_civil: %d...%d (%d) - %.0f\n",
+ from, to, to - from, sg);
+ for (j = from; j <= to; j++) {
+ int y, m, d, rj, ns;
+
+ c_jd_to_civil(j, sg, &y, &m, &d);
+ c_civil_to_jd(y, m, d, sg, &rj, &ns);
+ if (j != rj) {
+ fprintf(stderr, "%d != %d\n", j, rj);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* :nodoc: */
+static VALUE
+date_s_test_civil(VALUE klass)
+{
+ if (!test_civil(MIN_JD, MIN_JD + 366, GREGORIAN))
+ return Qfalse;
+ if (!test_civil(2305814, 2598007, GREGORIAN))
+ return Qfalse;
+ if (!test_civil(MAX_JD - 366, MAX_JD, GREGORIAN))
+ return Qfalse;
+
+ if (!test_civil(MIN_JD, MIN_JD + 366, ITALY))
+ return Qfalse;
+ if (!test_civil(2305814, 2598007, ITALY))
+ return Qfalse;
+ if (!test_civil(MAX_JD - 366, MAX_JD, ITALY))
+ return Qfalse;
+
+ return Qtrue;
+}
+
+/* :nodoc: */
+static int
+test_ordinal(int from, int to, double sg)
+{
+ int j;
+
+ fprintf(stderr, "test_ordinal: %d...%d (%d) - %.0f\n",
+ from, to, to - from, sg);
+ for (j = from; j <= to; j++) {
+ int y, d, rj, ns;
+
+ c_jd_to_ordinal(j, sg, &y, &d);
+ c_ordinal_to_jd(y, d, sg, &rj, &ns);
+ if (j != rj) {
+ fprintf(stderr, "%d != %d\n", j, rj);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* :nodoc: */
+static VALUE
+date_s_test_ordinal(VALUE klass)
+{
+ if (!test_ordinal(MIN_JD, MIN_JD + 366, GREGORIAN))
+ return Qfalse;
+ if (!test_ordinal(2305814, 2598007, GREGORIAN))
+ return Qfalse;
+ if (!test_ordinal(MAX_JD - 366, MAX_JD, GREGORIAN))
+ return Qfalse;
+
+ if (!test_ordinal(MIN_JD, MIN_JD + 366, ITALY))
+ return Qfalse;
+ if (!test_ordinal(2305814, 2598007, ITALY))
+ return Qfalse;
+ if (!test_ordinal(MAX_JD - 366, MAX_JD, ITALY))
+ return Qfalse;
+
+ return Qtrue;
+}
+
+/* :nodoc: */
+static int
+test_commercial(int from, int to, double sg)
+{
+ int j;
+
+ fprintf(stderr, "test_commercial: %d...%d (%d) - %.0f\n",
+ from, to, to - from, sg);
+ for (j = from; j <= to; j++) {
+ int y, w, d, rj, ns;
+
+ c_jd_to_commercial(j, sg, &y, &w, &d);
+ c_commercial_to_jd(y, w, d, sg, &rj, &ns);
+ if (j != rj) {
+ fprintf(stderr, "%d != %d\n", j, rj);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* :nodoc: */
+static VALUE
+date_s_test_commercial(VALUE klass)
+{
+ if (!test_commercial(MIN_JD, MIN_JD + 366, GREGORIAN))
+ return Qfalse;
+ if (!test_commercial(2305814, 2598007, GREGORIAN))
+ return Qfalse;
+ if (!test_commercial(MAX_JD - 366, MAX_JD, GREGORIAN))
+ return Qfalse;
+
+ if (!test_commercial(MIN_JD, MIN_JD + 366, ITALY))
+ return Qfalse;
+ if (!test_commercial(2305814, 2598007, ITALY))
+ return Qfalse;
+ if (!test_commercial(MAX_JD - 366, MAX_JD, ITALY))
+ return Qfalse;
+
+ return Qtrue;
+}
+
+/* :nodoc: */
+static int
+test_weeknum(int from, int to, int f, double sg)
+{
+ int j;
+
+ fprintf(stderr, "test_weeknum: %d...%d (%d) - %.0f\n",
+ from, to, to - from, sg);
+ for (j = from; j <= to; j++) {
+ int y, w, d, rj, ns;
+
+ c_jd_to_weeknum(j, f, sg, &y, &w, &d);
+ c_weeknum_to_jd(y, w, d, f, sg, &rj, &ns);
+ if (j != rj) {
+ fprintf(stderr, "%d != %d\n", j, rj);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* :nodoc: */
+static VALUE
+date_s_test_weeknum(VALUE klass)
+{
+ int f;
+
+ for (f = 0; f <= 1; f++) {
+ if (!test_weeknum(MIN_JD, MIN_JD + 366, f, GREGORIAN))
+ return Qfalse;
+ if (!test_weeknum(2305814, 2598007, f, GREGORIAN))
+ return Qfalse;
+ if (!test_weeknum(MAX_JD - 366, MAX_JD, f, GREGORIAN))
+ return Qfalse;
+
+ if (!test_weeknum(MIN_JD, MIN_JD + 366, f, ITALY))
+ return Qfalse;
+ if (!test_weeknum(2305814, 2598007, f, ITALY))
+ return Qfalse;
+ if (!test_weeknum(MAX_JD - 366, MAX_JD, f, ITALY))
+ return Qfalse;
+ }
+
+ return Qtrue;
+}
+
+/* :nodoc: */
+static int
+test_nth_kday(int from, int to, double sg)
+{
+ int j;
+
+ fprintf(stderr, "test_nth_kday: %d...%d (%d) - %.0f\n",
+ from, to, to - from, sg);
+ for (j = from; j <= to; j++) {
+ int y, m, n, k, rj, ns;
+
+ c_jd_to_nth_kday(j, sg, &y, &m, &n, &k);
+ c_nth_kday_to_jd(y, m, n, k, sg, &rj, &ns);
+ if (j != rj) {
+ fprintf(stderr, "%d != %d\n", j, rj);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* :nodoc: */
+static VALUE
+date_s_test_nth_kday(VALUE klass)
+{
+ if (!test_nth_kday(MIN_JD, MIN_JD + 366, GREGORIAN))
+ return Qfalse;
+ if (!test_nth_kday(2305814, 2598007, GREGORIAN))
+ return Qfalse;
+ if (!test_nth_kday(MAX_JD - 366, MAX_JD, GREGORIAN))
+ return Qfalse;
+
+ if (!test_nth_kday(MIN_JD, MIN_JD + 366, ITALY))
+ return Qfalse;
+ if (!test_nth_kday(2305814, 2598007, ITALY))
+ return Qfalse;
+ if (!test_nth_kday(MAX_JD - 366, MAX_JD, ITALY))
+ return Qfalse;
+
+ return Qtrue;
+}
+
+/* :nodoc: */
+static int
+test_unit_v2v(VALUE i,
+ VALUE (* conv1)(VALUE),
+ VALUE (* conv2)(VALUE))
+{
+ VALUE c, o;
+ c = (*conv1)(i);
+ o = (*conv2)(c);
+ return f_eqeq_p(o, i);
+}
+
+/* :nodoc: */
+static int
+test_unit_v2v_iter2(VALUE (* conv1)(VALUE),
+ VALUE (* conv2)(VALUE))
+{
+ if (!test_unit_v2v(INT2FIX(0), conv1, conv2))
+ return 0;
+ if (!test_unit_v2v(INT2FIX(1), conv1, conv2))
+ return 0;
+ if (!test_unit_v2v(INT2FIX(2), conv1, conv2))
+ return 0;
+ if (!test_unit_v2v(INT2FIX(3), conv1, conv2))
+ return 0;
+ if (!test_unit_v2v(INT2FIX(11), conv1, conv2))
+ return 0;
+ if (!test_unit_v2v(INT2FIX(65535), conv1, conv2))
+ return 0;
+ if (!test_unit_v2v(INT2FIX(1073741823), conv1, conv2))
+ return 0;
+ if (!test_unit_v2v(INT2NUM(1073741824), conv1, conv2))
+ return 0;
+ if (!test_unit_v2v(rb_rational_new2(INT2FIX(0), INT2FIX(1)), conv1, conv2))
+ return 0;
+ if (!test_unit_v2v(rb_rational_new2(INT2FIX(1), INT2FIX(1)), conv1, conv2))
+ return 0;
+ if (!test_unit_v2v(rb_rational_new2(INT2FIX(1), INT2FIX(2)), conv1, conv2))
+ return 0;
+ if (!test_unit_v2v(rb_rational_new2(INT2FIX(2), INT2FIX(3)), conv1, conv2))
+ return 0;
+ return 1;
+}
+
+/* :nodoc: */
+static int
+test_unit_v2v_iter(VALUE (* conv1)(VALUE),
+ VALUE (* conv2)(VALUE))
+{
+ if (!test_unit_v2v_iter2(conv1, conv2))
+ return 0;
+ if (!test_unit_v2v_iter2(conv2, conv1))
+ return 0;
+ return 1;
+}
+
+/* :nodoc: */
+static VALUE
+date_s_test_unit_conv(VALUE klass)
+{
+ if (!test_unit_v2v_iter(sec_to_day, day_to_sec))
+ return Qfalse;
+ if (!test_unit_v2v_iter(ms_to_sec, sec_to_ms))
+ return Qfalse;
+ if (!test_unit_v2v_iter(ns_to_day, day_to_ns))
+ return Qfalse;
+ if (!test_unit_v2v_iter(ns_to_sec, sec_to_ns))
+ return Qfalse;
+ return Qtrue;
+}
+
+/* :nodoc: */
+static VALUE
+date_s_test_all(VALUE klass)
+{
+ if (date_s_test_civil(klass) == Qfalse)
+ return Qfalse;
+ if (date_s_test_ordinal(klass) == Qfalse)
+ return Qfalse;
+ if (date_s_test_commercial(klass) == Qfalse)
+ return Qfalse;
+ if (date_s_test_weeknum(klass) == Qfalse)
+ return Qfalse;
+ if (date_s_test_nth_kday(klass) == Qfalse)
+ return Qfalse;
+ if (date_s_test_unit_conv(klass) == Qfalse)
+ return Qfalse;
+ return Qtrue;
+}
+#endif
+
+static const char *monthnames[] = {
+ NULL,
+ "January", "February", "March",
+ "April", "May", "June",
+ "July", "August", "September",
+ "October", "November", "December"
+};
+
+static const char *abbr_monthnames[] = {
+ NULL,
+ "Jan", "Feb", "Mar", "Apr",
+ "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec"
+};
+
+static const char *daynames[] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday"
+};
+
+static const char *abbr_daynames[] = {
+ "Sun", "Mon", "Tue", "Wed",
+ "Thu", "Fri", "Sat"
+};
+
+static VALUE
+mk_ary_of_str(long len, const char *a[])
+{
+ VALUE o;
+ long i;
+
+ o = rb_ary_new2(len);
+ for (i = 0; i < len; i++) {
+ VALUE e;
+
+ if (!a[i])
+ e = Qnil;
+ else {
+ e = rb_usascii_str_new2(a[i]);
+ rb_obj_freeze(e);
+ }
+ rb_ary_push(o, e);
+ }
+ rb_ary_freeze(o);
+ return o;
+}
+
+/* :nodoc: */
+static VALUE
+d_lite_zero(VALUE x)
+{
+ return INT2FIX(0);
+}
+
+void
+Init_date_core(void)
+{
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
+ RB_EXT_RACTOR_SAFE(true);
+ #endif
+ id_cmp = rb_intern_const("<=>");
+ id_le_p = rb_intern_const("<=");
+ id_ge_p = rb_intern_const(">=");
+ id_eqeq_p = rb_intern_const("==");
+
+ sym_year = ID2SYM(rb_intern_const("year"));
+ sym_month = ID2SYM(rb_intern_const("month"));
+ sym_yday = ID2SYM(rb_intern_const("yday"));
+ sym_wday = ID2SYM(rb_intern_const("wday"));
+ sym_day = ID2SYM(rb_intern_const("day"));
+ sym_hour = ID2SYM(rb_intern_const("hour"));
+ sym_min = ID2SYM(rb_intern_const("min"));
+ sym_sec = ID2SYM(rb_intern_const("sec"));
+ sym_sec_fraction = ID2SYM(rb_intern_const("sec_fraction"));
+ sym_zone = ID2SYM(rb_intern_const("zone"));
+
+ half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2));
+ rb_gc_register_mark_object(half_days_in_day);
+
+#if (LONG_MAX / DAY_IN_SECONDS) > SECOND_IN_NANOSECONDS
+ day_in_nanoseconds = LONG2NUM((long)DAY_IN_SECONDS *
+ SECOND_IN_NANOSECONDS);
+#elif defined HAVE_LONG_LONG
+ day_in_nanoseconds = LL2NUM((LONG_LONG)DAY_IN_SECONDS *
+ SECOND_IN_NANOSECONDS);
+#else
+ day_in_nanoseconds = f_mul(INT2FIX(DAY_IN_SECONDS),
+ INT2FIX(SECOND_IN_NANOSECONDS));
+#endif
+ rb_gc_register_mark_object(day_in_nanoseconds);
+
+ positive_inf = +INFINITY;
+ negative_inf = -INFINITY;
+
+ /*
+ * \Class \Date provides methods for storing and manipulating
+ * calendar dates.
+ *
+ * Consider using
+ * {class Time}[rdoc-ref:Time]
+ * instead of class \Date if:
+ *
+ * - You need both dates and times; \Date handles only dates.
+ * - You need only Gregorian dates (and not Julian dates);
+ * see {Julian and Gregorian Calendars}[rdoc-ref:language/calendars.rdoc].
+ *
+ * A \Date object, once created, is immutable, and cannot be modified.
+ *
+ * == Creating a \Date
+ *
+ * You can create a date for the current date, using Date.today:
+ *
+ * Date.today # => #<Date: 1999-12-31>
+ *
+ * You can create a specific date from various combinations of arguments:
+ *
+ * - Date.new takes integer year, month, and day-of-month:
+ *
+ * Date.new(1999, 12, 31) # => #<Date: 1999-12-31>
+ *
+ * - Date.ordinal takes integer year and day-of-year:
+ *
+ * Date.ordinal(1999, 365) # => #<Date: 1999-12-31>
+ *
+ * - Date.jd takes integer Julian day:
+ *
+ * Date.jd(2451544) # => #<Date: 1999-12-31>
+ *
+ * - Date.commercial takes integer commercial data (year, week, day-of-week):
+ *
+ * Date.commercial(1999, 52, 5) # => #<Date: 1999-12-31>
+ *
+ * - Date.parse takes a string, which it parses heuristically:
+ *
+ * Date.parse('1999-12-31') # => #<Date: 1999-12-31>
+ * Date.parse('31-12-1999') # => #<Date: 1999-12-31>
+ * Date.parse('1999-365') # => #<Date: 1999-12-31>
+ * Date.parse('1999-W52-5') # => #<Date: 1999-12-31>
+ *
+ * - Date.strptime takes a date string and a format string,
+ * then parses the date string according to the format string:
+ *
+ * Date.strptime('1999-12-31', '%Y-%m-%d') # => #<Date: 1999-12-31>
+ * Date.strptime('31-12-1999', '%d-%m-%Y') # => #<Date: 1999-12-31>
+ * Date.strptime('1999-365', '%Y-%j') # => #<Date: 1999-12-31>
+ * Date.strptime('1999-W52-5', '%G-W%V-%u') # => #<Date: 1999-12-31>
+ * Date.strptime('1999 52 5', '%Y %U %w') # => #<Date: 1999-12-31>
+ * Date.strptime('1999 52 5', '%Y %W %u') # => #<Date: 1999-12-31>
+ * Date.strptime('fri31dec99', '%a%d%b%y') # => #<Date: 1999-12-31>
+ *
+ * See also the specialized methods in
+ * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc@Specialized+Format+Strings]
+ *
+ * == Argument +limit+
+ *
+ * Certain singleton methods in \Date that parse string arguments
+ * also take optional keyword argument +limit+,
+ * which can limit the length of the string argument.
+ *
+ * When +limit+ is:
+ *
+ * - Non-negative:
+ * raises ArgumentError if the string length is greater than _limit_.
+ * - Other numeric or +nil+: ignores +limit+.
+ * - Other non-numeric: raises TypeError.
+ *
+ */
+ cDate = rb_define_class("Date", rb_cObject);
+
+ /* Exception for invalid date/time */
+ eDateError = rb_define_class_under(cDate, "Error", rb_eArgError);
+
+ rb_include_module(cDate, rb_mComparable);
+
+ /* An array of strings of full month names in English. The first
+ * element is nil.
+ */
+ rb_define_const(cDate, "MONTHNAMES", mk_ary_of_str(13, monthnames));
+
+ /* An array of strings of abbreviated month names in English. The
+ * first element is nil.
+ */
+ rb_define_const(cDate, "ABBR_MONTHNAMES",
+ mk_ary_of_str(13, abbr_monthnames));
+
+ /* An array of strings of the full names of days of the week in English.
+ * The first is "Sunday".
+ */
+ rb_define_const(cDate, "DAYNAMES", mk_ary_of_str(7, daynames));
+
+ /* An array of strings of abbreviated day names in English. The
+ * first is "Sun".
+ */
+ rb_define_const(cDate, "ABBR_DAYNAMES", mk_ary_of_str(7, abbr_daynames));
+
+ /* The Julian day number of the day of calendar reform for Italy
+ * and some catholic countries.
+ */
+ rb_define_const(cDate, "ITALY", INT2FIX(ITALY));
+
+ /* The Julian day number of the day of calendar reform for England
+ * and her colonies.
+ */
+ rb_define_const(cDate, "ENGLAND", INT2FIX(ENGLAND));
+
+ /* The Julian day number of the day of calendar reform for the
+ * proleptic Julian calendar.
+ */
+ rb_define_const(cDate, "JULIAN", DBL2NUM(JULIAN));
+
+ /* The Julian day number of the day of calendar reform for the
+ * proleptic Gregorian calendar.
+ */
+ rb_define_const(cDate, "GREGORIAN", DBL2NUM(GREGORIAN));
+
+ rb_define_alloc_func(cDate, d_lite_s_alloc_simple);
+
+#ifndef NDEBUG
+ rb_define_private_method(CLASS_OF(cDate), "_valid_jd?",
+ date_s__valid_jd_p, -1);
+ rb_define_private_method(CLASS_OF(cDate), "_valid_ordinal?",
+ date_s__valid_ordinal_p, -1);
+ rb_define_private_method(CLASS_OF(cDate), "_valid_civil?",
+ date_s__valid_civil_p, -1);
+ rb_define_private_method(CLASS_OF(cDate), "_valid_date?",
+ date_s__valid_civil_p, -1);
+ rb_define_private_method(CLASS_OF(cDate), "_valid_commercial?",
+ date_s__valid_commercial_p, -1);
+ rb_define_private_method(CLASS_OF(cDate), "_valid_weeknum?",
+ date_s__valid_weeknum_p, -1);
+ rb_define_private_method(CLASS_OF(cDate), "_valid_nth_kday?",
+ date_s__valid_nth_kday_p, -1);
+#endif
+
+ rb_define_singleton_method(cDate, "valid_jd?", date_s_valid_jd_p, -1);
+ rb_define_singleton_method(cDate, "valid_ordinal?",
+ date_s_valid_ordinal_p, -1);
+ rb_define_singleton_method(cDate, "valid_civil?", date_s_valid_civil_p, -1);
+ rb_define_singleton_method(cDate, "valid_date?", date_s_valid_civil_p, -1);
+ rb_define_singleton_method(cDate, "valid_commercial?",
+ date_s_valid_commercial_p, -1);
+
+#ifndef NDEBUG
+ rb_define_private_method(CLASS_OF(cDate), "valid_weeknum?",
+ date_s_valid_weeknum_p, -1);
+ rb_define_private_method(CLASS_OF(cDate), "valid_nth_kday?",
+ date_s_valid_nth_kday_p, -1);
+ rb_define_private_method(CLASS_OF(cDate), "zone_to_diff",
+ date_s_zone_to_diff, 1);
+#endif
+
+ rb_define_singleton_method(cDate, "julian_leap?", date_s_julian_leap_p, 1);
+ rb_define_singleton_method(cDate, "gregorian_leap?",
+ date_s_gregorian_leap_p, 1);
+ rb_define_singleton_method(cDate, "leap?",
+ date_s_gregorian_leap_p, 1);
+
+#ifndef NDEBUG
+ rb_define_singleton_method(cDate, "new!", date_s_new_bang, -1);
+ rb_define_alias(rb_singleton_class(cDate), "new_l!", "new");
+#endif
+
+ rb_define_singleton_method(cDate, "jd", date_s_jd, -1);
+ rb_define_singleton_method(cDate, "ordinal", date_s_ordinal, -1);
+ rb_define_singleton_method(cDate, "civil", date_s_civil, -1);
+ rb_define_singleton_method(cDate, "commercial", date_s_commercial, -1);
+
+#ifndef NDEBUG
+ rb_define_singleton_method(cDate, "weeknum", date_s_weeknum, -1);
+ rb_define_singleton_method(cDate, "nth_kday", date_s_nth_kday, -1);
+#endif
+
+ rb_define_singleton_method(cDate, "today", date_s_today, -1);
+ rb_define_singleton_method(cDate, "_strptime", date_s__strptime, -1);
+ rb_define_singleton_method(cDate, "strptime", date_s_strptime, -1);
+ rb_define_singleton_method(cDate, "_parse", date_s__parse, -1);
+ rb_define_singleton_method(cDate, "parse", date_s_parse, -1);
+ rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, -1);
+ rb_define_singleton_method(cDate, "iso8601", date_s_iso8601, -1);
+ rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, -1);
+ rb_define_singleton_method(cDate, "rfc3339", date_s_rfc3339, -1);
+ rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, -1);
+ rb_define_singleton_method(cDate, "xmlschema", date_s_xmlschema, -1);
+ rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, -1);
+ rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, -1);
+ rb_define_singleton_method(cDate, "rfc2822", date_s_rfc2822, -1);
+ rb_define_singleton_method(cDate, "rfc822", date_s_rfc2822, -1);
+ rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, -1);
+ rb_define_singleton_method(cDate, "httpdate", date_s_httpdate, -1);
+ rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, -1);
+ rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1);
+
+ rb_define_method(cDate, "initialize", date_initialize, -1);
+ rb_define_method(cDate, "initialize_copy", d_lite_initialize_copy, 1);
+
+#ifndef NDEBUG
+ rb_define_method(cDate, "fill", d_lite_fill, 0);
+#endif
+
+ rb_define_method(cDate, "ajd", d_lite_ajd, 0);
+ rb_define_method(cDate, "amjd", d_lite_amjd, 0);
+ rb_define_method(cDate, "jd", d_lite_jd, 0);
+ rb_define_method(cDate, "mjd", d_lite_mjd, 0);
+ rb_define_method(cDate, "ld", d_lite_ld, 0);
+
+ rb_define_method(cDate, "year", d_lite_year, 0);
+ rb_define_method(cDate, "yday", d_lite_yday, 0);
+ rb_define_method(cDate, "mon", d_lite_mon, 0);
+ rb_define_method(cDate, "month", d_lite_mon, 0);
+ rb_define_method(cDate, "mday", d_lite_mday, 0);
+ rb_define_method(cDate, "day", d_lite_mday, 0);
+ rb_define_method(cDate, "day_fraction", d_lite_day_fraction, 0);
+
+ rb_define_method(cDate, "cwyear", d_lite_cwyear, 0);
+ rb_define_method(cDate, "cweek", d_lite_cweek, 0);
+ rb_define_method(cDate, "cwday", d_lite_cwday, 0);
+
+#ifndef NDEBUG
+ rb_define_private_method(cDate, "wnum0", d_lite_wnum0, 0);
+ rb_define_private_method(cDate, "wnum1", d_lite_wnum1, 0);
+#endif
+
+ rb_define_method(cDate, "wday", d_lite_wday, 0);
+
+ rb_define_method(cDate, "sunday?", d_lite_sunday_p, 0);
+ rb_define_method(cDate, "monday?", d_lite_monday_p, 0);
+ rb_define_method(cDate, "tuesday?", d_lite_tuesday_p, 0);
+ rb_define_method(cDate, "wednesday?", d_lite_wednesday_p, 0);
+ rb_define_method(cDate, "thursday?", d_lite_thursday_p, 0);
+ rb_define_method(cDate, "friday?", d_lite_friday_p, 0);
+ rb_define_method(cDate, "saturday?", d_lite_saturday_p, 0);
+
+#ifndef NDEBUG
+ rb_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2);
+#endif
+
+ rb_define_private_method(cDate, "hour", d_lite_zero, 0);
+ rb_define_private_method(cDate, "min", d_lite_zero, 0);
+ rb_define_private_method(cDate, "minute", d_lite_zero, 0);
+ rb_define_private_method(cDate, "sec", d_lite_zero, 0);
+ rb_define_private_method(cDate, "second", d_lite_zero, 0);
+
+ rb_define_method(cDate, "julian?", d_lite_julian_p, 0);
+ rb_define_method(cDate, "gregorian?", d_lite_gregorian_p, 0);
+ rb_define_method(cDate, "leap?", d_lite_leap_p, 0);
+
+ rb_define_method(cDate, "start", d_lite_start, 0);
+ rb_define_method(cDate, "new_start", d_lite_new_start, -1);
+ rb_define_method(cDate, "italy", d_lite_italy, 0);
+ rb_define_method(cDate, "england", d_lite_england, 0);
+ rb_define_method(cDate, "julian", d_lite_julian, 0);
+ rb_define_method(cDate, "gregorian", d_lite_gregorian, 0);
+
+ rb_define_method(cDate, "+", d_lite_plus, 1);
+ rb_define_method(cDate, "-", d_lite_minus, 1);
+
+ rb_define_method(cDate, "next_day", d_lite_next_day, -1);
+ rb_define_method(cDate, "prev_day", d_lite_prev_day, -1);
+ rb_define_method(cDate, "next", d_lite_next, 0);
+ rb_define_method(cDate, "succ", d_lite_next, 0);
+
+ rb_define_method(cDate, ">>", d_lite_rshift, 1);
+ rb_define_method(cDate, "<<", d_lite_lshift, 1);
+
+ rb_define_method(cDate, "next_month", d_lite_next_month, -1);
+ rb_define_method(cDate, "prev_month", d_lite_prev_month, -1);
+ rb_define_method(cDate, "next_year", d_lite_next_year, -1);
+ rb_define_method(cDate, "prev_year", d_lite_prev_year, -1);
+
+ rb_define_method(cDate, "step", d_lite_step, -1);
+ rb_define_method(cDate, "upto", d_lite_upto, 1);
+ rb_define_method(cDate, "downto", d_lite_downto, 1);
+
+ rb_define_method(cDate, "<=>", d_lite_cmp, 1);
+ rb_define_method(cDate, "===", d_lite_equal, 1);
+ rb_define_method(cDate, "eql?", d_lite_eql_p, 1);
+ rb_define_method(cDate, "hash", d_lite_hash, 0);
+
+ rb_define_method(cDate, "to_s", d_lite_to_s, 0);
+#ifndef NDEBUG
+ rb_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0);
+#endif
+ rb_define_method(cDate, "inspect", d_lite_inspect, 0);
+
+ rb_define_method(cDate, "strftime", d_lite_strftime, -1);
+
+ rb_define_method(cDate, "asctime", d_lite_asctime, 0);
+ rb_define_method(cDate, "ctime", d_lite_asctime, 0);
+ rb_define_method(cDate, "iso8601", d_lite_iso8601, 0);
+ rb_define_method(cDate, "xmlschema", d_lite_iso8601, 0);
+ rb_define_method(cDate, "rfc3339", d_lite_rfc3339, 0);
+ rb_define_method(cDate, "rfc2822", d_lite_rfc2822, 0);
+ rb_define_method(cDate, "rfc822", d_lite_rfc2822, 0);
+ rb_define_method(cDate, "httpdate", d_lite_httpdate, 0);
+ rb_define_method(cDate, "jisx0301", d_lite_jisx0301, 0);
+
+ rb_define_method(cDate, "deconstruct_keys", d_lite_deconstruct_keys, 1);
+
+#ifndef NDEBUG
+ rb_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0);
+#endif
+ rb_define_method(cDate, "marshal_dump", d_lite_marshal_dump, 0);
+ rb_define_method(cDate, "marshal_load", d_lite_marshal_load, 1);
+ rb_define_singleton_method(cDate, "_load", date_s__load, 1);
+
+ /*
+ * == DateTime
+ *
+ * A subclass of Date that easily handles date, hour, minute, second,
+ * and offset.
+ *
+ * DateTime class is considered deprecated. Use Time class.
+ *
+ * DateTime does not consider any leap seconds, does not track
+ * any summer time rules.
+ *
+ * A DateTime object is created with DateTime::new, DateTime::jd,
+ * DateTime::ordinal, DateTime::commercial, DateTime::parse,
+ * DateTime::strptime, DateTime::now, Time#to_datetime, etc.
+ *
+ * require 'date'
+ *
+ * DateTime.new(2001,2,3,4,5,6)
+ * #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
+ *
+ * The last element of day, hour, minute, or second can be a
+ * fractional number. The fractional number's precision is assumed
+ * at most nanosecond.
+ *
+ * DateTime.new(2001,2,3.5)
+ * #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...>
+ *
+ * An optional argument, the offset, indicates the difference
+ * between the local time and UTC. For example, <tt>Rational(3,24)</tt>
+ * represents ahead of 3 hours of UTC, <tt>Rational(-5,24)</tt> represents
+ * behind of 5 hours of UTC. The offset should be -1 to +1, and
+ * its precision is assumed at most second. The default value is
+ * zero (equals to UTC).
+ *
+ * DateTime.new(2001,2,3,4,5,6,Rational(3,24))
+ * #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
+ *
+ * The offset also accepts string form:
+ *
+ * DateTime.new(2001,2,3,4,5,6,'+03:00')
+ * #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
+ *
+ * An optional argument, the day of calendar reform (+start+), denotes
+ * a Julian day number, which should be 2298874 to 2426355 or
+ * negative/positive infinity.
+ * The default value is +Date::ITALY+ (2299161=1582-10-15).
+ *
+ * A DateTime object has various methods. See each reference.
+ *
+ * d = DateTime.parse('3rd Feb 2001 04:05:06+03:30')
+ * #=> #<DateTime: 2001-02-03T04:05:06+03:30 ...>
+ * d.hour #=> 4
+ * d.min #=> 5
+ * d.sec #=> 6
+ * d.offset #=> (7/48)
+ * d.zone #=> "+03:30"
+ * d += Rational('1.5')
+ * #=> #<DateTime: 2001-02-04%16:05:06+03:30 ...>
+ * d = d.new_offset('+09:00')
+ * #=> #<DateTime: 2001-02-04%21:35:06+09:00 ...>
+ * d.strftime('%I:%M:%S %p')
+ * #=> "09:35:06 PM"
+ * d > DateTime.new(1999)
+ * #=> true
+ *
+ * === When should you use DateTime and when should you use Time?
+ *
+ * It's a common misconception that
+ * {William Shakespeare}[https://en.wikipedia.org/wiki/William_Shakespeare]
+ * and
+ * {Miguel de Cervantes}[https://en.wikipedia.org/wiki/Miguel_de_Cervantes]
+ * died on the same day in history -
+ * so much so that UNESCO named April 23 as
+ * {World Book Day because of this fact}[https://en.wikipedia.org/wiki/World_Book_Day].
+ * However, because England hadn't yet adopted the
+ * {Gregorian Calendar Reform}[https://en.wikipedia.org/wiki/Gregorian_calendar#Gregorian_reform]
+ * (and wouldn't until {1752}[https://en.wikipedia.org/wiki/Calendar_(New_Style)_Act_1750])
+ * their deaths are actually 10 days apart.
+ * Since Ruby's Time class implements a
+ * {proleptic Gregorian calendar}[https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar]
+ * and has no concept of calendar reform there's no way
+ * to express this with Time objects. This is where DateTime steps in:
+ *
+ * shakespeare = DateTime.iso8601('1616-04-23', Date::ENGLAND)
+ * #=> Tue, 23 Apr 1616 00:00:00 +0000
+ * cervantes = DateTime.iso8601('1616-04-23', Date::ITALY)
+ * #=> Sat, 23 Apr 1616 00:00:00 +0000
+ *
+ * Already you can see something is weird - the days of the week
+ * are different. Taking this further:
+ *
+ * cervantes == shakespeare
+ * #=> false
+ * (shakespeare - cervantes).to_i
+ * #=> 10
+ *
+ * This shows that in fact they died 10 days apart (in reality
+ * 11 days since Cervantes died a day earlier but was buried on
+ * the 23rd). We can see the actual date of Shakespeare's death by
+ * using the #gregorian method to convert it:
+ *
+ * shakespeare.gregorian
+ * #=> Tue, 03 May 1616 00:00:00 +0000
+ *
+ * So there's an argument that all the celebrations that take
+ * place on the 23rd April in Stratford-upon-Avon are actually
+ * the wrong date since England is now using the Gregorian calendar.
+ * You can see why when we transition across the reform
+ * date boundary:
+ *
+ * # start off with the anniversary of Shakespeare's birth in 1751
+ * shakespeare = DateTime.iso8601('1751-04-23', Date::ENGLAND)
+ * #=> Tue, 23 Apr 1751 00:00:00 +0000
+ *
+ * # add 366 days since 1752 is a leap year and April 23 is after February 29
+ * shakespeare + 366
+ * #=> Thu, 23 Apr 1752 00:00:00 +0000
+ *
+ * # add another 365 days to take us to the anniversary in 1753
+ * shakespeare + 366 + 365
+ * #=> Fri, 04 May 1753 00:00:00 +0000
+ *
+ * As you can see, if we're accurately tracking the number of
+ * {solar years}[https://en.wikipedia.org/wiki/Tropical_year]
+ * since Shakespeare's birthday then the correct anniversary date
+ * would be the 4th May and not the 23rd April.
+ *
+ * So when should you use DateTime in Ruby and when should
+ * you use Time? Almost certainly you'll want to use Time
+ * since your app is probably dealing with current dates and
+ * times. However, if you need to deal with dates and times in a
+ * historical context you'll want to use DateTime to avoid
+ * making the same mistakes as UNESCO. If you also have to deal
+ * with timezones then best of luck - just bear in mind that
+ * you'll probably be dealing with
+ * {local solar times}[https://en.wikipedia.org/wiki/Solar_time],
+ * since it wasn't until the 19th century that the introduction
+ * of the railways necessitated the need for
+ * {Standard Time}[https://en.wikipedia.org/wiki/Standard_time#Great_Britain]
+ * and eventually timezones.
+ */
+
+ cDateTime = rb_define_class("DateTime", cDate);
+ rb_define_alloc_func(cDateTime, d_lite_s_alloc_complex);
+
+ rb_define_singleton_method(cDateTime, "jd", datetime_s_jd, -1);
+ rb_define_singleton_method(cDateTime, "ordinal", datetime_s_ordinal, -1);
+ rb_define_singleton_method(cDateTime, "civil", datetime_s_civil, -1);
+ rb_define_singleton_method(cDateTime, "new", datetime_s_civil, -1);
+ rb_define_singleton_method(cDateTime, "commercial",
+ datetime_s_commercial, -1);
+
+#ifndef NDEBUG
+ rb_define_singleton_method(cDateTime, "weeknum",
+ datetime_s_weeknum, -1);
+ rb_define_singleton_method(cDateTime, "nth_kday",
+ datetime_s_nth_kday, -1);
+#endif
+
+ rb_undef_method(CLASS_OF(cDateTime), "today");
+
+ rb_define_singleton_method(cDateTime, "now", datetime_s_now, -1);
+ rb_define_singleton_method(cDateTime, "_strptime",
+ datetime_s__strptime, -1);
+ rb_define_singleton_method(cDateTime, "strptime",
+ datetime_s_strptime, -1);
+ rb_define_singleton_method(cDateTime, "parse",
+ datetime_s_parse, -1);
+ rb_define_singleton_method(cDateTime, "iso8601",
+ datetime_s_iso8601, -1);
+ rb_define_singleton_method(cDateTime, "rfc3339",
+ datetime_s_rfc3339, -1);
+ rb_define_singleton_method(cDateTime, "xmlschema",
+ datetime_s_xmlschema, -1);
+ rb_define_singleton_method(cDateTime, "rfc2822",
+ datetime_s_rfc2822, -1);
+ rb_define_singleton_method(cDateTime, "rfc822",
+ datetime_s_rfc2822, -1);
+ rb_define_singleton_method(cDateTime, "httpdate",
+ datetime_s_httpdate, -1);
+ rb_define_singleton_method(cDateTime, "jisx0301",
+ datetime_s_jisx0301, -1);
+
+ rb_define_method(cDateTime, "hour", d_lite_hour, 0);
+ rb_define_method(cDateTime, "min", d_lite_min, 0);
+ rb_define_method(cDateTime, "minute", d_lite_min, 0);
+ rb_define_method(cDateTime, "sec", d_lite_sec, 0);
+ rb_define_method(cDateTime, "second", d_lite_sec, 0);
+ rb_define_method(cDateTime, "sec_fraction", d_lite_sec_fraction, 0);
+ rb_define_method(cDateTime, "second_fraction", d_lite_sec_fraction, 0);
+ rb_define_method(cDateTime, "offset", d_lite_offset, 0);
+ rb_define_method(cDateTime, "zone", d_lite_zone, 0);
+ rb_define_method(cDateTime, "new_offset", d_lite_new_offset, -1);
+
+ rb_define_method(cDateTime, "to_s", dt_lite_to_s, 0);
+
+ rb_define_method(cDateTime, "strftime", dt_lite_strftime, -1);
+
+ rb_define_method(cDateTime, "iso8601", dt_lite_iso8601, -1);
+ rb_define_method(cDateTime, "xmlschema", dt_lite_iso8601, -1);
+ rb_define_method(cDateTime, "rfc3339", dt_lite_rfc3339, -1);
+ rb_define_method(cDateTime, "jisx0301", dt_lite_jisx0301, -1);
+
+ rb_define_method(cDateTime, "deconstruct_keys", dt_lite_deconstruct_keys, 1);
+
+ /* conversions */
+
+ rb_define_method(rb_cTime, "to_time", time_to_time, 0);
+ rb_define_method(rb_cTime, "to_date", time_to_date, 0);
+ rb_define_method(rb_cTime, "to_datetime", time_to_datetime, 0);
+
+ rb_define_method(cDate, "to_time", date_to_time, 0);
+ rb_define_method(cDate, "to_date", date_to_date, 0);
+ rb_define_method(cDate, "to_datetime", date_to_datetime, 0);
+
+ rb_define_method(cDateTime, "to_time", datetime_to_time, 0);
+ rb_define_method(cDateTime, "to_date", datetime_to_date, 0);
+ rb_define_method(cDateTime, "to_datetime", datetime_to_datetime, 0);
+
+#ifndef NDEBUG
+ /* tests */
+
+ rb_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0);
+ rb_define_singleton_method(cDate, "test_ordinal", date_s_test_ordinal, 0);
+ rb_define_singleton_method(cDate, "test_commercial",
+ date_s_test_commercial, 0);
+ rb_define_singleton_method(cDate, "test_weeknum", date_s_test_weeknum, 0);
+ rb_define_singleton_method(cDate, "test_nth_kday", date_s_test_nth_kday, 0);
+ rb_define_singleton_method(cDate, "test_unit_conv",
+ date_s_test_unit_conv, 0);
+ rb_define_singleton_method(cDate, "test_all", date_s_test_all, 0);
+#endif
+}
+
+/*
+Local variables:
+c-file-style: "ruby"
+End:
+*/
diff --git a/ext/date/date_parse.c b/ext/date/date_parse.c
new file mode 100644
index 0000000000..a1600e4708
--- /dev/null
+++ b/ext/date/date_parse.c
@@ -0,0 +1,3086 @@
+/*
+ date_parse.c: Coded by Tadayoshi Funaba 2011,2012
+*/
+
+#include "ruby.h"
+#include "ruby/encoding.h"
+#include "ruby/re.h"
+#include <ctype.h>
+
+#undef strncasecmp
+#define strncasecmp STRNCASECMP
+
+RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y);
+RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow);
+
+/* #define TIGHT_PARSER */
+
+#define sizeof_array(o) (sizeof o / sizeof o[0])
+
+#define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
+#define f_add(x,y) rb_funcall(x, '+', 1, y)
+#define f_sub(x,y) rb_funcall(x, '-', 1, y)
+#define f_mul(x,y) rb_funcall(x, '*', 1, y)
+#define f_div(x,y) rb_funcall(x, '/', 1, y)
+#define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
+#define f_mod(x,y) rb_funcall(x, '%', 1, y)
+#define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
+
+#define f_lt_p(x,y) rb_funcall(x, '<', 1, y)
+#define f_gt_p(x,y) rb_funcall(x, '>', 1, y)
+#define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y)
+#define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y)
+
+#define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
+
+#define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s)
+#define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i)
+#define f_aref2(o,i,j) rb_funcall(o, rb_intern("[]"), 2, i, j)
+#define f_begin(o,i) rb_funcall(o, rb_intern("begin"), 1, i)
+#define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i)
+#define f_aset(o,i,v) rb_funcall(o, rb_intern("[]="), 2, i, v)
+#define f_aset2(o,i,j,v) rb_funcall(o, rb_intern("[]="), 3, i, j, v)
+#define f_sub_bang(s,r,x) rb_funcall(s, rb_intern("sub!"), 2, r, x)
+#define f_gsub_bang(s,r,x) rb_funcall(s, rb_intern("gsub!"), 2, r, x)
+
+#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k"")), v)
+#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k"")))
+#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k"")))
+
+#define cstr2num(s) rb_cstr_to_inum(s, 10, 0)
+#define str2num(s) rb_str_to_inum(s, 10, 0)
+
+static const char abbr_days[][4] = {
+ "sun", "mon", "tue", "wed",
+ "thu", "fri", "sat"
+};
+
+static const char abbr_months[][4] = {
+ "jan", "feb", "mar", "apr", "may", "jun",
+ "jul", "aug", "sep", "oct", "nov", "dec"
+};
+
+#define issign(c) ((c) == '-' || (c) == '+')
+#define asp_string() rb_str_new(" ", 1)
+#ifdef TIGHT_PARSER
+#define asuba_string() rb_str_new("\001", 1)
+#define asubb_string() rb_str_new("\002", 1)
+#define asubw_string() rb_str_new("\027", 1)
+#define asubt_string() rb_str_new("\024", 1)
+#endif
+
+static size_t
+digit_span(const char *s, const char *e)
+{
+ size_t i = 0;
+ while (s + i < e && isdigit((unsigned char)s[i])) i++;
+ return i;
+}
+
+static void
+s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
+{
+ VALUE vbuf = 0;
+ VALUE c = Qnil;
+
+ if (!RB_TYPE_P(m, T_STRING))
+ m = f_to_s(m);
+
+ if (!NIL_P(y) && !NIL_P(m) && NIL_P(d)) {
+ VALUE oy = y;
+ VALUE om = m;
+ VALUE od = d;
+
+ y = od;
+ m = oy;
+ d = om;
+ }
+
+ if (NIL_P(y)) {
+ if (!NIL_P(d) && RSTRING_LEN(d) > 2) {
+ y = d;
+ d = Qnil;
+ }
+ if (!NIL_P(d) && RSTRING_LEN(d) > 0 && *RSTRING_PTR(d) == '\'') {
+ y = d;
+ d = Qnil;
+ }
+ }
+
+ if (!NIL_P(y)) {
+ const char *s, *bp, *ep;
+ size_t l;
+
+ s = RSTRING_PTR(y);
+ ep = RSTRING_END(y);
+ while (s < ep && !issign(*s) && !isdigit((unsigned char)*s))
+ s++;
+ if (s >= ep) goto no_date;
+ bp = s;
+ if (issign((unsigned char)*s))
+ s++;
+ l = digit_span(s, ep);
+ ep = s + l;
+ if (*ep) {
+ y = d;
+ d = rb_str_new(bp, ep - bp);
+ }
+ no_date:;
+ }
+
+ if (!NIL_P(m)) {
+ const char *s;
+
+ s = RSTRING_PTR(m);
+ if (*s == '\'' || RSTRING_LEN(m) > 2) {
+ /* us -> be */
+ VALUE oy = y;
+ VALUE om = m;
+ VALUE od = d;
+
+ y = om;
+ m = od;
+ d = oy;
+ }
+ }
+
+ if (!NIL_P(d)) {
+ const char *s;
+
+ s = RSTRING_PTR(d);
+ if (*s == '\'' || RSTRING_LEN(d) > 2) {
+ VALUE oy = y;
+ VALUE od = d;
+
+ y = od;
+ d = oy;
+ }
+ }
+
+ if (!NIL_P(y)) {
+ const char *s, *bp, *ep;
+ int sign = 0;
+ size_t l;
+ VALUE iy;
+
+ s = RSTRING_PTR(y);
+ ep = RSTRING_END(y);
+ while (s < ep && !issign(*s) && !isdigit((unsigned char)*s))
+ s++;
+ if (s >= ep) goto no_year;
+ bp = s;
+ if (issign(*s)) {
+ s++;
+ sign = 1;
+ }
+ if (sign)
+ c = Qfalse;
+ l = digit_span(s, ep);
+ ep = s + l;
+ if (l > 2)
+ c = Qfalse;
+ {
+ char *buf;
+
+ buf = ALLOCV_N(char, vbuf, ep - bp + 1);
+ memcpy(buf, bp, ep - bp);
+ buf[ep - bp] = '\0';
+ iy = cstr2num(buf);
+ ALLOCV_END(vbuf);
+ }
+ set_hash("year", iy);
+ no_year:;
+ }
+
+ if (bc)
+ set_hash("_bc", Qtrue);
+
+ if (!NIL_P(m)) {
+ const char *s, *bp, *ep;
+ size_t l;
+ VALUE im;
+
+ s = RSTRING_PTR(m);
+ ep = RSTRING_END(m);
+ while (s < ep && !isdigit((unsigned char)*s))
+ s++;
+ if (s >= ep) goto no_month;
+ bp = s;
+ l = digit_span(s, ep);
+ ep = s + l;
+ {
+ char *buf;
+
+ buf = ALLOCV_N(char, vbuf, ep - bp + 1);
+ memcpy(buf, bp, ep - bp);
+ buf[ep - bp] = '\0';
+ im = cstr2num(buf);
+ ALLOCV_END(vbuf);
+ }
+ set_hash("mon", im);
+ no_month:;
+ }
+
+ if (!NIL_P(d)) {
+ const char *s, *bp, *ep;
+ size_t l;
+ VALUE id;
+
+ s = RSTRING_PTR(d);
+ ep = RSTRING_END(d);
+ while (s < ep && !isdigit((unsigned char)*s))
+ s++;
+ if (s >= ep) goto no_mday;
+ bp = s;
+ l = digit_span(s, ep);
+ ep = s + l;
+ {
+ char *buf;
+
+ buf = ALLOCV_N(char, vbuf, ep - bp + 1);
+ memcpy(buf, bp, ep - bp);
+ buf[ep - bp] = '\0';
+ id = cstr2num(buf);
+ ALLOCV_END(vbuf);
+ }
+ set_hash("mday", id);
+ no_mday:;
+ }
+
+ if (!NIL_P(c))
+ set_hash("_comp", c);
+}
+
+#define DAYS "sunday|monday|tuesday|wednesday|thursday|friday|saturday"
+#define MONTHS "january|february|march|april|may|june|july|august|september|october|november|december"
+#define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat"
+#define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec"
+
+#define NUMBER "(?<!\\d)\\d"
+
+#ifdef TIGHT_PARSER
+#define VALID_DAYS "(?:" DAYS ")" "|(?:tues|wednes|thurs|thur|" ABBR_DAYS ")\\.?"
+#define VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")\\.?"
+#define DOTLESS_VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")"
+#define BOS "\\A\\s*"
+#define FPA "\\001"
+#define FPB "\\002"
+#define FPW "\\027"
+#define FPT "\\024"
+#define FPW_COM "\\s*(?:" FPW "\\s*,?)?\\s*"
+#define FPT_COM "\\s*(?:" FPT "\\s*,?)?\\s*"
+#define COM_FPW "\\s*(?:,?\\s*" FPW ")?\\s*"
+#define COM_FPT "\\s*(?:,?\\s*(?:@|\\b[aA][tT]\\b)?\\s*" FPT ")?\\s*"
+#define TEE_FPT "\\s*(?:[tT]?" FPT ")?"
+#define EOS "\\s*\\z"
+#endif
+
+static VALUE
+regcomp(const char *source, long len, int opt)
+{
+ VALUE pat;
+
+ pat = rb_reg_new(source, len, opt);
+ rb_obj_freeze(pat);
+ rb_gc_register_mark_object(pat);
+ return pat;
+}
+
+#define REGCOMP(pat,opt) \
+do { \
+ if (NIL_P(pat)) \
+ pat = regcomp(pat##_source, sizeof pat##_source - 1, opt); \
+} while (0)
+
+#define REGCOMP_0(pat) REGCOMP(pat, 0)
+#define REGCOMP_I(pat) REGCOMP(pat, ONIG_OPTION_IGNORECASE)
+
+#define MATCH(s,p,c) \
+do { \
+ return match(s, p, hash, c); \
+} while (0)
+
+static int
+match(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
+{
+ VALUE m;
+
+ m = f_match(pat, str);
+
+ if (NIL_P(m))
+ return 0;
+
+ (*cb)(m, hash);
+
+ return 1;
+}
+
+static int
+subx(VALUE str, VALUE rep, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
+{
+ VALUE m;
+
+ m = f_match(pat, str);
+
+ if (NIL_P(m))
+ return 0;
+
+ {
+ VALUE be, en;
+
+ be = f_begin(m, INT2FIX(0));
+ en = f_end(m, INT2FIX(0));
+ f_aset2(str, be, LONG2NUM(NUM2LONG(en) - NUM2LONG(be)), rep);
+ (*cb)(m, hash);
+ }
+
+ return 1;
+}
+
+#define SUBS(s,p,c) \
+do { \
+ return subx(s, asp_string(), p, hash, c); \
+} while (0)
+
+#ifdef TIGHT_PARSER
+#define SUBA(s,p,c) \
+do { \
+ return subx(s, asuba_string(), p, hash, c); \
+} while (0)
+
+#define SUBB(s,p,c) \
+do { \
+ return subx(s, asubb_string(), p, hash, c); \
+} while (0)
+
+#define SUBW(s,p,c) \
+do { \
+ return subx(s, asubw_string(), p, hash, c); \
+} while (0)
+
+#define SUBT(s,p,c) \
+do { \
+ return subx(s, asubt_string(), p, hash, c); \
+} while (0)
+#endif
+
+#include "zonetab.h"
+
+static int
+str_end_with_word(const char *s, long l, const char *w)
+{
+ int n = (int)strlen(w);
+ if (l <= n || !isspace((unsigned char)s[l - n - 1])) return 0;
+ if (strncasecmp(&s[l - n], w, n)) return 0;
+ do ++n; while (l > n && isspace((unsigned char)s[l - n - 1]));
+ return n;
+}
+
+static long
+shrunk_size(const char *s, long l)
+{
+ long i, ni;
+ int sp = 0;
+ for (i = ni = 0; i < l; ++i) {
+ if (!isspace((unsigned char)s[i])) {
+ if (sp) ni++;
+ sp = 0;
+ ni++;
+ }
+ else {
+ sp = 1;
+ }
+ }
+ return ni < l ? ni : 0;
+}
+
+static long
+shrink_space(char *d, const char *s, long l)
+{
+ long i, ni;
+ int sp = 0;
+ for (i = ni = 0; i < l; ++i) {
+ if (!isspace((unsigned char)s[i])) {
+ if (sp) d[ni++] = ' ';
+ sp = 0;
+ d[ni++] = s[i];
+ }
+ else {
+ sp = 1;
+ }
+ }
+ return ni;
+}
+
+VALUE
+date_zone_to_diff(VALUE str)
+{
+ VALUE offset = Qnil;
+ long l = RSTRING_LEN(str);
+ const char *s = RSTRING_PTR(str);
+
+ {
+ int dst = 0;
+ int w;
+
+ if ((w = str_end_with_word(s, l, "time")) > 0) {
+ int wtime = w;
+ l -= w;
+ if ((w = str_end_with_word(s, l, "standard")) > 0) {
+ l -= w;
+ }
+ else if ((w = str_end_with_word(s, l, "daylight")) > 0) {
+ l -= w;
+ dst = 1;
+ }
+ else {
+ l += wtime;
+ }
+ }
+ else if ((w = str_end_with_word(s, l, "dst")) > 0) {
+ l -= w;
+ dst = 1;
+ }
+
+ {
+ const char *zn = s;
+ long sl = shrunk_size(s, l);
+ char shrunk_buff[MAX_WORD_LENGTH]; /* no terminator to be added */
+ const struct zone *z = 0;
+
+ if (sl <= 0) {
+ sl = l;
+ }
+ else if (sl <= MAX_WORD_LENGTH) {
+ char *d = shrunk_buff;
+ sl = shrink_space(d, s, l);
+ zn = d;
+ }
+
+ if (sl > 0 && sl <= MAX_WORD_LENGTH) {
+ z = zonetab(zn, (unsigned int)sl);
+ }
+
+ if (z) {
+ int d = z->offset;
+ if (dst)
+ d += 3600;
+ offset = INT2FIX(d);
+ goto ok;
+ }
+ }
+
+ {
+ char *p;
+ int sign = 0;
+ long hour = 0, min = 0, sec = 0;
+
+ if (l > 3 &&
+ (strncasecmp(s, "gmt", 3) == 0 ||
+ strncasecmp(s, "utc", 3) == 0)) {
+ s += 3;
+ l -= 3;
+ }
+ if (issign(*s)) {
+ sign = *s == '-';
+ s++;
+ l--;
+
+#define out_of_range(v, min, max) ((v) < (min) || (max) < (v))
+ hour = STRTOUL(s, &p, 10);
+ if (*p == ':') {
+ if (out_of_range(hour, 0, 23)) return Qnil;
+ s = ++p;
+ min = STRTOUL(s, &p, 10);
+ if (out_of_range(min, 0, 59)) return Qnil;
+ if (*p == ':') {
+ s = ++p;
+ sec = STRTOUL(s, &p, 10);
+ if (out_of_range(sec, 0, 59)) return Qnil;
+ }
+ }
+ else if (*p == ',' || *p == '.') {
+ /* fractional hour */
+ size_t n;
+ int ov;
+ /* no over precision for offset; 10**-7 hour = 0.36
+ * milliseconds should be enough. */
+ const size_t max_digits = 7; /* 36 * 10**7 < 32-bit FIXNUM_MAX */
+
+ if (out_of_range(hour, 0, 23)) return Qnil;
+
+ n = (s + l) - ++p;
+ if (n > max_digits) n = max_digits;
+ sec = ruby_scan_digits(p, n, 10, &n, &ov);
+ if ((p += n) < s + l && *p >= ('5' + !(sec & 1)) && *p <= '9') {
+ /* round half to even */
+ sec++;
+ }
+ sec *= 36;
+ if (sign) {
+ hour = -hour;
+ sec = -sec;
+ }
+ if (n <= 2) {
+ /* HH.nn or HH.n */
+ if (n == 1) sec *= 10;
+ offset = INT2FIX(sec + hour * 3600);
+ }
+ else {
+ VALUE denom = rb_int_positive_pow(10, (int)(n - 2));
+ offset = f_add(rb_rational_new(INT2FIX(sec), denom), INT2FIX(hour * 3600));
+ if (rb_rational_den(offset) == INT2FIX(1)) {
+ offset = rb_rational_num(offset);
+ }
+ }
+ goto ok;
+ }
+ else if (l > 2) {
+ size_t n;
+ int ov;
+
+ if (l >= 1)
+ hour = ruby_scan_digits(&s[0], 2 - l % 2, 10, &n, &ov);
+ if (l >= 3)
+ min = ruby_scan_digits(&s[2 - l % 2], 2, 10, &n, &ov);
+ if (l >= 5)
+ sec = ruby_scan_digits(&s[4 - l % 2], 2, 10, &n, &ov);
+ }
+ sec += min * 60 + hour * 3600;
+ if (sign) sec = -sec;
+ offset = INT2FIX(sec);
+#undef out_of_range
+ }
+ }
+ }
+ RB_GC_GUARD(str);
+ ok:
+ return offset;
+}
+
+static int
+day_num(VALUE s)
+{
+ int i;
+
+ for (i = 0; i < (int)sizeof_array(abbr_days); i++)
+ if (strncasecmp(abbr_days[i], RSTRING_PTR(s), 3) == 0)
+ break;
+ return i;
+}
+
+static int
+mon_num(VALUE s)
+{
+ int i;
+
+ for (i = 0; i < (int)sizeof_array(abbr_months); i++)
+ if (strncasecmp(abbr_months[i], RSTRING_PTR(s), 3) == 0)
+ break;
+ return i + 1;
+}
+
+static int
+parse_day_cb(VALUE m, VALUE hash)
+{
+ VALUE s;
+
+ s = rb_reg_nth_match(1, m);
+ set_hash("wday", INT2FIX(day_num(s)));
+ return 1;
+}
+
+static int
+parse_day(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "\\b(" ABBR_DAYS ")[^-/\\d\\s]*"
+#else
+ "(" VALID_DAYS ")"
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+#ifndef TIGHT_PARSER
+ SUBS(str, pat, parse_day_cb);
+#else
+ SUBW(str, pat, parse_day_cb);
+#endif
+}
+
+static int
+parse_time2_cb(VALUE m, VALUE hash)
+{
+ VALUE h, min, s, f, p;
+
+ h = rb_reg_nth_match(1, m);
+ h = str2num(h);
+
+ min = rb_reg_nth_match(2, m);
+ if (!NIL_P(min))
+ min = str2num(min);
+
+ s = rb_reg_nth_match(3, m);
+ if (!NIL_P(s))
+ s = str2num(s);
+
+ f = rb_reg_nth_match(4, m);
+
+ if (!NIL_P(f))
+ f = rb_rational_new2(str2num(f),
+ f_expt(INT2FIX(10), LONG2NUM(RSTRING_LEN(f))));
+
+ p = rb_reg_nth_match(5, m);
+
+ if (!NIL_P(p)) {
+ int ih = NUM2INT(h);
+ ih %= 12;
+ if (*RSTRING_PTR(p) == 'P' || *RSTRING_PTR(p) == 'p')
+ ih += 12;
+ h = INT2FIX(ih);
+ }
+
+ set_hash("hour", h);
+ if (!NIL_P(min))
+ set_hash("min", min);
+ if (!NIL_P(s))
+ set_hash("sec", s);
+ if (!NIL_P(f))
+ set_hash("sec_fraction", f);
+
+ return 1;
+}
+
+static int
+parse_time_cb(VALUE m, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A(\\d+)h?"
+ "(?:\\s*:?\\s*(\\d+)m?"
+ "(?:"
+ "\\s*:?\\s*(\\d+)(?:[,.](\\d+))?s?"
+ ")?"
+ ")?"
+ "(?:\\s*([ap])(?:m\\b|\\.m\\.))?";
+ static VALUE pat = Qnil;
+ VALUE s1, s2;
+
+ s1 = rb_reg_nth_match(1, m);
+ s2 = rb_reg_nth_match(2, m);
+
+ if (!NIL_P(s2))
+ set_hash("zone", s2);
+
+ REGCOMP_I(pat);
+
+ {
+ VALUE m = f_match(pat, s1);
+
+ if (NIL_P(m))
+ return 0;
+ parse_time2_cb(m, hash);
+ }
+
+ return 1;
+}
+
+static int
+parse_time(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "("
+ "" NUMBER "+\\s*"
+ "(?:"
+ "(?:"
+ ":\\s*\\d+"
+ "(?:"
+#ifndef TIGHT_PARSER
+ "\\s*:\\s*\\d+(?:[,.]\\d*)?"
+#else
+ "\\s*:\\s*\\d+(?:[,.]\\d+)?"
+#endif
+ ")?"
+ "|"
+ "h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?"
+ ")"
+ "(?:"
+ "\\s*"
+ "[ap](?:m\\b|\\.m\\.)"
+ ")?"
+ "|"
+ "[ap](?:m\\b|\\.m\\.)"
+ ")"
+ ")"
+ "(?:"
+ "\\s*"
+ "("
+ "(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?"
+ "|"
+ "(?-i:[[:alpha:].\\s]+)(?:standard|daylight)\\stime\\b"
+ "|"
+ "(?-i:[[:alpha:]]+)(?:\\sdst)?\\b"
+ ")"
+ ")?";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+#ifndef TIGHT_PARSER
+ SUBS(str, pat, parse_time_cb);
+#else
+ SUBT(str, pat, parse_time_cb);
+#endif
+}
+
+#define BEGIN_ERA "\\b"
+#define END_ERA "(?!(?<!\\.)[a-z])"
+
+#ifdef TIGHT_PARSER
+static int
+parse_era1_cb(VALUE m, VALUE hash)
+{
+ return 1;
+}
+
+static int
+parse_era1(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ BEGIN_ERA "(a(?:d\\b|\\.d\\.))" END_ERA;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBA(str, pat, parse_era1_cb);
+}
+
+static int
+parse_era2_cb(VALUE m, VALUE hash)
+{
+ VALUE b;
+
+ b = rb_reg_nth_match(1, m);
+ if (*RSTRING_PTR(b) == 'B' ||
+ *RSTRING_PTR(b) == 'b')
+ set_hash("_bc", Qtrue);
+ return 1;
+}
+
+static int
+parse_era2(VALUE str, VALUE hash)
+{
+ static const char pat_source[] = BEGIN_ERA
+ "(c(?:e\\b|\\.e\\.)|b(?:ce\\b|\\.c\\.e\\.)|b(?:c\\b|\\.c\\.))"
+ END_ERA;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBB(str, pat, parse_era2_cb);
+}
+
+static int
+parse_era(VALUE str, VALUE hash)
+{
+ if (parse_era1(str, hash)) /* pre */
+ goto ok;
+ if (parse_era2(str, hash)) /* post */
+ goto ok;
+ return 0;
+ ok:
+ return 1;
+}
+#endif
+
+#ifdef TIGHT_PARSER
+static int
+check_year_width(VALUE y)
+{
+ const char *s;
+ long l;
+
+ l = RSTRING_LEN(y);
+ if (l < 2) return 0;
+ s = RSTRING_PTR(y);
+ if (!isdigit((unsigned char)s[1])) return 0;
+ return (l == 2 || !isdigit((unsigned char)s[2]));
+}
+
+static int
+check_apost(VALUE a, VALUE b, VALUE c)
+{
+ int f = 0;
+
+ if (!NIL_P(a) && *RSTRING_PTR(a) == '\'') {
+ if (!check_year_width(a))
+ return 0;
+ f++;
+ }
+ if (!NIL_P(b) && *RSTRING_PTR(b) == '\'') {
+ if (!check_year_width(b))
+ return 0;
+ if (!NIL_P(c))
+ return 0;
+ f++;
+ }
+ if (!NIL_P(c) && *RSTRING_PTR(c) == '\'') {
+ if (!check_year_width(c))
+ return 0;
+ f++;
+ }
+ if (f > 1)
+ return 0;
+ return 1;
+}
+#endif
+
+static int
+parse_eu_cb(VALUE m, VALUE hash)
+{
+#ifndef TIGHT_PARSER
+ VALUE y, mon, d, b;
+
+ d = rb_reg_nth_match(1, m);
+ mon = rb_reg_nth_match(2, m);
+ b = rb_reg_nth_match(3, m);
+ y = rb_reg_nth_match(4, m);
+
+ mon = INT2FIX(mon_num(mon));
+
+ s3e(hash, y, mon, d, !NIL_P(b) &&
+ (*RSTRING_PTR(b) == 'B' ||
+ *RSTRING_PTR(b) == 'b'));
+#else
+ VALUE y, mon, d;
+
+ d = rb_reg_nth_match(1, m);
+ mon = rb_reg_nth_match(2, m);
+ y = rb_reg_nth_match(3, m);
+
+ if (!check_apost(d, mon, y))
+ return 0;
+
+ mon = INT2FIX(mon_num(mon));
+
+ s3e(hash, y, mon, d, 0);
+#endif
+ return 1;
+}
+
+static int
+parse_eu(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifdef TIGHT_PARSER
+ BOS
+ FPW_COM FPT_COM
+#endif
+#ifndef TIGHT_PARSER
+ "('?" NUMBER "+)[^-\\d\\s]*"
+#else
+ "(\\d+)(?:(?:st|nd|rd|th)\\b)?"
+#endif
+ "\\s*"
+#ifndef TIGHT_PARSER
+ "(" ABBR_MONTHS ")[^-\\d\\s']*"
+#else
+ "(" VALID_MONTHS ")"
+#endif
+ "(?:"
+ "\\s*"
+#ifndef TIGHT_PARSER
+ "(?:"
+ BEGIN_ERA
+ "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))"
+ END_ERA
+ ")?"
+ "\\s*"
+ "('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)"
+#else
+ "(?:" FPA ")?"
+ "\\s*"
+ "([-']?\\d+)"
+ "\\s*"
+ "(?:" FPA "|" FPB ")?"
+#endif
+ ")?"
+#ifdef TIGHT_PARSER
+ COM_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_eu_cb);
+}
+
+static int
+parse_us_cb(VALUE m, VALUE hash)
+{
+#ifndef TIGHT_PARSER
+ VALUE y, mon, d, b;
+
+ mon = rb_reg_nth_match(1, m);
+ d = rb_reg_nth_match(2, m);
+
+ b = rb_reg_nth_match(3, m);
+ y = rb_reg_nth_match(4, m);
+
+ mon = INT2FIX(mon_num(mon));
+
+ s3e(hash, y, mon, d, !NIL_P(b) &&
+ (*RSTRING_PTR(b) == 'B' ||
+ *RSTRING_PTR(b) == 'b'));
+#else
+ VALUE y, mon, d;
+
+ mon = rb_reg_nth_match(1, m);
+ d = rb_reg_nth_match(2, m);
+ y = rb_reg_nth_match(3, m);
+
+ if (!check_apost(mon, d, y))
+ return 0;
+
+ mon = INT2FIX(mon_num(mon));
+
+ s3e(hash, y, mon, d, 0);
+#endif
+ return 1;
+}
+
+static int
+parse_us(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifdef TIGHT_PARSER
+ BOS
+ FPW_COM FPT_COM
+#endif
+#ifndef TIGHT_PARSER
+ "\\b(" ABBR_MONTHS ")[^-\\d\\s']*"
+#else
+ "\\b(" VALID_MONTHS ")"
+#endif
+ "\\s*"
+#ifndef TIGHT_PARSER
+ "('?\\d+)[^-\\d\\s']*"
+#else
+ "('?\\d+)(?:(?:st|nd|rd|th)\\b)?"
+ COM_FPT
+#endif
+ "(?:"
+ "\\s*+,?"
+ "\\s*+"
+#ifndef TIGHT_PARSER
+ "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
+ "\\s*"
+ "('?-?\\d+)"
+#else
+ "(?:" FPA ")?"
+ "\\s*"
+ "([-']?\\d+)"
+ "\\s*"
+ "(?:" FPA "|" FPB ")?"
+#endif
+ ")?"
+#ifdef TIGHT_PARSER
+ COM_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_us_cb);
+}
+
+static int
+parse_iso_cb(VALUE m, VALUE hash)
+{
+ VALUE y, mon, d;
+
+ y = rb_reg_nth_match(1, m);
+ mon = rb_reg_nth_match(2, m);
+ d = rb_reg_nth_match(3, m);
+
+#ifdef TIGHT_PARSER
+ if (!check_apost(y, mon, d))
+ return 0;
+#endif
+
+ s3e(hash, y, mon, d, 0);
+ return 1;
+}
+
+static int
+parse_iso(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "('?[-+]?" NUMBER "+)-(\\d+)-('?-?\\d+)"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "([-+']?\\d+)-(\\d+)-([-']?\\d+)"
+ TEE_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_0(pat);
+ SUBS(str, pat, parse_iso_cb);
+}
+
+static int
+parse_iso21_cb(VALUE m, VALUE hash)
+{
+ VALUE y, w, d;
+
+ y = rb_reg_nth_match(1, m);
+ w = rb_reg_nth_match(2, m);
+ d = rb_reg_nth_match(3, m);
+
+ if (!NIL_P(y))
+ set_hash("cwyear", str2num(y));
+ set_hash("cweek", str2num(w));
+ if (!NIL_P(d))
+ set_hash("cwday", str2num(d));
+
+ return 1;
+}
+
+static int
+parse_iso21(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "\\b(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?\\b"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?"
+ TEE_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_iso21_cb);
+}
+
+static int
+parse_iso22_cb(VALUE m, VALUE hash)
+{
+ VALUE d;
+
+ d = rb_reg_nth_match(1, m);
+ set_hash("cwday", str2num(d));
+ return 1;
+}
+
+static int
+parse_iso22(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "-w-(\\d)\\b"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "-w-(\\d)"
+ TEE_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_iso22_cb);
+}
+
+static int
+parse_iso23_cb(VALUE m, VALUE hash)
+{
+ VALUE mon, d;
+
+ mon = rb_reg_nth_match(1, m);
+ d = rb_reg_nth_match(2, m);
+
+ if (!NIL_P(mon))
+ set_hash("mon", str2num(mon));
+ set_hash("mday", str2num(d));
+
+ return 1;
+}
+
+static int
+parse_iso23(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "--(\\d{2})?-(\\d{2})\\b"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "--(\\d{2})?-(\\d{2})"
+ TEE_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_0(pat);
+ SUBS(str, pat, parse_iso23_cb);
+}
+
+static int
+parse_iso24_cb(VALUE m, VALUE hash)
+{
+ VALUE mon, d;
+
+ mon = rb_reg_nth_match(1, m);
+ d = rb_reg_nth_match(2, m);
+
+ set_hash("mon", str2num(mon));
+ if (!NIL_P(d))
+ set_hash("mday", str2num(d));
+
+ return 1;
+}
+
+static int
+parse_iso24(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "--(\\d{2})(\\d{2})?\\b"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "--(\\d{2})(\\d{2})?"
+ TEE_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_0(pat);
+ SUBS(str, pat, parse_iso24_cb);
+}
+
+static int
+parse_iso25_cb(VALUE m, VALUE hash)
+{
+ VALUE y, d;
+
+ y = rb_reg_nth_match(1, m);
+ d = rb_reg_nth_match(2, m);
+
+ set_hash("year", str2num(y));
+ set_hash("yday", str2num(d));
+
+ return 1;
+}
+
+static int
+parse_iso25(VALUE str, VALUE hash)
+{
+ static const char pat0_source[] =
+#ifndef TIGHT_PARSER
+ "[,.](\\d{2}|\\d{4})-\\d{3}\\b"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "[,.](\\d{2}|\\d{4})-\\d{3}"
+ TEE_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat0 = Qnil;
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "\\b(\\d{2}|\\d{4})-(\\d{3})\\b"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "(\\d{2}|\\d{4})-(\\d{3})"
+ TEE_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_0(pat0);
+ REGCOMP_0(pat);
+
+ if (!NIL_P(f_match(pat0, str)))
+ return 0;
+ SUBS(str, pat, parse_iso25_cb);
+}
+
+static int
+parse_iso26_cb(VALUE m, VALUE hash)
+{
+ VALUE d;
+
+ d = rb_reg_nth_match(1, m);
+ set_hash("yday", str2num(d));
+
+ return 1;
+}
+static int
+parse_iso26(VALUE str, VALUE hash)
+{
+ static const char pat0_source[] =
+#ifndef TIGHT_PARSER
+ "\\d-\\d{3}\\b"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "\\d-\\d{3}"
+ TEE_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat0 = Qnil;
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "\\b-(\\d{3})\\b"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "-(\\d{3})"
+ TEE_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_0(pat0);
+ REGCOMP_0(pat);
+
+ if (!NIL_P(f_match(pat0, str)))
+ return 0;
+ SUBS(str, pat, parse_iso26_cb);
+}
+
+static int
+parse_iso2(VALUE str, VALUE hash)
+{
+ if (parse_iso21(str, hash))
+ goto ok;
+ if (parse_iso22(str, hash))
+ goto ok;
+ if (parse_iso23(str, hash))
+ goto ok;
+ if (parse_iso24(str, hash))
+ goto ok;
+ if (parse_iso25(str, hash))
+ goto ok;
+ if (parse_iso26(str, hash))
+ goto ok;
+ return 0;
+
+ ok:
+ return 1;
+}
+
+#define JISX0301_ERA_INITIALS "mtshr"
+#define JISX0301_DEFAULT_ERA 'H' /* obsolete */
+
+static int
+gengo(int c)
+{
+ int e;
+
+ switch (c) {
+ case 'M': case 'm': e = 1867; break;
+ case 'T': case 't': e = 1911; break;
+ case 'S': case 's': e = 1925; break;
+ case 'H': case 'h': e = 1988; break;
+ case 'R': case 'r': e = 2018; break;
+ default: e = 0; break;
+ }
+ return e;
+}
+
+static int
+parse_jis_cb(VALUE m, VALUE hash)
+{
+ VALUE e, y, mon, d;
+ int ep;
+
+ e = rb_reg_nth_match(1, m);
+ y = rb_reg_nth_match(2, m);
+ mon = rb_reg_nth_match(3, m);
+ d = rb_reg_nth_match(4, m);
+
+ ep = gengo(*RSTRING_PTR(e));
+
+ set_hash("year", f_add(str2num(y), INT2FIX(ep)));
+ set_hash("mon", str2num(mon));
+ set_hash("mday", str2num(d));
+
+ return 1;
+}
+
+static int
+parse_jis(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "\\b([" JISX0301_ERA_INITIALS "])(\\d+)\\.(\\d+)\\.(\\d+)"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "([" JISX0301_ERA_INITIALS "])(\\d+)\\.(\\d+)\\.(\\d+)"
+ TEE_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_jis_cb);
+}
+
+static int
+parse_vms11_cb(VALUE m, VALUE hash)
+{
+ VALUE y, mon, d;
+
+ d = rb_reg_nth_match(1, m);
+ mon = rb_reg_nth_match(2, m);
+ y = rb_reg_nth_match(3, m);
+
+#ifdef TIGHT_PARSER
+ if (!check_apost(d, mon, y))
+ return 0;
+#endif
+
+ mon = INT2FIX(mon_num(mon));
+
+ s3e(hash, y, mon, d, 0);
+ return 1;
+}
+
+static int
+parse_vms11(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "('?-?" NUMBER "+)-(" ABBR_MONTHS ")[^-/.]*"
+ "-('?-?\\d+)"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "([-']?\\d+)-(" DOTLESS_VALID_MONTHS ")"
+ "-([-']?\\d+)"
+ COM_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_vms11_cb);
+}
+
+static int
+parse_vms12_cb(VALUE m, VALUE hash)
+{
+ VALUE y, mon, d;
+
+ mon = rb_reg_nth_match(1, m);
+ d = rb_reg_nth_match(2, m);
+ y = rb_reg_nth_match(3, m);
+
+#ifdef TIGHT_PARSER
+ if (!check_apost(mon, d, y))
+ return 0;
+#endif
+
+ mon = INT2FIX(mon_num(mon));
+
+ s3e(hash, y, mon, d, 0);
+ return 1;
+}
+
+static int
+parse_vms12(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "\\b(" ABBR_MONTHS ")[^-/.]*"
+ "-('?-?\\d+)(?:-('?-?\\d+))?"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "(" DOTLESS_VALID_MONTHS ")"
+ "-([-']?\\d+)(?:-([-']?\\d+))?"
+ COM_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_vms12_cb);
+}
+
+static int
+parse_vms(VALUE str, VALUE hash)
+{
+ if (parse_vms11(str, hash))
+ goto ok;
+ if (parse_vms12(str, hash))
+ goto ok;
+ return 0;
+
+ ok:
+ return 1;
+}
+
+static int
+parse_sla_cb(VALUE m, VALUE hash)
+{
+ VALUE y, mon, d;
+
+ y = rb_reg_nth_match(1, m);
+ mon = rb_reg_nth_match(2, m);
+ d = rb_reg_nth_match(3, m);
+
+#ifdef TIGHT_PARSER
+ if (!check_apost(y, mon, d))
+ return 0;
+#endif
+
+ s3e(hash, y, mon, d, 0);
+ return 1;
+}
+
+static int
+parse_sla(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "('?-?" NUMBER "+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "([-']?\\d+)/\\s*('?\\d+)(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
+ COM_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_sla_cb);
+}
+
+#ifdef TIGHT_PARSER
+static int
+parse_sla2_cb(VALUE m, VALUE hash)
+{
+ VALUE y, mon, d;
+
+ d = rb_reg_nth_match(1, m);
+ mon = rb_reg_nth_match(2, m);
+ y = rb_reg_nth_match(3, m);
+
+ if (!check_apost(d, mon, y))
+ return 0;
+
+ mon = INT2FIX(mon_num(mon));
+
+ s3e(hash, y, mon, d, 0);
+ return 1;
+}
+
+static int
+parse_sla2(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ BOS
+ FPW_COM FPT_COM
+ "([-']?\\d+)/\\s*(" DOTLESS_VALID_MONTHS ")(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
+ COM_FPT COM_FPW
+ EOS
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_sla2_cb);
+}
+
+static int
+parse_sla3_cb(VALUE m, VALUE hash)
+{
+ VALUE y, mon, d;
+
+ mon = rb_reg_nth_match(1, m);
+ d = rb_reg_nth_match(2, m);
+ y = rb_reg_nth_match(3, m);
+
+ if (!check_apost(mon, d, y))
+ return 0;
+
+ mon = INT2FIX(mon_num(mon));
+
+ s3e(hash, y, mon, d, 0);
+ return 1;
+}
+
+static int
+parse_sla3(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ BOS
+ FPW_COM FPT_COM
+ "(" DOTLESS_VALID_MONTHS ")/\\s*([-']?\\d+)(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
+ COM_FPT COM_FPW
+ EOS
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_sla3_cb);
+}
+#endif
+
+static int
+parse_dot_cb(VALUE m, VALUE hash)
+{
+ VALUE y, mon, d;
+
+ y = rb_reg_nth_match(1, m);
+ mon = rb_reg_nth_match(2, m);
+ d = rb_reg_nth_match(3, m);
+
+#ifdef TIGHT_PARSER
+ if (!check_apost(y, mon, d))
+ return 0;
+#endif
+
+ s3e(hash, y, mon, d, 0);
+ return 1;
+}
+
+static int
+parse_dot(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "('?-?" NUMBER "+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "([-']?\\d+)\\.\\s*(\\d+)\\.\\s*([-']?\\d+)"
+ COM_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_dot_cb);
+}
+
+#ifdef TIGHT_PARSER
+static int
+parse_dot2_cb(VALUE m, VALUE hash)
+{
+ VALUE y, mon, d;
+
+ d = rb_reg_nth_match(1, m);
+ mon = rb_reg_nth_match(2, m);
+ y = rb_reg_nth_match(3, m);
+
+ if (!check_apost(d, mon, y))
+ return 0;
+
+ mon = INT2FIX(mon_num(mon));
+
+ s3e(hash, y, mon, d, 0);
+ return 1;
+}
+
+static int
+parse_dot2(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ BOS
+ FPW_COM FPT_COM
+ "([-']?\\d+)\\.\\s*(" DOTLESS_VALID_MONTHS ")(?:(?:[./])\\s*([-']?\\d+))?"
+ COM_FPT COM_FPW
+ EOS
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_dot2_cb);
+}
+
+static int
+parse_dot3_cb(VALUE m, VALUE hash)
+{
+ VALUE y, mon, d;
+
+ mon = rb_reg_nth_match(1, m);
+ d = rb_reg_nth_match(2, m);
+ y = rb_reg_nth_match(3, m);
+
+ if (!check_apost(mon, d, y))
+ return 0;
+
+ mon = INT2FIX(mon_num(mon));
+
+ s3e(hash, y, mon, d, 0);
+ return 1;
+}
+
+static int
+parse_dot3(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ BOS
+ FPW_COM FPT_COM
+ "(" DOTLESS_VALID_MONTHS ")\\.\\s*([-']?\\d+)(?:(?:[./])\\s*([-']?\\d+))?"
+ COM_FPT COM_FPW
+ EOS
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_dot3_cb);
+}
+#endif
+
+static int
+parse_year_cb(VALUE m, VALUE hash)
+{
+ VALUE y;
+
+ y = rb_reg_nth_match(1, m);
+ set_hash("year", str2num(y));
+ return 1;
+}
+
+static int
+parse_year(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "'(\\d+)\\b"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "'(\\d+)"
+ COM_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_0(pat);
+ SUBS(str, pat, parse_year_cb);
+}
+
+static int
+parse_mon_cb(VALUE m, VALUE hash)
+{
+ VALUE mon;
+
+ mon = rb_reg_nth_match(1, m);
+ set_hash("mon", INT2FIX(mon_num(mon)));
+ return 1;
+}
+
+static int
+parse_mon(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "\\b(" ABBR_MONTHS ")\\S*"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "(" VALID_MONTHS ")"
+ COM_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_mon_cb);
+}
+
+static int
+parse_mday_cb(VALUE m, VALUE hash)
+{
+ VALUE d;
+
+ d = rb_reg_nth_match(1, m);
+ set_hash("mday", str2num(d));
+ return 1;
+}
+
+static int
+parse_mday(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "(" NUMBER "+)(st|nd|rd|th)\\b"
+#else
+ BOS
+ FPW_COM FPT_COM
+ "(\\d+)(st|nd|rd|th)"
+ COM_FPT COM_FPW
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_mday_cb);
+}
+
+static int
+n2i(const char *s, long f, long w)
+{
+ long e, i;
+ int v;
+
+ e = f + w;
+ v = 0;
+ for (i = f; i < e; i++) {
+ v *= 10;
+ v += s[i] - '0';
+ }
+ return v;
+}
+
+static int
+parse_ddd_cb(VALUE m, VALUE hash)
+{
+ VALUE s1, s2, s3, s4, s5;
+ const char *cs2, *cs3, *cs5;
+ long l2, l3, l4, l5;
+
+ s1 = rb_reg_nth_match(1, m);
+ s2 = rb_reg_nth_match(2, m);
+ s3 = rb_reg_nth_match(3, m);
+ s4 = rb_reg_nth_match(4, m);
+ s5 = rb_reg_nth_match(5, m);
+
+ cs2 = RSTRING_PTR(s2);
+ l2 = RSTRING_LEN(s2);
+
+ switch (l2) {
+ case 2:
+ if (NIL_P(s3) && !NIL_P(s4))
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
+ else
+ set_hash("mday", INT2FIX(n2i(cs2, 0, 2)));
+ break;
+ case 4:
+ if (NIL_P(s3) && !NIL_P(s4)) {
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
+ set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
+ }
+ else {
+ set_hash("mon", INT2FIX(n2i(cs2, 0, 2)));
+ set_hash("mday", INT2FIX(n2i(cs2, 2, 2)));
+ }
+ break;
+ case 6:
+ if (NIL_P(s3) && !NIL_P(s4)) {
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
+ set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
+ set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
+ }
+ else {
+ int y = n2i(cs2, 0, 2);
+ if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
+ y = -y;
+ set_hash("year", INT2FIX(y));
+ set_hash("mon", INT2FIX(n2i(cs2, 2, 2)));
+ set_hash("mday", INT2FIX(n2i(cs2, 4, 2)));
+ }
+ break;
+ case 8:
+ case 10:
+ case 12:
+ case 14:
+ if (NIL_P(s3) && !NIL_P(s4)) {
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
+ set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
+ set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
+ set_hash("mday", INT2FIX(n2i(cs2, l2-8, 2)));
+ if (l2 >= 10)
+ set_hash("mon", INT2FIX(n2i(cs2, l2-10, 2)));
+ if (l2 == 12) {
+ int y = n2i(cs2, l2-12, 2);
+ if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
+ y = -y;
+ set_hash("year", INT2FIX(y));
+ }
+ if (l2 == 14) {
+ int y = n2i(cs2, l2-14, 4);
+ if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
+ y = -y;
+ set_hash("year", INT2FIX(y));
+ set_hash("_comp", Qfalse);
+ }
+ }
+ else {
+ int y = n2i(cs2, 0, 4);
+ if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
+ y = -y;
+ set_hash("year", INT2FIX(y));
+ set_hash("mon", INT2FIX(n2i(cs2, 4, 2)));
+ set_hash("mday", INT2FIX(n2i(cs2, 6, 2)));
+ if (l2 >= 10)
+ set_hash("hour", INT2FIX(n2i(cs2, 8, 2)));
+ if (l2 >= 12)
+ set_hash("min", INT2FIX(n2i(cs2, 10, 2)));
+ if (l2 >= 14)
+ set_hash("sec", INT2FIX(n2i(cs2, 12, 2)));
+ set_hash("_comp", Qfalse);
+ }
+ break;
+ case 3:
+ if (NIL_P(s3) && !NIL_P(s4)) {
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
+ set_hash("min", INT2FIX(n2i(cs2, l2-3, 1)));
+ }
+ else
+ set_hash("yday", INT2FIX(n2i(cs2, 0, 3)));
+ break;
+ case 5:
+ if (NIL_P(s3) && !NIL_P(s4)) {
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
+ set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
+ set_hash("hour", INT2FIX(n2i(cs2, l2-5, 1)));
+ }
+ else {
+ int y = n2i(cs2, 0, 2);
+ if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
+ y = -y;
+ set_hash("year", INT2FIX(y));
+ set_hash("yday", INT2FIX(n2i(cs2, 2, 3)));
+ }
+ break;
+ case 7:
+ if (NIL_P(s3) && !NIL_P(s4)) {
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
+ set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
+ set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
+ set_hash("mday", INT2FIX(n2i(cs2, l2-7, 1)));
+ }
+ else {
+ int y = n2i(cs2, 0, 4);
+ if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
+ y = -y;
+ set_hash("year", INT2FIX(y));
+ set_hash("yday", INT2FIX(n2i(cs2, 4, 3)));
+ }
+ break;
+ }
+ RB_GC_GUARD(s2);
+ if (!NIL_P(s3)) {
+ cs3 = RSTRING_PTR(s3);
+ l3 = RSTRING_LEN(s3);
+
+ if (!NIL_P(s4)) {
+ switch (l3) {
+ case 2:
+ case 4:
+ case 6:
+ set_hash("sec", INT2FIX(n2i(cs3, l3-2, 2)));
+ if (l3 >= 4)
+ set_hash("min", INT2FIX(n2i(cs3, l3-4, 2)));
+ if (l3 >= 6)
+ set_hash("hour", INT2FIX(n2i(cs3, l3-6, 2)));
+ break;
+ }
+ }
+ else {
+ switch (l3) {
+ case 2:
+ case 4:
+ case 6:
+ set_hash("hour", INT2FIX(n2i(cs3, 0, 2)));
+ if (l3 >= 4)
+ set_hash("min", INT2FIX(n2i(cs3, 2, 2)));
+ if (l3 >= 6)
+ set_hash("sec", INT2FIX(n2i(cs3, 4, 2)));
+ break;
+ }
+ }
+ RB_GC_GUARD(s3);
+ }
+ if (!NIL_P(s4)) {
+ l4 = RSTRING_LEN(s4);
+
+ set_hash("sec_fraction",
+ rb_rational_new2(str2num(s4),
+ f_expt(INT2FIX(10), LONG2NUM(l4))));
+ }
+ if (!NIL_P(s5)) {
+ cs5 = RSTRING_PTR(s5);
+ l5 = RSTRING_LEN(s5);
+
+ set_hash("zone", s5);
+
+ if (*cs5 == '[') {
+ const char *s1, *s2;
+ VALUE zone;
+
+ l5 -= 2;
+ s1 = cs5 + 1;
+ s2 = memchr(s1, ':', l5);
+ if (s2) {
+ s2++;
+ zone = rb_str_subseq(s5, s2 - cs5, l5 - (s2 - s1));
+ s5 = rb_str_subseq(s5, 1, s2 - s1);
+ }
+ else {
+ zone = rb_str_subseq(s5, 1, l5);
+ if (isdigit((unsigned char)*s1))
+ s5 = rb_str_append(rb_str_new_cstr("+"), zone);
+ else
+ s5 = zone;
+ }
+ set_hash("zone", zone);
+ set_hash("offset", date_zone_to_diff(s5));
+ }
+ RB_GC_GUARD(s5);
+ }
+
+ return 1;
+}
+
+static int
+parse_ddd(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+#ifdef TIGHT_PARSER
+ BOS
+#endif
+ "([-+]?)(" NUMBER "{2,14})"
+ "(?:"
+ "\\s*"
+ "t?"
+ "\\s*"
+ "(\\d{2,6})?(?:[,.](\\d*))?"
+ ")?"
+ "(?:"
+ "\\s*"
+ "("
+ "z\\b"
+ "|"
+ "[-+]\\d{1,4}\\b"
+ "|"
+ "\\[[-+]?\\d[^\\]]*\\]"
+ ")"
+ ")?"
+#ifdef TIGHT_PARSER
+ EOS
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_ddd_cb);
+}
+
+#ifndef TIGHT_PARSER
+static int
+parse_bc_cb(VALUE m, VALUE hash)
+{
+ set_hash("_bc", Qtrue);
+ return 1;
+}
+
+static int
+parse_bc(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\b(bc\\b|bce\\b|b\\.c\\.|b\\.c\\.e\\.)";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_bc_cb);
+}
+
+static int
+parse_frag_cb(VALUE m, VALUE hash)
+{
+ VALUE s, n;
+
+ s = rb_reg_nth_match(1, m);
+
+ if (!NIL_P(ref_hash("hour")) && NIL_P(ref_hash("mday"))) {
+ n = str2num(s);
+ if (f_ge_p(n, INT2FIX(1)) &&
+ f_le_p(n, INT2FIX(31)))
+ set_hash("mday", n);
+ }
+ if (!NIL_P(ref_hash("mday")) && NIL_P(ref_hash("hour"))) {
+ n = str2num(s);
+ if (f_ge_p(n, INT2FIX(0)) &&
+ f_le_p(n, INT2FIX(24)))
+ set_hash("hour", n);
+ }
+
+ return 1;
+}
+
+static int
+parse_frag(VALUE str, VALUE hash)
+{
+ static const char pat_source[] = "\\A\\s*(\\d{1,2})\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ SUBS(str, pat, parse_frag_cb);
+}
+#endif
+
+#ifdef TIGHT_PARSER
+static int
+parse_dummy_cb(VALUE m, VALUE hash)
+{
+ return 1;
+}
+
+static int
+parse_wday_only(VALUE str, VALUE hash)
+{
+ static const char pat_source[] = "\\A\\s*" FPW "\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_0(pat);
+ SUBS(str, pat, parse_dummy_cb);
+}
+
+static int
+parse_time_only(VALUE str, VALUE hash)
+{
+ static const char pat_source[] = "\\A\\s*" FPT "\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_0(pat);
+ SUBS(str, pat, parse_dummy_cb);
+}
+
+static int
+parse_wday_and_time(VALUE str, VALUE hash)
+{
+ static const char pat_source[] = "\\A\\s*(" FPW "\\s+" FPT "|" FPT "\\s+" FPW ")\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_0(pat);
+ SUBS(str, pat, parse_dummy_cb);
+}
+
+static unsigned
+have_invalid_char_p(VALUE s)
+{
+ long i;
+
+ for (i = 0; i < RSTRING_LEN(s); i++)
+ if (iscntrl((unsigned char)RSTRING_PTR(s)[i]) &&
+ !isspace((unsigned char)RSTRING_PTR(s)[i]))
+ return 1;
+ return 0;
+}
+#endif
+
+#define HAVE_ALPHA (1<<0)
+#define HAVE_DIGIT (1<<1)
+#define HAVE_DASH (1<<2)
+#define HAVE_DOT (1<<3)
+#define HAVE_SLASH (1<<4)
+
+static unsigned
+check_class(VALUE s)
+{
+ unsigned flags;
+ long i;
+
+ flags = 0;
+ for (i = 0; i < RSTRING_LEN(s); i++) {
+ if (isalpha((unsigned char)RSTRING_PTR(s)[i]))
+ flags |= HAVE_ALPHA;
+ if (isdigit((unsigned char)RSTRING_PTR(s)[i]))
+ flags |= HAVE_DIGIT;
+ if (RSTRING_PTR(s)[i] == '-')
+ flags |= HAVE_DASH;
+ if (RSTRING_PTR(s)[i] == '.')
+ flags |= HAVE_DOT;
+ if (RSTRING_PTR(s)[i] == '/')
+ flags |= HAVE_SLASH;
+ }
+ return flags;
+}
+
+#define HAVE_ELEM_P(x) ((check_class(str) & (x)) == (x))
+
+#ifdef TIGHT_PARSER
+#define PARSER_ERROR return rb_hash_new()
+#endif
+
+VALUE
+date__parse(VALUE str, VALUE comp)
+{
+ VALUE backref, hash;
+
+#ifdef TIGHT_PARSER
+ if (have_invalid_char_p(str))
+ PARSER_ERROR;
+#endif
+
+ backref = rb_backref_get();
+ rb_match_busy(backref);
+
+ {
+ static const char pat_source[] =
+#ifndef TIGHT_PARSER
+ "[^-+',./:@[:alnum:]\\[\\]]+"
+#else
+ "[^[:graph:]]+"
+#endif
+ ;
+ static VALUE pat = Qnil;
+
+ REGCOMP_0(pat);
+ str = rb_str_dup(str);
+ f_gsub_bang(str, pat, asp_string());
+ }
+
+ hash = rb_hash_new();
+ set_hash("_comp", comp);
+
+ if (HAVE_ELEM_P(HAVE_ALPHA))
+ parse_day(str, hash);
+ if (HAVE_ELEM_P(HAVE_DIGIT))
+ parse_time(str, hash);
+
+#ifdef TIGHT_PARSER
+ if (HAVE_ELEM_P(HAVE_ALPHA))
+ parse_era(str, hash);
+#endif
+
+ if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT)) {
+ if (parse_eu(str, hash))
+ goto ok;
+ if (parse_us(str, hash))
+ goto ok;
+ }
+ if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DASH))
+ if (parse_iso(str, hash))
+ goto ok;
+ if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT))
+ if (parse_jis(str, hash))
+ goto ok;
+ if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_DASH))
+ if (parse_vms(str, hash))
+ goto ok;
+ if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_SLASH))
+ if (parse_sla(str, hash))
+ goto ok;
+#ifdef TIGHT_PARSER
+ if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_SLASH)) {
+ if (parse_sla2(str, hash))
+ goto ok;
+ if (parse_sla3(str, hash))
+ goto ok;
+ }
+#endif
+ if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT))
+ if (parse_dot(str, hash))
+ goto ok;
+#ifdef TIGHT_PARSER
+ if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_DOT)) {
+ if (parse_dot2(str, hash))
+ goto ok;
+ if (parse_dot3(str, hash))
+ goto ok;
+ }
+#endif
+ if (HAVE_ELEM_P(HAVE_DIGIT))
+ if (parse_iso2(str, hash))
+ goto ok;
+ if (HAVE_ELEM_P(HAVE_DIGIT))
+ if (parse_year(str, hash))
+ goto ok;
+ if (HAVE_ELEM_P(HAVE_ALPHA))
+ if (parse_mon(str, hash))
+ goto ok;
+ if (HAVE_ELEM_P(HAVE_DIGIT))
+ if (parse_mday(str, hash))
+ goto ok;
+ if (HAVE_ELEM_P(HAVE_DIGIT))
+ if (parse_ddd(str, hash))
+ goto ok;
+
+#ifdef TIGHT_PARSER
+ if (parse_wday_only(str, hash))
+ goto ok;
+ if (parse_time_only(str, hash))
+ goto ok;
+ if (parse_wday_and_time(str, hash))
+ goto ok;
+
+ PARSER_ERROR; /* not found */
+#endif
+
+ ok:
+#ifndef TIGHT_PARSER
+ if (HAVE_ELEM_P(HAVE_ALPHA))
+ parse_bc(str, hash);
+ if (HAVE_ELEM_P(HAVE_DIGIT))
+ parse_frag(str, hash);
+#endif
+
+ {
+ if (RTEST(del_hash("_bc"))) {
+ VALUE y;
+
+ y = ref_hash("cwyear");
+ if (!NIL_P(y)) {
+ y = f_add(f_negate(y), INT2FIX(1));
+ set_hash("cwyear", y);
+ }
+ y = ref_hash("year");
+ if (!NIL_P(y)) {
+ y = f_add(f_negate(y), INT2FIX(1));
+ set_hash("year", y);
+ }
+ }
+
+ if (RTEST(del_hash("_comp"))) {
+ VALUE y;
+
+ y = ref_hash("cwyear");
+ if (!NIL_P(y))
+ if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
+ if (f_ge_p(y, INT2FIX(69)))
+ set_hash("cwyear", f_add(y, INT2FIX(1900)));
+ else
+ set_hash("cwyear", f_add(y, INT2FIX(2000)));
+ }
+ y = ref_hash("year");
+ if (!NIL_P(y))
+ if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
+ if (f_ge_p(y, INT2FIX(69)))
+ set_hash("year", f_add(y, INT2FIX(1900)));
+ else
+ set_hash("year", f_add(y, INT2FIX(2000)));
+ }
+ }
+
+ }
+
+ {
+ VALUE zone = ref_hash("zone");
+ if (!NIL_P(zone) && NIL_P(ref_hash("offset")))
+ set_hash("offset", date_zone_to_diff(zone));
+ }
+
+ rb_backref_set(backref);
+
+ return hash;
+}
+
+static VALUE
+comp_year69(VALUE y)
+{
+ if (f_ge_p(y, INT2FIX(69)))
+ return f_add(y, INT2FIX(1900));
+ return f_add(y, INT2FIX(2000));
+}
+
+static VALUE
+comp_year50(VALUE y)
+{
+ if (f_ge_p(y, INT2FIX(50)))
+ return f_add(y, INT2FIX(1900));
+ return f_add(y, INT2FIX(2000));
+}
+
+static VALUE
+sec_fraction(VALUE f)
+{
+ return rb_rational_new2(str2num(f),
+ f_expt(INT2FIX(10),
+ LONG2NUM(RSTRING_LEN(f))));
+}
+
+#define SNUM 14
+
+static int
+iso8601_ext_datetime_cb(VALUE m, VALUE hash)
+{
+ VALUE s[SNUM + 1], y;
+
+ {
+ int i;
+ s[0] = Qnil;
+ for (i = 1; i <= SNUM; i++)
+ s[i] = rb_reg_nth_match(i, m);
+ }
+
+ if (!NIL_P(s[1])) {
+ if (!NIL_P(s[3])) set_hash("mday", str2num(s[3]));
+ if (strcmp(RSTRING_PTR(s[1]), "-") != 0) {
+ y = str2num(s[1]);
+ if (RSTRING_LEN(s[1]) < 4)
+ y = comp_year69(y);
+ set_hash("year", y);
+ }
+ if (NIL_P(s[2])) {
+ if (strcmp(RSTRING_PTR(s[1]), "-") != 0)
+ return 0;
+ }
+ else
+ set_hash("mon", str2num(s[2]));
+ }
+ else if (!NIL_P(s[5])) {
+ set_hash("yday", str2num(s[5]));
+ if (!NIL_P(s[4])) {
+ y = str2num(s[4]);
+ if (RSTRING_LEN(s[4]) < 4)
+ y = comp_year69(y);
+ set_hash("year", y);
+ }
+ }
+ else if (!NIL_P(s[8])) {
+ set_hash("cweek", str2num(s[7]));
+ set_hash("cwday", str2num(s[8]));
+ if (!NIL_P(s[6])) {
+ y = str2num(s[6]);
+ if (RSTRING_LEN(s[6]) < 4)
+ y = comp_year69(y);
+ set_hash("cwyear", y);
+ }
+ }
+ else if (!NIL_P(s[9])) {
+ set_hash("cwday", str2num(s[9]));
+ }
+ if (!NIL_P(s[10])) {
+ set_hash("hour", str2num(s[10]));
+ set_hash("min", str2num(s[11]));
+ if (!NIL_P(s[12]))
+ set_hash("sec", str2num(s[12]));
+ }
+ if (!NIL_P(s[13])) {
+ set_hash("sec_fraction", sec_fraction(s[13]));
+ }
+ if (!NIL_P(s[14])) {
+ set_hash("zone", s[14]);
+ set_hash("offset", date_zone_to_diff(s[14]));
+ }
+
+ return 1;
+}
+
+static int
+iso8601_ext_datetime(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*(?:([-+]?\\d{2,}|-)-(\\d{2})?(?:-(\\d{2}))?|"
+ "([-+]?\\d{2,})?-(\\d{3})|"
+ "(\\d{4}|\\d{2})?-w(\\d{2})-(\\d)|"
+ "-w-(\\d))"
+ "(?:t"
+ "(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?"
+ "(z|[-+]\\d{2}(?::?\\d{2})?)?)?\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, iso8601_ext_datetime_cb);
+}
+
+#undef SNUM
+#define SNUM 17
+
+static int
+iso8601_bas_datetime_cb(VALUE m, VALUE hash)
+{
+ VALUE s[SNUM + 1], y;
+
+ {
+ int i;
+ s[0] = Qnil;
+ for (i = 1; i <= SNUM; i++)
+ s[i] = rb_reg_nth_match(i, m);
+ }
+
+ if (!NIL_P(s[3])) {
+ set_hash("mday", str2num(s[3]));
+ if (strcmp(RSTRING_PTR(s[1]), "--") != 0) {
+ y = str2num(s[1]);
+ if (RSTRING_LEN(s[1]) < 4)
+ y = comp_year69(y);
+ set_hash("year", y);
+ }
+ if (*RSTRING_PTR(s[2]) == '-') {
+ if (strcmp(RSTRING_PTR(s[1]), "--") != 0)
+ return 0;
+ }
+ else
+ set_hash("mon", str2num(s[2]));
+ }
+ else if (!NIL_P(s[5])) {
+ set_hash("yday", str2num(s[5]));
+ y = str2num(s[4]);
+ if (RSTRING_LEN(s[4]) < 4)
+ y = comp_year69(y);
+ set_hash("year", y);
+ }
+ else if (!NIL_P(s[6])) {
+ set_hash("yday", str2num(s[6]));
+ }
+ else if (!NIL_P(s[9])) {
+ set_hash("cweek", str2num(s[8]));
+ set_hash("cwday", str2num(s[9]));
+ y = str2num(s[7]);
+ if (RSTRING_LEN(s[7]) < 4)
+ y = comp_year69(y);
+ set_hash("cwyear", y);
+ }
+ else if (!NIL_P(s[11])) {
+ set_hash("cweek", str2num(s[10]));
+ set_hash("cwday", str2num(s[11]));
+ }
+ else if (!NIL_P(s[12])) {
+ set_hash("cwday", str2num(s[12]));
+ }
+ if (!NIL_P(s[13])) {
+ set_hash("hour", str2num(s[13]));
+ set_hash("min", str2num(s[14]));
+ if (!NIL_P(s[15]))
+ set_hash("sec", str2num(s[15]));
+ }
+ if (!NIL_P(s[16])) {
+ set_hash("sec_fraction", sec_fraction(s[16]));
+ }
+ if (!NIL_P(s[17])) {
+ set_hash("zone", s[17]);
+ set_hash("offset", date_zone_to_diff(s[17]));
+ }
+
+ return 1;
+}
+
+static int
+iso8601_bas_datetime(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*(?:([-+]?(?:\\d{4}|\\d{2})|--)(\\d{2}|-)(\\d{2})|"
+ "([-+]?(?:\\d{4}|\\d{2}))(\\d{3})|"
+ "-(\\d{3})|"
+ "(\\d{4}|\\d{2})w(\\d{2})(\\d)|"
+ "-w(\\d{2})(\\d)|"
+ "-w-(\\d))"
+ "(?:t?"
+ "(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?"
+ "(z|[-+]\\d{2}(?:\\d{2})?)?)?\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, iso8601_bas_datetime_cb);
+}
+
+#undef SNUM
+#define SNUM 5
+
+static int
+iso8601_ext_time_cb(VALUE m, VALUE hash)
+{
+ VALUE s[SNUM + 1];
+
+ {
+ int i;
+ s[0] = Qnil;
+ for (i = 1; i <= SNUM; i++)
+ s[i] = rb_reg_nth_match(i, m);
+ }
+
+ set_hash("hour", str2num(s[1]));
+ set_hash("min", str2num(s[2]));
+ if (!NIL_P(s[3]))
+ set_hash("sec", str2num(s[3]));
+ if (!NIL_P(s[4]))
+ set_hash("sec_fraction", sec_fraction(s[4]));
+ if (!NIL_P(s[5])) {
+ set_hash("zone", s[5]);
+ set_hash("offset", date_zone_to_diff(s[5]));
+ }
+
+ return 1;
+}
+
+#define iso8601_bas_time_cb iso8601_ext_time_cb
+
+static int
+iso8601_ext_time(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?"
+ "(z|[-+]\\d{2}(:?\\d{2})?)?)?\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, iso8601_ext_time_cb);
+}
+
+static int
+iso8601_bas_time(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?"
+ "(z|[-+]\\d{2}(\\d{2})?)?)?\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, iso8601_bas_time_cb);
+}
+
+VALUE
+date__iso8601(VALUE str)
+{
+ VALUE backref, hash;
+
+ backref = rb_backref_get();
+ rb_match_busy(backref);
+
+ hash = rb_hash_new();
+
+ if (iso8601_ext_datetime(str, hash))
+ goto ok;
+ if (iso8601_bas_datetime(str, hash))
+ goto ok;
+ if (iso8601_ext_time(str, hash))
+ goto ok;
+ if (iso8601_bas_time(str, hash))
+ goto ok;
+
+ ok:
+ rb_backref_set(backref);
+
+ return hash;
+}
+
+#undef SNUM
+#define SNUM 8
+
+static int
+rfc3339_cb(VALUE m, VALUE hash)
+{
+ VALUE s[SNUM + 1];
+
+ {
+ int i;
+ s[0] = Qnil;
+ for (i = 1; i <= SNUM; i++)
+ s[i] = rb_reg_nth_match(i, m);
+ }
+
+ set_hash("year", str2num(s[1]));
+ set_hash("mon", str2num(s[2]));
+ set_hash("mday", str2num(s[3]));
+ set_hash("hour", str2num(s[4]));
+ set_hash("min", str2num(s[5]));
+ set_hash("sec", str2num(s[6]));
+ set_hash("zone", s[8]);
+ set_hash("offset", date_zone_to_diff(s[8]));
+ if (!NIL_P(s[7]))
+ set_hash("sec_fraction", sec_fraction(s[7]));
+
+ return 1;
+}
+
+static int
+rfc3339(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*(-?\\d{4})-(\\d{2})-(\\d{2})"
+ "(?:t|\\s)"
+ "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
+ "(z|[-+]\\d{2}:\\d{2})\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, rfc3339_cb);
+}
+
+VALUE
+date__rfc3339(VALUE str)
+{
+ VALUE backref, hash;
+
+ backref = rb_backref_get();
+ rb_match_busy(backref);
+
+ hash = rb_hash_new();
+ rfc3339(str, hash);
+ rb_backref_set(backref);
+ return hash;
+}
+
+#undef SNUM
+#define SNUM 8
+
+static int
+xmlschema_datetime_cb(VALUE m, VALUE hash)
+{
+ VALUE s[SNUM + 1];
+
+ {
+ int i;
+ s[0] = Qnil;
+ for (i = 1; i <= SNUM; i++)
+ s[i] = rb_reg_nth_match(i, m);
+ }
+
+ set_hash("year", str2num(s[1]));
+ if (!NIL_P(s[2]))
+ set_hash("mon", str2num(s[2]));
+ if (!NIL_P(s[3]))
+ set_hash("mday", str2num(s[3]));
+ if (!NIL_P(s[4]))
+ set_hash("hour", str2num(s[4]));
+ if (!NIL_P(s[5]))
+ set_hash("min", str2num(s[5]));
+ if (!NIL_P(s[6]))
+ set_hash("sec", str2num(s[6]));
+ if (!NIL_P(s[7]))
+ set_hash("sec_fraction", sec_fraction(s[7]));
+ if (!NIL_P(s[8])) {
+ set_hash("zone", s[8]);
+ set_hash("offset", date_zone_to_diff(s[8]));
+ }
+
+ return 1;
+}
+
+static int
+xmlschema_datetime(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*(-?\\d{4,})(?:-(\\d{2})(?:-(\\d{2}))?)?"
+ "(?:t"
+ "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?"
+ "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, xmlschema_datetime_cb);
+}
+
+#undef SNUM
+#define SNUM 5
+
+static int
+xmlschema_time_cb(VALUE m, VALUE hash)
+{
+ VALUE s[SNUM + 1];
+
+ {
+ int i;
+ s[0] = Qnil;
+ for (i = 1; i <= SNUM; i++)
+ s[i] = rb_reg_nth_match(i, m);
+ }
+
+ set_hash("hour", str2num(s[1]));
+ set_hash("min", str2num(s[2]));
+ if (!NIL_P(s[3]))
+ set_hash("sec", str2num(s[3]));
+ if (!NIL_P(s[4]))
+ set_hash("sec_fraction", sec_fraction(s[4]));
+ if (!NIL_P(s[5])) {
+ set_hash("zone", s[5]);
+ set_hash("offset", date_zone_to_diff(s[5]));
+ }
+
+ return 1;
+}
+
+static int
+xmlschema_time(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
+ "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, xmlschema_time_cb);
+}
+
+#undef SNUM
+#define SNUM 4
+
+static int
+xmlschema_trunc_cb(VALUE m, VALUE hash)
+{
+ VALUE s[SNUM + 1];
+
+ {
+ int i;
+ s[0] = Qnil;
+ for (i = 1; i <= SNUM; i++)
+ s[i] = rb_reg_nth_match(i, m);
+ }
+
+ if (!NIL_P(s[1]))
+ set_hash("mon", str2num(s[1]));
+ if (!NIL_P(s[2]))
+ set_hash("mday", str2num(s[2]));
+ if (!NIL_P(s[3]))
+ set_hash("mday", str2num(s[3]));
+ if (!NIL_P(s[4])) {
+ set_hash("zone", s[4]);
+ set_hash("offset", date_zone_to_diff(s[4]));
+ }
+
+ return 1;
+}
+
+static int
+xmlschema_trunc(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*(?:--(\\d{2})(?:-(\\d{2}))?|---(\\d{2}))"
+ "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, xmlschema_trunc_cb);
+}
+
+VALUE
+date__xmlschema(VALUE str)
+{
+ VALUE backref, hash;
+
+ backref = rb_backref_get();
+ rb_match_busy(backref);
+
+ hash = rb_hash_new();
+
+ if (xmlschema_datetime(str, hash))
+ goto ok;
+ if (xmlschema_time(str, hash))
+ goto ok;
+ if (xmlschema_trunc(str, hash))
+ goto ok;
+
+ ok:
+ rb_backref_set(backref);
+
+ return hash;
+}
+
+#undef SNUM
+#define SNUM 8
+
+static int
+rfc2822_cb(VALUE m, VALUE hash)
+{
+ VALUE s[SNUM + 1], y;
+
+ {
+ int i;
+ s[0] = Qnil;
+ for (i = 1; i <= SNUM; i++)
+ s[i] = rb_reg_nth_match(i, m);
+ }
+
+ if (!NIL_P(s[1])) {
+ set_hash("wday", INT2FIX(day_num(s[1])));
+ }
+ set_hash("mday", str2num(s[2]));
+ set_hash("mon", INT2FIX(mon_num(s[3])));
+ y = str2num(s[4]);
+ if (RSTRING_LEN(s[4]) < 4)
+ y = comp_year50(y);
+ set_hash("year", y);
+ set_hash("hour", str2num(s[5]));
+ set_hash("min", str2num(s[6]));
+ if (!NIL_P(s[7]))
+ set_hash("sec", str2num(s[7]));
+ set_hash("zone", s[8]);
+ set_hash("offset", date_zone_to_diff(s[8]));
+
+ return 1;
+}
+
+static int
+rfc2822(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*(?:(" ABBR_DAYS ")\\s*,\\s+)?"
+ "(\\d{1,2})\\s+"
+ "(" ABBR_MONTHS ")\\s+"
+ "(-?\\d{2,})\\s+"
+ "(\\d{2}):(\\d{2})(?::(\\d{2}))?\\s*"
+ "([-+]\\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, rfc2822_cb);
+}
+
+VALUE
+date__rfc2822(VALUE str)
+{
+ VALUE backref, hash;
+
+ backref = rb_backref_get();
+ rb_match_busy(backref);
+
+ hash = rb_hash_new();
+ rfc2822(str, hash);
+ rb_backref_set(backref);
+ return hash;
+}
+
+#undef SNUM
+#define SNUM 8
+
+static int
+httpdate_type1_cb(VALUE m, VALUE hash)
+{
+ VALUE s[SNUM + 1];
+
+ {
+ int i;
+ s[0] = Qnil;
+ for (i = 1; i <= SNUM; i++)
+ s[i] = rb_reg_nth_match(i, m);
+ }
+
+ set_hash("wday", INT2FIX(day_num(s[1])));
+ set_hash("mday", str2num(s[2]));
+ set_hash("mon", INT2FIX(mon_num(s[3])));
+ set_hash("year", str2num(s[4]));
+ set_hash("hour", str2num(s[5]));
+ set_hash("min", str2num(s[6]));
+ set_hash("sec", str2num(s[7]));
+ set_hash("zone", s[8]);
+ set_hash("offset", INT2FIX(0));
+
+ return 1;
+}
+
+static int
+httpdate_type1(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*(" ABBR_DAYS ")\\s*,\\s+"
+ "(\\d{2})\\s+"
+ "(" ABBR_MONTHS ")\\s+"
+ "(-?\\d{4})\\s+"
+ "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
+ "(gmt)\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, httpdate_type1_cb);
+}
+
+#undef SNUM
+#define SNUM 8
+
+static int
+httpdate_type2_cb(VALUE m, VALUE hash)
+{
+ VALUE s[SNUM + 1], y;
+
+ {
+ int i;
+ s[0] = Qnil;
+ for (i = 1; i <= SNUM; i++)
+ s[i] = rb_reg_nth_match(i, m);
+ }
+
+ set_hash("wday", INT2FIX(day_num(s[1])));
+ set_hash("mday", str2num(s[2]));
+ set_hash("mon", INT2FIX(mon_num(s[3])));
+ y = str2num(s[4]);
+ if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99)))
+ y = comp_year69(y);
+ set_hash("year", y);
+ set_hash("hour", str2num(s[5]));
+ set_hash("min", str2num(s[6]));
+ set_hash("sec", str2num(s[7]));
+ set_hash("zone", s[8]);
+ set_hash("offset", INT2FIX(0));
+
+ return 1;
+}
+
+static int
+httpdate_type2(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*(" DAYS ")\\s*,\\s+"
+ "(\\d{2})\\s*-\\s*"
+ "(" ABBR_MONTHS ")\\s*-\\s*"
+ "(\\d{2})\\s+"
+ "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
+ "(gmt)\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, httpdate_type2_cb);
+}
+
+#undef SNUM
+#define SNUM 7
+
+static int
+httpdate_type3_cb(VALUE m, VALUE hash)
+{
+ VALUE s[SNUM + 1];
+
+ {
+ int i;
+ s[0] = Qnil;
+ for (i = 1; i <= SNUM; i++)
+ s[i] = rb_reg_nth_match(i, m);
+ }
+
+ set_hash("wday", INT2FIX(day_num(s[1])));
+ set_hash("mon", INT2FIX(mon_num(s[2])));
+ set_hash("mday", str2num(s[3]));
+ set_hash("hour", str2num(s[4]));
+ set_hash("min", str2num(s[5]));
+ set_hash("sec", str2num(s[6]));
+ set_hash("year", str2num(s[7]));
+
+ return 1;
+}
+
+static int
+httpdate_type3(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*(" ABBR_DAYS ")\\s+"
+ "(" ABBR_MONTHS ")\\s+"
+ "(\\d{1,2})\\s+"
+ "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
+ "(\\d{4})\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, httpdate_type3_cb);
+}
+
+VALUE
+date__httpdate(VALUE str)
+{
+ VALUE backref, hash;
+
+ backref = rb_backref_get();
+ rb_match_busy(backref);
+
+ hash = rb_hash_new();
+
+ if (httpdate_type1(str, hash))
+ goto ok;
+ if (httpdate_type2(str, hash))
+ goto ok;
+ if (httpdate_type3(str, hash))
+ goto ok;
+
+ ok:
+ rb_backref_set(backref);
+
+ return hash;
+}
+
+#undef SNUM
+#define SNUM 9
+
+static int
+jisx0301_cb(VALUE m, VALUE hash)
+{
+ VALUE s[SNUM + 1];
+ int ep;
+
+ {
+ int i;
+ s[0] = Qnil;
+ for (i = 1; i <= SNUM; i++)
+ s[i] = rb_reg_nth_match(i, m);
+ }
+
+ ep = gengo(NIL_P(s[1]) ? JISX0301_DEFAULT_ERA : *RSTRING_PTR(s[1]));
+ set_hash("year", f_add(str2num(s[2]), INT2FIX(ep)));
+ set_hash("mon", str2num(s[3]));
+ set_hash("mday", str2num(s[4]));
+ if (!NIL_P(s[5])) {
+ set_hash("hour", str2num(s[5]));
+ if (!NIL_P(s[6]))
+ set_hash("min", str2num(s[6]));
+ if (!NIL_P(s[7]))
+ set_hash("sec", str2num(s[7]));
+ }
+ if (!NIL_P(s[8]))
+ set_hash("sec_fraction", sec_fraction(s[8]));
+ if (!NIL_P(s[9])) {
+ set_hash("zone", s[9]);
+ set_hash("offset", date_zone_to_diff(s[9]));
+ }
+
+ return 1;
+}
+
+static int
+jisx0301(VALUE str, VALUE hash)
+{
+ static const char pat_source[] =
+ "\\A\\s*([" JISX0301_ERA_INITIALS "])?(\\d{2})\\.(\\d{2})\\.(\\d{2})"
+ "(?:t"
+ "(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?"
+ "(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z";
+ static VALUE pat = Qnil;
+
+ REGCOMP_I(pat);
+ MATCH(str, pat, jisx0301_cb);
+}
+
+VALUE
+date__jisx0301(VALUE str)
+{
+ VALUE backref, hash;
+
+ backref = rb_backref_get();
+ rb_match_busy(backref);
+
+ hash = rb_hash_new();
+ if (jisx0301(str, hash))
+ goto ok;
+ hash = date__iso8601(str);
+
+ ok:
+ rb_backref_set(backref);
+ return hash;
+}
+
+/*
+Local variables:
+c-file-style: "ruby"
+End:
+*/
diff --git a/ext/date/date_strftime.c b/ext/date/date_strftime.c
new file mode 100644
index 0000000000..d7f28989d6
--- /dev/null
+++ b/ext/date/date_strftime.c
@@ -0,0 +1,638 @@
+/*
+ date_strftime.c: based on a public-domain implementation of ANSI C
+ library routine strftime, which is originally written by Arnold
+ Robbins.
+ */
+
+#include "ruby/ruby.h"
+#include "date_tmx.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#if defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#undef strchr /* avoid AIX weirdness */
+
+#define range(low, item, hi) (item)
+
+#define add(x,y) (rb_funcall((x), '+', 1, (y)))
+#define sub(x,y) (rb_funcall((x), '-', 1, (y)))
+#define mul(x,y) (rb_funcall((x), '*', 1, (y)))
+#define quo(x,y) (rb_funcall((x), rb_intern("quo"), 1, (y)))
+#define div(x,y) (rb_funcall((x), rb_intern("div"), 1, (y)))
+#define mod(x,y) (rb_funcall((x), '%', 1, (y)))
+
+static void
+upcase(char *s, size_t i)
+{
+ do {
+ if (ISLOWER(*s))
+ *s = TOUPPER(*s);
+ } while (s++, --i);
+}
+
+static void
+downcase(char *s, size_t i)
+{
+ do {
+ if (ISUPPER(*s))
+ *s = TOLOWER(*s);
+ } while (s++, --i);
+}
+
+/* strftime --- produce formatted time */
+
+static size_t
+date_strftime_with_tmx(char *s, const size_t maxsize, const char *format,
+ const struct tmx *tmx)
+{
+ char *endp = s + maxsize;
+ char *start = s;
+ const char *sp, *tp;
+ auto char tbuf[100];
+ ptrdiff_t i;
+ int v, w;
+ size_t colons;
+ int precision, flags;
+ char padding;
+ /* LOCALE_[OE] and COLONS are actually modifiers, not flags */
+ enum {LEFT, CHCASE, LOWER, UPPER, LOCALE_O, LOCALE_E, COLONS};
+#define BIT_OF(n) (1U<<(n))
+
+ /* various tables for locale C */
+ static const char days_l[][10] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday",
+ };
+ static const char months_l[][10] = {
+ "January", "February", "March", "April",
+ "May", "June", "July", "August", "September",
+ "October", "November", "December",
+ };
+ static const char ampm[][3] = { "AM", "PM", };
+
+ if (s == NULL || format == NULL || tmx == NULL || maxsize == 0)
+ return 0;
+
+ /* quick check if we even need to bother */
+ if (strchr(format, '%') == NULL && strlen(format) + 1 >= maxsize) {
+ err:
+ errno = ERANGE;
+ return 0;
+ }
+
+ for (; *format && s < endp - 1; format++) {
+#define FLAG_FOUND() do { \
+ if (precision > 0 || flags & (BIT_OF(LOCALE_E) | BIT_OF(LOCALE_O) | BIT_OF(COLONS))) \
+ goto unknown; \
+ } while (0)
+#define NEEDS(n) do if (s >= endp || (n) >= endp - s - 1) goto err; while (0)
+#define FILL_PADDING(i) do { \
+ if (!(flags & BIT_OF(LEFT)) && precision > (i)) { \
+ NEEDS(precision); \
+ memset(s, padding ? padding : ' ', precision - (i)); \
+ s += precision - (i); \
+ } \
+ else { \
+ NEEDS(i); \
+ } \
+ } while (0);
+#define FMT(def_pad, def_prec, fmt, val) \
+ do { \
+ int l; \
+ if (precision <= 0) precision = (def_prec); \
+ if (flags & BIT_OF(LEFT)) precision = 1; \
+ l = snprintf(s, endp - s, \
+ ((padding == '0' || (!padding && (def_pad) == '0')) ? \
+ "%0*"fmt : "%*"fmt), \
+ precision, (val)); \
+ if (l < 0) goto err; \
+ s += l; \
+ } while (0)
+#define STRFTIME(fmt) \
+ do { \
+ i = date_strftime_with_tmx(s, endp - s, (fmt), tmx); \
+ if (!i) return 0; \
+ if (flags & BIT_OF(UPPER)) \
+ upcase(s, i); \
+ if (!(flags & BIT_OF(LEFT)) && precision > i) { \
+ if (start + maxsize < s + precision) { \
+ errno = ERANGE; \
+ return 0; \
+ } \
+ memmove(s + precision - i, s, i); \
+ memset(s, padding ? padding : ' ', precision - i); \
+ s += precision; \
+ } \
+ else s += i; \
+ } while (0)
+#define FMTV(def_pad, def_prec, fmt, val) \
+ do { \
+ VALUE tmp = (val); \
+ if (FIXNUM_P(tmp)) { \
+ FMT((def_pad), (def_prec), "l"fmt, FIX2LONG(tmp)); \
+ } \
+ else { \
+ VALUE args[2], result; \
+ size_t l; \
+ if (precision <= 0) precision = (def_prec); \
+ if (flags & BIT_OF(LEFT)) precision = 1; \
+ args[0] = INT2FIX(precision); \
+ args[1] = (val); \
+ if (padding == '0' || (!padding && (def_pad) == '0')) \
+ result = rb_str_format(2, args, rb_str_new2("%0*"fmt)); \
+ else \
+ result = rb_str_format(2, args, rb_str_new2("%*"fmt)); \
+ l = strlcpy(s, StringValueCStr(result), endp - s); \
+ if ((size_t)(endp - s) <= l) \
+ goto err; \
+ s += l; \
+ } \
+ } while (0)
+
+ if (*format != '%') {
+ *s++ = *format;
+ continue;
+ }
+ tp = tbuf;
+ sp = format;
+ precision = -1;
+ flags = 0;
+ padding = 0;
+ colons = 0;
+ again:
+ switch (*++format) {
+ case '\0':
+ format--;
+ goto unknown;
+
+ case 'A': /* full weekday name */
+ case 'a': /* abbreviated weekday name */
+ if (flags & BIT_OF(CHCASE)) {
+ flags &= ~(BIT_OF(LOWER) | BIT_OF(CHCASE));
+ flags |= BIT_OF(UPPER);
+ }
+ {
+ int wday = tmx_wday;
+ if (wday < 0 || wday > 6)
+ i = 1, tp = "?";
+ else {
+ if (*format == 'A')
+ i = strlen(tp = days_l[wday]);
+ else
+ i = 3, tp = days_l[wday];
+ }
+ }
+ break;
+
+ case 'B': /* full month name */
+ case 'b': /* abbreviated month name */
+ case 'h': /* same as %b */
+ if (flags & BIT_OF(CHCASE)) {
+ flags &= ~(BIT_OF(LOWER) | BIT_OF(CHCASE));
+ flags |= BIT_OF(UPPER);
+ }
+ {
+ int mon = tmx_mon;
+ if (mon < 1 || mon > 12)
+ i = 1, tp = "?";
+ else {
+ if (*format == 'B')
+ i = strlen(tp = months_l[mon - 1]);
+ else
+ i = 3, tp = months_l[mon - 1];
+ }
+ }
+ break;
+
+ case 'C': /* century (year/100) */
+ FMTV('0', 2, "d", div(tmx_year, INT2FIX(100)));
+ continue;
+
+ case 'c': /* appropriate date and time representation */
+ STRFTIME("%a %b %e %H:%M:%S %Y");
+ continue;
+
+ case 'D':
+ STRFTIME("%m/%d/%y");
+ continue;
+
+ case 'd': /* day of the month, 01 - 31 */
+ case 'e': /* day of month, blank padded */
+ v = range(1, tmx_mday, 31);
+ FMT((*format == 'd') ? '0' : ' ', 2, "d", v);
+ continue;
+
+ case 'F':
+ STRFTIME("%Y-%m-%d");
+ continue;
+
+ case 'G': /* year of ISO week with century */
+ case 'Y': /* year with century */
+ {
+ VALUE year = (*format == 'G') ? tmx_cwyear : tmx_year;
+ if (FIXNUM_P(year)) {
+ long y = FIX2LONG(year);
+ FMT('0', 0 <= y ? 4 : 5, "ld", y);
+ }
+ else {
+ FMTV('0', 4, "d", year);
+ }
+ }
+ continue;
+
+ case 'g': /* year of ISO week without a century */
+ case 'y': /* year without a century */
+ v = NUM2INT(mod((*format == 'g') ? tmx_cwyear : tmx_year, INT2FIX(100)));
+ FMT('0', 2, "d", v);
+ continue;
+
+ case 'H': /* hour, 24-hour clock, 00 - 23 */
+ case 'k': /* hour, 24-hour clock, blank pad */
+ v = range(0, tmx_hour, 23);
+ FMT((*format == 'H') ? '0' : ' ', 2, "d", v);
+ continue;
+
+ case 'I': /* hour, 12-hour clock, 01 - 12 */
+ case 'l': /* hour, 12-hour clock, 1 - 12, blank pad */
+ v = range(0, tmx_hour, 23);
+ if (v == 0)
+ v = 12;
+ else if (v > 12)
+ v -= 12;
+ FMT((*format == 'I') ? '0' : ' ', 2, "d", v);
+ continue;
+
+ case 'j': /* day of the year, 001 - 366 */
+ v = range(1, tmx_yday, 366);
+ FMT('0', 3, "d", v);
+ continue;
+
+ case 'L': /* millisecond */
+ case 'N': /* nanosecond */
+ if (*format == 'L')
+ w = 3;
+ else
+ w = 9;
+ if (precision <= 0)
+ precision = w;
+ NEEDS(precision);
+
+ {
+ VALUE subsec = tmx_sec_fraction;
+ int ww;
+ long n;
+
+ ww = precision;
+ while (9 <= ww) {
+ subsec = mul(subsec, INT2FIX(1000000000));
+ ww -= 9;
+ }
+ n = 1;
+ for (; 0 < ww; ww--)
+ n *= 10;
+ if (n != 1)
+ subsec = mul(subsec, INT2FIX(n));
+ subsec = div(subsec, INT2FIX(1));
+
+ if (FIXNUM_P(subsec)) {
+ (void)snprintf(s, endp - s, "%0*ld",
+ precision, FIX2LONG(subsec));
+ s += precision;
+ }
+ else {
+ VALUE args[2], result;
+ args[0] = INT2FIX(precision);
+ args[1] = subsec;
+ result = rb_str_format(2, args, rb_str_new2("%0*d"));
+ (void)strlcpy(s, StringValueCStr(result), endp - s);
+ s += precision;
+ }
+ }
+ continue;
+
+ case 'M': /* minute, 00 - 59 */
+ v = range(0, tmx_min, 59);
+ FMT('0', 2, "d", v);
+ continue;
+
+ case 'm': /* month, 01 - 12 */
+ v = range(1, tmx_mon, 12);
+ FMT('0', 2, "d", v);
+ continue;
+
+ case 'n': /* same as \n */
+ FILL_PADDING(1);
+ *s++ = '\n';
+ continue;
+
+ case 't': /* same as \t */
+ FILL_PADDING(1);
+ *s++ = '\t';
+ continue;
+
+ case 'P': /* am or pm based on 12-hour clock */
+ case 'p': /* AM or PM based on 12-hour clock */
+ if ((*format == 'p' && (flags & BIT_OF(CHCASE))) ||
+ (*format == 'P' && !(flags & (BIT_OF(CHCASE) | BIT_OF(UPPER))))) {
+ flags &= ~(BIT_OF(UPPER) | BIT_OF(CHCASE));
+ flags |= BIT_OF(LOWER);
+ }
+ v = range(0, tmx_hour, 23);
+ if (v < 12)
+ tp = ampm[0];
+ else
+ tp = ampm[1];
+ i = 2;
+ break;
+
+ case 'Q': /* milliseconds since Unix epoch */
+ FMTV('0', 1, "d", tmx_msecs);
+ continue;
+
+ case 'R':
+ STRFTIME("%H:%M");
+ continue;
+
+ case 'r':
+ STRFTIME("%I:%M:%S %p");
+ continue;
+
+ case 'S': /* second, 00 - 59 */
+ v = range(0, tmx_sec, 59);
+ FMT('0', 2, "d", v);
+ continue;
+
+ case 's': /* seconds since Unix epoch */
+ FMTV('0', 1, "d", tmx_secs);
+ continue;
+
+ case 'T':
+ STRFTIME("%H:%M:%S");
+ continue;
+
+ case 'U': /* week of year, Sunday is first day of week */
+ case 'W': /* week of year, Monday is first day of week */
+ v = range(0, (*format == 'U') ? tmx_wnum0 : tmx_wnum1, 53);
+ FMT('0', 2, "d", v);
+ continue;
+
+ case 'u': /* weekday, Monday == 1, 1 - 7 */
+ v = range(1, tmx_cwday, 7);
+ FMT('0', 1, "d", v);
+ continue;
+
+ case 'V': /* week of year according ISO 8601 */
+ v = range(1, tmx_cweek, 53);
+ FMT('0', 2, "d", v);
+ continue;
+
+ case 'v':
+ STRFTIME("%e-%^b-%Y");
+ continue;
+
+ case 'w': /* weekday, Sunday == 0, 0 - 6 */
+ v = range(0, tmx_wday, 6);
+ FMT('0', 1, "d", v);
+ continue;
+
+ case 'X': /* appropriate time representation */
+ STRFTIME("%H:%M:%S");
+ continue;
+
+ case 'x': /* appropriate date representation */
+ STRFTIME("%m/%d/%y");
+ continue;
+
+ case 'Z': /* time zone name or abbreviation */
+ if (flags & BIT_OF(CHCASE)) {
+ flags &= ~(BIT_OF(UPPER) | BIT_OF(CHCASE));
+ flags |= BIT_OF(LOWER);
+ }
+ {
+ char *zone = tmx_zone;
+ if (zone == NULL)
+ tp = "";
+ else
+ tp = zone;
+ i = strlen(tp);
+ }
+ break;
+
+ case 'z': /* offset from UTC */
+ {
+ long off, aoff;
+ int hl, hw;
+
+ off = tmx_offset;
+ aoff = off;
+ if (aoff < 0)
+ aoff = -off;
+
+ if ((aoff / 3600) < 10)
+ hl = 1;
+ else
+ hl = 2;
+ hw = 2;
+ if (flags & BIT_OF(LEFT) && hl == 1)
+ hw = 1;
+
+ switch (colons) {
+ case 0: /* %z -> +hhmm */
+ precision = precision <= (3 + hw) ? hw : precision - 3;
+ NEEDS(precision + 3);
+ break;
+
+ case 1: /* %:z -> +hh:mm */
+ precision = precision <= (4 + hw) ? hw : precision - 4;
+ NEEDS(precision + 4);
+ break;
+
+ case 2: /* %::z -> +hh:mm:ss */
+ precision = precision <= (7 + hw) ? hw : precision - 7;
+ NEEDS(precision + 7);
+ break;
+
+ case 3: /* %:::z -> +hh[:mm[:ss]] */
+ {
+ if (aoff % 3600 == 0) {
+ precision = precision <= (1 + hw) ?
+ hw : precision - 1;
+ NEEDS(precision + 3);
+ }
+ else if (aoff % 60 == 0) {
+ precision = precision <= (4 + hw) ?
+ hw : precision - 4;
+ NEEDS(precision + 4);
+ }
+ else {
+ precision = precision <= (7 + hw) ?
+ hw : precision - 7;
+ NEEDS(precision + 7);
+ }
+ }
+ break;
+
+ default:
+ format--;
+ goto unknown;
+ }
+ if (padding == ' ' && precision > hl) {
+ i = snprintf(s, endp - s, "%*s", precision - hl, "");
+ precision = hl;
+ if (i < 0) goto err;
+ s += i;
+ }
+ if (off < 0) {
+ off = -off;
+ *s++ = '-';
+ } else {
+ *s++ = '+';
+ }
+ i = snprintf(s, endp - s, "%.*ld", precision, off / 3600);
+ if (i < 0) goto err;
+ s += i;
+ off = off % 3600;
+ if (colons == 3 && off == 0)
+ continue;
+ if (1 <= colons)
+ *s++ = ':';
+ i = snprintf(s, endp - s, "%02d", (int)(off / 60));
+ if (i < 0) goto err;
+ s += i;
+ off = off % 60;
+ if (colons == 3 && off == 0)
+ continue;
+ if (2 <= colons) {
+ *s++ = ':';
+ i = snprintf(s, endp - s, "%02d", (int)off);
+ if (i < 0) goto err;
+ s += i;
+ }
+ }
+ continue;
+
+ case '+':
+ STRFTIME("%a %b %e %H:%M:%S %Z %Y");
+ continue;
+
+ case 'E':
+ /* POSIX locale extensions, ignored for now */
+ flags |= BIT_OF(LOCALE_E);
+ if (*(format + 1) && strchr("cCxXyY", *(format + 1)))
+ goto again;
+ goto unknown;
+ case 'O':
+ /* POSIX locale extensions, ignored for now */
+ flags |= BIT_OF(LOCALE_O);
+ if (*(format + 1) && strchr("deHkIlmMSuUVwWy", *(format + 1)))
+ goto again;
+ goto unknown;
+
+ case ':':
+ flags |= BIT_OF(COLONS);
+ {
+ size_t l = strspn(format, ":");
+ format += l;
+ if (*format == 'z') {
+ colons = l;
+ format--;
+ goto again;
+ }
+ format -= l;
+ }
+ goto unknown;
+
+ case '_':
+ FLAG_FOUND();
+ padding = ' ';
+ goto again;
+
+ case '-':
+ FLAG_FOUND();
+ flags |= BIT_OF(LEFT);
+ goto again;
+
+ case '^':
+ FLAG_FOUND();
+ flags |= BIT_OF(UPPER);
+ goto again;
+
+ case '#':
+ FLAG_FOUND();
+ flags |= BIT_OF(CHCASE);
+ goto again;
+
+ case '0':
+ FLAG_FOUND();
+ padding = '0';
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ char *e;
+ unsigned long prec = strtoul(format, &e, 10);
+ if (prec > INT_MAX || prec > maxsize) {
+ errno = ERANGE;
+ return 0;
+ }
+ precision = (int)prec;
+ format = e - 1;
+ goto again;
+ }
+
+ case '%':
+ FILL_PADDING(1);
+ *s++ = '%';
+ continue;
+
+ default:
+ unknown:
+ i = format - sp + 1;
+ tp = sp;
+ precision = -1;
+ flags = 0;
+ padding = 0;
+ colons = 0;
+ break;
+ }
+ if (i) {
+ FILL_PADDING(i);
+ memcpy(s, tp, i);
+ switch (flags & (BIT_OF(UPPER) | BIT_OF(LOWER))) {
+ case BIT_OF(UPPER):
+ upcase(s, i);
+ break;
+ case BIT_OF(LOWER):
+ downcase(s, i);
+ break;
+ }
+ s += i;
+ }
+ }
+ if (s >= endp) {
+ goto err;
+ }
+ if (*format == '\0') {
+ *s = '\0';
+ return (s - start);
+ }
+ return 0;
+}
+
+size_t
+date_strftime(char *s, size_t maxsize, const char *format,
+ const struct tmx *tmx)
+{
+ return date_strftime_with_tmx(s, maxsize, format, tmx);
+}
+
+/*
+Local variables:
+c-file-style: "ruby"
+End:
+*/
diff --git a/ext/date/date_strptime.c b/ext/date/date_strptime.c
new file mode 100644
index 0000000000..1dde5fa3ec
--- /dev/null
+++ b/ext/date/date_strptime.c
@@ -0,0 +1,704 @@
+/*
+ date_strptime.c: Coded by Tadayoshi Funaba 2011,2012
+*/
+
+#include "ruby.h"
+#include "ruby/encoding.h"
+#include "ruby/re.h"
+#include <ctype.h>
+
+#undef strncasecmp
+#define strncasecmp STRNCASECMP
+
+static const char *day_names[] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday",
+};
+static const int ABBREVIATED_DAY_NAME_LENGTH = 3;
+
+static const char *month_names[] = {
+ "January", "February", "March", "April",
+ "May", "June", "July", "August", "September",
+ "October", "November", "December",
+};
+static const int ABBREVIATED_MONTH_NAME_LENGTH = 3;
+
+#define sizeof_array(o) (sizeof o / sizeof o[0])
+
+#define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
+#define f_add(x,y) rb_funcall(x, '+', 1, y)
+#define f_sub(x,y) rb_funcall(x, '-', 1, y)
+#define f_mul(x,y) rb_funcall(x, '*', 1, y)
+#define f_div(x,y) rb_funcall(x, '/', 1, y)
+#define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
+#define f_mod(x,y) rb_funcall(x, '%', 1, y)
+#define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
+
+#define f_lt_p(x,y) rb_funcall(x, '<', 1, y)
+#define f_gt_p(x,y) rb_funcall(x, '>', 1, y)
+#define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y)
+#define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y)
+
+#define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s)
+#define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i)
+#define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i)
+
+#define issign(c) ((c) == '-' || (c) == '+')
+
+static int
+num_pattern_p(const char *s)
+{
+ if (isdigit((unsigned char)*s))
+ return 1;
+ if (*s == '%') {
+ s++;
+ if (*s == 'E' || *s == 'O')
+ s++;
+ if (*s &&
+ (strchr("CDdeFGgHIjkLlMmNQRrSsTUuVvWwXxYy", *s) ||
+ isdigit((unsigned char)*s)))
+ return 1;
+ }
+ return 0;
+}
+
+#define NUM_PATTERN_P() num_pattern_p(&fmt[fi + 1])
+
+static long
+read_digits(const char *s, size_t slen, VALUE *n, size_t width)
+{
+ size_t l;
+
+ if (!width)
+ return 0;
+
+ l = 0;
+ while (l < slen && ISDIGIT(s[l])) {
+ if (++l == width) break;
+ }
+
+ if (l == 0)
+ return 0;
+
+ if ((4 * l * sizeof(char)) <= (sizeof(long)*CHAR_BIT)) {
+ const char *os = s;
+ long v;
+
+ v = 0;
+ while ((size_t)(s - os) < l) {
+ v *= 10;
+ v += *s - '0';
+ s++;
+ }
+ if (os == s)
+ return 0;
+ *n = LONG2NUM(v);
+ return l;
+ }
+ else {
+ VALUE vbuf = 0;
+ char *s2 = ALLOCV_N(char, vbuf, l + 1);
+ memcpy(s2, s, l);
+ s2[l] = '\0';
+ *n = rb_cstr_to_inum(s2, 10, 0);
+ ALLOCV_END(vbuf);
+ return l;
+ }
+}
+
+#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k"")), v)
+#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k"")))
+#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k"")))
+
+#define fail() \
+do { \
+ set_hash("_fail", Qtrue); \
+ return 0; \
+} while (0)
+
+#define fail_p() (!NIL_P(ref_hash("_fail")))
+
+#define READ_DIGITS(n,w) \
+do { \
+ size_t l; \
+ l = read_digits(&str[si], slen - si, &n, w); \
+ if (l == 0) { \
+ fail(); \
+ } \
+ si += l; \
+} while (0)
+
+#define READ_DIGITS_MAX(n) READ_DIGITS(n, LONG_MAX)
+
+static int
+valid_range_p(VALUE v, int a, int b)
+{
+ if (FIXNUM_P(v)) {
+ int vi = FIX2INT(v);
+ return !(vi < a || vi > b);
+ }
+ return !(f_lt_p(v, INT2NUM(a)) || f_gt_p(v, INT2NUM(b)));
+}
+
+#define recur(fmt) \
+do { \
+ size_t l; \
+ l = date__strptime_internal(&str[si], slen - si, \
+ fmt, sizeof fmt - 1, hash); \
+ if (fail_p()) \
+ return 0; \
+ si += l; \
+} while (0)
+
+VALUE date_zone_to_diff(VALUE);
+
+static inline int
+head_match_p(size_t len, const char *name, const char *str, size_t slen, size_t si)
+{
+ return slen - si >= len && strncasecmp(name, &str[si], len) == 0;
+}
+
+static size_t
+date__strptime_internal(const char *str, size_t slen,
+ const char *fmt, size_t flen, VALUE hash)
+{
+ size_t si, fi;
+ int c;
+
+#define HEAD_MATCH_P(len, name) head_match_p(len, name, str, slen, si)
+ si = fi = 0;
+
+ while (fi < flen) {
+ if (isspace((unsigned char)fmt[fi])) {
+ while (si < slen && isspace((unsigned char)str[si]))
+ si++;
+ while (++fi < flen && isspace((unsigned char)fmt[fi]));
+ continue;
+ }
+
+ if (si >= slen) fail();
+
+ switch (fmt[fi]) {
+ case '%':
+
+ again:
+ fi++;
+ c = fmt[fi];
+
+ switch (c) {
+ case 'E':
+ if (fmt[fi + 1] && strchr("cCxXyY", fmt[fi + 1]))
+ goto again;
+ fi--;
+ goto ordinal;
+ case 'O':
+ if (fmt[fi + 1] && strchr("deHImMSuUVwWy", fmt[fi + 1]))
+ goto again;
+ fi--;
+ goto ordinal;
+ case ':':
+ {
+ int i;
+
+ for (i = 1; i < 3 && fi + i < flen && fmt[fi+i] == ':'; ++i);
+ if (fmt[fi+i] == 'z') {
+ fi += i - 1;
+ goto again;
+ }
+ fail();
+ }
+
+ case 'A':
+ case 'a':
+ {
+ int i;
+
+ for (i = 0; i < (int)sizeof_array(day_names); i++) {
+ const char *day_name = day_names[i];
+ size_t l = strlen(day_name);
+ if (HEAD_MATCH_P(l, day_name) ||
+ HEAD_MATCH_P(l = ABBREVIATED_DAY_NAME_LENGTH, day_name)) {
+ si += l;
+ set_hash("wday", INT2FIX(i));
+ goto matched;
+ }
+ }
+ fail();
+ }
+ case 'B':
+ case 'b':
+ case 'h':
+ {
+ int i;
+
+ for (i = 0; i < (int)sizeof_array(month_names); i++) {
+ const char *month_name = month_names[i];
+ size_t l = strlen(month_name);
+ if (HEAD_MATCH_P(l, month_name) ||
+ HEAD_MATCH_P(l = ABBREVIATED_MONTH_NAME_LENGTH, month_name)) {
+ si += l;
+ set_hash("mon", INT2FIX(i + 1));
+ goto matched;
+ }
+ }
+ fail();
+ }
+
+ case 'C':
+ {
+ VALUE n;
+
+ if (NUM_PATTERN_P())
+ READ_DIGITS(n, 2);
+ else
+ READ_DIGITS_MAX(n);
+ set_hash("_cent", n);
+ goto matched;
+ }
+
+ case 'c':
+ recur("%a %b %e %H:%M:%S %Y");
+ goto matched;
+
+ case 'D':
+ recur("%m/%d/%y");
+ goto matched;
+
+ case 'd':
+ case 'e':
+ {
+ VALUE n;
+
+ if (str[si] == ' ') {
+ si++;
+ READ_DIGITS(n, 1);
+ } else {
+ READ_DIGITS(n, 2);
+ }
+ if (!valid_range_p(n, 1, 31))
+ fail();
+ set_hash("mday", n);
+ goto matched;
+ }
+
+ case 'F':
+ recur("%Y-%m-%d");
+ goto matched;
+
+ case 'G':
+ {
+ VALUE n;
+
+ if (NUM_PATTERN_P())
+ READ_DIGITS(n, 4);
+ else
+ READ_DIGITS_MAX(n);
+ set_hash("cwyear", n);
+ goto matched;
+ }
+
+ case 'g':
+ {
+ VALUE n;
+
+ READ_DIGITS(n, 2);
+ if (!valid_range_p(n, 0, 99))
+ fail();
+ set_hash("cwyear",n);
+ if (NIL_P(ref_hash("_cent")))
+ set_hash("_cent",
+ INT2FIX(f_ge_p(n, INT2FIX(69)) ? 19 : 20));
+ goto matched;
+ }
+
+ case 'H':
+ case 'k':
+ {
+ VALUE n;
+
+ if (str[si] == ' ') {
+ si++;
+ READ_DIGITS(n, 1);
+ } else {
+ READ_DIGITS(n, 2);
+ }
+ if (!valid_range_p(n, 0, 24))
+ fail();
+ set_hash("hour", n);
+ goto matched;
+ }
+
+ case 'I':
+ case 'l':
+ {
+ VALUE n;
+
+ if (str[si] == ' ') {
+ si++;
+ READ_DIGITS(n, 1);
+ } else {
+ READ_DIGITS(n, 2);
+ }
+ if (!valid_range_p(n, 1, 12))
+ fail();
+ set_hash("hour", n);
+ goto matched;
+ }
+
+ case 'j':
+ {
+ VALUE n;
+
+ READ_DIGITS(n, 3);
+ if (!valid_range_p(n, 1, 366))
+ fail();
+ set_hash("yday", n);
+ goto matched;
+ }
+
+ case 'L':
+ case 'N':
+ {
+ VALUE n;
+ int sign = 1;
+ size_t osi;
+
+ if (issign(str[si])) {
+ if (str[si] == '-')
+ sign = -1;
+ si++;
+ }
+ osi = si;
+ if (NUM_PATTERN_P())
+ READ_DIGITS(n, c == 'L' ? 3 : 9);
+ else
+ READ_DIGITS_MAX(n);
+ if (sign == -1)
+ n = f_negate(n);
+ set_hash("sec_fraction",
+ rb_rational_new2(n,
+ f_expt(INT2FIX(10),
+ ULONG2NUM(si - osi))));
+ goto matched;
+ }
+
+ case 'M':
+ {
+ VALUE n;
+
+ READ_DIGITS(n, 2);
+ if (!valid_range_p(n, 0, 59))
+ fail();
+ set_hash("min", n);
+ goto matched;
+ }
+
+ case 'm':
+ {
+ VALUE n;
+
+ READ_DIGITS(n, 2);
+ if (!valid_range_p(n, 1, 12))
+ fail();
+ set_hash("mon", n);
+ goto matched;
+ }
+
+ case 'n':
+ case 't':
+ recur(" ");
+ goto matched;
+
+ case 'P':
+ case 'p':
+ if (slen - si < 2) fail();
+ {
+ char c = str[si];
+ const int hour = (c == 'P' || c == 'p') ? 12 : 0;
+ if (!hour && !(c == 'A' || c == 'a')) fail();
+ if ((c = str[si+1]) == '.') {
+ if (slen - si < 4 || str[si+3] != '.') fail();
+ c = str[si += 2];
+ }
+ if (!(c == 'M' || c == 'm')) fail();
+ si += 2;
+ set_hash("_merid", INT2FIX(hour));
+ goto matched;
+ }
+
+ case 'Q':
+ {
+ VALUE n;
+ int sign = 1;
+
+ if (str[si] == '-') {
+ sign = -1;
+ si++;
+ }
+ READ_DIGITS_MAX(n);
+ if (sign == -1)
+ n = f_negate(n);
+ set_hash("seconds",
+ rb_rational_new2(n, INT2FIX(1000)));
+ goto matched;
+ }
+
+ case 'R':
+ recur("%H:%M");
+ goto matched;
+
+ case 'r':
+ recur("%I:%M:%S %p");
+ goto matched;
+
+ case 'S':
+ {
+ VALUE n;
+
+ READ_DIGITS(n, 2);
+ if (!valid_range_p(n, 0, 60))
+ fail();
+ set_hash("sec", n);
+ goto matched;
+ }
+
+ case 's':
+ {
+ VALUE n;
+ int sign = 1;
+
+ if (str[si] == '-') {
+ sign = -1;
+ si++;
+ }
+ READ_DIGITS_MAX(n);
+ if (sign == -1)
+ n = f_negate(n);
+ set_hash("seconds", n);
+ goto matched;
+ }
+
+ case 'T':
+ recur("%H:%M:%S");
+ goto matched;
+
+ case 'U':
+ case 'W':
+ {
+ VALUE n;
+
+ READ_DIGITS(n, 2);
+ if (!valid_range_p(n, 0, 53))
+ fail();
+ set_hash(c == 'U' ? "wnum0" : "wnum1", n);
+ goto matched;
+ }
+
+ case 'u':
+ {
+ VALUE n;
+
+ READ_DIGITS(n, 1);
+ if (!valid_range_p(n, 1, 7))
+ fail();
+ set_hash("cwday", n);
+ goto matched;
+ }
+
+ case 'V':
+ {
+ VALUE n;
+
+ READ_DIGITS(n, 2);
+ if (!valid_range_p(n, 1, 53))
+ fail();
+ set_hash("cweek", n);
+ goto matched;
+ }
+
+ case 'v':
+ recur("%e-%b-%Y");
+ goto matched;
+
+ case 'w':
+ {
+ VALUE n;
+
+ READ_DIGITS(n, 1);
+ if (!valid_range_p(n, 0, 6))
+ fail();
+ set_hash("wday", n);
+ goto matched;
+ }
+
+ case 'X':
+ recur("%H:%M:%S");
+ goto matched;
+
+ case 'x':
+ recur("%m/%d/%y");
+ goto matched;
+
+ case 'Y':
+ {
+ VALUE n;
+ int sign = 1;
+
+ if (issign(str[si])) {
+ if (str[si] == '-')
+ sign = -1;
+ si++;
+ }
+ if (NUM_PATTERN_P())
+ READ_DIGITS(n, 4);
+ else
+ READ_DIGITS_MAX(n);
+ if (sign == -1)
+ n = f_negate(n);
+ set_hash("year", n);
+ goto matched;
+ }
+
+ case 'y':
+ {
+ VALUE n;
+ int sign = 1;
+
+ READ_DIGITS(n, 2);
+ if (!valid_range_p(n, 0, 99))
+ fail();
+ if (sign == -1)
+ n = f_negate(n);
+ set_hash("year", n);
+ if (NIL_P(ref_hash("_cent")))
+ set_hash("_cent",
+ INT2FIX(f_ge_p(n, INT2FIX(69)) ? 19 : 20));
+ goto matched;
+ }
+
+ case 'Z':
+ case 'z':
+ {
+ static const char pat_source[] =
+ "\\A("
+ "(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?"
+ "|(?-i:[[:alpha:].\\s]+)(?:standard|daylight)\\s+time\\b"
+ "|(?-i:[[:alpha:]]+)(?:\\s+dst)?\\b"
+ ")";
+ static VALUE pat = Qnil;
+ VALUE m, b;
+
+ if (NIL_P(pat)) {
+ pat = rb_reg_new(pat_source, sizeof pat_source - 1,
+ ONIG_OPTION_IGNORECASE);
+ rb_obj_freeze(pat);
+ rb_gc_register_mark_object(pat);
+ }
+
+ b = rb_backref_get();
+ rb_match_busy(b);
+ m = f_match(pat, rb_usascii_str_new(&str[si], slen - si));
+
+ if (!NIL_P(m)) {
+ VALUE s, l, o;
+
+ s = rb_reg_nth_match(1, m);
+ l = f_end(m, INT2FIX(0));
+ o = date_zone_to_diff(s);
+ si += NUM2LONG(l);
+ set_hash("zone", s);
+ set_hash("offset", o);
+ rb_backref_set(b);
+ goto matched;
+ }
+ rb_backref_set(b);
+ fail();
+ }
+
+ case '%':
+ if (str[si] != '%')
+ fail();
+ si++;
+ goto matched;
+
+ case '+':
+ recur("%a %b %e %H:%M:%S %Z %Y");
+ goto matched;
+
+ default:
+ if (str[si] != '%')
+ fail();
+ si++;
+ if (fi < flen) {
+ if (si >= slen || str[si] != fmt[fi])
+ fail();
+ si++;
+ }
+ goto matched;
+ }
+ default:
+ ordinal:
+ if (str[si] != fmt[fi])
+ fail();
+ si++;
+ fi++;
+ break;
+ matched:
+ fi++;
+ break;
+ }
+ }
+
+ return si;
+}
+
+VALUE
+date__strptime(const char *str, size_t slen,
+ const char *fmt, size_t flen, VALUE hash)
+{
+ size_t si;
+ VALUE cent, merid;
+
+ si = date__strptime_internal(str, slen, fmt, flen, hash);
+
+ if (fail_p())
+ return Qnil;
+
+ if (slen > si) {
+ VALUE s;
+
+ s = rb_usascii_str_new(&str[si], slen - si);
+ set_hash("leftover", s);
+ }
+
+ cent = del_hash("_cent");
+ if (!NIL_P(cent)) {
+ VALUE year;
+
+ year = ref_hash("cwyear");
+ if (!NIL_P(year))
+ set_hash("cwyear", f_add(year, f_mul(cent, INT2FIX(100))));
+ year = ref_hash("year");
+ if (!NIL_P(year))
+ set_hash("year", f_add(year, f_mul(cent, INT2FIX(100))));
+ }
+
+ merid = del_hash("_merid");
+ if (!NIL_P(merid)) {
+ VALUE hour;
+
+ hour = ref_hash("hour");
+ if (!NIL_P(hour)) {
+ hour = f_mod(hour, INT2FIX(12));
+ set_hash("hour", f_add(hour, merid));
+ }
+ }
+
+ return hash;
+}
+
+/*
+Local variables:
+c-file-style: "ruby"
+End:
+*/
diff --git a/ext/date/date_tmx.h b/ext/date/date_tmx.h
new file mode 100644
index 0000000000..993a15327d
--- /dev/null
+++ b/ext/date/date_tmx.h
@@ -0,0 +1,56 @@
+#ifndef DATE_TMX_H
+#define DATE_TMX_H
+
+struct tmx_funcs {
+ VALUE (*year)(void *dat);
+ int (*yday)(void *dat);
+ int (*mon)(void *dat);
+ int (*mday)(void *dat);
+ VALUE (*cwyear)(void *dat);
+ int (*cweek)(void *dat);
+ int (*cwday)(void *dat);
+ int (*wnum0)(void *dat);
+ int (*wnum1)(void *dat);
+ int (*wday)(void *dat);
+ int (*hour)(void *dat);
+ int (*min)(void *dat);
+ int (*sec)(void *dat);
+ VALUE (*sec_fraction)(void *dat);
+ VALUE (*secs)(void *dat);
+ VALUE (*msecs)(void *dat);
+ int (*offset)(void *dat);
+ char *(*zone)(void *dat);
+};
+struct tmx {
+ void *dat;
+ const struct tmx_funcs *funcs;
+};
+
+#define tmx_attr(x) (tmx->funcs->x)(tmx->dat)
+
+#define tmx_year tmx_attr(year)
+#define tmx_yday tmx_attr(yday)
+#define tmx_mon tmx_attr(mon)
+#define tmx_mday tmx_attr(mday)
+#define tmx_cwyear tmx_attr(cwyear)
+#define tmx_cweek tmx_attr(cweek)
+#define tmx_cwday tmx_attr(cwday)
+#define tmx_wnum0 tmx_attr(wnum0)
+#define tmx_wnum1 tmx_attr(wnum1)
+#define tmx_wday tmx_attr(wday)
+#define tmx_hour tmx_attr(hour)
+#define tmx_min tmx_attr(min)
+#define tmx_sec tmx_attr(sec)
+#define tmx_sec_fraction tmx_attr(sec_fraction)
+#define tmx_secs tmx_attr(secs)
+#define tmx_msecs tmx_attr(msecs)
+#define tmx_offset tmx_attr(offset)
+#define tmx_zone tmx_attr(zone)
+
+#endif
+
+/*
+Local variables:
+c-file-style: "ruby"
+End:
+*/
diff --git a/ext/date/depend b/ext/date/depend
new file mode 100644
index 0000000000..4fb78149a1
--- /dev/null
+++ b/ext/date/depend
@@ -0,0 +1,692 @@
+# AUTOGENERATED DEPENDENCIES START
+date_core.o: $(RUBY_EXTCONF_H)
+date_core.o: $(arch_hdrdir)/ruby/config.h
+date_core.o: $(hdrdir)/ruby.h
+date_core.o: $(hdrdir)/ruby/assert.h
+date_core.o: $(hdrdir)/ruby/backward.h
+date_core.o: $(hdrdir)/ruby/backward/2/assume.h
+date_core.o: $(hdrdir)/ruby/backward/2/attributes.h
+date_core.o: $(hdrdir)/ruby/backward/2/bool.h
+date_core.o: $(hdrdir)/ruby/backward/2/inttypes.h
+date_core.o: $(hdrdir)/ruby/backward/2/limits.h
+date_core.o: $(hdrdir)/ruby/backward/2/long_long.h
+date_core.o: $(hdrdir)/ruby/backward/2/stdalign.h
+date_core.o: $(hdrdir)/ruby/backward/2/stdarg.h
+date_core.o: $(hdrdir)/ruby/defines.h
+date_core.o: $(hdrdir)/ruby/encoding.h
+date_core.o: $(hdrdir)/ruby/intern.h
+date_core.o: $(hdrdir)/ruby/internal/abi.h
+date_core.o: $(hdrdir)/ruby/internal/anyargs.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+date_core.o: $(hdrdir)/ruby/internal/assume.h
+date_core.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+date_core.o: $(hdrdir)/ruby/internal/attr/artificial.h
+date_core.o: $(hdrdir)/ruby/internal/attr/cold.h
+date_core.o: $(hdrdir)/ruby/internal/attr/const.h
+date_core.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+date_core.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+date_core.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+date_core.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+date_core.o: $(hdrdir)/ruby/internal/attr/error.h
+date_core.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+date_core.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+date_core.o: $(hdrdir)/ruby/internal/attr/format.h
+date_core.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+date_core.o: $(hdrdir)/ruby/internal/attr/noalias.h
+date_core.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+date_core.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+date_core.o: $(hdrdir)/ruby/internal/attr/noinline.h
+date_core.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+date_core.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+date_core.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+date_core.o: $(hdrdir)/ruby/internal/attr/pure.h
+date_core.o: $(hdrdir)/ruby/internal/attr/restrict.h
+date_core.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+date_core.o: $(hdrdir)/ruby/internal/attr/warning.h
+date_core.o: $(hdrdir)/ruby/internal/attr/weakref.h
+date_core.o: $(hdrdir)/ruby/internal/cast.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_since.h
+date_core.o: $(hdrdir)/ruby/internal/config.h
+date_core.o: $(hdrdir)/ruby/internal/constant_p.h
+date_core.o: $(hdrdir)/ruby/internal/core.h
+date_core.o: $(hdrdir)/ruby/internal/core/rarray.h
+date_core.o: $(hdrdir)/ruby/internal/core/rbasic.h
+date_core.o: $(hdrdir)/ruby/internal/core/rbignum.h
+date_core.o: $(hdrdir)/ruby/internal/core/rclass.h
+date_core.o: $(hdrdir)/ruby/internal/core/rdata.h
+date_core.o: $(hdrdir)/ruby/internal/core/rfile.h
+date_core.o: $(hdrdir)/ruby/internal/core/rhash.h
+date_core.o: $(hdrdir)/ruby/internal/core/robject.h
+date_core.o: $(hdrdir)/ruby/internal/core/rregexp.h
+date_core.o: $(hdrdir)/ruby/internal/core/rstring.h
+date_core.o: $(hdrdir)/ruby/internal/core/rstruct.h
+date_core.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+date_core.o: $(hdrdir)/ruby/internal/ctype.h
+date_core.o: $(hdrdir)/ruby/internal/dllexport.h
+date_core.o: $(hdrdir)/ruby/internal/dosish.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/re.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/string.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+date_core.o: $(hdrdir)/ruby/internal/error.h
+date_core.o: $(hdrdir)/ruby/internal/eval.h
+date_core.o: $(hdrdir)/ruby/internal/event.h
+date_core.o: $(hdrdir)/ruby/internal/fl_type.h
+date_core.o: $(hdrdir)/ruby/internal/gc.h
+date_core.o: $(hdrdir)/ruby/internal/glob.h
+date_core.o: $(hdrdir)/ruby/internal/globals.h
+date_core.o: $(hdrdir)/ruby/internal/has/attribute.h
+date_core.o: $(hdrdir)/ruby/internal/has/builtin.h
+date_core.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+date_core.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+date_core.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+date_core.o: $(hdrdir)/ruby/internal/has/extension.h
+date_core.o: $(hdrdir)/ruby/internal/has/feature.h
+date_core.o: $(hdrdir)/ruby/internal/has/warning.h
+date_core.o: $(hdrdir)/ruby/internal/intern/array.h
+date_core.o: $(hdrdir)/ruby/internal/intern/bignum.h
+date_core.o: $(hdrdir)/ruby/internal/intern/class.h
+date_core.o: $(hdrdir)/ruby/internal/intern/compar.h
+date_core.o: $(hdrdir)/ruby/internal/intern/complex.h
+date_core.o: $(hdrdir)/ruby/internal/intern/cont.h
+date_core.o: $(hdrdir)/ruby/internal/intern/dir.h
+date_core.o: $(hdrdir)/ruby/internal/intern/enum.h
+date_core.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+date_core.o: $(hdrdir)/ruby/internal/intern/error.h
+date_core.o: $(hdrdir)/ruby/internal/intern/eval.h
+date_core.o: $(hdrdir)/ruby/internal/intern/file.h
+date_core.o: $(hdrdir)/ruby/internal/intern/hash.h
+date_core.o: $(hdrdir)/ruby/internal/intern/io.h
+date_core.o: $(hdrdir)/ruby/internal/intern/load.h
+date_core.o: $(hdrdir)/ruby/internal/intern/marshal.h
+date_core.o: $(hdrdir)/ruby/internal/intern/numeric.h
+date_core.o: $(hdrdir)/ruby/internal/intern/object.h
+date_core.o: $(hdrdir)/ruby/internal/intern/parse.h
+date_core.o: $(hdrdir)/ruby/internal/intern/proc.h
+date_core.o: $(hdrdir)/ruby/internal/intern/process.h
+date_core.o: $(hdrdir)/ruby/internal/intern/random.h
+date_core.o: $(hdrdir)/ruby/internal/intern/range.h
+date_core.o: $(hdrdir)/ruby/internal/intern/rational.h
+date_core.o: $(hdrdir)/ruby/internal/intern/re.h
+date_core.o: $(hdrdir)/ruby/internal/intern/ruby.h
+date_core.o: $(hdrdir)/ruby/internal/intern/select.h
+date_core.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+date_core.o: $(hdrdir)/ruby/internal/intern/set.h
+date_core.o: $(hdrdir)/ruby/internal/intern/signal.h
+date_core.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+date_core.o: $(hdrdir)/ruby/internal/intern/string.h
+date_core.o: $(hdrdir)/ruby/internal/intern/struct.h
+date_core.o: $(hdrdir)/ruby/internal/intern/thread.h
+date_core.o: $(hdrdir)/ruby/internal/intern/time.h
+date_core.o: $(hdrdir)/ruby/internal/intern/variable.h
+date_core.o: $(hdrdir)/ruby/internal/intern/vm.h
+date_core.o: $(hdrdir)/ruby/internal/interpreter.h
+date_core.o: $(hdrdir)/ruby/internal/iterator.h
+date_core.o: $(hdrdir)/ruby/internal/memory.h
+date_core.o: $(hdrdir)/ruby/internal/method.h
+date_core.o: $(hdrdir)/ruby/internal/module.h
+date_core.o: $(hdrdir)/ruby/internal/newobj.h
+date_core.o: $(hdrdir)/ruby/internal/scan_args.h
+date_core.o: $(hdrdir)/ruby/internal/special_consts.h
+date_core.o: $(hdrdir)/ruby/internal/static_assert.h
+date_core.o: $(hdrdir)/ruby/internal/stdalign.h
+date_core.o: $(hdrdir)/ruby/internal/stdbool.h
+date_core.o: $(hdrdir)/ruby/internal/stdckdint.h
+date_core.o: $(hdrdir)/ruby/internal/symbol.h
+date_core.o: $(hdrdir)/ruby/internal/value.h
+date_core.o: $(hdrdir)/ruby/internal/value_type.h
+date_core.o: $(hdrdir)/ruby/internal/variable.h
+date_core.o: $(hdrdir)/ruby/internal/warning_push.h
+date_core.o: $(hdrdir)/ruby/internal/xmalloc.h
+date_core.o: $(hdrdir)/ruby/missing.h
+date_core.o: $(hdrdir)/ruby/onigmo.h
+date_core.o: $(hdrdir)/ruby/oniguruma.h
+date_core.o: $(hdrdir)/ruby/ruby.h
+date_core.o: $(hdrdir)/ruby/st.h
+date_core.o: $(hdrdir)/ruby/subst.h
+date_core.o: $(hdrdir)/ruby/util.h
+date_core.o: date_core.c
+date_core.o: date_tmx.h
+date_parse.o: $(RUBY_EXTCONF_H)
+date_parse.o: $(arch_hdrdir)/ruby/config.h
+date_parse.o: $(hdrdir)/ruby.h
+date_parse.o: $(hdrdir)/ruby/assert.h
+date_parse.o: $(hdrdir)/ruby/backward.h
+date_parse.o: $(hdrdir)/ruby/backward/2/assume.h
+date_parse.o: $(hdrdir)/ruby/backward/2/attributes.h
+date_parse.o: $(hdrdir)/ruby/backward/2/bool.h
+date_parse.o: $(hdrdir)/ruby/backward/2/inttypes.h
+date_parse.o: $(hdrdir)/ruby/backward/2/limits.h
+date_parse.o: $(hdrdir)/ruby/backward/2/long_long.h
+date_parse.o: $(hdrdir)/ruby/backward/2/stdalign.h
+date_parse.o: $(hdrdir)/ruby/backward/2/stdarg.h
+date_parse.o: $(hdrdir)/ruby/defines.h
+date_parse.o: $(hdrdir)/ruby/encoding.h
+date_parse.o: $(hdrdir)/ruby/intern.h
+date_parse.o: $(hdrdir)/ruby/internal/abi.h
+date_parse.o: $(hdrdir)/ruby/internal/anyargs.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+date_parse.o: $(hdrdir)/ruby/internal/assume.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/artificial.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/cold.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/const.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/error.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/format.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/noalias.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/noinline.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/pure.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/restrict.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/warning.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/weakref.h
+date_parse.o: $(hdrdir)/ruby/internal/cast.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_since.h
+date_parse.o: $(hdrdir)/ruby/internal/config.h
+date_parse.o: $(hdrdir)/ruby/internal/constant_p.h
+date_parse.o: $(hdrdir)/ruby/internal/core.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rarray.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rbasic.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rbignum.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rclass.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rdata.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rfile.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rhash.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rmatch.h
+date_parse.o: $(hdrdir)/ruby/internal/core/robject.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rregexp.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rstring.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rstruct.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+date_parse.o: $(hdrdir)/ruby/internal/ctype.h
+date_parse.o: $(hdrdir)/ruby/internal/dllexport.h
+date_parse.o: $(hdrdir)/ruby/internal/dosish.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/re.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/string.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+date_parse.o: $(hdrdir)/ruby/internal/error.h
+date_parse.o: $(hdrdir)/ruby/internal/eval.h
+date_parse.o: $(hdrdir)/ruby/internal/event.h
+date_parse.o: $(hdrdir)/ruby/internal/fl_type.h
+date_parse.o: $(hdrdir)/ruby/internal/gc.h
+date_parse.o: $(hdrdir)/ruby/internal/glob.h
+date_parse.o: $(hdrdir)/ruby/internal/globals.h
+date_parse.o: $(hdrdir)/ruby/internal/has/attribute.h
+date_parse.o: $(hdrdir)/ruby/internal/has/builtin.h
+date_parse.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+date_parse.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+date_parse.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+date_parse.o: $(hdrdir)/ruby/internal/has/extension.h
+date_parse.o: $(hdrdir)/ruby/internal/has/feature.h
+date_parse.o: $(hdrdir)/ruby/internal/has/warning.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/array.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/bignum.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/class.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/compar.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/complex.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/cont.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/dir.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/enum.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/error.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/eval.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/file.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/hash.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/io.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/load.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/marshal.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/numeric.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/object.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/parse.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/proc.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/process.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/random.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/range.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/rational.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/re.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/ruby.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/select.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/set.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/signal.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/string.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/struct.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/thread.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/time.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/variable.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/vm.h
+date_parse.o: $(hdrdir)/ruby/internal/interpreter.h
+date_parse.o: $(hdrdir)/ruby/internal/iterator.h
+date_parse.o: $(hdrdir)/ruby/internal/memory.h
+date_parse.o: $(hdrdir)/ruby/internal/method.h
+date_parse.o: $(hdrdir)/ruby/internal/module.h
+date_parse.o: $(hdrdir)/ruby/internal/newobj.h
+date_parse.o: $(hdrdir)/ruby/internal/scan_args.h
+date_parse.o: $(hdrdir)/ruby/internal/special_consts.h
+date_parse.o: $(hdrdir)/ruby/internal/static_assert.h
+date_parse.o: $(hdrdir)/ruby/internal/stdalign.h
+date_parse.o: $(hdrdir)/ruby/internal/stdbool.h
+date_parse.o: $(hdrdir)/ruby/internal/stdckdint.h
+date_parse.o: $(hdrdir)/ruby/internal/symbol.h
+date_parse.o: $(hdrdir)/ruby/internal/value.h
+date_parse.o: $(hdrdir)/ruby/internal/value_type.h
+date_parse.o: $(hdrdir)/ruby/internal/variable.h
+date_parse.o: $(hdrdir)/ruby/internal/warning_push.h
+date_parse.o: $(hdrdir)/ruby/internal/xmalloc.h
+date_parse.o: $(hdrdir)/ruby/missing.h
+date_parse.o: $(hdrdir)/ruby/onigmo.h
+date_parse.o: $(hdrdir)/ruby/oniguruma.h
+date_parse.o: $(hdrdir)/ruby/re.h
+date_parse.o: $(hdrdir)/ruby/regex.h
+date_parse.o: $(hdrdir)/ruby/ruby.h
+date_parse.o: $(hdrdir)/ruby/st.h
+date_parse.o: $(hdrdir)/ruby/subst.h
+date_parse.o: date_parse.c
+date_parse.o: zonetab.h
+date_parse.o: zonetab.list
+date_strftime.o: $(RUBY_EXTCONF_H)
+date_strftime.o: $(arch_hdrdir)/ruby/config.h
+date_strftime.o: $(hdrdir)/ruby/assert.h
+date_strftime.o: $(hdrdir)/ruby/backward.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/assume.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/attributes.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/bool.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/inttypes.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/limits.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/long_long.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/stdalign.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/stdarg.h
+date_strftime.o: $(hdrdir)/ruby/defines.h
+date_strftime.o: $(hdrdir)/ruby/intern.h
+date_strftime.o: $(hdrdir)/ruby/internal/abi.h
+date_strftime.o: $(hdrdir)/ruby/internal/anyargs.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/assume.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/artificial.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/cold.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/const.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/error.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/format.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/noalias.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/noinline.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/pure.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/restrict.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/warning.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/weakref.h
+date_strftime.o: $(hdrdir)/ruby/internal/cast.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_since.h
+date_strftime.o: $(hdrdir)/ruby/internal/config.h
+date_strftime.o: $(hdrdir)/ruby/internal/constant_p.h
+date_strftime.o: $(hdrdir)/ruby/internal/core.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rarray.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rbasic.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rbignum.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rclass.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rdata.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rfile.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rhash.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/robject.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rregexp.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rstring.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rstruct.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+date_strftime.o: $(hdrdir)/ruby/internal/ctype.h
+date_strftime.o: $(hdrdir)/ruby/internal/dllexport.h
+date_strftime.o: $(hdrdir)/ruby/internal/dosish.h
+date_strftime.o: $(hdrdir)/ruby/internal/error.h
+date_strftime.o: $(hdrdir)/ruby/internal/eval.h
+date_strftime.o: $(hdrdir)/ruby/internal/event.h
+date_strftime.o: $(hdrdir)/ruby/internal/fl_type.h
+date_strftime.o: $(hdrdir)/ruby/internal/gc.h
+date_strftime.o: $(hdrdir)/ruby/internal/glob.h
+date_strftime.o: $(hdrdir)/ruby/internal/globals.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/attribute.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/builtin.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/extension.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/feature.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/warning.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/array.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/bignum.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/class.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/compar.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/complex.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/cont.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/dir.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/enum.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/error.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/eval.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/file.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/hash.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/io.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/load.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/marshal.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/numeric.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/object.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/parse.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/proc.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/process.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/random.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/range.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/rational.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/re.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/ruby.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/select.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/set.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/signal.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/string.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/struct.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/thread.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/time.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/variable.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/vm.h
+date_strftime.o: $(hdrdir)/ruby/internal/interpreter.h
+date_strftime.o: $(hdrdir)/ruby/internal/iterator.h
+date_strftime.o: $(hdrdir)/ruby/internal/memory.h
+date_strftime.o: $(hdrdir)/ruby/internal/method.h
+date_strftime.o: $(hdrdir)/ruby/internal/module.h
+date_strftime.o: $(hdrdir)/ruby/internal/newobj.h
+date_strftime.o: $(hdrdir)/ruby/internal/scan_args.h
+date_strftime.o: $(hdrdir)/ruby/internal/special_consts.h
+date_strftime.o: $(hdrdir)/ruby/internal/static_assert.h
+date_strftime.o: $(hdrdir)/ruby/internal/stdalign.h
+date_strftime.o: $(hdrdir)/ruby/internal/stdbool.h
+date_strftime.o: $(hdrdir)/ruby/internal/stdckdint.h
+date_strftime.o: $(hdrdir)/ruby/internal/symbol.h
+date_strftime.o: $(hdrdir)/ruby/internal/value.h
+date_strftime.o: $(hdrdir)/ruby/internal/value_type.h
+date_strftime.o: $(hdrdir)/ruby/internal/variable.h
+date_strftime.o: $(hdrdir)/ruby/internal/warning_push.h
+date_strftime.o: $(hdrdir)/ruby/internal/xmalloc.h
+date_strftime.o: $(hdrdir)/ruby/missing.h
+date_strftime.o: $(hdrdir)/ruby/ruby.h
+date_strftime.o: $(hdrdir)/ruby/st.h
+date_strftime.o: $(hdrdir)/ruby/subst.h
+date_strftime.o: date_strftime.c
+date_strftime.o: date_tmx.h
+date_strptime.o: $(RUBY_EXTCONF_H)
+date_strptime.o: $(arch_hdrdir)/ruby/config.h
+date_strptime.o: $(hdrdir)/ruby.h
+date_strptime.o: $(hdrdir)/ruby/assert.h
+date_strptime.o: $(hdrdir)/ruby/backward.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/assume.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/attributes.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/bool.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/inttypes.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/limits.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/long_long.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/stdalign.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/stdarg.h
+date_strptime.o: $(hdrdir)/ruby/defines.h
+date_strptime.o: $(hdrdir)/ruby/encoding.h
+date_strptime.o: $(hdrdir)/ruby/intern.h
+date_strptime.o: $(hdrdir)/ruby/internal/abi.h
+date_strptime.o: $(hdrdir)/ruby/internal/anyargs.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/assume.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/artificial.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/cold.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/const.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/error.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/format.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/noalias.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/noinline.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/pure.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/restrict.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/warning.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/weakref.h
+date_strptime.o: $(hdrdir)/ruby/internal/cast.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_since.h
+date_strptime.o: $(hdrdir)/ruby/internal/config.h
+date_strptime.o: $(hdrdir)/ruby/internal/constant_p.h
+date_strptime.o: $(hdrdir)/ruby/internal/core.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rarray.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rbasic.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rbignum.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rclass.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rdata.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rfile.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rhash.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rmatch.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/robject.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rregexp.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rstring.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rstruct.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+date_strptime.o: $(hdrdir)/ruby/internal/ctype.h
+date_strptime.o: $(hdrdir)/ruby/internal/dllexport.h
+date_strptime.o: $(hdrdir)/ruby/internal/dosish.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/re.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/string.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+date_strptime.o: $(hdrdir)/ruby/internal/error.h
+date_strptime.o: $(hdrdir)/ruby/internal/eval.h
+date_strptime.o: $(hdrdir)/ruby/internal/event.h
+date_strptime.o: $(hdrdir)/ruby/internal/fl_type.h
+date_strptime.o: $(hdrdir)/ruby/internal/gc.h
+date_strptime.o: $(hdrdir)/ruby/internal/glob.h
+date_strptime.o: $(hdrdir)/ruby/internal/globals.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/attribute.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/builtin.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/extension.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/feature.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/warning.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/array.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/bignum.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/class.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/compar.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/complex.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/cont.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/dir.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/enum.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/error.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/eval.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/file.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/hash.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/io.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/load.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/marshal.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/numeric.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/object.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/parse.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/proc.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/process.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/random.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/range.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/rational.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/re.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/ruby.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/select.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/set.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/signal.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/string.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/struct.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/thread.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/time.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/variable.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/vm.h
+date_strptime.o: $(hdrdir)/ruby/internal/interpreter.h
+date_strptime.o: $(hdrdir)/ruby/internal/iterator.h
+date_strptime.o: $(hdrdir)/ruby/internal/memory.h
+date_strptime.o: $(hdrdir)/ruby/internal/method.h
+date_strptime.o: $(hdrdir)/ruby/internal/module.h
+date_strptime.o: $(hdrdir)/ruby/internal/newobj.h
+date_strptime.o: $(hdrdir)/ruby/internal/scan_args.h
+date_strptime.o: $(hdrdir)/ruby/internal/special_consts.h
+date_strptime.o: $(hdrdir)/ruby/internal/static_assert.h
+date_strptime.o: $(hdrdir)/ruby/internal/stdalign.h
+date_strptime.o: $(hdrdir)/ruby/internal/stdbool.h
+date_strptime.o: $(hdrdir)/ruby/internal/stdckdint.h
+date_strptime.o: $(hdrdir)/ruby/internal/symbol.h
+date_strptime.o: $(hdrdir)/ruby/internal/value.h
+date_strptime.o: $(hdrdir)/ruby/internal/value_type.h
+date_strptime.o: $(hdrdir)/ruby/internal/variable.h
+date_strptime.o: $(hdrdir)/ruby/internal/warning_push.h
+date_strptime.o: $(hdrdir)/ruby/internal/xmalloc.h
+date_strptime.o: $(hdrdir)/ruby/missing.h
+date_strptime.o: $(hdrdir)/ruby/onigmo.h
+date_strptime.o: $(hdrdir)/ruby/oniguruma.h
+date_strptime.o: $(hdrdir)/ruby/re.h
+date_strptime.o: $(hdrdir)/ruby/regex.h
+date_strptime.o: $(hdrdir)/ruby/ruby.h
+date_strptime.o: $(hdrdir)/ruby/st.h
+date_strptime.o: $(hdrdir)/ruby/subst.h
+date_strptime.o: date_strptime.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/date/extconf.rb b/ext/date/extconf.rb
new file mode 100644
index 0000000000..8a1467df09
--- /dev/null
+++ b/ext/date/extconf.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+require 'mkmf'
+
+config_string("strict_warnflags") {|w| $warnflags += " #{w}"}
+
+append_cflags("-Wno-compound-token-split-by-macro") if RUBY_VERSION < "2.7."
+have_func("rb_category_warn")
+with_werror("", {:werror => true}) do |opt, |
+ have_var("timezone", "time.h", opt)
+ have_var("altzone", "time.h", opt)
+end
+
+create_makefile('date_core')
diff --git a/ext/date/lib/date.rb b/ext/date/lib/date.rb
new file mode 100644
index 0000000000..0cb763017f
--- /dev/null
+++ b/ext/date/lib/date.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+# date.rb: Written by Tadayoshi Funaba 1998-2011
+
+require 'date_core'
+
+class Date
+ VERSION = "3.5.1" # :nodoc:
+
+ # call-seq:
+ # infinite? -> false
+ #
+ # Returns +false+
+ def infinite?
+ false
+ end
+
+ class Infinity < Numeric # :nodoc:
+
+ def initialize(d=1) @d = d <=> 0 end
+
+ def d() @d end
+
+ protected :d
+
+ def zero?() false end
+ def finite?() false end
+ def infinite?() d.nonzero? end
+ def nan?() d.zero? end
+
+ def abs() self.class.new end
+
+ def -@() self.class.new(-d) end
+ def +@() self.class.new(+d) end
+
+ def <=>(other)
+ case other
+ when Infinity; return d <=> other.d
+ when Float::INFINITY; return d <=> 1
+ when -Float::INFINITY; return d <=> -1
+ when Numeric; return d
+ else
+ begin
+ l, r = other.coerce(self)
+ return l <=> r
+ rescue NoMethodError
+ end
+ end
+ nil
+ end
+
+ def coerce(other)
+ case other
+ when Numeric; return -d, d
+ else
+ super
+ end
+ end
+
+ def to_f
+ return 0 if @d == 0
+ if @d > 0
+ Float::INFINITY
+ else
+ -Float::INFINITY
+ end
+ end
+
+ end
+
+end
diff --git a/ext/date/prereq.mk b/ext/date/prereq.mk
new file mode 100644
index 0000000000..b5d271a32c
--- /dev/null
+++ b/ext/date/prereq.mk
@@ -0,0 +1,19 @@
+.SUFFIXES: .list
+
+.list.h:
+ gperf --ignore-case -L ANSI-C -C -c -P -p -j1 -i 1 -g -o -t -N $(*F) $< \
+ | sed -f $(top_srcdir)/tool/gperf.sed \
+ > $(@F)
+
+zonetab.h: zonetab.list
+
+.PHONY: update-zonetab
+update-zonetab:
+ $(RUBY) -C $(srcdir) update-abbr
+
+.PHONY: update-nothing
+update-nothing:
+
+update = nothing
+
+zonetab.list: update-$(update)
diff --git a/ext/date/update-abbr b/ext/date/update-abbr
new file mode 100644
index 0000000000..7fe9734e6d
--- /dev/null
+++ b/ext/date/update-abbr
@@ -0,0 +1,52 @@
+# -*- mode: ruby -*-
+require 'nokogiri'
+require 'open-uri'
+
+doc = Nokogiri::HTML(URI.open(ARGV[0] || 'https://www.timeanddate.com/time/zones/'))
+
+h = {}
+
+doc.css('#tz-abb tbody tr').each do |tr|
+ tds = tr.css('td')
+ abbr = tds[0].text.strip.downcase
+ offset = tds[3].text.strip.gsub(/UTC\s*/, '')
+ next if offset.include?('/') # skip ambiguous timezones
+ next if offset.empty?
+
+
+ hour, min = offset.split(':', 2)
+ offset = (Integer(hour) * 60 + (Integer(min || 0)))*60
+ if h.has_key?(abbr)
+ h[abbr] = false
+ else
+ h[abbr] = offset
+ end
+end
+
+h.delete_if{|_,v| !v}
+
+lines = File.readlines('zonetab.list')
+lines.map! do |l|
+ if (sep = /^%%/ =~ l)...(sep = /^%%/ =~ l) and !sep
+ z, o = l.split(/,\s*/, 2)
+ o.strip!
+ if ho = h.delete(z) and ho != eval(o)
+ warn "offset of #{z}: #{o} -> #{ho}"
+ l = l.sub(/,\s*\K.*/) {
+ if o.include?("*")
+ o1, o2 = ho.abs.divmod(3600)
+ o1 = "#{o1}*3600"
+ o1 = "(#{o1}+#{o2})" if o2 != 0
+ ho < 0 ? "-#{o1}" : o1
+ else
+ ho.to_s
+ end
+ }
+ end
+ end
+ l
+end
+
+lines.insert(-2, h.sort.map{|k,v| "#{k},#{v}\n"})
+lines.flatten!
+File.write('zonetab.list', lines.join)
diff --git a/ext/date/zonetab.h b/ext/date/zonetab.h
new file mode 100644
index 0000000000..2a2e8910c9
--- /dev/null
+++ b/ext/date/zonetab.h
@@ -0,0 +1,1564 @@
+/* ANSI-C code produced by gperf version 3.1 */
+/* Command-line: gperf --ignore-case -L ANSI-C -C -c -P -p -j1 -i 1 -g -o -t -N zonetab zonetab.list */
+/* Computed positions: -k'1-4,9' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
+#endif
+
+#line 1 "zonetab.list"
+
+#define GPERF_DOWNCASE 1
+#define GPERF_CASE_STRNCMP 1
+#define gperf_case_strncmp strncasecmp
+struct zone {
+ int name;
+ int offset;
+};
+static const struct zone *zonetab(register const char *str, register size_t len);
+#line 12 "zonetab.list"
+struct zone;
+
+#define TOTAL_KEYWORDS 316
+#define MIN_WORD_LENGTH 1
+#define MAX_WORD_LENGTH 17
+#define MIN_HASH_VALUE 2
+#define MAX_HASH_VALUE 619
+/* maximum key range = 618, duplicates = 0 */
+
+#ifndef GPERF_DOWNCASE
+#define GPERF_DOWNCASE 1
+static unsigned char gperf_downcase[256] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
+ 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
+ 255
+ };
+#endif
+
+#ifndef GPERF_CASE_STRNCMP
+#define GPERF_CASE_STRNCMP 1
+static int
+gperf_case_strncmp (register const char *s1, register const char *s2, register size_t n)
+{
+ for (; n > 0;)
+ {
+ unsigned char c1 = gperf_downcase[(unsigned char)*s1++];
+ unsigned char c2 = gperf_downcase[(unsigned char)*s2++];
+ if (c1 != 0 && c1 == c2)
+ {
+ n--;
+ continue;
+ }
+ return (int)c1 - (int)c2;
+ }
+ return 0;
+}
+#endif
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash (register const char *str, register size_t len)
+{
+ static const unsigned short asso_values[] =
+ {
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 17, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 3, 2, 620, 620, 620,
+ 620, 620, 70, 8, 3, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 39, 176, 207, 70, 168,
+ 1, 5, 18, 74, 218, 2, 117, 130, 48, 88,
+ 125, 225, 92, 1, 1, 12, 54, 30, 36, 13,
+ 48, 168, 263, 59, 114, 166, 109, 39, 176, 207,
+ 70, 168, 1, 5, 18, 74, 218, 2, 117, 130,
+ 48, 88, 125, 225, 92, 1, 1, 12, 54, 30,
+ 36, 13, 48, 168, 263, 59, 114, 166, 109, 27,
+ 104, 1, 9, 4, 309, 190, 188, 177, 255, 108,
+ 2, 341, 3, 620, 620, 620, 620, 620, 620, 12,
+ 54, 30, 36, 13, 48, 168, 263, 59, 114, 166,
+ 109, 27, 104, 1, 9, 4, 309, 190, 188, 177,
+ 255, 108, 2, 341, 3, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 620, 620, 620, 620, 620, 620, 620
+ };
+ register unsigned int hval = (unsigned int)len;
+
+ switch (hval)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[8]];
+ /*FALLTHROUGH*/
+ case 8:
+ case 7:
+ case 6:
+ case 5:
+ case 4:
+ hval += asso_values[(unsigned char)str[3]];
+ /*FALLTHROUGH*/
+ case 3:
+ hval += asso_values[(unsigned char)str[2]];
+ /*FALLTHROUGH*/
+ case 2:
+ hval += asso_values[(unsigned char)str[1]+6];
+ /*FALLTHROUGH*/
+ case 1:
+ hval += asso_values[(unsigned char)str[0]+52];
+ break;
+ }
+ return (unsigned int)hval;
+}
+
+struct stringpool_t
+ {
+ char stringpool_str2[sizeof("o")];
+ char stringpool_str3[sizeof("x")];
+ char stringpool_str4[sizeof("z")];
+ char stringpool_str5[sizeof("q")];
+ char stringpool_str8[sizeof("omst")];
+ char stringpool_str9[sizeof("omsst")];
+ char stringpool_str10[sizeof("p")];
+ char stringpool_str13[sizeof("a")];
+ char stringpool_str14[sizeof("e")];
+ char stringpool_str15[sizeof("pet")];
+ char stringpool_str16[sizeof("pmst")];
+ char stringpool_str17[sizeof("pett")];
+ char stringpool_str18[sizeof("petst")];
+ char stringpool_str19[sizeof("eet")];
+ char stringpool_str20[sizeof("aest")];
+ char stringpool_str21[sizeof("eest")];
+ char stringpool_str22[sizeof("eat")];
+ char stringpool_str24[sizeof("east")];
+ char stringpool_str25[sizeof("easst")];
+ char stringpool_str26[sizeof("pst")];
+ char stringpool_str27[sizeof("eastern")];
+ char stringpool_str28[sizeof("m")];
+ char stringpool_str29[sizeof("ast")];
+ char stringpool_str30[sizeof("est")];
+ char stringpool_str31[sizeof("c")];
+ char stringpool_str32[sizeof("mmt")];
+ char stringpool_str33[sizeof("met")];
+ char stringpool_str35[sizeof("mest")];
+ char stringpool_str36[sizeof("cet")];
+ char stringpool_str37[sizeof("d")];
+ char stringpool_str38[sizeof("cest")];
+ char stringpool_str39[sizeof("cat")];
+ char stringpool_str41[sizeof("cast")];
+ char stringpool_str42[sizeof("magt")];
+ char stringpool_str43[sizeof("magst")];
+ char stringpool_str44[sizeof("mst")];
+ char stringpool_str45[sizeof("msk")];
+ char stringpool_str46[sizeof("cot")];
+ char stringpool_str47[sizeof("cst")];
+ char stringpool_str48[sizeof("aqtt")];
+ char stringpool_str49[sizeof("f")];
+ char stringpool_str52[sizeof("art")];
+ char stringpool_str53[sizeof("fnt")];
+ char stringpool_str54[sizeof("fet")];
+ char stringpool_str55[sizeof("b")];
+ char stringpool_str57[sizeof("anat")];
+ char stringpool_str58[sizeof("anast")];
+ char stringpool_str59[sizeof("bnt")];
+ char stringpool_str60[sizeof("i")];
+ char stringpool_str61[sizeof("pht")];
+ char stringpool_str62[sizeof("at")];
+ char stringpool_str63[sizeof("zp6")];
+ char stringpool_str64[sizeof("mewt")];
+ char stringpool_str65[sizeof("fst")];
+ char stringpool_str66[sizeof("ahst")];
+ char stringpool_str67[sizeof("mawt")];
+ char stringpool_str68[sizeof("zp5")];
+ char stringpool_str70[sizeof("bot")];
+ char stringpool_str71[sizeof("bst")];
+ char stringpool_str72[sizeof("pwt")];
+ char stringpool_str74[sizeof("pont")];
+ char stringpool_str75[sizeof("iot")];
+ char stringpool_str76[sizeof("ist")];
+ char stringpool_str77[sizeof("awst")];
+ char stringpool_str79[sizeof("mht")];
+ char stringpool_str80[sizeof("mez")];
+ char stringpool_str81[sizeof("orat")];
+ char stringpool_str82[sizeof("mesz")];
+ char stringpool_str84[sizeof("chst")];
+ char stringpool_str85[sizeof("pmdt")];
+ char stringpool_str88[sizeof("central")];
+ char stringpool_str89[sizeof("aedt")];
+ char stringpool_str90[sizeof("act")];
+ char stringpool_str91[sizeof("ect")];
+ char stringpool_str92[sizeof("acst")];
+ char stringpool_str93[sizeof("eadt")];
+ char stringpool_str94[sizeof("brt")];
+ char stringpool_str95[sizeof("chut")];
+ char stringpool_str96[sizeof("brst")];
+ char stringpool_str97[sizeof("cen. australia")];
+ char stringpool_str100[sizeof("davt")];
+ char stringpool_str101[sizeof("irst")];
+ char stringpool_str102[sizeof("irkt")];
+ char stringpool_str103[sizeof("irkst")];
+ char stringpool_str104[sizeof("bt")];
+ char stringpool_str105[sizeof("n")];
+ char stringpool_str106[sizeof("btt")];
+ char stringpool_str107[sizeof("mountain")];
+ char stringpool_str108[sizeof("cct")];
+ char stringpool_str109[sizeof("w")];
+ char stringpool_str110[sizeof("l")];
+ char stringpool_str111[sizeof("fwt")];
+ char stringpool_str113[sizeof("msd")];
+ char stringpool_str114[sizeof("wet")];
+ char stringpool_str116[sizeof("west")];
+ char stringpool_str117[sizeof("wat")];
+ char stringpool_str119[sizeof("wast")];
+ char stringpool_str120[sizeof("wakt")];
+ char stringpool_str121[sizeof("nst")];
+ char stringpool_str122[sizeof("acwst")];
+ char stringpool_str123[sizeof("chast")];
+ char stringpool_str124[sizeof("cist")];
+ char stringpool_str125[sizeof("azt")];
+ char stringpool_str126[sizeof("clt")];
+ char stringpool_str127[sizeof("azst")];
+ char stringpool_str128[sizeof("clst")];
+ char stringpool_str129[sizeof("mart")];
+ char stringpool_str130[sizeof("zp4")];
+ char stringpool_str131[sizeof("jst")];
+ char stringpool_str132[sizeof("central asia")];
+ char stringpool_str133[sizeof("aft")];
+ char stringpool_str134[sizeof("e. south america")];
+ char stringpool_str135[sizeof("central america")];
+ char stringpool_str137[sizeof("ict")];
+ char stringpool_str143[sizeof("pgt")];
+ char stringpool_str144[sizeof("nrt")];
+ char stringpool_str145[sizeof("mexico")];
+ char stringpool_str146[sizeof("awdt")];
+ char stringpool_str147[sizeof("egt")];
+ char stringpool_str148[sizeof("cxt")];
+ char stringpool_str149[sizeof("egst")];
+ char stringpool_str150[sizeof("phot")];
+ char stringpool_str151[sizeof("alaskan")];
+ char stringpool_str154[sizeof("nt")];
+ char stringpool_str158[sizeof("wt")];
+ char stringpool_str160[sizeof("west asia")];
+ char stringpool_str161[sizeof("acdt")];
+ char stringpool_str162[sizeof("npt")];
+ char stringpool_str163[sizeof("lhst")];
+ char stringpool_str164[sizeof("afghanistan")];
+ char stringpool_str167[sizeof("k")];
+ char stringpool_str169[sizeof("g")];
+ char stringpool_str170[sizeof("irdt")];
+ char stringpool_str171[sizeof("chot")];
+ char stringpool_str172[sizeof("chost")];
+ char stringpool_str173[sizeof("gmt")];
+ char stringpool_str174[sizeof("get")];
+ char stringpool_str175[sizeof("novt")];
+ char stringpool_str176[sizeof("novst")];
+ char stringpool_str177[sizeof("fjt")];
+ char stringpool_str178[sizeof("u")];
+ char stringpool_str179[sizeof("fjst")];
+ char stringpool_str181[sizeof("pyst")];
+ char stringpool_str182[sizeof("nct")];
+ char stringpool_str183[sizeof("kst")];
+ char stringpool_str184[sizeof("kost")];
+ char stringpool_str185[sizeof("gst")];
+ char stringpool_str186[sizeof("iran")];
+ char stringpool_str187[sizeof("e. africa")];
+ char stringpool_str188[sizeof("wadt")];
+ char stringpool_str189[sizeof("t")];
+ char stringpool_str190[sizeof("e. australia")];
+ char stringpool_str191[sizeof("s")];
+ char stringpool_str192[sizeof("chadt")];
+ char stringpool_str193[sizeof("tmt")];
+ char stringpool_str194[sizeof("cidst")];
+ char stringpool_str195[sizeof("aoe")];
+ char stringpool_str197[sizeof("myt")];
+ char stringpool_str198[sizeof("west pacific")];
+ char stringpool_str199[sizeof("mut")];
+ char stringpool_str200[sizeof("wit")];
+ char stringpool_str201[sizeof("sast")];
+ char stringpool_str202[sizeof("sakt")];
+ char stringpool_str203[sizeof("new zealand")];
+ char stringpool_str204[sizeof("tot")];
+ char stringpool_str205[sizeof("china")];
+ char stringpool_str206[sizeof("tost")];
+ char stringpool_str207[sizeof("sst")];
+ char stringpool_str209[sizeof("india")];
+ char stringpool_str211[sizeof("warst")];
+ char stringpool_str212[sizeof("sbt")];
+ char stringpool_str214[sizeof("azot")];
+ char stringpool_str215[sizeof("azost")];
+ char stringpool_str216[sizeof("taht")];
+ char stringpool_str217[sizeof("nzt")];
+ char stringpool_str218[sizeof("dateline")];
+ char stringpool_str219[sizeof("nzst")];
+ char stringpool_str220[sizeof("tokyo")];
+ char stringpool_str221[sizeof("central pacific")];
+ char stringpool_str223[sizeof("qyzt")];
+ char stringpool_str224[sizeof("atlantic")];
+ char stringpool_str225[sizeof("nft")];
+ char stringpool_str227[sizeof("ut")];
+ char stringpool_str228[sizeof("trt")];
+ char stringpool_str229[sizeof("wft")];
+ char stringpool_str230[sizeof("srt")];
+ char stringpool_str231[sizeof("pdt")];
+ char stringpool_str232[sizeof("lhdt")];
+ char stringpool_str234[sizeof("adt")];
+ char stringpool_str235[sizeof("edt")];
+ char stringpool_str238[sizeof("pkt")];
+ char stringpool_str239[sizeof("almt")];
+ char stringpool_str240[sizeof("wita")];
+ char stringpool_str242[sizeof("wgt")];
+ char stringpool_str243[sizeof("akst")];
+ char stringpool_str244[sizeof("wgst")];
+ char stringpool_str246[sizeof("krat")];
+ char stringpool_str247[sizeof("krast")];
+ char stringpool_str248[sizeof("mid-atlantic")];
+ char stringpool_str249[sizeof("mdt")];
+ char stringpool_str250[sizeof("lint")];
+ char stringpool_str251[sizeof("malay peninsula")];
+ char stringpool_str252[sizeof("cdt")];
+ char stringpool_str253[sizeof("swt")];
+ char stringpool_str255[sizeof("se asia")];
+ char stringpool_str256[sizeof("v")];
+ char stringpool_str258[sizeof("tonga")];
+ char stringpool_str259[sizeof("ckt")];
+ char stringpool_str261[sizeof("vet")];
+ char stringpool_str262[sizeof("caucasus")];
+ char stringpool_str263[sizeof("central europe")];
+ char stringpool_str264[sizeof("h")];
+ char stringpool_str265[sizeof("central european")];
+ char stringpool_str266[sizeof("newfoundland")];
+ char stringpool_str267[sizeof("arab")];
+ char stringpool_str268[sizeof("sct")];
+ char stringpool_str269[sizeof("arabic")];
+ char stringpool_str270[sizeof("arabian")];
+ char stringpool_str271[sizeof("ddut")];
+ char stringpool_str273[sizeof("vost")];
+ char stringpool_str274[sizeof("hast")];
+ char stringpool_str275[sizeof("nepal")];
+ char stringpool_str276[sizeof("nut")];
+ char stringpool_str277[sizeof("fkt")];
+ char stringpool_str279[sizeof("fkst")];
+ char stringpool_str280[sizeof("hst")];
+ char stringpool_str281[sizeof("idt")];
+ char stringpool_str284[sizeof("tlt")];
+ char stringpool_str285[sizeof("w. australia")];
+ char stringpool_str286[sizeof("egypt")];
+ char stringpool_str287[sizeof("myanmar")];
+ char stringpool_str288[sizeof("nzdt")];
+ char stringpool_str289[sizeof("gft")];
+ char stringpool_str290[sizeof("uzt")];
+ char stringpool_str293[sizeof("north asia")];
+ char stringpool_str294[sizeof("mvt")];
+ char stringpool_str295[sizeof("galt")];
+ char stringpool_str296[sizeof("nfdt")];
+ char stringpool_str297[sizeof("cvt")];
+ char stringpool_str298[sizeof("north asia east")];
+ char stringpool_str300[sizeof("kgt")];
+ char stringpool_str301[sizeof("aus central")];
+ char stringpool_str302[sizeof("pacific")];
+ char stringpool_str304[sizeof("canada central")];
+ char stringpool_str306[sizeof("pacific sa")];
+ char stringpool_str307[sizeof("azores")];
+ char stringpool_str308[sizeof("gamt")];
+ char stringpool_str309[sizeof("tft")];
+ char stringpool_str310[sizeof("r")];
+ char stringpool_str311[sizeof("fle")];
+ char stringpool_str312[sizeof("akdt")];
+ char stringpool_str313[sizeof("ulat")];
+ char stringpool_str314[sizeof("ulast")];
+ char stringpool_str315[sizeof("ret")];
+ char stringpool_str317[sizeof("tjt")];
+ char stringpool_str319[sizeof("south africa")];
+ char stringpool_str324[sizeof("sgt")];
+ char stringpool_str326[sizeof("ndt")];
+ char stringpool_str327[sizeof("rott")];
+ char stringpool_str330[sizeof("samt")];
+ char stringpool_str332[sizeof("tasmania")];
+ char stringpool_str334[sizeof("hovt")];
+ char stringpool_str335[sizeof("hovst")];
+ char stringpool_str338[sizeof("gyt")];
+ char stringpool_str342[sizeof("y")];
+ char stringpool_str343[sizeof("hadt")];
+ char stringpool_str344[sizeof("sa western")];
+ char stringpool_str345[sizeof("hawaiian")];
+ char stringpool_str347[sizeof("uyt")];
+ char stringpool_str349[sizeof("uyst")];
+ char stringpool_str350[sizeof("yekt")];
+ char stringpool_str351[sizeof("yekst")];
+ char stringpool_str352[sizeof("kuyt")];
+ char stringpool_str353[sizeof("yakt")];
+ char stringpool_str354[sizeof("yakst")];
+ char stringpool_str358[sizeof("yst")];
+ char stringpool_str359[sizeof("jerusalem")];
+ char stringpool_str365[sizeof("sri lanka")];
+ char stringpool_str367[sizeof("yakutsk")];
+ char stringpool_str375[sizeof("wib")];
+ char stringpool_str377[sizeof("aus eastern")];
+ char stringpool_str378[sizeof("gilt")];
+ char stringpool_str387[sizeof("us mountain")];
+ char stringpool_str391[sizeof("vlat")];
+ char stringpool_str392[sizeof("vlast")];
+ char stringpool_str395[sizeof("gtb")];
+ char stringpool_str398[sizeof("taipei")];
+ char stringpool_str399[sizeof("sret")];
+ char stringpool_str408[sizeof("cape verde")];
+ char stringpool_str417[sizeof("tkt")];
+ char stringpool_str418[sizeof("samoa")];
+ char stringpool_str421[sizeof("sa pacific")];
+ char stringpool_str427[sizeof("vut")];
+ char stringpool_str428[sizeof("idlw")];
+ char stringpool_str432[sizeof("fiji")];
+ char stringpool_str435[sizeof("utc")];
+ char stringpool_str443[sizeof("korea")];
+ char stringpool_str445[sizeof("e. europe")];
+ char stringpool_str449[sizeof("syot")];
+ char stringpool_str452[sizeof("n. central asia")];
+ char stringpool_str455[sizeof("tvt")];
+ char stringpool_str458[sizeof("w. central africa")];
+ char stringpool_str466[sizeof("ekaterinburg")];
+ char stringpool_str468[sizeof("vladivostok")];
+ char stringpool_str476[sizeof("yapt")];
+ char stringpool_str477[sizeof("us eastern")];
+ char stringpool_str482[sizeof("sa eastern")];
+ char stringpool_str485[sizeof("hdt")];
+ char stringpool_str486[sizeof("russian")];
+ char stringpool_str492[sizeof("hkt")];
+ char stringpool_str497[sizeof("romance")];
+ char stringpool_str540[sizeof("w. europe")];
+ char stringpool_str563[sizeof("ydt")];
+ char stringpool_str566[sizeof("idle")];
+ char stringpool_str567[sizeof("greenwich")];
+ char stringpool_str619[sizeof("greenland")];
+ };
+static const struct stringpool_t stringpool_contents =
+ {
+ "o",
+ "x",
+ "z",
+ "q",
+ "omst",
+ "omsst",
+ "p",
+ "a",
+ "e",
+ "pet",
+ "pmst",
+ "pett",
+ "petst",
+ "eet",
+ "aest",
+ "eest",
+ "eat",
+ "east",
+ "easst",
+ "pst",
+ "eastern",
+ "m",
+ "ast",
+ "est",
+ "c",
+ "mmt",
+ "met",
+ "mest",
+ "cet",
+ "d",
+ "cest",
+ "cat",
+ "cast",
+ "magt",
+ "magst",
+ "mst",
+ "msk",
+ "cot",
+ "cst",
+ "aqtt",
+ "f",
+ "art",
+ "fnt",
+ "fet",
+ "b",
+ "anat",
+ "anast",
+ "bnt",
+ "i",
+ "pht",
+ "at",
+ "zp6",
+ "mewt",
+ "fst",
+ "ahst",
+ "mawt",
+ "zp5",
+ "bot",
+ "bst",
+ "pwt",
+ "pont",
+ "iot",
+ "ist",
+ "awst",
+ "mht",
+ "mez",
+ "orat",
+ "mesz",
+ "chst",
+ "pmdt",
+ "central",
+ "aedt",
+ "act",
+ "ect",
+ "acst",
+ "eadt",
+ "brt",
+ "chut",
+ "brst",
+ "cen. australia",
+ "davt",
+ "irst",
+ "irkt",
+ "irkst",
+ "bt",
+ "n",
+ "btt",
+ "mountain",
+ "cct",
+ "w",
+ "l",
+ "fwt",
+ "msd",
+ "wet",
+ "west",
+ "wat",
+ "wast",
+ "wakt",
+ "nst",
+ "acwst",
+ "chast",
+ "cist",
+ "azt",
+ "clt",
+ "azst",
+ "clst",
+ "mart",
+ "zp4",
+ "jst",
+ "central asia",
+ "aft",
+ "e. south america",
+ "central america",
+ "ict",
+ "pgt",
+ "nrt",
+ "mexico",
+ "awdt",
+ "egt",
+ "cxt",
+ "egst",
+ "phot",
+ "alaskan",
+ "nt",
+ "wt",
+ "west asia",
+ "acdt",
+ "npt",
+ "lhst",
+ "afghanistan",
+ "k",
+ "g",
+ "irdt",
+ "chot",
+ "chost",
+ "gmt",
+ "get",
+ "novt",
+ "novst",
+ "fjt",
+ "u",
+ "fjst",
+ "pyst",
+ "nct",
+ "kst",
+ "kost",
+ "gst",
+ "iran",
+ "e. africa",
+ "wadt",
+ "t",
+ "e. australia",
+ "s",
+ "chadt",
+ "tmt",
+ "cidst",
+ "aoe",
+ "myt",
+ "west pacific",
+ "mut",
+ "wit",
+ "sast",
+ "sakt",
+ "new zealand",
+ "tot",
+ "china",
+ "tost",
+ "sst",
+ "india",
+ "warst",
+ "sbt",
+ "azot",
+ "azost",
+ "taht",
+ "nzt",
+ "dateline",
+ "nzst",
+ "tokyo",
+ "central pacific",
+ "qyzt",
+ "atlantic",
+ "nft",
+ "ut",
+ "trt",
+ "wft",
+ "srt",
+ "pdt",
+ "lhdt",
+ "adt",
+ "edt",
+ "pkt",
+ "almt",
+ "wita",
+ "wgt",
+ "akst",
+ "wgst",
+ "krat",
+ "krast",
+ "mid-atlantic",
+ "mdt",
+ "lint",
+ "malay peninsula",
+ "cdt",
+ "swt",
+ "se asia",
+ "v",
+ "tonga",
+ "ckt",
+ "vet",
+ "caucasus",
+ "central europe",
+ "h",
+ "central european",
+ "newfoundland",
+ "arab",
+ "sct",
+ "arabic",
+ "arabian",
+ "ddut",
+ "vost",
+ "hast",
+ "nepal",
+ "nut",
+ "fkt",
+ "fkst",
+ "hst",
+ "idt",
+ "tlt",
+ "w. australia",
+ "egypt",
+ "myanmar",
+ "nzdt",
+ "gft",
+ "uzt",
+ "north asia",
+ "mvt",
+ "galt",
+ "nfdt",
+ "cvt",
+ "north asia east",
+ "kgt",
+ "aus central",
+ "pacific",
+ "canada central",
+ "pacific sa",
+ "azores",
+ "gamt",
+ "tft",
+ "r",
+ "fle",
+ "akdt",
+ "ulat",
+ "ulast",
+ "ret",
+ "tjt",
+ "south africa",
+ "sgt",
+ "ndt",
+ "rott",
+ "samt",
+ "tasmania",
+ "hovt",
+ "hovst",
+ "gyt",
+ "y",
+ "hadt",
+ "sa western",
+ "hawaiian",
+ "uyt",
+ "uyst",
+ "yekt",
+ "yekst",
+ "kuyt",
+ "yakt",
+ "yakst",
+ "yst",
+ "jerusalem",
+ "sri lanka",
+ "yakutsk",
+ "wib",
+ "aus eastern",
+ "gilt",
+ "us mountain",
+ "vlat",
+ "vlast",
+ "gtb",
+ "taipei",
+ "sret",
+ "cape verde",
+ "tkt",
+ "samoa",
+ "sa pacific",
+ "vut",
+ "idlw",
+ "fiji",
+ "utc",
+ "korea",
+ "e. europe",
+ "syot",
+ "n. central asia",
+ "tvt",
+ "w. central africa",
+ "ekaterinburg",
+ "vladivostok",
+ "yapt",
+ "us eastern",
+ "sa eastern",
+ "hdt",
+ "russian",
+ "hkt",
+ "romance",
+ "w. europe",
+ "ydt",
+ "idle",
+ "greenwich",
+ "greenland"
+ };
+#define stringpool ((const char *) &stringpool_contents)
+const struct zone *
+zonetab (register const char *str, register size_t len)
+{
+ static const struct zone wordlist[] =
+ {
+ {-1}, {-1},
+#line 37 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str2, -2*3600},
+#line 46 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str3, -11*3600},
+#line 48 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str4, 0*3600},
+#line 39 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str5, -4*3600},
+ {-1}, {-1},
+#line 272 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str8,21600},
+#line 271 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str9,25200},
+#line 38 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str10, -3*3600},
+ {-1}, {-1},
+#line 24 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str13, 1*3600},
+#line 28 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str14, 5*3600},
+#line 274 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str15,-18000},
+#line 282 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str16,-10800},
+#line 276 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str17,43200},
+#line 275 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str18,43200},
+#line 83 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str19, 2*3600},
+#line 189 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str20,36000},
+#line 91 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str21, 3*3600},
+#line 90 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str22, 3*3600},
+ {-1},
+#line 104 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str24,-6*3600},
+#line 220 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str25,-18000},
+#line 22 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str26, -8*3600},
+#line 136 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str27, -18000},
+#line 35 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str28, 12*3600},
+#line 59 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str29, -4*3600},
+#line 16 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str30, -5*3600},
+#line 26 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str31, 3*3600},
+#line 259 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str32,23400},
+#line 76 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str33, 1*3600},
+ {-1},
+#line 85 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str35, 2*3600},
+#line 74 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str36, 1*3600},
+#line 27 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str37, 4*3600},
+#line 82 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str38, 2*3600},
+#line 68 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str39,2*3600},
+ {-1},
+#line 205 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str41,28800},
+#line 255 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str42,39600},
+#line 254 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str43,43200},
+#line 20 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str44, -7*3600},
+#line 92 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str45, 3*3600},
+#line 215 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str46,-18000},
+#line 18 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str47, -6*3600},
+#line 195 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str48,18000},
+#line 29 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str49, 6*3600},
+ {-1}, {-1},
+#line 54 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str52, -3*3600},
+#line 229 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str53,-7200},
+#line 224 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str54,10800},
+#line 25 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str55, 2*3600},
+ {-1},
+#line 193 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str57,43200},
+#line 192 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str58,43200},
+#line 202 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str59,28800},
+#line 32 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str60, 9*3600},
+#line 279 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str61,28800},
+#line 51 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str62, -2*3600},
+#line 97 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str63, 6*3600},
+#line 77 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str64, 1*3600},
+#line 84 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str65, 2*3600},
+#line 67 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str66,-10*3600},
+#line 257 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str67,18000},
+#line 95 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str68, 5*3600},
+ {-1},
+#line 203 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str70,-14400},
+#line 73 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str71, 1*3600},
+#line 284 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str72,32400},
+ {-1},
+#line 283 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str74,39600},
+#line 241 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str75,21600},
+#line 96 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str76, (5*3600+1800)},
+#line 197 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str77,28800},
+ {-1},
+#line 258 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str79,43200},
+#line 78 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str80, 1*3600},
+#line 273 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str81,18000},
+#line 86 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str82, 2*3600},
+ {-1},
+#line 210 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str84,36000},
+#line 281 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str85,-7200},
+ {-1}, {-1},
+#line 129 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str88, -21600},
+#line 188 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str89,39600},
+#line 186 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str90,-18000},
+#line 221 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str91,-18000},
+#line 185 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str92,34200},
+#line 106 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str93,11*3600},
+#line 56 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str94, -3*3600},
+#line 211 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str95,36000},
+#line 52 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str96,-2*3600},
+#line 123 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str97, 34200},
+ {-1}, {-1},
+#line 218 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str100,25200},
+#line 245 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str101,12600},
+#line 244 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str102,28800},
+#line 243 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str103,32400},
+#line 89 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str104, 3*3600},
+#line 36 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str105, -1*3600},
+#line 204 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str106,21600},
+#line 151 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str107, -25200},
+#line 99 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str108, (6*3600+1800)},
+#line 45 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str109, -10*3600},
+#line 34 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str110, 11*3600},
+#line 75 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str111, 1*3600},
+ {-1},
+#line 93 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str113, 4*3600},
+#line 50 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str114, 0*3600},
+ {-1},
+#line 81 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str116, 1*3600},
+#line 80 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str117, 1*3600},
+ {-1},
+#line 98 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str119, 2*3600},
+#line 316 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str120,43200},
+#line 58 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str121, -(2*3600+1800)},
+#line 187 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str122,31500},
+#line 207 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str123,45900},
+#line 213 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str124,-18000},
+#line 201 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str125,14400},
+#line 60 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str126, -4*3600},
+#line 200 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str127,18000},
+#line 57 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str128,-3*3600},
+#line 256 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str129,-30600},
+#line 94 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str130, 4*3600},
+#line 102 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str131, 9*3600},
+#line 125 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str132, 21600},
+#line 190 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str133,16200},
+#line 135 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str134, -10800},
+#line 124 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str135, -21600},
+ {-1},
+#line 239 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str137,25200},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+#line 277 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str143,36000},
+#line 269 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str144,43200},
+#line 149 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str145, -21600},
+#line 196 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str146,32400},
+#line 223 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str147,-3600},
+#line 217 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str148,25200},
+#line 222 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str149,0},
+#line 278 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str150,46800},
+#line 112 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str151, -32400},
+ {-1}, {-1},
+#line 71 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str154, -11*3600},
+ {-1}, {-1}, {-1},
+#line 324 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str158,0},
+ {-1},
+#line 181 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str160, 18000},
+#line 184 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str161,37800},
+#line 268 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str162,20700},
+#line 252 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str163,37800},
+#line 111 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str164, 16200},
+ {-1}, {-1},
+#line 33 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str167, 10*3600},
+ {-1},
+#line 30 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str169, 7*3600},
+#line 242 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str170,16200},
+#line 209 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str171,28800},
+#line 208 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str172,32400},
+#line 15 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str173, 0*3600},
+#line 232 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str174,14400},
+#line 267 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str175,25200},
+#line 266 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str176,25200},
+#line 226 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str177,43200},
+#line 43 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str178, -8*3600},
+#line 225 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str179,46800},
+ {-1},
+#line 285 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str181,-10800},
+#line 263 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str182,39600},
+#line 103 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str183, 9*3600},
+#line 247 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str184,39600},
+#line 105 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str185, 10*3600},
+#line 146 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str186, 12600},
+#line 132 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str187, 10800},
+#line 101 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str188, 8*3600},
+#line 42 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str189, -7*3600},
+#line 133 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str190, 36000},
+#line 41 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str191, -6*3600},
+#line 206 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str192,49500},
+#line 301 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str193,18000},
+#line 212 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str194,-14400},
+#line 194 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str195,-43200},
+ {-1},
+#line 262 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str197,28800},
+#line 182 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str198, 36000},
+#line 260 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str199,14400},
+#line 322 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str200,32400},
+#line 87 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str201, 2*3600},
+#line 289 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str202,39600},
+#line 155 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str203, 43200},
+#line 303 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str204,46800},
+#line 130 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str205, 28800},
+#line 302 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str206,50400},
+#line 88 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str207, -11*3600},
+ {-1},
+#line 145 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str209, 19800},
+ {-1},
+#line 317 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str211,-10800},
+#line 291 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str212,39600},
+ {-1},
+#line 199 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str214,-3600},
+#line 198 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str215,0},
+#line 296 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str216,-36000},
+#line 109 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str217, 12*3600},
+#line 131 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str218, -43200},
+#line 108 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str219,12*3600},
+#line 173 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str220, 32400},
+#line 128 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str221, 39600},
+ {-1},
+#line 286 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str223,21600},
+#line 116 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str224, -14400},
+#line 265 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str225,39600},
+ {-1},
+#line 14 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str227, 0*3600},
+#line 304 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str228,10800},
+#line 318 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str229,43200},
+#line 294 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str230,-10800},
+#line 23 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str231, -7*3600},
+#line 251 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str232,39600},
+ {-1},
+#line 55 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str234, -3*3600},
+#line 17 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str235, -4*3600},
+ {-1}, {-1},
+#line 280 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str238,18000},
+#line 191 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str239,21600},
+#line 323 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str240,28800},
+ {-1},
+#line 320 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str242,-7200},
+#line 63 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str243,-9*3600},
+#line 319 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str244,-3600},
+ {-1},
+#line 249 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str246,25200},
+#line 248 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str247,28800},
+#line 150 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str248, -7200},
+#line 21 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str249, -6*3600},
+#line 253 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str250,50400},
+#line 168 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str251, 28800},
+#line 19 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str252, -5*3600},
+#line 79 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str253, 1*3600},
+ {-1},
+#line 167 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str255, 25200},
+#line 44 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str256, -9*3600},
+ {-1},
+#line 174 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str258, 46800},
+#line 214 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str259,-36000},
+ {-1},
+#line 311 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str261,-14400},
+#line 122 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str262, 14400},
+#line 126 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str263, 3600},
+#line 31 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str264, 8*3600},
+#line 127 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str265, 3600},
+#line 156 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str266, -12600},
+#line 113 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str267, 10800},
+#line 292 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str268,14400},
+#line 115 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str269, 10800},
+#line 114 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str270, 14400},
+#line 219 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str271,36000},
+ {-1},
+#line 314 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str273,21600},
+#line 69 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str274,-10*3600},
+#line 154 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str275, 20700},
+#line 270 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str276,-39600},
+#line 228 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str277,-14400},
+ {-1},
+#line 227 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str279,-10800},
+#line 70 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str280,-10*3600},
+#line 240 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str281,10800},
+ {-1}, {-1},
+#line 300 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str284,32400},
+#line 178 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str285, 28800},
+#line 137 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str286, 7200},
+#line 152 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str287, 23400},
+#line 110 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str288,13*3600},
+#line 233 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str289,-10800},
+#line 310 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str290,18000},
+ {-1}, {-1},
+#line 158 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str293, 25200},
+#line 261 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str294,18000},
+#line 230 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str295,-21600},
+#line 264 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str296,43200},
+#line 216 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str297,-3600},
+#line 157 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str298, 28800},
+ {-1},
+#line 246 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str300,21600},
+#line 117 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str301, 34200},
+#line 160 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str302, -28800},
+ {-1},
+#line 120 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str304, -21600},
+ {-1},
+#line 159 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str306, -14400},
+#line 119 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str307, -3600},
+#line 231 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str308,-32400},
+#line 297 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str309,18000},
+#line 40 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str310, -5*3600},
+#line 140 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str311, 7200},
+#line 61 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str312,-8*3600},
+#line 307 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str313,28800},
+#line 306 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str314,32400},
+#line 287 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str315,14400},
+ {-1},
+#line 298 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str317,18000},
+ {-1},
+#line 169 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str319, 7200},
+ {-1}, {-1}, {-1}, {-1},
+#line 100 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str324, 8*3600},
+ {-1},
+#line 53 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str326, -(1*3600+1800)},
+#line 288 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str327,-10800},
+ {-1}, {-1},
+#line 290 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str330,14400},
+ {-1},
+#line 172 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str332, 36000},
+ {-1},
+#line 238 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str334,25200},
+#line 237 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str335,28800},
+ {-1}, {-1},
+#line 235 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str338,-14400},
+ {-1}, {-1}, {-1},
+#line 47 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str342, -12*3600},
+#line 64 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str343,-9*3600},
+#line 165 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str344, -14400},
+#line 144 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str345, -36000},
+ {-1},
+#line 309 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str347,-10800},
+ {-1},
+#line 308 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str349,-7200},
+#line 329 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str350,18000},
+#line 328 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str351,21600},
+#line 250 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str352,14400},
+#line 326 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str353,32400},
+#line 325 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str354,36000},
+ {-1}, {-1}, {-1},
+#line 66 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str358, -9*3600},
+#line 147 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str359, 7200},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+#line 170 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str365, 21600},
+ {-1},
+#line 183 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str367, 32400},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 321 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str375,25200},
+ {-1},
+#line 118 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str377, 36000},
+#line 234 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str378,43200},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 176 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str387, -25200},
+ {-1}, {-1}, {-1},
+#line 313 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str391,36000},
+#line 312 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str392,39600},
+ {-1}, {-1},
+#line 143 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str395, 7200},
+ {-1}, {-1},
+#line 171 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str398, 28800},
+#line 293 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str399,39600},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 121 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str408, -3600},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 299 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str417,46800},
+#line 166 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str418, -39600},
+ {-1}, {-1},
+#line 164 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str421, -18000},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+#line 315 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str427,39600},
+#line 72 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str428,-12*3600},
+ {-1}, {-1}, {-1},
+#line 139 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str432, 43200},
+ {-1}, {-1},
+#line 49 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str435, 0*3600},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 148 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str443, 32400},
+ {-1},
+#line 134 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str445, 7200},
+ {-1}, {-1}, {-1},
+#line 295 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str449,10800},
+ {-1}, {-1},
+#line 153 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str452, 21600},
+ {-1}, {-1},
+#line 305 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str455,43200},
+ {-1}, {-1},
+#line 179 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str458, 3600},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 138 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str466, 18000},
+ {-1},
+#line 177 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str468, 36000},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 327 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str476,36000},
+#line 175 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str477, -18000},
+ {-1}, {-1}, {-1}, {-1},
+#line 163 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str482, -10800},
+ {-1}, {-1},
+#line 65 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str485, -9*3600},
+#line 162 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str486, 10800},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+#line 236 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str492,28800},
+ {-1}, {-1}, {-1}, {-1},
+#line 161 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str497, 3600},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 180 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str540, 3600},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+#line 62 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str563, -8*3600},
+ {-1}, {-1},
+#line 107 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str566,12*3600},
+#line 142 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str567, 0},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 141 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str619, -10800}
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register unsigned int key = hash (str, len);
+
+ if (key <= MAX_HASH_VALUE)
+ {
+ register int o = wordlist[key].name;
+ if (o >= 0)
+ {
+ register const char *s = o + stringpool;
+
+ if ((((unsigned char)*str ^ (unsigned char)*s) & ~32) == 0 && !gperf_case_strncmp (str, s, len) && s[len] == '\0')
+ return &wordlist[key];
+ }
+ }
+ }
+ return 0;
+}
+#line 330 "zonetab.list"
+
diff --git a/ext/date/zonetab.list b/ext/date/zonetab.list
new file mode 100644
index 0000000000..63b6873447
--- /dev/null
+++ b/ext/date/zonetab.list
@@ -0,0 +1,330 @@
+%{
+#define GPERF_DOWNCASE 1
+#define GPERF_CASE_STRNCMP 1
+#define gperf_case_strncmp strncasecmp
+struct zone {
+ int name;
+ int offset;
+};
+static const struct zone *zonetab(register const char *str, register size_t len);
+%}
+
+struct zone;
+%%
+ut, 0*3600
+gmt, 0*3600
+est, -5*3600
+edt, -4*3600
+cst, -6*3600
+cdt, -5*3600
+mst, -7*3600
+mdt, -6*3600
+pst, -8*3600
+pdt, -7*3600
+a, 1*3600
+b, 2*3600
+c, 3*3600
+d, 4*3600
+e, 5*3600
+f, 6*3600
+g, 7*3600
+h, 8*3600
+i, 9*3600
+k, 10*3600
+l, 11*3600
+m, 12*3600
+n, -1*3600
+o, -2*3600
+p, -3*3600
+q, -4*3600
+r, -5*3600
+s, -6*3600
+t, -7*3600
+u, -8*3600
+v, -9*3600
+w, -10*3600
+x, -11*3600
+y, -12*3600
+z, 0*3600
+utc, 0*3600
+wet, 0*3600
+at, -2*3600
+brst,-2*3600
+ndt, -(1*3600+1800)
+art, -3*3600
+adt, -3*3600
+brt, -3*3600
+clst,-3*3600
+nst, -(2*3600+1800)
+ast, -4*3600
+clt, -4*3600
+akdt,-8*3600
+ydt, -8*3600
+akst,-9*3600
+hadt,-9*3600
+hdt, -9*3600
+yst, -9*3600
+ahst,-10*3600
+cat,2*3600
+hast,-10*3600
+hst,-10*3600
+nt, -11*3600
+idlw,-12*3600
+bst, 1*3600
+cet, 1*3600
+fwt, 1*3600
+met, 1*3600
+mewt, 1*3600
+mez, 1*3600
+swt, 1*3600
+wat, 1*3600
+west, 1*3600
+cest, 2*3600
+eet, 2*3600
+fst, 2*3600
+mest, 2*3600
+mesz, 2*3600
+sast, 2*3600
+sst, -11*3600
+bt, 3*3600
+eat, 3*3600
+eest, 3*3600
+msk, 3*3600
+msd, 4*3600
+zp4, 4*3600
+zp5, 5*3600
+ist, (5*3600+1800)
+zp6, 6*3600
+wast, 2*3600
+cct, (6*3600+1800)
+sgt, 8*3600
+wadt, 8*3600
+jst, 9*3600
+kst, 9*3600
+east,-6*3600
+gst, 10*3600
+eadt,11*3600
+idle,12*3600
+nzst,12*3600
+nzt, 12*3600
+nzdt,13*3600
+afghanistan, 16200
+alaskan, -32400
+arab, 10800
+arabian, 14400
+arabic, 10800
+atlantic, -14400
+aus central, 34200
+aus eastern, 36000
+azores, -3600
+canada central, -21600
+cape verde, -3600
+caucasus, 14400
+cen. australia, 34200
+central america, -21600
+central asia, 21600
+central europe, 3600
+central european, 3600
+central pacific, 39600
+central, -21600
+china, 28800
+dateline, -43200
+e. africa, 10800
+e. australia, 36000
+e. europe, 7200
+e. south america, -10800
+eastern, -18000
+egypt, 7200
+ekaterinburg, 18000
+fiji, 43200
+fle, 7200
+greenland, -10800
+greenwich, 0
+gtb, 7200
+hawaiian, -36000
+india, 19800
+iran, 12600
+jerusalem, 7200
+korea, 32400
+mexico, -21600
+mid-atlantic, -7200
+mountain, -25200
+myanmar, 23400
+n. central asia, 21600
+nepal, 20700
+new zealand, 43200
+newfoundland, -12600
+north asia east, 28800
+north asia, 25200
+pacific sa, -14400
+pacific, -28800
+romance, 3600
+russian, 10800
+sa eastern, -10800
+sa pacific, -18000
+sa western, -14400
+samoa, -39600
+se asia, 25200
+malay peninsula, 28800
+south africa, 7200
+sri lanka, 21600
+taipei, 28800
+tasmania, 36000
+tokyo, 32400
+tonga, 46800
+us eastern, -18000
+us mountain, -25200
+vladivostok, 36000
+w. australia, 28800
+w. central africa, 3600
+w. europe, 3600
+west asia, 18000
+west pacific, 36000
+yakutsk, 32400
+acdt,37800
+acst,34200
+act,-18000
+acwst,31500
+aedt,39600
+aest,36000
+aft,16200
+almt,21600
+anast,43200
+anat,43200
+aoe,-43200
+aqtt,18000
+awdt,32400
+awst,28800
+azost,0
+azot,-3600
+azst,18000
+azt,14400
+bnt,28800
+bot,-14400
+btt,21600
+cast,28800
+chadt,49500
+chast,45900
+chost,32400
+chot,28800
+chst,36000
+chut,36000
+cidst,-14400
+cist,-18000
+ckt,-36000
+cot,-18000
+cvt,-3600
+cxt,25200
+davt,25200
+ddut,36000
+easst,-18000
+ect,-18000
+egst,0
+egt,-3600
+fet,10800
+fjst,46800
+fjt,43200
+fkst,-10800
+fkt,-14400
+fnt,-7200
+galt,-21600
+gamt,-32400
+get,14400
+gft,-10800
+gilt,43200
+gyt,-14400
+hkt,28800
+hovst,28800
+hovt,25200
+ict,25200
+idt,10800
+iot,21600
+irdt,16200
+irkst,32400
+irkt,28800
+irst,12600
+kgt,21600
+kost,39600
+krast,28800
+krat,25200
+kuyt,14400
+lhdt,39600
+lhst,37800
+lint,50400
+magst,43200
+magt,39600
+mart,-30600
+mawt,18000
+mht,43200
+mmt,23400
+mut,14400
+mvt,18000
+myt,28800
+nct,39600
+nfdt,43200
+nft,39600
+novst,25200
+novt,25200
+npt,20700
+nrt,43200
+nut,-39600
+omsst,25200
+omst,21600
+orat,18000
+pet,-18000
+petst,43200
+pett,43200
+pgt,36000
+phot,46800
+pht,28800
+pkt,18000
+pmdt,-7200
+pmst,-10800
+pont,39600
+pwt,32400
+pyst,-10800
+qyzt,21600
+ret,14400
+rott,-10800
+sakt,39600
+samt,14400
+sbt,39600
+sct,14400
+sret,39600
+srt,-10800
+syot,10800
+taht,-36000
+tft,18000
+tjt,18000
+tkt,46800
+tlt,32400
+tmt,18000
+tost,50400
+tot,46800
+trt,10800
+tvt,43200
+ulast,32400
+ulat,28800
+uyst,-7200
+uyt,-10800
+uzt,18000
+vet,-14400
+vlast,39600
+vlat,36000
+vost,21600
+vut,39600
+wakt,43200
+warst,-10800
+wft,43200
+wgst,-3600
+wgt,-7200
+wib,25200
+wit,32400
+wita,28800
+wt,0
+yakst,36000
+yakt,32400
+yapt,36000
+yekst,21600
+yekt,18000
+%%
diff --git a/ext/dbm/.cvsignore b/ext/dbm/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/dbm/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
deleted file mode 100644
index 69b7a6e7a7..0000000000
--- a/ext/dbm/dbm.c
+++ /dev/null
@@ -1,816 +0,0 @@
-/************************************************
-
- dbm.c -
-
- $Author$
- $Date$
- created at: Mon Jan 24 15:59:52 JST 1994
-
- Copyright (C) 1995-2001 Yukihiro Matsumoto
-
-************************************************/
-
-#include "ruby.h"
-
-#ifdef HAVE_CDEFS_H
-# include <cdefs.h>
-#endif
-#ifdef HAVE_SYS_CDEFS_H
-# include <sys/cdefs.h>
-#endif
-#include DBM_HDR
-#include <fcntl.h>
-#include <errno.h>
-
-static VALUE rb_cDBM, rb_eDBMError;
-
-#define RUBY_DBM_RW_BIT 0x20000000
-
-struct dbmdata {
- int di_size;
- DBM *di_dbm;
-};
-
-static void
-closed_dbm()
-{
- rb_raise(rb_eDBMError, "closed DBM file");
-}
-
-#define GetDBM(obj, dbmp) {\
- Data_Get_Struct(obj, struct dbmdata, dbmp);\
- if (dbmp == 0) closed_dbm();\
- if (dbmp->di_dbm == 0) closed_dbm();\
-}
-
-#define GetDBM2(obj, data, dbm) {\
- GetDBM(obj, data);\
- (dbm) = dbmp->di_dbm;\
-}
-
-static void
-free_dbm(dbmp)
- struct dbmdata *dbmp;
-{
- if (dbmp) {
- if (dbmp->di_dbm) dbm_close(dbmp->di_dbm);
- free(dbmp);
- }
-}
-
-static VALUE
-fdbm_close(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
-
- GetDBM(obj, dbmp);
- dbm_close(dbmp->di_dbm);
- dbmp->di_dbm = 0;
-
- return Qnil;
-}
-
-static VALUE
-fdbm_closed(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
-
- Data_Get_Struct(obj, struct dbmdata, dbmp);
- if (dbmp == 0)
- return Qtrue;
- if (dbmp->di_dbm == 0)
- return Qtrue;
-
- return Qfalse;
-}
-
-static VALUE fdbm_alloc _((VALUE));
-static VALUE
-fdbm_alloc(klass)
- VALUE klass;
-{
- return Data_Wrap_Struct(klass, 0, free_dbm, 0);
-}
-
-static VALUE
-fdbm_initialize(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE file, vmode, vflags;
- DBM *dbm;
- struct dbmdata *dbmp;
- int mode, flags = 0;
-
- if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
- mode = 0666; /* default value */
- }
- else if (NIL_P(vmode)) {
- mode = -1; /* return nil if DB not exist */
- }
- else {
- mode = NUM2INT(vmode);
- }
-
- if (!NIL_P(vflags))
- flags = NUM2INT(vflags);
-
- SafeStringValue(file);
-
- if (flags & RUBY_DBM_RW_BIT) {
- flags &= ~RUBY_DBM_RW_BIT;
- dbm = dbm_open(RSTRING(file)->ptr, flags, mode);
- }
- else {
- dbm = 0;
- if (mode >= 0) {
- dbm = dbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode);
- }
- if (!dbm) {
- dbm = dbm_open(RSTRING(file)->ptr, O_RDWR, 0);
- }
- if (!dbm) {
- dbm = dbm_open(RSTRING(file)->ptr, O_RDONLY, 0);
- }
- }
-
- if (!dbm) {
- if (mode == -1) return Qnil;
- rb_sys_fail(RSTRING(file)->ptr);
- }
-
- dbmp = ALLOC(struct dbmdata);
- DATA_PTR(obj) = dbmp;
- dbmp->di_dbm = dbm;
- dbmp->di_size = -1;
-
- return obj;
-}
-
-static VALUE
-fdbm_s_open(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
-
- if (NIL_P(fdbm_initialize(argc, argv, obj))) {
- return Qnil;
- }
-
- if (rb_block_given_p()) {
- return rb_ensure(rb_yield, obj, fdbm_close, obj);
- }
-
- return obj;
-}
-
-static VALUE
-fdbm_fetch(obj, keystr, ifnone)
- VALUE obj, keystr, ifnone;
-{
- datum key, value;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- StringValue(keystr);
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- value = dbm_fetch(dbm, key);
- if (value.dptr == 0) {
- if (ifnone == Qnil && rb_block_given_p())
- return rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
- return ifnone;
- }
- return rb_tainted_str_new(value.dptr, value.dsize);
-}
-
-static VALUE
-fdbm_aref(obj, keystr)
- VALUE obj, keystr;
-{
- return fdbm_fetch(obj, keystr, Qnil);
-}
-
-static VALUE
-fdbm_fetch_m(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE keystr, valstr, ifnone;
-
- rb_scan_args(argc, argv, "11", &keystr, &ifnone);
- valstr = fdbm_fetch(obj, keystr, ifnone);
- if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
- rb_raise(rb_eIndexError, "key not found");
-
- return valstr;
-}
-
-static VALUE
-fdbm_index(obj, valstr)
- VALUE obj, valstr;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- StringValue(valstr);
- val.dptr = RSTRING(valstr)->ptr;
- val.dsize = RSTRING(valstr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- val = dbm_fetch(dbm, key);
- if (val.dsize == RSTRING(valstr)->len &&
- memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0) {
- return rb_tainted_str_new(key.dptr, key.dsize);
- }
- }
- return Qnil;
-}
-
-static VALUE
-fdbm_indexes(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE new;
- int i;
-
- new = rb_ary_new2(argc);
- for (i=0; i<argc; i++) {
- rb_ary_push(new, fdbm_fetch(obj, argv[i], Qnil));
- }
-
- return new;
-}
-
-static VALUE
-fdbm_select(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE new = rb_ary_new2(argc);
- int i;
-
- if (rb_block_given_p()) {
- datum key, val;
- DBM *dbm;
- struct dbmdata *dbmp;
-
- if (argc > 0) {
- rb_raise(rb_eArgError, "wrong number arguments(%d for 0)", argc);
- }
- GetDBM2(obj, dbmp, dbm);
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- VALUE assoc, v;
- val = dbm_fetch(dbm, key);
- assoc = rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
- rb_tainted_str_new(val.dptr, val.dsize));
- v = rb_yield(assoc);
- if (RTEST(v)) {
- rb_ary_push(new, assoc);
- }
- GetDBM2(obj, dbmp, dbm);
- }
- }
- else {
- rb_warn("DBM#select(index..) is deprecated; use DBM#values_at");
-
- for (i=0; i<argc; i++) {
- rb_ary_push(new, fdbm_fetch(obj, argv[i], Qnil));
- }
- }
-
- return new;
-}
-
-static VALUE
-fdbm_values_at(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE new = rb_ary_new2(argc);
- int i;
-
- for (i=0; i<argc; i++) {
- rb_ary_push(new, fdbm_fetch(obj, argv[i], Qnil));
- }
-
- return new;
-}
-
-static void
-fdbm_modify(obj)
- VALUE obj;
-{
- rb_secure(4);
- if (OBJ_FROZEN(obj)) rb_error_frozen("DBM");
-}
-
-static VALUE
-fdbm_delete(obj, keystr)
- VALUE obj, keystr;
-{
- datum key, value;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE valstr;
-
- fdbm_modify(obj);
- StringValue(keystr);
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- value = dbm_fetch(dbm, key);
- if (value.dptr == 0) {
- if (rb_block_given_p()) return rb_yield(keystr);
- return Qnil;
- }
-
- /* need to save value before dbm_delete() */
- valstr = rb_tainted_str_new(value.dptr, value.dsize);
-
- if (dbm_delete(dbm, key)) {
- dbmp->di_size = -1;
- rb_raise(rb_eDBMError, "dbm_delete failed");
- }
- else if (dbmp->di_size >= 0) {
- dbmp->di_size--;
- }
- return valstr;
-}
-
-static VALUE
-fdbm_shift(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE keystr, valstr;
-
- fdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- dbmp->di_size = -1;
-
- key = dbm_firstkey(dbm);
- if (!key.dptr) return Qnil;
- val = dbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
- dbm_delete(dbm, key);
-
- return rb_assoc_new(keystr, valstr);
-}
-
-static VALUE
-fdbm_delete_if(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE keystr, valstr;
- VALUE ret, ary = rb_ary_new();
- int i, status = 0, n;
-
- fdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- n = dbmp->di_size;
- dbmp->di_size = -1;
-
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- val = dbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
- ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
- if (status != 0) break;
- if (RTEST(ret)) rb_ary_push(ary, keystr);
- GetDBM2(obj, dbmp, dbm);
- }
-
- for (i = 0; i < RARRAY(ary)->len; i++) {
- keystr = RARRAY(ary)->ptr[i];
- StringValue(keystr);
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
- if (dbm_delete(dbm, key)) {
- rb_raise(rb_eDBMError, "dbm_delete failed");
- }
- }
- if (status) rb_jump_tag(status);
- if (n > 0) dbmp->di_size = n - RARRAY(ary)->len;
-
- return obj;
-}
-
-static VALUE
-fdbm_clear(obj)
- VALUE obj;
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- fdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- dbmp->di_size = -1;
- while (key = dbm_firstkey(dbm), key.dptr) {
- if (dbm_delete(dbm, key)) {
- rb_raise(rb_eDBMError, "dbm_delete failed");
- }
- }
- dbmp->di_size = 0;
-
- return obj;
-}
-
-static VALUE
-fdbm_invert(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE keystr, valstr;
- VALUE hash = rb_hash_new();
-
- GetDBM2(obj, dbmp, dbm);
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- val = dbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
- rb_hash_aset(hash, valstr, keystr);
- }
- return hash;
-}
-
-static VALUE each_pair _((VALUE));
-
-static VALUE
-each_pair(obj)
- VALUE obj;
-{
- return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
-}
-
-static VALUE fdbm_store _((VALUE,VALUE,VALUE));
-
-static VALUE
-update_i(pair, dbm)
- VALUE pair, dbm;
-{
- Check_Type(pair, T_ARRAY);
- if (RARRAY(pair)->len < 2) {
- rb_raise(rb_eArgError, "pair must be [key, value]");
- }
- fdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]);
- return Qnil;
-}
-
-static VALUE
-fdbm_update(obj, other)
- VALUE obj, other;
-{
- rb_iterate(each_pair, other, update_i, obj);
- return obj;
-}
-
-static VALUE
-fdbm_replace(obj, other)
- VALUE obj, other;
-{
- fdbm_clear(obj);
- rb_iterate(each_pair, other, update_i, obj);
- return obj;
-}
-
-static VALUE
-fdbm_store(obj, keystr, valstr)
- VALUE obj, keystr, valstr;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- fdbm_modify(obj);
- keystr = rb_obj_as_string(keystr);
- valstr = rb_obj_as_string(valstr);
-
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
-
- val.dptr = RSTRING(valstr)->ptr;
- val.dsize = RSTRING(valstr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- dbmp->di_size = -1;
- if (dbm_store(dbm, key, val, DBM_REPLACE)) {
-#ifdef HAVE_DBM_CLEARERR
- dbm_clearerr(dbm);
-#endif
- if (errno == EPERM) rb_sys_fail(0);
- rb_raise(rb_eDBMError, "dbm_store failed");
- }
-
- return valstr;
-}
-
-static VALUE
-fdbm_length(obj)
- VALUE obj;
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
- int i = 0;
-
- GetDBM2(obj, dbmp, dbm);
- if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
-
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- i++;
- }
- dbmp->di_size = i;
-
- return INT2FIX(i);
-}
-
-static VALUE
-fdbm_empty_p(obj)
- VALUE obj;
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
- int i = 0;
-
- GetDBM2(obj, dbmp, dbm);
- if (dbmp->di_size < 0) {
- dbm = dbmp->di_dbm;
-
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- i++;
- }
- }
- else {
- i = dbmp->di_size;
- }
- if (i == 0) return Qtrue;
- return Qfalse;
-}
-
-static VALUE
-fdbm_each_value(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- GetDBM2(obj, dbmp, dbm);
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- val = dbm_fetch(dbm, key);
- rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
- GetDBM2(obj, dbmp, dbm);
- }
- return obj;
-}
-
-static VALUE
-fdbm_each_key(obj)
- VALUE obj;
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- GetDBM2(obj, dbmp, dbm);
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
- GetDBM2(obj, dbmp, dbm);
- }
- return obj;
-}
-
-static VALUE
-fdbm_each_pair(obj)
- VALUE obj;
-{
- datum key, val;
- DBM *dbm;
- struct dbmdata *dbmp;
- VALUE keystr, valstr;
-
- GetDBM2(obj, dbmp, dbm);
-
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- val = dbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
- rb_yield(rb_assoc_new(keystr, valstr));
- GetDBM2(obj, dbmp, dbm);
- }
-
- return obj;
-}
-
-static VALUE
-fdbm_keys(obj)
- VALUE obj;
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE ary;
-
- GetDBM2(obj, dbmp, dbm);
-
- ary = rb_ary_new();
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
- }
-
- return ary;
-}
-
-static VALUE
-fdbm_values(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE ary;
-
- GetDBM2(obj, dbmp, dbm);
- ary = rb_ary_new();
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- val = dbm_fetch(dbm, key);
- rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
- }
-
- return ary;
-}
-
-static VALUE
-fdbm_has_key(obj, keystr)
- VALUE obj, keystr;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- StringValue(keystr);
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- val = dbm_fetch(dbm, key);
- if (val.dptr) return Qtrue;
- return Qfalse;
-}
-
-static VALUE
-fdbm_has_value(obj, valstr)
- VALUE obj, valstr;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- StringValue(valstr);
- val.dptr = RSTRING(valstr)->ptr;
- val.dsize = RSTRING(valstr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- val = dbm_fetch(dbm, key);
- if (val.dsize == RSTRING(valstr)->len &&
- memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
- return Qtrue;
- }
- return Qfalse;
-}
-
-static VALUE
-fdbm_to_a(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE ary;
-
- GetDBM2(obj, dbmp, dbm);
- ary = rb_ary_new();
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- val = dbm_fetch(dbm, key);
- rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
- rb_tainted_str_new(val.dptr, val.dsize)));
- }
-
- return ary;
-}
-
-static VALUE
-fdbm_to_hash(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE hash;
-
- GetDBM2(obj, dbmp, dbm);
- hash = rb_hash_new();
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- val = dbm_fetch(dbm, key);
- rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize),
- rb_tainted_str_new(val.dptr, val.dsize));
- }
-
- return hash;
-}
-
-static VALUE
-fdbm_reject(obj)
- VALUE obj;
-{
- return rb_hash_delete_if(fdbm_to_hash(obj));
-}
-
-void
-Init_dbm()
-{
- rb_cDBM = rb_define_class("DBM", rb_cObject);
- rb_eDBMError = rb_define_class("DBMError", rb_eStandardError);
- rb_include_module(rb_cDBM, rb_mEnumerable);
-
- rb_define_alloc_func(rb_cDBM, fdbm_alloc);
- rb_define_singleton_method(rb_cDBM, "open", fdbm_s_open, -1);
-
- rb_define_method(rb_cDBM, "initialize", fdbm_initialize, -1);
- rb_define_method(rb_cDBM, "close", fdbm_close, 0);
- rb_define_method(rb_cDBM, "closed?", fdbm_closed, 0);
- rb_define_method(rb_cDBM, "[]", fdbm_aref, 1);
- rb_define_method(rb_cDBM, "fetch", fdbm_fetch_m, -1);
- rb_define_method(rb_cDBM, "[]=", fdbm_store, 2);
- rb_define_method(rb_cDBM, "store", fdbm_store, 2);
- rb_define_method(rb_cDBM, "index", fdbm_index, 1);
- rb_define_method(rb_cDBM, "indexes", fdbm_indexes, -1);
- rb_define_method(rb_cDBM, "indices", fdbm_indexes, -1);
- rb_define_method(rb_cDBM, "select", fdbm_select, -1);
- rb_define_method(rb_cDBM, "values_at", fdbm_values_at, -1);
- rb_define_method(rb_cDBM, "length", fdbm_length, 0);
- rb_define_method(rb_cDBM, "size", fdbm_length, 0);
- rb_define_method(rb_cDBM, "empty?", fdbm_empty_p, 0);
- rb_define_method(rb_cDBM, "each", fdbm_each_pair, 0);
- rb_define_method(rb_cDBM, "each_value", fdbm_each_value, 0);
- rb_define_method(rb_cDBM, "each_key", fdbm_each_key, 0);
- rb_define_method(rb_cDBM, "each_pair", fdbm_each_pair, 0);
- rb_define_method(rb_cDBM, "keys", fdbm_keys, 0);
- rb_define_method(rb_cDBM, "values", fdbm_values, 0);
- rb_define_method(rb_cDBM, "shift", fdbm_shift, 0);
- rb_define_method(rb_cDBM, "delete", fdbm_delete, 1);
- rb_define_method(rb_cDBM, "delete_if", fdbm_delete_if, 0);
- rb_define_method(rb_cDBM, "reject!", fdbm_delete_if, 0);
- rb_define_method(rb_cDBM, "reject", fdbm_reject, 0);
- rb_define_method(rb_cDBM, "clear", fdbm_clear, 0);
- rb_define_method(rb_cDBM,"invert", fdbm_invert, 0);
- rb_define_method(rb_cDBM,"update", fdbm_update, 1);
- rb_define_method(rb_cDBM,"replace", fdbm_replace, 1);
-
- rb_define_method(rb_cDBM, "include?", fdbm_has_key, 1);
- rb_define_method(rb_cDBM, "has_key?", fdbm_has_key, 1);
- rb_define_method(rb_cDBM, "member?", fdbm_has_key, 1);
- rb_define_method(rb_cDBM, "has_value?", fdbm_has_value, 1);
- rb_define_method(rb_cDBM, "key?", fdbm_has_key, 1);
- rb_define_method(rb_cDBM, "value?", fdbm_has_value, 1);
-
- rb_define_method(rb_cDBM, "to_a", fdbm_to_a, 0);
- rb_define_method(rb_cDBM, "to_hash", fdbm_to_hash, 0);
-
- /* flags for dbm_open() */
- rb_define_const(rb_cDBM, "READER", INT2FIX(O_RDONLY|RUBY_DBM_RW_BIT));
- rb_define_const(rb_cDBM, "WRITER", INT2FIX(O_RDWR|RUBY_DBM_RW_BIT));
- rb_define_const(rb_cDBM, "WRCREAT", INT2FIX(O_RDWR|O_CREAT|RUBY_DBM_RW_BIT));
- rb_define_const(rb_cDBM, "NEWDB", INT2FIX(O_RDWR|O_CREAT|O_TRUNC|RUBY_DBM_RW_BIT));
-
-#ifdef DB_VERSION_STRING
- rb_define_const(rb_cDBM, "VERSION", rb_str_new2(DB_VERSION_STRING));
-#endif
-}
diff --git a/ext/dbm/depend b/ext/dbm/depend
deleted file mode 100644
index 5fae80b096..0000000000
--- a/ext/dbm/depend
+++ /dev/null
@@ -1 +0,0 @@
-dbm.o: dbm.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/dbm/extconf.rb b/ext/dbm/extconf.rb
deleted file mode 100644
index 52ec688952..0000000000
--- a/ext/dbm/extconf.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-require 'mkmf'
-
-dir_config("dbm")
-
-dblib = with_config("dbm-type", nil)
-
-$dbm_conf_headers = {
- "db" => ["db.h"],
- "db1" => ["db1/ndbm.h", "db1.h", "ndbm.h"],
- "db2" => ["db2/db.h", "db2.h", "db.h"],
- "dbm" => ["ndbm.h"],
- "gdbm" => ["gdbm-ndbm.h", "ndbm.h"],
- "gdbm_compat" => ["gdbm-ndbm.h", "ndbm.h"],
- "qdbm" => ["relic.h"],
-}
-
-def db_check(db)
- $dbm_conf_db_prefix = ""
- $dbm_conf_have_gdbm = false
- hsearch = ""
-
- case db
- when /^db2?$/
- $dbm_conf_db_prefix = "__db_n"
- hsearch = "-DDB_DBM_HSEARCH "
- when "gdbm"
- $dbm_conf_have_gdbm = true
- when "gdbm_compat"
- $dbm_conf_have_gdbm = true
- have_library("gdbm") or return false
- end
-
- if have_library(db, db_prefix("dbm_open")) || have_func(db_prefix("dbm_open"))
- for hdr in $dbm_conf_headers.fetch(db, ["ndbm.h"])
- if have_header(hdr.dup) and have_type("DBM", hdr.dup, hsearch)
- $defs << hsearch << '-DDBM_HDR="<'+hdr+'>"'
- return true
- end
- end
- end
- return false
-end
-
-def db_prefix(func)
- $dbm_conf_db_prefix+func
-end
-
-if dblib
- dbm_hdr = db_check(dblib)
-else
- dbm_hdr = %w(db db2 db1 dbm gdbm gdbm_compat qdbm).any? do |dblib|
- db_check(dblib)
- end
-end
-
-have_header("cdefs.h")
-have_header("sys/cdefs.h")
-if dbm_hdr and have_func(db_prefix("dbm_open"))
- have_func(db_prefix("dbm_clearerr")) unless $dbm_conf_have_gdbm
- create_makefile("dbm")
-end
diff --git a/ext/digest/.cvsignore b/ext/digest/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/digest/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/digest/.document b/ext/digest/.document
new file mode 100644
index 0000000000..beab275b5a
--- /dev/null
+++ b/ext/digest/.document
@@ -0,0 +1,3 @@
+digest.c
+bubblebabble/bubblebabble.c
+*/*init.c
diff --git a/ext/digest/bubblebabble/bubblebabble.c b/ext/digest/bubblebabble/bubblebabble.c
new file mode 100644
index 0000000000..dac603c0d7
--- /dev/null
+++ b/ext/digest/bubblebabble/bubblebabble.c
@@ -0,0 +1,146 @@
+/************************************************
+
+ bubblebabble.c - BubbleBabble encoding support
+
+ $Author$
+ created at: Fri Oct 13 18:31:42 JST 2006
+
+ Copyright (C) 2006 Akinori MUSHA
+
+ $Id$
+
+************************************************/
+
+#include <ruby/ruby.h>
+#include "../digest.h"
+
+static ID id_digest;
+
+static VALUE
+bubblebabble_str_new(VALUE str_digest)
+{
+ char *digest;
+ size_t digest_len;
+ VALUE str;
+ char *p;
+ size_t i, j, seed = 1;
+ static const char vowels[] = {
+ 'a', 'e', 'i', 'o', 'u', 'y'
+ };
+ static const char consonants[] = {
+ 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 'n',
+ 'p', 'r', 's', 't', 'v', 'z', 'x'
+ };
+
+ StringValue(str_digest);
+ digest = RSTRING_PTR(str_digest);
+ digest_len = RSTRING_LEN(str_digest);
+
+ if ((LONG_MAX - 2) / 3 < (digest_len | 1)) {
+ rb_raise(rb_eRuntimeError, "digest string too long");
+ }
+
+ str = rb_str_new(0, (digest_len | 1) * 3 + 2);
+ p = RSTRING_PTR(str);
+
+ i = j = 0;
+ p[j++] = 'x';
+
+ for (;;) {
+ unsigned char byte1, byte2;
+
+ if (i >= digest_len) {
+ p[j++] = vowels[seed % 6];
+ p[j++] = consonants[16];
+ p[j++] = vowels[seed / 6];
+ break;
+ }
+
+ byte1 = digest[i++];
+ p[j++] = vowels[(((byte1 >> 6) & 3) + seed) % 6];
+ p[j++] = consonants[(byte1 >> 2) & 15];
+ p[j++] = vowels[((byte1 & 3) + (seed / 6)) % 6];
+
+ if (i >= digest_len) {
+ break;
+ }
+
+ byte2 = digest[i++];
+ p[j++] = consonants[(byte2 >> 4) & 15];
+ p[j++] = '-';
+ p[j++] = consonants[byte2 & 15];
+
+ seed = (seed * 5 + byte1 * 7 + byte2) % 36;
+ }
+
+ p[j] = 'x';
+
+ return str;
+}
+
+/* Document-method: Digest::bubblebabble
+ *
+ * call-seq:
+ * Digest.bubblebabble(string) -> bubblebabble_string
+ *
+ * Returns a BubbleBabble encoded version of a given _string_.
+ */
+static VALUE
+rb_digest_s_bubblebabble(VALUE klass, VALUE str)
+{
+ return bubblebabble_str_new(str);
+}
+
+/* Document-method: Digest::Class::bubblebabble
+ *
+ * call-seq:
+ * Digest::Class.bubblebabble(string, ...) -> hash_string
+ *
+ * Returns the BubbleBabble encoded hash value of a given _string_.
+ */
+static VALUE
+rb_digest_class_s_bubblebabble(int argc, VALUE *argv, VALUE klass)
+{
+ return bubblebabble_str_new(rb_funcallv(klass, id_digest, argc, argv));
+}
+
+/* Document-method: Digest::Instance#bubblebabble
+ *
+ * call-seq:
+ * digest_obj.bubblebabble -> hash_string
+ *
+ * Returns the resulting hash value in a Bubblebabble encoded form.
+ */
+static VALUE
+rb_digest_instance_bubblebabble(VALUE self)
+{
+ return bubblebabble_str_new(rb_funcall(self, id_digest, 0));
+}
+
+/*
+ * This module adds some methods to Digest classes to perform
+ * BubbleBabble encoding.
+ */
+void
+Init_bubblebabble(void)
+{
+#undef rb_intern
+ VALUE rb_mDigest, rb_mDigest_Instance, rb_cDigest_Class;
+
+ rb_require("digest");
+
+#if 0
+ rb_mDigest = rb_define_module("Digest");
+ rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance");
+ rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject);
+#endif
+ rb_mDigest = rb_digest_namespace();
+ rb_mDigest_Instance = rb_const_get(rb_mDigest, rb_intern_const("Instance"));
+ rb_cDigest_Class = rb_const_get(rb_mDigest, rb_intern_const("Class"));
+
+ rb_define_module_function(rb_mDigest, "bubblebabble", rb_digest_s_bubblebabble, 1);
+ rb_define_singleton_method(rb_cDigest_Class, "bubblebabble", rb_digest_class_s_bubblebabble, -1);
+ rb_define_method(rb_mDigest_Instance, "bubblebabble", rb_digest_instance_bubblebabble, 0);
+
+ id_digest = rb_intern("digest");
+}
diff --git a/ext/digest/bubblebabble/depend b/ext/digest/bubblebabble/depend
new file mode 100644
index 0000000000..02d88e960c
--- /dev/null
+++ b/ext/digest/bubblebabble/depend
@@ -0,0 +1,164 @@
+# AUTOGENERATED DEPENDENCIES START
+bubblebabble.o: $(RUBY_EXTCONF_H)
+bubblebabble.o: $(arch_hdrdir)/ruby/config.h
+bubblebabble.o: $(hdrdir)/ruby.h
+bubblebabble.o: $(hdrdir)/ruby/assert.h
+bubblebabble.o: $(hdrdir)/ruby/backward.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/assume.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/attributes.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/bool.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/limits.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/long_long.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bubblebabble.o: $(hdrdir)/ruby/defines.h
+bubblebabble.o: $(hdrdir)/ruby/intern.h
+bubblebabble.o: $(hdrdir)/ruby/internal/abi.h
+bubblebabble.o: $(hdrdir)/ruby/internal/anyargs.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/assume.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/cold.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/const.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/error.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/format.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/pure.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/warning.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bubblebabble.o: $(hdrdir)/ruby/internal/cast.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_since.h
+bubblebabble.o: $(hdrdir)/ruby/internal/config.h
+bubblebabble.o: $(hdrdir)/ruby/internal/constant_p.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rarray.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rclass.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rdata.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rfile.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rhash.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/robject.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rstring.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bubblebabble.o: $(hdrdir)/ruby/internal/ctype.h
+bubblebabble.o: $(hdrdir)/ruby/internal/dllexport.h
+bubblebabble.o: $(hdrdir)/ruby/internal/dosish.h
+bubblebabble.o: $(hdrdir)/ruby/internal/error.h
+bubblebabble.o: $(hdrdir)/ruby/internal/eval.h
+bubblebabble.o: $(hdrdir)/ruby/internal/event.h
+bubblebabble.o: $(hdrdir)/ruby/internal/fl_type.h
+bubblebabble.o: $(hdrdir)/ruby/internal/gc.h
+bubblebabble.o: $(hdrdir)/ruby/internal/glob.h
+bubblebabble.o: $(hdrdir)/ruby/internal/globals.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/attribute.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/builtin.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/extension.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/feature.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/warning.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/array.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/class.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/compar.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/complex.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/cont.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/dir.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/enum.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/error.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/eval.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/file.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/hash.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/io.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/load.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/object.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/parse.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/proc.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/process.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/random.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/range.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/rational.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/re.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/select.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/set.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/signal.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/string.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/struct.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/thread.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/time.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/variable.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/vm.h
+bubblebabble.o: $(hdrdir)/ruby/internal/interpreter.h
+bubblebabble.o: $(hdrdir)/ruby/internal/iterator.h
+bubblebabble.o: $(hdrdir)/ruby/internal/memory.h
+bubblebabble.o: $(hdrdir)/ruby/internal/method.h
+bubblebabble.o: $(hdrdir)/ruby/internal/module.h
+bubblebabble.o: $(hdrdir)/ruby/internal/newobj.h
+bubblebabble.o: $(hdrdir)/ruby/internal/scan_args.h
+bubblebabble.o: $(hdrdir)/ruby/internal/special_consts.h
+bubblebabble.o: $(hdrdir)/ruby/internal/static_assert.h
+bubblebabble.o: $(hdrdir)/ruby/internal/stdalign.h
+bubblebabble.o: $(hdrdir)/ruby/internal/stdbool.h
+bubblebabble.o: $(hdrdir)/ruby/internal/stdckdint.h
+bubblebabble.o: $(hdrdir)/ruby/internal/symbol.h
+bubblebabble.o: $(hdrdir)/ruby/internal/value.h
+bubblebabble.o: $(hdrdir)/ruby/internal/value_type.h
+bubblebabble.o: $(hdrdir)/ruby/internal/variable.h
+bubblebabble.o: $(hdrdir)/ruby/internal/warning_push.h
+bubblebabble.o: $(hdrdir)/ruby/internal/xmalloc.h
+bubblebabble.o: $(hdrdir)/ruby/missing.h
+bubblebabble.o: $(hdrdir)/ruby/ruby.h
+bubblebabble.o: $(hdrdir)/ruby/st.h
+bubblebabble.o: $(hdrdir)/ruby/subst.h
+bubblebabble.o: $(srcdir)/../digest.h
+bubblebabble.o: bubblebabble.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/bubblebabble/extconf.rb b/ext/digest/bubblebabble/extconf.rb
new file mode 100644
index 0000000000..8fb001c61d
--- /dev/null
+++ b/ext/digest/bubblebabble/extconf.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: false
+require 'mkmf'
+
+create_makefile('digest/bubblebabble')
diff --git a/ext/digest/defs.h b/ext/digest/defs.h
index 5cfc77dd24..9b11f4eca9 100644
--- a/ext/digest/defs.h
+++ b/ext/digest/defs.h
@@ -16,22 +16,26 @@
# define __END_DECLS
#endif
-#if defined(HAVE_INTTYPES_H)
-# include <inttypes.h>
-#elif !defined __CYGWIN__ || !defined __uint8_t_defined
- typedef unsigned char uint8_t;
- typedef unsigned int uint32_t;
-# if SIZEOF_LONG == 8
- typedef unsigned long uint64_t;
-# elif defined(__GNUC__)
- typedef unsigned long long uint64_t;
-# elif defined(_MSC_VER)
- typedef unsigned _int64 uint64_t;
-# elif defined(__BORLANDC__)
- typedef unsigned __int64 uint64_t;
-# else
-# define NO_UINT64_T
-# endif
+#define RB_DIGEST_DIAGNOSTIC(compiler, op, flag) _Pragma(STRINGIZE(compiler diagnostic op flag))
+#ifdef RBIMPL_WARNING_IGNORED
+# define RB_DIGEST_WARNING_IGNORED(flag) RBIMPL_WARNING_IGNORED(flag)
+# define RB_DIGEST_WARNING_PUSH() RBIMPL_WARNING_PUSH()
+# define RB_DIGEST_WARNING_POP() RBIMPL_WARNING_POP()
+#elif defined(__clang__)
+# define RB_DIGEST_WARNING_IGNORED(flag) RB_DIGEST_DIAGNOSTIC(clang, ignored, #flag)
+# define RB_DIGEST_WARNING_PUSH() _Pragma("clang diagnostic push")
+# define RB_DIGEST_WARNING_POP() _Pragma("clang diagnostic pop")
+#else /* __GNUC__ */
+# define RB_DIGEST_WARNING_IGNORED(flag) RB_DIGEST_DIAGNOSTIC(GCC, ignored, #flag)
+# define RB_DIGEST_WARNING_PUSH() _Pragma("GCC diagnostic push")
+# define RB_DIGEST_WARNING_POP() _Pragma("GCC diagnostic pop")
+#endif
+#ifdef RBIMPL_HAS_WARNING
+# define RB_DIGEST_HAS_WARNING(_) RBIMPL_HAS_WARNING(_)
+#elif defined(__has_warning)
+# define RB_DIGEST_HAS_WARNING(_) __has_warning(_)
+#else
+# define RB_DIGEST_HAS_WARNING(_) 0
#endif
#endif /* DEFS_H */
diff --git a/ext/digest/depend b/ext/digest/depend
index 43601a208f..3eabb1d1d6 100644
--- a/ext/digest/depend
+++ b/ext/digest/depend
@@ -1,2 +1,164 @@
-digest.o: digest.c digest.h $(hdrdir)/ruby.h $(topdir)/config.h \
- $(hdrdir)/defines.h $(hdrdir)/intern.h
+# AUTOGENERATED DEPENDENCIES START
+digest.o: $(RUBY_EXTCONF_H)
+digest.o: $(arch_hdrdir)/ruby/config.h
+digest.o: $(hdrdir)/ruby.h
+digest.o: $(hdrdir)/ruby/assert.h
+digest.o: $(hdrdir)/ruby/backward.h
+digest.o: $(hdrdir)/ruby/backward/2/assume.h
+digest.o: $(hdrdir)/ruby/backward/2/attributes.h
+digest.o: $(hdrdir)/ruby/backward/2/bool.h
+digest.o: $(hdrdir)/ruby/backward/2/inttypes.h
+digest.o: $(hdrdir)/ruby/backward/2/limits.h
+digest.o: $(hdrdir)/ruby/backward/2/long_long.h
+digest.o: $(hdrdir)/ruby/backward/2/stdalign.h
+digest.o: $(hdrdir)/ruby/backward/2/stdarg.h
+digest.o: $(hdrdir)/ruby/defines.h
+digest.o: $(hdrdir)/ruby/intern.h
+digest.o: $(hdrdir)/ruby/internal/abi.h
+digest.o: $(hdrdir)/ruby/internal/anyargs.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+digest.o: $(hdrdir)/ruby/internal/assume.h
+digest.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+digest.o: $(hdrdir)/ruby/internal/attr/artificial.h
+digest.o: $(hdrdir)/ruby/internal/attr/cold.h
+digest.o: $(hdrdir)/ruby/internal/attr/const.h
+digest.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+digest.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+digest.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+digest.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+digest.o: $(hdrdir)/ruby/internal/attr/error.h
+digest.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+digest.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+digest.o: $(hdrdir)/ruby/internal/attr/format.h
+digest.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+digest.o: $(hdrdir)/ruby/internal/attr/noalias.h
+digest.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+digest.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+digest.o: $(hdrdir)/ruby/internal/attr/noinline.h
+digest.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+digest.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+digest.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+digest.o: $(hdrdir)/ruby/internal/attr/pure.h
+digest.o: $(hdrdir)/ruby/internal/attr/restrict.h
+digest.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+digest.o: $(hdrdir)/ruby/internal/attr/warning.h
+digest.o: $(hdrdir)/ruby/internal/attr/weakref.h
+digest.o: $(hdrdir)/ruby/internal/cast.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+digest.o: $(hdrdir)/ruby/internal/compiler_since.h
+digest.o: $(hdrdir)/ruby/internal/config.h
+digest.o: $(hdrdir)/ruby/internal/constant_p.h
+digest.o: $(hdrdir)/ruby/internal/core.h
+digest.o: $(hdrdir)/ruby/internal/core/rarray.h
+digest.o: $(hdrdir)/ruby/internal/core/rbasic.h
+digest.o: $(hdrdir)/ruby/internal/core/rbignum.h
+digest.o: $(hdrdir)/ruby/internal/core/rclass.h
+digest.o: $(hdrdir)/ruby/internal/core/rdata.h
+digest.o: $(hdrdir)/ruby/internal/core/rfile.h
+digest.o: $(hdrdir)/ruby/internal/core/rhash.h
+digest.o: $(hdrdir)/ruby/internal/core/robject.h
+digest.o: $(hdrdir)/ruby/internal/core/rregexp.h
+digest.o: $(hdrdir)/ruby/internal/core/rstring.h
+digest.o: $(hdrdir)/ruby/internal/core/rstruct.h
+digest.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+digest.o: $(hdrdir)/ruby/internal/ctype.h
+digest.o: $(hdrdir)/ruby/internal/dllexport.h
+digest.o: $(hdrdir)/ruby/internal/dosish.h
+digest.o: $(hdrdir)/ruby/internal/error.h
+digest.o: $(hdrdir)/ruby/internal/eval.h
+digest.o: $(hdrdir)/ruby/internal/event.h
+digest.o: $(hdrdir)/ruby/internal/fl_type.h
+digest.o: $(hdrdir)/ruby/internal/gc.h
+digest.o: $(hdrdir)/ruby/internal/glob.h
+digest.o: $(hdrdir)/ruby/internal/globals.h
+digest.o: $(hdrdir)/ruby/internal/has/attribute.h
+digest.o: $(hdrdir)/ruby/internal/has/builtin.h
+digest.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+digest.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+digest.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+digest.o: $(hdrdir)/ruby/internal/has/extension.h
+digest.o: $(hdrdir)/ruby/internal/has/feature.h
+digest.o: $(hdrdir)/ruby/internal/has/warning.h
+digest.o: $(hdrdir)/ruby/internal/intern/array.h
+digest.o: $(hdrdir)/ruby/internal/intern/bignum.h
+digest.o: $(hdrdir)/ruby/internal/intern/class.h
+digest.o: $(hdrdir)/ruby/internal/intern/compar.h
+digest.o: $(hdrdir)/ruby/internal/intern/complex.h
+digest.o: $(hdrdir)/ruby/internal/intern/cont.h
+digest.o: $(hdrdir)/ruby/internal/intern/dir.h
+digest.o: $(hdrdir)/ruby/internal/intern/enum.h
+digest.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+digest.o: $(hdrdir)/ruby/internal/intern/error.h
+digest.o: $(hdrdir)/ruby/internal/intern/eval.h
+digest.o: $(hdrdir)/ruby/internal/intern/file.h
+digest.o: $(hdrdir)/ruby/internal/intern/hash.h
+digest.o: $(hdrdir)/ruby/internal/intern/io.h
+digest.o: $(hdrdir)/ruby/internal/intern/load.h
+digest.o: $(hdrdir)/ruby/internal/intern/marshal.h
+digest.o: $(hdrdir)/ruby/internal/intern/numeric.h
+digest.o: $(hdrdir)/ruby/internal/intern/object.h
+digest.o: $(hdrdir)/ruby/internal/intern/parse.h
+digest.o: $(hdrdir)/ruby/internal/intern/proc.h
+digest.o: $(hdrdir)/ruby/internal/intern/process.h
+digest.o: $(hdrdir)/ruby/internal/intern/random.h
+digest.o: $(hdrdir)/ruby/internal/intern/range.h
+digest.o: $(hdrdir)/ruby/internal/intern/rational.h
+digest.o: $(hdrdir)/ruby/internal/intern/re.h
+digest.o: $(hdrdir)/ruby/internal/intern/ruby.h
+digest.o: $(hdrdir)/ruby/internal/intern/select.h
+digest.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+digest.o: $(hdrdir)/ruby/internal/intern/set.h
+digest.o: $(hdrdir)/ruby/internal/intern/signal.h
+digest.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+digest.o: $(hdrdir)/ruby/internal/intern/string.h
+digest.o: $(hdrdir)/ruby/internal/intern/struct.h
+digest.o: $(hdrdir)/ruby/internal/intern/thread.h
+digest.o: $(hdrdir)/ruby/internal/intern/time.h
+digest.o: $(hdrdir)/ruby/internal/intern/variable.h
+digest.o: $(hdrdir)/ruby/internal/intern/vm.h
+digest.o: $(hdrdir)/ruby/internal/interpreter.h
+digest.o: $(hdrdir)/ruby/internal/iterator.h
+digest.o: $(hdrdir)/ruby/internal/memory.h
+digest.o: $(hdrdir)/ruby/internal/method.h
+digest.o: $(hdrdir)/ruby/internal/module.h
+digest.o: $(hdrdir)/ruby/internal/newobj.h
+digest.o: $(hdrdir)/ruby/internal/scan_args.h
+digest.o: $(hdrdir)/ruby/internal/special_consts.h
+digest.o: $(hdrdir)/ruby/internal/static_assert.h
+digest.o: $(hdrdir)/ruby/internal/stdalign.h
+digest.o: $(hdrdir)/ruby/internal/stdbool.h
+digest.o: $(hdrdir)/ruby/internal/stdckdint.h
+digest.o: $(hdrdir)/ruby/internal/symbol.h
+digest.o: $(hdrdir)/ruby/internal/value.h
+digest.o: $(hdrdir)/ruby/internal/value_type.h
+digest.o: $(hdrdir)/ruby/internal/variable.h
+digest.o: $(hdrdir)/ruby/internal/warning_push.h
+digest.o: $(hdrdir)/ruby/internal/xmalloc.h
+digest.o: $(hdrdir)/ruby/missing.h
+digest.o: $(hdrdir)/ruby/ruby.h
+digest.o: $(hdrdir)/ruby/st.h
+digest.o: $(hdrdir)/ruby/subst.h
+digest.o: digest.c
+digest.o: digest.h
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/digest.c b/ext/digest/digest.c
index ead9da3c10..28f6022754 100644
--- a/ext/digest/digest.c
+++ b/ext/digest/digest.c
@@ -6,311 +6,844 @@
created at: Fri May 25 08:57:27 JST 2001
Copyright (C) 1995-2001 Yukihiro Matsumoto
- Copyright (C) 2001 Akinori MUSHA
+ Copyright (C) 2001-2006 Akinori MUSHA
$RoughId: digest.c,v 1.16 2001/07/13 15:38:27 knu Exp $
$Id$
************************************************/
+#include "digest.h"
+
+static VALUE rb_mDigest;
+static VALUE rb_mDigest_Instance;
+static VALUE rb_cDigest_Class;
+static VALUE rb_cDigest_Base;
+
+static ID id_reset, id_update, id_finish, id_digest, id_hexdigest, id_digest_length;
+static ID id_metadata;
+
+RUBY_EXTERN void Init_digest_base(void);
+
/*
- * This module provides an interface to the following hash algorithms:
+ * Document-module: Digest
+ *
+ * This module provides a framework for message digest libraries.
+ *
+ * You may want to look at OpenSSL::Digest as it supports more algorithms.
+ *
+ * A cryptographic hash function is a procedure that takes data and returns a
+ * fixed bit string: the hash value, also known as _digest_. Hash functions
+ * are also called one-way functions, it is easy to compute a digest from
+ * a message, but it is infeasible to generate a message from a digest.
+ *
+ * == Examples
+ *
+ * require 'digest'
+ *
+ * # Compute a complete digest
+ * Digest::SHA256.digest 'message' #=> "\xABS\n\x13\xE4Y..."
+ *
+ * sha256 = Digest::SHA256.new
+ * sha256.digest 'message' #=> "\xABS\n\x13\xE4Y..."
+ *
+ * # Other encoding formats
+ * Digest::SHA256.hexdigest 'message' #=> "ab530a13e459..."
+ * Digest::SHA256.base64digest 'message' #=> "q1MKE+RZFJgr..."
+ *
+ * # Compute digest by chunks
+ * md5 = Digest::MD5.new
+ * md5.update 'message1'
+ * md5 << 'message2' # << is an alias for update
+ *
+ * md5.hexdigest #=> "94af09c09bb9..."
+ *
+ * # Compute digest for a file
+ * sha256 = Digest::SHA256.file 'testfile'
+ * sha256.hexdigest
*
- * - the MD5 Message-Digest Algorithm by the RSA Data Security,
- * Inc., described in RFC 1321
+ * Additionally digests can be encoded in "bubble babble" format as a sequence
+ * of consonants and vowels which is more recognizable and comparable than a
+ * hexadecimal digest.
*
- * - the SHA-1 Secure Hash Algorithm by NIST (the US' National
- * Institute of Standards and Technology), described in FIPS PUB
- * 180-1.
+ * require 'digest/bubblebabble'
*
- * - the SHA-256/384/512 Secure Hash Algorithm by NIST (the US'
- * National Institute of Standards and Technology), described in
- * FIPS PUB 180-2.
+ * Digest::SHA256.bubblebabble 'message' #=> "xopoh-fedac-fenyh-..."
*
- * - the RIPEMD-160 cryptographic hash function, designed by Hans
- * Dobbertin, Antoon Bosselaers, and Bart Preneel.
+ * See the bubble babble specification at
+ * http://web.mit.edu/kenta/www/one/bubblebabble/spec/jrtrjwzi/draft-huima-01.txt.
+ *
+ * == Digest algorithms
+ *
+ * Different digest algorithms (or hash functions) are available:
+ *
+ * MD5::
+ * See RFC 1321 The MD5 Message-Digest Algorithm
+ * RIPEMD-160::
+ * As Digest::RMD160.
+ * See http://homes.esat.kuleuven.be/~bosselae/ripemd160.html.
+ * SHA1::
+ * See FIPS 180 Secure Hash Standard.
+ * SHA2 family::
+ * See FIPS 180 Secure Hash Standard which defines the following algorithms:
+ * * SHA512
+ * * SHA384
+ * * SHA256
+ *
+ * The latest versions of the FIPS publications can be found here:
+ * http://csrc.nist.gov/publications/PubsFIPS.html.
*/
-#include "digest.h"
+static VALUE
+hexencode_str_new(VALUE str_digest)
+{
+ char *digest;
+ size_t digest_len;
+ size_t i;
+ VALUE str;
+ char *p;
+ static const char hex[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ StringValue(str_digest);
+ digest = RSTRING_PTR(str_digest);
+ digest_len = RSTRING_LEN(str_digest);
+
+ if (LONG_MAX / 2 < digest_len) {
+ rb_raise(rb_eRuntimeError, "digest string too long");
+ }
-static VALUE mDigest, cDigest_Base;
-static ID id_metadata;
+ str = rb_usascii_str_new(0, digest_len * 2);
+
+ for (i = 0, p = RSTRING_PTR(str); i < digest_len; i++) {
+ unsigned char byte = digest[i];
+
+ p[i + i] = hex[byte >> 4];
+ p[i + i + 1] = hex[byte & 0x0f];
+ }
+
+ RB_GC_GUARD(str_digest);
+
+ return str;
+}
/*
- * Digest::Base
+ * call-seq:
+ * Digest.hexencode(string) -> hexencoded_string
+ *
+ * Generates a hex-encoded version of a given _string_.
*/
-
-static algo_t *
-get_digest_base_metadata(klass)
- VALUE klass;
+static VALUE
+rb_digest_s_hexencode(VALUE klass, VALUE str)
{
- VALUE obj;
- algo_t *algo;
-
- if (rb_cvar_defined(klass, id_metadata) == Qfalse) {
- rb_notimplement();
- }
+ return hexencode_str_new(str);
+}
- obj = rb_cvar_get(klass, id_metadata);
+NORETURN(static void rb_digest_instance_method_unimpl(VALUE self, const char *method));
- Data_Get_Struct(obj, algo_t, algo);
+/*
+ * Document-module: Digest::Instance
+ *
+ * This module provides instance methods for a digest implementation
+ * object to calculate message digest values.
+ */
- return algo;
+static void
+rb_digest_instance_method_unimpl(VALUE self, const char *method)
+{
+ rb_raise(rb_eRuntimeError, "%s does not implement %s()",
+ rb_obj_classname(self), method);
}
-static VALUE rb_digest_base_alloc _((VALUE));
+/*
+ * call-seq:
+ * digest_obj.update(string) -> digest_obj
+ * digest_obj << string -> digest_obj
+ *
+ * Updates the digest using a given _string_ and returns self.
+ *
+ * The update() method and the left-shift operator are overridden by
+ * each implementation subclass. (One should be an alias for the
+ * other)
+ */
static VALUE
-rb_digest_base_alloc(klass)
- VALUE klass;
+rb_digest_instance_update(VALUE self, VALUE str)
{
- algo_t *algo;
- VALUE obj;
- void *pctx;
+ rb_digest_instance_method_unimpl(self, "update");
- if (klass == cDigest_Base) {
- rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
- }
+ UNREACHABLE;
+}
- algo = get_digest_base_metadata(klass);
+/*
+ * call-seq:
+ * digest_obj.instance_eval { finish } -> digest_obj
+ *
+ * Finishes the digest and returns the resulting hash value.
+ *
+ * This method is overridden by each implementation subclass and often
+ * made private, because some of those subclasses may leave internal
+ * data uninitialized. Do not call this method from outside. Use
+ * #digest!() instead, which ensures that internal data be reset for
+ * security reasons.
+ */
+static VALUE
+rb_digest_instance_finish(VALUE self)
+{
+ rb_digest_instance_method_unimpl(self, "finish");
- /* XXX: An uninitialized buffer leads ALGO_Equal() to fail */
- pctx = xcalloc(algo->ctx_size, 1);
- algo->init_func(pctx);
+ UNREACHABLE;
+}
- obj = Data_Wrap_Struct(klass, 0, free, pctx);
+/*
+ * call-seq:
+ * digest_obj.reset -> digest_obj
+ *
+ * Resets the digest to the initial state and returns self.
+ *
+ * This method is overridden by each implementation subclass.
+ */
+static VALUE
+rb_digest_instance_reset(VALUE self)
+{
+ rb_digest_instance_method_unimpl(self, "reset");
- return obj;
+ UNREACHABLE;
}
+/*
+ * call-seq:
+ * digest_obj.new -> another_digest_obj
+ *
+ * Returns a new, initialized copy of the digest object. Equivalent
+ * to digest_obj.clone().reset().
+ */
static VALUE
-rb_digest_base_s_digest(klass, str)
- VALUE klass;
- VALUE str;
+rb_digest_instance_new(VALUE self)
{
- algo_t *algo;
- void *pctx;
- size_t len;
- unsigned char *digest;
- volatile VALUE obj = rb_digest_base_alloc(klass);
+ VALUE clone = rb_obj_clone(self);
+ rb_funcall(clone, id_reset, 0);
+ return clone;
+}
- algo = get_digest_base_metadata(klass);
- Data_Get_Struct(obj, void, pctx);
+/*
+ * call-seq:
+ * digest_obj.digest -> string
+ * digest_obj.digest(string) -> string
+ *
+ * If none is given, returns the resulting hash value of the digest,
+ * keeping the digest's state.
+ *
+ * If a _string_ is given, returns the hash value for the given
+ * _string_, resetting the digest to the initial state before and
+ * after the process.
+ */
+static VALUE
+rb_digest_instance_digest(int argc, VALUE *argv, VALUE self)
+{
+ VALUE str, value;
+
+ if (rb_scan_args(argc, argv, "01", &str) > 0) {
+ rb_funcall(self, id_reset, 0);
+ rb_funcall(self, id_update, 1, str);
+ value = rb_funcall(self, id_finish, 0);
+ rb_funcall(self, id_reset, 0);
+ } else {
+ value = rb_funcall(rb_obj_clone(self), id_finish, 0);
+ }
- StringValue(str);
- algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
+ return value;
+}
- len = algo->digest_len;
+/*
+ * call-seq:
+ * digest_obj.digest! -> string
+ *
+ * Returns the resulting hash value and resets the digest to the
+ * initial state.
+ */
+static VALUE
+rb_digest_instance_digest_bang(VALUE self)
+{
+ VALUE value = rb_funcall(self, id_finish, 0);
+ rb_funcall(self, id_reset, 0);
- digest = xmalloc(len);
- algo->final_func(digest, pctx);
+ return value;
+}
- obj = rb_str_new(digest, len);
+/*
+ * call-seq:
+ * digest_obj.hexdigest -> string
+ * digest_obj.hexdigest(string) -> string
+ *
+ * If none is given, returns the resulting hash value of the digest in
+ * a hex-encoded form, keeping the digest's state.
+ *
+ * If a _string_ is given, returns the hash value for the given
+ * _string_ in a hex-encoded form, resetting the digest to the initial
+ * state before and after the process.
+ */
+static VALUE
+rb_digest_instance_hexdigest(int argc, VALUE *argv, VALUE self)
+{
+ VALUE str, value;
+
+ if (rb_scan_args(argc, argv, "01", &str) > 0) {
+ rb_funcall(self, id_reset, 0);
+ rb_funcall(self, id_update, 1, str);
+ value = rb_funcall(self, id_finish, 0);
+ rb_funcall(self, id_reset, 0);
+ } else {
+ value = rb_funcall(rb_obj_clone(self), id_finish, 0);
+ }
- free(digest);
+ return hexencode_str_new(value);
+}
- return obj;
+/*
+ * call-seq:
+ * digest_obj.hexdigest! -> string
+ *
+ * Returns the resulting hash value in a hex-encoded form and resets
+ * the digest to the initial state.
+ */
+static VALUE
+rb_digest_instance_hexdigest_bang(VALUE self)
+{
+ VALUE value = rb_funcall(self, id_finish, 0);
+ rb_funcall(self, id_reset, 0);
+
+ return hexencode_str_new(value);
}
+/*
+ * call-seq:
+ * digest_obj.to_s -> string
+ *
+ * Returns digest_obj.hexdigest().
+ */
static VALUE
-rb_digest_base_s_hexdigest(klass, str)
- VALUE klass;
- VALUE str;
+rb_digest_instance_to_s(VALUE self)
{
- algo_t *algo;
- void *pctx;
- size_t len;
- unsigned char *hexdigest;
- volatile VALUE obj = rb_digest_base_alloc(klass);
+ return rb_funcall(self, id_hexdigest, 0);
+}
- algo = get_digest_base_metadata(klass);
- Data_Get_Struct(obj, void, pctx);
+/*
+ * call-seq:
+ * digest_obj.inspect -> string
+ *
+ * Creates a printable version of the digest object.
+ */
+static VALUE
+rb_digest_instance_inspect(VALUE self)
+{
+ VALUE str;
+ size_t digest_len = 32; /* about this size at least */
+ const char *cname;
+
+ cname = rb_obj_classname(self);
+
+ /* #<Digest::ClassName: xxxxx...xxxx> */
+ str = rb_str_buf_new(2 + strlen(cname) + 2 + digest_len * 2 + 1);
+ rb_str_buf_cat2(str, "#<");
+ rb_str_buf_cat2(str, cname);
+ rb_str_buf_cat2(str, ": ");
+ rb_str_buf_append(str, rb_digest_instance_hexdigest(0, 0, self));
+ rb_str_buf_cat2(str, ">");
+ return str;
+}
- StringValue(str);
- algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
+/*
+ * call-seq:
+ * digest_obj == another_digest_obj -> boolean
+ * digest_obj == string -> boolean
+ *
+ * If a string is given, checks whether it is equal to the hex-encoded
+ * hash value of the digest object. If another digest instance is
+ * given, checks whether they have the same hash value. Otherwise
+ * returns false.
+ */
+static VALUE
+rb_digest_instance_equal(VALUE self, VALUE other)
+{
+ VALUE str1, str2;
- len = algo->digest_len * 2;
+ if (rb_obj_is_kind_of(other, rb_mDigest_Instance) == Qtrue) {
+ str1 = rb_digest_instance_digest(0, 0, self);
+ str2 = rb_digest_instance_digest(0, 0, other);
+ } else {
+ str1 = rb_digest_instance_to_s(self);
+ str2 = rb_check_string_type(other);
+ if (NIL_P(str2)) return Qfalse;
+ }
- hexdigest = xmalloc(len + 1); /* +1 is for '\0' */
- algo->end_func(pctx, hexdigest);
+ /* never blindly assume that subclass methods return strings */
+ StringValue(str1);
+ StringValue(str2);
- obj = rb_str_new(hexdigest, len);
+ if (RSTRING_LEN(str1) == RSTRING_LEN(str2) &&
+ rb_str_cmp(str1, str2) == 0) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
- free(hexdigest);
+/*
+ * call-seq:
+ * digest_obj.digest_length -> integer
+ *
+ * Returns the length of the hash value of the digest.
+ *
+ * This method should be overridden by each implementation subclass.
+ * If not, digest_obj.digest().length() is returned.
+ */
+static VALUE
+rb_digest_instance_digest_length(VALUE self)
+{
+ /* subclasses really should redefine this method */
+ VALUE digest = rb_digest_instance_digest(0, 0, self);
- return obj;
+ /* never blindly assume that #digest() returns a string */
+ StringValue(digest);
+ return LONG2NUM(RSTRING_LEN(digest));
}
+/*
+ * call-seq:
+ * digest_obj.length -> integer
+ * digest_obj.size -> integer
+ *
+ * Returns digest_obj.digest_length().
+ */
static VALUE
-rb_digest_base_copy(copy, obj)
- VALUE copy, obj;
+rb_digest_instance_length(VALUE self)
{
- algo_t *algo;
- void *pctx1, *pctx2;
+ return rb_funcall(self, id_digest_length, 0);
+}
- if (copy == obj) return copy;
- rb_check_frozen(copy);
- algo = get_digest_base_metadata(rb_obj_class(copy));
- if (algo != get_digest_base_metadata(rb_obj_class(obj))) {
- rb_raise(rb_eTypeError, "wrong argument class");
- }
- Data_Get_Struct(obj, void, pctx1);
- Data_Get_Struct(copy, void, pctx2);
- memcpy(pctx2, pctx1, algo->ctx_size);
+/*
+ * call-seq:
+ * digest_obj.block_length -> integer
+ *
+ * Returns the block length of the digest.
+ *
+ * This method is overridden by each implementation subclass.
+ */
+static VALUE
+rb_digest_instance_block_length(VALUE self)
+{
+ rb_digest_instance_method_unimpl(self, "block_length");
- return copy;
+ UNREACHABLE;
}
+/*
+ * Document-class: Digest::Class
+ *
+ * This module stands as a base class for digest implementation
+ * classes.
+ */
+
+/*
+ * call-seq:
+ * Digest::Class.digest(string, *parameters) -> hash_string
+ *
+ * Returns the hash value of a given _string_. This is equivalent to
+ * Digest::Class.new(*parameters).digest(string), where extra
+ * _parameters_, if any, are passed through to the constructor and the
+ * _string_ is passed to #digest().
+ */
static VALUE
-rb_digest_base_update(self, str)
- VALUE self, str;
+rb_digest_class_s_digest(int argc, VALUE *argv, VALUE klass)
{
- algo_t *algo;
- void *pctx;
+ VALUE str;
+ volatile VALUE obj;
+
+ if (argc < 1) {
+ rb_raise(rb_eArgError, "no data given");
+ }
+
+ str = *argv++;
+ argc--;
StringValue(str);
- algo = get_digest_base_metadata(rb_obj_class(self));
- Data_Get_Struct(self, void, pctx);
- algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
+ obj = rb_obj_alloc(klass);
+ rb_obj_call_init(obj, argc, argv);
- return self;
+ return rb_funcall(obj, id_digest, 1, str);
+}
+
+/*
+ * call-seq:
+ * Digest::Class.hexdigest(string[, ...]) -> hash_string
+ *
+ * Returns the hex-encoded hash value of a given _string_. This is
+ * almost equivalent to
+ * Digest.hexencode(Digest::Class.new(*parameters).digest(string)).
+ */
+static VALUE
+rb_digest_class_s_hexdigest(int argc, VALUE *argv, VALUE klass)
+{
+ return hexencode_str_new(rb_funcallv(klass, id_digest, argc, argv));
}
+/* :nodoc: */
static VALUE
-rb_digest_base_init(argc, argv, self)
- int argc;
- VALUE* argv;
- VALUE self;
+rb_digest_class_init(VALUE self)
{
- VALUE arg;
+ return self;
+}
- rb_scan_args(argc, argv, "01", &arg);
+/*
+ * Document-class: Digest::Base
+ *
+ * This abstract class provides a common interface to message digest
+ * implementation classes written in C.
+ *
+ * ==Write a Digest subclass in C
+ * Digest::Base provides a common interface to message digest
+ * classes written in C. These classes must provide a struct
+ * of type rb_digest_metadata_t:
+ * typedef int (*rb_digest_hash_init_func_t)(void *);
+ * typedef void (*rb_digest_hash_update_func_t)(void *, unsigned char *, size_t);
+ * typedef int (*rb_digest_hash_finish_func_t)(void *, unsigned char *);
+ *
+ * typedef struct {
+ * int api_version;
+ * size_t digest_len;
+ * size_t block_len;
+ * size_t ctx_size;
+ * rb_digest_hash_init_func_t init_func;
+ * rb_digest_hash_update_func_t update_func;
+ * rb_digest_hash_finish_func_t finish_func;
+ * } rb_digest_metadata_t;
+ *
+ * This structure must be set as an instance variable named +metadata+
+ * (without the +@+ in front of the name). By example:
+ * static const rb_digest_metadata_t sha1 = {
+ * RUBY_DIGEST_API_VERSION,
+ * SHA1_DIGEST_LENGTH,
+ * SHA1_BLOCK_LENGTH,
+ * sizeof(SHA1_CTX),
+ * (rb_digest_hash_init_func_t)SHA1_Init,
+ * (rb_digest_hash_update_func_t)SHA1_Update,
+ * (rb_digest_hash_finish_func_t)SHA1_Finish,
+ * };
+ *
+ *
+ * rb_ivar_set(cDigest_SHA1, rb_intern("metadata"),
+ * rb_digest_make_metadata(&sha1));
+ */
- if (!NIL_P(arg)) rb_digest_base_update(self, arg);
+#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+static const rb_data_type_t metadata_type = {
+ "digest/metadata",
+ {0},
+};
- return self;
+RUBY_FUNC_EXPORTED VALUE
+rb_digest_wrap_metadata(const rb_digest_metadata_t *meta)
+{
+ return rb_obj_freeze(TypedData_Wrap_Struct(0, &metadata_type, (void *)meta));
}
+#endif
-static VALUE
-rb_digest_base_digest(self)
- VALUE self;
+static rb_digest_metadata_t *
+get_metadata_ptr(VALUE obj)
{
- algo_t *algo;
- void *pctx1, *pctx2;
- unsigned char *digest;
- size_t len;
- VALUE str;
+ rb_digest_metadata_t *algo;
- algo = get_digest_base_metadata(rb_obj_class(self));
- Data_Get_Struct(self, void, pctx1);
+#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+ if (!rb_typeddata_is_kind_of(obj, &metadata_type)) return 0;
+ algo = RTYPEDDATA_DATA(obj);
+#else
+# undef RUBY_UNTYPED_DATA_WARNING
+# define RUBY_UNTYPED_DATA_WARNING 0
+ Data_Get_Struct(obj, rb_digest_metadata_t, algo);
+#endif
- len = algo->ctx_size;
+ return algo;
+}
- pctx2 = xmalloc(len);
- memcpy(pctx2, pctx1, len);
+static rb_digest_metadata_t *
+get_digest_base_metadata(VALUE klass)
+{
+ VALUE p;
+ VALUE obj = Qnil;
+ rb_digest_metadata_t *algo;
+
+ for (p = klass; !NIL_P(p); p = rb_class_superclass(p)) {
+ if (rb_ivar_defined(p, id_metadata)) {
+ obj = rb_ivar_get(p, id_metadata);
+ break;
+ }
+ }
- len = algo->digest_len;
+ if (NIL_P(p))
+ rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby");
+
+ algo = get_metadata_ptr(obj);
+ if (!algo) {
+ if (p == klass)
+ rb_raise(rb_eTypeError, "%"PRIsVALUE"::metadata is not initialized properly",
+ klass);
+ else
+ rb_raise(rb_eTypeError, "%"PRIsVALUE"(%"PRIsVALUE")::metadata is not initialized properly",
+ klass, p);
+ }
- digest = xmalloc(len);
- algo->final_func(digest, pctx2);
+ switch (algo->api_version) {
+ case 3:
+ break;
- str = rb_str_new(digest, len);
+ /*
+ * put conversion here if possible when API is updated
+ */
- free(digest);
- free(pctx2);
+ default:
+ rb_raise(rb_eRuntimeError, "Incompatible digest API version");
+ }
- return str;
+ return algo;
+}
+
+static rb_digest_metadata_t *
+get_digest_obj_metadata(VALUE obj)
+{
+ return get_digest_base_metadata(rb_obj_class(obj));
+}
+
+static const rb_data_type_t digest_type = {
+ "digest",
+ {0, RUBY_TYPED_DEFAULT_FREE, 0,},
+ 0, 0,
+ (RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED),
+};
+
+static inline void
+algo_init(const rb_digest_metadata_t *algo, void *pctx)
+{
+ if (algo->init_func(pctx) != 1) {
+ rb_raise(rb_eRuntimeError, "Digest initialization failed.");
+ }
}
static VALUE
-rb_digest_base_hexdigest(self)
- VALUE self;
+rb_digest_base_alloc(VALUE klass)
{
- algo_t *algo;
+ rb_digest_metadata_t *algo;
+ VALUE obj;
+ void *pctx;
+
+ if (klass == rb_cDigest_Base) {
+ rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
+ }
+
+ algo = get_digest_base_metadata(klass);
+
+ obj = rb_data_typed_object_zalloc(klass, algo->ctx_size, &digest_type);
+ pctx = RTYPEDDATA_DATA(obj);
+ algo_init(algo, pctx);
+
+ return obj;
+}
+
+/* :nodoc: */
+static VALUE
+rb_digest_base_copy(VALUE copy, VALUE obj)
+{
+ rb_digest_metadata_t *algo;
void *pctx1, *pctx2;
- unsigned char *hexdigest;
- size_t len;
- VALUE str;
- algo = get_digest_base_metadata(rb_obj_class(self));
- Data_Get_Struct(self, void, pctx1);
+ if (copy == obj) return copy;
- len = algo->ctx_size;
+ rb_check_frozen(copy);
- pctx2 = xmalloc(len);
- memcpy(pctx2, pctx1, len);
+ algo = get_digest_obj_metadata(copy);
+ if (algo != get_digest_obj_metadata(obj))
+ rb_raise(rb_eTypeError, "different algorithms");
- len = algo->digest_len * 2;
+ TypedData_Get_Struct(obj, void, &digest_type, pctx1);
+ TypedData_Get_Struct(copy, void, &digest_type, pctx2);
+ memcpy(pctx2, pctx1, algo->ctx_size);
- hexdigest = xmalloc(len + 1); /* +1 is for '\0' */
- algo->end_func(pctx2, hexdigest);
+ return copy;
+}
- str = rb_str_new(hexdigest, len);
+/*
+ * call-seq: digest_base.reset -> digest_base
+ *
+ * Reset the digest to its initial state and return +self+.
+ */
+static VALUE
+rb_digest_base_reset(VALUE self)
+{
+ rb_digest_metadata_t *algo;
+ void *pctx;
- free(hexdigest);
- free(pctx2);
+ algo = get_digest_obj_metadata(self);
- return str;
+ TypedData_Get_Struct(self, void, &digest_type, pctx);
+
+ algo_init(algo, pctx);
+
+ return self;
}
+/*
+ * call-seq:
+ * digest_base.update(string) -> digest_base
+ * digest_base << string -> digest_base
+ *
+ * Update the digest using given _string_ and return +self+.
+ */
static VALUE
-rb_digest_base_equal(self, other)
- VALUE self, other;
+rb_digest_base_update(VALUE self, VALUE str)
{
- algo_t *algo;
- VALUE klass;
- VALUE str1, str2;
+ rb_digest_metadata_t *algo;
+ void *pctx;
- klass = rb_obj_class(self);
- algo = get_digest_base_metadata(klass);
+ algo = get_digest_obj_metadata(self);
- if (rb_obj_class(other) == klass) {
- void *pctx1, *pctx2;
+ TypedData_Get_Struct(self, void, &digest_type, pctx);
- Data_Get_Struct(self, void, pctx1);
- Data_Get_Struct(other, void, pctx2);
+ StringValue(str);
+ algo->update_func(pctx, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str));
+ RB_GC_GUARD(str);
- return algo->equal_func(pctx1, pctx2) ? Qtrue : Qfalse;
- }
+ return self;
+}
- StringValue(other);
- str2 = other;
+/* :nodoc: */
+static VALUE
+rb_digest_base_finish(VALUE self)
+{
+ rb_digest_metadata_t *algo;
+ void *pctx;
+ VALUE str;
- if (RSTRING(str2)->len == algo->digest_len)
- str1 = rb_digest_base_digest(self);
- else
- str1 = rb_digest_base_hexdigest(self);
+ algo = get_digest_obj_metadata(self);
- if (RSTRING(str1)->len == RSTRING(str2)->len
- && rb_str_cmp(str1, str2) == 0)
- return Qtrue;
+ TypedData_Get_Struct(self, void, &digest_type, pctx);
- return Qfalse;
+ str = rb_str_new(0, algo->digest_len);
+ algo->finish_func(pctx, (unsigned char *)RSTRING_PTR(str));
+
+ /* avoid potential coredump caused by use of a finished context */
+ algo_init(algo, pctx);
+
+ return str;
}
/*
- * Init
+ * call-seq: digest_base.digest_length -> Integer
+ *
+ * Return the length of the hash value in bytes.
*/
+static VALUE
+rb_digest_base_digest_length(VALUE self)
+{
+ rb_digest_metadata_t *algo;
-void
-Init_digest()
+ algo = get_digest_obj_metadata(self);
+
+ return SIZET2NUM(algo->digest_len);
+}
+
+/*
+ * call-seq: digest_base.block_length -> Integer
+ *
+ * Return the block length of the digest in bytes.
+ */
+static VALUE
+rb_digest_base_block_length(VALUE self)
{
- mDigest = rb_define_module("Digest");
+ rb_digest_metadata_t *algo;
- cDigest_Base = rb_define_class_under(mDigest, "Base", rb_cObject);
+ algo = get_digest_obj_metadata(self);
- rb_define_alloc_func(cDigest_Base, rb_digest_base_alloc);
- rb_define_singleton_method(cDigest_Base, "digest", rb_digest_base_s_digest, 1);
- rb_define_singleton_method(cDigest_Base, "hexdigest", rb_digest_base_s_hexdigest, 1);
+ return SIZET2NUM(algo->block_len);
+}
- rb_define_method(cDigest_Base, "initialize", rb_digest_base_init, -1);
- rb_define_method(cDigest_Base, "initialize_copy", rb_digest_base_copy, 1);
- rb_define_method(cDigest_Base, "update", rb_digest_base_update, 1);
- rb_define_method(cDigest_Base, "<<", rb_digest_base_update, 1);
- rb_define_method(cDigest_Base, "digest", rb_digest_base_digest, 0);
- rb_define_method(cDigest_Base, "hexdigest", rb_digest_base_hexdigest, 0);
- rb_define_method(cDigest_Base, "to_s", rb_digest_base_hexdigest, 0);
- rb_define_method(cDigest_Base, "==", rb_digest_base_equal, 1);
+void
+Init_digest(void)
+{
+#undef rb_intern
+ id_reset = rb_intern("reset");
+ id_update = rb_intern("update");
+ id_finish = rb_intern("finish");
+ id_digest = rb_intern("digest");
+ id_hexdigest = rb_intern("hexdigest");
+ id_digest_length = rb_intern("digest_length");
+ id_metadata = rb_id_metadata();
+ InitVM(digest);
+}
- id_metadata = rb_intern("metadata");
+void
+InitVM_digest(void)
+{
+ /*
+ * module Digest
+ */
+ rb_mDigest = rb_define_module("Digest");
+
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
+ /* module functions */
+ rb_define_module_function(rb_mDigest, "hexencode", rb_digest_s_hexencode, 1);
+
+ /*
+ * module Digest::Instance
+ */
+ rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance");
+
+ /* instance methods that should be overridden */
+ rb_define_method(rb_mDigest_Instance, "update", rb_digest_instance_update, 1);
+ rb_define_method(rb_mDigest_Instance, "<<", rb_digest_instance_update, 1);
+ rb_define_private_method(rb_mDigest_Instance, "finish", rb_digest_instance_finish, 0);
+ rb_define_method(rb_mDigest_Instance, "reset", rb_digest_instance_reset, 0);
+ rb_define_method(rb_mDigest_Instance, "digest_length", rb_digest_instance_digest_length, 0);
+ rb_define_method(rb_mDigest_Instance, "block_length", rb_digest_instance_block_length, 0);
+
+ /* instance methods that may be overridden */
+ rb_define_method(rb_mDigest_Instance, "==", rb_digest_instance_equal, 1);
+ rb_define_method(rb_mDigest_Instance, "inspect", rb_digest_instance_inspect, 0);
+
+ /* instance methods that need not usually be overridden */
+ rb_define_method(rb_mDigest_Instance, "new", rb_digest_instance_new, 0);
+ rb_define_method(rb_mDigest_Instance, "digest", rb_digest_instance_digest, -1);
+ rb_define_method(rb_mDigest_Instance, "digest!", rb_digest_instance_digest_bang, 0);
+ rb_define_method(rb_mDigest_Instance, "hexdigest", rb_digest_instance_hexdigest, -1);
+ rb_define_method(rb_mDigest_Instance, "hexdigest!", rb_digest_instance_hexdigest_bang, 0);
+ rb_define_method(rb_mDigest_Instance, "to_s", rb_digest_instance_to_s, 0);
+ rb_define_method(rb_mDigest_Instance, "length", rb_digest_instance_length, 0);
+ rb_define_method(rb_mDigest_Instance, "size", rb_digest_instance_length, 0);
+
+ /*
+ * class Digest::Class
+ */
+ rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject);
+ rb_define_method(rb_cDigest_Class, "initialize", rb_digest_class_init, 0);
+ rb_include_module(rb_cDigest_Class, rb_mDigest_Instance);
+
+ /* class methods */
+ rb_define_singleton_method(rb_cDigest_Class, "digest", rb_digest_class_s_digest, -1);
+ rb_define_singleton_method(rb_cDigest_Class, "hexdigest", rb_digest_class_s_hexdigest, -1);
+
+ /* class Digest::Base < Digest::Class */
+ rb_cDigest_Base = rb_define_class_under(rb_mDigest, "Base", rb_cDigest_Class);
+
+ rb_define_alloc_func(rb_cDigest_Base, rb_digest_base_alloc);
+
+ rb_define_method(rb_cDigest_Base, "initialize_copy", rb_digest_base_copy, 1);
+ rb_define_method(rb_cDigest_Base, "reset", rb_digest_base_reset, 0);
+ rb_define_method(rb_cDigest_Base, "update", rb_digest_base_update, 1);
+ rb_define_method(rb_cDigest_Base, "<<", rb_digest_base_update, 1);
+ rb_define_private_method(rb_cDigest_Base, "finish", rb_digest_base_finish, 0);
+ rb_define_method(rb_cDigest_Base, "digest_length", rb_digest_base_digest_length, 0);
+ rb_define_method(rb_cDigest_Base, "block_length", rb_digest_base_block_length, 0);
}
diff --git a/ext/digest/digest.gemspec b/ext/digest/digest.gemspec
new file mode 100644
index 0000000000..4a01c5fde1
--- /dev/null
+++ b/ext/digest/digest.gemspec
@@ -0,0 +1,44 @@
+# coding: utf-8
+# frozen_string_literal: true
+
+Gem::Specification.new do |spec|
+ version_module = Module.new do
+ version_rb = File.join(__dir__, "lib/digest/version.rb")
+ module_eval(File.read(version_rb), version_rb)
+ end
+
+ spec.name = "digest"
+ spec.version = version_module::Digest::VERSION
+ spec.authors = ["Akinori MUSHA"]
+ spec.email = ["knu@idaemons.org"]
+
+ spec.summary = %q{Provides a framework for message digest libraries.}
+ spec.description = %q{Provides a framework for message digest libraries.}
+ spec.homepage = "https://github.com/ruby/digest"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.files = [
+ "LICENSE.txt",
+ "README.md",
+ *Dir["lib/digest{.rb,/**/*.rb}"],
+ ]
+
+ spec.required_ruby_version = ">= 2.5.0"
+
+ spec.bindir = "exe"
+ spec.executables = []
+
+ if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby'
+ spec.platform = 'java'
+
+ spec.files += Dir["ext/java/**/*.{rb,java}", "lib/digest.jar"]
+ spec.require_paths = %w[lib ext/java/org/jruby/ext/digest/lib]
+ else
+ spec.extensions = Dir["ext/digest/**/extconf.rb"]
+
+ spec.files += Dir["ext/digest/**/{*.{rb,c,h,sh},depend}"]
+ spec.require_paths = %w[lib]
+ end
+
+ spec.metadata["msys2_mingw_dependencies"] = "openssl"
+end
diff --git a/ext/digest/digest.h b/ext/digest/digest.h
index 5e846df040..c5c37583a6 100644
--- a/ext/digest/digest.h
+++ b/ext/digest/digest.h
@@ -1,12 +1,12 @@
/************************************************
- digest.c -
+ digest.h - header file for ruby digest modules
$Author$
created at: Fri May 25 08:54:56 JST 2001
- Copyright (C) 2001 Akinori MUSHA
+ Copyright (C) 2001-2006 Akinori MUSHA
$RoughId: digest.h,v 1.3 2001/07/13 15:38:27 knu Exp $
$Id$
@@ -15,18 +15,92 @@
#include "ruby.h"
-typedef void (*hash_init_func_t) _((void *));
-typedef void (*hash_update_func_t) _((void *, unsigned char *, size_t));
-typedef void (*hash_end_func_t) _((void *, unsigned char *));
-typedef void (*hash_final_func_t) _((unsigned char *, void *));
-typedef int (*hash_equal_func_t) _((void *, void *));
+#define RUBY_DIGEST_API_VERSION 3
+
+typedef int (*rb_digest_hash_init_func_t)(void *);
+typedef void (*rb_digest_hash_update_func_t)(void *, unsigned char *, size_t);
+typedef int (*rb_digest_hash_finish_func_t)(void *, unsigned char *);
typedef struct {
+ int api_version;
size_t digest_len;
+ size_t block_len;
size_t ctx_size;
- hash_init_func_t init_func;
- hash_update_func_t update_func;
- hash_end_func_t end_func;
- hash_final_func_t final_func;
- hash_equal_func_t equal_func;
-} algo_t;
+ rb_digest_hash_init_func_t init_func;
+ rb_digest_hash_update_func_t update_func;
+ rb_digest_hash_finish_func_t finish_func;
+} rb_digest_metadata_t;
+
+#define DEFINE_UPDATE_FUNC_FOR_UINT(name) \
+void \
+rb_digest_##name##_update(void *ctx, unsigned char *ptr, size_t size) \
+{ \
+ const unsigned int stride = 16384; \
+ \
+ for (; size > stride; size -= stride, ptr += stride) { \
+ name##_Update(ctx, ptr, stride); \
+ } \
+ /* Since size <= stride, size should fit into an unsigned int */ \
+ if (size > 0) name##_Update(ctx, ptr, (unsigned int)size); \
+}
+
+#define DEFINE_FINISH_FUNC_FROM_FINAL(name) \
+int \
+rb_digest_##name##_finish(void *ctx, unsigned char *ptr) \
+{ \
+ return name##_Final(ptr, ctx); \
+}
+
+static inline VALUE
+rb_digest_namespace(void)
+{
+ rb_require("digest");
+ return rb_path2class("Digest");
+}
+
+static inline ID
+rb_id_metadata(void)
+{
+ return rb_intern_const("metadata");
+}
+
+#if !defined(HAVE_RB_EXT_RESOLVE_SYMBOL)
+#elif !defined(RUBY_UNTYPED_DATA_WARNING)
+# error RUBY_UNTYPED_DATA_WARNING is not defined
+#elif RUBY_UNTYPED_DATA_WARNING
+/* rb_ext_resolve_symbol() has been defined since Ruby 3.3, but digest
+ * bundled with 3.3 didn't use it. */
+# define DIGEST_USE_RB_EXT_RESOLVE_SYMBOL 1
+#endif
+
+static inline VALUE
+rb_digest_make_metadata(const rb_digest_metadata_t *meta)
+{
+#if defined(EXTSTATIC) && EXTSTATIC
+ /* The extension is built as a static library, so safe to refer to
+ * rb_digest_wrap_metadata directly. */
+ extern VALUE rb_digest_wrap_metadata(const rb_digest_metadata_t *meta);
+ return rb_digest_wrap_metadata(meta);
+#else
+ /* The extension is built as a shared library, so we can't refer
+ * to rb_digest_wrap_metadata directly. */
+# ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+ /* If rb_ext_resolve_symbol() is available, use it to get the address of
+ * rb_digest_wrap_metadata. */
+ typedef VALUE (*wrapper_func_type)(const rb_digest_metadata_t *meta);
+ static wrapper_func_type wrapper;
+ if (!wrapper) {
+ wrapper = (wrapper_func_type)(uintptr_t)
+ rb_ext_resolve_symbol("digest.so", "rb_digest_wrap_metadata");
+ if (!wrapper) rb_raise(rb_eLoadError, "rb_digest_wrap_metadata not found");
+ }
+ return wrapper(meta);
+# else
+ /* If rb_ext_resolve_symbol() is not available, keep using untyped
+ * data. */
+# undef RUBY_UNTYPED_DATA_WARNING
+# define RUBY_UNTYPED_DATA_WARNING 0
+ return rb_obj_freeze(Data_Wrap_Struct(0, 0, 0, (void *)meta));
+# endif
+#endif
+}
diff --git a/ext/digest/digest.txt b/ext/digest/digest.txt
deleted file mode 100644
index 5797dd18f9..0000000000
--- a/ext/digest/digest.txt
+++ /dev/null
@@ -1,113 +0,0 @@
-.\" digest.txt - -*- Indented-Text -*- created at: Fri May 25 08:13:50 JST 2001
-$RoughId: digest.txt,v 1.9 2001/07/13 19:46:51 knu Exp $
-$Id$
-
-** MD5(Class)
-
-A class to implement the MD5 Message-Digest Algorithm by RSA Data
-Security, Inc., described in RFC1321.
-
-Superclass: Digest::Base
-
-require 'digest/md5'
-
-** SHA1(Class)
-
-A class to implement the SHA-1 Secure Hash Algorithm by NIST (the US'
-National Institute of Standards and Technology), described in FIPS PUB
-180-1.
-
-Superclass: Digest::Base
-
-require 'digest/sha1'
-
-** SHA256(Class)
-** SHA384(Class)
-** SHA512(Class)
-
-Classes to implement the SHA-256/384/512 Secure Hash Algorithm(s) by
-NIST (the US' National Institute of Standards and Technology),
-described in FIPS PUB 180-2.
-
-Superclass: Digest::Base
-
-require 'digest/sha2'
-
-** RMD160(Class)
-
-A class to implement the RIPEMD-160 cryptographic hash function,
-designed by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel.
-
-Superclass: Digest::Base
-
-require 'digest/rmd160'
-
-
-Those above classes provide a common interface as shown below.
-
-
-Class Methods:
-
- new([str])
-
- Creates a new digest object. If a string argument is given,
- it is added to the object. (see update.)
-
- digest(str)
-
- Immediately calculates and return the hash of the given
- strings as a string. Equivalent to new(str).digest.
-
- hexdigest(str)
-
- Immediately calculates and return the hash of the given
- strings as a string of hexadecimal digits. Equivalent to
- new(str).hexdigest.
-
-Methods:
-
- clone
-
- Creates a copy of the digest object.
-
- digest
-
- Returns the hash of the added strings as a string of 16 bytes
- for MD5, 20 bytes for SHA1 and RMD160, 32 bytes for SHA256, 48
- bytes for SHA384, and 64 bytes for SHA512.
-
- hexdigest
- to_s
-
- Returns the hash of the added strings as a string of 32
- hexadecimal digits for MD5, 40 hexadecimal digits for SHA1 and
- RMD160, 64 hexadecimal digits for SHA256, 96 hexadecimal
- digits for SHA384, and 128 hexadecimal digits for SHA512.
- This method is equal to:
-
- def hexdigest
- digest.unpack("H*")[0]
- end
-
- update(str)
- << str
-
- Appends the string str to the digest object. Repeated calls
- are equivalent to a single call with the concatenation of all
- the arguments, i.e. m.update(a); m.update(b) is equivalent to
- m.update(a + b) and m << a << b is equivalent to m << a + b.
-
- == md
-
- Checks if the object is equal to the given digest object.
-
- == str
-
- Regards the value as either a digest value or a hexdigest
- value (depending on the length) and checks if the object is
- equal to the given string.
-
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/ext/digest/digest.txt.ja b/ext/digest/digest.txt.ja
deleted file mode 100644
index 8997d25b9d..0000000000
--- a/ext/digest/digest.txt.ja
+++ /dev/null
@@ -1,111 +0,0 @@
-.\" digest.txt.ja - -*- Indented-Text -*- created at: Fri May 25 08:22:19 JST 2001
-$RoughId: digest.txt.jp,v 1.8 2001/07/13 15:38:27 knu Exp $
-$Id$
-
-** MD5(¥¯¥é¥¹)
-
-RFC1321¤Ëµ­½Ò¤µ¤ì¤Æ¤¤¤ëRSA Data Security, Inc. ¤Î MD5 Message-Digest
-Algorithm¤ò¼ÂÁõ¤¹¤ë¥¯¥é¥¹¡£
-
-Superclass: Digest::Base
-
-require 'digest/md5'
-
-** SHA1(¥¯¥é¥¹)
-
-FIPS PUB 180-1¤Ëµ­½Ò¤µ¤ì¤Æ¤¤¤ëNIST (the US' National Institute of
-Standards and Technology) ¤Î SHA-1 Secure Hash Algorithm¤ò¼ÂÁõ¤¹¤ë¥¯¥é¥¹¡£
-
-Superclass: Digest::Base
-
-require 'digest/sha1'
-
-** SHA256(¥¯¥é¥¹)
-** SHA384(¥¯¥é¥¹)
-** SHA512(¥¯¥é¥¹)
-
-FIPS PUB 180-2¤Ëµ­½Ò¤µ¤ì¤Æ¤¤¤ëNIST (the US' National Institute of
-Standards and Technology) ¤Î SHA-256/384/512 Secure Hash Algorithm¤ò
-¼ÂÁõ¤¹¤ë¥¯¥é¥¹¡£
-
-Superclass: Digest::Base
-
-require 'digest/sha2'
-
-** RMD160(¥¯¥é¥¹)
-
-Hans Dobbertin, Antoon Bosselaers, Bart Preneel ¤Ë¤è¤Ã¤ÆÀ߷פµ¤ì¤¿
-RIPEMD-160 ¥Ï¥Ã¥·¥å´Ø¿ô¤ò¼ÂÁõ¤¹¤ë¥¯¥é¥¹¡£
-
-Superclass: Digest::Base
-
-require 'digest/rmd160'
-
-
-¤³¤ì¤é¤Î¥¯¥é¥¹¤Ï°Ê²¼¤Î¤è¤¦¤Ê¶¦Ä̤Υ¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤òÄ󶡤¹¤ë¡£
-
-
-Class Methods:
-
- new([str])
-
- ¿·¤·¤¤¥À¥¤¥¸¥§¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤¹¤ë¡¥Ê¸»úÎó°ú¿ô¤¬Í¿¤¨¤é¤ì¤ë
- ¤È¤½¤ì¤òÄɲ乤ë(see update)¡£
-
- digest(str)
-
- Í¿¤¨¤é¤ì¤¿Ê¸»úÎó¤ËÂФ¹¤ë¥Ï¥Ã¥·¥åÃͤòʸ»úÎó¤ÇÊÖ¤¹¡£
- new(str).digest ¤ÈÅù²Á¡£
-
- hexdigest(str)
-
- Í¿¤¨¤é¤ì¤¿Ê¸»úÎó¤ËÂФ¹¤ë¥Ï¥Ã¥·¥åÃͤò¡¢ASCII¥³¡¼¥É¤ò»È¤Ã¤Æ
- 16¿Ê¿ô¤ÎÎó¤ò¼¨¤¹Ê¸»úÎó¤Ë¥¨¥ó¥³¡¼¥É¤·¤ÆÊÖ¤¹¡£
- new(str).hexdigest ¤ÈÅù²Á¡£
-
-Methods:
-
- clone
-
- ¥À¥¤¥¸¥§¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤ÎÊ£À½¤òºî¤ë¡£
-
- digest
-
- º£¤Þ¤Ç¤ËÄɲä·¤¿Ê¸»úÎó¤ËÂФ¹¤ë¥Ï¥Ã¥·¥åÃͤòʸ»úÎó¤ÇÊÖ¤¹¡£MD5¤Ç¤Ï
- 16¥Ð¥¤¥ÈĹ¡¢SHA1¤ª¤è¤ÓRMD160¤Ç¤Ï20¥Ð¥¤¥ÈĹ¡¢SHA256¤Ç¤Ï32¥Ð¥¤¥ÈĹ¡¢
- SHA384¤Ç¤Ï48¥Ð¥¤¥ÈĹ¡¢SHA512¤Ç¤Ï64¥Ð¥¤¥ÈĹ¤È¤Ê¤ë¡£
-
- hexdigest
- to_s
-
- º£¤Þ¤Ç¤ËÄɲä·¤¿Ê¸»úÎó¤ËÂФ¹¤ë¥Ï¥Ã¥·¥åÃͤò¡¢ASCII¥³¡¼¥É¤ò»È¤Ã¤Æ
- 16¿Ê¿ô¤ÎÎó¤ò¼¨¤¹Ê¸»úÎó¤Ë¥¨¥ó¥³¡¼¥É¤·¤ÆÊÖ¤¹¡£MD5¤Ç¤Ï32¥Ð¥¤¥ÈĹ¡¢
- SHA1¤ª¤è¤ÓRMD160¤Ç¤Ï40¥Ð¥¤¥ÈĹ¡¢SHA256¤Ç¤Ï64¥Ð¥¤¥ÈĹ¡¢SHA384¤Ç¤Ï
- 96¥Ð¥¤¥ÈĹ¡¢SHA512¤Ç¤Ï128¥Ð¥¤¥ÈĹ¤È¤Ê¤ë¡£Ruby¤Ç½ñ¤¯¤È°Ê²¼¤ÈƱ¤¸¡£
-
- def hexdigest
- digest.unpack("H*")[0]
- end
-
- update(str)
- << str
-
- ʸ»úÎó¤òÄɲ乤롣ʣ¿ô²óupdate¤ò¸Æ¤Ö¤³¤È¤Ïʸ»úÎó¤òÏ¢·ë¤·¤Æ
- update¤ò¸Æ¤Ö¤³¤È¤ÈÅù¤·¤¤¡£¤¹¤Ê¤ï¤Á m.update(a); m.update(b) ¤Ï
- m.update(a + b) ¤È¡¢ m << a << b ¤Ï m << a + b ¤È¤½¤ì¤¾¤ìÅù²Á
- ¤Ç¤¢¤ë¡£
-
- == md
-
- Í¿¤¨¤é¤ì¤¿¥À¥¤¥¸¥§¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤ÈÈæ³Ó¤¹¤ë¡£
-
- == str
-
- Í¿¤¨¤é¤ì¤¿Ê¸»úÎó¤ò digest ÃÍ¡¢¤â¤·¤¯¤Ï hexdigest ÃͤÈÈæ³Ó¤¹¤ë¡£
- ¤¤¤º¤ì¤ÎÃͤȸ«¤ë¤«¤ÏÍ¿¤¨¤é¤ì¤¿Ê¸»úÎó¤ÎŤµ¤Ë¤è¤Ã¤Æ¼«Æ°È½ÊÌ
- ¤µ¤ì¤ë¡£
-
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/ext/digest/digest_conf.rb b/ext/digest/digest_conf.rb
new file mode 100644
index 0000000000..099d20fcbe
--- /dev/null
+++ b/ext/digest/digest_conf.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: false
+
+def digest_conf(name)
+ unless with_config("bundled-#{name}")
+ case cc = with_config("common-digest", true)
+ when true, false
+ else
+ cc = cc.split(/[\s,]++/).any? {|pat| File.fnmatch?(pat, name)}
+ end
+ if cc and File.exist?("#$srcdir/#{name}cc.h") and
+ have_header("CommonCrypto/CommonDigest.h")
+ $defs << "-D#{name.upcase}_USE_COMMONDIGEST"
+ $headers << "#{name}cc.h"
+ return :commondigest
+ end
+ end
+ $objs << "#{name}.#{$OBJEXT}"
+ return
+end
diff --git a/ext/digest/extconf.rb b/ext/digest/extconf.rb
index cd512622a4..0e5f08d794 100644
--- a/ext/digest/extconf.rb
+++ b/ext/digest/extconf.rb
@@ -1,6 +1,11 @@
+# frozen_string_literal: false
# $RoughId: extconf.rb,v 1.6 2001/07/13 15:38:27 knu Exp $
# $Id$
require "mkmf"
+$INSTALLFILES = {
+ "digest.h" => "$(HDRDIR)"
+} if $extmk
+
create_makefile("digest")
diff --git a/ext/digest/lib/digest.rb b/ext/digest/lib/digest.rb
new file mode 100644
index 0000000000..e995adb450
--- /dev/null
+++ b/ext/digest/lib/digest.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: false
+
+if defined?(Digest) &&
+ /\A(?:2\.|3\.0\.[0-2]\z)/.match?(RUBY_VERSION) &&
+ caller_locations.any? { |l|
+ %r{/(rubygems/gem_runner|bundler/cli)\.rb}.match?(l.path)
+ }
+ # Before Ruby 3.0.3/3.1.0, the gem and bundle commands used to load
+ # the digest library before loading additionally installed gems, so
+ # you will get constant redefinition warnings and unexpected
+ # implementation overwriting if we proceed here. Avoid that.
+ return
+end
+
+require 'digest/version'
+require 'digest/loader'
+
+module Digest
+ # A mutex for Digest().
+ REQUIRE_MUTEX = Thread::Mutex.new
+
+ def self.const_missing(name) # :nodoc:
+ case name
+ when :SHA256, :SHA384, :SHA512
+ lib = 'digest/sha2'
+ else
+ lib = File.join('digest', name.to_s.downcase)
+ end
+
+ begin
+ require lib
+ rescue LoadError
+ raise LoadError, "library not found for class Digest::#{name} -- #{lib}", caller(1)
+ end
+ unless Digest.const_defined?(name)
+ raise NameError, "uninitialized constant Digest::#{name}", caller(1)
+ end
+ Digest.const_get(name)
+ end
+
+ class ::Digest::Class
+ # Creates a digest object and reads a given file, _name_.
+ # Optional arguments are passed to the constructor of the digest
+ # class.
+ #
+ # p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest
+ # # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534"
+ def self.file(name, *args)
+ new(*args).file(name)
+ end
+
+ # Returns the base64 encoded hash value of a given _string_. The
+ # return value is properly padded with '=' and contains no line
+ # feeds.
+ def self.base64digest(str, *args)
+ [digest(str, *args)].pack('m0')
+ end
+ end
+
+ module Instance
+ # Updates the digest with the contents of a given file _name_ and
+ # returns self.
+ def file(name)
+ File.open(name, "rb") {|f|
+ buf = ""
+ while f.read(16384, buf)
+ update buf
+ end
+ }
+ self
+ end
+
+ # If none is given, returns the resulting hash value of the digest
+ # in a base64 encoded form, keeping the digest's state.
+ #
+ # If a +string+ is given, returns the hash value for the given
+ # +string+ in a base64 encoded form, resetting the digest to the
+ # initial state before and after the process.
+ #
+ # In either case, the return value is properly padded with '=' and
+ # contains no line feeds.
+ def base64digest(str = nil)
+ [str ? digest(str) : digest].pack('m0')
+ end
+
+ # Returns the resulting hash value and resets the digest to the
+ # initial state.
+ def base64digest!
+ [digest!].pack('m0')
+ end
+ end
+end
+
+# call-seq:
+# Digest(name) -> digest_subclass
+#
+# Returns a Digest subclass by +name+ in a thread-safe manner even
+# when on-demand loading is involved.
+#
+# require 'digest'
+#
+# Digest("MD5")
+# # => Digest::MD5
+#
+# Digest(:SHA256)
+# # => Digest::SHA256
+#
+# Digest(:Foo)
+# # => LoadError: library not found for class Digest::Foo -- digest/foo
+def Digest(name)
+ const = name.to_sym
+ Digest::REQUIRE_MUTEX.synchronize {
+ # Ignore autoload's because it is void when we have #const_missing
+ Digest.const_missing(const)
+ }
+rescue LoadError
+ # Constants do not necessarily rely on digest/*.
+ if Digest.const_defined?(const)
+ Digest.const_get(const)
+ else
+ raise
+ end
+end
diff --git a/ext/digest/lib/digest/loader.rb b/ext/digest/lib/digest/loader.rb
new file mode 100644
index 0000000000..6b989e07be
--- /dev/null
+++ b/ext/digest/lib/digest/loader.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+require 'digest.so'
diff --git a/ext/digest/lib/digest/version.rb b/ext/digest/lib/digest/version.rb
new file mode 100644
index 0000000000..a56e80c54e
--- /dev/null
+++ b/ext/digest/lib/digest/version.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+module Digest
+ # The version string
+ VERSION = "3.2.1"
+end
diff --git a/ext/digest/lib/md5.rb b/ext/digest/lib/md5.rb
deleted file mode 100644
index 1d05d7d04e..0000000000
--- a/ext/digest/lib/md5.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# just for compatibility; requiring "md5" is obsoleted
-#
-# $RoughId: md5.rb,v 1.4 2001/07/13 15:38:27 knu Exp $
-# $Id$
-
-require 'digest/md5'
-
-MD5 = Digest::MD5
-
-class MD5
- def self.md5(*args)
- new(*args)
- end
-end
diff --git a/ext/digest/lib/sha1.rb b/ext/digest/lib/sha1.rb
deleted file mode 100644
index c4ac6f66ea..0000000000
--- a/ext/digest/lib/sha1.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# just for compatibility; requiring "sha1" is obsoleted
-#
-# $RoughId: sha1.rb,v 1.4 2001/07/13 15:38:27 knu Exp $
-# $Id$
-
-require 'digest/sha1'
-
-SHA1 = Digest::SHA1
-
-class SHA1
- def self.sha1(*args)
- new(*args)
- end
-end
diff --git a/ext/digest/md5/.cvsignore b/ext/digest/md5/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/digest/md5/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/digest/md5/depend b/ext/digest/md5/depend
index 8eaec20b4b..d1c25c28c8 100644
--- a/ext/digest/md5/depend
+++ b/ext/digest/md5/depend
@@ -1,6 +1,333 @@
-md5.o: md5.c md5.h $(srcdir)/../defs.h $(hdrdir)/ruby.h $(topdir)/config.h \
- $(hdrdir)/defines.h $(hdrdir)/intern.h
-md5init.o: md5init.c $(srcdir)/../digest.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h md5.h \
- $(srcdir)/../defs.h
-md5ossl.o: md5ossl.h
+md5.o: md5.c md5.h $(srcdir)/../defs.h
+md5init.o: $(LOCAL_HDRS)
+
+# AUTOGENERATED DEPENDENCIES START
+md5.o: $(RUBY_EXTCONF_H)
+md5.o: $(arch_hdrdir)/ruby/config.h
+md5.o: $(hdrdir)/ruby.h
+md5.o: $(hdrdir)/ruby/assert.h
+md5.o: $(hdrdir)/ruby/backward.h
+md5.o: $(hdrdir)/ruby/backward/2/assume.h
+md5.o: $(hdrdir)/ruby/backward/2/attributes.h
+md5.o: $(hdrdir)/ruby/backward/2/bool.h
+md5.o: $(hdrdir)/ruby/backward/2/inttypes.h
+md5.o: $(hdrdir)/ruby/backward/2/limits.h
+md5.o: $(hdrdir)/ruby/backward/2/long_long.h
+md5.o: $(hdrdir)/ruby/backward/2/stdalign.h
+md5.o: $(hdrdir)/ruby/backward/2/stdarg.h
+md5.o: $(hdrdir)/ruby/defines.h
+md5.o: $(hdrdir)/ruby/intern.h
+md5.o: $(hdrdir)/ruby/internal/abi.h
+md5.o: $(hdrdir)/ruby/internal/anyargs.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+md5.o: $(hdrdir)/ruby/internal/assume.h
+md5.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+md5.o: $(hdrdir)/ruby/internal/attr/artificial.h
+md5.o: $(hdrdir)/ruby/internal/attr/cold.h
+md5.o: $(hdrdir)/ruby/internal/attr/const.h
+md5.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+md5.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+md5.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+md5.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+md5.o: $(hdrdir)/ruby/internal/attr/error.h
+md5.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+md5.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+md5.o: $(hdrdir)/ruby/internal/attr/format.h
+md5.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+md5.o: $(hdrdir)/ruby/internal/attr/noalias.h
+md5.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+md5.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+md5.o: $(hdrdir)/ruby/internal/attr/noinline.h
+md5.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+md5.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+md5.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+md5.o: $(hdrdir)/ruby/internal/attr/pure.h
+md5.o: $(hdrdir)/ruby/internal/attr/restrict.h
+md5.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+md5.o: $(hdrdir)/ruby/internal/attr/warning.h
+md5.o: $(hdrdir)/ruby/internal/attr/weakref.h
+md5.o: $(hdrdir)/ruby/internal/cast.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+md5.o: $(hdrdir)/ruby/internal/compiler_since.h
+md5.o: $(hdrdir)/ruby/internal/config.h
+md5.o: $(hdrdir)/ruby/internal/constant_p.h
+md5.o: $(hdrdir)/ruby/internal/core.h
+md5.o: $(hdrdir)/ruby/internal/core/rarray.h
+md5.o: $(hdrdir)/ruby/internal/core/rbasic.h
+md5.o: $(hdrdir)/ruby/internal/core/rbignum.h
+md5.o: $(hdrdir)/ruby/internal/core/rclass.h
+md5.o: $(hdrdir)/ruby/internal/core/rdata.h
+md5.o: $(hdrdir)/ruby/internal/core/rfile.h
+md5.o: $(hdrdir)/ruby/internal/core/rhash.h
+md5.o: $(hdrdir)/ruby/internal/core/robject.h
+md5.o: $(hdrdir)/ruby/internal/core/rregexp.h
+md5.o: $(hdrdir)/ruby/internal/core/rstring.h
+md5.o: $(hdrdir)/ruby/internal/core/rstruct.h
+md5.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+md5.o: $(hdrdir)/ruby/internal/ctype.h
+md5.o: $(hdrdir)/ruby/internal/dllexport.h
+md5.o: $(hdrdir)/ruby/internal/dosish.h
+md5.o: $(hdrdir)/ruby/internal/error.h
+md5.o: $(hdrdir)/ruby/internal/eval.h
+md5.o: $(hdrdir)/ruby/internal/event.h
+md5.o: $(hdrdir)/ruby/internal/fl_type.h
+md5.o: $(hdrdir)/ruby/internal/gc.h
+md5.o: $(hdrdir)/ruby/internal/glob.h
+md5.o: $(hdrdir)/ruby/internal/globals.h
+md5.o: $(hdrdir)/ruby/internal/has/attribute.h
+md5.o: $(hdrdir)/ruby/internal/has/builtin.h
+md5.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+md5.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+md5.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+md5.o: $(hdrdir)/ruby/internal/has/extension.h
+md5.o: $(hdrdir)/ruby/internal/has/feature.h
+md5.o: $(hdrdir)/ruby/internal/has/warning.h
+md5.o: $(hdrdir)/ruby/internal/intern/array.h
+md5.o: $(hdrdir)/ruby/internal/intern/bignum.h
+md5.o: $(hdrdir)/ruby/internal/intern/class.h
+md5.o: $(hdrdir)/ruby/internal/intern/compar.h
+md5.o: $(hdrdir)/ruby/internal/intern/complex.h
+md5.o: $(hdrdir)/ruby/internal/intern/cont.h
+md5.o: $(hdrdir)/ruby/internal/intern/dir.h
+md5.o: $(hdrdir)/ruby/internal/intern/enum.h
+md5.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+md5.o: $(hdrdir)/ruby/internal/intern/error.h
+md5.o: $(hdrdir)/ruby/internal/intern/eval.h
+md5.o: $(hdrdir)/ruby/internal/intern/file.h
+md5.o: $(hdrdir)/ruby/internal/intern/hash.h
+md5.o: $(hdrdir)/ruby/internal/intern/io.h
+md5.o: $(hdrdir)/ruby/internal/intern/load.h
+md5.o: $(hdrdir)/ruby/internal/intern/marshal.h
+md5.o: $(hdrdir)/ruby/internal/intern/numeric.h
+md5.o: $(hdrdir)/ruby/internal/intern/object.h
+md5.o: $(hdrdir)/ruby/internal/intern/parse.h
+md5.o: $(hdrdir)/ruby/internal/intern/proc.h
+md5.o: $(hdrdir)/ruby/internal/intern/process.h
+md5.o: $(hdrdir)/ruby/internal/intern/random.h
+md5.o: $(hdrdir)/ruby/internal/intern/range.h
+md5.o: $(hdrdir)/ruby/internal/intern/rational.h
+md5.o: $(hdrdir)/ruby/internal/intern/re.h
+md5.o: $(hdrdir)/ruby/internal/intern/ruby.h
+md5.o: $(hdrdir)/ruby/internal/intern/select.h
+md5.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+md5.o: $(hdrdir)/ruby/internal/intern/set.h
+md5.o: $(hdrdir)/ruby/internal/intern/signal.h
+md5.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+md5.o: $(hdrdir)/ruby/internal/intern/string.h
+md5.o: $(hdrdir)/ruby/internal/intern/struct.h
+md5.o: $(hdrdir)/ruby/internal/intern/thread.h
+md5.o: $(hdrdir)/ruby/internal/intern/time.h
+md5.o: $(hdrdir)/ruby/internal/intern/variable.h
+md5.o: $(hdrdir)/ruby/internal/intern/vm.h
+md5.o: $(hdrdir)/ruby/internal/interpreter.h
+md5.o: $(hdrdir)/ruby/internal/iterator.h
+md5.o: $(hdrdir)/ruby/internal/memory.h
+md5.o: $(hdrdir)/ruby/internal/method.h
+md5.o: $(hdrdir)/ruby/internal/module.h
+md5.o: $(hdrdir)/ruby/internal/newobj.h
+md5.o: $(hdrdir)/ruby/internal/scan_args.h
+md5.o: $(hdrdir)/ruby/internal/special_consts.h
+md5.o: $(hdrdir)/ruby/internal/static_assert.h
+md5.o: $(hdrdir)/ruby/internal/stdalign.h
+md5.o: $(hdrdir)/ruby/internal/stdbool.h
+md5.o: $(hdrdir)/ruby/internal/stdckdint.h
+md5.o: $(hdrdir)/ruby/internal/symbol.h
+md5.o: $(hdrdir)/ruby/internal/value.h
+md5.o: $(hdrdir)/ruby/internal/value_type.h
+md5.o: $(hdrdir)/ruby/internal/variable.h
+md5.o: $(hdrdir)/ruby/internal/warning_push.h
+md5.o: $(hdrdir)/ruby/internal/xmalloc.h
+md5.o: $(hdrdir)/ruby/missing.h
+md5.o: $(hdrdir)/ruby/ruby.h
+md5.o: $(hdrdir)/ruby/st.h
+md5.o: $(hdrdir)/ruby/subst.h
+md5.o: $(srcdir)/../defs.h
+md5.o: md5.c
+md5.o: md5.h
+md5init.o: $(RUBY_EXTCONF_H)
+md5init.o: $(arch_hdrdir)/ruby/config.h
+md5init.o: $(hdrdir)/ruby.h
+md5init.o: $(hdrdir)/ruby/assert.h
+md5init.o: $(hdrdir)/ruby/backward.h
+md5init.o: $(hdrdir)/ruby/backward/2/assume.h
+md5init.o: $(hdrdir)/ruby/backward/2/attributes.h
+md5init.o: $(hdrdir)/ruby/backward/2/bool.h
+md5init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+md5init.o: $(hdrdir)/ruby/backward/2/limits.h
+md5init.o: $(hdrdir)/ruby/backward/2/long_long.h
+md5init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+md5init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+md5init.o: $(hdrdir)/ruby/defines.h
+md5init.o: $(hdrdir)/ruby/intern.h
+md5init.o: $(hdrdir)/ruby/internal/abi.h
+md5init.o: $(hdrdir)/ruby/internal/anyargs.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+md5init.o: $(hdrdir)/ruby/internal/assume.h
+md5init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+md5init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+md5init.o: $(hdrdir)/ruby/internal/attr/cold.h
+md5init.o: $(hdrdir)/ruby/internal/attr/const.h
+md5init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+md5init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+md5init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+md5init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+md5init.o: $(hdrdir)/ruby/internal/attr/error.h
+md5init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+md5init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+md5init.o: $(hdrdir)/ruby/internal/attr/format.h
+md5init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+md5init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+md5init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+md5init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+md5init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+md5init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+md5init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+md5init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+md5init.o: $(hdrdir)/ruby/internal/attr/pure.h
+md5init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+md5init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+md5init.o: $(hdrdir)/ruby/internal/attr/warning.h
+md5init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+md5init.o: $(hdrdir)/ruby/internal/cast.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_since.h
+md5init.o: $(hdrdir)/ruby/internal/config.h
+md5init.o: $(hdrdir)/ruby/internal/constant_p.h
+md5init.o: $(hdrdir)/ruby/internal/core.h
+md5init.o: $(hdrdir)/ruby/internal/core/rarray.h
+md5init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+md5init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+md5init.o: $(hdrdir)/ruby/internal/core/rclass.h
+md5init.o: $(hdrdir)/ruby/internal/core/rdata.h
+md5init.o: $(hdrdir)/ruby/internal/core/rfile.h
+md5init.o: $(hdrdir)/ruby/internal/core/rhash.h
+md5init.o: $(hdrdir)/ruby/internal/core/robject.h
+md5init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+md5init.o: $(hdrdir)/ruby/internal/core/rstring.h
+md5init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+md5init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+md5init.o: $(hdrdir)/ruby/internal/ctype.h
+md5init.o: $(hdrdir)/ruby/internal/dllexport.h
+md5init.o: $(hdrdir)/ruby/internal/dosish.h
+md5init.o: $(hdrdir)/ruby/internal/error.h
+md5init.o: $(hdrdir)/ruby/internal/eval.h
+md5init.o: $(hdrdir)/ruby/internal/event.h
+md5init.o: $(hdrdir)/ruby/internal/fl_type.h
+md5init.o: $(hdrdir)/ruby/internal/gc.h
+md5init.o: $(hdrdir)/ruby/internal/glob.h
+md5init.o: $(hdrdir)/ruby/internal/globals.h
+md5init.o: $(hdrdir)/ruby/internal/has/attribute.h
+md5init.o: $(hdrdir)/ruby/internal/has/builtin.h
+md5init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+md5init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+md5init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+md5init.o: $(hdrdir)/ruby/internal/has/extension.h
+md5init.o: $(hdrdir)/ruby/internal/has/feature.h
+md5init.o: $(hdrdir)/ruby/internal/has/warning.h
+md5init.o: $(hdrdir)/ruby/internal/intern/array.h
+md5init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+md5init.o: $(hdrdir)/ruby/internal/intern/class.h
+md5init.o: $(hdrdir)/ruby/internal/intern/compar.h
+md5init.o: $(hdrdir)/ruby/internal/intern/complex.h
+md5init.o: $(hdrdir)/ruby/internal/intern/cont.h
+md5init.o: $(hdrdir)/ruby/internal/intern/dir.h
+md5init.o: $(hdrdir)/ruby/internal/intern/enum.h
+md5init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+md5init.o: $(hdrdir)/ruby/internal/intern/error.h
+md5init.o: $(hdrdir)/ruby/internal/intern/eval.h
+md5init.o: $(hdrdir)/ruby/internal/intern/file.h
+md5init.o: $(hdrdir)/ruby/internal/intern/hash.h
+md5init.o: $(hdrdir)/ruby/internal/intern/io.h
+md5init.o: $(hdrdir)/ruby/internal/intern/load.h
+md5init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+md5init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+md5init.o: $(hdrdir)/ruby/internal/intern/object.h
+md5init.o: $(hdrdir)/ruby/internal/intern/parse.h
+md5init.o: $(hdrdir)/ruby/internal/intern/proc.h
+md5init.o: $(hdrdir)/ruby/internal/intern/process.h
+md5init.o: $(hdrdir)/ruby/internal/intern/random.h
+md5init.o: $(hdrdir)/ruby/internal/intern/range.h
+md5init.o: $(hdrdir)/ruby/internal/intern/rational.h
+md5init.o: $(hdrdir)/ruby/internal/intern/re.h
+md5init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+md5init.o: $(hdrdir)/ruby/internal/intern/select.h
+md5init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+md5init.o: $(hdrdir)/ruby/internal/intern/set.h
+md5init.o: $(hdrdir)/ruby/internal/intern/signal.h
+md5init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+md5init.o: $(hdrdir)/ruby/internal/intern/string.h
+md5init.o: $(hdrdir)/ruby/internal/intern/struct.h
+md5init.o: $(hdrdir)/ruby/internal/intern/thread.h
+md5init.o: $(hdrdir)/ruby/internal/intern/time.h
+md5init.o: $(hdrdir)/ruby/internal/intern/variable.h
+md5init.o: $(hdrdir)/ruby/internal/intern/vm.h
+md5init.o: $(hdrdir)/ruby/internal/interpreter.h
+md5init.o: $(hdrdir)/ruby/internal/iterator.h
+md5init.o: $(hdrdir)/ruby/internal/memory.h
+md5init.o: $(hdrdir)/ruby/internal/method.h
+md5init.o: $(hdrdir)/ruby/internal/module.h
+md5init.o: $(hdrdir)/ruby/internal/newobj.h
+md5init.o: $(hdrdir)/ruby/internal/scan_args.h
+md5init.o: $(hdrdir)/ruby/internal/special_consts.h
+md5init.o: $(hdrdir)/ruby/internal/static_assert.h
+md5init.o: $(hdrdir)/ruby/internal/stdalign.h
+md5init.o: $(hdrdir)/ruby/internal/stdbool.h
+md5init.o: $(hdrdir)/ruby/internal/stdckdint.h
+md5init.o: $(hdrdir)/ruby/internal/symbol.h
+md5init.o: $(hdrdir)/ruby/internal/value.h
+md5init.o: $(hdrdir)/ruby/internal/value_type.h
+md5init.o: $(hdrdir)/ruby/internal/variable.h
+md5init.o: $(hdrdir)/ruby/internal/warning_push.h
+md5init.o: $(hdrdir)/ruby/internal/xmalloc.h
+md5init.o: $(hdrdir)/ruby/missing.h
+md5init.o: $(hdrdir)/ruby/ruby.h
+md5init.o: $(hdrdir)/ruby/st.h
+md5init.o: $(hdrdir)/ruby/subst.h
+md5init.o: $(srcdir)/../defs.h
+md5init.o: $(srcdir)/../digest.h
+md5init.o: md5.h
+md5init.o: md5cc.h
+md5init.o: md5init.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/md5/extconf.rb b/ext/digest/md5/extconf.rb
index 9819241184..01658e1b60 100644
--- a/ext/digest/md5/extconf.rb
+++ b/ext/digest/md5/extconf.rb
@@ -1,27 +1,17 @@
+# -*- coding: us-ascii -*-
+# frozen_string_literal: false
# $RoughId: extconf.rb,v 1.3 2001/08/14 19:54:51 knu Exp $
# $Id$
require "mkmf"
-
-$defs << "-DHAVE_CONFIG_H"
-$INCFLAGS << " -I$(srcdir)/.."
+require File.expand_path("../../digest_conf", __FILE__)
$objs = [ "md5init.#{$OBJEXT}" ]
-dir_config("openssl")
-
-if !with_config("bundled-md5") &&
- have_library("crypto") && have_header("openssl/md5.h")
- $objs << "md5ossl.#{$OBJEXT}"
-
-else
- $objs << "md5.#{$OBJEXT}"
-end
+digest_conf("md5")
have_header("sys/cdefs.h")
-have_header("inttypes.h")
-
-have_header("unistd.h")
+$preload = %w[digest]
create_makefile("digest/md5")
diff --git a/ext/digest/md5/md5.c b/ext/digest/md5/md5.c
index 6b61f031c4..3a7fe2cdad 100644
--- a/ext/digest/md5/md5.c
+++ b/ext/digest/md5/md5.c
@@ -41,6 +41,12 @@
1999-05-03 lpd Original version.
*/
+/*
+ This code was modified for use in Ruby.
+
+ - Akinori MUSHA <knu@idaemons.org>
+ */
+
/*$OrigId: md5c.c,v 1.2 2001/03/26 08:57:14 matz Exp $ */
/*$RoughId: md5.c,v 1.2 2001/07/13 19:48:41 knu Exp $ */
/*$Id$ */
@@ -54,7 +60,8 @@
* A.5 of RFC 1321, reproduced below.
*/
#include <string.h>
-main()
+int
+main(void)
{
static const char *const test[7*2] = {
"", "d41d8cd98f00b204e9800998ecf8427e",
@@ -94,7 +101,8 @@ main()
*/
#ifdef COMPUTE_T_VALUES
#include <math.h>
-main()
+int
+main(void)
{
int i;
for (i = 1; i <= 64; ++i) {
@@ -217,7 +225,7 @@ md5_process(MD5_CTX *pms, const uint8_t *data /*[64]*/)
uint32_t xbuf[16];
const uint32_t *X;
- if (!((data - (const uint8_t *)0) & 3)) {
+ if (!(((uintptr_t)data) & 3)) {
/* data are properly aligned */
X = (const uint32_t *)data;
} else {
@@ -342,7 +350,7 @@ md5_process(MD5_CTX *pms, const uint8_t *data /*[64]*/)
pms->state[3] += d;
}
-void
+int
MD5_Init(MD5_CTX *pms)
{
pms->count[0] = pms->count[1] = 0;
@@ -350,6 +358,7 @@ MD5_Init(MD5_CTX *pms)
pms->state[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
pms->state[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
pms->state[3] = 0x10325476;
+ return 1;
}
void
@@ -360,7 +369,7 @@ MD5_Update(MD5_CTX *pms, const uint8_t *data, size_t nbytes)
size_t offset = (pms->count[0] >> 3) & 63;
uint32_t nbits = (uint32_t)(nbytes << 3);
- if (nbytes <= 0)
+ if (nbytes == 0)
return;
/* Update the message length. */
@@ -390,8 +399,8 @@ MD5_Update(MD5_CTX *pms, const uint8_t *data, size_t nbytes)
memcpy(pms->buffer, p, left);
}
-void
-MD5_Final(uint8_t *digest, MD5_CTX *pms)
+int
+MD5_Finish(MD5_CTX *pms, uint8_t *digest)
{
static const uint8_t pad[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -411,22 +420,5 @@ MD5_Final(uint8_t *digest, MD5_CTX *pms)
MD5_Update(pms, data, 8);
for (i = 0; i < 16; ++i)
digest[i] = (uint8_t)(pms->state[i >> 2] >> ((i & 3) << 3));
-}
-
-void
-MD5_End(MD5_CTX *pctx, uint8_t *hexdigest)
-{
- unsigned char digest[16];
- size_t i;
-
- MD5_Final(digest, pctx);
-
- for (i = 0; i < 16; i++)
- sprintf(hexdigest + i * 2, "%02x", digest[i]);
-}
-
-int MD5_Equal(MD5_CTX* pctx1, MD5_CTX* pctx2) {
- return memcmp(pctx1->count, pctx2->count, sizeof(pctx1->count)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
+ return 1;
}
diff --git a/ext/digest/md5/md5.h b/ext/digest/md5/md5.h
index fc41380d38..1b3383c5ee 100644
--- a/ext/digest/md5/md5.h
+++ b/ext/digest/md5/md5.h
@@ -46,7 +46,7 @@
#ifndef MD5_INCLUDED
# define MD5_INCLUDED
-#include "defs.h"
+#include "../defs.h"
/*
* This code has some adaptations for the Ghostscript environment, but it
@@ -63,18 +63,15 @@ typedef struct md5_state_s {
} MD5_CTX;
#ifdef RUBY
+/* avoid name clash */
#define MD5_Init rb_Digest_MD5_Init
#define MD5_Update rb_Digest_MD5_Update
-#define MD5_Final rb_Digest_MD5_Final
-#define MD5_End rb_Digest_MD5_End
-#define MD5_Equal rb_Digest_MD5_Equal
+#define MD5_Finish rb_Digest_MD5_Finish
#endif
-void MD5_Init _((MD5_CTX *pms));
+int MD5_Init _((MD5_CTX *pms));
void MD5_Update _((MD5_CTX *pms, const uint8_t *data, size_t nbytes));
-void MD5_Final _((uint8_t *digest, MD5_CTX *pms));
-void MD5_End _((MD5_CTX *pctx, uint8_t *hexdigest));
-int MD5_Equal _((MD5_CTX *pctx1, MD5_CTX *pctx2));
+int MD5_Finish _((MD5_CTX *pms, uint8_t *digest));
#define MD5_BLOCK_LENGTH 64
#define MD5_DIGEST_LENGTH 16
diff --git a/ext/digest/md5/md5cc.h b/ext/digest/md5/md5cc.h
new file mode 100644
index 0000000000..a002c17604
--- /dev/null
+++ b/ext/digest/md5/md5cc.h
@@ -0,0 +1,27 @@
+#define COMMON_DIGEST_FOR_OPENSSL 1
+#include <CommonCrypto/CommonDigest.h>
+
+#ifdef __GNUC__
+RB_DIGEST_WARNING_IGNORED(-Wdeprecated-declarations)
+/* Suppress deprecation warnings of MD5 from Xcode 11.1 */
+/* Although we know MD5 is deprecated too, provide just for backward
+ * compatibility, as well as Apple does. */
+#endif
+
+#define MD5_BLOCK_LENGTH CC_MD5_BLOCK_BYTES
+
+static DEFINE_UPDATE_FUNC_FOR_UINT(MD5)
+static DEFINE_FINISH_FUNC_FROM_FINAL(MD5)
+
+#undef MD5_Update
+#undef MD5_Finish
+#define MD5_Update rb_digest_MD5_update
+#define MD5_Finish rb_digest_MD5_finish
+
+/*
+ * Pre-10.6 defines are with args, which don't match the argless use in
+ * the function pointer inits. Thus, we redefine MD5_Init as well.
+ * This is a NOP on 10.6+.
+ */
+#undef MD5_Init
+#define MD5_Init CC_MD5_Init
diff --git a/ext/digest/md5/md5init.c b/ext/digest/md5/md5init.c
index 2acca16a46..c919060587 100644
--- a/ext/digest/md5/md5init.c
+++ b/ext/digest/md5/md5init.c
@@ -1,35 +1,61 @@
/* $RoughId: md5init.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
/* $Id$ */
-#include "digest.h"
-#if defined(HAVE_OPENSSL_MD5_H)
-#include "md5ossl.h"
+#include <ruby/ruby.h>
+#include "../digest.h"
+#include "../defs.h"
+#if defined(MD5_USE_COMMONDIGEST)
+#include "md5cc.h"
#else
#include "md5.h"
#endif
-static algo_t md5 = {
+static const rb_digest_metadata_t md5 = {
+ RUBY_DIGEST_API_VERSION,
MD5_DIGEST_LENGTH,
+ MD5_BLOCK_LENGTH,
sizeof(MD5_CTX),
- (hash_init_func_t)MD5_Init,
- (hash_update_func_t)MD5_Update,
- (hash_end_func_t)MD5_End,
- (hash_final_func_t)MD5_Final,
- (hash_equal_func_t)MD5_Equal,
+ (rb_digest_hash_init_func_t)MD5_Init,
+ (rb_digest_hash_update_func_t)MD5_Update,
+ (rb_digest_hash_finish_func_t)MD5_Finish,
};
+/*
+ * Document-class: Digest::MD5 < Digest::Base
+ * A class for calculating message digests using the MD5
+ * Message-Digest Algorithm by RSA Data Security, Inc., described in
+ * RFC1321.
+ *
+ * MD5 calculates a digest of 128 bits (16 bytes).
+ *
+ * == Examples
+ * require 'digest'
+ *
+ * # Compute a complete digest
+ * Digest::MD5.hexdigest 'abc' #=> "90015098..."
+ *
+ * # Compute digest by chunks
+ * md5 = Digest::MD5.new # =>#<Digest::MD5>
+ * md5.update "ab"
+ * md5 << "c" # alias for #update
+ * md5.hexdigest # => "90015098..."
+ *
+ * # Use the same object to compute another digest
+ * md5.reset
+ * md5 << "message"
+ * md5.hexdigest # => "78e73102..."
+ */
void
-Init_md5()
+Init_md5(void)
{
VALUE mDigest, cDigest_Base, cDigest_MD5;
- rb_require("digest.so");
-
- mDigest = rb_path2class("Digest");
- cDigest_Base = rb_path2class("Digest::Base");
+#if 0
+ mDigest = rb_define_module("Digest"); /* let rdoc know */
+#endif
+ mDigest = rb_digest_namespace();
+ cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base"));
cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base);
-
- rb_cvar_set(cDigest_MD5, rb_intern("metadata"),
- Data_Wrap_Struct(rb_cObject, 0, 0, &md5), Qtrue);
+ rb_iv_set(cDigest_MD5, "metadata", rb_digest_make_metadata(&md5));
}
diff --git a/ext/digest/md5/md5ossl.c b/ext/digest/md5/md5ossl.c
deleted file mode 100644
index d930c7ab51..0000000000
--- a/ext/digest/md5/md5ossl.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* $Id$ */
-
-#include "md5ossl.h"
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
-
-void
-MD5_End(MD5_CTX *pctx, unsigned char *hexdigest)
-{
- unsigned char digest[16];
- size_t i;
-
- MD5_Final(digest, pctx);
-
- for (i = 0; i < 16; i++)
- sprintf(hexdigest + i * 2, "%02x", digest[i]);
-}
-
-int
-MD5_Equal(MD5_CTX* pctx1, MD5_CTX* pctx2) {
- return pctx1->num == pctx2->num
- && pctx1->A == pctx2->A
- && pctx1->B == pctx2->B
- && pctx1->C == pctx2->C
- && pctx1->D == pctx2->D
- && pctx1->Nl == pctx2->Nl
- && pctx1->Nh == pctx2->Nh
- && memcmp(pctx1->data, pctx2->data, sizeof(pctx1->data)) == 0;
-}
diff --git a/ext/digest/md5/md5ossl.h b/ext/digest/md5/md5ossl.h
deleted file mode 100644
index 610f58db06..0000000000
--- a/ext/digest/md5/md5ossl.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* $Id$ */
-
-#ifndef MD5OSSL_H_INCLUDED
-#define MD5OSSL_H_INCLUDED
-
-#include <stddef.h>
-#include <openssl/md5.h>
-
-void MD5_End(MD5_CTX *pctx, unsigned char *hexdigest);
-int MD5_Equal(MD5_CTX *pctx1, MD5_CTX *pctx2);
-
-#endif
diff --git a/ext/digest/rmd160/.cvsignore b/ext/digest/rmd160/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/digest/rmd160/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/digest/rmd160/depend b/ext/digest/rmd160/depend
index 0ca79c5f40..aec484f7b3 100644
--- a/ext/digest/rmd160/depend
+++ b/ext/digest/rmd160/depend
@@ -1,8 +1,332 @@
-rmd160.o: rmd160.c rmd160.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
-rmd160hl.o: rmd160hl.c rmd160.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
-rmd160init.o: rmd160init.c $(srcdir)/../digest.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h \
- rmd160.h $(srcdir)/../defs.h
-rmd160ossl.o: rmd160ossl.h $(srcdir)/../defs.h
+rmd160.o: rmd160.c rmd160.h $(srcdir)/../defs.h
+rmd160init.o: $(LOCAL_HDRS)
+
+# AUTOGENERATED DEPENDENCIES START
+rmd160.o: $(RUBY_EXTCONF_H)
+rmd160.o: $(arch_hdrdir)/ruby/config.h
+rmd160.o: $(hdrdir)/ruby.h
+rmd160.o: $(hdrdir)/ruby/assert.h
+rmd160.o: $(hdrdir)/ruby/backward.h
+rmd160.o: $(hdrdir)/ruby/backward/2/assume.h
+rmd160.o: $(hdrdir)/ruby/backward/2/attributes.h
+rmd160.o: $(hdrdir)/ruby/backward/2/bool.h
+rmd160.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rmd160.o: $(hdrdir)/ruby/backward/2/limits.h
+rmd160.o: $(hdrdir)/ruby/backward/2/long_long.h
+rmd160.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rmd160.o: $(hdrdir)/ruby/backward/2/stdarg.h
+rmd160.o: $(hdrdir)/ruby/defines.h
+rmd160.o: $(hdrdir)/ruby/intern.h
+rmd160.o: $(hdrdir)/ruby/internal/abi.h
+rmd160.o: $(hdrdir)/ruby/internal/anyargs.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rmd160.o: $(hdrdir)/ruby/internal/assume.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/cold.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/const.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/error.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/format.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/pure.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/warning.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rmd160.o: $(hdrdir)/ruby/internal/cast.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_since.h
+rmd160.o: $(hdrdir)/ruby/internal/config.h
+rmd160.o: $(hdrdir)/ruby/internal/constant_p.h
+rmd160.o: $(hdrdir)/ruby/internal/core.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rarray.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rclass.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rdata.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rfile.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rhash.h
+rmd160.o: $(hdrdir)/ruby/internal/core/robject.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rstring.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rmd160.o: $(hdrdir)/ruby/internal/ctype.h
+rmd160.o: $(hdrdir)/ruby/internal/dllexport.h
+rmd160.o: $(hdrdir)/ruby/internal/dosish.h
+rmd160.o: $(hdrdir)/ruby/internal/error.h
+rmd160.o: $(hdrdir)/ruby/internal/eval.h
+rmd160.o: $(hdrdir)/ruby/internal/event.h
+rmd160.o: $(hdrdir)/ruby/internal/fl_type.h
+rmd160.o: $(hdrdir)/ruby/internal/gc.h
+rmd160.o: $(hdrdir)/ruby/internal/glob.h
+rmd160.o: $(hdrdir)/ruby/internal/globals.h
+rmd160.o: $(hdrdir)/ruby/internal/has/attribute.h
+rmd160.o: $(hdrdir)/ruby/internal/has/builtin.h
+rmd160.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rmd160.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rmd160.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rmd160.o: $(hdrdir)/ruby/internal/has/extension.h
+rmd160.o: $(hdrdir)/ruby/internal/has/feature.h
+rmd160.o: $(hdrdir)/ruby/internal/has/warning.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/array.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/class.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/compar.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/complex.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/cont.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/dir.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/enum.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/error.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/eval.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/file.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/hash.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/io.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/load.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/object.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/parse.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/proc.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/process.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/random.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/range.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/rational.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/re.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/select.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/set.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/signal.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/string.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/struct.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/thread.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/time.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/variable.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/vm.h
+rmd160.o: $(hdrdir)/ruby/internal/interpreter.h
+rmd160.o: $(hdrdir)/ruby/internal/iterator.h
+rmd160.o: $(hdrdir)/ruby/internal/memory.h
+rmd160.o: $(hdrdir)/ruby/internal/method.h
+rmd160.o: $(hdrdir)/ruby/internal/module.h
+rmd160.o: $(hdrdir)/ruby/internal/newobj.h
+rmd160.o: $(hdrdir)/ruby/internal/scan_args.h
+rmd160.o: $(hdrdir)/ruby/internal/special_consts.h
+rmd160.o: $(hdrdir)/ruby/internal/static_assert.h
+rmd160.o: $(hdrdir)/ruby/internal/stdalign.h
+rmd160.o: $(hdrdir)/ruby/internal/stdbool.h
+rmd160.o: $(hdrdir)/ruby/internal/stdckdint.h
+rmd160.o: $(hdrdir)/ruby/internal/symbol.h
+rmd160.o: $(hdrdir)/ruby/internal/value.h
+rmd160.o: $(hdrdir)/ruby/internal/value_type.h
+rmd160.o: $(hdrdir)/ruby/internal/variable.h
+rmd160.o: $(hdrdir)/ruby/internal/warning_push.h
+rmd160.o: $(hdrdir)/ruby/internal/xmalloc.h
+rmd160.o: $(hdrdir)/ruby/missing.h
+rmd160.o: $(hdrdir)/ruby/ruby.h
+rmd160.o: $(hdrdir)/ruby/st.h
+rmd160.o: $(hdrdir)/ruby/subst.h
+rmd160.o: $(srcdir)/../defs.h
+rmd160.o: rmd160.c
+rmd160.o: rmd160.h
+rmd160init.o: $(RUBY_EXTCONF_H)
+rmd160init.o: $(arch_hdrdir)/ruby/config.h
+rmd160init.o: $(hdrdir)/ruby.h
+rmd160init.o: $(hdrdir)/ruby/assert.h
+rmd160init.o: $(hdrdir)/ruby/backward.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/assume.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/attributes.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/bool.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/limits.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/long_long.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+rmd160init.o: $(hdrdir)/ruby/defines.h
+rmd160init.o: $(hdrdir)/ruby/intern.h
+rmd160init.o: $(hdrdir)/ruby/internal/abi.h
+rmd160init.o: $(hdrdir)/ruby/internal/anyargs.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/assume.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/cold.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/const.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/error.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/format.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/pure.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/warning.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rmd160init.o: $(hdrdir)/ruby/internal/cast.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_since.h
+rmd160init.o: $(hdrdir)/ruby/internal/config.h
+rmd160init.o: $(hdrdir)/ruby/internal/constant_p.h
+rmd160init.o: $(hdrdir)/ruby/internal/core.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rarray.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rclass.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rdata.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rfile.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rhash.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/robject.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rstring.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rmd160init.o: $(hdrdir)/ruby/internal/ctype.h
+rmd160init.o: $(hdrdir)/ruby/internal/dllexport.h
+rmd160init.o: $(hdrdir)/ruby/internal/dosish.h
+rmd160init.o: $(hdrdir)/ruby/internal/error.h
+rmd160init.o: $(hdrdir)/ruby/internal/eval.h
+rmd160init.o: $(hdrdir)/ruby/internal/event.h
+rmd160init.o: $(hdrdir)/ruby/internal/fl_type.h
+rmd160init.o: $(hdrdir)/ruby/internal/gc.h
+rmd160init.o: $(hdrdir)/ruby/internal/glob.h
+rmd160init.o: $(hdrdir)/ruby/internal/globals.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/attribute.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/builtin.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/extension.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/feature.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/warning.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/array.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/class.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/compar.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/complex.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/cont.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/dir.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/enum.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/error.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/eval.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/file.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/hash.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/io.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/load.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/object.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/parse.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/proc.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/process.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/random.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/range.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/rational.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/re.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/select.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/set.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/signal.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/string.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/struct.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/thread.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/time.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/variable.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/vm.h
+rmd160init.o: $(hdrdir)/ruby/internal/interpreter.h
+rmd160init.o: $(hdrdir)/ruby/internal/iterator.h
+rmd160init.o: $(hdrdir)/ruby/internal/memory.h
+rmd160init.o: $(hdrdir)/ruby/internal/method.h
+rmd160init.o: $(hdrdir)/ruby/internal/module.h
+rmd160init.o: $(hdrdir)/ruby/internal/newobj.h
+rmd160init.o: $(hdrdir)/ruby/internal/scan_args.h
+rmd160init.o: $(hdrdir)/ruby/internal/special_consts.h
+rmd160init.o: $(hdrdir)/ruby/internal/static_assert.h
+rmd160init.o: $(hdrdir)/ruby/internal/stdalign.h
+rmd160init.o: $(hdrdir)/ruby/internal/stdbool.h
+rmd160init.o: $(hdrdir)/ruby/internal/stdckdint.h
+rmd160init.o: $(hdrdir)/ruby/internal/symbol.h
+rmd160init.o: $(hdrdir)/ruby/internal/value.h
+rmd160init.o: $(hdrdir)/ruby/internal/value_type.h
+rmd160init.o: $(hdrdir)/ruby/internal/variable.h
+rmd160init.o: $(hdrdir)/ruby/internal/warning_push.h
+rmd160init.o: $(hdrdir)/ruby/internal/xmalloc.h
+rmd160init.o: $(hdrdir)/ruby/missing.h
+rmd160init.o: $(hdrdir)/ruby/ruby.h
+rmd160init.o: $(hdrdir)/ruby/st.h
+rmd160init.o: $(hdrdir)/ruby/subst.h
+rmd160init.o: $(srcdir)/../defs.h
+rmd160init.o: $(srcdir)/../digest.h
+rmd160init.o: rmd160.h
+rmd160init.o: rmd160init.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/rmd160/extconf.rb b/ext/digest/rmd160/extconf.rb
index 9358dbd09e..8b894da0c8 100644
--- a/ext/digest/rmd160/extconf.rb
+++ b/ext/digest/rmd160/extconf.rb
@@ -1,26 +1,21 @@
+# -*- coding: us-ascii -*-
+# frozen_string_literal: false
# $RoughId: extconf.rb,v 1.3 2001/08/14 19:54:51 knu Exp $
# $Id$
require "mkmf"
+require File.expand_path("../../digest_conf", __FILE__)
-$defs << "-DNDEBUG" << "-DHAVE_CONFIG_H"
-$INCFLAGS << " -I$(srcdir)/.."
+if try_static_assert("RUBY_API_VERSION_MAJOR < 3", "ruby/version.h")
+ $defs << "-DNDEBUG"
+end
$objs = [ "rmd160init.#{$OBJEXT}" ]
-dir_config("openssl")
-
-if !with_config("bundled-rmd160") &&
- have_library("crypto") && have_header("openssl/ripemd.h")
- $objs << "rmd160ossl.#{$OBJEXT}"
-else
- $objs << "rmd160.#{$OBJEXT}" << "rmd160hl.#{$OBJEXT}"
-end
+digest_conf("rmd160")
have_header("sys/cdefs.h")
-have_header("inttypes.h")
-
-have_header("unistd.h")
+$preload = %w[digest]
create_makefile("digest/rmd160")
diff --git a/ext/digest/rmd160/rmd160.c b/ext/digest/rmd160/rmd160.c
index 2de3c99b29..058d004f3a 100644
--- a/ext/digest/rmd160/rmd160.c
+++ b/ext/digest/rmd160/rmd160.c
@@ -124,7 +124,7 @@
/********************************************************************/
-void
+int
RMD160_Init(RMD160_CTX *context)
{
@@ -138,6 +138,7 @@ RMD160_Init(RMD160_CTX *context)
context->state[4] = 0xc3d2e1f0U;
context->length[0] = context->length[1] = 0;
context->buflen = 0;
+ return 1;
}
/********************************************************************/
@@ -362,16 +363,20 @@ RMD160_Update(RMD160_CTX *context, const uint8_t *data, size_t nbytes)
_DIAGASSERT(data != NULL);
/* update length[] */
+#if SIZEOF_SIZE_T * CHAR_BIT > 32
+ context->length[1] += (uint32_t)((context->length[0] + nbytes) >> 32);
+#else
if (context->length[0] + nbytes < context->length[0])
context->length[1]++; /* overflow to msb of length */
- context->length[0] += nbytes;
+#endif
+ context->length[0] += (uint32_t)nbytes;
(void)memset(X, 0, sizeof(X));
if ( context->buflen + nbytes < 64 )
{
(void)memcpy(context->bbuffer + context->buflen, data, nbytes);
- context->buflen += nbytes;
+ context->buflen += (uint32_t)nbytes;
}
else
{
@@ -401,15 +406,15 @@ RMD160_Update(RMD160_CTX *context, const uint8_t *data, size_t nbytes)
/*
* Put last bytes from data into context's buffer
*/
- context->buflen = nbytes & 63;
+ context->buflen = (uint32_t)nbytes & 63;
memcpy(context->bbuffer, data + (64 * i) + ofs, context->buflen);
}
}
/********************************************************************/
-void
-RMD160_Final(uint8_t digest[20], RMD160_CTX *context)
+int
+RMD160_Finish(RMD160_CTX *context, uint8_t digest[20])
{
uint32_t i;
uint32_t X[16];
@@ -452,13 +457,7 @@ RMD160_Final(uint8_t digest[20], RMD160_CTX *context)
digest[i + 3] = (context->state[i>>2] >> 24);
}
}
-}
-
-int RMD160_Equal(RMD160_CTX* pctx1, RMD160_CTX* pctx2) {
- return pctx1->buflen == pctx2->buflen
- && memcmp(pctx1->length, pctx2->length, sizeof(pctx1->length)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->bbuffer, pctx2->bbuffer, sizeof(pctx1->bbuffer)) == 0;
+ return 1;
}
/************************ end of file rmd160.c **********************/
diff --git a/ext/digest/rmd160/rmd160.h b/ext/digest/rmd160/rmd160.h
index 24f9a025f0..6324709d96 100644
--- a/ext/digest/rmd160/rmd160.h
+++ b/ext/digest/rmd160/rmd160.h
@@ -7,7 +7,7 @@
* FILE: rmd160.h
*
* CONTENTS: Header file for a sample C-implementation of the
- * RIPEMD-160 hash-function.
+ * RIPEMD-160 hash-function.
* TARGET: any computer with an ANSI C compiler
*
* AUTHOR: Antoon Bosselaers, ESAT-COSIC
@@ -26,7 +26,7 @@
#ifndef _RMD160_H_
#define _RMD160_H_
-#include "defs.h"
+#include "../defs.h"
typedef struct {
uint32_t state[5]; /* state (ABCDE) */
@@ -39,26 +39,14 @@ typedef struct {
#define RMD160_Init rb_Digest_RMD160_Init
#define RMD160_Transform rb_Digest_RMD160_Transform
#define RMD160_Update rb_Digest_RMD160_Update
-#define RMD160_Final rb_Digest_RMD160_Final
-#define RMD160_Equal rb_Digest_RMD160_Equal
-#ifndef _KERNEL
-#define RMD160_End rb_Digest_RMD160_End
-#define RMD160_File rb_Digest_RMD160_File
-#define RMD160_Data rb_Digest_RMD160_Data
-#endif /* _KERNEL */
+#define RMD160_Finish rb_Digest_RMD160_Finish
#endif
__BEGIN_DECLS
-void RMD160_Init _((RMD160_CTX *));
+int RMD160_Init _((RMD160_CTX *));
void RMD160_Transform _((uint32_t[5], const uint32_t[16]));
void RMD160_Update _((RMD160_CTX *, const uint8_t *, size_t));
-void RMD160_Final _((uint8_t[20], RMD160_CTX *));
-int RMD160_Equal _((RMD160_CTX *, RMD160_CTX *));
-#ifndef _KERNEL
-char *RMD160_End _((RMD160_CTX *, char *));
-char *RMD160_File _((char *, char *));
-char *RMD160_Data _((const uint8_t *, size_t, char *));
-#endif /* _KERNEL */
+int RMD160_Finish _((RMD160_CTX *, uint8_t[20]));
__END_DECLS
#define RMD160_BLOCK_LENGTH 64
diff --git a/ext/digest/rmd160/rmd160hl.c b/ext/digest/rmd160/rmd160hl.c
deleted file mode 100644
index 4c5e0217d9..0000000000
--- a/ext/digest/rmd160/rmd160hl.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* $NetBSD: rmd160hl.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $ */
-/* $RoughId: rmd160hl.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id$ */
-
-/* rmd160hl.c
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@login.dkuug.dk> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- *
- * from OpenBSD: rmd160hl.c,v 1.2 1999/08/17 09:13:12 millert Exp $
- */
-
-#include "rmd160.h"
-
-#ifndef lint
-/* __RCSID("$NetBSD: rmd160hl.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $"); */
-#endif /* not lint */
-
-/* #include "namespace.h" */
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-
-char *
-RMD160_End(RMD160_CTX *ctx, char *buf)
-{
- size_t i;
- char *p = buf;
- uint8_t digest[20];
- static const char hex[]="0123456789abcdef";
-
- _DIAGASSERT(ctx != NULL);
- /* buf may be NULL */
-
- if (p == NULL && (p = malloc(41)) == NULL)
- return 0;
-
- RMD160_Final(digest,ctx);
- for (i = 0; i < 20; i++) {
- p[i + i] = hex[(uint32_t)digest[i] >> 4];
- p[i + i + 1] = hex[digest[i] & 0x0f];
- }
- p[i + i] = '\0';
- return(p);
-}
-
-char *
-RMD160_File(char *filename, char *buf)
-{
- uint8_t buffer[BUFSIZ];
- RMD160_CTX ctx;
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- RMD160_Init(&ctx);
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- return(0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- RMD160_Update(&ctx, buffer, (size_t)num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return(num < 0 ? 0 : RMD160_End(&ctx, buf));
-}
-
-char *
-RMD160_Data(const uint8_t *data, size_t len, char *buf)
-{
- RMD160_CTX ctx;
-
- _DIAGASSERT(data != NULL);
- /* XXX: buf may be NULL ? */
-
- RMD160_Init(&ctx);
- RMD160_Update(&ctx, data, len);
- return(RMD160_End(&ctx, buf));
-}
diff --git a/ext/digest/rmd160/rmd160init.c b/ext/digest/rmd160/rmd160init.c
index b16cdbbed8..e4b707ed9e 100644
--- a/ext/digest/rmd160/rmd160init.c
+++ b/ext/digest/rmd160/rmd160init.c
@@ -1,38 +1,56 @@
/* $RoughId: rmd160init.c,v 1.3 2001/07/13 20:00:43 knu Exp $ */
/* $Id$ */
-#include "digest.h"
-#if defined(HAVE_OPENSSL_RIPEMD_H)
-#include "rmd160ossl.h"
-#else
+#include <ruby/ruby.h>
+#include "../digest.h"
#include "rmd160.h"
-#endif
-static algo_t rmd160 = {
+static const rb_digest_metadata_t rmd160 = {
+ RUBY_DIGEST_API_VERSION,
RMD160_DIGEST_LENGTH,
+ RMD160_BLOCK_LENGTH,
sizeof(RMD160_CTX),
- (hash_init_func_t)RMD160_Init,
- (hash_update_func_t)RMD160_Update,
- (hash_end_func_t)RMD160_End,
- (hash_final_func_t)RMD160_Final,
- (hash_equal_func_t)RMD160_Equal,
+ (rb_digest_hash_init_func_t)RMD160_Init,
+ (rb_digest_hash_update_func_t)RMD160_Update,
+ (rb_digest_hash_finish_func_t)RMD160_Finish,
};
+/*
+ * Document-class: Digest::RMD160 < Digest::Base
+ * A class for calculating message digests using RIPEMD-160
+ * cryptographic hash function, designed by Hans Dobbertin, Antoon
+ * Bosselaers, and Bart Preneel.
+ *
+ * RMD160 calculates a digest of 160 bits (20 bytes).
+ *
+ * == Examples
+ * require 'digest'
+ *
+ * # Compute a complete digest
+ * Digest::RMD160.hexdigest 'abc' #=> "8eb208f7..."
+ *
+ * # Compute digest by chunks
+ * rmd160 = Digest::RMD160.new # =>#<Digest::RMD160>
+ * rmd160.update "ab"
+ * rmd160 << "c" # alias for #update
+ * rmd160.hexdigest # => "8eb208f7..."
+ *
+ * # Use the same object to compute another digest
+ * rmd160.reset
+ * rmd160 << "message"
+ * rmd160.hexdigest # => "1dddbe1b..."
+ */
void
-Init_rmd160()
+Init_rmd160(void)
{
VALUE mDigest, cDigest_Base, cDigest_RMD160;
- ID id_metadata;
-
- rb_require("digest.so");
- mDigest = rb_path2class("Digest");
- cDigest_Base = rb_path2class("Digest::Base");
+#if 0
+ mDigest = rb_define_module("Digest"); /* let rdoc know */
+#endif
+ mDigest = rb_digest_namespace();
+ cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base"));
cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base);
-
- id_metadata = rb_intern("metadata");
-
- rb_cvar_set(cDigest_RMD160, id_metadata,
- Data_Wrap_Struct(rb_cObject, 0, 0, &rmd160), Qtrue);
+ rb_iv_set(cDigest_RMD160, "metadata", rb_digest_make_metadata(&rmd160));
}
diff --git a/ext/digest/rmd160/rmd160ossl.c b/ext/digest/rmd160/rmd160ossl.c
deleted file mode 100644
index 2989ffd00e..0000000000
--- a/ext/digest/rmd160/rmd160ossl.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* $Id$ */
-
-#include "defs.h"
-#include "rmd160ossl.h"
-#include <assert.h>
-#include <stdlib.h>
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-char *
-RMD160_End(RMD160_CTX *ctx, char *buf)
-{
- size_t i;
- char *p = buf;
- uint8_t digest[20];
- static const char hex[]="0123456789abcdef";
-
- _DIAGASSERT(ctx != NULL);
- /* buf may be NULL */
-
- if (p == NULL && (p = malloc(41)) == NULL)
- return 0;
-
- RMD160_Final(digest,ctx);
- for (i = 0; i < 20; i++) {
- p[i + i] = hex[(uint32_t)digest[i] >> 4];
- p[i + i + 1] = hex[digest[i] & 0x0f];
- }
- p[i + i] = '\0';
- return(p);
-}
-
-int RMD160_Equal(RMD160_CTX* pctx1, RMD160_CTX* pctx2) {
- return pctx1->num == pctx2->num
- && pctx1->A == pctx2->A
- && pctx1->B == pctx2->B
- && pctx1->C == pctx2->C
- && pctx1->D == pctx2->D
- && pctx1->E == pctx2->E
- && pctx1->Nl == pctx2->Nl
- && pctx1->Nh == pctx2->Nh
- && memcmp(pctx1->data, pctx2->data, sizeof(pctx1->data)) == 0;
-}
diff --git a/ext/digest/rmd160/rmd160ossl.h b/ext/digest/rmd160/rmd160ossl.h
deleted file mode 100644
index e8928d164b..0000000000
--- a/ext/digest/rmd160/rmd160ossl.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* $Id$ */
-
-#ifndef RMD160OSSL_H_INCLUDED
-#define RMD160OSSL_H_INCLUDED
-
-#include <stddef.h>
-#include <openssl/ripemd.h>
-
-#define RMD160_CTX RIPEMD160_CTX
-
-#define RMD160_Init RIPEMD160_Init
-#define RMD160_Update RIPEMD160_Update
-#define RMD160_Final RIPEMD160_Final
-
-#define RMD160_BLOCK_LENGTH RIPEMD160_CBLOCK
-#define RMD160_DIGEST_LENGTH RIPEMD160_DIGEST_LENGTH
-
-char *RMD160_End(RMD160_CTX *ctx, char *buf);
-int RMD160_Equal(RMD160_CTX *pctx1, RMD160_CTX *pctx2);
-
-#endif
diff --git a/ext/digest/sha1/.cvsignore b/ext/digest/sha1/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/digest/sha1/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/digest/sha1/depend b/ext/digest/sha1/depend
index a159f456d3..e6bd9d8f73 100644
--- a/ext/digest/sha1/depend
+++ b/ext/digest/sha1/depend
@@ -1,8 +1,333 @@
-sha1.o: sha1.c sha1.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
-sha1hl.o: sha1hl.c sha1.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
-sha1init.o: sha1init.c $(srcdir)/../digest.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h \
- sha1.h $(srcdir)/../defs.h
-sha1ossl.o: sha1ossl.h $(srcdir)/../defs.h
+sha1.o: sha1.c sha1.h $(srcdir)/../defs.h
+sha1init.o: $(LOCAL_HDRS)
+
+# AUTOGENERATED DEPENDENCIES START
+sha1.o: $(RUBY_EXTCONF_H)
+sha1.o: $(arch_hdrdir)/ruby/config.h
+sha1.o: $(hdrdir)/ruby.h
+sha1.o: $(hdrdir)/ruby/assert.h
+sha1.o: $(hdrdir)/ruby/backward.h
+sha1.o: $(hdrdir)/ruby/backward/2/assume.h
+sha1.o: $(hdrdir)/ruby/backward/2/attributes.h
+sha1.o: $(hdrdir)/ruby/backward/2/bool.h
+sha1.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sha1.o: $(hdrdir)/ruby/backward/2/limits.h
+sha1.o: $(hdrdir)/ruby/backward/2/long_long.h
+sha1.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sha1.o: $(hdrdir)/ruby/backward/2/stdarg.h
+sha1.o: $(hdrdir)/ruby/defines.h
+sha1.o: $(hdrdir)/ruby/intern.h
+sha1.o: $(hdrdir)/ruby/internal/abi.h
+sha1.o: $(hdrdir)/ruby/internal/anyargs.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sha1.o: $(hdrdir)/ruby/internal/assume.h
+sha1.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sha1.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sha1.o: $(hdrdir)/ruby/internal/attr/cold.h
+sha1.o: $(hdrdir)/ruby/internal/attr/const.h
+sha1.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sha1.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sha1.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sha1.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sha1.o: $(hdrdir)/ruby/internal/attr/error.h
+sha1.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sha1.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sha1.o: $(hdrdir)/ruby/internal/attr/format.h
+sha1.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sha1.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sha1.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sha1.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sha1.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sha1.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sha1.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sha1.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+sha1.o: $(hdrdir)/ruby/internal/attr/pure.h
+sha1.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sha1.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sha1.o: $(hdrdir)/ruby/internal/attr/warning.h
+sha1.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sha1.o: $(hdrdir)/ruby/internal/cast.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_since.h
+sha1.o: $(hdrdir)/ruby/internal/config.h
+sha1.o: $(hdrdir)/ruby/internal/constant_p.h
+sha1.o: $(hdrdir)/ruby/internal/core.h
+sha1.o: $(hdrdir)/ruby/internal/core/rarray.h
+sha1.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sha1.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sha1.o: $(hdrdir)/ruby/internal/core/rclass.h
+sha1.o: $(hdrdir)/ruby/internal/core/rdata.h
+sha1.o: $(hdrdir)/ruby/internal/core/rfile.h
+sha1.o: $(hdrdir)/ruby/internal/core/rhash.h
+sha1.o: $(hdrdir)/ruby/internal/core/robject.h
+sha1.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sha1.o: $(hdrdir)/ruby/internal/core/rstring.h
+sha1.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sha1.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sha1.o: $(hdrdir)/ruby/internal/ctype.h
+sha1.o: $(hdrdir)/ruby/internal/dllexport.h
+sha1.o: $(hdrdir)/ruby/internal/dosish.h
+sha1.o: $(hdrdir)/ruby/internal/error.h
+sha1.o: $(hdrdir)/ruby/internal/eval.h
+sha1.o: $(hdrdir)/ruby/internal/event.h
+sha1.o: $(hdrdir)/ruby/internal/fl_type.h
+sha1.o: $(hdrdir)/ruby/internal/gc.h
+sha1.o: $(hdrdir)/ruby/internal/glob.h
+sha1.o: $(hdrdir)/ruby/internal/globals.h
+sha1.o: $(hdrdir)/ruby/internal/has/attribute.h
+sha1.o: $(hdrdir)/ruby/internal/has/builtin.h
+sha1.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sha1.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sha1.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sha1.o: $(hdrdir)/ruby/internal/has/extension.h
+sha1.o: $(hdrdir)/ruby/internal/has/feature.h
+sha1.o: $(hdrdir)/ruby/internal/has/warning.h
+sha1.o: $(hdrdir)/ruby/internal/intern/array.h
+sha1.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sha1.o: $(hdrdir)/ruby/internal/intern/class.h
+sha1.o: $(hdrdir)/ruby/internal/intern/compar.h
+sha1.o: $(hdrdir)/ruby/internal/intern/complex.h
+sha1.o: $(hdrdir)/ruby/internal/intern/cont.h
+sha1.o: $(hdrdir)/ruby/internal/intern/dir.h
+sha1.o: $(hdrdir)/ruby/internal/intern/enum.h
+sha1.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sha1.o: $(hdrdir)/ruby/internal/intern/error.h
+sha1.o: $(hdrdir)/ruby/internal/intern/eval.h
+sha1.o: $(hdrdir)/ruby/internal/intern/file.h
+sha1.o: $(hdrdir)/ruby/internal/intern/hash.h
+sha1.o: $(hdrdir)/ruby/internal/intern/io.h
+sha1.o: $(hdrdir)/ruby/internal/intern/load.h
+sha1.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sha1.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sha1.o: $(hdrdir)/ruby/internal/intern/object.h
+sha1.o: $(hdrdir)/ruby/internal/intern/parse.h
+sha1.o: $(hdrdir)/ruby/internal/intern/proc.h
+sha1.o: $(hdrdir)/ruby/internal/intern/process.h
+sha1.o: $(hdrdir)/ruby/internal/intern/random.h
+sha1.o: $(hdrdir)/ruby/internal/intern/range.h
+sha1.o: $(hdrdir)/ruby/internal/intern/rational.h
+sha1.o: $(hdrdir)/ruby/internal/intern/re.h
+sha1.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sha1.o: $(hdrdir)/ruby/internal/intern/select.h
+sha1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sha1.o: $(hdrdir)/ruby/internal/intern/set.h
+sha1.o: $(hdrdir)/ruby/internal/intern/signal.h
+sha1.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sha1.o: $(hdrdir)/ruby/internal/intern/string.h
+sha1.o: $(hdrdir)/ruby/internal/intern/struct.h
+sha1.o: $(hdrdir)/ruby/internal/intern/thread.h
+sha1.o: $(hdrdir)/ruby/internal/intern/time.h
+sha1.o: $(hdrdir)/ruby/internal/intern/variable.h
+sha1.o: $(hdrdir)/ruby/internal/intern/vm.h
+sha1.o: $(hdrdir)/ruby/internal/interpreter.h
+sha1.o: $(hdrdir)/ruby/internal/iterator.h
+sha1.o: $(hdrdir)/ruby/internal/memory.h
+sha1.o: $(hdrdir)/ruby/internal/method.h
+sha1.o: $(hdrdir)/ruby/internal/module.h
+sha1.o: $(hdrdir)/ruby/internal/newobj.h
+sha1.o: $(hdrdir)/ruby/internal/scan_args.h
+sha1.o: $(hdrdir)/ruby/internal/special_consts.h
+sha1.o: $(hdrdir)/ruby/internal/static_assert.h
+sha1.o: $(hdrdir)/ruby/internal/stdalign.h
+sha1.o: $(hdrdir)/ruby/internal/stdbool.h
+sha1.o: $(hdrdir)/ruby/internal/stdckdint.h
+sha1.o: $(hdrdir)/ruby/internal/symbol.h
+sha1.o: $(hdrdir)/ruby/internal/value.h
+sha1.o: $(hdrdir)/ruby/internal/value_type.h
+sha1.o: $(hdrdir)/ruby/internal/variable.h
+sha1.o: $(hdrdir)/ruby/internal/warning_push.h
+sha1.o: $(hdrdir)/ruby/internal/xmalloc.h
+sha1.o: $(hdrdir)/ruby/missing.h
+sha1.o: $(hdrdir)/ruby/ruby.h
+sha1.o: $(hdrdir)/ruby/st.h
+sha1.o: $(hdrdir)/ruby/subst.h
+sha1.o: $(srcdir)/../defs.h
+sha1.o: sha1.c
+sha1.o: sha1.h
+sha1init.o: $(RUBY_EXTCONF_H)
+sha1init.o: $(arch_hdrdir)/ruby/config.h
+sha1init.o: $(hdrdir)/ruby.h
+sha1init.o: $(hdrdir)/ruby/assert.h
+sha1init.o: $(hdrdir)/ruby/backward.h
+sha1init.o: $(hdrdir)/ruby/backward/2/assume.h
+sha1init.o: $(hdrdir)/ruby/backward/2/attributes.h
+sha1init.o: $(hdrdir)/ruby/backward/2/bool.h
+sha1init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sha1init.o: $(hdrdir)/ruby/backward/2/limits.h
+sha1init.o: $(hdrdir)/ruby/backward/2/long_long.h
+sha1init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sha1init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+sha1init.o: $(hdrdir)/ruby/defines.h
+sha1init.o: $(hdrdir)/ruby/intern.h
+sha1init.o: $(hdrdir)/ruby/internal/abi.h
+sha1init.o: $(hdrdir)/ruby/internal/anyargs.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sha1init.o: $(hdrdir)/ruby/internal/assume.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/cold.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/const.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/error.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/format.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/pure.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/warning.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sha1init.o: $(hdrdir)/ruby/internal/cast.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_since.h
+sha1init.o: $(hdrdir)/ruby/internal/config.h
+sha1init.o: $(hdrdir)/ruby/internal/constant_p.h
+sha1init.o: $(hdrdir)/ruby/internal/core.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rarray.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rclass.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rdata.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rfile.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rhash.h
+sha1init.o: $(hdrdir)/ruby/internal/core/robject.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rstring.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sha1init.o: $(hdrdir)/ruby/internal/ctype.h
+sha1init.o: $(hdrdir)/ruby/internal/dllexport.h
+sha1init.o: $(hdrdir)/ruby/internal/dosish.h
+sha1init.o: $(hdrdir)/ruby/internal/error.h
+sha1init.o: $(hdrdir)/ruby/internal/eval.h
+sha1init.o: $(hdrdir)/ruby/internal/event.h
+sha1init.o: $(hdrdir)/ruby/internal/fl_type.h
+sha1init.o: $(hdrdir)/ruby/internal/gc.h
+sha1init.o: $(hdrdir)/ruby/internal/glob.h
+sha1init.o: $(hdrdir)/ruby/internal/globals.h
+sha1init.o: $(hdrdir)/ruby/internal/has/attribute.h
+sha1init.o: $(hdrdir)/ruby/internal/has/builtin.h
+sha1init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sha1init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sha1init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sha1init.o: $(hdrdir)/ruby/internal/has/extension.h
+sha1init.o: $(hdrdir)/ruby/internal/has/feature.h
+sha1init.o: $(hdrdir)/ruby/internal/has/warning.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/array.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/class.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/compar.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/complex.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/cont.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/dir.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/enum.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/error.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/eval.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/file.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/hash.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/io.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/load.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/object.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/parse.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/proc.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/process.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/random.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/range.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/rational.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/re.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/select.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/set.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/signal.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/string.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/struct.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/thread.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/time.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/variable.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/vm.h
+sha1init.o: $(hdrdir)/ruby/internal/interpreter.h
+sha1init.o: $(hdrdir)/ruby/internal/iterator.h
+sha1init.o: $(hdrdir)/ruby/internal/memory.h
+sha1init.o: $(hdrdir)/ruby/internal/method.h
+sha1init.o: $(hdrdir)/ruby/internal/module.h
+sha1init.o: $(hdrdir)/ruby/internal/newobj.h
+sha1init.o: $(hdrdir)/ruby/internal/scan_args.h
+sha1init.o: $(hdrdir)/ruby/internal/special_consts.h
+sha1init.o: $(hdrdir)/ruby/internal/static_assert.h
+sha1init.o: $(hdrdir)/ruby/internal/stdalign.h
+sha1init.o: $(hdrdir)/ruby/internal/stdbool.h
+sha1init.o: $(hdrdir)/ruby/internal/stdckdint.h
+sha1init.o: $(hdrdir)/ruby/internal/symbol.h
+sha1init.o: $(hdrdir)/ruby/internal/value.h
+sha1init.o: $(hdrdir)/ruby/internal/value_type.h
+sha1init.o: $(hdrdir)/ruby/internal/variable.h
+sha1init.o: $(hdrdir)/ruby/internal/warning_push.h
+sha1init.o: $(hdrdir)/ruby/internal/xmalloc.h
+sha1init.o: $(hdrdir)/ruby/missing.h
+sha1init.o: $(hdrdir)/ruby/ruby.h
+sha1init.o: $(hdrdir)/ruby/st.h
+sha1init.o: $(hdrdir)/ruby/subst.h
+sha1init.o: $(srcdir)/../defs.h
+sha1init.o: $(srcdir)/../digest.h
+sha1init.o: sha1.h
+sha1init.o: sha1cc.h
+sha1init.o: sha1init.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/sha1/extconf.rb b/ext/digest/sha1/extconf.rb
index b93ac593ac..7582cd9ab5 100644
--- a/ext/digest/sha1/extconf.rb
+++ b/ext/digest/sha1/extconf.rb
@@ -1,26 +1,17 @@
+# -*- coding: us-ascii -*-
+# frozen_string_literal: false
# $RoughId: extconf.rb,v 1.3 2001/08/14 19:54:51 knu Exp $
# $Id$
require "mkmf"
-
-$defs << "-DHAVE_CONFIG_H"
-$INCFLAGS << " -I$(srcdir)/.."
+require File.expand_path("../../digest_conf", __FILE__)
$objs = [ "sha1init.#{$OBJEXT}" ]
-dir_config("openssl")
-
-if !with_config("bundled-sha1") &&
- have_library("crypto") && have_header("openssl/sha.h")
- $objs << "sha1ossl.#{$OBJEXT}"
-else
- $objs << "sha1.#{$OBJEXT}" << "sha1hl.#{$OBJEXT}"
-end
+digest_conf("sha1")
have_header("sys/cdefs.h")
-have_header("inttypes.h")
-
-have_header("unistd.h")
+$preload = %w[digest]
create_makefile("digest/sha1")
diff --git a/ext/digest/sha1/sha1.c b/ext/digest/sha1/sha1.c
index 1012ef8751..003c87d224 100644
--- a/ext/digest/sha1/sha1.c
+++ b/ext/digest/sha1/sha1.c
@@ -129,9 +129,7 @@ do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LON
/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/
-void SHA1_Transform(state, buffer)
- uint32_t state[5];
- const uint8_t buffer[64];
+void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
{
uint32_t a, b, c, d, e;
CHAR64LONG16 *block;
@@ -201,8 +199,7 @@ void SHA1_Transform(state, buffer)
/*
* SHA1_Init - Initialize new context
*/
-void SHA1_Init(context)
- SHA1_CTX *context;
+int SHA1_Init(SHA1_CTX *context)
{
_DIAGASSERT(context != 0);
@@ -214,31 +211,37 @@ void SHA1_Init(context)
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
+ return 1;
}
/*
* Run your data through this.
*/
-void SHA1_Update(context, data, len)
- SHA1_CTX *context;
- const uint8_t *data;
- size_t len;
+void SHA1_Update(SHA1_CTX *context, const uint8_t *data, size_t len)
{
- uint32_t i, j;
+ size_t i;
+ uint32_t j;
_DIAGASSERT(context != 0);
_DIAGASSERT(data != 0);
j = context->count[0];
if ((context->count[0] += len << 3) < j)
- context->count[1] += (len>>29)+1;
+ context->count[1]++;
+ context->count[1] += (uint32_t)(len >> 29);
j = (j >> 3) & 63;
if ((j + len) > 63) {
(void)memcpy(&context->buffer[j], data, (i = 64-j));
SHA1_Transform(context->state, context->buffer);
- for ( ; i + 63 < len; i += 64)
+ for ( ; i + 63 < len; i += 64) {
+ RB_DIGEST_WARNING_PUSH();
+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 11
+ RB_DIGEST_WARNING_IGNORED(-Wstringop-overread);
+#endif
SHA1_Transform(context->state, &data[i]);
+ RB_DIGEST_WARNING_POP();
+ }
j = 0;
} else {
i = 0;
@@ -250,9 +253,7 @@ void SHA1_Update(context, data, len)
/*
* Add padding and return the message digest.
*/
-void SHA1_Final(digest, context)
- uint8_t digest[20];
- SHA1_CTX* context;
+int SHA1_Finish(SHA1_CTX* context, uint8_t digest[20])
{
size_t i;
uint8_t finalcount[8];
@@ -274,10 +275,5 @@ void SHA1_Final(digest, context)
digest[i] = (uint8_t)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
-}
-
-int SHA1_Equal(SHA1_CTX* pctx1, SHA1_CTX* pctx2) {
- return memcmp(pctx1->count, pctx2->count, sizeof(pctx1->count)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
+ return 1;
}
diff --git a/ext/digest/sha1/sha1.h b/ext/digest/sha1/sha1.h
index 2303cecc2b..2accc46d46 100644
--- a/ext/digest/sha1/sha1.h
+++ b/ext/digest/sha1/sha1.h
@@ -11,40 +11,29 @@
#ifndef _SYS_SHA1_H_
#define _SYS_SHA1_H_
-#include "defs.h"
+#include "../defs.h"
typedef struct {
uint32_t state[5];
- uint32_t count[2];
+ uint32_t count[2];
uint8_t buffer[64];
} SHA1_CTX;
#ifdef RUBY
+/* avoid name clash */
#define SHA1_Transform rb_Digest_SHA1_Transform
#define SHA1_Init rb_Digest_SHA1_Init
#define SHA1_Update rb_Digest_SHA1_Update
-#define SHA1_Final rb_Digest_SHA1_Final
-#define SHA1_Equal rb_Digest_SHA1_Equal
-#ifndef _KERNEL
-#define SHA1_End rb_Digest_SHA1_End
-#define SHA1_File rb_Digest_SHA1_File
-#define SHA1_Data rb_Digest_SHA1_Data
-#endif /* _KERNEL */
+#define SHA1_Finish rb_Digest_SHA1_Finish
#endif
void SHA1_Transform _((uint32_t state[5], const uint8_t buffer[64]));
-void SHA1_Init _((SHA1_CTX *context));
+int SHA1_Init _((SHA1_CTX *context));
void SHA1_Update _((SHA1_CTX *context, const uint8_t *data, size_t len));
-void SHA1_Final _((uint8_t digest[20], SHA1_CTX *context));
-int SHA1_Equal _((SHA1_CTX *pctx1, SHA1_CTX *pctx2));
-#ifndef _KERNEL
-char *SHA1_End _((SHA1_CTX *, char *));
-char *SHA1_File _((char *, char *));
-char *SHA1_Data _((const uint8_t *, size_t, char *));
-#endif /* _KERNEL */
+int SHA1_Finish _((SHA1_CTX *context, uint8_t digest[20]));
#define SHA1_BLOCK_LENGTH 64
#define SHA1_DIGEST_LENGTH 20
#define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1)
-
+
#endif /* _SYS_SHA1_H_ */
diff --git a/ext/digest/sha1/sha1cc.h b/ext/digest/sha1/sha1cc.h
new file mode 100644
index 0000000000..f39ecc6234
--- /dev/null
+++ b/ext/digest/sha1/sha1cc.h
@@ -0,0 +1,22 @@
+#define COMMON_DIGEST_FOR_OPENSSL 1
+#include <CommonCrypto/CommonDigest.h>
+
+#define SHA1_BLOCK_LENGTH CC_SHA1_BLOCK_BYTES
+#define SHA1_DIGEST_LENGTH CC_SHA1_DIGEST_LENGTH
+#define SHA1_CTX CC_SHA1_CTX
+
+static DEFINE_UPDATE_FUNC_FOR_UINT(SHA1)
+static DEFINE_FINISH_FUNC_FROM_FINAL(SHA1)
+
+#undef SHA1_Update
+#undef SHA1_Finish
+#define SHA1_Update rb_digest_SHA1_update
+#define SHA1_Finish rb_digest_SHA1_finish
+
+/*
+ * Pre-10.6 defines are with args, which don't match the argless use in
+ * the function pointer inits. Thus, we redefine SHA1_Init as well.
+ * This is a NOP on 10.6+.
+ */
+#undef SHA1_Init
+#define SHA1_Init CC_SHA1_Init
diff --git a/ext/digest/sha1/sha1hl.c b/ext/digest/sha1/sha1hl.c
deleted file mode 100644
index d1a236b22c..0000000000
--- a/ext/digest/sha1/sha1hl.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/* $NetBSD: sha1hl.c,v 1.2 2001/03/10 15:55:14 tron Exp $ */
-/* $RoughId: sha1hl.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id$ */
-
-/* sha1hl.c
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@login.dkuug.dk> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- */
-
-/* #include "namespace.h" */
-
-#include "sha1.h"
-#include <fcntl.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/* __RCSID("$NetBSD: sha1hl.c,v 1.2 2001/03/10 15:55:14 tron Exp $"); */
-#endif /* LIBC_SCCS and not lint */
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-
-/* ARGSUSED */
-char *
-SHA1_End(ctx, buf)
- SHA1_CTX *ctx;
- char *buf;
-{
- int i;
- char *p = buf;
- uint8_t digest[20];
- static const char hex[]="0123456789abcdef";
-
- _DIAGASSERT(ctx != NULL);
- /* buf may be NULL */
-
- if (p == NULL && (p = malloc(41)) == NULL)
- return 0;
-
- SHA1_Final(digest,ctx);
- for (i = 0; i < 20; i++) {
- p[i + i] = hex[((uint32_t)digest[i]) >> 4];
- p[i + i + 1] = hex[digest[i] & 0x0f];
- }
- p[i + i] = '\0';
- return(p);
-}
-
-char *
-SHA1_File (filename, buf)
- char *filename;
- char *buf;
-{
- uint8_t buffer[BUFSIZ];
- SHA1_CTX ctx;
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA1_Init(&ctx);
-
- if ((fd = open(filename,O_RDONLY)) < 0)
- return(0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- SHA1_Update(&ctx, buffer, (size_t)num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return(num < 0 ? 0 : SHA1_End(&ctx, buf));
-}
-
-char *
-SHA1_Data (data, len, buf)
- const uint8_t *data;
- size_t len;
- char *buf;
-{
- SHA1_CTX ctx;
-
- _DIAGASSERT(data != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, data, len);
- return(SHA1_End(&ctx, buf));
-}
diff --git a/ext/digest/sha1/sha1init.c b/ext/digest/sha1/sha1init.c
index 426afb7cd0..c39959f428 100644
--- a/ext/digest/sha1/sha1init.c
+++ b/ext/digest/sha1/sha1init.c
@@ -1,38 +1,62 @@
/* $RoughId: sha1init.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
/* $Id$ */
-#include "digest.h"
-#if defined(HAVE_OPENSSL_SHA_H)
-#include "sha1ossl.h"
+#include <ruby/ruby.h>
+#include "../digest.h"
+#if defined(SHA1_USE_COMMONDIGEST)
+#include "sha1cc.h"
#else
#include "sha1.h"
#endif
-static algo_t sha1 = {
+static const rb_digest_metadata_t sha1 = {
+ RUBY_DIGEST_API_VERSION,
SHA1_DIGEST_LENGTH,
+ SHA1_BLOCK_LENGTH,
sizeof(SHA1_CTX),
- (hash_init_func_t)SHA1_Init,
- (hash_update_func_t)SHA1_Update,
- (hash_end_func_t)SHA1_End,
- (hash_final_func_t)SHA1_Final,
- (hash_equal_func_t)SHA1_Equal,
+ (rb_digest_hash_init_func_t)SHA1_Init,
+ (rb_digest_hash_update_func_t)SHA1_Update,
+ (rb_digest_hash_finish_func_t)SHA1_Finish,
};
+/*
+ * Document-class: Digest::SHA1 < Digest::Base
+ * A class for calculating message digests using the SHA-1 Secure Hash
+ * Algorithm by NIST (the US' National Institute of Standards and
+ * Technology), described in FIPS PUB 180-1.
+ *
+ * See Digest::Instance for digest API.
+ *
+ * SHA-1 calculates a digest of 160 bits (20 bytes).
+ *
+ * == Examples
+ * require 'digest'
+ *
+ * # Compute a complete digest
+ * Digest::SHA1.hexdigest 'abc' #=> "a9993e36..."
+ *
+ * # Compute digest by chunks
+ * sha1 = Digest::SHA1.new # =>#<Digest::SHA1>
+ * sha1.update "ab"
+ * sha1 << "c" # alias for #update
+ * sha1.hexdigest # => "a9993e36..."
+ *
+ * # Use the same object to compute another digest
+ * sha1.reset
+ * sha1 << "message"
+ * sha1.hexdigest # => "6f9b9af3..."
+ */
void
-Init_sha1()
+Init_sha1(void)
{
VALUE mDigest, cDigest_Base, cDigest_SHA1;
- ID id_metadata;
- rb_require("digest.so");
-
- mDigest = rb_path2class("Digest");
- cDigest_Base = rb_path2class("Digest::Base");
+#if 0
+ mDigest = rb_define_module("Digest"); /* let rdoc know */
+#endif
+ mDigest = rb_digest_namespace();
+ cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base"));
cDigest_SHA1 = rb_define_class_under(mDigest, "SHA1", cDigest_Base);
-
- id_metadata = rb_intern("metadata");
-
- rb_cvar_set(cDigest_SHA1, id_metadata,
- Data_Wrap_Struct(rb_cObject, 0, 0, &sha1), Qtrue);
+ rb_iv_set(cDigest_SHA1, "metadata", rb_digest_make_metadata(&sha1));
}
diff --git a/ext/digest/sha1/sha1ossl.c b/ext/digest/sha1/sha1ossl.c
deleted file mode 100644
index 82a4f6f057..0000000000
--- a/ext/digest/sha1/sha1ossl.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* $Id$ */
-
-#include "defs.h"
-#include "sha1ossl.h"
-#include <assert.h>
-#include <stdlib.h>
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-char *
-SHA1_End(SHA1_CTX *ctx, char *buf)
-{
- int i;
- char *p = buf;
- uint8_t digest[20];
- static const char hex[]="0123456789abcdef";
-
- _DIAGASSERT(ctx != NULL);
- /* buf may be NULL */
-
- if (p == NULL && (p = malloc(41)) == NULL)
- return 0;
-
- SHA1_Final(digest,ctx);
- for (i = 0; i < 20; i++) {
- p[i + i] = hex[((uint32_t)digest[i]) >> 4];
- p[i + i + 1] = hex[digest[i] & 0x0f];
- }
- p[i + i] = '\0';
- return(p);
-}
-
-int SHA1_Equal(SHA1_CTX* pctx1, SHA1_CTX* pctx2) {
- return pctx1->num == pctx2->num
- && pctx1->h0 == pctx2->h0
- && pctx1->h1 == pctx2->h1
- && pctx1->h2 == pctx2->h2
- && pctx1->h3 == pctx2->h3
- && pctx1->h4 == pctx2->h4
- && pctx1->Nl == pctx2->Nl
- && pctx1->Nh == pctx2->Nh
- && memcmp(pctx1->data, pctx2->data, sizeof(pctx1->data)) == 0;
-}
diff --git a/ext/digest/sha1/sha1ossl.h b/ext/digest/sha1/sha1ossl.h
deleted file mode 100644
index c271cc47c6..0000000000
--- a/ext/digest/sha1/sha1ossl.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $Id$ */
-
-#ifndef SHA1OSSL_H_INCLUDED
-#define SHA1OSSL_H_INCLUDED
-
-#include <stddef.h>
-#include <openssl/sha.h>
-
-#define SHA1_CTX SHA_CTX
-
-#define SHA1_BLOCK_LENGTH SHA_BLOCK_LENGTH
-#define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
-
-char *SHA1_End(SHA1_CTX *ctx, char *buf);
-int SHA1_Equal(SHA1_CTX *pctx1, SHA1_CTX *pctx2);
-
-#endif
diff --git a/ext/digest/sha2/.cvsignore b/ext/digest/sha2/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/digest/sha2/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/digest/sha2/depend b/ext/digest/sha2/depend
index 2587415fdc..2b74776b3e 100644
--- a/ext/digest/sha2/depend
+++ b/ext/digest/sha2/depend
@@ -1,7 +1,332 @@
-sha2.o: sha2.c sha2.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
-sha2hl.o: sha2hl.c sha2.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
-sha2init.o: sha2init.c $(srcdir)/../digest.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h \
- sha2.h $(srcdir)/../defs.h
+sha2.o: sha2.c sha2.h $(srcdir)/../defs.h
+sha2init.o: $(LOCAL_HDRS)
+
+# AUTOGENERATED DEPENDENCIES START
+sha2.o: $(RUBY_EXTCONF_H)
+sha2.o: $(arch_hdrdir)/ruby/config.h
+sha2.o: $(hdrdir)/ruby.h
+sha2.o: $(hdrdir)/ruby/assert.h
+sha2.o: $(hdrdir)/ruby/backward.h
+sha2.o: $(hdrdir)/ruby/backward/2/assume.h
+sha2.o: $(hdrdir)/ruby/backward/2/attributes.h
+sha2.o: $(hdrdir)/ruby/backward/2/bool.h
+sha2.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sha2.o: $(hdrdir)/ruby/backward/2/limits.h
+sha2.o: $(hdrdir)/ruby/backward/2/long_long.h
+sha2.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sha2.o: $(hdrdir)/ruby/backward/2/stdarg.h
+sha2.o: $(hdrdir)/ruby/defines.h
+sha2.o: $(hdrdir)/ruby/intern.h
+sha2.o: $(hdrdir)/ruby/internal/abi.h
+sha2.o: $(hdrdir)/ruby/internal/anyargs.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sha2.o: $(hdrdir)/ruby/internal/assume.h
+sha2.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sha2.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sha2.o: $(hdrdir)/ruby/internal/attr/cold.h
+sha2.o: $(hdrdir)/ruby/internal/attr/const.h
+sha2.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sha2.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sha2.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sha2.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sha2.o: $(hdrdir)/ruby/internal/attr/error.h
+sha2.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sha2.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sha2.o: $(hdrdir)/ruby/internal/attr/format.h
+sha2.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sha2.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sha2.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sha2.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sha2.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sha2.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sha2.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sha2.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+sha2.o: $(hdrdir)/ruby/internal/attr/pure.h
+sha2.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sha2.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sha2.o: $(hdrdir)/ruby/internal/attr/warning.h
+sha2.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sha2.o: $(hdrdir)/ruby/internal/cast.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_since.h
+sha2.o: $(hdrdir)/ruby/internal/config.h
+sha2.o: $(hdrdir)/ruby/internal/constant_p.h
+sha2.o: $(hdrdir)/ruby/internal/core.h
+sha2.o: $(hdrdir)/ruby/internal/core/rarray.h
+sha2.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sha2.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sha2.o: $(hdrdir)/ruby/internal/core/rclass.h
+sha2.o: $(hdrdir)/ruby/internal/core/rdata.h
+sha2.o: $(hdrdir)/ruby/internal/core/rfile.h
+sha2.o: $(hdrdir)/ruby/internal/core/rhash.h
+sha2.o: $(hdrdir)/ruby/internal/core/robject.h
+sha2.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sha2.o: $(hdrdir)/ruby/internal/core/rstring.h
+sha2.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sha2.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sha2.o: $(hdrdir)/ruby/internal/ctype.h
+sha2.o: $(hdrdir)/ruby/internal/dllexport.h
+sha2.o: $(hdrdir)/ruby/internal/dosish.h
+sha2.o: $(hdrdir)/ruby/internal/error.h
+sha2.o: $(hdrdir)/ruby/internal/eval.h
+sha2.o: $(hdrdir)/ruby/internal/event.h
+sha2.o: $(hdrdir)/ruby/internal/fl_type.h
+sha2.o: $(hdrdir)/ruby/internal/gc.h
+sha2.o: $(hdrdir)/ruby/internal/glob.h
+sha2.o: $(hdrdir)/ruby/internal/globals.h
+sha2.o: $(hdrdir)/ruby/internal/has/attribute.h
+sha2.o: $(hdrdir)/ruby/internal/has/builtin.h
+sha2.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sha2.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sha2.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sha2.o: $(hdrdir)/ruby/internal/has/extension.h
+sha2.o: $(hdrdir)/ruby/internal/has/feature.h
+sha2.o: $(hdrdir)/ruby/internal/has/warning.h
+sha2.o: $(hdrdir)/ruby/internal/intern/array.h
+sha2.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sha2.o: $(hdrdir)/ruby/internal/intern/class.h
+sha2.o: $(hdrdir)/ruby/internal/intern/compar.h
+sha2.o: $(hdrdir)/ruby/internal/intern/complex.h
+sha2.o: $(hdrdir)/ruby/internal/intern/cont.h
+sha2.o: $(hdrdir)/ruby/internal/intern/dir.h
+sha2.o: $(hdrdir)/ruby/internal/intern/enum.h
+sha2.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sha2.o: $(hdrdir)/ruby/internal/intern/error.h
+sha2.o: $(hdrdir)/ruby/internal/intern/eval.h
+sha2.o: $(hdrdir)/ruby/internal/intern/file.h
+sha2.o: $(hdrdir)/ruby/internal/intern/hash.h
+sha2.o: $(hdrdir)/ruby/internal/intern/io.h
+sha2.o: $(hdrdir)/ruby/internal/intern/load.h
+sha2.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sha2.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sha2.o: $(hdrdir)/ruby/internal/intern/object.h
+sha2.o: $(hdrdir)/ruby/internal/intern/parse.h
+sha2.o: $(hdrdir)/ruby/internal/intern/proc.h
+sha2.o: $(hdrdir)/ruby/internal/intern/process.h
+sha2.o: $(hdrdir)/ruby/internal/intern/random.h
+sha2.o: $(hdrdir)/ruby/internal/intern/range.h
+sha2.o: $(hdrdir)/ruby/internal/intern/rational.h
+sha2.o: $(hdrdir)/ruby/internal/intern/re.h
+sha2.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sha2.o: $(hdrdir)/ruby/internal/intern/select.h
+sha2.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sha2.o: $(hdrdir)/ruby/internal/intern/set.h
+sha2.o: $(hdrdir)/ruby/internal/intern/signal.h
+sha2.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sha2.o: $(hdrdir)/ruby/internal/intern/string.h
+sha2.o: $(hdrdir)/ruby/internal/intern/struct.h
+sha2.o: $(hdrdir)/ruby/internal/intern/thread.h
+sha2.o: $(hdrdir)/ruby/internal/intern/time.h
+sha2.o: $(hdrdir)/ruby/internal/intern/variable.h
+sha2.o: $(hdrdir)/ruby/internal/intern/vm.h
+sha2.o: $(hdrdir)/ruby/internal/interpreter.h
+sha2.o: $(hdrdir)/ruby/internal/iterator.h
+sha2.o: $(hdrdir)/ruby/internal/memory.h
+sha2.o: $(hdrdir)/ruby/internal/method.h
+sha2.o: $(hdrdir)/ruby/internal/module.h
+sha2.o: $(hdrdir)/ruby/internal/newobj.h
+sha2.o: $(hdrdir)/ruby/internal/scan_args.h
+sha2.o: $(hdrdir)/ruby/internal/special_consts.h
+sha2.o: $(hdrdir)/ruby/internal/static_assert.h
+sha2.o: $(hdrdir)/ruby/internal/stdalign.h
+sha2.o: $(hdrdir)/ruby/internal/stdbool.h
+sha2.o: $(hdrdir)/ruby/internal/stdckdint.h
+sha2.o: $(hdrdir)/ruby/internal/symbol.h
+sha2.o: $(hdrdir)/ruby/internal/value.h
+sha2.o: $(hdrdir)/ruby/internal/value_type.h
+sha2.o: $(hdrdir)/ruby/internal/variable.h
+sha2.o: $(hdrdir)/ruby/internal/warning_push.h
+sha2.o: $(hdrdir)/ruby/internal/xmalloc.h
+sha2.o: $(hdrdir)/ruby/missing.h
+sha2.o: $(hdrdir)/ruby/ruby.h
+sha2.o: $(hdrdir)/ruby/st.h
+sha2.o: $(hdrdir)/ruby/subst.h
+sha2.o: $(srcdir)/../defs.h
+sha2.o: sha2.c
+sha2.o: sha2.h
+sha2init.o: $(RUBY_EXTCONF_H)
+sha2init.o: $(arch_hdrdir)/ruby/config.h
+sha2init.o: $(hdrdir)/ruby.h
+sha2init.o: $(hdrdir)/ruby/assert.h
+sha2init.o: $(hdrdir)/ruby/backward.h
+sha2init.o: $(hdrdir)/ruby/backward/2/assume.h
+sha2init.o: $(hdrdir)/ruby/backward/2/attributes.h
+sha2init.o: $(hdrdir)/ruby/backward/2/bool.h
+sha2init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sha2init.o: $(hdrdir)/ruby/backward/2/limits.h
+sha2init.o: $(hdrdir)/ruby/backward/2/long_long.h
+sha2init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sha2init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+sha2init.o: $(hdrdir)/ruby/defines.h
+sha2init.o: $(hdrdir)/ruby/intern.h
+sha2init.o: $(hdrdir)/ruby/internal/abi.h
+sha2init.o: $(hdrdir)/ruby/internal/anyargs.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sha2init.o: $(hdrdir)/ruby/internal/assume.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/cold.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/const.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/error.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/format.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/pure.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/warning.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sha2init.o: $(hdrdir)/ruby/internal/cast.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_since.h
+sha2init.o: $(hdrdir)/ruby/internal/config.h
+sha2init.o: $(hdrdir)/ruby/internal/constant_p.h
+sha2init.o: $(hdrdir)/ruby/internal/core.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rarray.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rclass.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rdata.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rfile.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rhash.h
+sha2init.o: $(hdrdir)/ruby/internal/core/robject.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rstring.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sha2init.o: $(hdrdir)/ruby/internal/ctype.h
+sha2init.o: $(hdrdir)/ruby/internal/dllexport.h
+sha2init.o: $(hdrdir)/ruby/internal/dosish.h
+sha2init.o: $(hdrdir)/ruby/internal/error.h
+sha2init.o: $(hdrdir)/ruby/internal/eval.h
+sha2init.o: $(hdrdir)/ruby/internal/event.h
+sha2init.o: $(hdrdir)/ruby/internal/fl_type.h
+sha2init.o: $(hdrdir)/ruby/internal/gc.h
+sha2init.o: $(hdrdir)/ruby/internal/glob.h
+sha2init.o: $(hdrdir)/ruby/internal/globals.h
+sha2init.o: $(hdrdir)/ruby/internal/has/attribute.h
+sha2init.o: $(hdrdir)/ruby/internal/has/builtin.h
+sha2init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sha2init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sha2init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sha2init.o: $(hdrdir)/ruby/internal/has/extension.h
+sha2init.o: $(hdrdir)/ruby/internal/has/feature.h
+sha2init.o: $(hdrdir)/ruby/internal/has/warning.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/array.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/class.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/compar.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/complex.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/cont.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/dir.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/enum.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/error.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/eval.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/file.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/hash.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/io.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/load.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/object.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/parse.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/proc.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/process.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/random.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/range.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/rational.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/re.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/select.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/set.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/signal.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/string.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/struct.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/thread.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/time.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/variable.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/vm.h
+sha2init.o: $(hdrdir)/ruby/internal/interpreter.h
+sha2init.o: $(hdrdir)/ruby/internal/iterator.h
+sha2init.o: $(hdrdir)/ruby/internal/memory.h
+sha2init.o: $(hdrdir)/ruby/internal/method.h
+sha2init.o: $(hdrdir)/ruby/internal/module.h
+sha2init.o: $(hdrdir)/ruby/internal/newobj.h
+sha2init.o: $(hdrdir)/ruby/internal/scan_args.h
+sha2init.o: $(hdrdir)/ruby/internal/special_consts.h
+sha2init.o: $(hdrdir)/ruby/internal/static_assert.h
+sha2init.o: $(hdrdir)/ruby/internal/stdalign.h
+sha2init.o: $(hdrdir)/ruby/internal/stdbool.h
+sha2init.o: $(hdrdir)/ruby/internal/stdckdint.h
+sha2init.o: $(hdrdir)/ruby/internal/symbol.h
+sha2init.o: $(hdrdir)/ruby/internal/value.h
+sha2init.o: $(hdrdir)/ruby/internal/value_type.h
+sha2init.o: $(hdrdir)/ruby/internal/variable.h
+sha2init.o: $(hdrdir)/ruby/internal/warning_push.h
+sha2init.o: $(hdrdir)/ruby/internal/xmalloc.h
+sha2init.o: $(hdrdir)/ruby/missing.h
+sha2init.o: $(hdrdir)/ruby/ruby.h
+sha2init.o: $(hdrdir)/ruby/st.h
+sha2init.o: $(hdrdir)/ruby/subst.h
+sha2init.o: $(srcdir)/../digest.h
+sha2init.o: sha2.h
+sha2init.o: sha2cc.h
+sha2init.o: sha2init.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/sha2/extconf.rb b/ext/digest/sha2/extconf.rb
index 7bb143e8d1..3b772675e1 100644
--- a/ext/digest/sha2/extconf.rb
+++ b/ext/digest/sha2/extconf.rb
@@ -1,23 +1,19 @@
+# -*- coding: us-ascii -*-
+# frozen_string_literal: false
# $RoughId: extconf.rb,v 1.4 2001/08/14 19:54:51 knu Exp $
# $Id$
require "mkmf"
+require File.expand_path("../../digest_conf", __FILE__)
-$defs << "-DHAVE_CONFIG_H"
-$INCFLAGS << " -I$(srcdir)/.."
+$objs = [ "sha2init.#{$OBJEXT}" ]
-$objs = [
- "sha2.#{$OBJEXT}",
- "sha2hl.#{$OBJEXT}",
- "sha2init.#{$OBJEXT}",
-]
+unless digest_conf("sha2")
+ have_type("u_int8_t")
+end
have_header("sys/cdefs.h")
-have_header("inttypes.h")
-
-have_header("unistd.h")
+$preload = %w[digest]
-if have_type("uint64_t", "defs.h", $defs.join(' '))
- create_makefile("digest/sha2")
-end
+create_makefile("digest/sha2")
diff --git a/ext/digest/sha2/lib/sha2.rb b/ext/digest/sha2/lib/sha2.rb
new file mode 100644
index 0000000000..f17593a206
--- /dev/null
+++ b/ext/digest/sha2/lib/sha2.rb
@@ -0,0 +1,142 @@
+# frozen_string_literal: false
+#--
+# sha2.rb - defines Digest::SHA2 class which wraps up the SHA256,
+# SHA384, and SHA512 classes.
+#++
+# Copyright (c) 2006 Akinori MUSHA <knu@iDaemons.org>
+#
+# All rights reserved. You can redistribute and/or modify it under the same
+# terms as Ruby.
+#
+# $Id$
+
+require 'digest'
+require 'digest/sha2/loader'
+
+module Digest
+ #
+ # A meta digest provider class for SHA256, SHA384 and SHA512.
+ #
+ # FIPS 180-2 describes SHA2 family of digest algorithms. It defines
+ # three algorithms:
+ # * one which works on chunks of 512 bits and returns a 256-bit
+ # digest (SHA256),
+ # * one which works on chunks of 1024 bits and returns a 384-bit
+ # digest (SHA384),
+ # * and one which works on chunks of 1024 bits and returns a 512-bit
+ # digest (SHA512).
+ #
+ # ==Examples
+ # require 'digest'
+ #
+ # # Compute a complete digest
+ # Digest::SHA2.hexdigest 'abc' # => "ba7816bf8..."
+ # Digest::SHA2.new(256).hexdigest 'abc' # => "ba7816bf8..."
+ # Digest::SHA256.hexdigest 'abc' # => "ba7816bf8..."
+ #
+ # Digest::SHA2.new(384).hexdigest 'abc' # => "cb00753f4..."
+ # Digest::SHA384.hexdigest 'abc' # => "cb00753f4..."
+ #
+ # Digest::SHA2.new(512).hexdigest 'abc' # => "ddaf35a19..."
+ # Digest::SHA512.hexdigest 'abc' # => "ddaf35a19..."
+ #
+ # # Compute digest by chunks
+ # sha2 = Digest::SHA2.new # =>#<Digest::SHA2:256>
+ # sha2.update "ab"
+ # sha2 << "c" # alias for #update
+ # sha2.hexdigest # => "ba7816bf8..."
+ #
+ # # Use the same object to compute another digest
+ # sha2.reset
+ # sha2 << "message"
+ # sha2.hexdigest # => "ab530a13e..."
+ #
+ class SHA2 < Digest::Class
+ # call-seq:
+ # Digest::SHA2.new(bitlen = 256) -> digest_obj
+ #
+ # Create a new SHA2 hash object with a given bit length.
+ #
+ # Valid bit lengths are 256, 384 and 512.
+ def initialize(bitlen = 256)
+ case bitlen
+ when 256
+ @sha2 = Digest::SHA256.new
+ when 384
+ @sha2 = Digest::SHA384.new
+ when 512
+ @sha2 = Digest::SHA512.new
+ else
+ raise ArgumentError, "unsupported bit length: %s" % bitlen.inspect
+ end
+ @bitlen = bitlen
+ end
+
+ # call-seq:
+ # digest_obj.reset -> digest_obj
+ #
+ # Reset the digest to the initial state and return self.
+ def reset
+ @sha2.reset
+ self
+ end
+
+ # call-seq:
+ # digest_obj.update(string) -> digest_obj
+ # digest_obj << string -> digest_obj
+ #
+ # Update the digest using a given _string_ and return self.
+ def update(str)
+ @sha2.update(str)
+ self
+ end
+ alias << update
+
+ def finish # :nodoc:
+ @sha2.digest!
+ end
+ private :finish
+
+
+ # call-seq:
+ # digest_obj.block_length -> Integer
+ #
+ # Return the block length of the digest in bytes.
+ #
+ # Digest::SHA256.new.block_length * 8
+ # # => 512
+ # Digest::SHA384.new.block_length * 8
+ # # => 1024
+ # Digest::SHA512.new.block_length * 8
+ # # => 1024
+ def block_length
+ @sha2.block_length
+ end
+
+ # call-seq:
+ # digest_obj.digest_length -> Integer
+ #
+ # Return the length of the hash value (the digest) in bytes.
+ #
+ # Digest::SHA256.new.digest_length * 8
+ # # => 256
+ # Digest::SHA384.new.digest_length * 8
+ # # => 384
+ # Digest::SHA512.new.digest_length * 8
+ # # => 512
+ #
+ # For example, digests produced by Digest::SHA256 will always be 32 bytes
+ # (256 bits) in size.
+ def digest_length
+ @sha2.digest_length
+ end
+
+ def initialize_copy(other) # :nodoc:
+ @sha2 = other.instance_eval { @sha2.clone }
+ end
+
+ def inspect # :nodoc:
+ "#<%s:%d %s>" % [self.class.name, @bitlen, hexdigest]
+ end
+ end
+end
diff --git a/ext/digest/sha2/lib/sha2/loader.rb b/ext/digest/sha2/lib/sha2/loader.rb
new file mode 100644
index 0000000000..7d6d04a59c
--- /dev/null
+++ b/ext/digest/sha2/lib/sha2/loader.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+require 'digest/sha2.so'
diff --git a/ext/digest/sha2/sha2.c b/ext/digest/sha2/sha2.c
index 41ed2df106..21d5acbe96 100644
--- a/ext/digest/sha2/sha2.c
+++ b/ext/digest/sha2/sha2.c
@@ -1,11 +1,9 @@
/*
- * sha2.c
+ * FILE: sha2.c
+ * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
*
- * Version 1.0.0beta1
- *
- * Written by Aaron D. Gifford <me@aarongifford.com>
- *
- * Copyright 2000 Aaron D. Gifford. All rights reserved.
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -18,11 +16,11 @@
* 3. Neither the name of the copyright holder nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -31,15 +29,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
+ * $OrigId: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
+ * $RoughId: sha2.c,v 1.3 2002/02/26 22:03:36 knu Exp $
+ * $Id$
*/
-/* $RoughId: sha2.c,v 1.3 2002/02/26 22:03:36 knu Exp $ */
-/* $Id$ */
-
-#include "sha2.h"
-#include <stdio.h>
+#include "../defs.h"
#include <string.h> /* memcpy()/memset() or bcopy()/bzero() */
#include <assert.h> /* assert() */
+#include "sha2.h"
/*
* ASSERT NOTE:
@@ -63,15 +61,64 @@
/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+/*
+ * BYTE_ORDER NOTE:
+ *
+ * Please make sure that your system defines BYTE_ORDER. If your
+ * architecture is little-endian, make sure it also defines
+ * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
+ * equivalent.
+ *
+ * If your system does not define the above, then you can do so by
+ * hand like this:
+ *
+ * #define LITTLE_ENDIAN 1234
+ * #define BIG_ENDIAN 4321
+ *
+ * And for little-endian machines, add:
+ *
+ * #define BYTE_ORDER LITTLE_ENDIAN
+ *
+ * Or for big-endian machines:
+ *
+ * #define BYTE_ORDER BIG_ENDIAN
+ *
+ * The FreeBSD machine this was written on defines BYTE_ORDER
+ * appropriately by including <sys/types.h> (which in turn includes
+ * <machine/endian.h> where the appropriate definitions are actually
+ * made).
+ */
+#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
+#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
+#endif
+
+/*
+ * Define the followingsha2_* types to types of the correct length on
+ * the native architecture. Most BSD systems and Linux define u_intXX_t
+ * types. Machines with very recent ANSI C headers, can use the
+ * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H
+ * during compile or in the sha.h header file.
+ *
+ * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t
+ * will need to define these three typedefs below (and the appropriate
+ * ones in sha.h too) by hand according to their system architecture.
+ *
+ * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t
+ * types and pointing out recent ANSI C support for uintXX_t in inttypes.h.
+ */
+#ifdef SHA2_USE_INTTYPES_H
+
typedef uint8_t sha2_byte; /* Exactly 1 byte */
typedef uint32_t sha2_word32; /* Exactly 4 bytes */
typedef uint64_t sha2_word64; /* Exactly 8 bytes */
-#if defined(__GNUC__) || defined(_HPUX_SOURCE) || defined(__IBMC__)
-#define ULL(number) number##ULL
-#else
-#define ULL(number) (uint64_t)(number)
-#endif
+#else /* SHA2_USE_INTTYPES_H */
+
+typedef u_int8_t sha2_byte; /* Exactly 1 byte */
+typedef u_int32_t sha2_word32; /* Exactly 4 bytes */
+typedef u_int64_t sha2_word64; /* Exactly 8 bytes */
+
+#endif /* SHA2_USE_INTTYPES_H */
/*** SHA-256/384/512 Various Length Definitions ***********************/
@@ -81,12 +128,17 @@ typedef uint64_t sha2_word64; /* Exactly 8 bytes */
#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__GNUC__) || defined(__IBMC__)
+#define ULL(number) number##ULL
+#else
+#define ULL(number) (uint64_t)(number)
+#endif
/*** ENDIAN REVERSAL MACROS *******************************************/
-#ifndef WORDS_BIGENDIAN
+#if BYTE_ORDER == LITTLE_ENDIAN
#define REVERSE32(w,x) { \
sha2_word32 tmp = (w); \
tmp = (tmp >> 16) | (tmp << 16); \
- (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+ (x) = ((tmp & (sha2_word32)0xff00ff00UL) >> 8) | ((tmp & (sha2_word32)0x00ff00ffUL) << 8); \
}
#define REVERSE64(w,x) { \
sha2_word64 tmp = (w); \
@@ -96,7 +148,7 @@ typedef uint64_t sha2_word64; /* Exactly 8 bytes */
(x) = ((tmp & ULL(0xffff0000ffff0000)) >> 16) | \
((tmp & ULL(0x0000ffff0000ffff)) << 16); \
}
-#endif
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
/*
* Macro for incrementally adding the unsigned 64-bit integer n to the
@@ -182,7 +234,7 @@ void SHA512_Transform(SHA512_CTX*, const sha2_word64*);
/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
/* Hash constant words K for SHA-256: */
-const static sha2_word32 K256[64] = {
+static const sha2_word32 K256[64] = {
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
@@ -202,7 +254,7 @@ const static sha2_word32 K256[64] = {
};
/* Initial hash value H for SHA-256: */
-const static sha2_word32 sha256_initial_hash_value[8] = {
+static const sha2_word32 sha256_initial_hash_value[8] = {
0x6a09e667UL,
0xbb67ae85UL,
0x3c6ef372UL,
@@ -214,7 +266,7 @@ const static sha2_word32 sha256_initial_hash_value[8] = {
};
/* Hash constant words K for SHA-384 and SHA-512: */
-const static sha2_word64 K512[80] = {
+static const sha2_word64 K512[80] = {
ULL(0x428a2f98d728ae22), ULL(0x7137449123ef65cd),
ULL(0xb5c0fbcfec4d3b2f), ULL(0xe9b5dba58189dbbc),
ULL(0x3956c25bf348b538), ULL(0x59f111f1b605d019),
@@ -258,7 +310,7 @@ const static sha2_word64 K512[80] = {
};
/* Initial hash value H for SHA-384 */
-const static sha2_word64 sha384_initial_hash_value[8] = {
+static const sha2_word64 sha384_initial_hash_value[8] = {
ULL(0xcbbb9d5dc1059ed8),
ULL(0x629a292a367cd507),
ULL(0x9159015a3070dd17),
@@ -270,7 +322,7 @@ const static sha2_word64 sha384_initial_hash_value[8] = {
};
/* Initial hash value H for SHA-512 */
-const static sha2_word64 sha512_initial_hash_value[8] = {
+static const sha2_word64 sha512_initial_hash_value[8] = {
ULL(0x6a09e667f3bcc908),
ULL(0xbb67ae8584caa73b),
ULL(0x3c6ef372fe94f82b),
@@ -281,22 +333,29 @@ const static sha2_word64 sha512_initial_hash_value[8] = {
ULL(0x5be0cd19137e2179)
};
+/*
+ * Constant used by SHA256/384/512_End() functions for converting the
+ * digest to a readable hexadecimal character string:
+ */
+static const char *sha2_hex_digits = "0123456789abcdef";
+
/*** SHA-256: *********************************************************/
-void SHA256_Init(SHA256_CTX* context) {
+int SHA256_Init(SHA256_CTX* context) {
if (context == (SHA256_CTX*)0) {
- return;
+ return 0;
}
MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH);
MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH);
context->bitcount = 0;
+ return 1;
}
#ifdef SHA2_UNROLL_TRANSFORM
/* Unrolled SHA-256 round macros: */
-#ifndef WORDS_BIGENDIAN
+#if BYTE_ORDER == LITTLE_ENDIAN
#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
REVERSE32(*data++, W256[j]); \
@@ -307,7 +366,7 @@ void SHA256_Init(SHA256_CTX* context) {
j++
-#else
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
@@ -316,7 +375,7 @@ void SHA256_Init(SHA256_CTX* context) {
(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
j++
-#endif
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
#define ROUND256(a,b,c,d,e,f,g,h) \
s0 = W256[(j+1)&0x0f]; \
@@ -406,15 +465,15 @@ void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
j = 0;
do {
-#ifndef WORDS_BIGENDIAN
+#if BYTE_ORDER == LITTLE_ENDIAN
/* Copy data while converting to host byte order */
REVERSE32(*data++,W256[j]);
/* Apply the SHA-256 compression function to update a..h */
T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
-#else
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
/* Apply the SHA-256 compression function to update a..h with copy */
T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
-#endif
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
T2 = Sigma0_256(a) + Maj(a, b, c);
h = g;
g = f;
@@ -432,11 +491,11 @@ void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
/* Part of the message block expansion: */
s0 = W256[(j+1)&0x0f];
s0 = sigma0_256(s0);
- s1 = W256[(j+14)&0x0f];
+ s1 = W256[(j+14)&0x0f];
s1 = sigma1_256(s1);
/* Apply the SHA-256 compression function to update a..h */
- T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
(W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
T2 = Sigma0_256(a) + Maj(a, b, c);
h = g;
@@ -476,9 +535,9 @@ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
}
/* Sanity check: */
- assert(context != NULL && data != NULL);
+ assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0);
- usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+ usedspace = (unsigned int)((context->bitcount >> 3) % SHA256_BLOCK_LENGTH);
if (usedspace > 0) {
/* Calculate how much free space is available in the buffer */
freespace = SHA256_BLOCK_LENGTH - usedspace;
@@ -501,7 +560,8 @@ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
}
while (len >= SHA256_BLOCK_LENGTH) {
/* Process as many complete blocks as we can */
- SHA256_Transform(context, (const sha2_word32*)data);
+ MEMCPY_BCOPY(context->buffer, data, SHA256_BLOCK_LENGTH);
+ SHA256_Transform(context, (sha2_word32*)context->buffer);
context->bitcount += SHA256_BLOCK_LENGTH << 3;
len -= SHA256_BLOCK_LENGTH;
data += SHA256_BLOCK_LENGTH;
@@ -515,17 +575,17 @@ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
usedspace = freespace = 0;
}
-void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
+int SHA256_Final(sha2_byte digest[SHA256_DIGEST_LENGTH], SHA256_CTX* context) {
sha2_word32 *d = (sha2_word32*)digest;
unsigned int usedspace;
/* Sanity check: */
- assert(context != NULL);
+ assert(context != (SHA256_CTX*)0);
/* If no digest buffer is passed, we don't bother doing this: */
if (digest != (sha2_byte*)0) {
- usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
-#ifndef WORDS_BIGENDIAN
+ usedspace = (unsigned int)((context->bitcount >> 3) % SHA256_BLOCK_LENGTH);
+#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert FROM host byte order */
REVERSE64(context->bitcount,context->bitcount);
#endif
@@ -554,12 +614,13 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
*context->buffer = 0x80;
}
/* Set the bit count: */
- *(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
+ MEMCPY_BCOPY(&context->buffer[SHA256_SHORT_BLOCK_LENGTH], &context->bitcount,
+ sizeof(sha2_word64));
/* Final transform: */
SHA256_Transform(context, (sha2_word32*)context->buffer);
-#ifndef WORDS_BIGENDIAN
+#if BYTE_ORDER == LITTLE_ENDIAN
{
/* Convert TO host byte order */
int j;
@@ -574,30 +635,57 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
}
/* Clean up state data: */
- MEMSET_BZERO(context, sizeof(SHA256_CTX));
+ MEMSET_BZERO(context, sizeof(*context));
usedspace = 0;
+ return 1;
}
-int SHA256_Equal(SHA256_CTX* pctx1, SHA256_CTX* pctx2) {
- return pctx1->bitcount == pctx2->bitcount
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
+char *SHA256_End(SHA256_CTX* context, char buffer[SHA256_DIGEST_STRING_LENGTH]) {
+ sha2_byte digest[SHA256_DIGEST_LENGTH], *d = digest;
+ int i;
+
+ /* Sanity check: */
+ assert(context != (SHA256_CTX*)0);
+
+ if (buffer != (char*)0) {
+ SHA256_Final(digest, context);
+ for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
+ *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+ *buffer++ = sha2_hex_digits[*d & 0x0f];
+ d++;
+ }
+ *buffer = (char)0;
+ } else {
+ MEMSET_BZERO(context, sizeof(*context));
+ }
+ MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH);
+ return buffer;
}
+char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
+ SHA256_CTX context;
+
+ SHA256_Init(&context);
+ SHA256_Update(&context, data, len);
+ return SHA256_End(&context, digest);
+}
+
+
/*** SHA-512: *********************************************************/
-void SHA512_Init(SHA512_CTX* context) {
+int SHA512_Init(SHA512_CTX* context) {
if (context == (SHA512_CTX*)0) {
- return;
+ return 0;
}
MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH);
MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH);
context->bitcount[0] = context->bitcount[1] = 0;
+ return 1;
}
#ifdef SHA2_UNROLL_TRANSFORM
/* Unrolled SHA-512 round macros: */
-#ifndef WORDS_BIGENDIAN
+#if BYTE_ORDER == LITTLE_ENDIAN
#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
REVERSE64(*data++, W512[j]); \
@@ -608,7 +696,7 @@ void SHA512_Init(SHA512_CTX* context) {
j++
-#else
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
@@ -617,7 +705,7 @@ void SHA512_Init(SHA512_CTX* context) {
(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
j++
-#endif
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
#define ROUND512(a,b,c,d,e,f,g,h) \
s0 = W512[(j+1)&0x0f]; \
@@ -702,15 +790,15 @@ void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
j = 0;
do {
-#ifndef WORDS_BIGENDIAN
+#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert TO host byte order */
REVERSE64(*data++, W512[j]);
/* Apply the SHA-512 compression function to update a..h */
T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
-#else
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
/* Apply the SHA-512 compression function to update a..h with copy */
T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
-#endif
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
T2 = Sigma0_512(a) + Maj(a, b, c);
h = g;
g = f;
@@ -772,9 +860,9 @@ void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
}
/* Sanity check: */
- assert(context != NULL && data != NULL);
+ assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0);
- usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+ usedspace = (unsigned int)((context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH);
if (usedspace > 0) {
/* Calculate how much free space is available in the buffer */
freespace = SHA512_BLOCK_LENGTH - usedspace;
@@ -785,7 +873,7 @@ void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
ADDINC128(context->bitcount, freespace << 3);
len -= freespace;
data += freespace;
- SHA512_Transform(context, (const sha2_word64*)context->buffer);
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
} else {
/* The buffer is not yet full */
MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
@@ -797,7 +885,8 @@ void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
}
while (len >= SHA512_BLOCK_LENGTH) {
/* Process as many complete blocks as we can */
- SHA512_Transform(context, (const sha2_word64*)data);
+ MEMCPY_BCOPY(context->buffer, data, SHA512_BLOCK_LENGTH);
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
len -= SHA512_BLOCK_LENGTH;
data += SHA512_BLOCK_LENGTH;
@@ -814,8 +903,8 @@ void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
void SHA512_Last(SHA512_CTX* context) {
unsigned int usedspace;
- usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
-#ifndef WORDS_BIGENDIAN
+ usedspace = (unsigned int)((context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH);
+#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert FROM host byte order */
REVERSE64(context->bitcount[0],context->bitcount[0]);
REVERSE64(context->bitcount[1],context->bitcount[1]);
@@ -832,7 +921,7 @@ void SHA512_Last(SHA512_CTX* context) {
MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
}
/* Do second-to-last transform: */
- SHA512_Transform(context, (const sha2_word64*)context->buffer);
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
/* And set-up for the last transform: */
MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2);
@@ -845,25 +934,27 @@ void SHA512_Last(SHA512_CTX* context) {
*context->buffer = 0x80;
}
/* Store the length of input data (in bits): */
- *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
- *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
+ MEMCPY_BCOPY(&context->buffer[SHA512_SHORT_BLOCK_LENGTH], &context->bitcount[1],
+ sizeof(sha2_word64));
+ MEMCPY_BCOPY(&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8], &context->bitcount[0],
+ sizeof(sha2_word64));
/* Final transform: */
- SHA512_Transform(context, (const sha2_word64*)context->buffer);
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
}
-void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
+int SHA512_Final(sha2_byte digest[SHA512_DIGEST_LENGTH], SHA512_CTX* context) {
sha2_word64 *d = (sha2_word64*)digest;
/* Sanity check: */
- assert(context != NULL);
+ assert(context != (SHA512_CTX*)0);
/* If no digest buffer is passed, we don't bother doing this: */
if (digest != (sha2_byte*)0) {
SHA512_Last(context);
/* Save the hash data for output: */
-#ifndef WORDS_BIGENDIAN
+#if BYTE_ORDER == LITTLE_ENDIAN
{
/* Convert TO host byte order */
int j;
@@ -878,41 +969,68 @@ void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
}
/* Zero out state data */
- MEMSET_BZERO(context, sizeof(SHA512_CTX));
+ MEMSET_BZERO(context, sizeof(*context));
+ return 1;
}
-int SHA512_Equal(SHA512_CTX* pctx1, SHA512_CTX* pctx2) {
- return memcmp(pctx1->bitcount, pctx2->bitcount, sizeof(pctx1->bitcount)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
+char *SHA512_End(SHA512_CTX* context, char buffer[SHA512_DIGEST_STRING_LENGTH]) {
+ sha2_byte digest[SHA512_DIGEST_LENGTH], *d = digest;
+ int i;
+
+ /* Sanity check: */
+ assert(context != (SHA512_CTX*)0);
+
+ if (buffer != (char*)0) {
+ SHA512_Final(digest, context);
+ for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
+ *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+ *buffer++ = sha2_hex_digits[*d & 0x0f];
+ d++;
+ }
+ *buffer = (char)0;
+ } else {
+ MEMSET_BZERO(context, sizeof(*context));
+ }
+ MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH);
+ return buffer;
}
+char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {
+ SHA512_CTX context;
+
+ SHA512_Init(&context);
+ SHA512_Update(&context, data, len);
+ return SHA512_End(&context, digest);
+}
+
+
/*** SHA-384: *********************************************************/
-void SHA384_Init(SHA384_CTX* context) {
+int SHA384_Init(SHA384_CTX* context) {
if (context == (SHA384_CTX*)0) {
- return;
+ return 0;
}
MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH);
MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH);
context->bitcount[0] = context->bitcount[1] = 0;
+ return 1;
}
void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
SHA512_Update((SHA512_CTX*)context, data, len);
}
-void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
+int SHA384_Final(sha2_byte digest[SHA384_DIGEST_LENGTH], SHA384_CTX* context) {
sha2_word64 *d = (sha2_word64*)digest;
/* Sanity check: */
- assert(context != NULL);
+ assert(context != (SHA384_CTX*)0);
/* If no digest buffer is passed, we don't bother doing this: */
if (digest != (sha2_byte*)0) {
SHA512_Last((SHA512_CTX*)context);
/* Save the hash data for output: */
-#ifndef WORDS_BIGENDIAN
+#if BYTE_ORDER == LITTLE_ENDIAN
{
/* Convert TO host byte order */
int j;
@@ -927,11 +1045,37 @@ void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
}
/* Zero out state data */
- MEMSET_BZERO(context, sizeof(SHA384_CTX));
+ MEMSET_BZERO(context, sizeof(*context));
+ return 1;
}
-int SHA384_Equal(SHA384_CTX* pctx1, SHA384_CTX* pctx2) {
- return memcmp(pctx1->bitcount, pctx2->bitcount, sizeof(pctx1->bitcount)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
+char *SHA384_End(SHA384_CTX* context, char buffer[SHA384_DIGEST_STRING_LENGTH]) {
+ sha2_byte digest[SHA384_DIGEST_LENGTH], *d = digest;
+ int i;
+
+ /* Sanity check: */
+ assert(context != (SHA384_CTX*)0);
+
+ if (buffer != (char*)0) {
+ SHA384_Final(digest, context);
+ for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
+ *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+ *buffer++ = sha2_hex_digits[*d & 0x0f];
+ d++;
+ }
+ *buffer = (char)0;
+ } else {
+ MEMSET_BZERO(context, sizeof(*context));
+ }
+ MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH);
+ return buffer;
}
+
+char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) {
+ SHA384_CTX context;
+
+ SHA384_Init(&context);
+ SHA384_Update(&context, data, len);
+ return SHA384_End(&context, digest);
+}
+
diff --git a/ext/digest/sha2/sha2.h b/ext/digest/sha2/sha2.h
index 4689ad93ce..e58f15ae12 100644
--- a/ext/digest/sha2/sha2.h
+++ b/ext/digest/sha2/sha2.h
@@ -1,11 +1,9 @@
/*
- * sha2.h
+ * FILE: sha2.h
+ * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
*
- * Version 1.0.0beta1
- *
- * Written by Aaron D. Gifford <me@aarongifford.com>
- *
- * Copyright 2000 Aaron D. Gifford. All rights reserved.
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -18,11 +16,11 @@
* 3. Neither the name of the copyright holder nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -31,11 +29,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
+ * $OrigId: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
+ * $RoughId: sha2.h,v 1.3 2002/02/24 08:14:32 knu Exp $
+ * $Id$
*/
-/* $RoughId: sha2.h,v 1.3 2002/02/24 08:14:32 knu Exp $ */
-/* $Id$ */
-
#ifndef __SHA2_H__
#define __SHA2_H__
@@ -43,7 +41,37 @@
extern "C" {
#endif
-#include "defs.h"
+
+/*
+ * Import u_intXX_t size_t type definitions from system headers. You
+ * may need to change this, or define these things yourself in this
+ * file.
+ */
+#include <sys/types.h>
+
+#ifdef RUBY
+# ifdef HAVE_PROTOTYPES
+# undef NOPROTO
+# else
+# define NOPROTO
+# endif /* HAVE_PROTOTYPES */
+# ifndef BYTE_ORDER
+# define LITTLE_ENDIAN 1234
+# define BIG_ENDIAN 4321
+# ifdef WORDS_BIGENDIAN
+# define BYTE_ORDER BIG_ENDIAN
+# else
+# define BYTE_ORDER LITTLE_ENDIAN
+# endif
+# endif /* BYTE_ORDER */
+# define SHA2_USE_INTTYPES_H
+#else /* RUBY */
+#ifdef SHA2_USE_INTTYPES_H
+
+#include <inttypes.h>
+
+#endif /* SHA2_USE_INTTYPES_H */
+#endif /* RUBY */
/*** SHA-256/384/512 Various Length Definitions ***********************/
@@ -59,7 +87,38 @@ extern "C" {
/*** SHA-256/384/512 Context Structures *******************************/
+/* NOTE: If your architecture does not define either u_intXX_t types or
+ * uintXX_t (from inttypes.h), you may need to define things by hand
+ * for your system:
+ */
+#ifndef SHA2_USE_INTTYPES_H
+# ifdef HAVE_U_INT8_T
+typedef u_int8_t uint8_t; /* 1-byte (8-bits) */
+typedef u_int32_t uint32_t; /* 4-bytes (32-bits) */
+typedef u_int64_t uint64_t; /* 8-bytes (64-bits) */
+# else
+typedef unsigned char uint8_t; /* 1-byte (8-bits) */
+typedef unsigned int uint32_t; /* 4-bytes (32-bits) */
+typedef unsigned long long uint64_t; /* 8-bytes (64-bits) */
+# endif
+#endif
+/*
+ * Most BSD systems already define u_intXX_t types, as does Linux.
+ * Some systems, however, like Compaq's Tru64 Unix instead can use
+ * uintXX_t types defined by very recent ANSI C standards and included
+ * in the file:
+ *
+ * #include <inttypes.h>
+ *
+ * If you choose to use <inttypes.h> then please define:
+ *
+ * #define SHA2_USE_INTTYPES_H
+ *
+ * Or on the command line during compile:
+ *
+ * cc -DSHA2_USE_INTTYPES_H ...
+ */
typedef struct _SHA256_CTX {
uint32_t state[8];
uint64_t bitcount;
@@ -74,56 +133,89 @@ typedef struct _SHA512_CTX {
typedef SHA512_CTX SHA384_CTX;
+/*** SHA-256/384/512 Function Prototypes ******************************/
#ifdef RUBY
#define SHA256_Init rb_Digest_SHA256_Init
#define SHA256_Update rb_Digest_SHA256_Update
-#define SHA256_Final rb_Digest_SHA256_Final
-#define SHA256_End rb_Digest_SHA256_End
+#define SHA256_Finish rb_Digest_SHA256_Finish
#define SHA256_Data rb_Digest_SHA256_Data
-#define SHA256_File rb_Digest_SHA256_File
-#define SHA256_Equal rb_Digest_SHA256_Equal
+#define SHA256_End rb_Digest_SHA256_End
+#define SHA256_Last rb_Digest_SHA256_Last
+#define SHA256_Transform rb_Digest_SHA256_Transform
+#define SHA256_Final(d, c) SHA256_Finish(c, d)
#define SHA384_Init rb_Digest_SHA384_Init
#define SHA384_Update rb_Digest_SHA384_Update
-#define SHA384_Final rb_Digest_SHA384_Final
-#define SHA384_End rb_Digest_SHA384_End
+#define SHA384_Finish rb_Digest_SHA384_Finish
#define SHA384_Data rb_Digest_SHA384_Data
-#define SHA384_File rb_Digest_SHA384_File
-#define SHA384_Equal rb_Digest_SHA384_Equal
+#define SHA384_End rb_Digest_SHA384_End
+#define SHA384_Last rb_Digest_SHA384_Last
+#define SHA384_Transform rb_Digest_SHA384_Transform
+#define SHA384_Final(d, c) SHA384_Finish(c, d)
#define SHA512_Init rb_Digest_SHA512_Init
#define SHA512_Update rb_Digest_SHA512_Update
-#define SHA512_Final rb_Digest_SHA512_Final
-#define SHA512_End rb_Digest_SHA512_End
+#define SHA512_Finish rb_Digest_SHA512_Finish
#define SHA512_Data rb_Digest_SHA512_Data
-#define SHA512_File rb_Digest_SHA512_File
-#define SHA512_Equal rb_Digest_SHA512_Equal
-#endif
-
-/*** SHA-256/384/512 Function Prototypes ******************************/
-void SHA256_Init _((SHA256_CTX *));
-void SHA256_Update _((SHA256_CTX*, const uint8_t*, size_t));
-void SHA256_Final _((uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*));
-char* SHA256_End _((SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]));
-char* SHA256_Data _((const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]));
-char *SHA256_File _((char *, char *));
-int SHA256_Equal _((SHA256_CTX*, SHA256_CTX*));
-
-void SHA384_Init _((SHA384_CTX*));
-void SHA384_Update _((SHA384_CTX*, const uint8_t*, size_t));
-void SHA384_Final _((uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*));
-char* SHA384_End _((SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]));
-char* SHA384_Data _((const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]));
-char *SHA384_File _((char *, char *));
-int SHA384_Equal _((SHA384_CTX*, SHA384_CTX*));
-
-void SHA512_Init _((SHA512_CTX*));
-void SHA512_Update _((SHA512_CTX*, const uint8_t*, size_t));
-void SHA512_Final _((uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*));
-char* SHA512_End _((SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]));
-char* SHA512_Data _((const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]));
-char *SHA512_File _((char *, char *));
-int SHA512_Equal _((SHA512_CTX*, SHA512_CTX*));
+#define SHA512_End rb_Digest_SHA512_End
+#define SHA512_Last rb_Digest_SHA512_Last
+#define SHA512_Transform rb_Digest_SHA512_Transform
+#define SHA512_Final(d, c) SHA512_Finish(c, d)
+#endif /* RUBY */
+
+#ifndef NOPROTO
+
+int SHA256_Init(SHA256_CTX *);
+void SHA256_Update(SHA256_CTX*, const uint8_t*, size_t);
+int SHA256_Final(uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*);
+char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
+char* SHA256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
+
+int SHA384_Init(SHA384_CTX*);
+void SHA384_Update(SHA384_CTX*, const uint8_t*, size_t);
+int SHA384_Final(uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
+char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
+char* SHA384_Data(const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
+
+int SHA512_Init(SHA512_CTX*);
+void SHA512_Update(SHA512_CTX*, const uint8_t*, size_t);
+int SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
+char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
+char* SHA512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
+
+#else /* NOPROTO */
+
+int SHA256_Init();
+void SHA256_Update();
+#ifdef RUBY
+int SHA256_Finish();
+#else
+int SHA256_Final();
+#endif /* RUBY */
+char* SHA256_End();
+char* SHA256_Data();
+
+int SHA384_Init();
+void SHA384_Update();
+#ifdef RUBY
+int SHA384_Finish();
+#else
+int SHA384_Final();
+#endif /* RUBY */
+char* SHA384_End();
+char* SHA384_Data();
+
+int SHA512_Init();
+void SHA512_Update();
+#ifdef RUBY
+int SHA512_Finish();
+#else
+int SHA512_Final();
+#endif /* RUBY */
+char* SHA512_End();
+char* SHA512_Data();
+
+#endif /* NOPROTO */
#ifdef __cplusplus
}
diff --git a/ext/digest/sha2/sha2cc.h b/ext/digest/sha2/sha2cc.h
new file mode 100644
index 0000000000..1245a2e2c7
--- /dev/null
+++ b/ext/digest/sha2/sha2cc.h
@@ -0,0 +1,70 @@
+#define COMMON_DIGEST_FOR_OPENSSL 1
+#include <CommonCrypto/CommonDigest.h>
+
+/*
+ * Prior to 10.5, OpenSSL-compatible definitions are missing for
+ * SHA2 macros, though the CC_ versions are present.
+ * Add the missing definitions we actually use here if needed.
+ * Note that the definitions are the argless 10.6+-style.
+ * The weird CTX mismatch is copied from the 10.6 header.
+ */
+#ifndef SHA256_DIGEST_LENGTH
+#define SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH
+#define SHA256_CTX CC_SHA256_CTX
+#define SHA256_Update CC_SHA256_Update
+#define SHA256_Final CC_SHA256_Final
+#endif /* !defined SHA256_DIGEST_LENGTH */
+
+#ifndef SHA384_DIGEST_LENGTH
+#define SHA384_DIGEST_LENGTH CC_SHA384_DIGEST_LENGTH
+#define SHA512_CTX CC_SHA512_CTX
+#define SHA384_Update CC_SHA384_Update
+#define SHA384_Final CC_SHA384_Final
+#endif /* !defined SHA384_DIGEST_LENGTH */
+
+#ifndef SHA512_DIGEST_LENGTH
+#define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH
+#define SHA512_Update CC_SHA512_Update
+#define SHA512_Final CC_SHA512_Final
+#endif /* !defined SHA512_DIGEST_LENGTH */
+
+#define SHA256_BLOCK_LENGTH CC_SHA256_BLOCK_BYTES
+#define SHA384_BLOCK_LENGTH CC_SHA384_BLOCK_BYTES
+#define SHA512_BLOCK_LENGTH CC_SHA512_BLOCK_BYTES
+
+#define SHA384_CTX CC_SHA512_CTX
+
+static DEFINE_UPDATE_FUNC_FOR_UINT(SHA256)
+static DEFINE_FINISH_FUNC_FROM_FINAL(SHA256)
+static DEFINE_UPDATE_FUNC_FOR_UINT(SHA384)
+static DEFINE_FINISH_FUNC_FROM_FINAL(SHA384)
+static DEFINE_UPDATE_FUNC_FOR_UINT(SHA512)
+static DEFINE_FINISH_FUNC_FROM_FINAL(SHA512)
+
+
+#undef SHA256_Update
+#undef SHA256_Finish
+#define SHA256_Update rb_digest_SHA256_update
+#define SHA256_Finish rb_digest_SHA256_finish
+
+#undef SHA384_Update
+#undef SHA384_Finish
+#define SHA384_Update rb_digest_SHA384_update
+#define SHA384_Finish rb_digest_SHA384_finish
+
+#undef SHA512_Update
+#undef SHA512_Finish
+#define SHA512_Update rb_digest_SHA512_update
+#define SHA512_Finish rb_digest_SHA512_finish
+
+/*
+ * Pre-10.6 defines are with args, which don't match the argless use in
+ * the function pointer inits. Thus, we redefine SHA*_Init as well.
+ * This is a NOP on 10.6+.
+ */
+#undef SHA256_Init
+#define SHA256_Init CC_SHA256_Init
+#undef SHA384_Init
+#define SHA384_Init CC_SHA384_Init
+#undef SHA512_Init
+#define SHA512_Init CC_SHA512_Init
diff --git a/ext/digest/sha2/sha2hl.c b/ext/digest/sha2/sha2hl.c
deleted file mode 100644
index 03fde538c3..0000000000
--- a/ext/digest/sha2/sha2hl.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/* $NetBSD: sha2hl.c,v 1.1 2001/03/12 09:08:40 agc Exp $ */
-/* $RoughId: sha2hl.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id$ */
-
-/*
- * sha2hl.c
- * This code includes some functions taken from sha2.c, hence the
- * following licence reproduction.
- *
- * This code is not a verbatim copy, since some routines have been added,
- * and some bugs have been fixed.
- *
- * Version 1.0.0beta1
- *
- * Written by Aaron D. Gifford <me@aarongifford.com>
- *
- * Copyright 2000 Aaron D. Gifford. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include "sha2.h"
-
-#ifndef lint
-/* __RCSID("$NetBSD: sha2hl.c,v 1.1 2001/03/12 09:08:40 agc Exp $"); */
-#endif /* not lint */
-
-/* #include "namespace.h" */
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-/*
- * Constant used by SHA256/384/512_End() functions for converting the
- * digest to a readable hexadecimal character string:
- */
-static const char sha2_hex_digits[] = "0123456789abcdef";
-
-char *
-SHA256_File(char *filename, char *buf)
-{
- uint8_t buffer[BUFSIZ * 20];
- SHA256_CTX ctx;
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA256_Init(&ctx);
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- return (0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- SHA256_Update(&ctx, buffer, (size_t) num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return (num < 0 ? 0 : SHA256_End(&ctx, buf));
-}
-
-
-char *
-SHA256_End(SHA256_CTX *ctx, char buffer[])
-{
- uint8_t digest[SHA256_DIGEST_LENGTH], *d = digest;
- uint8_t *ret;
- int i;
-
- /* Sanity check: */
- assert(ctx != NULL);
-
- if ((ret = buffer) != NULL) {
- SHA256_Final(digest, ctx);
-
- for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char) 0;
- } else {
- (void) memset(ctx, 0, sizeof(SHA256_CTX));
- }
- (void) memset(digest, 0, SHA256_DIGEST_LENGTH);
- return ret;
-}
-
-char *
-SHA256_Data(const uint8_t * data, size_t len, char *digest)
-{
- SHA256_CTX ctx;
-
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, data, len);
- return SHA256_End(&ctx, digest);
-}
-
-char *
-SHA384_File(char *filename, char *buf)
-{
- SHA384_CTX ctx;
- uint8_t buffer[BUFSIZ * 20];
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA384_Init(&ctx);
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- return (0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- SHA384_Update(&ctx, buffer, (size_t) num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return (num < 0 ? 0 : SHA384_End(&ctx, buf));
-}
-
-char *
-SHA384_End(SHA384_CTX * ctx, char buffer[])
-{
- uint8_t digest[SHA384_DIGEST_LENGTH], *d = digest;
- uint8_t *ret;
- int i;
-
- /* Sanity check: */
- assert(ctx != NULL);
-
- if ((ret = buffer) != NULL) {
- SHA384_Final(digest, ctx);
-
- for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char) 0;
- } else {
- (void) memset(ctx, 0, sizeof(SHA384_CTX));
- }
- (void) memset(digest, 0, SHA384_DIGEST_LENGTH);
- return ret;
-}
-
-char *
-SHA384_Data(const uint8_t * data, size_t len, char *digest)
-{
- SHA384_CTX ctx;
-
- SHA384_Init(&ctx);
- SHA384_Update(&ctx, data, len);
- return SHA384_End(&ctx, digest);
-}
-
-char *
-SHA512_File(char *filename, char *buf)
-{
- SHA512_CTX ctx;
- uint8_t buffer[BUFSIZ * 20];
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA512_Init(&ctx);
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- return (0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- SHA512_Update(&ctx, buffer, (size_t) num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return (num < 0 ? 0 : SHA512_End(&ctx, buf));
-}
-
-char *
-SHA512_End(SHA512_CTX * ctx, char buffer[])
-{
- uint8_t digest[SHA512_DIGEST_LENGTH], *d = digest;
- uint8_t *ret;
- int i;
-
- /* Sanity check: */
- assert(ctx != NULL);
-
- if ((ret = buffer) != NULL) {
- SHA512_Final(digest, ctx);
-
- for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char) 0;
- } else {
- (void) memset(ctx, 0, sizeof(SHA512_CTX));
- }
- (void) memset(digest, 0, SHA512_DIGEST_LENGTH);
- return ret;
-}
-
-char *
-SHA512_Data(const uint8_t * data, size_t len, char *digest)
-{
- SHA512_CTX ctx;
-
- SHA512_Init(&ctx);
- SHA512_Update(&ctx, data, len);
- return SHA512_End(&ctx, digest);
-}
diff --git a/ext/digest/sha2/sha2init.c b/ext/digest/sha2/sha2init.c
index 4b14031811..3923e3724c 100644
--- a/ext/digest/sha2/sha2init.c
+++ b/ext/digest/sha2/sha2init.c
@@ -1,47 +1,74 @@
/* $RoughId: sha2init.c,v 1.3 2001/07/13 20:00:43 knu Exp $ */
/* $Id$ */
-#include "digest.h"
+#include <ruby/ruby.h>
+#include "../digest.h"
+#if defined(SHA2_USE_COMMONDIGEST)
+#include "sha2cc.h"
+#else
#include "sha2.h"
+#endif
#define FOREACH_BITLEN(func) func(256) func(384) func(512)
#define DEFINE_ALGO_METADATA(bitlen) \
-static algo_t sha##bitlen = { \
+static const rb_digest_metadata_t sha##bitlen = { \
+ RUBY_DIGEST_API_VERSION, \
SHA##bitlen##_DIGEST_LENGTH, \
+ SHA##bitlen##_BLOCK_LENGTH, \
sizeof(SHA##bitlen##_CTX), \
- (hash_init_func_t)SHA##bitlen##_Init, \
- (hash_update_func_t)SHA##bitlen##_Update, \
- (hash_end_func_t)SHA##bitlen##_End, \
- (hash_final_func_t)SHA##bitlen##_Final, \
- (hash_equal_func_t)SHA##bitlen##_Equal, \
+ (rb_digest_hash_init_func_t)SHA##bitlen##_Init, \
+ (rb_digest_hash_update_func_t)SHA##bitlen##_Update, \
+ (rb_digest_hash_finish_func_t)SHA##bitlen##_Finish, \
};
FOREACH_BITLEN(DEFINE_ALGO_METADATA)
+/*
+ * Document-class: Digest::SHA256 < Digest::Base
+ *
+ * Classes for calculating message digests using the SHA-256/384/512
+ * Secure Hash Algorithm(s) by NIST (the US' National Institute of
+ * Standards and Technology), described in FIPS PUB 180-2.
+ *
+ * See SHA2.
+ */
+/*
+ * Document-class: Digest::SHA384 < Digest::Base
+ *
+ * Classes for calculating message digests using the SHA-256/384/512
+ * Secure Hash Algorithm(s) by NIST (the US' National Institute of
+ * Standards and Technology), described in FIPS PUB 180-2.
+ *
+ * See SHA2.
+ */
+/*
+ * Document-class: Digest::SHA512 < Digest::Base
+ *
+ * Classes for calculating message digests using the SHA-256/384/512
+ * Secure Hash Algorithm(s) by NIST (the US' National Institute of
+ * Standards and Technology), described in FIPS PUB 180-2.
+ *
+ * See SHA2.
+ */
void
-Init_sha2()
+Init_sha2(void)
{
- VALUE mDigest, cDigest_Base;
- ID id_metadata;
+ VALUE mDigest, cDigest_Base, cDigest_SHA2;
+ ID id_metadata = rb_id_metadata();
-#define DECLARE_ALGO_CLASS(bitlen) \
- VALUE cDigest_SHA##bitlen;
+#if 0
+ mDigest = rb_define_module("Digest"); /* let rdoc know */
+#endif
+ mDigest = rb_digest_namespace();
+ cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base"));
- FOREACH_BITLEN(DECLARE_ALGO_CLASS)
+ cDigest_SHA2 = rb_define_class_under(mDigest, "SHA256", cDigest_Base);
+ rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha256));
- rb_require("digest.so");
+ cDigest_SHA2 = rb_define_class_under(mDigest, "SHA384", cDigest_Base);
+ rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha384));
- id_metadata = rb_intern("metadata");
-
- mDigest = rb_path2class("Digest");
- cDigest_Base = rb_path2class("Digest::Base");
-
-#define DEFINE_ALGO_CLASS(bitlen) \
- cDigest_SHA##bitlen = rb_define_class_under(mDigest, "SHA" #bitlen, cDigest_Base); \
-\
- rb_cvar_set(cDigest_SHA##bitlen, id_metadata, \
- Data_Wrap_Struct(rb_cObject, 0, 0, &sha##bitlen), Qtrue);
-
- FOREACH_BITLEN(DEFINE_ALGO_CLASS)
+ cDigest_SHA2 = rb_define_class_under(mDigest, "SHA512", cDigest_Base);
+ rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha512));
}
diff --git a/ext/digest/test.sh b/ext/digest/test.sh
deleted file mode 100644
index 6fb07d2177..0000000000
--- a/ext/digest/test.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-#
-# $RoughId: test.sh,v 1.5 2001/07/13 15:38:27 knu Exp $
-# $Id$
-
-RUBY=${RUBY:=ruby}
-MAKE=${MAKE:=make}
-CFLAGS=${CFLAGS:=-Wall}
-
-${RUBY} extconf.rb --with-cflags="${CFLAGS}"
-${MAKE} clean
-${MAKE}
-
-mkdir -p lib/digest
-
-for algo in md5 rmd160 sha1 sha2; do
- args=--with-cflags="${CFLAGS}"
-
- if [ $WITH_BUNDLED_ENGINES ]; then
- args="$args --with-bundled-$algo"
- fi
-
- (cd $algo &&
- ${RUBY} extconf.rb $args;
- ${MAKE} clean;
- ${MAKE})
- ln -sf ../../$algo/$algo.so lib/digest/
-done
-
-${RUBY} -I. -I./lib test.rb
-
-rm lib/digest/*.so
-rmdir lib/digest
diff --git a/ext/dl/.cvsignore b/ext/dl/.cvsignore
deleted file mode 100644
index 6d884b6cec..0000000000
--- a/ext/dl/.cvsignore
+++ /dev/null
@@ -1,8 +0,0 @@
-Makefile
-mkmf.log
-dlconfig.h
-dlconfig.rb
-*.func
-*.o
-*~
-*.def
diff --git a/ext/dl/depend b/ext/dl/depend
deleted file mode 100644
index fba3df7a3d..0000000000
--- a/ext/dl/depend
+++ /dev/null
@@ -1,46 +0,0 @@
-LDSHARED_TEST = $(LDSHARED) $(LDFLAGS) test/test.o -o test/libtest.so $(LOCAL_LIBS)
-
-libtest.so: test/libtest.so
-
-test/libtest.so: test/test.o $(srcdir)/test/libtest.def
- $(RUBY) -rftools -e 'ARGV.each do|d|File.mkpath(File.dirname(d))end' $@
- $(LDSHARED_TEST:dl.def=test/libtest.def)
-
-test/test.o: $(srcdir)/test/test.c
- @$(RUBY) -rftools -e 'File.mkpath(*ARGV)' test
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/test/test.c -o $@
-
-test:: dl.so libtest.so force
- $(RUBY) -I. -I$(srcdir)/lib $(srcdir)/test/test.rb
-
-force:
-
-.PHONY: force test
-
-allclean: distclean
- @rm -f $(CLEANFILES) $(DISTCLEANFILES)
-
-$(OBJS): ./dlconfig.h
-
-sym.o: dl.h call.func
-
-dl.o: dl.h callback.func cbtable.func
-
-ptr.o: dl.h
-
-handle.o: dl.h
-
-call.func: $(srcdir)/mkcall.rb ./dlconfig.rb
- @echo "Generating call.func"
- @$(RUBY) $(srcdir)/mkcall.rb > $@
-
-callback.func: $(srcdir)/mkcallback.rb ./dlconfig.rb
- @echo "Generating callback.func"
- @$(RUBY) $(srcdir)/mkcallback.rb > $@
-
-cbtable.func: $(srcdir)/mkcbtable.rb ./dlconfig.rb
- @echo "Generating cbtable.func"
- @$(RUBY) $(srcdir)/mkcbtable.rb > $@
-
-debug:
- $(MAKE) CPPFLAGS="$(CPPFLAGS) -DDEBUG"
diff --git a/ext/dl/dl.c b/ext/dl/dl.c
deleted file mode 100644
index df8089e5aa..0000000000
--- a/ext/dl/dl.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/*
- * $Id$
- */
-
-#include <ruby.h>
-#include <rubyio.h>
-#include <ctype.h>
-#include "dl.h"
-
-VALUE rb_mDL;
-VALUE rb_eDLError;
-VALUE rb_eDLTypeError;
-
-static VALUE DLFuncTable;
-static void *rb_dl_callback_table[CALLBACK_TYPES][MAX_CALLBACK];
-static ID id_call;
-
-static int
-rb_dl_scan_callback_args(long stack[], const char *proto,
- int *argc, VALUE argv[])
-{
- int i;
- long *sp;
- VALUE val;
-
- sp = stack;
- for (i=1; proto[i]; i++) {
- switch (proto[i]) {
- case 'C':
- {
- char v;
- v = (char)(*sp);
- sp++;
- val = INT2NUM(v);
- }
- break;
- case 'H':
- {
- short v;
- v = (short)(*sp);
- sp++;
- val = INT2NUM(v);
- }
- break;
- case 'I':
- {
- int v;
- v = (int)(*sp);
- sp++;
- val = INT2NUM(v);
- }
- break;
- case 'L':
- {
- long v;
- v = (long)(*sp);
- sp++;
- val = INT2NUM(v);
- }
- break;
- case 'F':
- {
- float v;
- memcpy(&v, sp, sizeof(float));
- sp += sizeof(float)/sizeof(long);
- val = rb_float_new(v);
- }
- break;
- case 'D':
- {
- double v;
- memcpy(&v, sp, sizeof(double));
- sp += sizeof(double)/sizeof(long);
- val = rb_float_new(v);
- }
- break;
- case 'P':
- {
- void *v;
- memcpy(&v, sp, sizeof(void*));
- sp++;
- val = rb_dlptr_new(v, 0, 0);
- }
- break;
- case 'S':
- {
- char *v;
- memcpy(&v, sp, sizeof(void*));
- sp++;
- val = rb_tainted_str_new2(v);
- }
- break;
- default:
- rb_raise(rb_eDLTypeError, "unsupported type `%c'", proto[i]);
- break;
- }
- argv[i-1] = val;
- }
- *argc = (i - 1);
-
- return (*argc);
-}
-
-#include "callback.func"
-
-static void
-init_dl_func_table(){
-#include "cbtable.func"
-}
-
-void *
-dlmalloc(size_t size)
-{
- DEBUG_CODE2({
- void *ptr;
-
- printf("dlmalloc(%d)",size);
- ptr = xmalloc(size);
- printf(":0x%x\n",ptr);
- return ptr;
- },
- {
- return xmalloc(size);
- });
-}
-
-void *
-dlrealloc(void *ptr, size_t size)
-{
- DEBUG_CODE({
- printf("dlrealloc(0x%x,%d)\n",ptr,size);
- });
- return xrealloc(ptr, size);
-}
-
-void
-dlfree(void *ptr)
-{
- DEBUG_CODE({
- printf("dlfree(0x%x)\n",ptr);
- });
- xfree(ptr);
-}
-
-char*
-dlstrdup(const char *str)
-{
- char *newstr;
-
- newstr = (char*)dlmalloc(strlen(str)+1);
- strcpy(newstr,str);
-
- return newstr;
-}
-
-size_t
-dlsizeof(const char *cstr)
-{
- size_t size;
- int i, len, n, dlen;
- char *d;
-
- len = strlen(cstr);
- size = 0;
- for (i=0; i<len; i++) {
- n = 1;
- if (isdigit(cstr[i+1])) {
- dlen = 1;
- while (isdigit(cstr[i+dlen])) { dlen ++; };
- dlen --;
- d = ALLOCA_N(char, dlen + 1);
- strncpy(d, cstr + i + 1, dlen);
- d[dlen] = '\0';
- n = atoi(d);
- }
- else{
- dlen = 0;
- }
-
- switch (cstr[i]) {
- case 'I':
- DLALIGN(0,size,INT_ALIGN);
- case 'i':
- size += sizeof(int) * n;
- break;
- case 'L':
- DLALIGN(0,size,LONG_ALIGN);
- case 'l':
- size += sizeof(long) * n;
- break;
- case 'F':
- DLALIGN(0,size,FLOAT_ALIGN);
- case 'f':
- size += sizeof(float) * n;
- break;
- case 'D':
- DLALIGN(0,size,DOUBLE_ALIGN);
- case 'd':
- size += sizeof(double) * n;
- break;
- case 'C':
- case 'c':
- size += sizeof(char) * n;
- break;
- case 'H':
- DLALIGN(0,size,SHORT_ALIGN);
- case 'h':
- size += sizeof(short) * n;
- break;
- case 'P':
- case 'S':
- DLALIGN(0,size,VOIDP_ALIGN);
- case 'p':
- case 's':
- size += sizeof(void*) * n;
- break;
- default:
- rb_raise(rb_eDLTypeError, "unexpected type '%c'", cstr[i]);
- break;
- }
- i += dlen;
- }
-
- return size;
-}
-
-static float *
-c_farray(VALUE v, long *size)
-{
- int i, len;
- float *ary;
- VALUE e;
-
- len = RARRAY(v)->len;
- *size = sizeof(float) * len;
- ary = dlmalloc(*size);
- for (i=0; i < len; i++) {
- e = rb_ary_entry(v, i);
- switch (TYPE(e)) {
- case T_FLOAT:
- ary[i] = (float)(RFLOAT(e)->value);
- break;
- case T_NIL:
- ary[i] = 0.0;
- break;
- default:
- rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
- break;
- }
- }
-
- return ary;
-}
-
-static double *
-c_darray(VALUE v, long *size)
-{
- int i, len;
- double *ary;
- VALUE e;
-
- len = RARRAY(v)->len;
- *size = sizeof(double) * len;
- ary = dlmalloc(*size);
- for (i=0; i < len; i++) {
- e = rb_ary_entry(v, i);
- switch (TYPE(e)) {
- case T_FLOAT:
- ary[i] = (double)(RFLOAT(e)->value);
- break;
- case T_NIL:
- ary[i] = 0.0;
- break;
- default:
- rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
- break;
- }
- }
-
- return ary;
-}
-
-static long *
-c_larray(VALUE v, long *size)
-{
- int i, len;
- long *ary;
- VALUE e;
-
- len = RARRAY(v)->len;
- *size = sizeof(long) * len;
- ary = dlmalloc(*size);
- for (i=0; i < len; i++) {
- e = rb_ary_entry(v, i);
- switch (TYPE(e)) {
- case T_FIXNUM:
- case T_BIGNUM:
- ary[i] = (long)(NUM2INT(e));
- break;
- case T_NIL:
- ary[i] = 0;
- break;
- default:
- rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
- break;
- }
- }
-
- return ary;
-}
-
-static int *
-c_iarray(VALUE v, long *size)
-{
- int i, len;
- int *ary;
- VALUE e;
-
- len = RARRAY(v)->len;
- *size = sizeof(int) * len;
- ary = dlmalloc(*size);
- for (i=0; i < len; i++) {
- e = rb_ary_entry(v, i);
- switch (TYPE(e)) {
- case T_FIXNUM:
- case T_BIGNUM:
- ary[i] = (int)(NUM2INT(e));
- break;
- case T_NIL:
- ary[i] = 0;
- break;
- default:
- rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
- break;
- }
- }
-
- return ary;
-}
-
-static short *
-c_harray(VALUE v, long *size)
-{
- int i, len;
- short *ary;
- VALUE e;
-
- len = RARRAY(v)->len;
- *size = sizeof(short) * len;
- ary = dlmalloc(*size);
- for (i=0; i < len; i++) {
- e = rb_ary_entry(v, i);
- switch (TYPE(e)) {
- case T_FIXNUM:
- case T_BIGNUM:
- ary[i] = (short)(NUM2INT(e));
- break;
- case T_NIL:
- ary[i] = 0;
- break;
- default:
- rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
- break;
- }
- }
-
- return ary;
-}
-
-static char *
-c_carray(VALUE v, long *size)
-{
- int i, len;
- char *ary;
- VALUE e;
-
- len = RARRAY(v)->len;
- *size = sizeof(char) * len;
- ary = dlmalloc(*size);
- for (i=0; i < len; i++) {
- e = rb_ary_entry(v, i);
- switch (TYPE(e)) {
- case T_FIXNUM:
- case T_BIGNUM:
- ary[i] = (char)(NUM2INT(e));
- break;
- case T_NIL:
- ary[i] = 0;
- break;
- default:
- rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
- break;
- }
- }
-
- return ary;
-}
-
-static void *
-c_parray(VALUE v, long *size)
-{
- int i, len;
- void **ary;
- VALUE e, tmp;
-
- len = RARRAY(v)->len;
- *size = sizeof(void*) * len;
- ary = dlmalloc(*size);
- for (i=0; i < len; i++) {
- e = rb_ary_entry(v, i);
- switch (TYPE(e)) {
- default:
- tmp = rb_check_string_type(e);
- if (NIL_P(tmp)) {
- rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
- }
- e = tmp;
- /* fall through */
- case T_STRING:
- rb_check_safe_str(e);
- {
- char *str, *src;
- src = RSTRING(e)->ptr;
- str = dlstrdup(src);
- ary[i] = (void*)str;
- }
- break;
- case T_NIL:
- ary[i] = NULL;
- break;
- case T_DATA:
- if (rb_obj_is_kind_of(e, rb_cDLPtrData)) {
- struct ptr_data *pdata;
- Data_Get_Struct(e, struct ptr_data, pdata);
- ary[i] = (void*)(pdata->ptr);
- }
- else{
- e = rb_funcall(e, rb_intern("to_ptr"), 0);
- if (rb_obj_is_kind_of(e, rb_cDLPtrData)) {
- struct ptr_data *pdata;
- Data_Get_Struct(e, struct ptr_data, pdata);
- ary[i] = (void*)(pdata->ptr);
- }
- else{
- rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
- }
- }
- break;
- }
- }
-
- return ary;
-}
-
-void *
-rb_ary2cary(char t, VALUE v, long *size)
-{
- int len;
- VALUE val0;
-
- val0 = rb_check_array_type(v);
- if(NIL_P(TYPE(val0))) {
- rb_raise(rb_eDLTypeError, "an array is expected.");
- }
- v = val0;
-
- len = RARRAY(v)->len;
- if (len == 0) {
- return NULL;
- }
-
- if (!size) {
- size = ALLOCA_N(long,1);
- }
-
- val0 = rb_ary_entry(v,0);
- switch (TYPE(val0)) {
- case T_FIXNUM:
- case T_BIGNUM:
- switch (t) {
- case 'C': case 'c':
- return (void*)c_carray(v,size);
- case 'H': case 'h':
- return (void*)c_harray(v,size);
- case 'I': case 'i':
- return (void*)c_iarray(v,size);
- case 'L': case 'l': case 0:
- return (void*)c_larray(v,size);
- default:
- rb_raise(rb_eDLTypeError, "type mismatch");
- }
- case T_STRING:
- return (void*)c_parray(v,size);
- case T_FLOAT:
- switch (t) {
- case 'F': case 'f':
- return (void*)c_farray(v,size);
- case 'D': case 'd': case 0:
- return (void*)c_darray(v,size);
- }
- rb_raise(rb_eDLTypeError, "type mismatch");
- case T_DATA:
- if (rb_obj_is_kind_of(val0, rb_cDLPtrData)) {
- return (void*)c_parray(v,size);
- }
- else{
- val0 = rb_funcall(val0, rb_intern("to_ptr"), 0);
- if (rb_obj_is_kind_of(val0, rb_cDLPtrData)) {
- return (void*)c_parray(v,size);
- }
- }
- rb_raise(rb_eDLTypeError, "type mismatch");
- case T_NIL:
- return (void*)c_parray(v, size);
- default:
- rb_raise(rb_eDLTypeError, "unsupported type");
- }
-}
-
-VALUE
-rb_str_to_ptr(VALUE self)
-{
- char *ptr;
- int len;
-
- len = RSTRING(self)->len;
- ptr = (char*)dlmalloc(len + 1);
- memcpy(ptr, RSTRING(self)->ptr, len);
- ptr[len] = '\0';
- return rb_dlptr_new((void*)ptr,len,dlfree);
-}
-
-VALUE
-rb_ary_to_ptr(int argc, VALUE argv[], VALUE self)
-{
- void *ptr;
- VALUE t;
- long size;
-
- switch (rb_scan_args(argc, argv, "01", &t)) {
- case 1:
- ptr = rb_ary2cary(StringValuePtr(t)[0], self, &size);
- break;
- case 0:
- ptr = rb_ary2cary(0, self, &size);
- break;
- }
- return ptr ? rb_dlptr_new(ptr, size, dlfree) : Qnil;
-}
-
-VALUE
-rb_io_to_ptr(VALUE self)
-{
- OpenFile *fptr;
- FILE *fp;
-
- GetOpenFile(self, fptr);
- fp = fptr->f;
-
- return fp ? rb_dlptr_new(fp, 0, 0) : Qnil;
-}
-
-VALUE
-rb_dl_dlopen(int argc, VALUE argv[], VALUE self)
-{
- rb_secure(4);
- return rb_class_new_instance(argc, argv, rb_cDLHandle);
-}
-
-VALUE
-rb_dl_malloc(VALUE self, VALUE size)
-{
- rb_secure(4);
- return rb_dlptr_malloc(DLNUM2LONG(size), dlfree);
-}
-
-VALUE
-rb_dl_strdup(VALUE self, VALUE str)
-{
- SafeStringValue(str);
- return rb_dlptr_new(strdup(RSTRING(str)->ptr), RSTRING(str)->len, dlfree);
-}
-
-static VALUE
-rb_dl_sizeof(VALUE self, VALUE str)
-{
- return INT2NUM(dlsizeof(StringValuePtr(str)));
-}
-
-static VALUE
-rb_dl_callback(int argc, VALUE argv[], VALUE self)
-{
- VALUE type, proc;
- int rettype, entry, i;
- char fname[127];
-
- rb_secure(4);
- proc = Qnil;
- switch (rb_scan_args(argc, argv, "11", &type, &proc)) {
- case 1:
- if (rb_block_given_p()) {
- proc = rb_block_proc();
- }
- else{
- proc = Qnil;
- }
- default:
- break;
- }
-
- StringValue(type);
- switch (RSTRING(type)->ptr[0]) {
- case '0':
- rettype = 0x00;
- break;
- case 'C':
- rettype = 0x01;
- break;
- case 'H':
- rettype = 0x02;
- break;
- case 'I':
- rettype = 0x03;
- break;
- case 'L':
- rettype = 0x04;
- break;
- case 'F':
- rettype = 0x05;
- break;
- case 'D':
- rettype = 0x06;
- break;
- case 'P':
- rettype = 0x07;
- break;
- default:
- rb_raise(rb_eDLTypeError, "unsupported type `%c'", RSTRING(type)->ptr[0]);
- }
-
- entry = -1;
- for (i=0; i < MAX_CALLBACK; i++) {
- if (rb_hash_aref(DLFuncTable, rb_assoc_new(INT2NUM(rettype), INT2NUM(i))) == Qnil) {
- entry = i;
- break;
- }
- }
- if (entry < 0) {
- rb_raise(rb_eDLError, "too many callbacks are defined.");
- }
-
- rb_hash_aset(DLFuncTable,
- rb_assoc_new(INT2NUM(rettype),INT2NUM(entry)),
- rb_assoc_new(type,proc));
- sprintf(fname, "rb_dl_callback_func_%d_%d", rettype, entry);
- return rb_dlsym_new((void (*)())rb_dl_callback_table[rettype][entry],
- fname, RSTRING(type)->ptr);
-}
-
-static VALUE
-rb_dl_remove_callback(VALUE mod, VALUE sym)
-{
- freefunc_t f;
- int i, j;
-
- rb_secure(4);
- f = rb_dlsym2csym(sym);
- for (i=0; i < CALLBACK_TYPES; i++) {
- for (j=0; j < MAX_CALLBACK; j++) {
- if (rb_dl_callback_table[i][j] == f) {
- rb_hash_aset(DLFuncTable, rb_assoc_new(INT2NUM(i),INT2NUM(j)),Qnil);
- break;
- }
- }
- }
- return Qnil;
-}
-
-void
-Init_dl()
-{
- void Init_dlptr();
- void Init_dlsym();
- void Init_dlhandle();
-
- id_call = rb_intern("call");
-
- rb_mDL = rb_define_module("DL");
-
- rb_eDLError = rb_define_class_under(rb_mDL, "DLError", rb_eStandardError);
- rb_eDLTypeError = rb_define_class_under(rb_mDL, "DLTypeError", rb_eDLError);
-
- DLFuncTable = rb_hash_new();
- init_dl_func_table();
- rb_define_const(rb_mDL, "FuncTable", DLFuncTable);
-
- rb_define_const(rb_mDL, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL));
- rb_define_const(rb_mDL, "RTLD_LAZY", INT2NUM(RTLD_LAZY));
- rb_define_const(rb_mDL, "RTLD_NOW", INT2NUM(RTLD_NOW));
-
- rb_define_const(rb_mDL, "ALIGN_INT", INT2NUM(ALIGN_INT));
- rb_define_const(rb_mDL, "ALIGN_LONG", INT2NUM(ALIGN_LONG));
- rb_define_const(rb_mDL, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT));
- rb_define_const(rb_mDL, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT));
- rb_define_const(rb_mDL, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE));
- rb_define_const(rb_mDL, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP));
-
- rb_define_const(rb_mDL, "MAX_ARG", INT2NUM(MAX_ARG));
- rb_define_const(rb_mDL, "DLSTACK", rb_tainted_str_new2(DLSTACK_METHOD));
-
- rb_define_module_function(rb_mDL, "dlopen", rb_dl_dlopen, -1);
- rb_define_module_function(rb_mDL, "callback", rb_dl_callback, -1);
- rb_define_module_function(rb_mDL, "define_callback", rb_dl_callback, -1);
- rb_define_module_function(rb_mDL, "remove_callback", rb_dl_remove_callback, 1);
- rb_define_module_function(rb_mDL, "malloc", rb_dl_malloc, 1);
- rb_define_module_function(rb_mDL, "strdup", rb_dl_strdup, 1);
- rb_define_module_function(rb_mDL, "sizeof", rb_dl_sizeof, 1);
-
- Init_dlptr();
- Init_dlsym();
- Init_dlhandle();
-
- rb_define_const(rb_mDL, "FREE", rb_dlsym_new(dlfree, "free", "0P"));
-
- rb_define_method(rb_cString, "to_ptr", rb_str_to_ptr, 0);
- rb_define_method(rb_cArray, "to_ptr", rb_ary_to_ptr, -1);
- rb_define_method(rb_cIO, "to_ptr", rb_io_to_ptr, 0);
-}
diff --git a/ext/dl/dl.def b/ext/dl/dl.def
deleted file mode 100644
index cdab4af90d..0000000000
--- a/ext/dl/dl.def
+++ /dev/null
@@ -1,59 +0,0 @@
-EXPORTS
-Init_dl
-dlfree
-dlmalloc
-dlrealloc
-dlstrdup
-rb_ary_to_ptr
-rb_dl_dlopen
-rb_dl_malloc
-rb_dl_strdup
-rb_eDLError
-rb_eDLTypeError
-rb_io_to_ptr
-rb_mDL
-rb_str_to_ptr
-Init_dlhandle
-rb_cDLHandle
-rb_dlhandle_close
-rb_dlhandle_disable_close
-rb_dlhandle_enable_close
-rb_dlhandle_sym
-Init_dlptr
-rb_cDLPtrData
-rb_dlmem_each
-rb_dlptr2cptr
-rb_dlptr_malloc
-rb_dlptr_aref
-rb_dlptr_aset
-rb_dlptr_cmp
-rb_dlptr_define_data_type
-rb_dlptr_define_struct
-rb_dlptr_define_union
-rb_dlptr_eql
-rb_dlptr_free_get
-rb_dlptr_free_set
-rb_dlptr_get_data_type
-rb_dlptr_inspect
-rb_dlptr_minus
-rb_dlptr_new
-rb_dlptr_new2
-rb_dlptr_null_p
-rb_dlptr_plus
-rb_dlptr_ptr
-rb_dlptr_ref
-rb_dlptr_to_array
-rb_dlptr_to_i
-rb_dlptr_to_s
-rb_dlptr_to_str
-rb_mDLMemorySpace
-Init_dlsym
-rb_cDLSymbol
-rb_dlsym2csym
-rb_dlsym_call
-rb_dlsym_cproto
-rb_dlsym_inspect
-rb_dlsym_name
-rb_dlsym_new
-rb_dlsym_proto
-rb_dlsym_to_ptr
diff --git a/ext/dl/dl.h b/ext/dl/dl.h
deleted file mode 100644
index 1faa316cf1..0000000000
--- a/ext/dl/dl.h
+++ /dev/null
@@ -1,313 +0,0 @@
-/* -*- C -*-
- * $Id$
- */
-
-#ifndef RUBY_DL_H
-#define RUBY_DL_H
-
-#include <ruby.h>
-#include <dlconfig.h>
-
-#if defined(HAVE_DLFCN_H)
-# include <dlfcn.h>
-# /* some stranger systems may not define all of these */
-#ifndef RTLD_LAZY
-#define RTLD_LAZY 0
-#endif
-#ifndef RTLD_GLOBAL
-#define RTLD_GLOBAL 0
-#endif
-#ifndef RTLD_NOW
-#define RTLD_NOW 0
-#endif
-#else
-# if defined(HAVE_WINDOWS_H)
-# include <windows.h>
-# define dlclose(ptr) FreeLibrary((HINSTANCE)ptr)
-# define dlopen(name,flag) ((void*)LoadLibrary(name))
-# define dlerror() "unknown error"
-# define dlsym(handle,name) ((void*)GetProcAddress(handle,name))
-# define RTLD_LAZY -1
-# define RTLD_NOW -1
-# define RTLD_GLOBAL -1
-# endif
-#endif
-
-#if !defined(StringValue)
-# define StringValue(v) if(TYPE(v) != T_STRING) v = rb_str_to_str(v)
-#endif
-#if !defined(StringValuePtr)
-# define StringValuePtr(v) RSTRING((TYPE(v) == T_STRING) ? (v) : rb_str_to_str(v))->ptr
-#endif
-
-#ifdef DEBUG
-#define DEBUG_CODE(b) {printf("DEBUG:%d\n",__LINE__);b;}
-#define DEBUG_CODE2(b1,b2) {printf("DEBUG:%d\n",__LINE__);b1;}
-#else
-#define DEBUG_CODE(b)
-#define DEBUG_CODE2(b1,b2) b2
-#endif
-
-#define VOID_DLTYPE 0x00
-#define CHAR_DLTYPE 0x01
-#define SHORT_DLTYPE 0x02
-#define INT_DLTYPE 0x03
-#define LONG_DLTYPE 0x04
-#define FLOAT_DLTYPE 0x05
-#define DOUBLE_DLTYPE 0x06
-#define VOIDP_DLTYPE 0x07
-
-#define ARG_TYPE(x,i) (((x) & (0x07 << ((i)*3))) >> ((i)*3))
-#define PUSH_ARG(x,t) do{x <<= 3; x |= t;}while(0)
-#define PUSH_0(x) PUSH_ARG(x,VOID_DLTYPE)
-
-#if SIZEOF_INT == SIZEOF_LONG
-# define PUSH_I(x) PUSH_ARG(x,LONG_DLTYPE)
-# define ANY2I(x) x.l
-# define DLINT(x) (long)x
-#else
-# define PUSH_I(x) PUSH_ARG(x,INT_DLTYPE)
-# define ANY2I(x) x.i
-# define DLINT(x) (int)x
-#endif
-#define PUSH_L(x) PUSH_ARG(x,LONG_DLTYPE)
-#define ANY2L(x) x.l
-#define DLLONG(x) (long)x
-
-#if defined(WITH_TYPE_FLOAT)
-# if SIZEOF_FLOAT == SIZEOF_DOUBLE
-# define PUSH_F(x) PUSH_ARG(x,DOUBLE_DLTYPE)
-# define ANY2F(x) (x.d)
-# define DLFLOAT(x) ((double)x)
-# else
-# define PUSH_F(x) PUSH_ARG(x,FLOAT_DLTYPE)
-# define ANY2F(x) (x.f)
-# define DLFLOAT(x) ((float)x)
-# endif
-#else
-# define PUSH_F(x) PUSH_ARG(x,DOUBLE_DLTYPE)
-# define ANY2F(x) (x.d)
-# define DLFLOAT(x) ((double)x)
-#endif
-#define PUSH_D(x) PUSH_ARG(x,DOUBLE_DLTYPE)
-#define ANY2D(x) (x.d)
-#define DLDOUBLE(x) ((double)x)
-
-#if SIZEOF_INT == SIZEOF_VOIDP && SIZEOF_INT != SIZEOF_LONG
-# define PUSH_P(x) PUSH_ARG(x,INT_DLTYPE)
-# define ANY2P(x) (x.i)
-# define DLVOIDP(x) ((int)x)
-#elif SIZEOF_LONG == SIZEOF_VOIDP
-# define PUSH_P(x) PUSH_ARG(x,LONG_DLTYPE)
-# define ANY2P(x) (x.l)
-# define DLVOIDP(x) ((long)x)
-#else
-# define PUSH_P(x) PUSH_ARG(x,VOIDP_DLTYPE)
-# define ANY2P(x) (x.p)
-# define DLVOIDP(x) ((void*)p)
-#endif
-
-#if defined(WITH_TYPE_CHAR)
-# define PUSH_C(x) PUSH_ARG(x,CHAR_DLTYPE)
-# define ANY2C(x) (x.c)
-# define DLCHAR(x) ((char)x)
-#else
-# define PUSH_C(x) PUSH_I(x)
-# define ANY2C(x) ANY2I(x)
-# define DLCHAR(x) DLINT(x)
-#endif
-
-#if defined(WITH_TYPE_SHORT)
-# define PUSH_H(x) PUSH_ARG(x,SHORT_DLTYPE)
-# define ANY2H(x) (x.h)
-# define DLSHORT(x) ((short)x)
-#else
-# define PUSH_H(x) PUSH_I(x)
-# define ANY2H(x) ANY2I(x)
-# define DLSHORT(x) DLINT(x)
-#endif
-
-#define PUSH_S(x) PUSH_P(x)
-#define ANY2S(x) ANY2P(x)
-#define DLSTR(x) DLVOIDP(x)
-
-#define CBPUSH_0(x) PUSH_0(x)
-#define CBPUSH_C(x) PUSH_C(x)
-#define CBPUSH_H(x) PUSH_H(x)
-#define CBPUSH_I(x) PUSH_I(x)
-#define CBPUSH_L(x) PUSH_L(x)
-#define CBPUSH_F(x) PUSH_F(x)
-#define CBPUSH_D(x) PUSH_D(x)
-#if defined(WITH_CBTYPE_VOIDP)
-# define CBPUSH_P(x) PUSH_ARG(x,VOIDP_DLTYPE)
-#else
-# define CBPUSH_P(x) PUSH_P(x)
-#endif
-
-
-#if defined(USE_INLINE_ASM)
-# if defined(__i386__) && defined(__GNUC__)
-# define DLSTACK
-# define DLSTACK_METHOD "asm"
-# define DLSTACK_REVERSE
-# define DLSTACK_PROTO
-# define DLSTACK_ARGS
-# define DLSTACK_START(sym)
-# define DLSTACK_END(sym)
-# define DLSTACK_PUSH_C(x) asm volatile ("pushl %0" :: "g" (x));
-# define DLSTACK_PUSH_H(x) asm volatile ("pushl %0" :: "g" (x));
-# define DLSTACK_PUSH_I(x) asm volatile ("pushl %0" :: "g" (x));
-# define DLSTACK_PUSH_L(x) asm volatile ("pushl %0" :: "g" (x));
-# define DLSTACK_PUSH_P(x) asm volatile ("pushl %0" :: "g" (x));
-# define DLSTACK_PUSH_F(x) asm volatile ("flds %0"::"g"(x));\
- asm volatile ("subl $4,%esp");\
- asm volatile ("fstps (%esp)");
-# define DLSTACK_PUSH_D(x) asm volatile ("fldl %0"::"g"(x));\
- asm volatile ("subl $8,%esp");\
- asm volatile ("fstpl (%esp)")
-# else
-# error --with-asm is not supported on this machine
-# endif
-#elif defined(USE_DLSTACK)
-# define DLSTACK
-# define DLSTACK_GUARD
-# define DLSTACK_METHOD "dl"
-# define DLSTACK_PROTO long,long,long,long,long,\
- long,long,long,long,long,\
- long,long,long,long,long
-# define DLSTACK_ARGS stack[0],stack[1],stack[2],stack[3],stack[4],\
- stack[5],stack[6],stack[7],stack[8],stack[9],\
- stack[10],stack[11],stack[12],stack[13],stack[14]
-# define DLSTACK_SIZE (sizeof(long)*15)
-# define DLSTACK_START(sym)
-# define DLSTACK_END(sym)
-# define DLSTACK_PUSH_C(x) {long v=(long)x; memcpy(sp,&v,sizeof(long)); sp++;}
-# define DLSTACK_PUSH_H(x) {long v=(long)x; memcpy(sp,&v,sizeof(long)); sp++;}
-# define DLSTACK_PUSH_I(x) {long v=(long)x; memcpy(sp,&v,sizeof(long)); sp++;}
-# define DLSTACK_PUSH_L(x) memcpy(sp,&x,sizeof(long)); sp++;
-# define DLSTACK_PUSH_P(x) memcpy(sp,&x,sizeof(void*)); sp++;
-# define DLSTACK_PUSH_F(x) memcpy(sp,&x,sizeof(float)); sp+=sizeof(float)/sizeof(long);
-# define DLSTACK_PUSH_D(x) memcpy(sp,&x,sizeof(double)); sp+=sizeof(double)/sizeof(long);
-#else
-# define DLSTACK_METHOD "none"
-#endif
-
-extern VALUE rb_mDL;
-extern VALUE rb_mDLMemorySpace;
-extern VALUE rb_cDLHandle;
-extern VALUE rb_cDLSymbol;
-extern VALUE rb_cDLPtrData;
-extern VALUE rb_cDLStructData;
-
-extern VALUE rb_eDLError;
-extern VALUE rb_eDLTypeError;
-
-#if defined(LONG2NUM) && (SIZEOF_LONG == SIZEOF_VOIDP)
-# define DLLONG2NUM(x) LONG2NUM((long)x)
-# define DLNUM2LONG(x) (long)(NUM2LONG(x))
-#else
-# define DLLONG2NUM(x) INT2NUM((long)x)
-# define DLNUM2LONG(x) (long)(NUM2INT(x))
-#endif
-
-typedef struct { char c; void *x; } s_voidp;
-typedef struct { char c; short x; } s_short;
-typedef struct { char c; int x; } s_int;
-typedef struct { char c; long x; } s_long;
-typedef struct { char c; float x; } s_float;
-typedef struct { char c; double x; } s_double;
-
-#define ALIGN_VOIDP (sizeof(s_voidp) - sizeof(void *))
-#define ALIGN_SHORT (sizeof(s_short) - sizeof(short))
-#define ALIGN_INT (sizeof(s_int) - sizeof(int))
-#define ALIGN_LONG (sizeof(s_long) - sizeof(long))
-#define ALIGN_FLOAT (sizeof(s_float) - sizeof(float))
-#define ALIGN_DOUBLE (sizeof(s_double) - sizeof(double))
-
-/* for compatibility */
-#define VOIDP_ALIGN ALIGN_VOIDP
-#define SHORT_ALIGN ALIGN_SHORT
-#define INT_ALIGN ALIGN_INT
-#define LONG_ALIGN ALIGN_LONG
-#define FLOAT_ALIGN ALIGN_FLOAT
-#define DOUBLE_ALIGN ALIGN_DOUBLE
-
-#define DLALIGN(ptr,offset,align) {\
- while( (((unsigned long)((char *)ptr + offset)) % align) != 0 ) offset++;\
-}
-
-typedef void (*freefunc_t)(void *);
-#define DLFREEFUNC(func) ((freefunc_t)(func))
-
-typedef union {
- void* p;
- char c;
- short h;
- int i;
- long l;
- float f;
- double d;
- char *s;
-} ANY_TYPE;
-
-struct dl_handle {
- void *ptr;
- int open;
- int enable_close;
-};
-
-struct sym_data {
- void *func;
- char *name;
- char *type;
- int len;
-};
-
-enum DLPTR_CTYPE {
- DLPTR_CTYPE_UNKNOWN,
- DLPTR_CTYPE_STRUCT,
- DLPTR_CTYPE_UNION
-};
-
-struct ptr_data {
- void *ptr; /* a pointer to the data */
- freefunc_t free; /* free() */
- char *stype; /* array of type specifiers */
- int *ssize; /* size[i] = sizeof(type[i]) > 0 */
- int slen; /* the number of type specifiers */
- ID *ids;
- int ids_num;
- int ctype; /* DLPTR_CTYPE_UNKNOWN, DLPTR_CTYPE_STRUCT, DLPTR_CTYPE_UNION */
- long size;
-};
-
-#define RDLPTR(obj) ((struct ptr_data *)(DATA_PTR(obj)))
-#define RDLSYM(obj) ((struct sym_data *)(DATA_PTR(obj)))
-
-void dlfree(void*);
-void *dlmalloc(size_t);
-void *dlrealloc(void*,size_t);
-char *dlstrdup(const char *);
-size_t dlsizeof(const char *);
-
-void *rb_ary2cary(char t, VALUE ary, long *size);
-
-/*
-void rb_dlmem_delete(void *ptr);
-void rb_dlmem_aset(void *ptr, VALUE obj);
-VALUE rb_dlmem_aref(void *ptr);
-*/
-
-void dlptr_free(struct ptr_data *data);
-void dlptr_init(VALUE val);
-
-VALUE rb_dlptr_new(void *ptr, long size, freefunc_t func);
-VALUE rb_dlptr_new2(VALUE klass, void *ptr, long size, freefunc_t func);
-VALUE rb_dlptr_malloc(long size, freefunc_t func);
-void *rb_dlptr2cptr(VALUE val);
-
-VALUE rb_dlsym_new(void (*func)(), const char *name, const char *type);
-freefunc_t rb_dlsym2csym(VALUE val);
-
-
-#endif /* RUBY_DL_H */
diff --git a/ext/dl/doc/dl.txt b/ext/dl/doc/dl.txt
deleted file mode 100644
index 893bd21d79..0000000000
--- a/ext/dl/doc/dl.txt
+++ /dev/null
@@ -1,266 +0,0 @@
-=begin
-
-= Ruby/DL
-
-Ruby/DL provides an interface to the dynamic linker such as dlopen() on UNIX
-and LoadLibrary() on Windows.
-
-= Building and Installing
-
- $ ruby extconf.rb # to create the Makefile
- $ make # to build the library 'dl.so'
- $ make libtest.so # to build the C library 'libtest.so' for the test script
- $ make test # to run the test script
- $ make install # to install the library
- $ make clean # to remove the created files without Makefile
- $ make distclean # to remove the all created files
-
-= Using Ruby/DL
-
-We should usually use DL::Importable module provided by "dl/import.rb".
-It has high-level functions to access library functions. We use
-DL::Importable module to extend a module as follows:
-
- require "dl/import"
- module LIBC
- extend DL::Importable
- end
-
-Now we can use methods dlload and extern in this module. We load the
-libraries using dlload, and define wrapper methods to library functions
-using extern respectively as follows:
-
- module LIBC
- extend DL::Importable
- dlload "libc.so.6","libm.so.6"
- extern "int strlen(char*)"
- end
- # Note that we should not include the module LIBC from some reason.
-
-We can call the library function strlen() using LIBC.strlen. If the first
-character of given function name is an uppercase, the first character of the
-defined method name becomes lowercase.
-We can also construct memory images of structures and unions using functions
-struct and union which are defined in "dl/struct.rb" as follows:
-
- require "dl/import"
- require "dl/struct"
- module LIBC
- extend DL::Importable
- Timeval = struct [ # define timeval structure.
- "long tv_sec",
- "long tv_uses",
- ]
- end
- val = LIBC::Timeval.malloc # allocate memory.
-
-Notice that the above example takes LIBC::Timeval.malloc to allocate memory,
-rather than LIBC::Timeval.new. It is because DL::Timeval.new is for wrapping
-an object, PtrData, which has already been created.
-
-We can define a callback using the module function "callback" as follows:
-
- module Foo
- extend DL::Importable
- def my_comp(str1,str2)
- str1 <=> str2
- end
- COMPARE = callback "int my_comp(char*,char*)"
- end
-
-where Foo::COMPARE is a Symbol object which invokes the method "my_comp".
-
-DL::Importable module is very useful. However, we sometimes encounter a case
-that we must directly use low-level functions such as dlsym(). In such case,
-we would use DL module functions. They are described in next section.
-
-= DL module
-
-Module DL consists of three classes, a few module functions and constants.
-The class Symbol represents the symbol we can call. The class PtrData
-indicates a memory block such as a pointer in C. An object instantiated from
-the class Handle keeps a handle to opened library.
-
-== Constants
-
-* VERSION
-* MAJOR_VERSION
-* MINOR_VERSION
-* PATCH_VERSION
-* RTLD_GLOBAL
-* RTLD_LAZY
-* RTLD_NOW
-* MAX_ARG
-* MAX_CBARG
-* MAX_CBENT
-
-== Functions
-
-* handle = dlopen(lib){|handle| ... }
- * is quite equal to `Handle.new(lib)'
-
-* sym = set_callback(cbtype, entry){|args| ... }
-* sym = set_callback(cbtype, entry, proc)
- * makes entry-th pre-defined function to call the proc or given block. the
- entry-th pre-defined function is specified by cbtype and entry. cbtype is a
- prototype of the callback. see also the section `Type specifiers' about
- cbtype.
-
-* sym = get_callback(cbtype, entry)
- * returns the Proc object which is given by the above function
- `set_callback'.
-
-* ptr = malloc(size, [free = nil])
- * allocates the size bytes, and returns the pointer as a PtrData object ptr.
-
-* ptr = strdup(str)
- * returns a PtrData object ptr which represents the pointer to a new string
- which is a duplicate of the string str.
-
-* size = sizeof(type)
- * returns the size of type. `sizeof("C") + sizeof("L")' is not equal to
- `sizeof("CL")'. the latter is assumed to returns the enough size of the
- structure `struct foo { char c; long l; }', but the size may not equal to
- `sizeof(foo)' of C.
-
-== Handle class
-
-* handle = Handle.new(lib){|handle| ... }
- * opens a library lib and returns a Handle object handle. if a block is
- given, the handle is automatically closed as the block ends.
-
-* Handle#close
- * closes the handle opened by the above Handle.new(lib).
-
-* sym = Handle#sym(func, prototype = "0"),
- sym = Handle#[func, prototype = nil]
-
- * obtains the pointer to a function called func and returns a Symbol object
- or a DataPtr object. prototype is a string which consists of type
- specifiers, it indicates the function's prototype. see also the section
- `Type specifiers'.
-
-== Symbol class
-
-* sym = Symbol.new(addr, type = nil, name = nil)
- * creates the Symbol object sym with the type type if type is not nil. addr
- is the address where the function is allocated. If type is nil, it returns
- a DataPtr object.
-
-* Symbol::char2type(char)
- * takes a character char that represents a type and returns the type
- specifier of the C language.
-
-* str = Symbol#proto()
- * returns the function prototype.
-
-* str = Symbol#name()
- * Returns the function name.
-
-* str = Symbol#cproto(),
- str = Symbol#to_s()
- * returns the prototype of the C language.
-
-* str = Symbol#inspect()
- * returns the inspectable string.
-
-* r,rs = Symbol#call(arg1,arg2,...,argN),
- r,rs = Symbol#[](arg1,arg2,...,argN)
- * calls the function with parameters arg1, arg2, ..., argN. and the result
- consists of the return value r and parameters rs. rs is an array.
-
-* ptr = Symbol#to_ptr
- * returns the corresponding PtrData object ptr.
-
-== PtrData class
-
-* ptr = PtrData.new(addr, [size = 0, free = nil])
- * returns the PtrData object representing the pointer which indicates the
- address addr. GC frees the memory using the free function.
-
-* PtrData#free=(sym)
- * If you specify a symbol object sym, GC frees the memory using the function
- represented by sym.
-
-* sym = PtrData#free
- * returns a symbol object sym which is used when GC frees the memory. it
- usually configured by `PtrData#free=' or `PtrData.new'.
-
-* size = PtrData#size, PtrData#size=(size)
- * gets and sets allocated size of the memory.
-
-* ary = PtrData#to_a(type, [size])
- * returns an array of the type which specified with type. type must be one of
- 'S','P','I','L','D' and 'F'.
-
-* str = PtrData#to_s([len])
- * returns a string which length is len. if len is omitted, the end of the
- string is '\0'.
-
-* ptr = PtrData#ptr,+@
- * returns the pointed value as a PtrData object ptr.
-
-* ptr = PtrData#ref,-@
- * returns the reference as a PtrData object ptr.
-
-* ptr = PtrData#+
- * returns the PtrData object
-
-* ptr = PtrData#-
- * returns the PtrData object
-
-* PtrData#struct!(type, *members)
- * defines the data type to get access to a structure member with a symbol.
- (see also PtrData#[])
-
-* PtrData#union!(type, *members)
- * defines the data type to get access to a union member with a symbol. (see
- also PtrData#[])
-
-* val = PtrData#[key], PtrData#[key, num = 0]
- * if the key is a string or symbol, this method returns the value of the
- structure/union member which has the type defined by PtrData#
- {struct!,union!}. if the key is a integer value and this object represents
- the pointer ptr, it returns the value of `(ptr + key).to_s(num)'
-
-* PtrData#[key,num]=val, PtrData#[key]=val
- * if the key is a string or symbol, this method substitute the value of the
- structure/union member with val. if the key is a integer value and val is a
- string, this method copies num bytes of val to the memory area ptr using
- memcpy(3).
-
-== Type specifiers
-
-the prototype consists of the following type specifiers, first element of
-prototype represents the type of return value, and remaining elements represent
-the type of each argument.
-
- C : char
- c : char *
- H : short
- h : short *
- I : int
- i : int *
- L : long
- l : long *
- F : float
- f : float *
- D : double
- d : double *
- S : const char *
- s : char *
- A : const type[]
- a : type[] (allocates new memory space)
- P : void * (same as 'p')
- p : void * (same as 'P')
- 0 : void function (this must be a first character of the prototype)
-
-the cbtype consists of type specifiers 0, C, I, H, L, F, D, S and P.
-for example:
-
- DL.callback('IPP'){|ptr1,ptr2|
- str1 = ptr1.ptr.to_s
- str2 = ptr2.ptr.to_s
- str1 <=> str2
- }
-=end
diff --git a/ext/dl/extconf.rb b/ext/dl/extconf.rb
deleted file mode 100644
index beb15ab04c..0000000000
--- a/ext/dl/extconf.rb
+++ /dev/null
@@ -1,193 +0,0 @@
-require 'mkmf'
-
-begin # for the exception SystemExit
-
-$:.unshift File.dirname(__FILE__)
-require 'type'
-
-if( ARGV.include?("--help") )
- print <<EOF
- --help print this messages
- --with-type-char strictly use type 'char'
- --with-type-short strictly use type 'short'
- --with-type-float strictly use type 'float'
- --with-args=<max_arg>
- --with-callback=<max_callback>
- --enable-asm use the embedded assembler for passing arguments.
- (this option is available for i386 machine now.)
- --enable-dlstack use a stack emulation for constructing function call.
-EOF
- exit(0)
-end
-
-($CPPFLAGS || $CFLAGS) << " -I."
-
-if (Config::CONFIG['CC'] =~ /gcc/) # from Win32API
- $CFLAGS << " -fno-defer-pop -fno-omit-frame-pointer"
-end
-
-$with_dlstack ||= true
-$with_asm = ! $with_dlstack
-
-$with_type_int = try_cpp(<<EOF)
-#include "config.h"
-#if SIZEOF_INT == SIZEOF_LONG
-#error int not needed
-#endif
-EOF
-
-$with_type_float = try_cpp(<<EOF)
-#include "config.h"
-#if SIZEOF_FLOAT == SIZEOF_DOUBLE
-#error float not needed
-#endif
-EOF
-
-$with_type_voidp = try_cpp(<<EOF)
-#include "config.h"
-#if SIZEOF_VOIDP == SIZEOF_INT || SIZEOF_VOIDP == SIZEOF_LONG
-#error void* not needed
-#endif
-EOF
-
-$with_type_char = DLTYPE[CHAR][:sym]
-$with_type_short = DLTYPE[SHORT][:sym]
-$with_type_long = DLTYPE[LONG][:sym]
-$with_type_double= DLTYPE[DOUBLE][:sym]
-$with_type_int &= DLTYPE[INT][:sym]
-$with_type_float &= DLTYPE[FLOAT][:sym]
-$with_type_voidp &= DLTYPE[VOIDP][:sym]
-
-$with_type_char = enable_config("type-char", $with_type_char)
-$with_type_short = enable_config("type-short", $with_type_short)
-$with_type_float = enable_config("type-float", $with_type_float)
-
-$with_asm = enable_config("asm", $with_asm)
-$with_dlstack = enable_config("dlstack", $with_dlstack)
-
-args = with_config("args")
-max_arg = nil
-if( $with_asm || $with_dlstack )
- $with_type_char = true
- $with_type_short = true
- $with_type_float = true
- max_arg = 0
-end
-if( args )
- max_arg = args.to_i
- if( !max_arg )
- print("--with-args=<max_arg>\n")
- exit(1)
- end
-end
-max_arg ||= 6
-
-max_callback = with_config("callback","10").to_i
-callback_types = DLTYPE.keys.length
-
-
-$dlconfig_h = <<EOF
-#define MAX_ARG #{max_arg}
-EOF
-
-def dlc_define(const)
- $dlconfig_h << "#if !defined(#{const})\n" +
- "# define #{const}\n" +
- "#endif\n"
-end
-
-$dlconfig_h << "#define MAX_CALLBACK #{max_callback}\n"
-$dlconfig_h << "#define CALLBACK_TYPES #{callback_types}\n"
-if( $with_dlstack )
- $dlconfig_h << "#define USE_DLSTACK\n"
-else
- if( $with_asm )
- $dlconfig_h << "#define USE_INLINE_ASM\n"
- end
-end
-if( $with_type_char )
- $dlconfig_h << "#define WITH_TYPE_CHAR\n"
-end
-if( $with_type_short )
- $dlconfig_h << "#define WITH_TYPE_SHORT\n"
-end
-if( $with_type_long )
- $dlconfig_h << "#define WITH_TYPE_LONG\n"
-end
-if( $with_type_double )
- $dlconfig_h << "#define WITH_TYPE_DOUBLE\n"
-end
-if( $with_type_float )
- $dlconfig_h << "#define WITH_TYPE_FLOAT\n"
-end
-if( $with_type_int )
- $dlconfig_h << "#define WITH_TYPE_INT\n"
-end
-if( $with_type_voidp )
- $dlconfig_h << "#define WITH_TYPE_VOIDP\n"
-end
-
-if( have_header("windows.h") )
- have_library("kernel32")
- have_func("GetLastError", "windows.h")
- dlc_define("HAVE_WINDOWS_H")
- have_windows_h = true
-end
-
-if( have_header("dlfcn.h") )
- dlc_define("HAVE_DLFCN_H")
- have_library("dl")
- have_func("dlopen")
- have_func("dlclose")
- have_func("dlsym")
- if( have_func("dlerror") )
- dlc_define("HAVE_DLERROR")
- end
-elsif ( have_windows_h )
- have_func("LoadLibrary")
- have_func("FreeLibrary")
- have_func("GetProcAddress")
-else
- exit(0)
-end
-
-def File.update(file, str)
- begin
- open(file){|f|f.read} == str
- rescue Errno::ENOENT
- false
- end or open(file, "w"){|f|f.print(str)}
-end
-
-File.update("dlconfig.h", <<EOF)
-#ifndef DLCONFIG_H
-#define DLCONFIG_H
-#{$dlconfig_h}
-#endif /* DLCONFIG_H */
-EOF
-
-File.update("dlconfig.rb", <<EOF)
-MAX_ARG = #{max_arg}
-MAX_CALLBACK = #{max_callback}
-CALLBACK_TYPES = #{callback_types}
-DLTYPE[CHAR][:sym] = #{$with_type_char}
-DLTYPE[SHORT][:sym] = #{$with_type_short}
-DLTYPE[INT][:sym] = #{$with_type_int}
-DLTYPE[LONG][:sym] = #{$with_type_long}
-DLTYPE[FLOAT][:sym] = #{$with_type_float}
-DLTYPE[DOUBLE][:sym]= #{$with_type_double}
-DLTYPE[VOIDP][:sym] = #{$with_type_voidp}
-EOF
-
-$INSTALLFILES = [
- ["./dlconfig.h", "$(archdir)$(target_prefix)", "."],
- ["dl.h", "$(archdir)$(target_prefix)", ""],
-]
-$cleanfiles = %w[test/test.o]
-$distcleanfiles = %w[call.func callback.func cbtable.func dlconfig.rb
-./dlconfig.h test/libtest.so test/*~ *~ mkmf.log]
-
-create_makefile('dl')
-rescue SystemExit
- # do nothing
-end
diff --git a/ext/dl/h2rb b/ext/dl/h2rb
deleted file mode 100644
index 00fbd60c82..0000000000
--- a/ext/dl/h2rb
+++ /dev/null
@@ -1,500 +0,0 @@
-#!/usr/bin/env ruby
-# -*- ruby -*-
-# $Id$
-
-require 'mkmf'
-require 'ftools'
-
-$recursive = false
-$force = false
-$conly = true
-$inc_path = []
-$infilename= nil
-$insert_require = true
-
-def valid_ruby_code?(code)
- begin
- eval("BEGIN {return true}; #{code}")
- rescue SyntaxError
- return false
- end
- return false
-end
-
-def print_usage
- print <<EOF
-h2rb [-r] [-I <path>] [-d] [<filename>]
-EOF
-end
-
-while( ARGV[0] )
- case( ARGV[0] )
- when "-r"
- ARGV.shift
- $recursive = true
- when "-R"
- ARGV.shift
- $recursive = false
- when "-l"
- ARGV.shift
- $insert_require = true
- when "-L"
- ARGV.shift
- $insert_require = false
- when "-c"
- ARGV.shift
- $conly = true
- when "-C"
- ARGV.shift
- $conly = false
- when "-f"
- ARGV.shift
- $force = true
- when "-F"
- ARGV.shift
- $force = false
- when "-I"
- ARGV.shift
- $inc_path << ARGV.shift
- when "-d"
- ARGV.shift
- $DEBUG = true
- when "-h","--help"
- print_usage()
- exit 0
- when /-.*/
- $stderr.print("unknown option '#{ARGV[0]}'.\n")
- print_usage()
- exit 0
- else
- $infilename = ARGV.shift
- end
-end
-
-$inc_dir = File.join(CONFIG["prefix"], "lib", "ruby",
- CONFIG["MAJOR"] + "." + CONFIG["MINOR"],
- "dl")
-
-class H2RBError < StandardError; end
-
-
-class H2RB
- def initialize(inc_dir = nil, inc_path = nil, insert_require = nil)
- @inc_path = inc_path || []
- @inc_dir = inc_dir || '.'
- @indent = 0
- @parsed_files = []
- @insert_require = insert_require || false
- end
-
- def find_path(file)
- if( ! file )
- return nil
- end
- if( File.exist?(file) )
- if( file[0] == ?/ )
- return file
- else
- return file
- end
- end
- @inc_path.each{|path|
- full = File.join(path, file)
- if( File.exist?(full) )
- return full
- end
- }
- return nil
- end
-
- def strip_comment(line)
- if( @commented )
- if( e = line.index("*/") )
- line[0..(e+1)] = ""
- @commented = false
- else
- line = ""
- end
- else
- if( s = line.index("/*") )
- if( e = line.index("*/") )
- line[s..(e+1)] = ""
- else
- line[s..-1] = ""
- @commented = true
- end
- elsif( s = line.index("//") )
- line[s..(-1)] = ""
- end
- end
-
- line.gsub!(/\s+$/,"")
- return line
- end
-
- def up_indent
- @indent += 1
- end
-
- def down_indent
- @indent -= 1
- if( @indent < 0 )
- raise
- end
- end
-
- def indent
- " " * @indent
- end
-
- def rescue_begin
- line = "#{indent}begin"
- up_indent
- return line
- end
-
- def rescue_nameerror
- down_indent
- line = [
- "#{indent}rescue NameError => e",
- "#{indent} raise e if( $DEBUG )",
- "#{indent}end"].join($/)
- return line
- end
-
- def parse_enum(line)
- if( line =~ /enum\s+(\S+\s+)?\{(.+)\}/ )
- enum_name = $1
- enum_block = $2
- if( enum_name )
- line = "#{indent}# -- enum #{enum_name}\n"
- else
- line = "#{indent}# -- enum\n"
- end
- enums = enum_block.split(/,/).collect{|e| e.strip}
- i = 0
- enums.each{|elem|
- var,val = elem.split(/=/).collect{|e| e.strip}
- if( val )
- i = val.to_i
- end
- line += "#{indent}#{var} = #{i.to_s}\n"
- i += 1
- }
- line += "#{indent}# -- end of enum"
- return line
- else
- return nil
- end
- end
-
- def parse_define(line)
- case line
- when /^#\s*define\s+(\S+)\(\)/
- line = nil
- when /^#\s*define\s+(\S+)\((.+)\)\s+(.+)$/
- if( @conly )
- line = nil
- else
- defname = $1
- defargs = $2
- defval = $3
- if( !valid_ruby_code?(defval) )
- defval = "nil # #{defval}"
- end
- if( defname[0,1] =~ /^[A-Z]$/ )
- line = "#{indent}#{defname} = proc{|#{defargs}| #{defval}}"
- else
- line = [
- "#{indent}def #{defname}(#{defargs})",
- "#{indent} #{defval}",
- "#{indent}end"
- ].join("\n")
- end
- end
- when /^#\s*define\s+(\S+)\((.+)\)$/
- if( @conly )
- line = nil
- else
- defname = $1
- defargs = $2
- defval = nil
- if( !valid_ruby_code?(defval) )
- defval = "nil # #{defval}"
- end
- if( defname[0,1] =~ /^[A-Z]$/ )
- line = "#{indent}#{defname} = proc{|#{defargs}| #{defval}}"
- else
- line = [
- "#{indent}def #{defname}(#{defargs})",
- "#{indent} #{defval}",
- "#{indent}end"
- ].join("\n")
- end
- end
- when /^#\s*define\s+(\S+)\s+(.+)$/
- defname = $1
- defval = $2
- if( !valid_ruby_code?(defval) )
- defval = "nil # #{defval}"
- end
- line = [rescue_begin, "#{indent}#{defname} = #{defval}", rescue_nameerror].join($/)
- when /^#\s*define\s+(\S+)$/
- defname = $1
- line = "#{indent}#{defname} = nil"
- else
- line = nil
- end
- return line
- end
-
- def parse_undef(line)
- case line
- when /^#\s*undef\s+([A-Z]\S+)$/
- defname = $1
- line = "#{indent}remove_const(:#{defname})"
- when /^#\s*undef\s+(\S+)$/
- defname = $1
- line = "#{indent}#{defname} = nil"
- else
- line = nil
- end
- return line
- end
-
- def parse_ifdef(line)
- case line
- when /^#\s*ifdef\s+(\S+)$/
- defname = $1
- line = [
- rescue_begin,
- "#{indent}if( defined?(#{defname}) && ! #{defname}.nil? )"].join($/)
- else
- line = nil
- end
- return line
- end
-
- def parse_ifndef(line)
- case line
- when /^#\s*ifndef\s+(\S+)$/
- defname = $1
- line = [
- rescue_begin,
- "#{indent}if( ! defined?(#{defname}) || #{defname}.nil? )"].join($/)
- else
- line = nil
- end
- return line
- end
-
- def parse_if(line)
- case line
- when /^#\s*if\s+(.+)$/
- cond = $1
- cond.gsub!(/defined(.+)/){ "defined?(#{$1}) && ! #{$1}.nil?" }
- if( valid_ruby_code?(cond) )
- line = "#{indent}if( #{cond} )"
- else
- line = "#{indent}if( false ) # #{cond}"
- end
- line = [rescue_begin, line].join($/)
- else
- line = nil
- end
- return line
- end
-
- def parse_elif(line)
- case line
- when /^#\s*elif\s+(.+)$/
- cond = $1
- cond.gsub!("defined","defined?")
- line = "#{indent}elsif( #{cond} )"
- else
- line = nil
- end
- return line
- end
-
- def parse_else(line)
- case line
- when /^#\s*else\s*/
- line = "#{indent}else"
- else
- line = nil
- end
- return line
- end
-
- def parse_endif(line)
- case line
- when /^#\s*endif\s*$/
- line = ["#{indent}end", rescue_nameerror].join($/)
- else
- line = nil
- end
- return line
- end
-
- def parse_include(line)
- if( ! @insert_require )
- return nil
- end
-
- file = nil
- case line
- when /^#\s*include "(.+)"$/
- file = $1
- line = "#{indent}require '#{file}'"
- when /^#\s*include \<(.+)\>$/
- file = $1
- line = "#{indent}require '#{file}'"
- else
- line = nil
- end
- if( @recursive && file && (!@parsed_files.include?(file)) )
- parse(file, @recursive, @force, @conly)
- end
- return line
- end
-
-
- def open_files(infilename)
- if( ! infilename )
- return [$stdin, $stdout]
- end
-
- old_infilename = infilename
- infilename = find_path(infilename)
- if( ! infilename )
- $stderr.print("'#{old_infilename}' was not found.\n")
- return [nil,nil]
- end
-
- if( infilename )
- if( infilename[0,1] == '/' )
- outfilename = File.join(@inc_dir, infilename[1..-1] + ".rb")
- else
- outfilename = infilename + ".rb"
- end
- File.mkpath(File.dirname(outfilename))
- else
- outfilename = nil
- end
-
- if( infilename )
- fin = File.open(infilename,"r")
- else
- fin = $stdin
- end
- if( outfilename )
- if( File.exist?(outfilename) && (!@force) )
- $stderr.print("'#{outfilename}' have already existed.\n")
- return [fin, nil]
- end
- fout = File.open(outfilename,"w")
- else
- fout = $stdout
- end
-
- $stderr.print("#{infilename} -> #{outfilename}\n")
- if( fout )
- dir = File.dirname(outfilename)
- if( dir[0,1] != "." && dir != "" )
- fout.print("if( ! $LOAD_PATH.include?('#{dir}') )\n",
- " $LOAD_PATH.push('#{dir}')\n",
- "end\n")
- end
- end
- return [fin,fout]
- end
-
- def parse(infilename = nil, recursive = false, force = false, conly = false)
- @commented = false
- @recursive = recursive
- @force = force
- @conly = conly
- @parsed_files << infilename
-
- fin,fout = open_files(infilename)
- if( !fin )
- return
- end
-
- begin
- line_number = 0
- pre_line = nil
- fin.each_line{|line|
- line_number += 1
- line.chop!
- if( $DEBUG )
- $stderr.print("#{line_number}:(#{@indent}):", line, "\n")
- end
-
- if( pre_line )
- line = pre_line + line
- pre_line = nil
- end
-
- if( line[-1,1] == "\\" )
- pre_line = line[0..-2]
- next
- end
-
- if( eidx = line.index("enum ") )
- pre_line = line[eidx .. -1]
- if( i = line.index("{") && j = line.index("}") )
- line = line[0..j]
- pre_line = nil
- else
- next
- end
- end
-
- line = strip_comment(line)
- case line
- when /^enum\s/
- line = parse_enum(line)
- when /^#\s*define\s/
- line = parse_define(line)
- when /^#\s*undef\s/
- line = parse_undef(line)
- when /^#\s*ifdef\s/
- line = parse_ifdef(line)
- up_indent
- when /^#\s*ifndef\s/
- line = parse_ifndef(line)
- up_indent
- when /^#\s*if\s/
- line = parse_if(line)
- up_indent
- when /^#\s*elif\s/
- down_indent
- line = parse_elif(line)
- up_indent
- when /^#\s*else/
- down_indent
- line = parse_else(line)
- up_indent
- when /^#\s*endif/
- down_indent
- line = parse_endif(line)
- when /^#\s*include\s/
- line = parse_include(line)
- else
- line = nil
- end
- if( line && fout )
- fout.print(line, " # #{line_number}",$/)
- end
- }
- ensure
- fin.close if fin
- fout.close if fout
- end
- end
-end
-
-h2rb = H2RB.new($inc_dir, $inc_path, $insert_require)
-h2rb.parse($infilename, $recursive, $force, $conly)
diff --git a/ext/dl/handle.c b/ext/dl/handle.c
deleted file mode 100644
index 7a05115ec5..0000000000
--- a/ext/dl/handle.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* -*- C -*-
- * $Id$
- */
-
-#include <ruby.h>
-#include "dl.h"
-
-VALUE rb_cDLHandle;
-
-void
-dlhandle_free(struct dl_handle *dlhandle)
-{
- if (dlhandle->ptr && dlhandle->open && dlhandle->enable_close) {
- dlclose(dlhandle->ptr);
- }
-}
-
-VALUE
-rb_dlhandle_close(VALUE self)
-{
- struct dl_handle *dlhandle;
-
- Data_Get_Struct(self, struct dl_handle, dlhandle);
- dlhandle->open = 0;
- return INT2NUM(dlclose(dlhandle->ptr));
-}
-
-VALUE
-rb_dlhandle_s_allocate(VALUE klass)
-{
- VALUE obj;
- struct dl_handle *dlhandle;
-
- obj = Data_Make_Struct(rb_cDLHandle, struct dl_handle, 0,
- dlhandle_free, dlhandle);
- dlhandle->ptr = 0;
- dlhandle->open = 0;
- dlhandle->enable_close = 0;
-
- return obj;
-}
-
-VALUE
-rb_dlhandle_initialize(int argc, VALUE argv[], VALUE self)
-{
- void *ptr;
- struct dl_handle *dlhandle;
- VALUE lib, flag;
- char *clib;
- int cflag;
- const char *err;
-
- switch (rb_scan_args(argc, argv, "11", &lib, &flag)) {
- case 1:
- clib = NIL_P(lib) ? NULL : StringValuePtr(lib);
- cflag = RTLD_LAZY | RTLD_GLOBAL;
- break;
- case 2:
- clib = NIL_P(lib) ? NULL : StringValuePtr(lib);
- cflag = NUM2INT(flag);
- break;
- default:
- rb_bug("rb_dlhandle_new");
- }
-
- ptr = dlopen(clib, cflag);
-#if defined(HAVE_DLERROR)
- if (!ptr && (err = dlerror())) {
- rb_raise(rb_eRuntimeError, err);
- }
-#else
- if (!ptr) {
- err = dlerror();
- rb_raise(rb_eRuntimeError, err);
- }
-#endif
- Data_Get_Struct(self, struct dl_handle, dlhandle);
- if (dlhandle->ptr && dlhandle->open && dlhandle->enable_close) {
- dlclose(dlhandle->ptr);
- }
- dlhandle->ptr = ptr;
- dlhandle->open = 1;
- dlhandle->enable_close = 0;
-
- if (rb_block_given_p()) {
- rb_ensure(rb_yield, self, rb_dlhandle_close, self);
- }
-
- return Qnil;
-}
-
-VALUE
-rb_dlhandle_enable_close(VALUE self)
-{
- struct dl_handle *dlhandle;
-
- Data_Get_Struct(self, struct dl_handle, dlhandle);
- dlhandle->enable_close = 1;
- return Qnil;
-}
-
-VALUE
-rb_dlhandle_disable_close(VALUE self)
-{
- struct dl_handle *dlhandle;
-
- Data_Get_Struct(self, struct dl_handle, dlhandle);
- dlhandle->enable_close = 0;
- return Qnil;
-}
-
-VALUE
-rb_dlhandle_to_i(VALUE self)
-{
- struct dl_handle *dlhandle;
-
- Data_Get_Struct(self, struct dl_handle, dlhandle);
- return DLLONG2NUM(dlhandle);
-}
-
-VALUE
-rb_dlhandle_to_ptr(VALUE self)
-{
- struct dl_handle *dlhandle;
-
- Data_Get_Struct(self, struct dl_handle, dlhandle);
- return rb_dlptr_new(dlhandle, sizeof(dlhandle), 0);
-}
-
-VALUE
-rb_dlhandle_sym(int argc, VALUE argv[], VALUE self)
-{
- VALUE sym, type;
- void (*func)();
- VALUE val;
- struct dl_handle *dlhandle;
- void *handle;
- const char *name, *stype;
- const char *err;
-
- rb_secure(2);
- if (rb_scan_args(argc, argv, "11", &sym, &type) == 2) {
- SafeStringValue(type);
- stype = StringValuePtr(type);
- }
- else{
- stype = NULL;
- }
-
- if (sym == Qnil) {
-#if defined(RTLD_NEXT)
- name = RTLD_NEXT;
-#else
- name = NULL;
-#endif
- }
- else{
- SafeStringValue(sym);
- name = StringValuePtr(sym);
- }
-
- Data_Get_Struct(self, struct dl_handle, dlhandle);
- if (!dlhandle->open) {
- rb_raise(rb_eRuntimeError, "closed handle");
- }
- handle = dlhandle->ptr;
-
- func = dlsym(handle, name);
-#if defined(HAVE_DLERROR)
- if (!func && (err = dlerror()))
-#else
- if (!func)
-#endif
- {
-#if defined(__CYGWIN__) || defined(WIN32) || defined(__MINGW32__)
- {
- int len = strlen(name);
- char *name_a = (char*)dlmalloc(len+2);
- strcpy(name_a, name);
- name_a[len] = 'A';
- name_a[len+1] = '\0';
- func = dlsym(handle, name_a);
- dlfree(name_a);
-#if defined(HAVE_DLERROR)
- if (!func && (err = dlerror()))
-#else
- if (!func)
-#endif
- {
- rb_raise(rb_eRuntimeError, "unknown symbol \"%sA\"", name);
- }
- }
-#else
- rb_raise(rb_eRuntimeError, "unknown symbol \"%s\"", name);
-#endif
- }
- val = rb_dlsym_new(func, name, stype);
-
- return val;
-}
-
-void
-Init_dlhandle()
-{
- rb_cDLHandle = rb_define_class_under(rb_mDL, "Handle", rb_cObject);
- rb_define_alloc_func(rb_cDLHandle, rb_dlhandle_s_allocate);
- rb_define_method(rb_cDLHandle, "initialize", rb_dlhandle_initialize, -1);
- rb_define_method(rb_cDLHandle, "to_i", rb_dlhandle_to_i, 0);
- rb_define_method(rb_cDLHandle, "to_ptr", rb_dlhandle_to_ptr, 0);
- rb_define_method(rb_cDLHandle, "close", rb_dlhandle_close, 0);
- rb_define_method(rb_cDLHandle, "sym", rb_dlhandle_sym, -1);
- rb_define_method(rb_cDLHandle, "[]", rb_dlhandle_sym, -1);
- rb_define_method(rb_cDLHandle, "disable_close", rb_dlhandle_disable_close, 0);
- rb_define_method(rb_cDLHandle, "enable_close", rb_dlhandle_enable_close, 0);
-}
diff --git a/ext/dl/install.rb b/ext/dl/install.rb
deleted file mode 100644
index 69b1834301..0000000000
--- a/ext/dl/install.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-require 'mkmf'
-require 'ftools'
-
-SO_LIBS = ["dl.so"]
-
-$ruby_version = CONFIG['MAJOR'] + "." + CONFIG['MINOR']
-$prefix = CONFIG['prefix']
-$libdir = File.join($prefix,'lib')
-$rubylibdir = File.join($libdir, 'ruby', $ruby_version)
-$arch = CONFIG['arch']
-$archdir = File.join($rubylibdir, $arch)
-
-def find(dir, match = /./)
- Dir.chdir(dir)
- files = []
- Dir.new(".").each{|file|
- if( file != "." && file != ".." )
- case File.ftype(file)
- when "file"
- if( file =~ match )
- files.push(File.join(dir,file))
- end
- when "directory"
- files += find(file, match).collect{|f| File.join(dir,f)}
- end
- end
- }
- Dir.chdir("..")
- return files
-end
-
-def install()
- rb_files = find(File.join(".","lib"), /.rb$/)
-
- SO_LIBS.each{|f|
- File.makedirs($rubylibdir, "#{$archdir}")
- File.install(f, File.join($archdir,f), 0555, true)
- }
-
- rb_files.each{|f|
- origfile = f
- instfile = File.join($rubylibdir, origfile.sub("./lib/",""))
- instdir = File.dirname(instfile)
- File.makedirs(instdir)
- File.install(origfile, instfile, 0644, true)
- }
-end
-
-install()
diff --git a/ext/dl/lib/dl/import.rb b/ext/dl/lib/dl/import.rb
deleted file mode 100644
index 63c9b2c050..0000000000
--- a/ext/dl/lib/dl/import.rb
+++ /dev/null
@@ -1,225 +0,0 @@
-# -*- ruby -*-
-
-require 'dl'
-require 'dl/types'
-
-module DL
- module Importable
- LIB_MAP = {}
-
- module Internal
- def init_types()
- @types ||= ::DL::Types.new
- end
-
- def init_sym()
- @SYM ||= {}
- end
-
- def [](name)
- return @SYM[name.to_s][0]
- end
-
- def dlload(*libnames)
- if( !defined?(@LIBS) )
- @LIBS = []
- end
- libnames.each{|libname|
- if( !LIB_MAP[libname] )
- LIB_MAP[libname] = DL.dlopen(libname)
- end
- @LIBS.push(LIB_MAP[libname])
- }
- end
- alias dllink :dlload
-
- def parse_cproto(proto)
- proto = proto.gsub(/\s+/, " ").strip
- case proto
- when /^([\d\w\*_\s]+)\(([\d\w\*_\s\,\[\]]*)\)$/
- ret = $1
- args = $2.strip()
- ret = ret.split(/\s+/)
- args = args.split(/\s*,\s*/)
- func = ret.pop()
- if( func =~ /^\*/ )
- func.gsub!(/^\*+/,"")
- ret.push("*")
- end
- ret = ret.join(" ")
- return [func, ret, args]
- else
- raise(RuntimeError,"can't parse the function prototype: #{proto}")
- end
- end
-
- # example:
- # extern "int strlen(char*)"
- #
- def extern(proto)
- func,ret,args = parse_cproto(proto)
- return import(func, ret, args)
- end
-
- # example:
- # callback "int method_name(int, char*)"
- #
- def callback(proto)
- func,ret,args = parse_cproto(proto)
-
- init_types()
- init_sym()
-
- rty,renc,rdec = @types.encode_return_type(ret)
- if( !rty )
- raise(TypeError, "unsupported type: #{ret}")
- end
- ty,enc,dec = encode_argument_types(args)
- symty = rty + ty
-
- module_eval("module_function :#{func}")
- sym = module_eval([
- "DL::callback(\"#{symty}\"){|*args|",
- " sym,rdec,enc,dec = @SYM['#{func}']",
- " args = enc.call(args) if enc",
- " r,rs = #{func}(*args)",
- " r = renc.call(r) if rdec",
- " rs = dec.call(rs) if (dec && rs)",
- " @retval = r",
- " @args = rs",
- " @retval",
- "}",
- ].join("\n"))
-
- @SYM[func] = [sym,rdec,enc,dec]
-
- return sym
- end
-
- # example:
- # typealias("uint", "unsigned int")
- #
- def typealias(alias_type, ty1, enc1=nil, dec1=nil, ty2=nil, enc2=nil, dec2=nil)
- init_types()
- @types.typealias(alias_type, ty1, enc1, dec1,
- ty2||ty1, enc2, dec2)
- end
-
- # example:
- # symbol "foo_value"
- # symbol "foo_func", "IIP"
- #
- def symbol(name, ty = nil)
- sym = nil
- @LIBS.each{|lib|
- begin
- if( ty )
- sym = lib[name, ty]
- else
- sym = lib[name]
- end
- rescue
- next
- end
- }
- if( !sym )
- raise(RuntimeError, "can't find the symbol `#{name}'")
- end
- return sym
- end
-
- # example:
- # import("get_length", "int", ["void*", "int"])
- #
- def import(name, rettype, argtypes = nil)
- init_types()
- init_sym()
-
- rty,_,rdec = @types.encode_return_type(rettype)
- if( !rty )
- raise(TypeError, "unsupported type: #{rettype}")
- end
- ty,enc,dec = encode_argument_types(argtypes)
- symty = rty + ty
-
- sym = symbol(name, symty)
-
- mname = name.dup
- if( ?A <= mname[0] && mname[0] <= ?Z )
- mname[0,1] = mname[0,1].downcase
- end
- @SYM[mname] = [sym,rdec,enc,dec]
-
- module_eval [
- "def #{mname}(*args)",
- " sym,rdec,enc,dec = @SYM['#{mname}']",
- " args = enc.call(args) if enc",
- if( $DEBUG )
- " p \"[DL] call #{mname} with \#{args.inspect}\""
- else
- ""
- end,
- " r,rs = sym.call(*args)",
- if( $DEBUG )
- " p \"[DL] retval=\#{r.inspect} args=\#{rs.inspect}\""
- else
- ""
- end,
- " r = rdec.call(r) if rdec",
- " rs = dec.call(rs) if dec",
- " @retval = r",
- " @args = rs",
- " return @retval",
- "end",
- "module_function :#{mname}",
- ].join("\n")
-
- return sym
- end
-
- def _args_
- return @args
- end
-
- def _retval_
- return @retval
- end
-
- def encode_argument_types(tys)
- init_types()
- encty = []
- enc = nil
- dec = nil
- tys.each_with_index{|ty,idx|
- ty,c1,c2 = @types.encode_argument_type(ty)
- if( !ty )
- raise(TypeError, "unsupported type: #{ty}")
- end
- encty.push(ty)
- if( enc )
- if( c1 )
- conv1 = enc
- enc = proc{|v| v = conv1.call(v); v[idx] = c1.call(v[idx]); v}
- end
- else
- if( c1 )
- enc = proc{|v| v[idx] = c1.call(v[idx]); v}
- end
- end
- if( dec )
- if( c2 )
- conv2 = dec
- dec = proc{|v| v = conv2.call(v); v[idx] = c2.call(v[idx]); v}
- end
- else
- if( c2 )
- dec = proc{|v| v[idx] = c2.call(v[idx]); v}
- end
- end
- }
- return [encty.join, enc, dec]
- end
- end # end of Internal
- include Internal
- end # end of Importable
-end
diff --git a/ext/dl/lib/dl/struct.rb b/ext/dl/lib/dl/struct.rb
deleted file mode 100644
index 33f303fe22..0000000000
--- a/ext/dl/lib/dl/struct.rb
+++ /dev/null
@@ -1,149 +0,0 @@
-# -*- ruby -*-
-
-require 'dl'
-require 'dl/import'
-
-module DL
- module Importable
- module Internal
- def define_struct(contents)
- init_types()
- Struct.new(@types, contents)
- end
- alias struct define_struct
-
- def define_union(contents)
- init_types()
- Union.new(@types, contents)
- end
- alias union define_union
-
- class Memory
- def initialize(ptr, names, ty, len, enc, dec)
- @ptr = ptr
- @names = names
- @ty = ty
- @len = len
- @enc = enc
- @dec = dec
-
- # define methods
- @names.each{|name|
- instance_eval [
- "def #{name}",
- " v = @ptr[\"#{name}\"]",
- " if( @len[\"#{name}\"] )",
- " v = v.collect{|x| @dec[\"#{name}\"] ? @dec[\"#{name}\"].call(x) : x }",
- " else",
- " v = @dec[\"#{name}\"].call(v) if @dec[\"#{name}\"]",
- " end",
- " return v",
- "end",
- "def #{name}=(v)",
- " if( @len[\"#{name}\"] )",
- " v = v.collect{|x| @enc[\"#{name}\"] ? @enc[\"#{name}\"].call(x) : x }",
- " else",
- " v = @enc[\"#{name}\"].call(v) if @enc[\"#{name}\"]",
- " end",
- " @ptr[\"#{name}\"] = v",
- " return v",
- "end",
- ].join("\n")
- }
- end
-
- def to_ptr
- return @ptr
- end
-
- def size
- return @ptr.size
- end
- end
-
- class Struct
- def initialize(types, contents)
- @names = []
- @ty = {}
- @len = {}
- @enc = {}
- @dec = {}
- @size = 0
- @tys = ""
- @types = types
- parse(contents)
- end
-
- def size
- return @size
- end
-
- def members
- return @names
- end
-
- # ptr must be a PtrData object.
- def new(ptr)
- ptr.struct!(@tys, *@names)
- mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
- return mem
- end
-
- def malloc(size = nil)
- if( !size )
- size = @size
- end
- ptr = DL::malloc(size)
- return new(ptr)
- end
-
- def parse(contents)
- contents.each{|elem|
- name,ty,num,enc,dec = parse_elem(elem)
- @names.push(name)
- @ty[name] = ty
- @len[name] = num
- @enc[name] = enc
- @dec[name] = dec
- if( num )
- @tys += "#{ty}#{num}"
- else
- @tys += ty
- end
- }
- @size = DL.sizeof(@tys)
- end
-
- def parse_elem(elem)
- elem.strip!
- case elem
- when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)$/
- ty = ($1 + $2).strip
- name = $3
- num = nil;
- when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)\[(\d+)\]$/
- ty = ($1 + $2).strip
- name = $3
- num = $4.to_i
- else
- raise(RuntimeError, "invalid element: #{elem}")
- end
- ty,enc,dec = @types.encode_struct_type(ty)
- if( !ty )
- raise(TypeError, "unsupported type: #{ty}")
- end
- return [name,ty,num,enc,dec]
- end
- end # class Struct
-
- class Union < Struct
- def new
- ptr = DL::malloc(@size)
- ptr.union!(@tys, *@names)
- mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
- return mem
- end
- end
- end # module Internal
- end # module Importable
-end # module DL
diff --git a/ext/dl/lib/dl/types.rb b/ext/dl/lib/dl/types.rb
deleted file mode 100644
index 1144917dae..0000000000
--- a/ext/dl/lib/dl/types.rb
+++ /dev/null
@@ -1,245 +0,0 @@
-# -*- ruby -*-
-
-require 'dl'
-
-module DL
- class Types
- TYPES = [
- # FORMAT:
- # ["alias name",
- # "type name", encoding_method, decoding_method, for function prototypes
- # "type name", encoding_method, decoding_method] for structures (not implemented)
-
- # for Windows
- ["DWORD", "unsigned long", nil, nil,
- "unsigned long", nil, nil],
- ["PDWORD", "unsigned long *", nil, nil,
- "unsigned long *", nil, nil],
- ["WORD", "unsigned short", nil, nil,
- "unsigned short", nil, nil],
- ["PWORD", "unsigned int *", nil, nil,
- "unsigned int *", nil, nil],
- ["BYTE", "unsigned char", nil, nil,
- "unsigned char", nil, nil],
- ["PBYTE", "unsigned char *", nil, nil,
- "unsigned char *", nil, nil],
- ["BOOL", "ibool", nil, nil,
- "ibool", nil, nil],
- ["ATOM", "int", nil, nil,
- "int", nil, nil],
- ["BYTE", "unsigned char", nil, nil,
- "unsigned char", nil, nil],
- ["PBYTE", "unsigned char *", nil, nil,
- "unsigned char *", nil, nil],
- ["UINT", "unsigned int", nil, nil,
- "unsigned int", nil, nil],
- ["ULONG", "unsigned long", nil, nil,
- "unsigned long", nil, nil],
- ["UCHAR", "unsigned char", nil, nil,
- "unsigned char", nil, nil],
- ["HANDLE", "unsigned long", nil, nil,
- "unsigned long", nil, nil],
- ["PHANDLE","void*", nil, nil,
- "void*", nil, nil],
- ["PVOID", "void*", nil, nil,
- "void*", nil, nil],
- ["LPCSTR", "char*", nil, nil,
- "char*", nil, nil],
- ["HDC", "unsigned int", nil, nil,
- "unsigned int", nil, nil],
- ["HWND", "unsigned int", nil, nil,
- "unsigned int", nil, nil],
-
- # Others
- ["uint", "unsigned int", nil, nil,
- "unsigned int", nil, nil],
- ["u_int", "unsigned int", nil, nil,
- "unsigned int", nil, nil],
- ["ulong", "unsigned long", nil, nil,
- "unsigned long", nil, nil],
- ["u_long", "unsigned long", nil, nil,
- "unsigned long", nil, nil],
-
- # DL::Importable primitive types
- ["ibool",
- "I",
- proc{|v| v ? 1 : 0},
- proc{|v| (v != 0) ? true : false},
- "I",
- proc{|v| v ? 1 : 0 },
- proc{|v| (v != 0) ? true : false} ],
- ["cbool",
- "C",
- proc{|v| v ? 1 : 0},
- proc{|v| (v != 0) ? true : false},
- "C",
- proc{|v,len| v ? 1 : 0},
- proc{|v,len| (v != 0) ? true : false}],
- ["lbool",
- "L",
- proc{|v| v ? 1 : 0},
- proc{|v| (v != 0) ? true : false},
- "L",
- proc{|v,len| v ? 1 : 0},
- proc{|v,len| (v != 0) ? true : false}],
- ["unsigned char",
- "C",
- proc{|v| [v].pack("C").unpack("c")[0]},
- proc{|v| [v].pack("c").unpack("C")[0]},
- "C",
- proc{|v| [v].pack("C").unpack("c")[0]},
- proc{|v| [v].pack("c").unpack("C")[0]}],
- ["unsigned short",
- "H",
- proc{|v| [v].pack("S").unpack("s")[0]},
- proc{|v| [v].pack("s").unpack("S")[0]},
- "H",
- proc{|v| [v].pack("S").unpack("s")[0]},
- proc{|v| [v].pack("s").unpack("S")[0]}],
- ["unsigned int",
- "I",
- proc{|v| [v].pack("I").unpack("i")[0]},
- proc{|v| [v].pack("i").unpack("I")[0]},
- "I",
- proc{|v| [v].pack("I").unpack("i")[0]},
- proc{|v| [v].pack("i").unpack("I")[0]}],
- ["unsigned long",
- "L",
- proc{|v| [v].pack("L").unpack("l")[0]},
- proc{|v| [v].pack("l").unpack("L")[0]},
- "L",
- proc{|v| [v].pack("L").unpack("l")[0]},
- proc{|v| [v].pack("l").unpack("L")[0]}],
- ["unsigned char ref",
- "c",
- proc{|v| [v].pack("C").unpack("c")[0]},
- proc{|v| [v].pack("c").unpack("C")[0]},
- nil, nil, nil],
- ["unsigned int ref",
- "i",
- proc{|v| [v].pack("I").unpack("i")[0]},
- proc{|v| [v].pack("i").unpack("I")[0]},
- nil, nil, nil],
- ["unsigned long ref",
- "l",
- proc{|v| [v].pack("L").unpack("l")[0]},
- proc{|v| [v].pack("l").unpack("L")[0]},
- nil, nil, nil],
- ["char ref", "c", nil, nil,
- nil, nil, nil],
- ["short ref", "h", nil, nil,
- nil, nil, nil],
- ["int ref", "i", nil, nil,
- nil, nil, nil],
- ["long ref", "l", nil, nil,
- nil, nil, nil],
- ["float ref", "f", nil, nil,
- nil, nil, nil],
- ["double ref","d", nil, nil,
- nil, nil, nil],
- ["char", "C", nil, nil,
- "C", nil, nil],
- ["short", "H", nil, nil,
- "H", nil, nil],
- ["int", "I", nil, nil,
- "I", nil, nil],
- ["long", "L", nil, nil,
- "L", nil, nil],
- ["float", "F", nil, nil,
- "F", nil, nil],
- ["double", "D", nil, nil,
- "D", nil, nil],
- [/^char\s*\*$/,"s",nil, nil,
- "S",nil, nil],
- [/^const char\s*\*$/,"S",nil, nil,
- "S",nil, nil],
- [/^.+\*$/, "P", nil, nil,
- "P", nil, nil],
- [/^.+\[\]$/, "a", nil, nil,
- "a", nil, nil],
- ["void", "0", nil, nil,
- nil, nil, nil],
- ]
-
- def initialize
- init_types()
- end
-
- def typealias(ty1, ty2, enc=nil, dec=nil, ty3=nil, senc=nil, sdec=nil)
- @TYDEFS.unshift([ty1, ty2, enc, dec, ty3, senc, sdec])
- end
-
- def init_types
- @TYDEFS = TYPES.dup
- end
-
- def encode_argument_type(alias_type)
- proc_encode = nil
- proc_decode = nil
- @TYDEFS.each{|aty,ty,enc,dec,_,_,_|
- if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
- alias_type = alias_type.gsub(aty,ty) if ty
- alias_type.strip! if alias_type
- if( proc_encode )
- if( enc )
- conv1 = proc_encode
- proc_encode = proc{|v| enc.call(conv1.call(v))}
- end
- else
- if( enc )
- proc_encode = enc
- end
- end
- if( proc_decode )
- if( dec )
- conv2 = proc_decode
- proc_decode = proc{|v| dec.call(conv2.call(v))}
- end
- else
- if( dec )
- proc_decode = dec
- end
- end
- end
- }
- return [alias_type, proc_encode, proc_decode]
- end
-
- def encode_return_type(ty)
- ty, enc, dec = encode_argument_type(ty)
- return [ty, enc, dec]
- end
-
- def encode_struct_type(alias_type)
- proc_encode = nil
- proc_decode = nil
- @TYDEFS.each{|aty,_,_,_,ty,enc,dec|
- if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
- alias_type = alias_type.gsub(aty,ty) if ty
- alias_type.strip! if alias_type
- if( proc_encode )
- if( enc )
- conv1 = proc_encode
- proc_encode = proc{|v| enc.call(conv1.call(v))}
- end
- else
- if( enc )
- proc_encode = enc
- end
- end
- if( proc_decode )
- if( dec )
- conv2 = proc_decode
- proc_decode = proc{|v| dec.call(conv2.call(v))}
- end
- else
- if( dec )
- proc_decode = dec
- end
- end
- end
- }
- return [alias_type, proc_encode, proc_decode]
- end
- end # end of Types
-end
diff --git a/ext/dl/lib/dl/win32.rb b/ext/dl/lib/dl/win32.rb
deleted file mode 100644
index 92f473d392..0000000000
--- a/ext/dl/lib/dl/win32.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- ruby -*-
-
-require 'dl'
-
-class Win32API
- DLL = {}
-
- def initialize(dllname, func, import, export = "0")
- prototype = (export + import.to_s).tr("VPpNnLlIi", "0SSI")
- handle = DLL[dllname] ||= DL::Handle.new(dllname)
- @sym = handle.sym(func, prototype)
- end
-
- def call(*args)
- import = @sym.proto.split("", 2)[1]
- args.each_with_index do |x, i|
- args[i] = nil if x == 0 and import[i] == ?S
- args[i], = [x].pack("I").unpack("i") if import[i] == ?I
- end
- ret, = @sym.call(*args)
- return ret || 0
- end
-
- alias Call call
-end
diff --git a/ext/dl/mkcall.rb b/ext/dl/mkcall.rb
deleted file mode 100644
index 6a85570152..0000000000
--- a/ext/dl/mkcall.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# -*- ruby -*-
-
-require 'mkmf'
-$:.unshift File.dirname(__FILE__)
-require 'type'
-require 'dlconfig'
-
-def output_arg(x,i)
- "args[#{i}].#{DLTYPE[x][:stmem]}"
-end
-
-def output_args(types)
- t = []
- types[1..-1].each_with_index{|x,i| t.push(output_arg(x,i))}
- t.join(",")
-end
-
-def output_callfunc(types)
- t = types[0]
- stmem = DLTYPE[t][:stmem]
- ctypes = types2ctypes(types)
- if( t == VOID )
- callstm = "(*f)(#{output_args(types)})"
- else
- callstm = "ret.#{stmem} = (*f)(#{output_args(types)})"
- end
- [ "{",
- "#{ctypes[0]} (*f)(#{ctypes[1..-1].join(',')}) = func;",
- "#{callstm};",
- "}"].join(" ")
-end
-
-def output_case(types)
- num = types2num(types)
- callfunc_stm = output_callfunc(types)
-<<EOF
- case #{num}:
-#ifdef DEBUG
- printf("#{callfunc_stm}\\n");
-#endif
- #{callfunc_stm};
- break;
-EOF
-end
-
-def rec_output(types = [VOID])
- print output_case(types)
- if( types.length <= MAX_ARG )
- DLTYPE.keys.sort.each{|t|
- if( t != VOID && DLTYPE[t][:sym] )
- rec_output(types + [t])
- end
- }
- end
-end
-
-DLTYPE.keys.sort.each{|t|
- if( DLTYPE[t][:sym] )
- $stderr.printf(" #{DLTYPE[t][:ctype]}\n")
- rec_output([t])
- end
-}
diff --git a/ext/dl/mkcallback.rb b/ext/dl/mkcallback.rb
deleted file mode 100644
index b7ea1718d0..0000000000
--- a/ext/dl/mkcallback.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- ruby -*-
-
-require 'mkmf'
-$:.unshift File.dirname(__FILE__)
-require 'type'
-require 'dlconfig'
-
-def mkfunc(rettype, fnum, argc)
- args = (0..(argc-1)).collect{|i| "long arg#{i}"}.join(", ")
-
- subst_code = (0..(argc-1)).collect{|i|
- " buff[#{i.to_s}] = arg#{i.to_s};"
- }.join("\n")
-
- ret_code =
- if( DLTYPE[rettype][:c2rb] )
- " return #{DLTYPE[rettype][:rb2c]['retval']};"
- else
- " /* no return value */"
- end
-
- code = [
- "static #{DLTYPE[rettype][:ctype]}",
- "rb_dl_callback_func_#{rettype.to_s}_#{fnum.to_s}(#{args})",
- "{",
- " VALUE retval, proto, proc, obj;",
- " VALUE argv[#{argc.to_s}];",
- " int argc;",
- " long buff[#{argc.to_s}];",
- "",
- subst_code,
- "",
- " obj = rb_hash_aref(DLFuncTable, rb_assoc_new(INT2NUM(#{rettype.to_s}),INT2NUM(#{fnum.to_s})));",
- " proto = rb_ary_entry(obj, 0);",
- " proc = rb_ary_entry(obj, 1);",
- " Check_Type(proto, T_STRING);",
- " if( RSTRING(proto)->len >= #{argc.to_s} )",
- " rb_raise(rb_eArgError, \"too many arguments\");",
- " rb_dl_scan_callback_args(buff, RSTRING(proto)->ptr, &argc, argv);",
- " retval = rb_funcall2(proc, id_call, argc, argv);",
- "",
- ret_code,
- "}",
- ].join("\n")
-
- return code
-end
-
-DLTYPE.keys.sort.each{|t|
- for n in 0..(MAX_CALLBACK - 1)
- print(mkfunc(t, n, 15), "\n\n")
- end
-}
diff --git a/ext/dl/mkcbtable.rb b/ext/dl/mkcbtable.rb
deleted file mode 100644
index 165c4bdc88..0000000000
--- a/ext/dl/mkcbtable.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- ruby -*-
-
-require 'mkmf'
-$:.unshift File.dirname(__FILE__)
-require 'type'
-require 'dlconfig'
-
-def mktable(rettype, fnum, argc)
- code =
- "rb_dl_callback_table[#{rettype}][#{fnum}] = &rb_dl_callback_func_#{rettype.to_s}_#{fnum};"
- return code
-end
-
-DLTYPE.keys.sort.each{|t|
- for n in 0..(MAX_CALLBACK - 1)
- print(mktable(t, n, 15), "\n")
- end
-}
diff --git a/ext/dl/ptr.c b/ext/dl/ptr.c
deleted file mode 100644
index 59de4d8c98..0000000000
--- a/ext/dl/ptr.c
+++ /dev/null
@@ -1,1067 +0,0 @@
-/* -*- C -*-
- * $Id$
- */
-
-#include <ruby.h>
-#include <ctype.h>
-#include <version.h> /* for ruby version code */
-#include "dl.h"
-
-VALUE rb_cDLPtrData;
-VALUE rb_mDLMemorySpace;
-static VALUE DLMemoryTable;
-
-#ifndef T_SYMBOL
-# define T_SYMBOL T_FIXNUM
-#endif
-
-#if RUBY_VERSION_CODE < 171
-static VALUE
-rb_hash_delete(VALUE hash, VALUE key)
-{
- return rb_funcall(hash, rb_intern("delete"), 1, key);
-}
-#endif
-
-static void
-rb_dlmem_delete(void *ptr)
-{
- rb_secure(4);
- rb_hash_delete(DLMemoryTable, DLLONG2NUM(ptr));
-}
-
-static void
-rb_dlmem_aset(void *ptr, VALUE obj)
-{
- if (obj == Qnil) {
- rb_dlmem_delete(ptr);
- }
- else{
- rb_hash_aset(DLMemoryTable, DLLONG2NUM(ptr), DLLONG2NUM(obj));
- }
-}
-
-static VALUE
-rb_dlmem_aref(void *ptr)
-{
- VALUE val;
-
- val = rb_hash_aref(DLMemoryTable, DLLONG2NUM(ptr));
- return val == Qnil ? Qnil : (VALUE)DLNUM2LONG(val);
-}
-
-void
-dlptr_free(struct ptr_data *data)
-{
- if (data->ptr) {
- DEBUG_CODE({
- printf("dlptr_free(): removing the pointer `0x%x' from the MemorySpace\n",
- data->ptr);
- });
- rb_dlmem_delete(data->ptr);
- if (data->free) {
- DEBUG_CODE({
- printf("dlptr_free(): 0x%x(data->ptr:0x%x)\n",data->free,data->ptr);
- });
- (*(data->free))(data->ptr);
- }
- }
- if (data->stype) dlfree(data->stype);
- if (data->ssize) dlfree(data->ssize);
- if (data->ids) dlfree(data->ids);
-}
-
-void
-dlptr_init(VALUE val)
-{
- struct ptr_data *data;
-
- Data_Get_Struct(val, struct ptr_data, data);
- DEBUG_CODE({
- printf("dlptr_init(): add the pointer `0x%x' to the MemorySpace\n",
- data->ptr);
- });
- rb_dlmem_aset(data->ptr, val);
- OBJ_TAINT(val);
-}
-
-VALUE
-rb_dlptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
-{
- struct ptr_data *data;
- VALUE val;
-
- rb_secure(4);
- if (ptr) {
- val = rb_dlmem_aref(ptr);
- if (val == Qnil) {
- val = Data_Make_Struct(klass, struct ptr_data,
- 0, dlptr_free, data);
- data->ptr = ptr;
- data->free = func;
- data->ctype = DLPTR_CTYPE_UNKNOWN;
- data->stype = NULL;
- data->ssize = NULL;
- data->slen = 0;
- data->size = size;
- data->ids = NULL;
- data->ids_num = 0;
- dlptr_init(val);
- }
- else{
- if (func) {
- Data_Get_Struct(val, struct ptr_data, data);
- data->free = func;
- }
- }
- }
- else{
- val = Qnil;
- }
-
- return val;
-}
-
-VALUE
-rb_dlptr_new(void *ptr, long size, freefunc_t func)
-{
- return rb_dlptr_new2(rb_cDLPtrData, ptr, size, func);
-}
-
-VALUE
-rb_dlptr_malloc(long size, freefunc_t func)
-{
- void *ptr;
-
- rb_secure(4);
- ptr = dlmalloc((size_t)size);
- memset(ptr,0,(size_t)size);
- return rb_dlptr_new(ptr, size, func);
-}
-
-void *
-rb_dlptr2cptr(VALUE val)
-{
- struct ptr_data *data;
- void *ptr;
-
- if (rb_obj_is_kind_of(val, rb_cDLPtrData)) {
- Data_Get_Struct(val, struct ptr_data, data);
- ptr = data->ptr;
- }
- else if (val == Qnil) {
- ptr = NULL;
- }
- else{
- rb_raise(rb_eTypeError, "DL::PtrData was expected");
- }
-
- return ptr;
-}
-
-static VALUE
-rb_dlptr_s_allocate(VALUE klass)
-{
- VALUE obj;
- struct ptr_data *data;
-
- rb_secure(4);
- obj = Data_Make_Struct(klass, struct ptr_data, 0, dlptr_free, data);
- data->ptr = 0;
- data->free = 0;
- data->ctype = DLPTR_CTYPE_UNKNOWN;
- data->stype = NULL;
- data->ssize = NULL;
- data->slen = 0;
- data->size = 0;
- data->ids = NULL;
- data->ids_num = 0;
-
- return obj;
-}
-
-static VALUE
-rb_dlptr_initialize(int argc, VALUE argv[], VALUE self)
-{
- VALUE ptr, sym, size;
- struct ptr_data *data;
- void *p = NULL;
- freefunc_t f = NULL;
- long s = 0;
-
- switch (rb_scan_args(argc, argv, "12", &ptr, &size, &sym)) {
- case 1:
- p = (void*)(DLNUM2LONG(rb_Integer(ptr)));
- break;
- case 2:
- p = (void*)(DLNUM2LONG(rb_Integer(ptr)));
- s = DLNUM2LONG(size);
- break;
- case 3:
- p = (void*)(DLNUM2LONG(rb_Integer(ptr)));
- s = DLNUM2LONG(size);
- f = rb_dlsym2csym(sym);
- break;
- default:
- rb_bug("rb_dlptr_initialize");
- }
-
- if (p) {
- Data_Get_Struct(self, struct ptr_data, data);
- if (data->ptr && data->free) {
- /* Free previous memory. Use of inappropriate initialize may cause SEGV. */
- (*(data->free))(data->ptr);
- }
- data->ptr = p;
- data->size = s;
- data->free = f;
- }
-
- return Qnil;
-}
-
-static VALUE
-rb_dlptr_s_malloc(int argc, VALUE argv[], VALUE klass)
-{
- VALUE size, sym, obj;
- int s;
- freefunc_t f = NULL;
-
- switch (rb_scan_args(argc, argv, "11", &size, &sym)) {
- case 1:
- s = NUM2INT(size);
- break;
- case 2:
- s = NUM2INT(size);
- f = rb_dlsym2csym(sym);
- break;
- default:
- rb_bug("rb_dlptr_s_malloc");
- }
-
- obj = rb_dlptr_malloc(s,f);
-
- return obj;
-}
-
-VALUE
-rb_dlptr_to_i(VALUE self)
-{
- struct ptr_data *data;
-
- Data_Get_Struct(self, struct ptr_data, data);
- return DLLONG2NUM(data->ptr);
-}
-
-VALUE
-rb_dlptr_ptr(VALUE self)
-{
- struct ptr_data *data;
-
- Data_Get_Struct(self, struct ptr_data, data);
- return rb_dlptr_new(*((void**)(data->ptr)),0,0);
-}
-
-VALUE
-rb_dlptr_ref(VALUE self)
-{
- struct ptr_data *data;
-
- Data_Get_Struct(self, struct ptr_data, data);
- return rb_dlptr_new(&(data->ptr),0,0);
-}
-
-VALUE
-rb_dlptr_null_p(VALUE self)
-{
- struct ptr_data *data;
-
- Data_Get_Struct(self, struct ptr_data, data);
- return data->ptr ? Qfalse : Qtrue;
-}
-
-VALUE
-rb_dlptr_free_set(VALUE self, VALUE val)
-{
- struct ptr_data *data;
-
- Data_Get_Struct(self, struct ptr_data, data);
-
- data->free = DLFREEFUNC(rb_dlsym2csym(val));
-
- return Qnil;
-}
-
-VALUE
-rb_dlptr_free_get(VALUE self)
-{
- struct ptr_data *pdata;
-
- Data_Get_Struct(self, struct ptr_data, pdata);
-
- return rb_dlsym_new(pdata->free,"(free)","0P");
-}
-
-VALUE
-rb_dlptr_to_array(int argc, VALUE argv[], VALUE self)
-{
- struct ptr_data *data;
- int n;
- int i;
- int t;
- VALUE ary;
- VALUE type, size;
-
- Data_Get_Struct(self, struct ptr_data, data);
-
- switch (rb_scan_args(argc, argv, "11", &type, &size)) {
- case 2:
- t = StringValuePtr(type)[0];
- n = NUM2INT(size);
- break;
- case 1:
- t = StringValuePtr(type)[0];
- switch (t) {
- case 'C':
- n = data->size;
- break;
- case 'H':
- n = data->size / sizeof(short);
- break;
- case 'I':
- n = data->size / sizeof(int);
- break;
- case 'L':
- n = data->size / sizeof(long);
- break;
- case 'F':
- n = data->size / sizeof(float);
- break;
- case 'D':
- n = data->size / sizeof(double);
- break;
- case 'P': case 'p':
- n = data->size / sizeof(void*);
- break;
- case 'S': case 's':
- for (n=0; ((void**)(data->ptr))[n]; n++) {};
- break;
- default:
- n = 0;
- }
- break;
- default:
- rb_bug("rb_dlptr_to_array");
- }
-
- ary = rb_ary_new();
-
- for (i=0; i < n; i++) {
- switch (t) {
- case 'C':
- rb_ary_push(ary, INT2NUM(((char*)(data->ptr))[i]));
- break;
- case 'H':
- rb_ary_push(ary, INT2NUM(((short*)(data->ptr))[i]));
- break;
- case 'I':
- rb_ary_push(ary, INT2NUM(((int*)(data->ptr))[i]));
- break;
- case 'L':
- rb_ary_push(ary, DLLONG2NUM(((long*)(data->ptr))[i]));
- break;
- case 'D':
- rb_ary_push(ary, rb_float_new(((double*)(data->ptr))[i]));
- break;
- case 'F':
- rb_ary_push(ary, rb_float_new(((float*)(data->ptr))[i]));
- break;
- case 'S':
- {
- char *str = ((char**)(data->ptr))[i];
- if (str) {
- rb_ary_push(ary, rb_tainted_str_new2(str));
- }
- else{
- rb_ary_push(ary, Qnil);
- }
- }
- break;
- case 's':
- {
- char *str = ((char**)(data->ptr))[i];
- if (str) {
- rb_ary_push(ary, rb_tainted_str_new2(str));
- xfree(str);
- }
- else{
- rb_ary_push(ary, Qnil);
- }
- }
- break;
- case 'P':
- rb_ary_push(ary, rb_dlptr_new(((void**)(data->ptr))[i],0,0));
- break;
- case 'p':
- rb_ary_push(ary,
- rb_dlptr_new(((void**)(data->ptr))[i],0,dlfree));
- break;
- }
- }
-
- return ary;
-}
-
-
-VALUE
-rb_dlptr_to_s(int argc, VALUE argv[], VALUE self)
-{
- struct ptr_data *data;
- VALUE arg1, val;
- int len;
-
- Data_Get_Struct(self, struct ptr_data, data);
- switch (rb_scan_args(argc, argv, "01", &arg1)) {
- case 0:
- val = rb_tainted_str_new2((char*)(data->ptr));
- break;
- case 1:
- len = NUM2INT(arg1);
- val = rb_tainted_str_new((char*)(data->ptr), len);
- break;
- default:
- rb_bug("rb_dlptr_to_s");
- }
-
- return val;
-}
-
-VALUE
-rb_dlptr_to_str(int argc, VALUE argv[], VALUE self)
-{
- struct ptr_data *data;
- VALUE arg1, val;
- int len;
-
- Data_Get_Struct(self, struct ptr_data, data);
- switch (rb_scan_args(argc, argv, "01", &arg1)) {
- case 0:
- val = rb_tainted_str_new((char*)(data->ptr),data->size);
- break;
- case 1:
- len = NUM2INT(arg1);
- val = rb_tainted_str_new((char*)(data->ptr), len);
- break;
- default:
- rb_bug("rb_dlptr_to_str");
- }
-
- return val;
-}
-
-VALUE
-rb_dlptr_inspect(VALUE self)
-{
- struct ptr_data *data;
- char str[1024];
-
- Data_Get_Struct(self, struct ptr_data, data);
- snprintf(str, 1023, "#<%s:0x%p ptr=0x%p size=%ld free=0x%p>",
- rb_class2name(CLASS_OF(self)), data, data->ptr, data->size, data->free);
- return rb_str_new2(str);
-}
-
-VALUE
-rb_dlptr_eql(VALUE self, VALUE other)
-{
- void *ptr1, *ptr2;
- ptr1 = rb_dlptr2cptr(self);
- ptr2 = rb_dlptr2cptr(other);
-
- return ptr1 == ptr2 ? Qtrue : Qfalse;
-}
-
-VALUE
-rb_dlptr_cmp(VALUE self, VALUE other)
-{
- void *ptr1, *ptr2;
- ptr1 = rb_dlptr2cptr(self);
- ptr2 = rb_dlptr2cptr(other);
- return DLLONG2NUM((long)ptr1 - (long)ptr2);
-}
-
-VALUE
-rb_dlptr_plus(VALUE self, VALUE other)
-{
- void *ptr;
- long num, size;
-
- ptr = rb_dlptr2cptr(self);
- size = RDLPTR(self)->size;
- num = DLNUM2LONG(other);
- return rb_dlptr_new((char *)ptr + num, size - num, 0);
-}
-
-VALUE
-rb_dlptr_minus(VALUE self, VALUE other)
-{
- void *ptr;
- long num, size;
-
- ptr = rb_dlptr2cptr(self);
- size = RDLPTR(self)->size;
- num = DLNUM2LONG(other);
- return rb_dlptr_new((char *)ptr - num, size + num, 0);
-}
-
-VALUE
-rb_dlptr_define_data_type(int argc, VALUE argv[], VALUE self)
-{
- VALUE data_type, type, rest, vid;
- struct ptr_data *data;
- int i, t, num;
- char *ctype;
-
- rb_scan_args(argc, argv, "11*", &data_type, &type, &rest);
- Data_Get_Struct(self, struct ptr_data, data);
-
- if (argc == 1 || (argc == 2 && type == Qnil)) {
- if (NUM2INT(data_type) == DLPTR_CTYPE_UNKNOWN) {
- data->ctype = DLPTR_CTYPE_UNKNOWN;
- data->slen = 0;
- data->ids_num = 0;
- if (data->stype) {
- dlfree(data->stype);
- data->stype = NULL;
- }
- if (data->ids) {
- dlfree(data->ids);
- data->ids = NULL;
- }
- return Qnil;
- }
- else{
- rb_raise(rb_eArgError, "wrong arguments");
- }
- }
-
- t = NUM2INT(data_type);
- StringValue(type);
- Check_Type(rest, T_ARRAY);
- num = RARRAY(rest)->len;
- for (i=0; i<num; i++) {
- rb_to_id(rb_ary_entry(rest,i));
- }
-
- data->ctype = t;
- data->slen = num;
- data->ids_num = num;
- if (data->stype) dlfree(data->stype);
- data->stype = (char*)dlmalloc(sizeof(char) * num);
- if (data->ssize) dlfree(data->ssize);
- data->ssize = (int*)dlmalloc(sizeof(int) * num);
- if (data->ids) dlfree(data->ids);
- data->ids = (ID*)dlmalloc(sizeof(ID) * data->ids_num);
-
- ctype = StringValuePtr(type);
- for (i=0; i<num; i++) {
- vid = rb_ary_entry(rest,i);
- data->ids[i] = rb_to_id(vid);
- data->stype[i] = *ctype;
- ctype ++;
- if (isdigit(*ctype)) {
- char *p, *d;
- for (p=ctype; isdigit(*p); p++) ;
- d = ALLOCA_N(char, p - ctype + 1);
- strncpy(d, ctype, p - ctype);
- d[p - ctype] = '\0';
- data->ssize[i] = atoi(d);
- ctype = p;
- }
- else{
- data->ssize[i] = 1;
- }
- }
-
- if (*ctype) {
- rb_raise(rb_eArgError, "too few/many arguments");
- }
-
- if (!data->size)
- data->size = dlsizeof(RSTRING(type)->ptr);
-
- return Qnil;
-}
-
-VALUE
-rb_dlptr_define_struct(int argc, VALUE argv[], VALUE self)
-{
- VALUE *pass_argv;
- int pass_argc, i;
-
- pass_argc = argc + 1;
- pass_argv = ALLOCA_N(VALUE, pass_argc);
- pass_argv[0] = INT2FIX(DLPTR_CTYPE_STRUCT);
- for (i=1; i<pass_argc; i++) {
- pass_argv[i] = argv[i-1];
- }
- return rb_dlptr_define_data_type(pass_argc, pass_argv, self);
-}
-
-VALUE
-rb_dlptr_define_union(int argc, VALUE argv[], VALUE self)
-{
- VALUE *pass_argv;
- int pass_argc, i;
-
- pass_argc = argc + 1;
- pass_argv = ALLOCA_N(VALUE, pass_argc);
- pass_argv[0] = INT2FIX(DLPTR_CTYPE_UNION);
- for (i=1; i<pass_argc; i++) {
- pass_argv[i] = argv[i-1];
- }
- return rb_dlptr_define_data_type(pass_argc, pass_argv, self);
-}
-
-VALUE
-rb_dlptr_get_data_type(VALUE self)
-{
- struct ptr_data *data;
-
- Data_Get_Struct(self, struct ptr_data, data);
- if (data->stype)
- return rb_assoc_new(INT2FIX(data->ctype),
- rb_tainted_str_new(data->stype, data->slen));
- else
- return rb_assoc_new(INT2FIX(data->ctype), Qnil);
-}
-
-static VALUE
-cary2ary(void *ptr, char t, int len)
-{
- VALUE ary;
- VALUE elem;
- int i;
-
- if (len < 1)
- return Qnil;
-
- if (len == 1) {
- switch (t) {
- case 'I':
- elem = INT2NUM(*((int*)ptr));
- ptr = (char *)ptr + sizeof(int);
- break;
- case 'L':
- elem = DLLONG2NUM(*((long*)ptr));
- ptr = (char *)ptr + sizeof(long);
- break;
- case 'P':
- case 'S':
- elem = rb_dlptr_new(*((void**)ptr),0, 0);
- ptr = (char *)ptr + sizeof(void*);
- break;
- case 'F':
- elem = rb_float_new(*((float*)ptr));
- ptr = (char *)ptr + sizeof(float);
- break;
- case 'D':
- elem = rb_float_new(*((double*)ptr));
- ptr = (char *)ptr + sizeof(double);
- break;
- case 'C':
- elem = INT2NUM(*((char*)ptr));
- ptr = (char *)ptr + sizeof(char);
- break;
- case 'H':
- elem = INT2NUM(*((short*)ptr));
- ptr = (char *)ptr + sizeof(short);
- break;
- default:
- rb_raise(rb_eDLTypeError, "unsupported type '%c'", t);
- }
- return elem;
- }
-
- ary = rb_ary_new();
- for (i=0; i < len; i++) {
- switch (t) {
- case 'I':
- elem = INT2NUM(*((int*)ptr));
- ptr = (char *)ptr + sizeof(int);
- break;
- case 'L':
- elem = DLLONG2NUM(*((long*)ptr));
- ptr = (char *)ptr + sizeof(long);
- break;
- case 'P':
- case 'S':
- elem = rb_dlptr_new(*((void**)ptr), 0, 0);
- ptr = (char *)ptr + sizeof(void*);
- break;
- case 'F':
- elem = rb_float_new(*((float*)ptr));
- ptr = (char *)ptr + sizeof(float);
- break;
- case 'D':
- elem = rb_float_new(*((float*)ptr));
- ptr = (char *)ptr + sizeof(double);
- break;
- case 'C':
- elem = INT2NUM(*((char*)ptr));
- ptr = (char *)ptr + sizeof(char);
- break;
- case 'H':
- elem = INT2NUM(*((short*)ptr));
- ptr = (char *)ptr + sizeof(short);
- break;
- default:
- rb_raise(rb_eDLTypeError, "unsupported type '%c'", t);
- }
- rb_ary_push(ary, elem);
- }
-
- return ary;
-}
-
-VALUE
-rb_dlptr_aref(int argc, VALUE argv[], VALUE self)
-{
- VALUE key = Qnil, num = Qnil;
- ID id;
- struct ptr_data *data;
- int i;
- int offset;
-
- if (rb_scan_args(argc, argv, "11", &key, &num) == 1) {
- num = INT2NUM(0);
- }
-
- if (TYPE(key) == T_FIXNUM || TYPE(key) == T_BIGNUM) {
- VALUE pass[1];
- pass[0] = num;
- return rb_dlptr_to_str(1, pass, rb_dlptr_plus(self, key));
- }
- rb_to_id(key);
- if (! (TYPE(key) == T_STRING || TYPE(key) == T_SYMBOL)) {
- rb_raise(rb_eTypeError, "the key must be a string or symbol");
- }
-
- id = rb_to_id(key);
- Data_Get_Struct(self, struct ptr_data, data);
- offset = 0;
- switch (data->ctype) {
- case DLPTR_CTYPE_STRUCT:
- for (i=0; i < data->ids_num; i++) {
- switch (data->stype[i]) {
- case 'I':
- DLALIGN(data->ptr,offset,INT_ALIGN);
- break;
- case 'L':
- DLALIGN(data->ptr,offset,LONG_ALIGN);
- break;
- case 'P':
- case 'S':
- DLALIGN(data->ptr,offset,VOIDP_ALIGN);
- break;
- case 'F':
- DLALIGN(data->ptr,offset,FLOAT_ALIGN);
- break;
- case 'D':
- DLALIGN(data->ptr,offset,DOUBLE_ALIGN);
- break;
- case 'C':
- break;
- case 'H':
- DLALIGN(data->ptr,offset,SHORT_ALIGN);
- break;
- default:
- rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
- }
- if (data->ids[i] == id) {
- return cary2ary((char *)data->ptr + offset, data->stype[i], data->ssize[i]);
- }
- switch (data->stype[i]) {
- case 'I':
- offset += sizeof(int) * data->ssize[i];
- break;
- case 'L':
- offset += sizeof(long) * data->ssize[i];
- break;
- case 'P':
- case 'S':
- offset += sizeof(void*) * data->ssize[i];
- break;
- case 'F':
- offset += sizeof(float) * data->ssize[i];
- break;
- case 'D':
- offset += sizeof(double) * data->ssize[i];
- break;
- case 'C':
- offset += sizeof(char) * data->ssize[i];
- break;
- case 'H':
- offset += sizeof(short) * data->ssize[i];
- break;
- default:
- rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
- }
- }
- break;
- case DLPTR_CTYPE_UNION:
- for (i=0; i < data->ids_num; i++) {
- if (data->ids[i] == id) {
- return cary2ary((char *)data->ptr + offset, data->stype[i], data->ssize[i]);
- }
- }
- break;
- } /* end of switch */
-
- rb_raise(rb_eNameError, "undefined key `%s' for %s",
- rb_id2name(id), rb_class2name(CLASS_OF(self)));
-
- return Qnil;
-}
-
-static void *
-ary2cary(char t, VALUE val, long *size)
-{
- void *ptr;
-
- if (TYPE(val) == T_ARRAY) {
- ptr = rb_ary2cary(t, val, size);
- }
- else{
- ptr = rb_ary2cary(t, rb_ary_new3(1, val), size);
- }
- return ptr;
-}
-
-VALUE
-rb_dlptr_aset(int argc, VALUE argv[], VALUE self)
-{
- VALUE key = Qnil, num = Qnil, val = Qnil;
- ID id;
- struct ptr_data *data;
- int i;
- int offset;
- long memsize;
- void *memimg;
-
- rb_secure(4);
- switch (rb_scan_args(argc, argv, "21", &key, &num, &val)) {
- case 2:
- val = num;
- num = Qnil;
- break;
- }
-
- if (TYPE(key) == T_FIXNUM || TYPE(key) == T_BIGNUM) {
- void *dst, *src;
- long len;
-
- StringValue(val);
- Data_Get_Struct(self, struct ptr_data, data);
- dst = (void*)((long)(data->ptr) + DLNUM2LONG(key));
- src = RSTRING(val)->ptr;
- len = RSTRING(val)->len;
- if (num == Qnil) {
- memcpy(dst, src, len);
- }
- else{
- long n = NUM2INT(num);
- memcpy(dst, src, n < len ? n : len);
- if (n > len) MEMZERO((char*)dst + len, char, n - len);
- }
- return val;
- }
-
- id = rb_to_id(key);
- Data_Get_Struct(self, struct ptr_data, data);
- switch (data->ctype) {
- case DLPTR_CTYPE_STRUCT:
- offset = 0;
- for (i=0; i < data->ids_num; i++) {
- switch (data->stype[i]) {
- case 'I':
- DLALIGN(data->ptr,offset,INT_ALIGN);
- break;
- case 'L':
- DLALIGN(data->ptr,offset,LONG_ALIGN);
- break;
- case 'P':
- case 'S':
- DLALIGN(data->ptr,offset,VOIDP_ALIGN);
- break;
- case 'D':
- DLALIGN(data->ptr,offset,DOUBLE_ALIGN);
- break;
- case 'F':
- DLALIGN(data->ptr,offset,FLOAT_ALIGN);
- break;
- case 'C':
- break;
- case 'H':
- DLALIGN(data->ptr,offset,SHORT_ALIGN);
- break;
- default:
- rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
- }
- if (data->ids[i] == id) {
- memimg = ary2cary(data->stype[i], val, &memsize);
- memcpy((char *)data->ptr + offset, memimg, memsize);
- dlfree(memimg);
- return val;
- }
- switch (data->stype[i]) {
- case 'I':
- case 'i':
- offset += sizeof(int) * data->ssize[i];
- break;
- case 'L':
- case 'l':
- offset += sizeof(long) * data->ssize[i];
- break;
- case 'P':
- case 'p':
- case 'S':
- case 's':
- offset += sizeof(void*) * data->ssize[i];
- break;
- case 'D':
- case 'd':
- offset += sizeof(double) * data->ssize[i];
- break;
- case 'F':
- case 'f':
- offset += sizeof(float) * data->ssize[i];
- break;
- case 'C':
- case 'c':
- offset += sizeof(char) * data->ssize[i];
- break;
- case 'H':
- case 'h':
- offset += sizeof(short) * data->ssize[i];
- break;
- default:
- rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
- }
- }
- return val;
- /* break; */
- case DLPTR_CTYPE_UNION:
- for (i=0; i < data->ids_num; i++) {
- if (data->ids[i] == id) {
- switch (data->stype[i]) {
- case 'I': case 'i':
- memsize = sizeof(int) * data->ssize[i];
- break;
- case 'L': case 'l':
- memsize = sizeof(long) * data->ssize[i];
- break;
- case 'P': case 'p':
- case 'S': case 's':
- memsize = sizeof(void*) * data->ssize[i];
- break;
- case 'F': case 'f':
- memsize = sizeof(float) * data->ssize[i];
- break;
- case 'D': case 'd':
- memsize = sizeof(double) * data->ssize[i];
- break;
- case 'C': case 'c':
- memsize = sizeof(char) * data->ssize[i];
- break;
- case 'H': case 'h':
- memsize = sizeof(short) * data->ssize[i];
- break;
- default:
- rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
- }
- memimg = ary2cary(data->stype[i], val, NULL);
- memcpy(data->ptr, memimg, memsize);
- dlfree(memimg);
- }
- }
- return val;
- /* break; */
- }
-
- rb_raise(rb_eNameError, "undefined key `%s' for %s",
- rb_id2name(id), rb_class2name(CLASS_OF(self)));
-
- return Qnil;
-}
-
-VALUE
-rb_dlptr_size(int argc, VALUE argv[], VALUE self)
-{
- VALUE size;
-
- if (rb_scan_args(argc, argv, "01", &size) == 0){
- return DLLONG2NUM(RDLPTR(self)->size);
- }
- else{
- RDLPTR(self)->size = DLNUM2LONG(size);
- return size;
- }
-}
-
-static VALUE
-dlmem_each_i(VALUE assoc, void *data)
-{
- VALUE key, val;
- key = rb_ary_entry(assoc, 0);
- val = rb_ary_entry(assoc, 1);
- rb_yield(rb_assoc_new(key,(VALUE)DLNUM2LONG(val)));
- return Qnil;
-}
-
-VALUE
-rb_dlmem_each(VALUE self)
-{
- rb_iterate(rb_each, DLMemoryTable, dlmem_each_i, 0);
- return Qnil;
-}
-
-void
-Init_dlptr()
-{
- rb_cDLPtrData = rb_define_class_under(rb_mDL, "PtrData", rb_cObject);
- rb_define_alloc_func(rb_cDLPtrData, rb_dlptr_s_allocate);
- rb_define_singleton_method(rb_cDLPtrData, "malloc", rb_dlptr_s_malloc, -1);
- rb_define_method(rb_cDLPtrData, "initialize", rb_dlptr_initialize, -1);
- rb_define_method(rb_cDLPtrData, "free=", rb_dlptr_free_set, 1);
- rb_define_method(rb_cDLPtrData, "free", rb_dlptr_free_get, 0);
- rb_define_method(rb_cDLPtrData, "to_i", rb_dlptr_to_i, 0);
- rb_define_method(rb_cDLPtrData, "ptr", rb_dlptr_ptr, 0);
- rb_define_method(rb_cDLPtrData, "+@", rb_dlptr_ptr, 0);
- rb_define_method(rb_cDLPtrData, "ref", rb_dlptr_ref, 0);
- rb_define_method(rb_cDLPtrData, "-@", rb_dlptr_ref, 0);
- rb_define_method(rb_cDLPtrData, "null?", rb_dlptr_null_p, 0);
- rb_define_method(rb_cDLPtrData, "to_a", rb_dlptr_to_array, -1);
- rb_define_method(rb_cDLPtrData, "to_s", rb_dlptr_to_s, -1);
- rb_define_method(rb_cDLPtrData, "to_str", rb_dlptr_to_str, -1);
- rb_define_method(rb_cDLPtrData, "inspect", rb_dlptr_inspect, 0);
- rb_define_method(rb_cDLPtrData, "<=>", rb_dlptr_cmp, 1);
- rb_define_method(rb_cDLPtrData, "==", rb_dlptr_eql, 1);
- rb_define_method(rb_cDLPtrData, "eql?", rb_dlptr_eql, 1);
- rb_define_method(rb_cDLPtrData, "+", rb_dlptr_plus, 1);
- rb_define_method(rb_cDLPtrData, "-", rb_dlptr_minus, 1);
- rb_define_method(rb_cDLPtrData, "define_data_type",
- rb_dlptr_define_data_type, -1);
- rb_define_method(rb_cDLPtrData, "struct!", rb_dlptr_define_struct, -1);
- rb_define_method(rb_cDLPtrData, "union!", rb_dlptr_define_union, -1);
- rb_define_method(rb_cDLPtrData, "data_type", rb_dlptr_get_data_type, 0);
- rb_define_method(rb_cDLPtrData, "[]", rb_dlptr_aref, -1);
- rb_define_method(rb_cDLPtrData, "[]=", rb_dlptr_aset, -1);
- rb_define_method(rb_cDLPtrData, "size", rb_dlptr_size, -1);
- rb_define_method(rb_cDLPtrData, "size=", rb_dlptr_size, -1);
-
- rb_mDLMemorySpace = rb_define_module_under(rb_mDL, "MemorySpace");
- DLMemoryTable = rb_hash_new();
- rb_define_const(rb_mDLMemorySpace, "MemoryTable", DLMemoryTable);
- rb_define_module_function(rb_mDLMemorySpace, "each", rb_dlmem_each, 0);
-}
diff --git a/ext/dl/sample/c++sample.C b/ext/dl/sample/c++sample.C
deleted file mode 100644
index d083d337a7..0000000000
--- a/ext/dl/sample/c++sample.C
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <stdio.h>
-
-class Person {
-private:
- const char *name;
- int age;
-
-public:
- Person(const char *name, int age);
- const char * get_name();
- int get_age();
- void set_age(int i);
-};
-
-Person::Person(const char *name, int age)
- : name(name), age(age)
-{
- /* empty */
-}
-
-const char *
-Person::get_name()
-{
- return name;
-}
-
-int
-Person::get_age(){
- return age;
-}
-
-void
-Person::set_age(int i){
- age = i;
-}
diff --git a/ext/dl/sample/c++sample.rb b/ext/dl/sample/c++sample.rb
deleted file mode 100644
index 29887df845..0000000000
--- a/ext/dl/sample/c++sample.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-=begin
- This script shows how to deal with C++ classes using Ruby/DL.
- You must build a dynamic loadable library using "c++sample.C"
- to run this script as follows:
- $ g++ -o libsample.so -shared c++sample.C
-=end
-
-require 'dl'
-require 'dl/import'
-require 'dl/struct'
-
-# Give a name of dynamic loadable library
-LIBNAME = ARGV[0] || "libsample.so"
-
-class Person
- module Core
- extend DL::Importable
-
- dlload LIBNAME
-
- # mangled symbol names
- extern "void __6PersonPCci(void *, const char *, int)"
- extern "const char *get_name__6Person(void *)"
- extern "int get_age__6Person(void *)"
- extern "void set_age__6Personi(void *, int)"
-
- Data = struct [
- "char *name",
- "int age",
- ]
- end
-
- def initialize(name, age)
- @ptr = Core::Data.alloc
- Core::__6PersonPCci(@ptr, name, age)
- end
-
- def get_name()
- str = Core::get_name__6Person(@ptr)
- if( str )
- str.to_s
- else
- nil
- end
- end
-
- def get_age()
- Core::get_age__6Person(@ptr)
- end
-
- def set_age(age)
- Core::set_age__6Personi(@ptr, age)
- end
-end
-
-obj = Person.new("ttate", 1)
-p obj.get_name()
-p obj.get_age()
-obj.set_age(10)
-p obj.get_age()
diff --git a/ext/dl/sample/drives.rb b/ext/dl/sample/drives.rb
deleted file mode 100644
index 8a590404b1..0000000000
--- a/ext/dl/sample/drives.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-# -*- ruby -*-
-# drives.rb -- find existing drives and show the drive type.
-
-require 'dl'
-require 'dl/import'
-
-module Kernel32
- extend DL::Importable
-
- dlload "kernel32"
-
- extern "long GetLogicalDrives()"
- extern "int GetDriveType(char*)"
- extern "long GetDiskFreeSpace(char*, long ref, long ref, long ref, long ref)"
-end
-
-include Kernel32
-
-buff = Kernel32.getLogicalDrives()
-
-i = 0
-ds = []
-while( i < 26 )
- mask = (1 << i)
- if( buff & mask > 0 )
- ds.push((65+i).chr)
- end
- i += 1
-end
-
-=begin
-From the cygwin's /usr/include/w32api/winbase.h:
-#define DRIVE_UNKNOWN 0
-#define DRIVE_NO_ROOT_DIR 1
-#define DRIVE_REMOVABLE 2
-#define DRIVE_FIXED 3
-#define DRIVE_REMOTE 4
-#define DRIVE_CDROM 5
-#define DRIVE_RAMDISK 6
-=end
-
-types = [
- "unknown",
- "no root dir",
- "Removable",
- "Fixed",
- "Remote",
- "CDROM",
- "RAM",
-]
-print("Drive : Type (Free Space/Available Space)\n")
-ds.each{|d|
- t = Kernel32.getDriveType(d + ":\\")
- Kernel32.getDiskFreeSpace(d + ":\\", 0, 0, 0, 0)
- _,sec_per_clus,byte_per_sec,free_clus,total_clus = Kernel32._args_
- fbytes = sec_per_clus * byte_per_sec * free_clus
- tbytes = sec_per_clus * byte_per_sec * total_clus
- unit = "B"
- if( fbytes > 1024 && tbytes > 1024 )
- fbytes = fbytes / 1024
- tbytes = tbytes / 1024
- unit = "K"
- end
- if( fbytes > 1024 && tbytes > 1024 )
- fbytes = fbytes / 1024
- tbytes = tbytes / 1024
- unit = "M"
- end
- print("#{d} : #{types[t]} (#{fbytes} #{unit}/#{tbytes} #{unit})\n")
-}
diff --git a/ext/dl/sample/getch.rb b/ext/dl/sample/getch.rb
deleted file mode 100644
index 3f7261c979..0000000000
--- a/ext/dl/sample/getch.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'dl'
-
-crtdll = DL::dlopen("crtdll")
-getch = crtdll['_getch', 'L']
-print(getch.call, "\n")
diff --git a/ext/dl/sample/libc.rb b/ext/dl/sample/libc.rb
deleted file mode 100644
index a1f6fbe543..0000000000
--- a/ext/dl/sample/libc.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-require "dl/import"
-require "dl/struct"
-
-module LIBC
- extend DL::Importable
-
- begin
- dlload "libc.so.6"
- rescue
- dlload "libc.so.5"
- end
-
- extern "int atoi(char*)"
- extern "ibool isdigit(int)"
- extern "int gettimeofday(struct timeval *, struct timezone *)"
- extern "char* strcat(char*, char*)"
- extern "FILE* fopen(char*, char*)"
- extern "int fclose(FILE*)"
- extern "int fgetc(FILE*)"
- extern "int strlen(char*)"
- extern "void qsort(void*, int, int, void*)"
-
- def str_qsort(ary, comp)
- len = ary.length
- r,rs = qsort(ary, len, DL.sizeof('P'), comp)
- return rs[0].to_a('S', len)
- end
-
- Timeval = struct [
- "long tv_sec",
- "long tv_usec",
- ]
-
- Timezone = struct [
- "int tz_minuteswest",
- "int tz_dsttime",
- ]
-
- def my_compare(ptr1, ptr2)
- ptr1.ptr.to_s <=> ptr2.ptr.to_s
- end
- COMPARE = callback("int my_compare(char**, char**)")
-end
-
-
-$cb1 = DL.callback('IPP'){|ptr1, ptr2|
- str1 = ptr1.ptr.to_s
- str2 = ptr2.ptr.to_s
- str1 <=> str2
-}
-
-p LIBC.atoi("10")
-
-p LIBC.isdigit(?1)
-
-p LIBC.isdigit(?a)
-
-p LIBC.strcat("a", "b")
-
-ary = ["a","c","b"]
-ptr = ary.to_ptr
-LIBC.qsort(ptr, ary.length, DL.sizeof('P'), LIBC::COMPARE)
-p ptr.to_a('S', ary.length)
-
-tv = LIBC::Timeval.malloc
-tz = LIBC::Timezone.malloc
-LIBC.gettimeofday(tv, tz)
-
-p Time.at(tv.tv_sec)
diff --git a/ext/dl/sample/msgbox.rb b/ext/dl/sample/msgbox.rb
deleted file mode 100644
index 091e646091..0000000000
--- a/ext/dl/sample/msgbox.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# This script works on Windows.
-
-require 'dl'
-
-User32 = DL.dlopen("user32")
-Kernel32 = DL.dlopen("kernel32")
-
-MB_OK = 0
-MB_OKCANCEL = 1
-
-message_box = User32['MessageBoxA', 'ILSSI']
-r,rs = message_box.call(0, 'ok?', 'error', MB_OKCANCEL)
-
-case r
-when 1
- print("OK!\n")
-when 2
- print("Cancel!\n")
-end
diff --git a/ext/dl/sample/msgbox2.rb b/ext/dl/sample/msgbox2.rb
deleted file mode 100644
index e49846cc5e..0000000000
--- a/ext/dl/sample/msgbox2.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# This script works on Windows.
-
-require 'dl/win32'
-
-MB_OK = 0
-MB_OKCANCEL = 1
-
-message_box = Win32API.new("user32",'MessageBoxA', 'ISSI', 'I')
-r = message_box.call(0, 'ok?', 'error', MB_OKCANCEL)
-
-case r
-when 1
- print("OK!\n")
-when 2
- print("Cancel!\n")
-else
- p r
-end
diff --git a/ext/dl/sample/stream.rb b/ext/dl/sample/stream.rb
deleted file mode 100644
index 179836999d..0000000000
--- a/ext/dl/sample/stream.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-# -*- ruby -*-
-# Display a file name and stream names of a file with those size.
-
-require 'dl'
-require 'dl/import'
-
-module NTFS
- extend DL::Importable
-
- dlload "kernel32.dll"
-
- OPEN_EXISTING = 3
- GENERIC_READ = 0x80000000
- BACKUP_DATA = 0x00000001
- BACKUP_ALTERNATE_DATA = 0x00000004
- FILE_SHARE_READ = 0x00000001
- FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
-
- typealias "LPSECURITY_ATTRIBUTES", "void*"
-
- extern "BOOL BackupRead(HANDLE, PBYTE, DWORD, PDWORD, BOOL, BOOL, PVOID)"
- extern "BOOL BackupSeek(HANDLE, DWORD, DWORD, PDWORD, PDWORD, PVOID)"
- extern "BOOL CloseHandle(HANDLE)"
- extern "HANDLE CreateFile(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES,
- DWORD, DWORD, HANDLE)"
-
- module_function
-
- def streams(filename)
- status = []
- h = createFile(filename,GENERIC_READ,FILE_SHARE_READ,nil,
- OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0)
- if( h != 0 )
- begin
- # allocate the memory for backup data used in backupRead().
- data = DL.malloc(DL.sizeof("L5"))
- data.struct!("LLLLL", :id, :attrs, :size_low, :size_high, :name_size)
-
- # allocate memories for references to long values used in backupRead().
- context = DL.malloc(DL.sizeof("L"))
- lval = DL.malloc(DL.sizeof("L"))
-
- while( backupRead(h, data, data.size, lval, false, false, context) )
- size = data[:size_low] + (data[:size_high] << (DL.sizeof("I") * 8))
- case data[:id]
- when BACKUP_ALTERNATE_DATA
- stream_name = DL.malloc(data[:name_size])
- backupRead(h, stream_name, stream_name.size,
- lval, false, false, context)
- name = stream_name[0, stream_name.size]
- name.tr!("\000","")
- if( name =~ /^:(.*?):.*$/ )
- status.push([$1,size])
- end
- when BACKUP_DATA
- status.push([nil,size])
- else
- raise(RuntimeError, "unknown data type #{data[:id]}.")
- end
- l1 = DL.malloc(DL.sizeof("L"))
- l2 = DL.malloc(DL.sizeof("L"))
- if( !backupSeek(h, data[:size_low], data[:size_high], l1, l2, context) )
- break
- end
- end
- ensure
- backupRead(h, nil, 0, lval, true, false, context)
- closeHandle(h)
- end
- return status
- else
- raise(RuntimeError, "can't open #{filename}.\n")
- end
- end
-end
-
-ARGV.each{|filename|
- if( File.exist?(filename) )
- NTFS.streams(filename).each{|name,size|
- if( name )
- print("#{filename}:#{name}\t#{size}bytes\n")
- else
- print("#{filename}\t#{size}bytes\n")
- end
- }
- end
-}
diff --git a/ext/dl/sym.c b/ext/dl/sym.c
deleted file mode 100644
index 40b2035c00..0000000000
--- a/ext/dl/sym.c
+++ /dev/null
@@ -1,992 +0,0 @@
-/* -*- C -*-
- * $Id$
- */
-
-#include <ruby.h>
-#include <errno.h>
-#include "dl.h"
-
-VALUE rb_cDLSymbol;
-
-static const char *
-char2type(int ch)
-{
- switch (ch) {
- case '0':
- return "void";
- case 'P':
- return "void *";
- case 'p':
- return "void *";
- case 'C':
- return "char";
- case 'c':
- return "char *";
- case 'H':
- return "short";
- case 'h':
- return "short *";
- case 'I':
- return "int";
- case 'i':
- return "int *";
- case 'L':
- return "long";
- case 'l':
- return "long *";
- case 'F':
- return "double";
- case 'f':
- return "double *";
- case 'D':
- return "double";
- case 'd':
- return "double *";
- case 'S':
- return "const char *";
- case 's':
- return "char *";
- case 'A':
- return "[]";
- case 'a':
- return "[]"; /* ?? */
- }
- return NULL;
-}
-
-void
-dlsym_free(struct sym_data *data)
-{
- if( data->name ){
- DEBUG_CODE({
- printf("dlsym_free(): free(data->name:%s)\n",data->name);
- });
- free(data->name);
- }
- if( data->type ){
- DEBUG_CODE({
- printf("dlsym_free(): free(data->type:%s)\n",data->type);
- });
- free(data->type);
- }
-}
-
-VALUE
-rb_dlsym_new(void (*func)(), const char *name, const char *type)
-{
- VALUE val;
- struct sym_data *data;
- const char *ptype;
-
- rb_secure(4);
- if( !type || !type[0] ){
- return rb_dlptr_new((void*)func, 0, 0);
- }
-
- for( ptype = type; *ptype; ptype ++ ){
- if( ! char2type(*ptype) ){
- rb_raise(rb_eDLTypeError, "unknown type specifier '%c'", *ptype);
- }
- }
-
- if( func ){
- val = Data_Make_Struct(rb_cDLSymbol, struct sym_data, 0, dlsym_free, data);
- data->func = func;
- data->name = name ? strdup(name) : NULL;
- data->type = type ? strdup(type) : NULL;
- data->len = type ? strlen(type) : 0;
-#if !(defined(DLSTACK))
- if( data->len - 1 > MAX_ARG ){
- rb_raise(rb_eDLError, "maximum number of arguments is %d.", MAX_ARG);
- }
-#endif
- }
- else{
- val = Qnil;
- }
-
- return val;
-}
-
-freefunc_t
-rb_dlsym2csym(VALUE val)
-{
- struct sym_data *data;
- freefunc_t func;
-
- if( rb_obj_is_kind_of(val, rb_cDLSymbol) ){
- Data_Get_Struct(val, struct sym_data, data);
- func = data->func;
- }
- else if( val == Qnil ){
- func = NULL;
- }
- else{
- rb_raise(rb_eTypeError, "DL::Symbol was expected");
- }
-
- return func;
-}
-
-VALUE
-rb_dlsym_s_allocate(VALUE klass)
-{
- VALUE obj;
- struct sym_data *data;
-
- obj = Data_Make_Struct(klass, struct sym_data, 0, dlsym_free, data);
- data->func = 0;
- data->name = 0;
- data->type = 0;
- data->len = 0;
-
- return obj;
-}
-
-VALUE
-rb_dlsym_initialize(int argc, VALUE argv[], VALUE self)
-{
- VALUE addr, name, type;
- struct sym_data *data;
- void *saddr;
- const char *sname, *stype;
-
- rb_scan_args(argc, argv, "12", &addr, &name, &type);
-
- saddr = (void*)(DLNUM2LONG(rb_Integer(addr)));
- if (!NIL_P(name)) StringValue(name);
- stype = NIL_P(type) ? NULL : StringValuePtr(type);
- sname = NIL_P(name) ? NULL : RSTRING(name)->ptr;
-
- if( saddr ){
- Data_Get_Struct(self, struct sym_data, data);
- if( data->name ) free(data->name);
- if( data->type ) free(data->type);
- data->func = saddr;
- data->name = sname ? strdup(sname) : 0;
- data->type = stype ? strdup(stype) : 0;
- data->len = stype ? strlen(stype) : 0;
- }
-
- return Qnil;
-}
-
-VALUE
-rb_s_dlsym_char2type(VALUE self, VALUE ch)
-{
- const char *type;
-
- type = char2type(StringValuePtr(ch)[0]);
-
- if (type == NULL)
- return Qnil;
- else
- return rb_str_new2(type);
-}
-
-VALUE
-rb_dlsym_name(VALUE self)
-{
- struct sym_data *sym;
-
- Data_Get_Struct(self, struct sym_data, sym);
- return sym->name ? rb_tainted_str_new2(sym->name) : Qnil;
-}
-
-VALUE
-rb_dlsym_proto(VALUE self)
-{
- struct sym_data *sym;
-
- Data_Get_Struct(self, struct sym_data, sym);
- return sym->type ? rb_tainted_str_new2(sym->type) : Qnil;
-}
-
-VALUE
-rb_dlsym_cproto(VALUE self)
-{
- struct sym_data *sym;
- const char *ptype, *typestr;
- size_t len;
- VALUE val;
-
- Data_Get_Struct(self, struct sym_data, sym);
-
- ptype = sym->type;
-
- if( ptype ){
- typestr = char2type(*ptype++);
- len = strlen(typestr);
-
- val = rb_tainted_str_new(typestr, len);
- if (typestr[len - 1] != '*')
- rb_str_cat(val, " ", 1);
-
- if( sym->name ){
- rb_str_cat2(val, sym->name);
- }
- else{
- rb_str_cat2(val, "(null)");
- }
- rb_str_cat(val, "(", 1);
-
- while (*ptype) {
- const char *ty = char2type(*ptype++);
- rb_str_cat2(val, ty);
- if (*ptype)
- rb_str_cat(val, ", ", 2);
- }
-
- rb_str_cat(val, ");", 2);
- }
- else{
- val = rb_tainted_str_new2("void (");
- if( sym->name ){
- rb_str_cat2(val, sym->name);
- }
- else{
- rb_str_cat2(val, "(null)");
- }
- rb_str_cat2(val, ")()");
- }
-
- return val;
-}
-
-VALUE
-rb_dlsym_inspect(VALUE self)
-{
- VALUE proto;
- VALUE val;
- char *str;
- int str_size;
- struct sym_data *sym;
-
- Data_Get_Struct(self, struct sym_data, sym);
- proto = rb_dlsym_cproto(self);
-
- str_size = RSTRING(proto)->len + 100;
- str = dlmalloc(str_size);
- snprintf(str, str_size - 1,
- "#<DL::Symbol:0x%p func=0x%p '%s'>",
- sym, sym->func, RSTRING(proto)->ptr);
- val = rb_tainted_str_new2(str);
- dlfree(str);
-
- return val;
-}
-
-static int
-stack_size(struct sym_data *sym)
-{
- int i;
- int size;
-
- size = 0;
- for( i=1; i < sym->len; i++ ){
- switch(sym->type[i]){
- case 'C':
- case 'H':
- case 'I':
- case 'L':
- size += sizeof(long);
- break;
- case 'F':
- size += sizeof(float);
- break;
- case 'D':
- size += sizeof(double);
- break;
- case 'c':
- case 'h':
- case 'i':
- case 'l':
- case 'f':
- case 'd':
- case 'p':
- case 'P':
- case 's':
- case 'S':
- case 'a':
- case 'A':
- size += sizeof(void*);
- break;
- default:
- return -(sym->type[i]);
- }
- }
- return size;
-}
-
-static ID rb_dl_id_DLErrno;
-
-static VALUE
-rb_dl_get_last_error(VALUE self)
-{
- return rb_thread_local_aref(rb_thread_current(), rb_dl_id_DLErrno);
-}
-
-static VALUE
-rb_dl_set_last_error(VALUE self, VALUE val)
-{
- errno = NUM2INT(val);
- rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLErrno, val);
- return Qnil;
-}
-
-#ifdef HAVE_WINDOWS_H
-#include <windows.h>
-static ID rb_dl_id_DLW32Error;
-
-static VALUE
-rb_dl_win32_get_last_error(VALUE self)
-{
- return rb_thread_local_aref(rb_thread_current(), rb_dl_id_DLW32Error);
-}
-
-static VALUE
-rb_dl_win32_set_last_error(VALUE self, VALUE val)
-{
- SetLastError(NUM2INT(val));
- rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLW32Error, val);
- return Qnil;
-}
-#endif
-
-#ifdef DLSTACK_GUARD
-# ifdef __MSVC_RUNTIME_CHECKS
-# pragma runtime_checks("s", off)
-# endif
-# if _MSC_VER >= 1300
-__declspec(noinline)
-# endif
-static int
-rb_dlsym_guardcall(char type, ANY_TYPE *ret, long *stack, void *func)
-{
- char *volatile guard = ALLOCA_N(char, 1); /* guard stack pointer */
- switch(type){
- case '0':
- {
- void (*f)(DLSTACK_PROTO) = func;
- f(DLSTACK_ARGS);
- }
- break;
- case 'P':
- case 'p':
- {
- void * (*f)(DLSTACK_PROTO) = func;
- ret->p = f(DLSTACK_ARGS);
- }
- break;
- case 'C':
- case 'c':
- {
- char (*f)(DLSTACK_PROTO) = func;
- ret->c = f(DLSTACK_ARGS);
- }
- break;
- case 'H':
- case 'h':
- {
- short (*f)(DLSTACK_PROTO) = func;
- ret->h = f(DLSTACK_ARGS);
- }
- break;
- case 'I':
- case 'i':
- {
- int (*f)(DLSTACK_PROTO) = func;
- ret->i = f(DLSTACK_ARGS);
- }
- break;
- case 'L':
- case 'l':
- {
- long (*f)(DLSTACK_PROTO) = func;
- ret->l = f(DLSTACK_ARGS);
- }
- break;
- case 'F':
- case 'f':
- {
- float (*f)(DLSTACK_PROTO) = func;
- ret->f = f(DLSTACK_ARGS);
- }
- break;
- case 'D':
- case 'd':
- {
- double (*f)(DLSTACK_PROTO) = func;
- ret->d = f(DLSTACK_ARGS);
- }
- break;
- case 'S':
- case 's':
- {
- char * (*f)(DLSTACK_PROTO) = func;
- ret->s = f(DLSTACK_ARGS);
- }
- break;
- default:
- return 0;
- }
- return 1;
-}
-# ifdef __MSVC_RUNTIME_CHECKS
-# pragma runtime_checks("s", restore)
-# endif
-#endif /* defined(DLSTACK_GUARD) */
-
-VALUE
-rb_dlsym_call(int argc, VALUE argv[], VALUE self)
-{
- struct sym_data *sym;
- ANY_TYPE *args;
- ANY_TYPE *dargs;
- ANY_TYPE ret;
- int *dtypes;
- VALUE val;
- VALUE dvals;
- int i;
- long ftype;
- void *func;
-
- rb_secure_update(self);
- Data_Get_Struct(self, struct sym_data, sym);
- DEBUG_CODE({
- printf("rb_dlsym_call(): type = '%s', func = 0x%x\n", sym->type, sym->func);
- });
- if( (sym->len - 1) != argc ){
- rb_raise(rb_eArgError, "%d arguments are needed", sym->len - 1);
- }
-
- ftype = 0;
- dvals = Qnil;
-
- args = ALLOC_N(ANY_TYPE, sym->len - 1);
- dargs = ALLOC_N(ANY_TYPE, sym->len - 1);
- dtypes = ALLOC_N(int, sym->len - 1);
-#define FREE_ARGS {xfree(args); xfree(dargs); xfree(dtypes);}
-
- for( i = sym->len - 2; i >= 0; i-- ){
- dtypes[i] = 0;
-
- switch( sym->type[i+1] ){
- case 'p':
- dtypes[i] = 'p';
- case 'P':
- {
- struct ptr_data *data;
- VALUE pval;
-
- if( argv[i] == Qnil ){
- ANY2P(args[i]) = DLVOIDP(0);
- }
- else{
- if( rb_obj_is_kind_of(argv[i], rb_cDLPtrData) ){
- pval = argv[i];
- }
- else{
- pval = rb_funcall(argv[i], rb_intern("to_ptr"), 0);
- if( !rb_obj_is_kind_of(pval, rb_cDLPtrData) ){
- rb_raise(rb_eDLTypeError, "unexpected type of argument #%d", i);
- }
- }
- Data_Get_Struct(pval, struct ptr_data, data);
- ANY2P(args[i]) = DLVOIDP(data->ptr);
- }
- }
- PUSH_P(ftype);
- break;
- case 'a':
- dtypes[i] = 'a';
- case 'A':
- if( argv[i] == Qnil ){
- ANY2P(args[i]) = DLVOIDP(0);
- }
- else{
- ANY2P(args[i]) = DLVOIDP(rb_ary2cary(0, argv[i], NULL));
- }
- PUSH_P(ftype);
- break;
- case 'C':
- ANY2C(args[i]) = DLCHAR(NUM2CHR(argv[i]));
- PUSH_C(ftype);
- break;
- case 'c':
- ANY2C(dargs[i]) = DLCHAR(NUM2CHR(argv[i]));
- ANY2P(args[i]) = DLVOIDP(&(ANY2C(dargs[i])));
- dtypes[i] = 'c';
- PUSH_P(ftype);
- break;
- case 'H':
- ANY2H(args[i]) = DLSHORT(NUM2INT(argv[i]));
- PUSH_C(ftype);
- break;
- case 'h':
- ANY2H(dargs[i]) = DLSHORT(NUM2INT(argv[i]));
- ANY2P(args[i]) = DLVOIDP(&(ANY2H(dargs[i])));
- dtypes[i] = 'h';
- PUSH_P(ftype);
- break;
- case 'I':
- ANY2I(args[i]) = DLINT(NUM2INT(argv[i]));
- PUSH_I(ftype);
- break;
- case 'i':
- ANY2I(dargs[i]) = DLINT(NUM2INT(argv[i]));
- ANY2P(args[i]) = DLVOIDP(&(ANY2I(dargs[i])));
- dtypes[i] = 'i';
- PUSH_P(ftype);
- break;
- case 'L':
- ANY2L(args[i]) = DLNUM2LONG(argv[i]);
- PUSH_L(ftype);
- break;
- case 'l':
- ANY2L(dargs[i]) = DLNUM2LONG(argv[i]);
- ANY2P(args[i]) = DLVOIDP(&(ANY2L(dargs[i])));
- dtypes[i] = 'l';
- PUSH_P(ftype);
- break;
- case 'F':
- Check_Type(argv[i], T_FLOAT);
- ANY2F(args[i]) = DLFLOAT(RFLOAT(argv[i])->value);
- PUSH_F(ftype);
- break;
- case 'f':
- Check_Type(argv[i], T_FLOAT);
- ANY2F(dargs[i]) = DLFLOAT(RFLOAT(argv[i])->value);
- ANY2P(args[i]) = DLVOIDP(&(ANY2F(dargs[i])));
- dtypes[i] = 'f';
- PUSH_P(ftype);
- break;
- case 'D':
- Check_Type(argv[i], T_FLOAT);
- ANY2D(args[i]) = RFLOAT(argv[i])->value;
- PUSH_D(ftype);
- break;
- case 'd':
- Check_Type(argv[i], T_FLOAT);
- ANY2D(dargs[i]) = RFLOAT(argv[i])->value;
- ANY2P(args[i]) = DLVOIDP(&(ANY2D(dargs[i])));
- dtypes[i] = 'd';
- PUSH_P(ftype);
- break;
- case 'S':
- if( argv[i] == Qnil ){
- ANY2S(args[i]) = DLSTR(0);
- }
- else{
- VALUE str = argv[i];
- SafeStringValue(str);
- ANY2S(args[i]) = DLSTR(RSTRING(str)->ptr);
- }
- PUSH_P(ftype);
- break;
- case 's':
- {
- VALUE str = argv[i];
- SafeStringValue(str);
- ANY2S(args[i]) = DLSTR(dlmalloc(RSTRING(str)->len + 1));
- memcpy((char*)(ANY2S(args[i])), RSTRING(str)->ptr, RSTRING(str)->len + 1);
- dtypes[i] = 's';
- }
- PUSH_P(ftype);
- break;
- default:
- FREE_ARGS;
- rb_raise(rb_eDLTypeError,
- "unknown type '%c' of the return value.",
- sym->type[i+1]);
- }
- }
-
- switch( sym->type[0] ){
- case '0':
- PUSH_0(ftype);
- break;
- case 'P':
- case 'p':
- case 'S':
- case 's':
- case 'A':
- case 'a':
- PUSH_P(ftype);
- break;
- case 'C':
- case 'c':
- PUSH_C(ftype);
- break;
- case 'H':
- case 'h':
- PUSH_H(ftype);
- break;
- case 'I':
- case 'i':
- PUSH_I(ftype);
- break;
- case 'L':
- case 'l':
- PUSH_L(ftype);
- break;
- case 'F':
- case 'f':
- PUSH_F(ftype);
- break;
- case 'D':
- case 'd':
- PUSH_D(ftype);
- break;
- default:
- FREE_ARGS;
- rb_raise(rb_eDLTypeError,
- "unknown type `%c' of the return value.",
- sym->type[0]);
- }
-
- func = sym->func;
-
-#if defined(DLSTACK)
- {
-#if defined(DLSTACK_SIZE)
- int stk_size;
- long stack[DLSTACK_SIZE];
- long *sp;
-
- sp = stack;
- stk_size = stack_size(sym);
- if( stk_size < 0 ){
- FREE_ARGS;
- rb_raise(rb_eDLTypeError, "unknown type '%c'.", -stk_size);
- }
- else if( stk_size > (int)(DLSTACK_SIZE) ){
- FREE_ARGS;
- rb_raise(rb_eArgError, "too many arguments.");
- }
-#endif
-
- DLSTACK_START(sym);
-
-#if defined(DLSTACK_REVERSE)
- for( i = sym->len - 2; i >= 0; i-- )
-#else
- for( i = 0; i <= sym->len -2; i++ )
-#endif
- {
- switch( sym->type[i+1] ){
- case 'p':
- case 'P':
- DLSTACK_PUSH_P(ANY2P(args[i]));
- break;
- case 'a':
- case 'A':
- DLSTACK_PUSH_P(ANY2P(args[i]));
- break;
- case 'C':
- DLSTACK_PUSH_C(ANY2C(args[i]));
- break;
- case 'c':
- DLSTACK_PUSH_P(ANY2P(args[i]));
- break;
- case 'H':
- DLSTACK_PUSH_H(ANY2H(args[i]));
- break;
- case 'h':
- DLSTACK_PUSH_P(ANY2P(args[i]));
- break;
- case 'I':
- DLSTACK_PUSH_I(ANY2I(args[i]));
- break;
- case 'i':
- DLSTACK_PUSH_P(ANY2P(args[i]));
- break;
- case 'L':
- DLSTACK_PUSH_L(ANY2L(args[i]));
- break;
- case 'l':
- DLSTACK_PUSH_P(ANY2P(args[i]));
- break;
- case 'F':
- DLSTACK_PUSH_F(ANY2F(args[i]));
- break;
- case 'f':
- DLSTACK_PUSH_P(ANY2P(args[i]));
- break;
- case 'D':
- DLSTACK_PUSH_D(ANY2D(args[i]));
- break;
- case 'd':
- DLSTACK_PUSH_P(ANY2P(args[i]));
- break;
- case 'S':
- case 's':
- DLSTACK_PUSH_P(ANY2S(args[i]));
- break;
- }
- }
- DLSTACK_END(sym->type);
-
-#ifdef DLSTACK_GUARD
- if(!rb_dlsym_guardcall(sym->type[0], &ret, stack, func)) {
- FREE_ARGS;
- rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
- }
-#else /* defined(DLSTACK_GUARD) */
- {
- switch( sym->type[0] ){
- case '0':
- {
- void (*f)(DLSTACK_PROTO) = func;
- f(DLSTACK_ARGS);
- }
- break;
- case 'P':
- case 'p':
- {
- void * (*f)(DLSTACK_PROTO) = func;
- ret.p = f(DLSTACK_ARGS);
- }
- break;
- case 'C':
- case 'c':
- {
- char (*f)(DLSTACK_PROTO) = func;
- ret.c = f(DLSTACK_ARGS);
- }
- break;
- case 'H':
- case 'h':
- {
- short (*f)(DLSTACK_PROTO) = func;
- ret.h = f(DLSTACK_ARGS);
- }
- break;
- case 'I':
- case 'i':
- {
- int (*f)(DLSTACK_PROTO) = func;
- ret.i = f(DLSTACK_ARGS);
- }
- break;
- case 'L':
- case 'l':
- {
- long (*f)(DLSTACK_PROTO) = func;
- ret.l = f(DLSTACK_ARGS);
- }
- break;
- case 'F':
- case 'f':
- {
- float (*f)(DLSTACK_PROTO) = func;
- ret.f = f(DLSTACK_ARGS);
- }
- break;
- case 'D':
- case 'd':
- {
- double (*f)(DLSTACK_PROTO) = func;
- ret.d = f(DLSTACK_ARGS);
- }
- break;
- case 'S':
- case 's':
- {
- char * (*f)(DLSTACK_PROTO) = func;
- ret.s = f(DLSTACK_ARGS);
- }
- break;
- default:
- FREE_ARGS;
- rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
- }
- }
-#endif /* defubed(DLSTACK_GUARD) */
-
- {
- /*
- * We should get the value of errno/GetLastError() before calling another functions.
- */
- int last_errno = errno;
-#ifdef _WIN32
- DWORD win32_last_err = GetLastError();
-#endif
-
- rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLErrno, INT2NUM(last_errno));
-#ifdef _WIN32
- rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLW32Error, INT2NUM(win32_last_err));
-#endif
- }
-
- }
-#else /* defined(DLSTACK) */
- switch(ftype){
-#include "call.func"
- default:
- FREE_ARGS;
- rb_raise(rb_eDLTypeError, "unsupported function type `%s'", sym->type);
- }
-#endif /* defined(DLSTACK) */
-
- switch( sym->type[0] ){
- case '0':
- val = Qnil;
- break;
- case 'P':
- val = rb_dlptr_new((void*)(ANY2P(ret)), 0, 0);
- break;
- case 'p':
- val = rb_dlptr_new((void*)(ANY2P(ret)), 0, dlfree);
- break;
- case 'C':
- case 'c':
- val = CHR2FIX((char)(ANY2C(ret)));
- break;
- case 'H':
- case 'h':
- val = INT2NUM((short)(ANY2H(ret)));
- break;
- case 'I':
- case 'i':
- val = INT2NUM((int)(ANY2I(ret)));
- break;
- case 'L':
- case 'l':
- val = DLLONG2NUM((long)(ANY2L(ret)));
- break;
- case 'F':
- case 'f':
- val = rb_float_new((double)(ANY2F(ret)));
- break;
- case 'D':
- case 'd':
- val = rb_float_new((double)(ANY2D(ret)));
- break;
- case 'S':
- if( ANY2S(ret) ){
- val = rb_tainted_str_new2((char*)(ANY2S(ret)));
- }
- else{
- val = Qnil;
- }
- break;
- case 's':
- if( ANY2S(ret) ){
- val = rb_tainted_str_new2((char*)(ANY2S(ret)));
- DEBUG_CODE({
- printf("dlfree(%s)\n",(char*)(ANY2S(ret)));
- });
- dlfree((void*)(ANY2S(ret)));
- }
- else{
- val = Qnil;
- }
- break;
- default:
- FREE_ARGS;
- rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
- }
-
- dvals = rb_ary_new();
- for( i = 0; i <= sym->len - 2; i++ ){
- if( dtypes[i] ){
- switch( dtypes[i] ){
- case 'c':
- rb_ary_push(dvals, CHR2FIX(*((char*)(ANY2P(args[i])))));
- break;
- case 'h':
- rb_ary_push(dvals, INT2NUM(*((short*)(ANY2P(args[i])))));
- break;
- case 'i':
- rb_ary_push(dvals, INT2NUM(*((int*)(ANY2P(args[i])))));
- break;
- case 'l':
- rb_ary_push(dvals, DLLONG2NUM(*((long*)(ANY2P(args[i])))));
- break;
- case 'f':
- rb_ary_push(dvals, rb_float_new(*((float*)(ANY2P(args[i])))));
- break;
- case 'd':
- rb_ary_push(dvals, rb_float_new(*((double*)(ANY2P(args[i])))));
- break;
- case 'p':
- rb_ary_push(dvals, rb_dlptr_new((void*)(ANY2P(args[i])), 0, 0));
- break;
- case 'a':
- rb_ary_push(dvals, rb_dlptr_new((void*)ANY2P(args[i]), 0, 0));
- break;
- case 's':
- rb_ary_push(dvals, rb_tainted_str_new2((char*)ANY2S(args[i])));
- DEBUG_CODE({
- printf("dlfree(%s)\n",(char*)ANY2S(args[i]));
- });
- dlfree((void*)ANY2S(args[i]));
- break;
- default:
- {
- char c = dtypes[i];
- FREE_ARGS;
- rb_raise(rb_eRuntimeError, "unknown argument type '%c'", i, c);
- }
- }
- }
- else{
- switch( sym->type[i+1] ){
- case 'A':
- dlfree((void*)ANY2P(args[i]));
- break;
- }
- rb_ary_push(dvals, argv[i]);
- }
- }
-
- FREE_ARGS;
-#undef FREE_ARGS
- return rb_assoc_new(val,dvals);
-}
-
-VALUE
-rb_dlsym_to_i(VALUE self)
-{
- struct sym_data *sym;
-
- Data_Get_Struct(self, struct sym_data, sym);
- return DLLONG2NUM(sym);
-}
-
-VALUE
-rb_dlsym_to_ptr(VALUE self)
-{
- struct sym_data *sym;
-
- Data_Get_Struct(self, struct sym_data, sym);
- return rb_dlptr_new(sym->func, sizeof(freefunc_t), 0);
-}
-
-void
-Init_dlsym()
-{
- rb_cDLSymbol = rb_define_class_under(rb_mDL, "Symbol", rb_cObject);
- rb_define_alloc_func(rb_cDLSymbol, rb_dlsym_s_allocate);
- rb_define_singleton_method(rb_cDLSymbol, "char2type", rb_s_dlsym_char2type, 1);
- rb_define_method(rb_cDLSymbol, "initialize", rb_dlsym_initialize, -1);
- rb_define_method(rb_cDLSymbol, "call", rb_dlsym_call, -1);
- rb_define_method(rb_cDLSymbol, "[]", rb_dlsym_call, -1);
- rb_define_method(rb_cDLSymbol, "name", rb_dlsym_name, 0);
- rb_define_method(rb_cDLSymbol, "proto", rb_dlsym_proto, 0);
- rb_define_method(rb_cDLSymbol, "cproto", rb_dlsym_cproto, 0);
- rb_define_method(rb_cDLSymbol, "inspect", rb_dlsym_inspect, 0);
- rb_define_method(rb_cDLSymbol, "to_s", rb_dlsym_cproto, 0);
- rb_define_method(rb_cDLSymbol, "to_ptr", rb_dlsym_to_ptr, 0);
- rb_define_method(rb_cDLSymbol, "to_i", rb_dlsym_to_i, 0);
-
- rb_dl_id_DLErrno = rb_intern("DLErrno");
- rb_define_singleton_method(rb_mDL, "last_error", rb_dl_get_last_error, 0);
- rb_define_singleton_method(rb_mDL, "last_error=", rb_dl_set_last_error, 1);
-#ifdef _WIN32
- rb_dl_id_DLW32Error = rb_intern("DLW32Error");
- rb_define_singleton_method(rb_mDL, "win32_last_error", rb_dl_win32_get_last_error, 0);
- rb_define_singleton_method(rb_mDL, "win32_last_error=", rb_dl_win32_set_last_error, 1);
-#endif
-}
diff --git a/ext/dl/test/libtest.def b/ext/dl/test/libtest.def
deleted file mode 100644
index 8ecefc917b..0000000000
--- a/ext/dl/test/libtest.def
+++ /dev/null
@@ -1,28 +0,0 @@
-EXPORTS
-test_alloc_test_struct
-test_append
-test_arylen
-test_c2i
-test_call_func1
-test_callback1
-test_close
-test_d2f
-test_f2d
-test_fill_test_struct
-test_fill_test_union
-test_gets
-test_i2c
-test_init
-test_isucc
-test_lcc
-test_lsucc
-test_open
-test_strcat
-test_strlen
-test_succ
-test_data_init
-test_data_add
-test_data_aref
-test_set_long_value
-test_get_long_value
-internal_long_value
diff --git a/ext/dl/test/test.c b/ext/dl/test/test.c
deleted file mode 100644
index 7321379390..0000000000
--- a/ext/dl/test/test.c
+++ /dev/null
@@ -1,247 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-
-static char internal_string[] = "internal_string";
-long internal_long_value = 100;
-
-struct test_struct {
- char c;
- long l;
-};
-
-union test_union {
- char c;
- int i;
- long l;
- void *p;
-};
-
-struct test_data {
- char name[1024];
- struct test_data *next;
-};
-
-long
-test_get_long_value()
-{
- return internal_long_value;
-};
-
-void
-test_set_long_value(long l)
-{
- internal_long_value = l;
-};
-
-void
-test_fill_test_struct(struct test_struct *ptr, char c, long l)
-{
- ptr->c = c;
- ptr->l = l;
-};
-
-void
-test_fill_test_union(union test_union *ptr, long l)
-{
- ptr->l = l;
-};
-
-struct test_struct *
-test_alloc_test_struct(char c, long l)
-{
- struct test_struct *data;
-
- data = (struct test_struct *)malloc(sizeof(struct test_struct));
- data->c = c;
- data->l = l;
-
- return data;
-};
-
-int
-test_c2i(char c)
-{
- return (int)c;
-};
-
-char
-test_i2c(int i)
-{
- return (char)i;
-};
-
-long
-test_lcc(char c1, char c2)
-{
- return (long)(c1 + c2);
-};
-
-double
-test_f2d(float f)
-{
- double d;
- d = f;
- return d;
-};
-
-float
-test_d2f(double d)
-{
- float f;
- f = d;
- return f;
-};
-
-int
-test_strlen(const char *str)
-{
- return strlen(str);
-};
-
-int
-test_isucc(int i)
-{
- return (i+1);
-};
-
-long
-test_lsucc(long l)
-{
- return (l+1);
-};
-
-void
-test_succ(long *l)
-{
- (*l)++;
-};
-
-char *
-test_strcat(char *str1, const char *str2)
-{
- return strcat(str1, str2);
-};
-
-int
-test_arylen(char *ary[])
-{
- int i;
- for( i=0; ary[i]; i++ ){};
- return i;
-};
-
-void
-test_append(char *ary[], int len, char *astr)
-{
- int i;
- int size1,size2;
- char *str;
-
- size2 = strlen(astr);
-
- for( i=0; i <= len - 1; i++ ){
- size1 = strlen(ary[i]);
- str = (char*)malloc(size1 + size2 + 1);
- strcpy(str, ary[i]);
- strcat(str, astr);
- ary[i] = str;
- };
-};
-
-int
-test_init(int *argc, char **argv[])
-{
- int i;
- char s[256];
-
- for( i=0; i < (*argc); i++ ){
- sprintf(s, "arg%d", i);
- if( strcmp((*argv)[i], s) != 0 ){
- return 1;
- }
- }
- return 0;
-}
-
-FILE *
-test_open(const char *filename, const char *mode)
-{
- FILE *file;
- file = fopen(filename,mode);
- return file;
-};
-
-void
-test_close(FILE *file)
-{
- fclose(file);
-};
-
-char *
-test_gets(char *s, int size, FILE *f)
-{
- return fgets(s,size,f);
-};
-
-typedef int callback1_t(int, char *);
-#define CALLBACK_MSG "callback message"
-
-int
-test_callback1(int err, const char *msg)
-{
- if( strcmp(msg, CALLBACK_MSG) == 0 ){
- return 1;
- }
- else{
- return 0;
- }
-}
-
-int
-test_call_func1(callback1_t *func)
-{
- if( func ){
- return (*func)(0, CALLBACK_MSG);
- }
- else{
- return 0;
- }
-}
-
-struct test_data *
-test_data_init()
-{
- struct test_data *data;
-
- data = (struct test_data *)malloc(sizeof(struct test_data));
- data->next = NULL;
- memset(data->name, 0, 1024);
-
- return data;
-};
-
-void
-test_data_add(struct test_data *list, const char *name)
-{
- struct test_data *data;
-
- data = (struct test_data *)malloc(sizeof(struct test_data));
- memset(data->name, 0, 1024);
- strncpy(data->name, name, 1024);
- data->next = list->next;
- list->next = data;
-};
-
-struct test_data *
-test_data_aref(struct test_data *list, int i)
-{
- struct test_data *data;
- int j;
-
- for( data = list->next, j=0; data; data = data->next, j++ ){
- if( i == j ){
- return data;
- };
- };
- return NULL;
-};
diff --git a/ext/dl/test/test.rb b/ext/dl/test/test.rb
deleted file mode 100644
index bf8dfc18e3..0000000000
--- a/ext/dl/test/test.rb
+++ /dev/null
@@ -1,306 +0,0 @@
-# -*- ruby -*-
-
-require 'dl'
-require 'dl/import'
-
-$FAIL = 0
-$TOTAL = 0
-
-def assert(label, ty, *conds)
- $TOTAL += 1
- cond = !conds.include?(false)
- if( cond )
- printf("succeed in `#{label}'\n")
- else
- $FAIL += 1
- case ty
- when :may
- printf("fail in `#{label}' ... expected\n")
- when :must
- printf("fail in `#{label}' ... unexpected\n")
- when :raise
- raise(RuntimeError, "fail in `#{label}'")
- end
- end
-end
-
-def debug(*xs)
- if( $DEBUG )
- xs.each{|x|
- p x
- }
- end
-end
-
-print("DLSTACK = #{DL::DLSTACK}\n")
-print("MAX_ARG = #{DL::MAX_ARG}\n")
-print("\n")
-print("DL::FREE = #{DL::FREE.inspect}\n")
-print("\n")
-
-$LIB = nil
-if( !$LIB && File.exist?("libtest.so") )
- $LIB = "./libtest.so"
-end
-if( !$LIB && File.exist?("test/libtest.so") )
- $LIB = "./test/libtest.so"
-end
-
-module LIBTest
- extend DL::Importable
-
- dlload($LIB)
- extern "int test_c2i(char)"
- extern "char test_i2c(int)"
- extern "long test_lcc(char, char)"
- extern "double test_f2d(float)"
- extern "float test_d2f(double)"
- extern "int test_strlen(char*)"
- extern "int test_isucc(int)"
- extern "long test_lsucc(long)"
- extern "void test_succ(long *)"
- extern "int test_arylen(int [])"
- extern "void test_append(char*[], int, char *)"
-end
-
-DL.dlopen($LIB){|h|
- c2i = h["test_c2i","IC"]
- debug c2i
- r,rs = c2i[?a]
- debug r,rs
- assert("c2i", :may, r == ?a)
- assert("extern c2i", :must, r == LIBTest.test_c2i(?a))
-
- i2c = h["test_i2c","CI"]
- debug i2c
- r,rs = i2c[?a]
- debug r,rs
- assert("i2c", :may, r == ?a)
- assert("exern i2c", :must, r == LIBTest.test_i2c(?a))
-
- lcc = h["test_lcc","LCC"]
- debug lcc
- r,rs = lcc[1,2]
- assert("lcc", :may, r == 3)
- assert("extern lcc", :must, r == LIBTest.test_lcc(1,2))
-
- f2d = h["test_f2d","DF"]
- debug f2d
- r,rs = f2d[20.001]
- debug r,rs
- assert("f2d", :may, r.to_i == 20)
- assert("extern f2d", :must, r = LIBTest.test_f2d(20.001))
-
- d2f = h["test_d2f","FD"]
- debug d2f
- r,rs = d2f[20.001]
- debug r,rs
- assert("d2f", :may, r.to_i == 20)
- assert("extern d2f", :must, r == LIBTest.test_d2f(20.001))
-
- strlen = h["test_strlen","IS"]
- debug strlen
- r,rs = strlen["0123456789"]
- debug r,rs
- assert("strlen", :must, r == 10)
- assert("extern strlen", :must, r == LIBTest.test_strlen("0123456789"))
-
- isucc = h["test_isucc","II"]
- debug isucc
- r,rs = isucc[2]
- debug r,rs
- assert("isucc", :must, r == 3)
- assert("extern isucc", :must, r == LIBTest.test_isucc(2))
-
- lsucc = h["test_lsucc","LL"]
- debug lsucc
- r,rs = lsucc[10000000]
- debug r,rs
- assert("lsucc", :must, r == 10000001)
- assert("extern lsucc", :must, r == LIBTest.test_lsucc(10000000))
-
- succ = h["test_succ","0l"]
- debug succ
- r,rs = succ[0]
- debug r,rs
- assert("succ", :must, rs[0] == 1)
- l = DL.malloc(DL.sizeof("L"))
- l.struct!("L",:lval)
- LIBTest.test_succ(l)
- assert("extern succ", :must, rs[0] == l[:lval])
-
- arylen = h["test_arylen","IA"]
- debug arylen
- r,rs = arylen[["a","b","c","d",nil]]
- debug r,rs
- assert("arylen", :must, r == 4)
-
- arylen = h["test_arylen","IP"]
- debug arylen
- r,rs = arylen[["a","b","c","d",nil]]
- debug r,rs
- assert("arylen", :must, r == 4)
- assert("extern arylen", :must, r == LIBTest.test_arylen(["a","b","c","d",nil]))
-
- append = h["test_append","0aIS"]
- debug append
- r,rs = append[["a","b","c"],3,"x"]
- debug r,rs
- assert("append", :must, rs[0].to_a('S',3) == ["ax","bx","cx"])
-
- LIBTest.test_append(["a","b","c"],3,"x")
- assert("extern append", :must, rs[0].to_a('S',3) == LIBTest._args_[0].to_a('S',3))
-
- strcat = h["test_strcat","SsS"]
- debug strcat
- r,rs = strcat["abc\0","x"]
- debug r,rs
- assert("strcat", :must, rs[0].to_s == "abcx")
-
- init = h["test_init","IiP"]
- debug init
- argc = 3
- argv = ["arg0","arg1","arg2"].to_ptr
- r,rs = init[argc, argv.ref]
- assert("init", :must, r == 0)
-}
-
-
-h = DL.dlopen($LIB)
-
-sym_open = h["test_open", "PSS"]
-sym_gets = h["test_gets", "SsIP"]
-sym_close = h["test_close", "0P"]
-debug sym_open,sym_gets,sym_close
-
-line = "Hello world!\n"
-File.open("tmp.txt", "w"){|f|
- f.print(line)
-}
-
-fp,rs = sym_open["tmp.txt", "r"]
-if( fp )
- fp.free = sym_close
- r,rs = sym_gets[" " * 256, 256, fp]
- debug r,rs
- assert("open,gets", :must, rs[0] == line)
- ObjectSpace.define_finalizer(fp) {File.unlink("tmp.txt")}
- fp = nil
-else
- assert("open,gets", :must, line == nil)
- File.unlink("tmp.txt")
-end
-
-
-callback1 = h["test_callback1"]
-debug callback1
-r,rs = h["test_call_func1", "IP"][callback1]
-debug r,rs
-assert("callback1", :must, r == 1)
-
-
-callback2 = DL.callback("LLP"){|num,ptr|
- msg = ptr.to_s
- if( msg == "callback message" )
- 2
- else
- 0
- end
-}
-debug callback2
-r,rs = h["test_call_func1", "IP"][callback2]
-debug r,rs
-assert("callback2", :must, r == 2)
-DL.remove_callback(callback2)
-
-ptr = DL.malloc(DL.sizeof('CL'))
-ptr.struct!("CL", :c, :l)
-ptr["c"] = 0
-ptr["l"] = 0
-r,rs = h["test_fill_test_struct","0PIL"][ptr,100,1000]
-debug r,rs
-assert("fill_test_struct", :must, ptr["c"] == 100, ptr["l"] == 1000)
-assert("fill_test_struct", :must, ptr[:c] == 100, ptr[:l] == 1000) unless (Fixnum === :-)
-
-
-r,rs = h["test_alloc_test_struct", "PIL"][100,200]
-r.free = DL::FREE
-r.struct!("CL", :c, :l)
-assert("alloc_test_struct", :must, r["c"] == 100, r["l"] == 200)
-assert("alloc_test_struct", :must, r[:c] == 100, r[:l] == 200) unless (Fixnum === :-)
-
-ptr = h["test_strlen"]
-sym1 = DL::Symbol.new(ptr,"foo","0")
-sym2 = h["test_strlen","LS"]
-assert("Symbol.new", :must, ptr == sym1.to_ptr, sym1.to_ptr == sym2.to_ptr)
-
-set_val = h["test_set_long_value","0"]
-get_val = h["test_get_long_value","L"]
-lval = get_val[][0]
-ptr = h["internal_long_value"]
-ptr.struct!("L", :l)
-assert("get value", :must, ptr["l"] == lval)
-assert("get value", :must, ptr[:l] == lval) unless (Fixnum === :-)
-ptr["l"] = 200
-lval = get_val[][0]
-assert("set value", :must, ptr["l"] == lval)
-assert("set value", :must, ptr[:l] == lval) unless (Fixnum === :-)
-
-
-data_init = h["test_data_init", "P"]
-data_add = h["test_data_add", "0PS"]
-data_aref = h["test_data_aref", "PPI"]
-r,rs = data_init[]
-ptr = r
-data_add[ptr, "name1"]
-data_add[ptr, "name2"]
-data_add[ptr, "name3"]
-
-r,rs = data_aref[ptr, 1]
-ptr = r
-ptr.struct!("C1024P", :name, :next)
-assert("data_aref", :must,
- ptr["name"].collect{|c| c.chr}.join.split("\0")[0] == "name2")
-assert("data_aref", :must,
- ptr["name"].collect{|c| c.chr}.join.split("\0")[0] == "name2") unless (Fixnum === :-)
-
-ptr = ptr["next"]
-ptr.struct!("C1024P", :name, :next)
-assert("data_aref", :must,
- ptr["name"].collect{|c| c.chr}.join.split("\0")[0] == "name1")
-assert("data_aref", :must,
- ptr["name"].collect{|c| c.chr}.join.split("\0")[0] == "name1") unless (Fixnum === :-)
-
-GC.start
-
-ptr = DL::malloc(32)
-ptr.struct!("CHIL", "c", "h", "i", "l")
-ptr["c"] = 1
-ptr["h"] = 2
-ptr["i"] = 3
-ptr["l"] = 4
-assert("struct!", :must,
- ptr["c"] == 1 &&
- ptr["h"] == 2 &&
- ptr["i"] == 3 &&
- ptr["l"] == 4)
-
-ptr = DL::malloc(DL::sizeof("IP"))
-ptr.struct!("IP", "n", "ptr")
-ptr["n"] = 10
-ptr["ptr"] = nil
-assert("struct!", :must, ptr["n"] == 10 && ptr["ptr"] == nil)
-
-ptr = DL::malloc(16)
-ptr.struct!("CICI", "c1", "i1", "c2", "i2")
-ptr["c1"] = 0xf1
-ptr["c2"] = 0xf2
-c1 = [ptr["c1"]].pack("c").unpack("C")[0]
-c2 = [ptr["c2"]].pack("c").unpack("C")[0]
-assert("struct!", :must,
- c1 == 0xf1 &&
- c2 == 0xf2)
-
-
-GC.start
-printf("fail/total = #{$FAIL}/#{$TOTAL}\n")
diff --git a/ext/dl/type.rb b/ext/dl/type.rb
deleted file mode 100644
index 804420c395..0000000000
--- a/ext/dl/type.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-# example:
-# DLTYPE[INT][:rb2c]["arg0"] => "NUM2INT(arg0)"
-# DLTYPE[DOUBLE][:c2rb]["r"] => "rb_float_new(r)"
-
-DLTYPE = {
- VOID = 0x00 => {
- :name => 'VOID',
- :rb2c => nil,
- :c2rb => nil,
- :ctype => "void",
- :stmem => "v",
- :sym => true,
- :cb => true,
- },
- CHAR = 0x01 => {
- :name => 'CHAR',
- :rb2c => proc{|x| "NUM2CHR(#{x})"},
- :c2rb => proc{|x| "CHR2FIX(#{x})"},
- :ctype => "char",
- :stmem => "c",
- :sym => false,
- :cb => false,
- },
- SHORT = 0x02 => {
- :name => 'SHORT',
- :rb2c => proc{|x| "FIX2INT(#{x})"},
- :c2rb => proc{|x| "INT2FIX(#{x})"},
- :ctype => "short",
- :stmem => "h",
- :sym => false,
- :cb => false,
- },
- INT = 0x03 => {
- :name => 'INT',
- :rb2c => proc{|x| "NUM2INT(#{x})"},
- :c2rb => proc{|x| "INT2NUM(#{x})"},
- :ctype => "int",
- :stmem => "i",
- :sym => true,
- :cb => false,
- },
- LONG = 0x04 => {
- :name => 'LONG',
- :rb2c => proc{|x| "NUM2INT(#{x})"},
- :c2rb => proc{|x| "INT2NUM(#{x})"},
- :ctype => "long",
- :stmem => "l",
- :sym => true,
- :cb => true,
- },
- FLOAT = 0x05 => {
- :name => 'FLOAT',
- :rb2c => proc{|x| "(float)(RFLOAT(#{x})->value)"},
- :c2rb => proc{|x| "rb_float_new((double)#{x})"},
- :ctype => "float",
- :stmem => "f",
- :sym => false,
- :cb => false,
- },
- DOUBLE = 0x06 => {
- :name => 'DOUBLE',
- :rb2c => proc{|x| "RFLOAT(#{x})->value"},
- :c2rb => proc{|x| "rb_float_new(#{x})"},
- :ctype => "double",
- :stmem => "d",
- :sym => true,
- :cb => true,
- },
- VOIDP = 0x07 => {
- :name => 'VOIDP',
- :rb2c => proc{|x| "rb_dlptr2cptr(#{x})"},
- :c2rb => proc{|x| "rb_dlptr_new(#{x},sizeof(void*),0)"},
- :ctype => "void *",
- :stmem => "p",
- :sym => true,
- :cb => true,
- },
-}
-
-def tpush(t, x)
- (t << 3)|x
-end
-
-def tget(t, i)
- (t & (0x07 << (i * 3))) >> (i * 3)
-end
-
-def types2num(types)
- res = 0x00
- r = types.reverse
- r.each{|t|
- res = tpush(res,t)
- }
- res
-end
-
-def num2types(num)
- ts = []
- i = 0
- t = tget(num,i)
- while( (t != VOID && i > 0) || (i == 0) )
- ts.push(DLTYPE[t][:ctype])
- i += 1
- t = tget(num,i)
- end
- ts
-end
-
-def types2ctypes(types)
- res = []
- types.each{|t|
- res.push(DLTYPE[t][:ctype])
- }
- res
-end
diff --git a/ext/enumerator/.cvsignore b/ext/enumerator/.cvsignore
deleted file mode 100644
index fc802ff1c2..0000000000
--- a/ext/enumerator/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-mkmf.log
diff --git a/ext/enumerator/enumerator.c b/ext/enumerator/enumerator.c
deleted file mode 100644
index 1c6e1d1ace..0000000000
--- a/ext/enumerator/enumerator.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/************************************************
-
- enumerator.c - provides Enumerator class
-
- $Author$
-
- Copyright (C) 2001-2003 Akinori MUSHA
-
- $Idaemons: /home/cvs/rb/enumerator/enumerator.c,v 1.1.1.1 2001/07/15 10:12:48 knu Exp $
- $RoughId: enumerator.c,v 1.6 2003/07/27 11:03:24 nobu Exp $
- $Id$
-
-************************************************/
-
-#include "ruby.h"
-#include "node.h"
-
-/*
- * Document-class: Enumerable::Enumerator
- *
- * A class which provides a method `each' to be used as an Enumerable
- * object.
- */
-static VALUE rb_cEnumerator;
-static ID sym_each, sym_each_with_index, sym_each_slice, sym_each_cons;
-static ID id_new, id_enum_obj, id_enum_method, id_enum_args;
-
-/*
- * call-seq:
- * obj.to_enum(method = :each, *args)
- * obj.enum_for(method = :each, *args)
- *
- * Returns Enumerable::Enumerator.new(self, method, *args).
- *
- * e.g.:
- * str = "xyz"
- *
- * enum = str.enum_for(:each_byte)
- * a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
- *
- * # protects an array from being modified
- * a = [1, 2, 3]
- * some_method(a.to_enum)
- *
- */
-static VALUE
-obj_to_enum(obj, enum_args)
- VALUE obj, enum_args;
-{
- rb_ary_unshift(enum_args, obj);
-
- return rb_apply(rb_cEnumerator, id_new, enum_args);
-}
-
-/*
- * call-seq:
- * enum_with_index
- *
- * Returns Enumerable::Enumerator.new(self, :each_with_index).
- *
- */
-static VALUE
-enumerator_enum_with_index(obj)
- VALUE obj;
-{
- return rb_funcall(rb_cEnumerator, id_new, 2, obj, sym_each_with_index);
-}
-
-static VALUE
-each_slice_i(val, memo)
- VALUE val;
- NODE *memo;
-{
- VALUE ary = memo->u1.value;
- long size = memo->u3.cnt;
-
- rb_ary_push(ary, val);
-
- if (RARRAY(ary)->len == size) {
- rb_yield(ary);
- memo->u1.value = rb_ary_new2(size);
- }
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * e.each_slice(n) {...}
- *
- * Iterates the given block for each slice of <n> elements.
- *
- * e.g.:
- * (1..10).each_slice(3) {|a| p a}
- * # outputs below
- * [1, 2, 3]
- * [4, 5, 6]
- * [7, 8, 9]
- * [10]
- *
- */
-static VALUE
-enum_each_slice(obj, n)
- VALUE obj, n;
-{
- long size = NUM2LONG(n);
- NODE *memo;
- VALUE ary;
-
- if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
-
- memo = rb_node_newnode(NODE_MEMO, rb_ary_new2(size), 0, size);
-
- rb_iterate(rb_each, obj, each_slice_i, (VALUE)memo);
-
- ary = memo->u1.value;
- if (RARRAY(ary)->len > 0) rb_yield(ary);
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * e.enum_slice(n)
- *
- * Returns Enumerable::Enumerator.new(self, :each_slice, n).
- *
- */
-static VALUE
-enumerator_enum_slice(obj, n)
- VALUE obj, n;
-{
- return rb_funcall(rb_cEnumerator, id_new, 3, obj, sym_each_slice, n);
-}
-
-static VALUE
-each_cons_i(val, memo)
- VALUE val;
- NODE *memo;
-{
- VALUE ary = memo->u1.value;
- long size = memo->u3.cnt;
-
- if (RARRAY(ary)->len == size) {
- rb_ary_shift(ary);
- }
- rb_ary_push(ary, val);
- if (RARRAY(ary)->len == size) {
- rb_yield(rb_ary_dup(ary));
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * each_cons(n) {...}
- *
- * Iterates the given block for each array of consecutive <n>
- * elements.
- *
- * e.g.:
- * (1..10).each_cons(3) {|a| p a}
- * # outputs below
- * [1, 2, 3]
- * [2, 3, 4]
- * [3, 4, 5]
- * [4, 5, 6]
- * [5, 6, 7]
- * [6, 7, 8]
- * [7, 8, 9]
- * [8, 9, 10]
- *
- */
-static VALUE
-enum_each_cons(obj, n)
- VALUE obj, n;
-{
- long size = NUM2LONG(n);
- NODE *memo;
-
- if (size <= 0) rb_raise(rb_eArgError, "invalid size");
- memo = rb_node_newnode(NODE_MEMO, rb_ary_new2(size), 0, size);
-
- rb_iterate(rb_each, obj, each_cons_i, (VALUE)memo);
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * e.enum_cons(n)
- *
- * Returns Enumerable::Enumerator.new(self, :each_cons, n).
- *
- */
-static VALUE
-enumerator_enum_cons(obj, n)
- VALUE obj, n;
-{
- return rb_funcall(rb_cEnumerator, id_new, 3, obj, sym_each_cons, n);
-}
-
-/*
- * call-seq:
- * Enumerable::Enumerator.new(obj, method = :each, *args)
- *
- * Creates a new Enumerable::Enumerator object, which is to be
- * used as an Enumerable object using the given object's given
- * method with the given arguments.
- *
- * e.g.:
- * str = "xyz"
- *
- * enum = Enumerable::Enumerator.new(str, :each_byte)
- * a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
- *
- */
-static VALUE
-enumerator_initialize(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE enum_obj, enum_method, enum_args;
-
- rb_scan_args(argc, argv, "11*", &enum_obj, &enum_method, &enum_args);
-
- if (enum_method == Qnil)
- enum_method = sym_each;
-
- rb_ivar_set(obj, id_enum_obj, enum_obj);
- rb_ivar_set(obj, id_enum_method, enum_method);
- rb_ivar_set(obj, id_enum_args, enum_args);
-
- return Qnil;
-}
-
-static VALUE
-enumerator_iter(memo)
- NODE *memo;
-{
- return rb_apply(memo->u1.value, memo->u2.id, memo->u3.value);
-}
-
-/*
- * call-seq:
- * enum.each {...}
- *
- * Iterates the given block using the object and the method specified
- * in the first place.
- *
- */
-static VALUE
-enumerator_each(obj)
- VALUE obj;
-{
- VALUE val;
-
- obj = (VALUE)rb_node_newnode(NODE_MEMO,
- rb_ivar_get(obj, id_enum_obj),
- rb_to_id(rb_ivar_get(obj, id_enum_method)),
- rb_ivar_get(obj, id_enum_args));
- val = rb_iterate((VALUE (*)_((VALUE)))enumerator_iter, obj, rb_yield, 0);
- return val;
-}
-
-void
-Init_enumerator()
-{
- VALUE rb_mEnumerable;
-
- rb_define_method(rb_mKernel, "to_enum", obj_to_enum, -2);
- rb_define_method(rb_mKernel, "enum_for", obj_to_enum, -2);
-
- rb_mEnumerable = rb_path2class("Enumerable");
-
- rb_define_method(rb_mEnumerable, "enum_with_index", enumerator_enum_with_index, 0);
- rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
- rb_define_method(rb_mEnumerable, "enum_slice", enumerator_enum_slice, 1);
- rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
- rb_define_method(rb_mEnumerable, "enum_cons", enumerator_enum_cons, 1);
-
- rb_cEnumerator = rb_define_class_under(rb_mEnumerable, "Enumerator", rb_cObject);
- rb_include_module(rb_cEnumerator, rb_mEnumerable);
-
- rb_define_method(rb_cEnumerator, "initialize", enumerator_initialize, -1);
- rb_define_method(rb_cEnumerator, "each", enumerator_each, 0);
-
- sym_each = ID2SYM(rb_intern("each"));
- sym_each_with_index = ID2SYM(rb_intern("each_with_index"));
- sym_each_slice = ID2SYM(rb_intern("each_slice"));
- sym_each_cons = ID2SYM(rb_intern("each_cons"));
-
- id_new = rb_intern("new");
- id_enum_obj = rb_intern("enum_obj");
- id_enum_method = rb_intern("enum_method");
- id_enum_args = rb_intern("enum_args");
-}
diff --git a/ext/enumerator/enumerator.txt b/ext/enumerator/enumerator.txt
deleted file mode 100644
index 64c7d50226..0000000000
--- a/ext/enumerator/enumerator.txt
+++ /dev/null
@@ -1,102 +0,0 @@
-.\" enumerator.txt - -*- Indented-Text -*-
-$Idaemons: /home/cvs/rb/enumerator/enumerator.txt,v 1.2 2001/07/15 10:19:24 knu Exp $
-$RoughId: enumerator.txt,v 1.5 2003/02/20 12:24:51 knu Exp $
-$Id$
-
-** Enumerable::Enumerator(Class)
-
-A class which provides a method `each' to be used as an Enumerable
-object.
-
-Superclass: Object
-
-Mix-ins: Enumerable
-
-require 'enumerator'
-
-Class Methods:
-
- new(obj, method = :each, *args)
-
- Creates a new Enumerable::Enumerator object, which is to be
- used as an Enumerable object using the given object's given
- method with the given arguments.
-
- e.g.:
- str = "xyz"
-
- enum = Enumerable::Enumerator.new(str, :each_byte)
- a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
-
-Methods:
-
- each {...}
-
- Iterates the given block using the object and the method
- specified in the first place.
-
-
-Requiring this module also adds some methods to the Object class:
-
- to_enum(method = :each, *args)
- enum_for(method = :each, *args)
-
- Returns Enumerable::Enumerator.new(self, method, *args).
-
- e.g.:
- str = "xyz"
-
- enum = str.enum_for(:each_byte)
- a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
-
- # protects an array from being modified
- a = [1, 2, 3]
- some_method(a.to_enum)
-
-And the Enumerable module.
-
- each_slice(n) {...}
-
- Iterates the given block for each slice of <n> elements.
-
- e.g.:
- (1..10).each_slice(3) {|a| p a}
- # outputs below
- [1, 2, 3]
- [4, 5, 6]
- [7, 8, 9]
- [10]
-
- enum_slice(n)
-
- Returns Enumerable::Enumerator.new(self, :each_slice, n).
-
- each_cons(n) {...}
-
- Iterates the given block for each array of consecutive <n>
- elements.
-
- e.g.:
- (1..10).each_cons(3) {|a| p a}
- # outputs below
- [1, 2, 3]
- [2, 3, 4]
- [3, 4, 5]
- [4, 5, 6]
- [5, 6, 7]
- [6, 7, 8]
- [7, 8, 9]
- [8, 9, 10]
-
- enum_cons(n)
-
- Returns Enumerable::Enumerator.new(self, :each_cons, n).
-
- enum_with_index
-
- Returns Enumerable::Enumerator.new(self, :each_with_index).
-
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/ext/enumerator/extconf.rb b/ext/enumerator/extconf.rb
deleted file mode 100644
index 94e2ee38b2..0000000000
--- a/ext/enumerator/extconf.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require 'mkmf'
-create_makefile('enumerator')
diff --git a/ext/erb/escape/escape.c b/ext/erb/escape/escape.c
new file mode 100644
index 0000000000..1794fc30eb
--- /dev/null
+++ b/ext/erb/escape/escape.c
@@ -0,0 +1,114 @@
+#include "ruby.h"
+#include "ruby/encoding.h"
+
+static VALUE rb_cERB, rb_mEscape, rb_cCGI;
+static ID id_escapeHTML;
+
+#define HTML_ESCAPE_MAX_LEN 6
+
+static const struct {
+ uint8_t len;
+ char str[HTML_ESCAPE_MAX_LEN+1];
+} html_escape_table[UCHAR_MAX+1] = {
+#define HTML_ESCAPE(c, str) [c] = {rb_strlen_lit(str), str}
+ HTML_ESCAPE('\'', "&#39;"),
+ HTML_ESCAPE('&', "&amp;"),
+ HTML_ESCAPE('"', "&quot;"),
+ HTML_ESCAPE('<', "&lt;"),
+ HTML_ESCAPE('>', "&gt;"),
+#undef HTML_ESCAPE
+};
+
+static inline void
+preserve_original_state(VALUE orig, VALUE dest)
+{
+ rb_enc_associate(dest, rb_enc_get(orig));
+}
+
+static inline long
+escaped_length(VALUE str)
+{
+ const long len = RSTRING_LEN(str);
+ if (len >= LONG_MAX / HTML_ESCAPE_MAX_LEN) {
+ ruby_malloc_size_overflow(len, HTML_ESCAPE_MAX_LEN);
+ }
+ return len * HTML_ESCAPE_MAX_LEN;
+}
+
+static VALUE
+optimized_escape_html(VALUE str)
+{
+ VALUE vbuf;
+ char *buf = NULL;
+ const char *cstr = RSTRING_PTR(str);
+ const char *end = cstr + RSTRING_LEN(str);
+
+ const char *segment_start = cstr;
+ char *dest = NULL;
+ while (cstr < end) {
+ const unsigned char c = *cstr++;
+ uint8_t len = html_escape_table[c].len;
+ if (len) {
+ size_t segment_len = cstr - segment_start - 1;
+ if (!buf) {
+ buf = ALLOCV_N(char, vbuf, escaped_length(str));
+ dest = buf;
+ }
+ if (segment_len) {
+ memcpy(dest, segment_start, segment_len);
+ dest += segment_len;
+ }
+ segment_start = cstr;
+ memcpy(dest, html_escape_table[c].str, len);
+ dest += len;
+ }
+ }
+ VALUE escaped = str;
+ if (buf) {
+ size_t segment_len = cstr - segment_start;
+ if (segment_len) {
+ memcpy(dest, segment_start, segment_len);
+ dest += segment_len;
+ }
+ escaped = rb_str_new(buf, dest - buf);
+ preserve_original_state(str, escaped);
+ ALLOCV_END(vbuf);
+ }
+ return escaped;
+}
+
+/*
+ * ERB::Util.html_escape is similar to CGI.escapeHTML but different in the following two parts:
+ *
+ * * ERB::Util.html_escape converts an argument with #to_s first (only if it's not T_STRING)
+ * * ERB::Util.html_escape does not allocate a new string when nothing needs to be escaped
+ */
+static VALUE
+erb_escape_html(VALUE self, VALUE str)
+{
+ if (!RB_TYPE_P(str, T_STRING)) {
+ str = rb_convert_type(str, T_STRING, "String", "to_s");
+ }
+
+ if (rb_enc_str_asciicompat_p(str)) {
+ return optimized_escape_html(str);
+ }
+ else {
+ return rb_funcall(rb_cCGI, id_escapeHTML, 1, str);
+ }
+}
+
+void
+Init_escape(void)
+{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
+ rb_cERB = rb_define_class("ERB", rb_cObject);
+ rb_mEscape = rb_define_module_under(rb_cERB, "Escape");
+ rb_define_module_function(rb_mEscape, "html_escape", erb_escape_html, 1);
+
+ rb_cCGI = rb_define_class("CGI", rb_cObject);
+ id_escapeHTML = rb_intern("escapeHTML");
+}
diff --git a/ext/erb/escape/extconf.rb b/ext/erb/escape/extconf.rb
new file mode 100644
index 0000000000..b211a9783f
--- /dev/null
+++ b/ext/erb/escape/extconf.rb
@@ -0,0 +1,9 @@
+require 'mkmf'
+
+case RUBY_ENGINE
+when 'jruby', 'truffleruby'
+ File.write('Makefile', dummy_makefile($srcdir).join)
+else
+ have_func("rb_ext_ractor_safe", "ruby.h")
+ create_makefile 'erb/escape'
+end
diff --git a/ext/etc/.cvsignore b/ext/etc/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/etc/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/etc/.document b/ext/etc/.document
new file mode 100644
index 0000000000..9bbea23b92
--- /dev/null
+++ b/ext/etc/.document
@@ -0,0 +1,2 @@
+etc.c
+constdefs.h
diff --git a/ext/etc/depend b/ext/etc/depend
index ac706477b0..77fe56a6bf 100644
--- a/ext/etc/depend
+++ b/ext/etc/depend
@@ -1 +1,182 @@
-etc.o : etc.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
+constdefs.h : $(srcdir)/mkconstants.rb
+ @echo "generating constant definitions"
+ @$(RUBY) $(srcdir)/mkconstants.rb -o constdefs.h
+
+# AUTOGENERATED DEPENDENCIES START
+etc.o: $(RUBY_EXTCONF_H)
+etc.o: $(arch_hdrdir)/ruby/config.h
+etc.o: $(hdrdir)/ruby.h
+etc.o: $(hdrdir)/ruby/assert.h
+etc.o: $(hdrdir)/ruby/atomic.h
+etc.o: $(hdrdir)/ruby/backward.h
+etc.o: $(hdrdir)/ruby/backward/2/assume.h
+etc.o: $(hdrdir)/ruby/backward/2/attributes.h
+etc.o: $(hdrdir)/ruby/backward/2/bool.h
+etc.o: $(hdrdir)/ruby/backward/2/inttypes.h
+etc.o: $(hdrdir)/ruby/backward/2/limits.h
+etc.o: $(hdrdir)/ruby/backward/2/long_long.h
+etc.o: $(hdrdir)/ruby/backward/2/stdalign.h
+etc.o: $(hdrdir)/ruby/backward/2/stdarg.h
+etc.o: $(hdrdir)/ruby/defines.h
+etc.o: $(hdrdir)/ruby/encoding.h
+etc.o: $(hdrdir)/ruby/intern.h
+etc.o: $(hdrdir)/ruby/internal/abi.h
+etc.o: $(hdrdir)/ruby/internal/anyargs.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+etc.o: $(hdrdir)/ruby/internal/assume.h
+etc.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+etc.o: $(hdrdir)/ruby/internal/attr/artificial.h
+etc.o: $(hdrdir)/ruby/internal/attr/cold.h
+etc.o: $(hdrdir)/ruby/internal/attr/const.h
+etc.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+etc.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+etc.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+etc.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+etc.o: $(hdrdir)/ruby/internal/attr/error.h
+etc.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+etc.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+etc.o: $(hdrdir)/ruby/internal/attr/format.h
+etc.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+etc.o: $(hdrdir)/ruby/internal/attr/noalias.h
+etc.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+etc.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+etc.o: $(hdrdir)/ruby/internal/attr/noinline.h
+etc.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+etc.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+etc.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+etc.o: $(hdrdir)/ruby/internal/attr/pure.h
+etc.o: $(hdrdir)/ruby/internal/attr/restrict.h
+etc.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+etc.o: $(hdrdir)/ruby/internal/attr/warning.h
+etc.o: $(hdrdir)/ruby/internal/attr/weakref.h
+etc.o: $(hdrdir)/ruby/internal/cast.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+etc.o: $(hdrdir)/ruby/internal/compiler_since.h
+etc.o: $(hdrdir)/ruby/internal/config.h
+etc.o: $(hdrdir)/ruby/internal/constant_p.h
+etc.o: $(hdrdir)/ruby/internal/core.h
+etc.o: $(hdrdir)/ruby/internal/core/rarray.h
+etc.o: $(hdrdir)/ruby/internal/core/rbasic.h
+etc.o: $(hdrdir)/ruby/internal/core/rbignum.h
+etc.o: $(hdrdir)/ruby/internal/core/rclass.h
+etc.o: $(hdrdir)/ruby/internal/core/rdata.h
+etc.o: $(hdrdir)/ruby/internal/core/rfile.h
+etc.o: $(hdrdir)/ruby/internal/core/rhash.h
+etc.o: $(hdrdir)/ruby/internal/core/robject.h
+etc.o: $(hdrdir)/ruby/internal/core/rregexp.h
+etc.o: $(hdrdir)/ruby/internal/core/rstring.h
+etc.o: $(hdrdir)/ruby/internal/core/rstruct.h
+etc.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+etc.o: $(hdrdir)/ruby/internal/ctype.h
+etc.o: $(hdrdir)/ruby/internal/dllexport.h
+etc.o: $(hdrdir)/ruby/internal/dosish.h
+etc.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+etc.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+etc.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+etc.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+etc.o: $(hdrdir)/ruby/internal/encoding/re.h
+etc.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+etc.o: $(hdrdir)/ruby/internal/encoding/string.h
+etc.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+etc.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+etc.o: $(hdrdir)/ruby/internal/error.h
+etc.o: $(hdrdir)/ruby/internal/eval.h
+etc.o: $(hdrdir)/ruby/internal/event.h
+etc.o: $(hdrdir)/ruby/internal/fl_type.h
+etc.o: $(hdrdir)/ruby/internal/gc.h
+etc.o: $(hdrdir)/ruby/internal/glob.h
+etc.o: $(hdrdir)/ruby/internal/globals.h
+etc.o: $(hdrdir)/ruby/internal/has/attribute.h
+etc.o: $(hdrdir)/ruby/internal/has/builtin.h
+etc.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+etc.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+etc.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+etc.o: $(hdrdir)/ruby/internal/has/extension.h
+etc.o: $(hdrdir)/ruby/internal/has/feature.h
+etc.o: $(hdrdir)/ruby/internal/has/warning.h
+etc.o: $(hdrdir)/ruby/internal/intern/array.h
+etc.o: $(hdrdir)/ruby/internal/intern/bignum.h
+etc.o: $(hdrdir)/ruby/internal/intern/class.h
+etc.o: $(hdrdir)/ruby/internal/intern/compar.h
+etc.o: $(hdrdir)/ruby/internal/intern/complex.h
+etc.o: $(hdrdir)/ruby/internal/intern/cont.h
+etc.o: $(hdrdir)/ruby/internal/intern/dir.h
+etc.o: $(hdrdir)/ruby/internal/intern/enum.h
+etc.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+etc.o: $(hdrdir)/ruby/internal/intern/error.h
+etc.o: $(hdrdir)/ruby/internal/intern/eval.h
+etc.o: $(hdrdir)/ruby/internal/intern/file.h
+etc.o: $(hdrdir)/ruby/internal/intern/hash.h
+etc.o: $(hdrdir)/ruby/internal/intern/io.h
+etc.o: $(hdrdir)/ruby/internal/intern/load.h
+etc.o: $(hdrdir)/ruby/internal/intern/marshal.h
+etc.o: $(hdrdir)/ruby/internal/intern/numeric.h
+etc.o: $(hdrdir)/ruby/internal/intern/object.h
+etc.o: $(hdrdir)/ruby/internal/intern/parse.h
+etc.o: $(hdrdir)/ruby/internal/intern/proc.h
+etc.o: $(hdrdir)/ruby/internal/intern/process.h
+etc.o: $(hdrdir)/ruby/internal/intern/random.h
+etc.o: $(hdrdir)/ruby/internal/intern/range.h
+etc.o: $(hdrdir)/ruby/internal/intern/rational.h
+etc.o: $(hdrdir)/ruby/internal/intern/re.h
+etc.o: $(hdrdir)/ruby/internal/intern/ruby.h
+etc.o: $(hdrdir)/ruby/internal/intern/select.h
+etc.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+etc.o: $(hdrdir)/ruby/internal/intern/set.h
+etc.o: $(hdrdir)/ruby/internal/intern/signal.h
+etc.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+etc.o: $(hdrdir)/ruby/internal/intern/string.h
+etc.o: $(hdrdir)/ruby/internal/intern/struct.h
+etc.o: $(hdrdir)/ruby/internal/intern/thread.h
+etc.o: $(hdrdir)/ruby/internal/intern/time.h
+etc.o: $(hdrdir)/ruby/internal/intern/variable.h
+etc.o: $(hdrdir)/ruby/internal/intern/vm.h
+etc.o: $(hdrdir)/ruby/internal/interpreter.h
+etc.o: $(hdrdir)/ruby/internal/iterator.h
+etc.o: $(hdrdir)/ruby/internal/memory.h
+etc.o: $(hdrdir)/ruby/internal/method.h
+etc.o: $(hdrdir)/ruby/internal/module.h
+etc.o: $(hdrdir)/ruby/internal/newobj.h
+etc.o: $(hdrdir)/ruby/internal/scan_args.h
+etc.o: $(hdrdir)/ruby/internal/special_consts.h
+etc.o: $(hdrdir)/ruby/internal/static_assert.h
+etc.o: $(hdrdir)/ruby/internal/stdalign.h
+etc.o: $(hdrdir)/ruby/internal/stdbool.h
+etc.o: $(hdrdir)/ruby/internal/stdckdint.h
+etc.o: $(hdrdir)/ruby/internal/symbol.h
+etc.o: $(hdrdir)/ruby/internal/value.h
+etc.o: $(hdrdir)/ruby/internal/value_type.h
+etc.o: $(hdrdir)/ruby/internal/variable.h
+etc.o: $(hdrdir)/ruby/internal/warning_push.h
+etc.o: $(hdrdir)/ruby/internal/xmalloc.h
+etc.o: $(hdrdir)/ruby/io.h
+etc.o: $(hdrdir)/ruby/missing.h
+etc.o: $(hdrdir)/ruby/onigmo.h
+etc.o: $(hdrdir)/ruby/oniguruma.h
+etc.o: $(hdrdir)/ruby/ruby.h
+etc.o: $(hdrdir)/ruby/st.h
+etc.o: $(hdrdir)/ruby/subst.h
+etc.o: constdefs.h
+etc.o: etc.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index c79640d02a..8d50a96a62 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -3,12 +3,13 @@
etc.c -
$Author$
- $Date$
created at: Tue Mar 22 18:39:19 JST 1994
************************************************/
#include "ruby.h"
+#include "ruby/encoding.h"
+#include "ruby/io.h"
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
@@ -23,29 +24,98 @@
#include <grp.h>
#endif
-#ifndef HAVE_TYPE_UID_T
-#define uid_t int
+#include <errno.h>
+
+#ifdef HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+
+#ifdef HAVE_SCHED_GETAFFINITY
+#include <sched.h>
+#endif
+
+static VALUE sPasswd;
+#ifdef HAVE_GETGRENT
+static VALUE sGroup;
#endif
-static VALUE sPasswd, sGroup;
+#ifdef _WIN32
+#include <shlobj.h>
+#ifndef CSIDL_COMMON_APPDATA
+#define CSIDL_COMMON_APPDATA 35
+#endif
+#define HAVE_UNAME 1
+#endif
-#ifndef _WIN32
-char *getenv();
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+RUBY_EXTERN char *getlogin(void);
+
+#define RUBY_ETC_VERSION "1.4.6"
+
+#define SYMBOL_LIT(str) ID2SYM(rb_intern_const(str ""))
+
+#ifdef HAVE_RB_DEPRECATE_CONSTANT
+void rb_deprecate_constant(VALUE mod, const char *name);
+#else
+# define rb_deprecate_constant(mod,name) ((void)(mod),(void)(name))
+#endif
+
+#include "constdefs.h"
+
+#ifndef HAVE_RB_IO_DESCRIPTOR
+static int
+io_descriptor_fallback(VALUE io)
+{
+ rb_io_t *fptr;
+ GetOpenFile(io, fptr);
+ return fptr->fd;
+}
+#define rb_io_descriptor io_descriptor_fallback
#endif
-char *getlogin();
-/* Returns the short user name of the currently logged in user.
+#ifdef HAVE_RUBY_ATOMIC_H
+# include "ruby/atomic.h"
+#else
+typedef int rb_atomic_t;
+# define RUBY_ATOMIC_CAS(var, oldval, newval) \
+ ((var) == (oldval) ? ((var) = (newval), (oldval)) : (var))
+# define RUBY_ATOMIC_EXCHANGE(var, newval) \
+ atomic_exchange(&var, newval)
+static inline rb_atomic_t
+atomic_exchange(volatile rb_atomic_t *var, rb_atomic_t newval)
+{
+ rb_atomic_t oldval = *var;
+ *var = newval;
+ return oldval;
+}
+#endif
+
+/* call-seq:
+ * getlogin -> String
+ *
+ * Returns the short user name of the currently logged in user.
+ * Unfortunately, it is often rather easy to fool ::getlogin.
+ *
+ * Avoid ::getlogin for security-related purposes.
+ *
+ * If ::getlogin fails, try ::getpwuid.
+ *
+ * See the unix manpage for <code>getpwuid(3)</code> for more detail.
*
* e.g.
* Etc.getlogin -> 'guest'
*/
static VALUE
-etc_getlogin(obj)
- VALUE obj;
+etc_getlogin(VALUE obj)
{
char *login;
- rb_secure(4);
#ifdef HAVE_GETLOGIN
login = getlogin();
if (!login) login = getenv("USER");
@@ -53,151 +123,203 @@ etc_getlogin(obj)
login = getenv("USER");
#endif
- if (login)
- return rb_tainted_str_new2(login);
+ if (login) {
+#ifdef _WIN32
+ rb_encoding *extenc = rb_utf8_encoding();
+#else
+ rb_encoding *extenc = rb_locale_encoding();
+#endif
+ return rb_external_str_new_with_enc(login, strlen(login), extenc);
+ }
+
return Qnil;
}
#if defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
static VALUE
-safe_setup_str(str)
- const char *str;
+safe_setup_str(const char *str)
+{
+ if (str == 0) str = "";
+ return rb_str_new2(str);
+}
+
+static VALUE
+safe_setup_locale_str(const char *str)
{
if (str == 0) str = "";
- return rb_tainted_str_new2(str);
+ return rb_locale_str_new_cstr(str);
+}
+
+static VALUE
+safe_setup_filesystem_str(const char *str)
+{
+ if (str == 0) str = "";
+ return rb_filesystem_str_new_cstr(str);
}
#endif
#ifdef HAVE_GETPWENT
+# ifdef __APPLE__
+# define PW_TIME2VAL(t) INT2NUM((int)(t))
+# else
+# define PW_TIME2VAL(t) TIMET2NUM(t)
+# endif
+
static VALUE
-setup_passwd(pwd)
- struct passwd *pwd;
+setup_passwd(struct passwd *pwd)
{
if (pwd == 0) rb_sys_fail("/etc/passwd");
return rb_struct_new(sPasswd,
- safe_setup_str(pwd->pw_name),
-#ifdef HAVE_ST_PW_PASSWD
+ safe_setup_locale_str(pwd->pw_name),
+#ifdef HAVE_STRUCT_PASSWD_PW_PASSWD
safe_setup_str(pwd->pw_passwd),
#endif
- PW_UID2VAL(pwd->pw_uid),
- PW_GID2VAL(pwd->pw_gid),
-#ifdef HAVE_ST_PW_GECOS
- safe_setup_str(pwd->pw_gecos),
+ UIDT2NUM(pwd->pw_uid),
+ GIDT2NUM(pwd->pw_gid),
+#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
+ safe_setup_locale_str(pwd->pw_gecos),
#endif
- safe_setup_str(pwd->pw_dir),
- safe_setup_str(pwd->pw_shell),
-#ifdef HAVE_ST_PW_CHANGE
- INT2NUM(pwd->pw_change),
+ safe_setup_filesystem_str(pwd->pw_dir),
+ safe_setup_filesystem_str(pwd->pw_shell),
+#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
+ PW_TIME2VAL(pwd->pw_change),
#endif
-#ifdef HAVE_ST_PW_QUOTA
+#ifdef HAVE_STRUCT_PASSWD_PW_QUOTA
INT2NUM(pwd->pw_quota),
#endif
-#ifdef HAVE_ST_PW_AGE
+#ifdef HAVE_STRUCT_PASSWD_PW_AGE
PW_AGE2VAL(pwd->pw_age),
#endif
-#ifdef HAVE_ST_PW_CLASS
- safe_setup_str(pwd->pw_class),
+#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
+ safe_setup_locale_str(pwd->pw_class),
#endif
-#ifdef HAVE_ST_PW_COMMENT
- safe_setup_str(pwd->pw_comment),
+#ifdef HAVE_STRUCT_PASSWD_PW_COMMENT
+ safe_setup_locale_str(pwd->pw_comment),
#endif
-#ifdef HAVE_ST_PW_EXPIRE
- INT2NUM(pwd->pw_expire),
+#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
+ PW_TIME2VAL(pwd->pw_expire),
#endif
0 /*dummy*/
);
}
#endif
-/* Returns the /etc/passwd information for the user with specified integer
- * user id (uid).
+/* call-seq:
+ * getpwuid(uid) -> Etc::Passwd
+ *
+ * Returns the <tt>/etc/passwd</tt> information for the user with the given
+ * integer +uid+.
+ *
+ * The information is returned as a Passwd struct.
*
- * The information is returned as a Struct::Passwd; see getpwent above for
- * details.
+ * If +uid+ is omitted, the value from <code>Passwd[:uid]</code> is returned
+ * instead.
*
- * e.g. * Etc.getpwuid(0) -> #<struct Struct::Passwd name="root",
- * passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
+ * See the unix manpage for <code>getpwuid(3)</code> for more detail.
+ *
+ * *Example:*
+ *
+ * Etc.getpwuid(0)
+ * #=> #<struct Etc::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
*/
static VALUE
-etc_getpwuid(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
+etc_getpwuid(int argc, VALUE *argv, VALUE obj)
{
#if defined(HAVE_GETPWENT)
VALUE id;
- int uid;
+ rb_uid_t uid;
struct passwd *pwd;
- rb_secure(4);
if (rb_scan_args(argc, argv, "01", &id) == 1) {
- uid = NUM2INT(id);
+ uid = NUM2UIDT(id);
}
else {
uid = getuid();
}
pwd = getpwuid(uid);
- if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %d", uid);
+ if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %d", (int)uid);
return setup_passwd(pwd);
-#else
+#else
return Qnil;
#endif
}
-/* Returns the /etc/passwd information for the user with specified login name.
+/* call-seq:
+ * getpwnam(name) -> Etc::Passwd
+ *
+ * Returns the <tt>/etc/passwd</tt> information for the user with specified
+ * login +name+.
+ *
+ * The information is returned as a Passwd struct.
*
- * The information is returned as a Struct::Passwd; see getpwent above for
- * details.
+ * See the unix manpage for <code>getpwnam(3)</code> for more detail.
*
- * e.g. * Etc.getpwnam('root') -> #<struct Struct::Passwd name="root",
- * passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
+ * *Example:*
+ *
+ * Etc.getpwnam('root')
+ * #=> #<struct Etc::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
*/
static VALUE
-etc_getpwnam(obj, nam)
- VALUE obj, nam;
+etc_getpwnam(VALUE obj, VALUE nam)
{
#ifdef HAVE_GETPWENT
struct passwd *pwd;
+ const char *p = StringValueCStr(nam);
- SafeStringValue(nam);
- pwd = getpwnam(RSTRING(nam)->ptr);
- if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %s", RSTRING(nam)->ptr);
+ pwd = getpwnam(p);
+ if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %"PRIsVALUE, nam);
return setup_passwd(pwd);
-#else
+#else
return Qnil;
#endif
}
#ifdef HAVE_GETPWENT
-static int passwd_blocking = 0;
+static rb_atomic_t passwd_blocking;
static VALUE
-passwd_ensure()
+passwd_ensure(VALUE _)
{
- passwd_blocking = Qfalse;
+ endpwent();
+ if (RUBY_ATOMIC_EXCHANGE(passwd_blocking, 0) != 1) {
+ rb_raise(rb_eRuntimeError, "unexpected passwd_blocking");
+ }
return Qnil;
}
static VALUE
-passwd_iterate()
+passwd_iterate(VALUE _)
{
struct passwd *pw;
setpwent();
- while (pw = getpwent()) {
+ while ((pw = getpwent()) != 0) {
rb_yield(setup_passwd(pw));
}
- endpwent();
return Qnil;
}
+
+static void
+each_passwd(void)
+{
+ if (RUBY_ATOMIC_CAS(passwd_blocking, 0, 1)) {
+ rb_raise(rb_eRuntimeError, "parallel passwd iteration");
+ }
+ rb_ensure(passwd_iterate, 0, passwd_ensure, 0);
+}
#endif
-/* Provides a convenient Ruby iterator which executes a block for each entry
- * in the /etc/passwd file.
+/* call-seq:
+ * passwd { |struct| block }
+ * passwd -> Etc::Passwd
*
- * The code block is passed an Etc::Passwd struct; see getpwent above for
- * details.
+ * Provides a convenient Ruby iterator which executes a block for each entry
+ * in the <tt>/etc/passwd</tt> file.
*
- * Example:
+ * The code block is passed an Passwd struct.
+ *
+ * See ::getpwent above for details.
+ *
+ * *Example:*
*
* require 'etc'
*
@@ -207,33 +329,64 @@ passwd_iterate()
*
*/
static VALUE
-etc_passwd(obj)
- VALUE obj;
+etc_passwd(VALUE obj)
{
#ifdef HAVE_GETPWENT
struct passwd *pw;
- rb_secure(4);
if (rb_block_given_p()) {
- if (passwd_blocking) {
- rb_raise(rb_eRuntimeError, "parallel passwd iteration");
- }
- passwd_blocking = Qtrue;
- rb_ensure(passwd_iterate, 0, passwd_ensure, 0);
+ each_passwd();
}
- if (pw = getpwent()) {
+ else if ((pw = getpwent()) != 0) {
return setup_passwd(pw);
}
#endif
return Qnil;
}
-/* Resets the process of reading the /etc/passwd file, so that the next call
- * to getpwent will return the first entry again.
+/* call-seq:
+ * Etc::Passwd.each { |struct| block } -> Etc::Passwd
+ * Etc::Passwd.each -> Enumerator
+ *
+ * Iterates for each entry in the <tt>/etc/passwd</tt> file if a block is
+ * given.
+ *
+ * If no block is given, returns the Enumerator.
+ *
+ * The code block is passed an Passwd struct.
+ *
+ * See Etc.getpwent above for details.
+ *
+ * *Example:*
+ *
+ * require 'etc'
+ *
+ * Etc::Passwd.each {|u|
+ * puts u.name + " = " + u.gecos
+ * }
+ *
+ * Etc::Passwd.collect {|u| u.gecos}
+ * Etc::Passwd.collect {|u| u.gecos}
+ *
+ */
+static VALUE
+etc_each_passwd(VALUE obj)
+{
+#ifdef HAVE_GETPWENT
+ RETURN_ENUMERATOR(obj, 0, 0);
+ each_passwd();
+#endif
+ return obj;
+}
+
+/* call-seq:
+ * setpwent
+ *
+ * Resets the process of reading the <tt>/etc/passwd</tt> file, so that the
+ * next call to ::getpwent will return the first entry again.
*/
static VALUE
-etc_setpwent(obj)
- VALUE obj;
+etc_setpwent(VALUE obj)
{
#ifdef HAVE_GETPWENT
setpwent();
@@ -241,12 +394,14 @@ etc_setpwent(obj)
return Qnil;
}
-/* Ends the process of scanning through the /etc/passwd file begun with
- * getpwent, and closes the file.
+/* call-seq:
+ * endpwent
+ *
+ * Ends the process of scanning through the <tt>/etc/passwd</tt> file begun
+ * with ::getpwent, and closes the file.
*/
static VALUE
-etc_endpwent(obj)
- VALUE obj;
+etc_endpwent(VALUE obj)
{
#ifdef HAVE_GETPWENT
endpwent();
@@ -254,40 +409,27 @@ etc_endpwent(obj)
return Qnil;
}
-/* Returns an entry from the /etc/passwd file. The first time it is called it
- * opens the file and returns the first entry; each successive call returns
- * the next entry, or nil if the end of the file has been reached.
- *
- * To close the file when processing is complete, call endpwent.
- *
- * Each entry is returned as a Struct::Passwd:
- *
- * - Passwd#name contains the short login name of the user as a String.
+/* call-seq:
+ * getpwent -> Etc::Passwd
*
- * - Passwd#passwd contains the encrypted password of the user as a String.
- * an 'x' is returned if shadow passwords are in use. An '*' is returned
- * if the user cannot log in using a password.
+ * Returns an entry from the <tt>/etc/passwd</tt> file.
*
- * - Passwd#uid contains the integer user ID (uid) of the user.
+ * The first time it is called it opens the file and returns the first entry;
+ * each successive call returns the next entry, or +nil+ if the end of the file
+ * has been reached.
*
- * - Passwd#gid contains the integer group ID (gid) of the user's primary group.
+ * To close the file when processing is complete, call ::endpwent.
*
- * - Passwd#gecos contains a longer String description of the user, such as
- * a full name. Some Unix systems provide structured information in the
- * gecos field, but this is system-dependent.
+ * Each entry is returned as a Passwd struct.
*
- * - Passwd#dir contains the path to the home directory of the user as a String.
- *
- * - Passwd#shell contains the path to the login shell of the user as a String.
*/
static VALUE
-etc_getpwent(obj)
- VALUE obj;
+etc_getpwent(VALUE obj)
{
#ifdef HAVE_GETPWENT
struct passwd *pw;
- if (pw = getpwent()) {
+ if ((pw = getpwent()) != 0) {
return setup_passwd(pw);
}
#endif
@@ -296,8 +438,7 @@ etc_getpwent(obj)
#ifdef HAVE_GETGRENT
static VALUE
-setup_group(grp)
- struct group *grp;
+setup_group(struct group *grp)
{
VALUE mem;
char **tbl;
@@ -305,68 +446,82 @@ setup_group(grp)
mem = rb_ary_new();
tbl = grp->gr_mem;
while (*tbl) {
- rb_ary_push(mem, safe_setup_str(*tbl));
+ rb_ary_push(mem, safe_setup_locale_str(*tbl));
tbl++;
}
return rb_struct_new(sGroup,
- safe_setup_str(grp->gr_name),
-#ifdef HAVE_ST_GR_PASSWD
+ safe_setup_locale_str(grp->gr_name),
+#ifdef HAVE_STRUCT_GROUP_GR_PASSWD
safe_setup_str(grp->gr_passwd),
#endif
- PW_GID2VAL(grp->gr_gid),
+ GIDT2NUM(grp->gr_gid),
mem);
}
#endif
-/* Returns information about the group with specified integer group id (gid),
- * as found in /etc/group.
+/* call-seq:
+ * getgrgid(group_id) -> Etc::Group
+ *
+ * Returns information about the group with specified integer +group_id+,
+ * as found in <tt>/etc/group</tt>.
+ *
+ * The information is returned as a Group struct.
*
- * The information is returned as a Struct::Group; see getgrent above for
- * details.
+ * See the unix manpage for <code>getgrgid(3)</code> for more detail.
*
- * e.g. Etc.getgrgid(100) -> #<struct Struct::Group name="users", passwd="x",
- * gid=100, mem=["meta", "root"]>
+ * *Example:*
+ *
+ * Etc.getgrgid(100)
+ * #=> #<struct Etc::Group name="users", passwd="x", gid=100, mem=["meta", "root"]>
*
*/
static VALUE
-etc_getgrgid(obj, id)
- VALUE obj, id;
+etc_getgrgid(int argc, VALUE *argv, VALUE obj)
{
#ifdef HAVE_GETGRENT
- int gid;
+ VALUE id;
+ gid_t gid;
struct group *grp;
- rb_secure(4);
- gid = NUM2INT(id);
+ if (rb_scan_args(argc, argv, "01", &id) == 1) {
+ gid = NUM2GIDT(id);
+ }
+ else {
+ gid = getgid();
+ }
grp = getgrgid(gid);
- if (grp == 0) rb_raise(rb_eArgError, "can't find group for %d", gid);
+ if (grp == 0) rb_raise(rb_eArgError, "can't find group for %d", (int)gid);
return setup_group(grp);
#else
return Qnil;
#endif
}
-/* Returns information about the group with specified String name, as found
- * in /etc/group.
+/* call-seq:
+ * getgrnam(name) -> Etc::Group
+ *
+ * Returns information about the group with specified +name+, as found in
+ * <tt>/etc/group</tt>.
+ *
+ * The information is returned as a Group struct.
+ *
+ * See the unix manpage for <code>getgrnam(3)</code> for more detail.
*
- * The information is returned as a Struct::Group; see getgrent above for
- * details.
+ * *Example:*
*
- * e.g. Etc.getgrnam('users') -> #<struct Struct::Group name="users",
- * passwd="x", gid=100, mem=["meta", "root"]>
+ * Etc.getgrnam('users')
+ * #=> #<struct Etc::Group name="users", passwd="x", gid=100, mem=["meta", "root"]>
*
*/
static VALUE
-etc_getgrnam(obj, nam)
- VALUE obj, nam;
+etc_getgrnam(VALUE obj, VALUE nam)
{
#ifdef HAVE_GETGRENT
struct group *grp;
+ const char *p = StringValueCStr(nam);
- rb_secure(4);
- SafeStringValue(nam);
- grp = getgrnam(RSTRING(nam)->ptr);
- if (grp == 0) rb_raise(rb_eArgError, "can't find group for %s", RSTRING(nam)->ptr);
+ grp = getgrnam(p);
+ if (grp == 0) rb_raise(rb_eArgError, "can't find group for %"PRIsVALUE, nam);
return setup_group(grp);
#else
return Qnil;
@@ -374,35 +529,51 @@ etc_getgrnam(obj, nam)
}
#ifdef HAVE_GETGRENT
-static int group_blocking = 0;
+static rb_atomic_t group_blocking;
static VALUE
-group_ensure()
+group_ensure(VALUE _)
{
- group_blocking = Qfalse;
+ endgrent();
+ if (RUBY_ATOMIC_EXCHANGE(group_blocking, 0) != 1) {
+ rb_raise(rb_eRuntimeError, "unexpected group_blocking");
+ }
return Qnil;
}
static VALUE
-group_iterate()
+group_iterate(VALUE _)
{
struct group *pw;
setgrent();
- while (pw = getgrent()) {
+ while ((pw = getgrent()) != 0) {
rb_yield(setup_group(pw));
}
- endgrent();
return Qnil;
}
+
+static void
+each_group(void)
+{
+ if (RUBY_ATOMIC_CAS(group_blocking, 0, 1)) {
+ rb_raise(rb_eRuntimeError, "parallel group iteration");
+ }
+ rb_ensure(group_iterate, 0, group_ensure, 0);
+}
#endif
-/* Provides a convenient Ruby iterator which executes a block for each entry
- * in the /etc/group file.
+/* call-seq:
+ * group { |struct| block }
+ * group -> Etc::Group
+ *
+ * Provides a convenient Ruby iterator which executes a block for each entry
+ * in the <tt>/etc/group</tt> file.
+ *
+ * The code block is passed an Group struct.
*
- * The code block is passed an Etc::Group struct; see getgrent above for
- * details.
+ * See ::getgrent above for details.
*
- * Example:
+ * *Example:*
*
* require 'etc'
*
@@ -412,33 +583,62 @@ group_iterate()
*
*/
static VALUE
-etc_group(obj)
- VALUE obj;
+etc_group(VALUE obj)
{
#ifdef HAVE_GETGRENT
struct group *grp;
- rb_secure(4);
if (rb_block_given_p()) {
- if (group_blocking) {
- rb_raise(rb_eRuntimeError, "parallel group iteration");
- }
- group_blocking = Qtrue;
- rb_ensure(group_iterate, 0, group_ensure, 0);
+ each_group();
}
- if (grp = getgrent()) {
+ else if ((grp = getgrent()) != 0) {
return setup_group(grp);
}
#endif
return Qnil;
}
-/* Resets the process of reading the /etc/group file, so that the next call
- * to getgrent will return the first entry again.
+#ifdef HAVE_GETGRENT
+/* call-seq:
+ * Etc::Group.each { |group| block } -> Etc::Group
+ * Etc::Group.each -> Enumerator
+ *
+ * Iterates for each entry in the <tt>/etc/group</tt> file if a block is
+ * given.
+ *
+ * If no block is given, returns the Enumerator.
+ *
+ * The code block is passed a Group struct.
+ *
+ * *Example:*
+ *
+ * require 'etc'
+ *
+ * Etc::Group.each {|g|
+ * puts g.name + ": " + g.mem.join(', ')
+ * }
+ *
+ * Etc::Group.collect {|g| g.name}
+ * Etc::Group.select {|g| !g.mem.empty?}
+ *
+ */
+static VALUE
+etc_each_group(VALUE obj)
+{
+ RETURN_ENUMERATOR(obj, 0, 0);
+ each_group();
+ return obj;
+}
+#endif
+
+/* call-seq:
+ * setgrent
+ *
+ * Resets the process of reading the <tt>/etc/group</tt> file, so that the
+ * next call to ::getgrent will return the first entry again.
*/
static VALUE
-etc_setgrent(obj)
- VALUE obj;
+etc_setgrent(VALUE obj)
{
#ifdef HAVE_GETGRENT
setgrent();
@@ -446,12 +646,14 @@ etc_setgrent(obj)
return Qnil;
}
-/* Ends the process of scanning through the /etc/group file begun by
- * getgrent, and closes the file.
+/* call-seq:
+ * endgrent
+ *
+ * Ends the process of scanning through the <tt>/etc/group</tt> file begun
+ * by ::getgrent, and closes the file.
*/
static VALUE
-etc_endgrent(obj)
- VALUE obj;
+etc_endgrent(VALUE obj)
{
#ifdef HAVE_GETGRENT
endgrent();
@@ -459,52 +661,524 @@ etc_endgrent(obj)
return Qnil;
}
-/* Returns an entry from the /etc/group file. The first time it is called it
- * opens the file and returns the first entry; each successive call returns
- * the next entry, or nil if the end of the file has been reached.
- *
- * To close the file when processing is complete, call endgrent.
- *
- * Each entry is returned as a Struct::Group:
+/* call-seq:
+ * getgrent -> Etc::Group
*
- * - Group#name contains the name of the group as a String.
+ * Returns an entry from the <tt>/etc/group</tt> file.
*
- * - Group#passwd contains the encrypted password as a String. An 'x' is
- * returned if password access to the group is not available; an empty
- * string is returned if no password is needed to obtain membership of
- * the group.
+ * The first time it is called it opens the file and returns the first entry;
+ * each successive call returns the next entry, or +nil+ if the end of the file
+ * has been reached.
*
- * - Group#gid contains the group's numeric ID as an integer.
+ * To close the file when processing is complete, call ::endgrent.
*
- * - Group#mem is an Array of Strings containing the short login names of the
- * members of the group.
+ * Each entry is returned as a Group struct
*/
static VALUE
-etc_getgrent(obj)
- VALUE obj;
+etc_getgrent(VALUE obj)
{
#ifdef HAVE_GETGRENT
struct group *gr;
- if (gr = getgrent()) {
+ if ((gr = getgrent()) != 0) {
return setup_group(gr);
}
#endif
return Qnil;
}
-static VALUE mEtc;
+#define numberof(array) (sizeof(array) / sizeof(*(array)))
+
+#ifdef _WIN32
+VALUE rb_w32_special_folder(int type);
+UINT rb_w32_system_tmpdir(WCHAR *path, UINT len);
+VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
+#elif defined(LOAD_RELATIVE)
+static inline VALUE
+rbconfig(void)
+{
+ VALUE config;
+ rb_require("rbconfig");
+ config = rb_const_get(rb_path2class("RbConfig"), rb_intern_const("CONFIG"));
+ Check_Type(config, T_HASH);
+ return config;
+}
+#endif
-/* The etc module provides access to information from the /etc/passwd and
- * /etc/group files on Linux and Unix systems.
+/* call-seq:
+ * sysconfdir -> String
*
- * Documented by mathew <meta@pobox.com>.
+ * Returns system configuration directory.
+ *
+ * This is typically <code>"/etc"</code>, but is modified by the prefix used
+ * when Ruby was compiled. For example, if Ruby is built and installed in
+ * <tt>/usr/local</tt>, returns <code>"/usr/local/etc"</code> on other
+ * platforms than Windows.
+ *
+ * On Windows, this always returns the directory provided by the system.
+ */
+static VALUE
+etc_sysconfdir(VALUE obj)
+{
+#ifdef _WIN32
+ return rb_w32_special_folder(CSIDL_COMMON_APPDATA);
+#elif defined(LOAD_RELATIVE)
+ return rb_hash_aref(rbconfig(), rb_str_new_lit("sysconfdir"));
+#else
+ return rb_filesystem_str_new_cstr(SYSCONFDIR);
+#endif
+}
+
+/* call-seq:
+ * systmpdir -> String
+ *
+ * Returns system temporary directory; typically "/tmp".
+ */
+static VALUE
+etc_systmpdir(VALUE _)
+{
+ VALUE tmpdir;
+#ifdef _WIN32
+ WCHAR path[_MAX_PATH];
+ UINT len = rb_w32_system_tmpdir(path, numberof(path));
+ if (!len) return Qnil;
+ tmpdir = rb_w32_conv_from_wchar(path, rb_filesystem_encoding());
+#else
+ const char default_tmp[] = "/tmp";
+ const char *tmpstr = default_tmp;
+ size_t tmplen = strlen(default_tmp);
+# if defined _CS_DARWIN_USER_TEMP_DIR
+ #ifndef MAXPATHLEN
+ #define MAXPATHLEN 1024
+ #endif
+ char path[MAXPATHLEN];
+ size_t len;
+ len = confstr(_CS_DARWIN_USER_TEMP_DIR, path, sizeof(path));
+ if (len > 0) {
+ tmpstr = path;
+ tmplen = len - 1;
+ if (len > sizeof(path)) tmpstr = 0;
+ }
+# endif
+ tmpdir = rb_filesystem_str_new(tmpstr, tmplen);
+# if defined _CS_DARWIN_USER_TEMP_DIR
+ if (!tmpstr) {
+ confstr(_CS_DARWIN_USER_TEMP_DIR, RSTRING_PTR(tmpdir), len);
+ }
+# endif
+#endif
+#ifndef RB_PASS_KEYWORDS
+ /* untaint on Ruby < 2.7 */
+ FL_UNSET(tmpdir, FL_TAINT);
+#endif
+ return tmpdir;
+}
+
+#ifdef HAVE_UNAME
+/* call-seq:
+ * uname -> hash
+ *
+ * Returns the system information obtained by uname system call.
+ *
+ * The return value is a hash which has 5 keys at least:
+ * :sysname, :nodename, :release, :version, :machine
+ *
+ * *Example:*
+ *
+ * require 'etc'
+ * require 'pp'
+ *
+ * pp Etc.uname
+ * #=> {:sysname=>"Linux",
+ * # :nodename=>"boron",
+ * # :release=>"2.6.18-6-xen-686",
+ * # :version=>"#1 SMP Thu Nov 5 19:54:42 UTC 2009",
+ * # :machine=>"i686"}
+ *
+ */
+static VALUE
+etc_uname(VALUE obj)
+{
+#ifdef _WIN32
+ OSVERSIONINFOW v;
+ SYSTEM_INFO s;
+ const char *sysname, *mach;
+ VALUE result, release, version;
+ VALUE vbuf, nodename = Qnil;
+ DWORD len = 0;
+ WCHAR *buf;
+
+ v.dwOSVersionInfoSize = sizeof(v);
+ if (!GetVersionExW(&v))
+ rb_sys_fail("GetVersionEx");
+
+ result = rb_hash_new();
+ switch (v.dwPlatformId) {
+ case VER_PLATFORM_WIN32s:
+ sysname = "Win32s";
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ sysname = "Windows_NT";
+ break;
+ case VER_PLATFORM_WIN32_WINDOWS:
+ default:
+ sysname = "Windows";
+ break;
+ }
+ rb_hash_aset(result, SYMBOL_LIT("sysname"), rb_str_new_cstr(sysname));
+ release = rb_sprintf("%lu.%lu.%lu", v.dwMajorVersion, v.dwMinorVersion, v.dwBuildNumber);
+ rb_hash_aset(result, SYMBOL_LIT("release"), release);
+ version = rb_sprintf("%s Version %"PRIsVALUE": %"PRIsVALUE, sysname, release,
+ rb_w32_conv_from_wchar(v.szCSDVersion, rb_utf8_encoding()));
+ rb_hash_aset(result, SYMBOL_LIT("version"), version);
+
+# define GET_COMPUTER_NAME(ptr, plen) GetComputerNameExW(ComputerNameDnsFullyQualified, ptr, plen)
+ GET_COMPUTER_NAME(NULL, &len);
+ buf = ALLOCV_N(WCHAR, vbuf, len);
+ if (GET_COMPUTER_NAME(buf, &len)) {
+ nodename = rb_w32_conv_from_wchar(buf, rb_utf8_encoding());
+ }
+ ALLOCV_END(vbuf);
+ if (NIL_P(nodename)) nodename = rb_str_new(0, 0);
+ rb_hash_aset(result, SYMBOL_LIT("nodename"), nodename);
+
+# ifndef PROCESSOR_ARCHITECTURE_AMD64
+# define PROCESSOR_ARCHITECTURE_AMD64 9
+# endif
+# ifndef PROCESSOR_ARCHITECTURE_INTEL
+# define PROCESSOR_ARCHITECTURE_INTEL 0
+# endif
+ GetSystemInfo(&s);
+ switch (s.wProcessorArchitecture) {
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ mach = "x64";
+ break;
+ case PROCESSOR_ARCHITECTURE_ARM:
+ mach = "ARM";
+ break;
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ mach = "x86";
+ break;
+ default:
+ mach = "unknown";
+ break;
+ }
+
+ rb_hash_aset(result, SYMBOL_LIT("machine"), rb_str_new_cstr(mach));
+#else
+ struct utsname u;
+ int ret;
+ VALUE result;
+
+ ret = uname(&u);
+ if (ret == -1)
+ rb_sys_fail("uname");
+
+ result = rb_hash_new();
+ rb_hash_aset(result, SYMBOL_LIT("sysname"), rb_str_new_cstr(u.sysname));
+ rb_hash_aset(result, SYMBOL_LIT("nodename"), rb_str_new_cstr(u.nodename));
+ rb_hash_aset(result, SYMBOL_LIT("release"), rb_str_new_cstr(u.release));
+ rb_hash_aset(result, SYMBOL_LIT("version"), rb_str_new_cstr(u.version));
+ rb_hash_aset(result, SYMBOL_LIT("machine"), rb_str_new_cstr(u.machine));
+#endif
+
+ return result;
+}
+#else
+#define etc_uname rb_f_notimplement
+#endif
+
+#ifdef HAVE_SYSCONF
+/* call-seq:
+ * sysconf(name) -> Integer
+ *
+ * Returns system configuration variable using sysconf().
+ *
+ * _name_ should be a constant under <code>Etc</code> which begins with <code>SC_</code>.
+ *
+ * The return value is an integer or nil.
+ * nil means indefinite limit. (sysconf() returns -1 but errno is not set.)
+ *
+ * Etc.sysconf(Etc::SC_ARG_MAX) #=> 2097152
+ * Etc.sysconf(Etc::SC_LOGIN_NAME_MAX) #=> 256
+ *
+ */
+static VALUE
+etc_sysconf(VALUE obj, VALUE arg)
+{
+ int name;
+ long ret;
+
+ name = NUM2INT(arg);
+
+ errno = 0;
+ ret = sysconf(name);
+ if (ret == -1) {
+ if (errno == 0) /* no limit */
+ return Qnil;
+ rb_sys_fail("sysconf");
+ }
+ return LONG2NUM(ret);
+}
+#else
+#define etc_sysconf rb_f_notimplement
+#endif
+
+#ifdef HAVE_CONFSTR
+/* call-seq:
+ * confstr(name) -> String
+ *
+ * Returns system configuration variable using confstr().
+ *
+ * _name_ should be a constant under <code>Etc</code> which begins with <code>CS_</code>.
+ *
+ * The return value is a string or nil.
+ * nil means no configuration-defined value. (confstr() returns 0 but errno is not set.)
+ *
+ * Etc.confstr(Etc::CS_PATH) #=> "/bin:/usr/bin"
+ *
+ * # GNU/Linux
+ * Etc.confstr(Etc::CS_GNU_LIBC_VERSION) #=> "glibc 2.18"
+ * Etc.confstr(Etc::CS_GNU_LIBPTHREAD_VERSION) #=> "NPTL 2.18"
+ *
+ */
+static VALUE
+etc_confstr(VALUE obj, VALUE arg)
+{
+ int name;
+ char localbuf[128], *buf = localbuf;
+ size_t bufsize = sizeof(localbuf), ret;
+ VALUE tmp;
+
+ name = NUM2INT(arg);
+
+ errno = 0;
+ ret = confstr(name, buf, bufsize);
+ if (bufsize < ret) {
+ bufsize = ret;
+ buf = ALLOCV_N(char, tmp, bufsize);
+ errno = 0;
+ ret = confstr(name, buf, bufsize);
+ }
+ if (bufsize < ret)
+ rb_bug("required buffer size for confstr() changed dynamically.");
+ if (ret == 0) {
+ if (errno == 0) /* no configuration-defined value */
+ return Qnil;
+ rb_sys_fail("confstr");
+ }
+ return rb_str_new_cstr(buf);
+}
+#else
+#define etc_confstr rb_f_notimplement
+#endif
+
+#ifdef HAVE_FPATHCONF
+/* call-seq:
+ * pathconf(name) -> Integer
+ *
+ * Returns pathname configuration variable using fpathconf().
+ *
+ * _name_ should be a constant under <code>Etc</code> which begins with <code>PC_</code>.
+ *
+ * The return value is an integer or nil.
+ * nil means indefinite limit. (fpathconf() returns -1 but errno is not set.)
+ *
+ * require 'etc'
+ * IO.pipe {|r, w|
+ * p w.pathconf(Etc::PC_PIPE_BUF) #=> 4096
+ * }
+ *
+ */
+static VALUE
+io_pathconf(VALUE io, VALUE arg)
+{
+ int name;
+ long ret;
+
+ name = NUM2INT(arg);
+
+ errno = 0;
+ ret = fpathconf(rb_io_descriptor(io), name);
+ if (ret == -1) {
+ if (errno == 0) /* no limit */
+ return Qnil;
+ rb_sys_fail("fpathconf");
+ }
+ return LONG2NUM(ret);
+}
+#else
+#define io_pathconf rb_f_notimplement
+#endif
+
+#if (defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)) || defined(_WIN32)
+
+#if defined(HAVE_SCHED_GETAFFINITY) && defined(CPU_ALLOC)
+static int
+etc_nprocessors_affin(void)
+{
+ cpu_set_t *cpuset, cpuset_buff[1024 / sizeof(cpu_set_t)];
+ size_t size;
+ int ret;
+ int n;
+
+ CPU_ZERO_S(sizeof(cpuset_buff), cpuset_buff);
+
+ /*
+ * XXX:
+ * man page says CPU_ALLOC takes number of cpus. But it is not accurate
+ * explanation. sched_getaffinity() returns EINVAL if cpuset bitmap is
+ * smaller than kernel internal bitmap.
+ * That said, sched_getaffinity() can fail when a kernel have sparse bitmap
+ * even if cpuset bitmap is larger than number of cpus.
+ * The precious way is to use /sys/devices/system/cpu/online. But there are
+ * two problems,
+ * - Costly calculation
+ * It is a minor issue, but possibly kill a benefit of a parallel processing.
+ * - No guarantee to exist /sys/devices/system/cpu/online
+ * This is an issue especially when using Linux containers.
+ * So, we use hardcode number for a workaround. Current linux kernel
+ * (Linux 3.17) support 8192 cpus at maximum. Then 16384 must be enough.
+ */
+ for (n=64; n <= 16384; n *= 2) {
+ size = CPU_ALLOC_SIZE(n);
+ if (size >= sizeof(cpuset_buff)) {
+ cpuset = xcalloc(1, size);
+ if (!cpuset)
+ return -1;
+ } else {
+ cpuset = cpuset_buff;
+ }
+
+ ret = sched_getaffinity(0, size, cpuset);
+ if (ret == 0) {
+ /* On success, count number of cpus. */
+ ret = CPU_COUNT_S(size, cpuset);
+ }
+
+ if (size >= sizeof(cpuset_buff)) {
+ xfree(cpuset);
+ }
+ if (ret > 0 || errno != EINVAL) {
+ return ret;
+ }
+ }
+
+ return ret;
+}
+#endif
+
+/* call-seq:
+ * nprocessors -> Integer
+ *
+ * Returns the number of online processors.
+ *
+ * The result is intended as the number of processes to
+ * use all available processors.
+ *
+ * This method is implemented using:
+ * - sched_getaffinity(): Linux
+ * - sysconf(_SC_NPROCESSORS_ONLN): GNU/Linux, NetBSD, FreeBSD, OpenBSD, DragonFly BSD, OpenIndiana, Mac OS X, AIX
+ *
+ * *Example:*
+ *
+ * require 'etc'
+ * p Etc.nprocessors #=> 4
+ *
+ * The result might be smaller number than physical cpus especially when ruby
+ * process is bound to specific cpus. This is intended for getting better
+ * parallel processing.
+ *
+ * *Example:* (Linux)
+ *
+ * linux$ taskset 0x3 ./ruby -retc -e "p Etc.nprocessors" #=> 2
+ *
+ */
+static VALUE
+etc_nprocessors(VALUE obj)
+{
+ long ret;
+
+#if !defined(_WIN32)
+
+#if defined(HAVE_SCHED_GETAFFINITY) && defined(CPU_ALLOC)
+ int ncpus;
+
+ ncpus = etc_nprocessors_affin();
+ if (ncpus != -1) {
+ return INT2NUM(ncpus);
+ }
+ /* fallback to _SC_NPROCESSORS_ONLN */
+#endif
+
+ errno = 0;
+ ret = sysconf(_SC_NPROCESSORS_ONLN);
+ if (ret == -1) {
+ rb_sys_fail("sysconf(_SC_NPROCESSORS_ONLN)");
+ }
+#else
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ ret = (long)si.dwNumberOfProcessors;
+#endif
+ return LONG2NUM(ret);
+}
+#else
+#define etc_nprocessors rb_f_notimplement
+#endif
+
+/*
+ * The Etc module provides access to information typically stored in
+ * files in the <tt>/etc</tt> directory on Unix systems.
+ *
+ * The information accessible consists of the information found in the
+ * <tt>/etc/passwd</tt> and <tt>/etc/group</tt> files, plus information
+ * about the system's temporary directory (<tt>/tmp</tt>) and configuration
+ * directory (<tt>/etc</tt>).
+ *
+ * The Etc module provides a more reliable way to access information about
+ * the logged in user than environment variables such as +$USER+.
+ *
+ * *Example:*
+ *
+ * require 'etc'
+ *
+ * login = Etc.getlogin
+ * info = Etc.getpwnam(login)
+ * username = info.gecos.split(/,/).first
+ * puts "Hello #{username}, I see your login name is #{login}"
+ *
+ * Note that the methods provided by this module are not always secure.
+ * It should be used for informational purposes, and not for security.
+ *
+ * All operations defined in this module are class methods, so that you can
+ * include the Etc module into your class.
*/
void
-Init_etc()
+Init_etc(void)
{
+ VALUE mEtc;
+
mEtc = rb_define_module("Etc");
+ /* The version */
+ rb_define_const(mEtc, "VERSION", rb_str_new_cstr(RUBY_ETC_VERSION));
+ init_constants(mEtc);
+
+ /* Ractor-safe methods */
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ RB_EXT_RACTOR_SAFE(true);
+#endif
+ rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0);
+ rb_define_module_function(mEtc, "uname", etc_uname, 0);
+ rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1);
+ rb_define_module_function(mEtc, "confstr", etc_confstr, 1);
+ rb_define_method(rb_cIO, "pathconf", io_pathconf, 1);
+ rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0);
+ /* Non-Ractor-safe methods, see https://bugs.ruby-lang.org/issues/21115 */
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ RB_EXT_RACTOR_SAFE(false);
+#endif
rb_define_module_function(mEtc, "getlogin", etc_getlogin, 0);
rb_define_module_function(mEtc, "getpwuid", etc_getpwuid, -1);
@@ -514,46 +1188,127 @@ Init_etc()
rb_define_module_function(mEtc, "getpwent", etc_getpwent, 0);
rb_define_module_function(mEtc, "passwd", etc_passwd, 0);
- rb_define_module_function(mEtc, "getgrgid", etc_getgrgid, 1);
+ rb_define_module_function(mEtc, "getgrgid", etc_getgrgid, -1);
rb_define_module_function(mEtc, "getgrnam", etc_getgrnam, 1);
rb_define_module_function(mEtc, "group", etc_group, 0);
rb_define_module_function(mEtc, "setgrent", etc_setgrent, 0);
rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0);
rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0);
- rb_global_variable(&sPasswd);
- sPasswd = rb_struct_define("Passwd",
- "name", "passwd", "uid", "gid",
-#ifdef HAVE_ST_PW_GECOS
- "gecos",
+ /* Uses RbConfig::CONFIG so does not work in a Ractor */
+ rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0);
+
+ sPasswd = rb_struct_define_under(mEtc, "Passwd",
+ "name",
+#ifdef HAVE_STRUCT_PASSWD_PW_PASSWD
+ "passwd",
+#endif
+ "uid",
+ "gid",
+#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
+ "gecos",
#endif
- "dir", "shell",
-#ifdef HAVE_ST_PW_CHANGE
- "change",
+ "dir",
+ "shell",
+#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
+ "change",
#endif
-#ifdef HAVE_ST_PW_QUOTA
- "quota",
+#ifdef HAVE_STRUCT_PASSWD_PW_QUOTA
+ "quota",
#endif
-#ifdef HAVE_ST_PW_AGE
- "age",
+#ifdef HAVE_STRUCT_PASSWD_PW_AGE
+ "age",
#endif
-#ifdef HAVE_ST_PW_CLASS
- "uclass",
+#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
+ "uclass",
#endif
-#ifdef HAVE_ST_PW_COMMENT
- "comment",
+#ifdef HAVE_STRUCT_PASSWD_PW_COMMENT
+ "comment",
#endif
-#ifdef HAVE_ST_PW_EXPIRE
- "expire",
+#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
+ "expire",
#endif
- NULL);
+ NULL);
+#if 0
+ /*
+ * Passwd is a placeholder Struct for user database on Unix systems.
+ *
+ * === The struct contains the following members
+ *
+ * name::
+ * contains the short login name of the user as a String.
+ * passwd::
+ * contains the encrypted password of the user as a String.
+ * an <code>'x'</code> is returned if shadow passwords are in
+ * use. An <code>'*'</code> is returned if the user cannot
+ * log in using a password.
+ * uid::
+ * contains the integer user ID (uid) of the user.
+ * gid::
+ * contains the integer group ID (gid) of the user's primary group.
+ * dir::
+ * contains the path to the home directory of the user as a String.
+ * shell::
+ * contains the path to the login shell of the user as a String.
+ *
+ * === The following members below are system-dependent
+ *
+ * gecos::
+ * contains a longer String description of the user, such as
+ * a full name. Some Unix systems provide structured information in the
+ * gecos field, but this is system-dependent.
+ * change::
+ * password change time(integer).
+ * quota::
+ * quota value(integer).
+ * age::
+ * password age(integer).
+ * class::
+ * user access class(string).
+ * comment::
+ * comment(string).
+ * expire::
+ * account expiration time(integer).
+ */
+ sPasswd = rb_define_class_under(mEtc, "Passwd", rb_cStruct);
+#endif
+ rb_extend_object(sPasswd, rb_mEnumerable);
+ rb_define_singleton_method(sPasswd, "each", etc_each_passwd, 0);
#ifdef HAVE_GETGRENT
- rb_global_variable(&sGroup);
- sGroup = rb_struct_define("Group", "name",
-#ifdef HAVE_ST_GR_PASSWD
- "passwd",
+ sGroup = rb_struct_define_under(mEtc, "Group", "name",
+#ifdef HAVE_STRUCT_GROUP_GR_PASSWD
+ "passwd",
#endif
- "gid", "mem", NULL);
+ "gid", "mem", NULL);
+
+#if 0
+ /*
+ * Group is a placeholder Struct for user group database on Unix systems.
+ *
+ * === The struct contains the following members
+ *
+ * name::
+ * contains the name of the group as a String.
+ * passwd::
+ * contains the encrypted password as a String. An <code>'x'</code> is
+ * returned if password access to the group is not available; an empty
+ * string is returned if no password is needed to obtain membership of
+ * the group.
+ * This is system-dependent.
+ * gid::
+ * contains the group's numeric ID as an integer.
+ * mem::
+ * is an Array of Strings containing the short login names of the
+ * members of the group.
+ */
+ sGroup = rb_define_class_under(mEtc, "Group", rb_cStruct);
+#endif
+ rb_extend_object(sGroup, rb_mEnumerable);
+ rb_define_singleton_method(sGroup, "each", etc_each_group, 0);
+#endif
+
+#if defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
+ (void)safe_setup_str;
#endif
}
diff --git a/ext/etc/etc.gemspec b/ext/etc/etc.gemspec
new file mode 100644
index 0000000000..0e9803dc62
--- /dev/null
+++ b/ext/etc/etc.gemspec
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+version = ["", "ext/etc/"].find do |dir|
+ begin
+ break File.open(File.expand_path("../#{dir}/etc.c", __FILE__)) do |f|
+ f.gets "\n#define RUBY_ETC_VERSION "
+ f.gets[/"(.+)"/, 1]
+ end
+ rescue
+ next
+ end
+end
+
+Gem::Specification.new do |spec|
+ spec.name = "etc"
+ spec.version = version
+ spec.authors = ["Yukihiro Matsumoto"]
+ spec.email = ["matz@ruby-lang.org"]
+
+ spec.summary = %q{Provides access to information typically stored in UNIX /etc directory.}
+ spec.description = spec.summary
+ spec.homepage = "https://github.com/ruby/etc"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ changelogs = Dir.glob("logs/ChangeLog-[1-9]*[^~]", base: __dir__)
+ spec.files = %w[
+ BSDL
+ COPYING
+ README.md
+ ChangeLog
+ ext/etc/constdefs.h
+ ext/etc/etc.c
+ ext/etc/extconf.rb
+ ext/etc/mkconstants.rb
+ test/etc/test_etc.rb
+ ] + changelogs
+ spec.rdoc_options = ["--main", "README.md"]
+ spec.extra_rdoc_files = spec.files.grep_v(/\.{rb,[ch]}\z/)
+ spec.bindir = "exe"
+ spec.require_paths = ["lib"]
+ spec.extensions = %w{ext/etc/extconf.rb}
+
+ spec.required_ruby_version = ">= 2.7.0"
+end
diff --git a/ext/etc/etc.txt b/ext/etc/etc.txt
deleted file mode 100644
index 534790172c..0000000000
--- a/ext/etc/etc.txt
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" etc.txt - -*- Indented-Text -*- created at: Fri Jul 14 00:47:15 JST 1995
-
-** Etc(Module)
-
-The module to retrieve information under /etc directory. Available
-only on UNIX platforms. All operations defined in this module are
-module functions, so that you can include Etc module into your class.
-
-Module Function:
-
- getlogin
-
- returns login name of the user. It this fails, try getpwuid().
-
- getpwnam(name)
-
- searches in /etc/passwd file (or equivalent database), and
- returns password entry for the user. The return value is an
- passwd structure, which has members described below.
-
- struct passwd
- name # user name(string)
- passwd # encrypted password(string)
- uid # user ID(integer)
- gid # group ID(integer)
- gecos # gecos field(string)
- dir # home directory(string)
- shell # login shell(string)
- # members below are optional
- change # password change time(integer)
- quota # quota value(integer)
- age # password age(integer)
- class # user access class(string)
- comment # comment(string)
- expire # account expiration time(integer)
- end
-
- See getpwnam(3) for detail.
-
- getpwuid([uid])
-
- returns passwd entry for the specified user id. If uid is
- ommitted, use the value from getuid(). See getpwuid(3) for
- detail.
-
- getgrgid(gid)
-
- searches in /etc/group file (or equivalent database), and
- returns group entry for the group id. The return value is an
- group structure, which has members described below.
-
- struct group
- name # group name(string)
- passwd # group password(string)
- gid # group ID(integer)
- mem # array of the group member names
- end
-
- See getgrgid(3) for detail.
-
- getgrnam(name)
-
- returns the group entry for the specified name. The return
- value is the group structure. See getgrnam(3) for detail.
-
- group
-
- iterates over all group entries.
-
- passwd
-
- iterates over all passwd entries.
diff --git a/ext/etc/etc.txt.ja b/ext/etc/etc.txt.ja
deleted file mode 100644
index 2dddcfb036..0000000000
--- a/ext/etc/etc.txt.ja
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" etc.txt.ja - -*- Indented-Text -*- created at: Fri Jul 14 00:47:15 JST 1995
-
-** Etc(¥â¥¸¥å¡¼¥ë)
-
-/etc¥Ç¥£¥ì¥¯¥È¥ê°Ê²¼¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤Î¥â¥¸¥å¡¼¥ë¡¥¥¯¥é¥¹¤Ë¥¤¥ó¥¯¥ë¡¼¥É
-¤·¤Æ»È¤¦¤³¤È¤â¤Ç¤­¤ë¡¥
-
-Module Function:
-
- getlogin
-
- ¼«Ê¬¤Îlogin̾¤òÊÖ¤¹¡¥¤³¤ì¤¬¼ºÇÔ¤·¤¿¾ì¹ç¤Ïgetpwuid()¤òÍѤ¤¤ë¤È
- Îɤ¤¡¥
-
- getpwnam(name)
-
- /etc/passwd¥Õ¥¡¥¤¥ë(¤¢¤ë¤¤¤ÏDBM¥Õ¥¡¥¤¥ë¤äNIS¥Ç¡¼¥¿¥Ù¡¼¥¹)¤ò¸¡
- º÷¤·¡¤name¤Î̾Á°¤ò»ý¤Äpasswd¥¨¥ó¥È¥ê¤òÊÖ¤¹¡¥Ìá¤êÃͤÏpasswd¹½Â¤
- ÂΤǰʲ¼¤Î¥á¥ó¥Ð¤ò»ý¤Ä¡¥
-
- struct passwd
- name # ¥æ¡¼¥¶Ì¾(ʸ»úÎó)
- passwd # ¥Ñ¥¹¥ï¡¼¥É(ʸ»úÎó)
- uid # ¥æ¡¼¥¶ID(À°¿ô)
- gid # ¥°¥ë¡¼¥×ID(À°¿ô)
- gecos # gecos¥Õ¥£¡¼¥ë¥É(ʸ»úÎó)
- dir # ¥Û¡¼¥à¥Ç¥£¥ì¥¯¥È¥ê(ʸ»úÎó)
- shell # ¥í¥°¥¤¥ó¥·¥§¥ë(ʸ»úÎó)
- # °Ê¹ß¤Î¥á¥ó¥Ð¤Ï¥·¥¹¥Æ¥à¤Ë¤è¤Ã¤Æ¤ÏÄ󶡤µ¤ì¤Ê¤¤¡¥
- change # ¥Ñ¥¹¥ï¡¼¥ÉÊѹ¹»þ´Ö(À°¿ô)
- quota # ¥¯¥©¡¼¥¿(À°¿ô)
- age # ¥¨¡¼¥¸(À°¿ô)
- class # ¥æ¡¼¥¶¥¢¥¯¥»¥¹¥¯¥é¥¹(ʸ»úÎó)
- comment # ¥³¥á¥ó¥È(ʸ»úÎó)
- expire # ¥¢¥«¥¦¥ó¥ÈÍ­¸ú´ü¸Â(À°¿ô)
- end
-
- ¾ÜºÙ¤Ïgetpwnam(3)¤ò»²¾È¤Î¤³¤È¡¥
-
- getpwuid([uid])
-
- uid¤ò¥æ¡¼¥¶ID¤È¤¹¤ëpasswd¥¨¥ó¥È¥ê¤òÊÖ¤¹¡¥Ìá¤êÃͤÏgetpwnam()¤È
- ƱÍͤǤ¢¤ë¡¥°ú¿ô¤ò¾Êά¤·¤¿¾ì¹ç¤Ë¤Ïgetuid()¤ÎÃͤòÍѤ¤¤ë¡¥¾ÜºÙ¤Ï
- getpwuid(3)¤ò»²¾È¤Î¤³¤È¡¥
-
- getgrgid(gid)
-
- /etc/group¥Õ¥¡¥¤¥ë(¤¢¤ë¤¤¤Ï¡Ägetpwnam»²¾È)¤ò¸¡º÷¤·¡¤gid¤ò¥°¥ë¡¼
- ¥×ID¤È¤¹¤ë¥°¥ë¡¼¥×¥¨¥ó¥È¥ê¤òÊÖ¤¹¡¥Ìá¤êÃͤÏgroup¹½Â¤ÂΤǰʲ¼¤Î
- ¥á¥ó¥Ð¤ò»ý¤Ä¡¥
-
- struct group
- name # ¥°¥ë¡¼¥×̾(ʸ»úÎó)
- passwd # ¥°¥ë¡¼¥×¤Î¥Ñ¥¹¥ï¡¼¥É(ʸ»úÎó)
- gid # ¥°¥ë¡¼¥×ID(À°¿ô)
- mem # ¥°¥ë¡¼¥×¥á¥ó¥Ð̾¤ÎÇÛÎó
- end
-
- ¾ÜºÙ¤Ïgetgrgid(3)¤ò»²¾È¤Î¤³¤È¡¥
-
- getgrnam(name)
-
- name¤È¤¤¤¦Ì¾Á°¤Î¥°¥ë¡¼¥×¥¨¥ó¥È¥ê¤òÊÖ¤¹¡¥Ìá¤êÃͤÏgetgrgid()¤ÈƱ
- ÍͤǤ¢¤ë¡¥¾ÜºÙ¤Ïgetgrnam(3)¤ò»²¾È¡¥
-
- group
-
- Á´¤Æ¤Î¥°¥ë¡¼¥×¥¨¥ó¥È¥ê¤ò½ç¤Ë¥¢¥¯¥»¥¹¤¹¤ë¤¿¤á¤Î¥¤¥Æ¥ì¡¼¥¿¡¥
-
- passwd
-
- Á´¤Æ¤Îpasswd¥¨¥ó¥È¥ê¤ò½ç¤Ë¥¢¥¯¥»¥¹¤¹¤ë¤¿¤á¤Î¥¤¥Æ¥ì¡¼¥¿¡¥
diff --git a/ext/etc/extconf.rb b/ext/etc/extconf.rb
index 2496d36aa1..497303a4fa 100644
--- a/ext/etc/extconf.rb
+++ b/ext/etc/extconf.rb
@@ -1,10 +1,16 @@
+# frozen_string_literal: true
require 'mkmf'
+headers = []
+%w[sys/utsname.h].each {|h|
+ if have_header(h, headers)
+ headers << h
+ end
+}
have_library("sun", "getpwnam") # NIS (== YP) interface for IRIX 4
-a = have_func("getlogin")
-b = have_func("getpwent")
-c = have_func("getgrent")
-if a or b or c
+have_func("uname((struct utsname *)NULL)", headers)
+have_func("getlogin")
+if have_func("getpwent")
have_struct_member('struct passwd', 'pw_gecos', 'pwd.h')
have_struct_member('struct passwd', 'pw_change', 'pwd.h')
have_struct_member('struct passwd', 'pw_quota', 'pwd.h')
@@ -23,19 +29,39 @@ if a or b or c
have_struct_member('struct passwd', 'pw_comment', 'pwd.h') unless /cygwin/ === RUBY_PLATFORM
have_struct_member('struct passwd', 'pw_expire', 'pwd.h')
have_struct_member('struct passwd', 'pw_passwd', 'pwd.h')
+end
+if have_func("getgrent")
have_struct_member('struct group', 'gr_passwd', 'grp.h')
- [%w"uid_t pwd.h", %w"gid_t grp.h"].each do |t, *h|
- h.unshift("sys/types.h")
- f = "INT2NUM"
- if have_type(t, h)
- if try_static_assert("sizeof(#{t}) > sizeof(long)", h)
- f = "LL2NUM"
- end
- if try_static_assert("(#{t})-1 > 0", h)
- f = "U#{f}"
- end
- end
- $defs.push("-DPW_#{t.chomp('_t').upcase}2VAL=#{f}")
+end
+
+if (sysconfdir = RbConfig::CONFIG["sysconfdir"] and
+ !RbConfig.expand(sysconfdir.dup, "prefix"=>"", "DESTDIR"=>"").empty?)
+ $defs.push("-DSYSCONFDIR=#{Shellwords.escape(sysconfdir.dump)}")
+end
+
+have_func("sysconf")
+have_func("confstr")
+have_func("fpathconf")
+
+# for https://github.com/ruby/etc
+srcdir = File.expand_path("..", __FILE__)
+constdefs = "#{srcdir}/constdefs.h"
+if !File.exist?(constdefs)
+ ruby = RbConfig.ruby
+ if File.file?(ruby)
+ ruby = [ruby]
+ else
+ require "shellwords"
+ ruby = Shellwords.split(ruby)
end
- create_makefile("etc")
+ system(*ruby, "#{srcdir}/mkconstants.rb", "-o", constdefs)
end
+
+# TODO: remove when dropping 2.7 support, as exported since 3.0
+have_func('rb_deprecate_constant(Qnil, "None")')
+
+have_func("rb_io_descriptor", "ruby/io.h")
+
+$distcleanfiles << "constdefs.h"
+
+create_makefile("etc")
diff --git a/ext/etc/mkconstants.rb b/ext/etc/mkconstants.rb
new file mode 100644
index 0000000000..a766560a8a
--- /dev/null
+++ b/ext/etc/mkconstants.rb
@@ -0,0 +1,352 @@
+# frozen_string_literal: true
+require 'optparse'
+require 'erb'
+
+C_ESC = {
+ "\\" => "\\\\",
+ '"' => '\"',
+ "\n" => '\n',
+}
+
+0x00.upto(0x1f) {|ch| C_ESC[[ch].pack("C")] ||= "\\%03o" % ch }
+0x7f.upto(0xff) {|ch| C_ESC[[ch].pack("C")] = "\\%03o" % ch }
+C_ESC_PAT = Regexp.union(*C_ESC.keys)
+
+def c_str(str)
+ '"' + str.gsub(C_ESC_PAT) {|s| C_ESC[s]} + '"'
+end
+
+opt = OptionParser.new
+
+opt.def_option('-h', 'help') {
+ puts opt
+ exit 0
+}
+
+opt_o = nil
+opt.def_option('-o FILE', 'specify output file') {|filename|
+ opt_o = filename
+}
+
+opt_H = nil
+opt.def_option('-H FILE', 'specify output header file') {|filename|
+ opt_H = filename
+}
+
+opt.parse!
+
+CONST_PREFIXES = {
+ 'SC' => 'for Etc.sysconf; See <tt>man sysconf</tt>',
+ 'CS' => 'for Etc.confstr; See <tt>man constr</tt>',
+ 'PC' => 'for IO#pathconf; See <tt>man fpathconf</tt>',
+}
+
+h = {}
+COMMENTS = {}
+
+DATA.each_line {|s|
+ next if /\A\s*(\#|\z)/ =~ s
+ name, default_value, comment = s.chomp.split(/\s+/, 3)
+
+ default_value = nil if default_value == 'nil'
+
+ if h.has_key? name
+ warn "#{$.}: warning: duplicate name: #{name}"
+ next
+ end
+ h[name] = default_value
+ if additional = CONST_PREFIXES[name[/\A_([A-Z]+)_/, 1]]
+ if comment&.match(/\w\z/)
+ comment << " " << additional
+ else
+ (comment ||= String.new) << " " << additional.sub(/\A\w/) {$&.upcase}
+ end
+ end
+ COMMENTS[name] = comment if comment
+}
+DEFS = h.to_a
+
+def each_const
+ DEFS.each {|name, default_value|
+ yield name, default_value
+ }
+end
+
+def each_name(pat)
+ DEFS.each {|name, default_value|
+ next if pat !~ name
+ yield name
+ }
+end
+
+erb_new = lambda do |src, trim|
+ ERB.new(src, trim_mode: trim)
+end
+
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_decls")
+% each_const {|name, default_value|
+#if !defined(<%=name%>)
+# if defined(HAVE_CONST_<%=name.upcase%>)
+# define <%=name%> <%=name%>
+%if default_value
+# else
+# define <%=name%> <%=default_value%>
+%end
+# endif
+#endif
+% }
+EOS
+
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_defs")
+% each_const {|name, default_value|
+#if defined(<%=name%>)
+% if comment = COMMENTS[name]
+ /* <%=comment%> */
+% end
+ rb_define_const(mod, <%=c_str name.sub(/\A_*/, '')%>, INTEGER2NUM(<%=name%>));
+#endif
+% }
+EOS
+
+header_result = erb_new.call(<<'EOS', '%').result(binding)
+/* autogenerated file */
+
+<%= gen_const_decls %>
+EOS
+
+result = erb_new.call(<<'EOS', '%').result(binding)
+/* autogenerated file */
+
+#ifdef HAVE_LONG_LONG
+#define INTEGER2NUM(n) \
+ (FIXNUM_MAX < (n) ? ULL2NUM(n) : \
+ FIXNUM_MIN > (LONG_LONG)(n) ? LL2NUM(n) : \
+ LONG2FIX(n))
+#else
+#define INTEGER2NUM(n) \
+ (FIXNUM_MAX < (n) ? ULONG2NUM(n) : \
+ FIXNUM_MIN > (long)(n) ? LONG2NUM(n) : \
+ LONG2FIX(n))
+#endif
+
+static void
+init_constants(VALUE mod)
+{
+#if 0
+ mod = rb_define_module("Etc");
+#endif
+<%= gen_const_defs %>
+}
+EOS
+
+if opt_H
+ File.open(opt_H, 'w') {|f|
+ f << header_result
+ }
+else
+ result = header_result + result
+end
+
+if opt_o
+ File.open(opt_o, 'w') {|f|
+ f << result
+ }
+else
+ $stdout << result
+end
+
+__END__
+# SUSv4
+_SC_AIO_LISTIO_MAX
+_SC_AIO_MAX
+_SC_AIO_PRIO_DELTA_MAX
+_SC_ARG_MAX
+_SC_ATEXIT_MAX
+_SC_BC_BASE_MAX
+_SC_BC_DIM_MAX
+_SC_BC_SCALE_MAX
+_SC_BC_STRING_MAX
+_SC_CHILD_MAX
+_SC_CLK_TCK
+_SC_COLL_WEIGHTS_MAX
+_SC_DELAYTIMER_MAX
+_SC_EXPR_NEST_MAX
+_SC_HOST_NAME_MAX
+_SC_IOV_MAX
+_SC_LINE_MAX
+_SC_LOGIN_NAME_MAX
+_SC_NGROUPS_MAX
+_SC_GETGR_R_SIZE_MAX
+_SC_GETPW_R_SIZE_MAX
+_SC_MQ_OPEN_MAX
+_SC_MQ_PRIO_MAX
+_SC_OPEN_MAX
+_SC_ADVISORY_INFO
+_SC_BARRIERS
+_SC_ASYNCHRONOUS_IO
+_SC_CLOCK_SELECTION
+_SC_CPUTIME
+_SC_FSYNC
+_SC_IPV6
+_SC_JOB_CONTROL
+_SC_MAPPED_FILES
+_SC_MEMLOCK
+_SC_MEMLOCK_RANGE
+_SC_MEMORY_PROTECTION
+_SC_MESSAGE_PASSING
+_SC_MONOTONIC_CLOCK
+_SC_PRIORITIZED_IO
+_SC_PRIORITY_SCHEDULING
+_SC_RAW_SOCKETS
+_SC_READER_WRITER_LOCKS
+_SC_REALTIME_SIGNALS
+_SC_REGEXP
+_SC_SAVED_IDS
+_SC_SEMAPHORES
+_SC_SHARED_MEMORY_OBJECTS
+_SC_SHELL
+_SC_SPAWN
+_SC_SPIN_LOCKS
+_SC_SPORADIC_SERVER
+_SC_SS_REPL_MAX
+_SC_SYNCHRONIZED_IO
+_SC_THREAD_ATTR_STACKADDR
+_SC_THREAD_ATTR_STACKSIZE
+_SC_THREAD_CPUTIME
+_SC_THREAD_PRIO_INHERIT
+_SC_THREAD_PRIO_PROTECT
+_SC_THREAD_PRIORITY_SCHEDULING
+_SC_THREAD_PROCESS_SHARED
+_SC_THREAD_ROBUST_PRIO_INHERIT
+_SC_THREAD_ROBUST_PRIO_PROTECT
+_SC_THREAD_SAFE_FUNCTIONS
+_SC_THREAD_SPORADIC_SERVER
+_SC_THREADS
+_SC_TIMEOUTS
+_SC_TIMERS
+_SC_TRACE
+_SC_TRACE_EVENT_FILTER
+_SC_TRACE_EVENT_NAME_MAX
+_SC_TRACE_INHERIT
+_SC_TRACE_LOG
+_SC_TRACE_NAME_MAX
+_SC_TRACE_SYS_MAX
+_SC_TRACE_USER_EVENT_MAX
+_SC_TYPED_MEMORY_OBJECTS
+_SC_VERSION
+_SC_V7_ILP32_OFF32
+_SC_V7_ILP32_OFFBIG
+_SC_V7_LP64_OFF64
+_SC_V7_LPBIG_OFFBIG
+_SC_V6_ILP32_OFF32
+_SC_V6_ILP32_OFFBIG
+_SC_V6_LP64_OFF64
+_SC_V6_LPBIG_OFFBIG
+_SC_2_C_BIND
+_SC_2_C_DEV
+_SC_2_CHAR_TERM
+_SC_2_FORT_DEV
+_SC_2_FORT_RUN
+_SC_2_LOCALEDEF
+_SC_2_PBS
+_SC_2_PBS_ACCOUNTING
+_SC_2_PBS_CHECKPOINT
+_SC_2_PBS_LOCATE
+_SC_2_PBS_MESSAGE
+_SC_2_PBS_TRACK
+_SC_2_SW_DEV
+_SC_2_UPE
+_SC_2_VERSION
+_SC_PAGE_SIZE
+_SC_PAGESIZE
+_SC_THREAD_DESTRUCTOR_ITERATIONS
+_SC_THREAD_KEYS_MAX
+_SC_THREAD_STACK_MIN
+_SC_THREAD_THREADS_MAX
+_SC_RE_DUP_MAX
+_SC_RTSIG_MAX
+_SC_SEM_NSEMS_MAX
+_SC_SEM_VALUE_MAX
+_SC_SIGQUEUE_MAX
+_SC_STREAM_MAX
+_SC_SYMLOOP_MAX
+_SC_TIMER_MAX
+_SC_TTY_NAME_MAX
+_SC_TZNAME_MAX
+_SC_XOPEN_CRYPT
+_SC_XOPEN_ENH_I18N
+_SC_XOPEN_REALTIME
+_SC_XOPEN_REALTIME_THREADS
+_SC_XOPEN_SHM
+_SC_XOPEN_STREAMS
+_SC_XOPEN_UNIX
+_SC_XOPEN_UUCP
+_SC_XOPEN_VERSION
+
+# non-standard
+_SC_PHYS_PAGES
+_SC_AVPHYS_PAGES
+_SC_NPROCESSORS_CONF
+_SC_NPROCESSORS_ONLN
+_SC_CPUSET_SIZE
+
+# SUSv4
+_CS_PATH
+_CS_POSIX_V7_ILP32_OFF32_CFLAGS
+_CS_POSIX_V7_ILP32_OFF32_LDFLAGS
+_CS_POSIX_V7_ILP32_OFF32_LIBS
+_CS_POSIX_V7_ILP32_OFFBIG_CFLAGS
+_CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS
+_CS_POSIX_V7_ILP32_OFFBIG_LIBS
+_CS_POSIX_V7_LP64_OFF64_CFLAGS
+_CS_POSIX_V7_LP64_OFF64_LDFLAGS
+_CS_POSIX_V7_LP64_OFF64_LIBS
+_CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS
+_CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS
+_CS_POSIX_V7_LPBIG_OFFBIG_LIBS
+_CS_POSIX_V7_THREADS_CFLAGS
+_CS_POSIX_V7_THREADS_LDFLAGS
+_CS_POSIX_V7_WIDTH_RESTRICTED_ENVS
+_CS_V7_ENV
+_CS_POSIX_V6_ILP32_OFF32_CFLAGS
+_CS_POSIX_V6_ILP32_OFF32_LDFLAGS
+_CS_POSIX_V6_ILP32_OFF32_LIBS
+_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS
+_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS
+_CS_POSIX_V6_ILP32_OFFBIG_LIBS
+_CS_POSIX_V6_LP64_OFF64_CFLAGS
+_CS_POSIX_V6_LP64_OFF64_LDFLAGS
+_CS_POSIX_V6_LP64_OFF64_LIBS
+_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS
+_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS
+_CS_POSIX_V6_LPBIG_OFFBIG_LIBS
+_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS
+_CS_V6_ENV
+
+# non-standard
+_CS_GNU_LIBC_VERSION
+_CS_GNU_LIBPTHREAD_VERSION
+
+# SUSv4
+_PC_FILESIZEBITS
+_PC_LINK_MAX
+_PC_MAX_CANON
+_PC_MAX_INPUT
+_PC_NAME_MAX
+_PC_PATH_MAX
+_PC_PIPE_BUF
+_PC_2_SYMLINKS
+_PC_ALLOC_SIZE_MIN
+_PC_REC_INCR_XFER_SIZE
+_PC_REC_MAX_XFER_SIZE
+_PC_REC_MIN_XFER_SIZE
+_PC_REC_XFER_ALIGN
+_PC_SYMLINK_MAX
+_PC_CHOWN_RESTRICTED
+_PC_NO_TRUNC
+_PC_VDISABLE
+_PC_ASYNC_IO
+_PC_PRIO_IO
+_PC_SYNC_IO
+_PC_TIMESTAMP_RESOLUTION
+
diff --git a/ext/extmk.rb b/ext/extmk.rb
index bbcb3c09b8..f5244f72c8 100644..100755
--- a/ext/extmk.rb
+++ b/ext/extmk.rb
@@ -1,57 +1,99 @@
#! /usr/local/bin/ruby
-# -*- ruby -*-
+# -*- mode: ruby; coding: us-ascii -*-
+# frozen_string_literal: false
+module Gem
+ # Used by Gem::Platform.local
+ def self.target_rbconfig
+ RbConfig::CONFIG
+ end
+end
+
+# :stopdoc:
+$extension = nil
+$extstatic = nil
$force_static = nil
-$install = nil
$destdir = nil
-$clean = nil
+$dryrun = false
$nodynamic = nil
-$extinit = nil
-$extobjs = nil
-$ignore = nil
+$extobjs = []
+$extflags = ""
+$extlibs = nil
+$extpath = nil
$message = nil
+$command_output = nil
+$subconfigure = false
$progname = $0
alias $PROGRAM_NAME $0
alias $0 $progname
$extlist = []
-$compiled = {}
-$:.replace([Dir.pwd])
-require 'rbconfig'
+DUMMY_SIGNATURE = "***DUMMY MAKEFILE***"
srcdir = File.dirname(File.dirname(__FILE__))
+unless defined?(CROSS_COMPILING) and CROSS_COMPILING
+ $:.replace([Dir.pwd, File.expand_path("lib", srcdir)])
+end
+require 'rbconfig'
-$:.unshift(srcdir, File.expand_path("lib", srcdir))
+# only needs Gem::Platform
+require 'rubygems/platform'
$topdir = "."
$top_srcdir = srcdir
+$extmk = true
+inplace = File.identical?($top_srcdir, $topdir)
-require 'mkmf'
+$" << "mkmf.rb"
+load File.expand_path("lib/mkmf.rb", srcdir)
require 'optparse/shellwords'
-def sysquote(x)
- @quote ||= /human|os2|macos/ =~ (CROSS_COMPILING || RUBY_PLATFORM)
- @quote ? x.quote : x
+@null = File::NULL
+
+def verbose?
+ $mflags.defined?("V") == "1"
end
-def relative_from(path, base)
- dir = File.join(path, "")
- if File.expand_path(dir) == File.expand_path(dir, base)
- path
- else
- File.join(base, path)
+def system(*args)
+ if verbose?
+ if args.size == 1
+ puts args
+ else
+ puts Shellwords.join(args)
+ end
+ end
+ super
+end
+
+def atomic_write_open(filename)
+ filename_new = filename + ".new.#$$"
+ clean = false
+ File.open(filename_new, "wbx") do |f|
+ clean = true
+ yield f
+ end
+ if File.binread(filename_new) != (File.binread(filename) rescue nil)
+ File.rename(filename_new, filename)
+ clean = false
+ end
+ensure
+ if clean
+ File.unlink(filename_new)
end
end
def extract_makefile(makefile, keep = true)
m = File.read(makefile)
+ s = m[/^CLEANFILES[ \t]*=[ \t](.*)/, 1] and $cleanfiles = s.split
+ s = m[/^DISTCLEANFILES[ \t]*=[ \t](.*)/, 1] and $distcleanfiles = s.split
+ s = m[/^EXTSO[ \t]*=[ \t](.*)/, 1] and $extso = s.split
if !(target = m[/^TARGET[ \t]*=[ \t]*(\S*)/, 1])
return keep
end
installrb = {}
- m.scan(/^install-rb-default:[ \t]*(\S+)\n\1:[ \t]*(\S+)/) {installrb[$2] = $1}
+ m.scan(/^(?:do-)?install-rb-default:.*[ \t](\S+)(?:[ \t].*)?\n\1:[ \t]*(\S+)/) {installrb[$2] = $1}
oldrb = installrb.keys.sort
newrb = install_rb(nil, "").collect {|d, *f| f}.flatten.sort
if target_prefix = m[/^target_prefix[ \t]*=[ \t]*\/(.*)/, 1]
@@ -63,81 +105,124 @@ def extract_makefile(makefile, keep = true)
unless installrb.empty?
config = CONFIG.dup
install_dirs(target_prefix).each {|var, val| config[var] = val}
- FileUtils.rm_f(installrb.values.collect {|f| Config.expand(f, config)}, :verbose => true)
+ FileUtils.rm_f(installrb.values.collect {|f| RbConfig.expand(f, config)},
+ :verbose => verbose?)
end
end
return false
end
+ srcs = Dir[*SRC_EXT.map {|e| "*.#{e}"}, base: $srcdir].map {|fn| File.basename(fn)}.sort
+ if !srcs.empty?
+ old_srcs = m[/^ORIG_SRCS[ \t]*=[ \t](.*)/, 1] or return false
+ (old_srcs.split - srcs).empty? or return false
+ end
$target = target
$extconf_h = m[/^RUBY_EXTCONF_H[ \t]*=[ \t]*(\S+)/, 1]
- $static ||= m[/^EXTSTATIC[ \t]*=[ \t]*(\S+)/, 1] || false
- /^STATIC_LIB[ \t]*=[ \t]*\S+/ =~ m or $static = nil
+ if $static.nil?
+ $static ||= m[/^EXTSTATIC[ \t]*=[ \t]*(\S+)/, 1] || false
+ /^STATIC_LIB[ \t]*=[ \t]*\S+/ =~ m or $static = false
+ end
$preload = Shellwords.shellwords(m[/^preload[ \t]*=[ \t]*(.*)/, 1] || "")
- $DLDFLAGS += " " + (m[/^DLDFLAGS[ \t]*=[ \t]*(.*)/, 1] || "")
+ if dldflags = m[/^dldflags[ \t]*=[ \t]*(.*)/, 1] and !$DLDFLAGS.include?(dldflags)
+ $DLDFLAGS += " " + dldflags
+ end
if s = m[/^LIBS[ \t]*=[ \t]*(.*)/, 1]
s.sub!(/^#{Regexp.quote($LIBRUBYARG)} */, "")
s.sub!(/ *#{Regexp.quote($LIBS)}$/, "")
$libs = s
end
+ $objs = (m[/^OBJS[ \t]*=[ \t](.*)/, 1] || "").split
+ $srcs = (m[/^SRCS[ \t]*=[ \t](.*)/, 1] || "").split
+ $headers = (m[/^LOCAL_HDRS[ \t]*=[ \t](.*)/, 1] || "").split
$LOCAL_LIBS = m[/^LOCAL_LIBS[ \t]*=[ \t]*(.*)/, 1] || ""
$LIBPATH = Shellwords.shellwords(m[/^libpath[ \t]*=[ \t]*(.*)/, 1] || "") - %w[$(libdir) $(topdir)]
true
end
-def extmake(target)
- print "#{$message} #{target}\n"
- $stdout.flush
- if $force_static or $static_ext[target]
- $static = target
- else
- $static = false
- end
-
- unless $ignore
- return true if $nodynamic and not $static
- end
-
+def extmake(target, basedir = 'ext', maybestatic = true)
FileUtils.mkpath target unless File.directory?(target)
begin
+ # don't build if parent library isn't build
+ parent = true
+ d = target
+ until (d = File.dirname(d)) == '.'
+ if File.exist?("#{$top_srcdir}/#{basedir}/#{d}/extconf.rb")
+ parent = (/^all:\s*install/ =~ File.read("#{d}/Makefile") rescue false)
+ break
+ end
+ end
+
dir = Dir.pwd
FileUtils.mkpath target unless File.directory?(target)
Dir.chdir target
top_srcdir = $top_srcdir
topdir = $topdir
- mk_srcdir = CONFIG["srcdir"]
- mk_topdir = CONFIG["topdir"]
- prefix = "../" * (target.count("/")+1)
- $hdrdir = $top_srcdir = relative_from(top_srcdir, prefix)
+ hdrdir = $hdrdir
+ prefix = "../" * (basedir.count("/")+target.count("/")+1)
+ $top_srcdir = relative_from(top_srcdir, prefix)
+ $hdrdir = relative_from(hdrdir, prefix)
$topdir = prefix + $topdir
$target = target
$mdir = target
- $srcdir = File.join($top_srcdir, "ext", $mdir)
+ $srcdir = File.join($top_srcdir, basedir, $mdir)
$preload = nil
- $compiled[target] = false
+ $extso = []
makefile = "./Makefile"
- ok = File.exist?(makefile)
- unless $ignore
- Config::CONFIG["hdrdir"] = $hdrdir
- Config::CONFIG["srcdir"] = $srcdir
- Config::CONFIG["topdir"] = $topdir
- CONFIG["hdrdir"] = ($hdrdir == top_srcdir) ? top_srcdir : "$(topdir)"+top_srcdir[2..-1]
- CONFIG["srcdir"] = "$(hdrdir)/ext/#{$mdir}"
- CONFIG["topdir"] = $topdir
+ static = $static
+ $static = nil if noinstall = File.fnmatch?("-*", target)
+ ok = parent && File.exist?(makefile)
+ if parent
+ rbconfig0 = RbConfig::CONFIG
+ mkconfig0 = CONFIG
+ rbconfig = {
+ "hdrdir" => $hdrdir,
+ "srcdir" => $srcdir,
+ "topdir" => $topdir,
+ }
+ mkconfig = {
+ "hdrdir" => ($hdrdir == top_srcdir) ? top_srcdir : "$(top_srcdir)/include",
+ "srcdir" => "$(top_srcdir)/#{basedir}/#{$mdir}",
+ "topdir" => $topdir,
+ }
+ rbconfig0.each_pair {|key, val| rbconfig[key] ||= val.dup}
+ mkconfig0.each_pair {|key, val| mkconfig[key] ||= val.dup}
+ RbConfig.module_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, rbconfig)
+ remove_const(:MAKEFILE_CONFIG)
+ const_set(:MAKEFILE_CONFIG, mkconfig)
+ }
+ MakeMakefile.class_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, mkconfig)
+ }
begin
$extconf_h = nil
ok &&= extract_makefile(makefile)
- if (($extconf_h && !File.exist?($extconf_h)) ||
+ old_objs = $objs || []
+ old_cleanfiles = $distcleanfiles | $cleanfiles
+ conf = ["#{$srcdir}/makefile.rb", "#{$srcdir}/extconf.rb"].find {|f| File.exist?(f)}
+ if (!ok || ($extconf_h && !File.exist?($extconf_h)) ||
!(t = modified?(makefile, MTIMES)) ||
- %W"#{$srcdir}/makefile.rb #{$srcdir}/extconf.rb #{$srcdir}/depend".any? {|f| modified?(f, [t])})
+ [conf, "#{$srcdir}/depend"].any? {|f| modified?(f, [t])})
then
ok = false
+ if verbose?
+ print "#{conf}\n" if conf
+ else
+ print "#{$message} #{target}\n"
+ end
+ $stdout.flush
init_mkmf
Logging::logfile 'mkmf.log'
rm_f makefile
- if File.exist?($0 = "#{$srcdir}/makefile.rb")
- load $0
- elsif File.exist?($0 = "#{$srcdir}/extconf.rb")
- load $0
+ if conf
+ Logging.open do
+ unless verbose?
+ $stderr.reopen($stdout.reopen(@null))
+ end
+ load $0 = conf
+ end
else
create_makefile(target)
end
@@ -146,52 +231,75 @@ def extmake(target)
end
rescue SystemExit
# ignore
+ rescue => error
+ ok = false
ensure
rm_f "conftest*"
- config = $0
$0 = $PROGRAM_NAME
end
end
- ok = yield(ok) if block_given?
+ ok &&= File.open(makefile){|f| s = f.gets and !s[DUMMY_SIGNATURE]}
unless ok
- open(makefile, "w") do |f|
- f.print dummy_makefile(CONFIG["srcdir"])
+ mf = ["# #{DUMMY_SIGNATURE}\n", *dummy_makefile(CONFIG["srcdir"])].join("")
+ atomic_write_open(makefile) do |f|
+ f.print(mf)
end
- return true
- end
- args = sysquote($mflags)
- unless $destdir.to_s.empty? or $mflags.include?("DESTDIR")
- args += [sysquote("DESTDIR=" + relative_from($destdir, "../"+prefix))]
- end
- if $static
- args += ["static"] unless $clean
- $extlist.push [$static, $target, File.basename($target), $preload]
+
+ return true if !error and target.start_with?("-")
+
+ message = nil
+ if error
+ loc = error.backtrace_locations[0]
+ message = "#{loc.absolute_path}:#{loc.lineno}: #{error.message}"
+ if Logging.log_opened?
+ Logging::message("#{message}\n\t#{error.backtrace.join("\n\t")}\n")
+ end
+ end
+
+ return [parent, message]
end
- unless system($make, *args)
- $ignore or $continue or return false
+ args = $mflags
+ unless $destdir.to_s.empty? or $mflags.defined?("DESTDIR")
+ args += ["DESTDIR=" + relative_from($destdir, "../"+prefix)]
end
- $compiled[target] = true
- if $clean and $clean != true
- File.unlink(makefile) rescue nil
+ $objs ||= []
+ $srcs ||= []
+ if $static and ok and !$objs.empty? and !noinstall
+ args += ["static"]
+ $extlist.push [(maybestatic ? $static : false), target, $target, $preload]
end
+ FileUtils.rm_f(old_cleanfiles - $distcleanfiles - $cleanfiles)
+ FileUtils.rm_f(old_objs - $objs)
if $static
$extflags ||= ""
$extlibs ||= []
$extpath ||= []
unless $mswin
- $extflags = ($extflags.split | $DLDFLAGS.split | $LDFLAGS.split).join(" ")
+ $extflags = split_libs($extflags, $DLDFLAGS, $LDFLAGS).uniq.join(" ")
end
- $extlibs = merge_libs($extlibs, $libs.split, $LOCAL_LIBS.split)
+ $extlibs = merge_libs($extlibs, split_libs($libs, $LOCAL_LIBS).map {|lib| lib.sub(/\A\.\//, "ext/#{target}/")})
$extpath |= $LIBPATH
end
ensure
- Config::CONFIG["srcdir"] = $top_srcdir
- Config::CONFIG["topdir"] = topdir
- CONFIG["srcdir"] = mk_srcdir
- CONFIG["topdir"] = mk_topdir
- CONFIG.delete("hdrdir")
- $hdrdir = $top_srcdir = top_srcdir
+ Logging::log_close
+ if rbconfig0
+ RbConfig.module_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, rbconfig0)
+ remove_const(:MAKEFILE_CONFIG)
+ const_set(:MAKEFILE_CONFIG, mkconfig0)
+ }
+ end
+ if mkconfig0
+ MakeMakefile.class_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, mkconfig0)
+ }
+ end
+ $top_srcdir = top_srcdir
$topdir = topdir
+ $hdrdir = hdrdir
+ $static = static
Dir.chdir dir
end
begin
@@ -203,14 +311,10 @@ def extmake(target)
true
end
-def compiled?(target)
- $compiled[target]
-end
-
def parse_args()
$mflags = []
+ $makeflags = [] # for make command to build ruby, so quoted
- opts = nil
$optparser ||= OptionParser.new do |opts|
opts.on('-n') {$dryrun = true}
opts.on('--[no-]extension [EXTS]', Array) do |v|
@@ -238,19 +342,30 @@ def parse_args()
if arg = v.first
arg.insert(0, '-') if /\A[^-][^=]*\Z/ =~ arg
end
+ $makeflags.concat(v.reject {|arg2| /\AMINIRUBY=/ =~ arg2}.quote)
$mflags.concat(v)
end
opts.on('--message [MESSAGE]', String) do |v|
$message = v
end
+ opts.on('--command-output=FILE', String) do |v|
+ $command_output = v
+ end
+ opts.on('--gnumake=yes|no', true) do |v|
+ $gnumake = v
+ end
+ opts.on('--extflags=FLAGS') do |v|
+ $extflags = v || ""
+ end
end
begin
$optparser.parse!(ARGV)
rescue OptionParser::InvalidOption => e
retry if /^--/ =~ e.args[0]
$optparser.warn(e)
- abort opts.to_s
+ abort $optparser.to_s
end
+ $command_output or abort "--command-output option is mandatory"
$destdir ||= ''
@@ -258,7 +373,7 @@ def parse_args()
$mflags.unshift(*rest) unless rest.empty?
def $mflags.set?(flag)
- grep(/\A-(?!-).*#{'%c' % flag}/i) { return true }
+ grep(/\A-(?!-).*#{flag.chr}/i) { return true }
false
end
def $mflags.defined?(var)
@@ -275,6 +390,7 @@ def parse_args()
$continue = $mflags.set?(?k)
if $extout
$extout = '$(topdir)/'+$extout
+ RbConfig::CONFIG["extout"] = CONFIG["extout"] = $extout
$extout_prefix = $extout ? "$(extout)$(target_prefix)/" : ""
$mflags << "extout=#$extout" << "extout_prefix=#$extout_prefix"
end
@@ -284,22 +400,16 @@ parse_args()
if target = ARGV.shift and /^[a-z-]+$/ =~ target
$mflags.push(target)
- target = target.sub(/^(dist|real)(?=(?:clean)?$)/, '')
case target
- when /clean/
- $ignore ||= true
- $clean = $1 ? $1[0] : true
- when /^install\b/
- $install = true
- $ignore ||= true
- $mflags.unshift("INSTALL_PROG=install -c -p -m 0755",
- "INSTALL_DATA=install -c -p -m 0644",
- "MAKEDIRS=mkdir -p") if $dryrun
+ when /^(dist|real)?(clean)$/, /^install\b/
+ abort "#{target} is obsolete"
+ when /configure/
+ $subconfigure = !ARGV.empty?
end
end
unless $message
if target
- $message = target.sub(/^(\w+)e?\b/, '\1ing').tr('-', ' ')
+ $message = target.sub(/^(\w+?)e?\b/, '\1ing').tr('-', ' ')
else
$message = "compiling"
end
@@ -307,30 +417,41 @@ end
EXEEXT = CONFIG['EXEEXT']
if CROSS_COMPILING
- $ruby = CONFIG['MINIRUBY']
+ $ruby = $mflags.defined?("MINIRUBY") || CONFIG['MINIRUBY']
elsif sep = config_string('BUILD_FILE_SEPARATOR')
$ruby = "$(topdir:/=#{sep})#{sep}miniruby" + EXEEXT
-else
+elsif CONFIG['EXTSTATIC']
$ruby = '$(topdir)/miniruby' + EXEEXT
+else
+ $ruby = '$(topdir)/ruby' + EXEEXT
+end
+$ruby = [$ruby]
+$ruby << "-I'$(topdir)'"
+unless CROSS_COMPILING
+ $ruby << "-I'$(top_srcdir)/lib'"
+ $ruby << "-I'$(extout)/$(arch)'" << "-I'$(extout)/common'" if $extout
+ ENV["RUBYLIB"] = "-"
end
-$ruby << " -I'$(topdir)' -I'$(hdrdir)/lib'"
-$config_h = '$(topdir)/config.h'
+topruby = $ruby
+$ruby = topruby.join(' ')
+$mflags << "ruby=#$ruby"
+$builtruby = '$(topdir)/miniruby' + EXEEXT # Must be an executable path
MTIMES = [__FILE__, 'rbconfig.rb', srcdir+'/lib/mkmf.rb'].collect {|f| File.mtime(f)}
# get static-link modules
$static_ext = {}
if $extstatic
- $extstatic.each do |target|
- target = target.downcase if /mswin32|bccwin32/ =~ RUBY_PLATFORM
+ $extstatic.each do |t|
+ target = t
+ target = target.downcase if File::FNM_SYSCASE.nonzero?
$static_ext[target] = $static_ext.size
end
end
for dir in ["ext", File::join($top_srcdir, "ext")]
setup = File::join(dir, CONFIG['setup'])
- if File.file? setup
- f = open(setup)
- while line = f.gets()
+ if (f = File.stat(setup) and f.file? rescue next)
+ File.foreach(setup) do |line|
line.chomp!
line.sub!(/#.*$/, '')
next if /^\s*$/ =~ line
@@ -342,158 +463,415 @@ for dir in ["ext", File::join($top_srcdir, "ext")]
end
next
end
- target = target.downcase if /mswin32|bccwin32/ =~ RUBY_PLATFORM
+ target = target.downcase if File::FNM_SYSCASE.nonzero?
$static_ext[target] = $static_ext.size
end
MTIMES << f.mtime
$setup = setup
- f.close
break
end
end unless $extstatic
-ext_prefix = "#{$top_srcdir}/ext"
-exts = $static_ext.sort_by {|t, i| i}.collect {|t, i| t}
-if $extension
- exts |= $extension.select {|d| File.directory?("#{ext_prefix}/#{d}")}
-else
- withes, withouts = %w[--with --without].collect {|w|
- if not (w = %w[-extensions -ext].collect {|opt|arg_config(w+opt)}).any?
- proc {false}
- elsif (w = w.grep(String)).empty?
- proc {true}
- else
- w.collect {|opt| opt.split(/,/)}.flatten.method(:any?)
+@gemname = nil
+if exts = ARGV.shift
+ ext_prefix = exts[%r[\A(?>\.bundle/)?[^/]+(?:/(?=(.+)?)|\z)]]
+ exts = $1
+ $extension = [exts] if exts
+ if ext_prefix.start_with?('.')
+ @gemname = exts
+ exts = []
+ else
+ exts &&= $static_ext.select {|t, *| File.fnmatch(t, exts)}
+ end
+end
+ext_prefix ||= 'ext'
+exts = (exts || $static_ext).sort_by {|t, i| i}.collect {|t, i| t}
+default_exclude_exts =
+ case
+ when $cygwin
+ %w''
+ when $mswin, $mingw
+ %w'pty syslog'
+ else
+ %w'*win32*'
+ end
+mandatory_exts = {}
+withes, withouts = [["--with", nil], ["--without", default_exclude_exts]].collect {|w, d|
+ if !(w = %w[-extensions -ext].collect {|o|arg_config(w+o)}).any?
+ d ? proc {|&c1| d.any?(&c1)} : proc {true}
+ elsif (w = w.grep(String)).empty?
+ proc {true}
+ else
+ w = w.collect {|o| o.split(/,/)}.flatten
+ w.collect! {|o| o == '+' ? d : o}.flatten!
+ proc {|&c1| w.any?(&c1)}
+ end
+}
+cond = proc {|ext, *|
+ withes.call {|n| !n or (mandatory_exts[ext] = true if File.fnmatch(n, ext))} and
+ !withouts.call {|n| File.fnmatch(n, ext)}
+}
+($extension || %w[*]).each do |e|
+ e = e.sub(/\A(?:\.\/)+/, '')
+ incl, excl = Dir.glob("#{e}/**/extconf.rb", base: "#$top_srcdir/#{ext_prefix}").collect {|d|
+ File.dirname(d)
+ }.partition {|ext|
+ if @gemname
+ ext = ext[%r[\A[^/]+]] # extract gem name
+ Dir.glob("*.gemspec", base: "#$top_srcdir/#{ext_prefix}/#{ext}") do |g|
+ break ext = g if ext.start_with?("#{g.chomp!(".gemspec")}-")
+ end
end
- }
- cond = proc {|ext|
- cond1 = proc {|n| File.fnmatch(n, ext, File::FNM_PATHNAME)}
- withes.call(&cond1) or !withouts.call(&cond1)
- }
- exts |= Dir.glob("#{ext_prefix}/*/**/extconf.rb").collect {|d|
- d = File.dirname(d)
- d.slice!(0, ext_prefix.length + 1)
- d
- }.find_all {|ext|
with_config(ext, &cond)
- }.sort
+ }
+ incl.sort!
+ excl.sort!.collect! {|d| d+"/"}
+ nil while incl.reject! {|d| excl << d+"/" if excl.any? {|x| d.start_with?(x)}}
+ exts |= incl
+ if $LIBRUBYARG_SHARED.empty? and CONFIG["EXTSTATIC"] == "static"
+ exts.delete_if {|d| File.fnmatch?("-*", d)}
+ end
end
+ext_prefix.chomp!("/")
+
+@ext_prefix = ext_prefix
+@inplace = inplace
+extend Module.new {
-if $extout
- Config.expand(extout = "#$extout", Config::CONFIG.merge("topdir"=>$topdir))
- if $install
- dest = Config.expand($rubylibdir.dup)
- unless $destdir.empty?
- dest.sub!($dest_prefix_pattern, Config.expand($destdir.dup))
+ def timestamp_file(name, target_prefix = nil)
+ if @gemname and name == '$(TARGET_SO_DIR)'
+ gem = true
+ name = "$(gem_platform)/$(ruby_version)/gems/#{@gemname}#{target_prefix}"
end
- FileUtils.cp_r(extout+"/.", dest, :verbose => true, :noop => $dryrun)
- exit
+ path = super.sub(%r[/\.extout\.(?:-\.)?], '/.')
+ if gem
+ nil while path.sub!(%r[/\.(gem_platform|ruby_version)\.-(?=\.)], '/$(\1)/')
+ end
+ path
end
- unless $ignore
- FileUtils.mkpath(extout)
+
+ def configuration(srcdir)
+ super << "EXTSO #{['=', $extso].join(' ')}\n"
end
-end
+
+ def create_makefile(*args, &block)
+ unless @gemname
+ if $static and (target = args.first).include?("/")
+ base = File.basename(target)
+ $defs << "-DInit_#{base}=Init_#{target.tr('/', '_')}"
+ $defs << "-DInitVM_#{base}=InitVM_#{target.tr('/', '_')}"
+ end
+ return super
+ end
+ super(*args) do |conf|
+ conf.find do |s|
+ s.sub!(%r(^(srcdir *= *)\$\(top_srcdir\)/\.bundle/gems/[^/]+(?=/))) {
+ "gem_#{$&}\n" "#{$1}$(gem_srcdir)"
+ }
+ s.sub!(/^(TIMESTAMP_DIR *= *)\$\(extout\)/) {
+ "TARGET_TOPDIR = $(topdir)/.bundle\n" "#{$1}$(TARGET_TOPDIR)"
+ }
+ s.sub!(/^(TARGET_SO_DIR *= *)\$\(RUBYARCHDIR\)/) {
+ "TARGET_GEM_DIR = $(TARGET_TOPDIR)/extensions/$(gem_platform)"\
+ "/$(ruby_version)#{$enable_shared ? '' : '-static'}/#{@gemname}\n"\
+ "#{$1}$(TARGET_GEM_DIR)$(target_prefix)"
+ }
+ end
+
+ conf = yield conf if block
+
+ if conf.any? {|s| /^TARGET *= *\S/ =~ s}
+ conf << %{
+gem_platform = #{Gem::Platform.local}
+
+# default target
+all:
+
+gem = #{@gemname}
+
+build_complete = $(TARGET_GEM_DIR)/gem.build_complete
+install-so: build_complete
+clean-so:: clean-build_complete
+$(build_complete) $(OBJS): $(TARGET_SO_DIR_TIMESTAMP)
+
+build_complete: $(build_complete)
+$(build_complete): $(TARGET_SO)
+ $(Q) $(TOUCH) $@
+
+clean-build_complete:
+ -$(Q)$(RM) $(build_complete)
+
+install: gemspec
+clean: clean-gemspec
+
+gemspec = $(TARGET_TOPDIR)/specifications/$(gem).gemspec
+$(gemspec): $(gem_srcdir)/.bundled.$(gem).gemspec
+ $(Q) $(MAKEDIRS) $(@D)
+ $(Q) $(COPY) $(gem_srcdir)/.bundled.$(gem).gemspec $@
+
+gemspec: $(gemspec)
+
+clean-gemspec:
+ -$(Q)$(RM) $(gemspec)
+
+LN_S = #{config_string('LN_S')}
+CP_R = #{config_string('CP')} -r
+}
+ unless @inplace
+ %w[bin lib].each do |d|
+ next unless File.directory?("#{$top_srcdir}/#{@ext_prefix}/#{@gemname}/#{d}")
+ conf << %{
+install-rb: gem#{d}
+clean-rb:: clean-gem#{d}
+
+gem#{d} = $(TARGET_TOPDIR)/gems/$(gem)/#{d}
+gem#{d}:#{%{ $(gem#{d})\n$(gem#{d}): $(gem_srcdir)/#{d}} if $nmake}
+ $(Q) $(RUBY) $(top_srcdir)/tool/ln_sr.rb -q -f -T $(gem_srcdir)/#{d} $(gem#{d})
+
+clean-gem#{d}:
+ $(Q) $(RM_RF) $(gem#{d})
+}
+ end
+ end
+ end
+
+ conf
+ end
+ end
+}
dir = Dir.pwd
-FileUtils::makedirs('ext')
-Dir::chdir('ext')
+FileUtils::makedirs(ext_prefix)
+Dir::chdir(ext_prefix)
-$hdrdir = $top_srcdir = relative_from(srcdir, $topdir = "..")
+hdrdir = $hdrdir
+$hdrdir = ($top_srcdir = relative_from(srcdir, $topdir = "..")) + "/include"
+extso = []
+fails = []
exts.each do |d|
- extmake(d) or abort
+ $static = $force_static ? true : $static_ext.fetch(d) do
+ $static_ext.any? {|t, | File.fnmatch?(t, d)}
+ end
+
+ if !$nodynamic or $static
+ result = extmake(d, ext_prefix, !@gemname) or abort
+ extso |= $extso
+ fails << [d, result] unless result == true
+ end
end
-$hdrdir = $top_srcdir = srcdir
+
+$top_srcdir = srcdir
$topdir = "."
+$hdrdir = hdrdir
extinit = Struct.new(:c, :o) {
def initialize(src)
super("#{src}.c", "#{src}.#{$OBJEXT}")
end
}.new("extinit")
-if $ignore
- FileUtils.rm_f(extinit.to_a) if $clean
- Dir.chdir ".."
- if $clean
- Dir.rmdir('ext') rescue nil
- FileUtils.rm_rf(extout) if $extout
- end
- exit
-end
-if $extlist.size > 0
- $extinit ||= ""
- $extobjs ||= ""
+$extobjs ||= []
+$extpath ||= []
+$extflags ||= ""
+$extlibs ||= []
+extinits = []
+unless $extlist.empty?
list = $extlist.dup
built = []
while e = list.shift
- s,t,i,r = e
- if r and !(r -= built).empty?
+ static, target, feature, required = e
+ next unless static
+ if required and !(required -= built).empty?
l = list.size
- if (while l > 0; break true if r.include?(list[l-=1][1]) end)
+ if (while l > 0; break true if required.include?(list[l-=1][1]) end)
list.insert(l + 1, e)
end
next
end
- f = format("%s/%s.%s", s, i, $LIBEXT)
- if File.exist?(f)
- $extinit += "\tinit(Init_#{i}, \"#{t}.so\");\n"
- $extobjs += "ext/#{f} "
- built << t
- end
+ base = File.basename(feature)
+ extinits << feature
+ $extobjs << format("ext/%s/%s.%s", target, base, $LIBEXT)
+ built << target
end
- src = %{\
-extern char *ruby_sourcefile, *rb_source_filename();
-#define init(func, name) (ruby_sourcefile = src = rb_source_filename(name), func(), rb_provide(src))
-void Init_ext() {\n\tchar* src;\n#$extinit}
-}
- if !modified?(extinit.c, MTIMES) || IO.read(extinit.c) != src
- open(extinit.c, "w") {|f| f.print src}
- end
-
- $extobjs = "ext/#{extinit.o} " + $extobjs
- if RUBY_PLATFORM =~ /m68k-human|beos/
- $extflags.delete("-L/usr/local/lib")
- end
$extpath.delete("$(topdir)")
$extflags = libpathflag($extpath) << " " << $extflags.strip
conf = [
+ ['LIBRUBY_SO_UPDATE', '$(LIBRUBY_EXTS)'],
['SETUP', $setup],
- [enable_config("shared", $enable_shared) ? 'DLDOBJS' : 'EXTOBJS', $extobjs],
['EXTLIBS', $extlibs.join(' ')], ['EXTLDFLAGS', $extflags]
].map {|n, v|
- "#{n}=#{v}" if v and !(v = v.strip).empty?
+ "#{n}=#{v}" if v &&= v[/\S(?:.*\S)?/]
}.compact
- puts conf
+ puts(*conf) unless $subconfigure
$stdout.flush
$mflags.concat(conf)
+ $makeflags.concat(conf)
else
FileUtils.rm_f(extinit.to_a)
end
rubies = []
-%w[RUBY RUBYW STATIC_RUBY].each {|r|
- n = r
+%w[RUBY RUBYW STATIC_RUBY].each {|n|
+ r = n
if r = arg_config("--"+r.downcase) || config_string(r+"_INSTALL_NAME")
- rubies << r+EXEEXT
+ rubies << RbConfig.expand(r+=EXEEXT)
$mflags << "#{n}=#{r}"
end
}
-Dir.chdir ".."
+Dir.chdir dir
unless $destdir.to_s.empty?
$mflags.defined?("DESTDIR") or $mflags << "DESTDIR=#{$destdir}"
end
-unless $extlist.empty?
- rm_f(Config::CONFIG["LIBRUBY_SO"])
-end
-puts "making #{rubies.join(', ')}"
-$stdout.flush
-$mflags.concat(rubies)
+$makeflags.uniq!
+
+$mflags.unshift("topdir=#$topdir")
+ENV.delete("RUBYOPT")
+exts.map! {|d| "#{ext_prefix}/#{d}/."}
+FileUtils.makedirs(File.dirname($command_output))
+begin
+ atomic_write_open($command_output) do |mf|
+ mf.puts "V = 0"
+ mf.puts "V0 = $(V:0=)"
+ mf.puts "Q1 = $(V:1=)"
+ mf.puts "Q = $(Q1:0=@)"
+ mf.puts "ECHO1 = $(V:1=@:)"
+ mf.puts "ECHO = $(ECHO1:0=@echo)"
+ mf.puts "MFLAGS = -$(MAKEFLAGS)" if $nmake
+ mf.puts "override MFLAGS := $(filter-out -j%,$(MFLAGS))" if $gnumake
+ mf.puts "ext_build_dir = #{File.dirname($command_output)}"
+ mf.puts
+
+ def mf.macro(name, values, max = 70)
+ print name, " ="
+ w = w0 = name.size + 2
+ h = " \\\n" + "\t" * (w / 8) + " " * (w % 8)
+ values.each do |s|
+ if s.size + w > max
+ print h
+ w = w0
+ end
+ print " ", s
+ w += s.size + 1
+ end
+ puts
+ end
-if $nmake == ?b
- $mflags.collect {|flag| flag.sub!(/\A(?=\w+=)/, "-D")}
+ mf.macro "ruby", topruby
+ mf.macro "RUBY", ["$(ruby)"]
+ mf.macro "extensions", exts
+ mf.macro "EXTOBJS", $extlist.empty? ? ["dmyext.#{$OBJEXT}"] : ["ext/extinit.#{$OBJEXT}", *$extobjs]
+ mf.macro "EXTLIBS", $extlibs
+ mf.macro "EXTSO", extso
+ mf.macro "EXTLDFLAGS", $extflags.split
+ mf.macro "EXTINITS", extinits
+ submakeopts = []
+ if enable_config("shared", $enable_shared)
+ submakeopts << 'DLDOBJS="$(EXTOBJS) $(EXTENCS)"'
+ submakeopts << 'EXTOBJS='
+ submakeopts << 'EXTSOLIBS="$(EXTLIBS)"'
+ submakeopts << 'LIBRUBY_SO_UPDATE=$(LIBRUBY_EXTS)'
+ else
+ submakeopts << 'EXTOBJS="$(EXTOBJS) $(EXTENCS)"'
+ submakeopts << 'EXTLIBS="$(EXTLIBS)"'
+ end
+ submakeopts << 'EXTLDFLAGS="$(EXTLDFLAGS)"'
+ submakeopts << 'EXTINITS="$(EXTINITS)"'
+ submakeopts << 'SHOWFLAGS='
+ mf.macro "SUBMAKEOPTS", submakeopts
+ mf.macro "NOTE_MESG", %w[$(RUBY) $(top_srcdir)/tool/lib/colorize.rb skip]
+ mf.macro "NOTE_NAME", %w[$(RUBY) $(top_srcdir)/tool/lib/colorize.rb fail]
+ %w[RM RMDIRS RMDIR RMALL].each {|w| mf.macro w, [RbConfig::CONFIG[w]]}
+ if $nmake
+ message = ['@(for %I in (', ') do @echo.%~I)']
+ else
+ message = ['@for line in', '; do echo "$$line"; done']
+ end
+ mf.macro "MESSAGE_BEGIN", [message.first]
+ mf.macro "MESSAGE_END", [message.last]
+ mf.puts
+ targets = %w[all install static install-so install-rb clean distclean realclean]
+ targets.each do |tgt|
+ mf.puts "#{tgt}: $(extensions:/.=/#{tgt})"
+ mf.puts "#{tgt}: note" unless /clean\z/ =~ tgt
+ end
+ mf.puts
+ mf.puts "clean:\n\t-$(Q)$(RM) ext/extinit.#{$OBJEXT}"
+ mf.puts "distclean:\n\t-$(Q)$(RM) ext/extinit.c"
+ mf.puts
+ mf.puts "#{rubies.join(' ')}: $(extensions:/.=/#{$force_static ? 'static' : 'all'})"
+ submake = "$(Q)$(MAKE) $(MFLAGS) $(SUBMAKEOPTS)"
+ mf.puts "all static: #{rubies.join(' ')}\n"
+ $extobjs.each do |tgt|
+ mf.puts "#{tgt}: #{File.dirname(tgt)}/static"
+ end
+ mf.puts "#{rubies.join(' ')}: $(EXTOBJS)#{' libencs' if CONFIG['ENCSTATIC'] == 'static'}"
+ rubies.each do |tgt|
+ mf.puts "#{tgt}:\n\t#{submake} $@"
+ end
+ mf.puts "libencs:\n\t$(Q)$(MAKE) -f enc.mk V=$(V) $@"
+ mf.puts "ext/extinit.#{$OBJEXT}:\n\t$(Q)$(MAKE) $(MFLAGS) V=$(V) EXTINITS=\"$(EXTINITS)\" $@" if $static
+ mf.puts
+ if $gnumake == "yes"
+ submake = "$(MAKE) -C $(@D)"
+ else
+ submake = ["cd", (sep ? "$(@D:/=#{sep})" : "$(@D)"), "&&"]
+ config_string("exec") {|str| submake << str}
+ submake = (submake << "$(MAKE)").join(" ")
+ end
+ targets.each do |tgt|
+ exts.each do |d|
+ d = d[0..-2]
+ t = "#{d}#{tgt}"
+ if clean = /^(dist|real)?clean$/.match(tgt)
+ deps = exts.select {|e|e.start_with?(d)}.map {|e|"#{e[0..-2]}#{tgt}"} - [t]
+ pd = [' clean-local', *deps].join(' ')
+ else
+ pext = File.dirname(d)
+ pd = " #{pext}/#{tgt}" if exts.include?("#{pext}/.")
+ end
+ mf.puts "#{t}:#{pd}\n\t$(Q)#{submake} $(MFLAGS) V=$(V) $(@F)"
+ if clean and clean.begin(1)
+ mf.puts "\t$(Q)$(RM) $(ext_build_dir)/exts.mk\n\t$(Q)$(RMDIRS) $(@D)"
+ end
+ end
+ end
+ mf.puts "\n""clean-local:\n\t$(Q)$(RM) $(ext_build_dir)/*~ $(ext_build_dir)/*.bak $(ext_build_dir)/core"
+ mf.puts "\n""extso:\n"
+ mf.puts "\t@echo EXTSO=$(EXTSO)"
+
+ mf.puts "\n""note:\n"
+ unless fails.empty?
+ abandon = false
+ mf.puts "note: note-body\n"
+ mf.puts "note-body:: note-header\n"
+ mf.puts "note-header:\n"
+ mf.puts %Q<\t@$(NOTE_MESG) "*** Following extensions are not compiled:">
+ mf.puts "note-body:: note-header\n"
+ fails.each do |ext, (parent, err)|
+ abandon ||= mandatory_exts[ext]
+ mf.puts %Q<\t@$(NOTE_NAME) "#{ext}:">
+ mf.puts "\t$(MESSAGE_BEGIN) \\"
+ if parent
+ mf.puts %Q<\t"\tCould not be configured. It will not be installed." \\>
+ err and err.scan(/.+/) do |ee|
+ mf.puts %Q<\t"\t#{ee.gsub(/["`$^]/, '\\\\\\&')}" \\>
+ end
+ mf.puts %Q<\t"\tCheck #{ext_prefix}/#{ext}/mkmf.log for more details." \\>
+ else
+ mf.puts %Q<\t"\tSkipped because its parent was not configured." \\>
+ end
+ mf.puts "\t$(MESSAGE_END)"
+ end
+ mf.puts "note:\n"
+ mf.puts %Q<\t@$(NOTE_MESG) "*** Fix the problems, then remove these directories and try again if you want.">
+ if abandon
+ mf.puts "\t""@exit 1"
+ end
+ end
+ end
end
-system($make, *sysquote($mflags)) or exit($?.exitstatus)
+# :startdoc:
#Local variables:
# mode: ruby
diff --git a/ext/fcntl/.cvsignore b/ext/fcntl/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/fcntl/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/fcntl/depend b/ext/fcntl/depend
index 10eab64a46..57ea0f2106 100644
--- a/ext/fcntl/depend
+++ b/ext/fcntl/depend
@@ -1 +1,163 @@
-fcntl.o: fcntl.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
+# AUTOGENERATED DEPENDENCIES START
+fcntl.o: $(RUBY_EXTCONF_H)
+fcntl.o: $(arch_hdrdir)/ruby/config.h
+fcntl.o: $(hdrdir)/ruby.h
+fcntl.o: $(hdrdir)/ruby/assert.h
+fcntl.o: $(hdrdir)/ruby/backward.h
+fcntl.o: $(hdrdir)/ruby/backward/2/assume.h
+fcntl.o: $(hdrdir)/ruby/backward/2/attributes.h
+fcntl.o: $(hdrdir)/ruby/backward/2/bool.h
+fcntl.o: $(hdrdir)/ruby/backward/2/inttypes.h
+fcntl.o: $(hdrdir)/ruby/backward/2/limits.h
+fcntl.o: $(hdrdir)/ruby/backward/2/long_long.h
+fcntl.o: $(hdrdir)/ruby/backward/2/stdalign.h
+fcntl.o: $(hdrdir)/ruby/backward/2/stdarg.h
+fcntl.o: $(hdrdir)/ruby/defines.h
+fcntl.o: $(hdrdir)/ruby/intern.h
+fcntl.o: $(hdrdir)/ruby/internal/abi.h
+fcntl.o: $(hdrdir)/ruby/internal/anyargs.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+fcntl.o: $(hdrdir)/ruby/internal/assume.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/artificial.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/cold.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/const.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/error.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/format.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/noalias.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/noinline.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/pure.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/restrict.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/warning.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/weakref.h
+fcntl.o: $(hdrdir)/ruby/internal/cast.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_since.h
+fcntl.o: $(hdrdir)/ruby/internal/config.h
+fcntl.o: $(hdrdir)/ruby/internal/constant_p.h
+fcntl.o: $(hdrdir)/ruby/internal/core.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rarray.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rbasic.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rbignum.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rclass.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rdata.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rfile.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rhash.h
+fcntl.o: $(hdrdir)/ruby/internal/core/robject.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rregexp.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rstring.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rstruct.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+fcntl.o: $(hdrdir)/ruby/internal/ctype.h
+fcntl.o: $(hdrdir)/ruby/internal/dllexport.h
+fcntl.o: $(hdrdir)/ruby/internal/dosish.h
+fcntl.o: $(hdrdir)/ruby/internal/error.h
+fcntl.o: $(hdrdir)/ruby/internal/eval.h
+fcntl.o: $(hdrdir)/ruby/internal/event.h
+fcntl.o: $(hdrdir)/ruby/internal/fl_type.h
+fcntl.o: $(hdrdir)/ruby/internal/gc.h
+fcntl.o: $(hdrdir)/ruby/internal/glob.h
+fcntl.o: $(hdrdir)/ruby/internal/globals.h
+fcntl.o: $(hdrdir)/ruby/internal/has/attribute.h
+fcntl.o: $(hdrdir)/ruby/internal/has/builtin.h
+fcntl.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+fcntl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+fcntl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+fcntl.o: $(hdrdir)/ruby/internal/has/extension.h
+fcntl.o: $(hdrdir)/ruby/internal/has/feature.h
+fcntl.o: $(hdrdir)/ruby/internal/has/warning.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/array.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/bignum.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/class.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/compar.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/complex.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/cont.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/dir.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/enum.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/error.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/eval.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/file.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/hash.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/io.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/load.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/marshal.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/numeric.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/object.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/parse.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/proc.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/process.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/random.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/range.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/rational.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/re.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/ruby.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/select.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/set.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/signal.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/string.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/struct.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/thread.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/time.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/variable.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/vm.h
+fcntl.o: $(hdrdir)/ruby/internal/interpreter.h
+fcntl.o: $(hdrdir)/ruby/internal/iterator.h
+fcntl.o: $(hdrdir)/ruby/internal/memory.h
+fcntl.o: $(hdrdir)/ruby/internal/method.h
+fcntl.o: $(hdrdir)/ruby/internal/module.h
+fcntl.o: $(hdrdir)/ruby/internal/newobj.h
+fcntl.o: $(hdrdir)/ruby/internal/scan_args.h
+fcntl.o: $(hdrdir)/ruby/internal/special_consts.h
+fcntl.o: $(hdrdir)/ruby/internal/static_assert.h
+fcntl.o: $(hdrdir)/ruby/internal/stdalign.h
+fcntl.o: $(hdrdir)/ruby/internal/stdbool.h
+fcntl.o: $(hdrdir)/ruby/internal/stdckdint.h
+fcntl.o: $(hdrdir)/ruby/internal/symbol.h
+fcntl.o: $(hdrdir)/ruby/internal/value.h
+fcntl.o: $(hdrdir)/ruby/internal/value_type.h
+fcntl.o: $(hdrdir)/ruby/internal/variable.h
+fcntl.o: $(hdrdir)/ruby/internal/warning_push.h
+fcntl.o: $(hdrdir)/ruby/internal/xmalloc.h
+fcntl.o: $(hdrdir)/ruby/missing.h
+fcntl.o: $(hdrdir)/ruby/ruby.h
+fcntl.o: $(hdrdir)/ruby/st.h
+fcntl.o: $(hdrdir)/ruby/subst.h
+fcntl.o: fcntl.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/fcntl/extconf.rb b/ext/fcntl/extconf.rb
index 8b717d4a5b..6998f77483 100644
--- a/ext/fcntl/extconf.rb
+++ b/ext/fcntl/extconf.rb
@@ -1,2 +1,3 @@
+# frozen_string_literal: true
require 'mkmf'
create_makefile('fcntl')
diff --git a/ext/fcntl/fcntl.c b/ext/fcntl/fcntl.c
index 57cca103f4..b987e237dd 100644
--- a/ext/fcntl/fcntl.c
+++ b/ext/fcntl/fcntl.c
@@ -14,15 +14,9 @@
fcntl - load the C fcntl.h defines
-= SYNOPSIS
-
- require "fcntl"
- m = s.fcntl(Fcntl::F_GETFL, 0)
- f.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK|m)
-
= DESCRIPTION
-This module is just a translation of the C <fnctl.h> file.
+This module is just a translation of the C <fcntl.h> file.
= NOTE
@@ -34,154 +28,273 @@ pack up your own arguments to pass as args for locking functions, etc.
#include "ruby.h"
#include <fcntl.h>
-/* Fcntl loads the constants defined in the system's <fcntl.h> C header
- * file, and used with both the fcntl(2) and open(2) POSIX system calls.
- *
- * Copyright (C) 1997-2001 Yukihiro Matsumoto
+/*
+ * Document-module: Fcntl
*
- * Documented by mathew <meta@pobox.com>
+ * Fcntl loads the constants defined in the system's <fcntl.h> C header
+ * file, and used with both the fcntl(2) and open(2) POSIX system calls.
*
- * = Usage
- *
- * To perform a fcntl(2) operation, use IO::fcntl in the core classes.
+ * To perform a fcntl(2) operation, use IO::fcntl.
*
* To perform an open(2) operation, use IO::sysopen.
*
- * The set of operations and constants available depends upon specific OS
- * platform. Some values listed below may not be supported on your system.
- *
- * The constants supported by Ruby for use with IO::fcntl are:
- *
- * - F_DUPFD - duplicate a close-on-exec file handle to a non-close-on-exec
- * file handle.
- *
- * - F_GETFD - read the close-on-exec flag of a file handle.
- *
- * - F_SETFD - set the close-on-exec flag of a file handle.
- *
- * - FD_CLOEXEC - the value of the close-on-exec flag.
- *
- * - F_GETFL - get file descriptor flags.
- *
- * - F_SETFL - set file descriptor flags.
- *
- * - O_APPEND, O_NONBLOCK, etc (see below) - file descriptor flag
- * values for the above.
- *
- * - F_GETLK - determine whether a given region of a file is locked.
- *
- * - F_SETLK - acquire a lock on a region of a file.
- *
- * - F_SETLKW - acquire a lock on a region of a file, waiting if necessary.
- *
- * - F_RDLCK, F_WRLCK, F_UNLCK - types of lock for the above.
- *
- * The constants supported by Ruby for use with IO::sysopen are:
- *
- * - O_APPEND - open file in append mode.
- *
- * - O_NOCTTY - open tty without it becoming controlling tty.
- *
- * - O_CREAT - create file if it doesn't exist.
- *
- * - O_EXCL - used with O_CREAT, fail if file exists.
- *
- * - O_TRUNC - truncate file on open.
- *
- * - O_NONBLOCK / O_NDELAY - open in non-blocking mode.
- *
- * - O_RDONLY - open read-only.
+ * The set of operations and constants available depends upon specific
+ * operating system. Some values listed below may not be supported on your
+ * system.
*
- * - O_WRONLY - open write-only.
+ * See your fcntl(2) man page for complete details.
*
- * - O_RDWR - open read-write.
+ * Open /tmp/tempfile as a write-only file that is created if it doesn't
+ * exist:
*
- * - O_ACCMODE - mask to extract read/write flags.
- *
- * Example:
- *
* require 'fcntl'
*
- * fd = IO::sysopen('/tmp/tempfile',
- * Fcntl::O_WRONLY | Fcntl::O_EXCL | Fcntl::O_CREAT)
+ * fd = IO.sysopen('/tmp/tempfile',
+ * Fcntl::O_WRONLY | Fcntl::O_EXCL | Fcntl::O_CREAT)
* f = IO.open(fd)
* f.syswrite("TEMP DATA")
* f.close
*
+ * Get the flags on file +s+:
+ *
+ * m = s.fcntl(Fcntl::F_GETFL, 0)
+ *
+ * Set the non-blocking flag on +f+ in addition to the existing flags in +m+.
+ *
+ * f.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK|m)
+ *
*/
+
+#define FCNTL_VERSION "1.3.0"
+
void
-Init_fcntl()
+Init_fcntl(void)
{
VALUE mFcntl = rb_define_module("Fcntl");
+
+ /* The version string. */
+ rb_define_const(mFcntl, "VERSION", rb_str_new_cstr(FCNTL_VERSION));
+
#ifdef F_DUPFD
+ /*
+ * Duplicate a file descriptor to the minimum unused file descriptor
+ * greater than or equal to the argument.
+ *
+ * The close-on-exec flag of the duplicated file descriptor is set.
+ * (Ruby uses F_DUPFD_CLOEXEC internally if available to avoid race
+ * condition. F_SETFD is used if F_DUPFD_CLOEXEC is not available.)
+ */
rb_define_const(mFcntl, "F_DUPFD", INT2NUM(F_DUPFD));
#endif
#ifdef F_GETFD
+ /*
+ * Read the close-on-exec flag of a file descriptor.
+ */
rb_define_const(mFcntl, "F_GETFD", INT2NUM(F_GETFD));
#endif
#ifdef F_GETLK
+ /*
+ * Determine whether a given region of a file is locked. This uses one of
+ * the F_*LK flags.
+ */
rb_define_const(mFcntl, "F_GETLK", INT2NUM(F_GETLK));
#endif
#ifdef F_SETFD
+ /*
+ * Set the close-on-exec flag of a file descriptor.
+ */
rb_define_const(mFcntl, "F_SETFD", INT2NUM(F_SETFD));
#endif
#ifdef F_GETFL
+ /*
+ * Get the file descriptor flags. This will be one or more of the O_*
+ * flags.
+ */
rb_define_const(mFcntl, "F_GETFL", INT2NUM(F_GETFL));
#endif
#ifdef F_SETFL
+ /*
+ * Set the file descriptor flags. This will be one or more of the O_*
+ * flags.
+ */
rb_define_const(mFcntl, "F_SETFL", INT2NUM(F_SETFL));
#endif
#ifdef F_SETLK
+ /*
+ * Acquire a lock on a region of a file. This uses one of the F_*LCK
+ * flags.
+ */
rb_define_const(mFcntl, "F_SETLK", INT2NUM(F_SETLK));
#endif
#ifdef F_SETLKW
+ /*
+ * Acquire a lock on a region of a file, waiting if necessary. This uses
+ * one of the F_*LCK flags
+ */
rb_define_const(mFcntl, "F_SETLKW", INT2NUM(F_SETLKW));
#endif
#ifdef FD_CLOEXEC
+ /*
+ * the value of the close-on-exec flag.
+ */
rb_define_const(mFcntl, "FD_CLOEXEC", INT2NUM(FD_CLOEXEC));
#endif
#ifdef F_RDLCK
+ /*
+ * Read lock for a region of a file
+ */
rb_define_const(mFcntl, "F_RDLCK", INT2NUM(F_RDLCK));
#endif
#ifdef F_UNLCK
+ /*
+ * Remove lock for a region of a file
+ */
rb_define_const(mFcntl, "F_UNLCK", INT2NUM(F_UNLCK));
#endif
#ifdef F_WRLCK
+ /*
+ * Write lock for a region of a file
+ */
rb_define_const(mFcntl, "F_WRLCK", INT2NUM(F_WRLCK));
#endif
+#ifdef F_SETPIPE_SZ
+ /*
+ * Change the capacity of the pipe referred to by fd to be at least arg bytes.
+ */
+ rb_define_const(mFcntl, "F_SETPIPE_SZ", INT2NUM(F_SETPIPE_SZ));
+#endif
+#ifdef F_GETPIPE_SZ
+ /*
+ * Return (as the function result) the capacity of the pipe referred to by fd.
+ */
+ rb_define_const(mFcntl, "F_GETPIPE_SZ", INT2NUM(F_GETPIPE_SZ));
+#endif
#ifdef O_CREAT
+ /*
+ * Create the file if it doesn't exist
+ */
rb_define_const(mFcntl, "O_CREAT", INT2NUM(O_CREAT));
#endif
#ifdef O_EXCL
+ /*
+ * Used with O_CREAT, fail if the file exists
+ */
rb_define_const(mFcntl, "O_EXCL", INT2NUM(O_EXCL));
#endif
#ifdef O_NOCTTY
+ /*
+ * Open TTY without it becoming the controlling TTY
+ */
rb_define_const(mFcntl, "O_NOCTTY", INT2NUM(O_NOCTTY));
#endif
#ifdef O_TRUNC
+ /*
+ * Truncate the file on open
+ */
rb_define_const(mFcntl, "O_TRUNC", INT2NUM(O_TRUNC));
#endif
#ifdef O_APPEND
+ /*
+ * Open the file in append mode
+ */
rb_define_const(mFcntl, "O_APPEND", INT2NUM(O_APPEND));
#endif
#ifdef O_NONBLOCK
+ /*
+ * Open the file in non-blocking mode
+ */
rb_define_const(mFcntl, "O_NONBLOCK", INT2NUM(O_NONBLOCK));
#endif
#ifdef O_NDELAY
+ /*
+ * Open the file in non-blocking mode
+ */
rb_define_const(mFcntl, "O_NDELAY", INT2NUM(O_NDELAY));
#endif
#ifdef O_RDONLY
+ /*
+ * Open the file in read-only mode
+ */
rb_define_const(mFcntl, "O_RDONLY", INT2NUM(O_RDONLY));
#endif
#ifdef O_RDWR
+ /*
+ * Open the file in read-write mode
+ */
rb_define_const(mFcntl, "O_RDWR", INT2NUM(O_RDWR));
#endif
#ifdef O_WRONLY
+ /*
+ * Open the file in write-only mode.
+ */
rb_define_const(mFcntl, "O_WRONLY", INT2NUM(O_WRONLY));
#endif
-#ifdef O_ACCMODE
+#ifndef O_ACCMODE
+ int O_ACCMODE = (O_RDONLY | O_WRONLY | O_RDWR);
+#endif
+ /*
+ * Mask to extract the read/write flags
+ */
rb_define_const(mFcntl, "O_ACCMODE", INT2FIX(O_ACCMODE));
-#else
- rb_define_const(mFcntl, "O_ACCMODE", INT2FIX(O_RDONLY | O_WRONLY | O_RDWR));
+#ifdef F_DUP2FD
+ /*
+ * It is a FreeBSD specific constant and equivalent
+ * to dup2 call.
+ */
+ rb_define_const(mFcntl, "F_DUP2FD", INT2NUM(F_DUP2FD));
+#endif
+#ifdef F_DUP2FD_CLOEXEC
+ /*
+ * It is a FreeBSD specific constant and acts
+ * similarly as F_DUP2FD but set the FD_CLOEXEC
+ * flag in addition.
+ */
+ rb_define_const(mFcntl, "F_DUP2FD_CLOEXEC", INT2NUM(F_DUP2FD_CLOEXEC));
+#endif
+
+#ifdef F_PREALLOCATE
+ /*
+ * macOS specific flag used for preallocating file space.
+ */
+ rb_define_const(mFcntl, "F_PREALLOCATE", INT2NUM(F_PREALLOCATE));
+#endif
+
+#ifdef F_ALLOCATECONTIG
+ /*
+ * macOS specific flag used with F_PREALLOCATE for allocating contiguous
+ * space.
+ */
+ rb_define_const(mFcntl, "F_ALLOCATECONTIG", INT2NUM(F_ALLOCATECONTIG));
+#endif
+
+#ifdef F_ALLOCATEALL
+ /*
+ * macOS specific flag used with F_PREALLOCATE for allocating all contiguous
+ * space or no space.
+ */
+ rb_define_const(mFcntl, "F_ALLOCATEALL", INT2NUM(F_ALLOCATEALL));
+#endif
+
+#ifdef F_ALLOCATEPERSIST
+ /*
+ * macOS specific flag used with F_PREALLOCATE. Allocate space that is not
+ * freed when close is called.
+ */
+ rb_define_const(mFcntl, "F_ALLOCATEPERSIST", INT2NUM(F_ALLOCATEPERSIST));
+#endif
+
+#ifdef F_PEOFPOSMODE
+ /*
+ * macOS specific flag used with F_PREALLOCATE. Allocate from the physical
+ * end of file
+ */
+ rb_define_const(mFcntl, "F_PEOFPOSMODE", INT2NUM(F_PEOFPOSMODE));
+#endif
+
+#ifdef F_VOLPOSMODE
+ /*
+ * macOS specific flag used with F_PREALLOCATE. Allocate from the volume offset.
+ */
+ rb_define_const(mFcntl, "F_VOLPOSMODE", INT2NUM(F_VOLPOSMODE));
#endif
}
diff --git a/ext/fcntl/fcntl.gemspec b/ext/fcntl/fcntl.gemspec
new file mode 100644
index 0000000000..613a90d1ae
--- /dev/null
+++ b/ext/fcntl/fcntl.gemspec
@@ -0,0 +1,32 @@
+# coding: utf-8
+# frozen_string_literal: true
+
+source_version = ["", "ext/fcntl/"].find do |dir|
+ begin
+ break File.open(File.join(__dir__, "#{dir}fcntl.c")) {|f|
+ f.gets("\n#define FCNTL_VERSION ")
+ f.gets[/\s*"(.+)"/, 1]
+ }
+ rescue Errno::ENOENT
+ end
+end
+
+Gem::Specification.new do |spec|
+ spec.name = "fcntl"
+ spec.version = source_version
+ spec.authors = ["Yukihiro Matsumoto"]
+ spec.email = ["matz@ruby-lang.org"]
+
+ spec.summary = "Loads constants defined in the OS fcntl.h C header file"
+ spec.description = "Loads constants defined in the OS fcntl.h C header file"
+ spec.homepage = "https://github.com/ruby/fcntl"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.files = ["ext/fcntl/extconf.rb", "ext/fcntl/fcntl.c"]
+ spec.extra_rdoc_files = [".document", ".rdoc_options", "BSDL", "COPYING", "README.md"]
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+ spec.extensions = "ext/fcntl/extconf.rb"
+ spec.required_ruby_version = ">= 2.5.0"
+end
diff --git a/ext/gdbm/.cvsignore b/ext/gdbm/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/gdbm/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/gdbm/README b/ext/gdbm/README
deleted file mode 100644
index df7a261c68..0000000000
--- a/ext/gdbm/README
+++ /dev/null
@@ -1 +0,0 @@
-gdbm ext-library for Ruby 1.3 or later
diff --git a/ext/gdbm/depend b/ext/gdbm/depend
deleted file mode 100644
index c080a81619..0000000000
--- a/ext/gdbm/depend
+++ /dev/null
@@ -1 +0,0 @@
-gdbm.o: gdbm.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/gdbm/extconf.rb b/ext/gdbm/extconf.rb
deleted file mode 100644
index 5a09492e5e..0000000000
--- a/ext/gdbm/extconf.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require 'mkmf'
-
-dir_config("gdbm")
-if have_library("gdbm", "gdbm_open") and
- have_header("gdbm.h")
- create_makefile("gdbm")
-end
diff --git a/ext/gdbm/gdbm.c b/ext/gdbm/gdbm.c
deleted file mode 100644
index d50cb91eed..0000000000
--- a/ext/gdbm/gdbm.c
+++ /dev/null
@@ -1,1022 +0,0 @@
-/************************************************
-
- gdbm.c -
-
- $Author$
- $Date$
- modified at: Mon Jan 24 15:59:52 JST 1994
-
-************************************************/
-
-#include "ruby.h"
-
-#include <gdbm.h>
-#include <fcntl.h>
-#include <errno.h>
-
-static VALUE rb_cGDBM, rb_eGDBMError, rb_eGDBMFatalError;
-
-#define RUBY_GDBM_RW_BIT 0x20000000
-
-#define MY_BLOCK_SIZE (2048)
-#define MY_FATAL_FUNC rb_gdbm_fatal
-static void
-rb_gdbm_fatal(msg)
- char *msg;
-{
- rb_raise(rb_eGDBMFatalError, msg);
-}
-
-struct dbmdata {
- int di_size;
- GDBM_FILE di_dbm;
-};
-
-static void
-closed_dbm()
-{
- rb_raise(rb_eRuntimeError, "closed GDBM file");
-}
-
-#define GetDBM(obj, dbmp) do {\
- Data_Get_Struct(obj, struct dbmdata, dbmp);\
- if (dbmp == 0) closed_dbm();\
- if (dbmp->di_dbm == 0) closed_dbm();\
-} while (0)
-
-#define GetDBM2(obj, data, dbm) {\
- GetDBM(obj, data);\
- (dbm) = dbmp->di_dbm;\
-}
-
-static void
-free_dbm(dbmp)
- struct dbmdata *dbmp;
-{
- if (dbmp) {
- if (dbmp->di_dbm) gdbm_close(dbmp->di_dbm);
- free(dbmp);
- }
-}
-
-static VALUE
-fgdbm_close(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
-
- GetDBM(obj, dbmp);
- gdbm_close(dbmp->di_dbm);
- dbmp->di_dbm = 0;
-
- return Qnil;
-}
-
-static VALUE
-fgdbm_closed(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
-
- Data_Get_Struct(obj, struct dbmdata, dbmp);
- if (dbmp == 0)
- return Qtrue;
- if (dbmp->di_dbm == 0)
- return Qtrue;
-
- return Qfalse;
-}
-
-static VALUE fgdbm_s_alloc _((VALUE));
-
-static VALUE
-fgdbm_s_alloc(klass)
- VALUE klass;
-{
- return Data_Wrap_Struct(klass, 0, free_dbm, 0);
-}
-
-static VALUE
-fgdbm_initialize(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE file, vmode, vflags;
- GDBM_FILE dbm;
- struct dbmdata *dbmp;
- int mode, flags = 0;
-
- if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
- mode = 0666; /* default value */
- }
- else if (NIL_P(vmode)) {
- mode = -1; /* return nil if DB not exist */
- }
- else {
- mode = NUM2INT(vmode);
- }
-
- if (!NIL_P(vflags))
- flags = NUM2INT(vflags);
-
- SafeStringValue(file);
-
- if (flags & RUBY_GDBM_RW_BIT) {
- flags &= ~RUBY_GDBM_RW_BIT;
- dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
- flags, mode, MY_FATAL_FUNC);
- }
- else {
- dbm = 0;
- if (mode >= 0)
- dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
- GDBM_WRCREAT|flags, mode, MY_FATAL_FUNC);
- if (!dbm)
- dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
- GDBM_WRITER|flags, 0, MY_FATAL_FUNC);
- if (!dbm)
- dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
- GDBM_READER|flags, 0, MY_FATAL_FUNC);
- }
-
- if (!dbm) {
- if (mode == -1) return Qnil;
-
- if (gdbm_errno == GDBM_FILE_OPEN_ERROR ||
- gdbm_errno == GDBM_CANT_BE_READER ||
- gdbm_errno == GDBM_CANT_BE_WRITER)
- rb_sys_fail(RSTRING(file)->ptr);
- else
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
- }
-
- dbmp = ALLOC(struct dbmdata);
- free_dbm(DATA_PTR(obj));
- DATA_PTR(obj) = dbmp;
- dbmp->di_dbm = dbm;
- dbmp->di_size = -1;
-
- return obj;
-}
-
-static VALUE
-fgdbm_s_open(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
-
- if (NIL_P(fgdbm_initialize(argc, argv, obj))) {
- return Qnil;
- }
-
- if (rb_block_given_p()) {
- return rb_ensure(rb_yield, obj, fgdbm_close, obj);
- }
-
- return obj;
-}
-
-static VALUE
-rb_gdbm_fetch(dbm, key)
- GDBM_FILE dbm;
- datum key;
-{
- datum val;
- VALUE str;
-
- val = gdbm_fetch(dbm, key);
- if (val.dptr == 0)
- return Qnil;
-
- str = rb_obj_alloc(rb_cString);
- RSTRING(str)->len = val.dsize;
- RSTRING(str)->aux.capa = val.dsize;
- RSTRING(str)->ptr = REALLOC_N(val.dptr,char,val.dsize+1);
- RSTRING(str)->ptr[val.dsize] = '\0';
-
- OBJ_TAINT(str);
- return (VALUE)str;
-}
-
-static VALUE
-rb_gdbm_fetch2(dbm, keystr)
- GDBM_FILE dbm;
- VALUE keystr;
-{
- datum key;
-
- StringValue(keystr);
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
-
- return rb_gdbm_fetch(dbm, key);
-}
-
-static VALUE
-rb_gdbm_fetch3(obj, keystr)
- VALUE obj, keystr;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
-
- GetDBM2(obj, dbmp, dbm);
- return rb_gdbm_fetch2(dbm, keystr);
-}
-
-static VALUE
-rb_gdbm_firstkey(dbm)
- GDBM_FILE dbm;
-{
- datum key;
- VALUE str;
-
- key = gdbm_firstkey(dbm);
- if (key.dptr == 0)
- return Qnil;
-
- str = rb_obj_alloc(rb_cString);
- RSTRING(str)->len = key.dsize;
- RSTRING(str)->aux.capa = key.dsize;
- RSTRING(str)->ptr = REALLOC_N(key.dptr,char,key.dsize+1);
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
-
- OBJ_TAINT(str);
- return str;
-}
-
-static VALUE
-rb_gdbm_nextkey(dbm, keystr)
- GDBM_FILE dbm;
- VALUE keystr;
-{
- datum key, key2;
- VALUE str;
-
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
- key2 = gdbm_nextkey(dbm, key);
- if (key2.dptr == 0)
- return Qnil;
-
- str = rb_obj_alloc(rb_cString);
- RSTRING(str)->len = key2.dsize;
- RSTRING(str)->aux.capa = key2.dsize;
- RSTRING(str)->ptr = REALLOC_N(key2.dptr,char,key2.dsize+1);
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
-
- OBJ_TAINT(str);
- return str;
-}
-
-static VALUE
-fgdbm_fetch(obj, keystr, ifnone)
- VALUE obj, keystr, ifnone;
-{
- VALUE valstr;
-
- valstr = rb_gdbm_fetch3(obj, keystr);
- if (NIL_P(valstr)) {
- if (ifnone == Qnil && rb_block_given_p())
- return rb_yield(keystr);
- return ifnone;
- }
- return valstr;
-}
-
-static VALUE
-fgdbm_aref(obj, keystr)
- VALUE obj, keystr;
-{
- return rb_gdbm_fetch3(obj, keystr);
-}
-
-static VALUE
-fgdbm_fetch_m(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE keystr, valstr, ifnone;
-
- rb_scan_args(argc, argv, "11", &keystr, &ifnone);
- valstr = fgdbm_fetch(obj, keystr, ifnone);
- if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
- rb_raise(rb_eIndexError, "key not found");
-
- return valstr;
-}
-
-static VALUE
-fgdbm_index(obj, valstr)
- VALUE obj, valstr;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- VALUE keystr, valstr2;
-
- StringValue(valstr);
- GetDBM2(obj, dbmp, dbm);
- for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
- keystr = rb_gdbm_nextkey(dbm, keystr)) {
-
- valstr2 = rb_gdbm_fetch2(dbm, keystr);
- if (!NIL_P(valstr2) &&
- RSTRING(valstr)->len == RSTRING(valstr2)->len &&
- memcmp(RSTRING(valstr)->ptr, RSTRING(valstr2)->ptr,
- RSTRING(valstr)->len) == 0) {
- return keystr;
- }
- }
- return Qnil;
-}
-
-static VALUE
-fgdbm_indexes(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE new;
- int i;
-
- new = rb_ary_new2(argc);
- for (i=0; i<argc; i++) {
- rb_ary_push(new, rb_gdbm_fetch3(obj, argv[i]));
- }
-
- return new;
-}
-
-static VALUE
-fgdbm_select(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE new = rb_ary_new2(argc);
- int i;
-
- if (rb_block_given_p()) {
- GDBM_FILE dbm;
- struct dbmdata *dbmp;
- VALUE keystr;
-
- if (argc > 0) {
- rb_raise(rb_eArgError, "wrong number arguments(%d for 0)", argc);
- }
- GetDBM2(obj, dbmp, dbm);
- for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
- keystr = rb_gdbm_nextkey(dbm, keystr)) {
- VALUE assoc = rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr));
- VALUE v = rb_yield(assoc);
-
- if (RTEST(v)) {
- rb_ary_push(new, assoc);
- }
- GetDBM2(obj, dbmp, dbm);
- }
- }
- else {
- rb_warn("GDBM#select(index..) is deprecated; use GDBM#values_at");
-
- for (i=0; i<argc; i++) {
- rb_ary_push(new, rb_gdbm_fetch3(obj, argv[i]));
- }
- }
-
- return new;
-}
-
-static VALUE
-fgdbm_values_at(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE new = rb_ary_new2(argc);
- int i;
-
- for (i=0; i<argc; i++) {
- rb_ary_push(new, rb_gdbm_fetch3(obj, argv[i]));
- }
-
- return new;
-}
-
-static void
-rb_gdbm_modify(obj)
- VALUE obj;
-{
- rb_secure(4);
- if (OBJ_FROZEN(obj)) rb_error_frozen("GDBM");
-}
-
-static VALUE
-rb_gdbm_delete(obj, keystr)
- VALUE obj, keystr;
-{
- datum key;
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
-
- rb_gdbm_modify(obj);
- StringValue(keystr);
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- if (!gdbm_exists(dbm, key)) {
- return Qnil;
- }
-
- if (gdbm_delete(dbm, key)) {
- dbmp->di_size = -1;
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
- }
- else if (dbmp->di_size >= 0) {
- dbmp->di_size--;
- }
- return obj;
-}
-
-static VALUE
-fgdbm_delete(obj, keystr)
- VALUE obj, keystr;
-{
- VALUE valstr;
-
- valstr = fgdbm_fetch(obj, keystr, Qnil);
- rb_gdbm_delete(obj, keystr);
- return valstr;
-}
-
-static VALUE
-fgdbm_shift(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- VALUE keystr, valstr;
-
- rb_gdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- keystr = rb_gdbm_firstkey(dbm);
- if (NIL_P(keystr)) return Qnil;
- valstr = rb_gdbm_fetch2(dbm, keystr);
- rb_gdbm_delete(obj, keystr);
-
- return rb_assoc_new(keystr, valstr);
-}
-
-static VALUE
-fgdbm_delete_if(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- VALUE keystr, valstr;
- VALUE ret, ary = rb_ary_new();
- int i, status = 0, n;
-
- rb_gdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- n = dbmp->di_size;
- dbmp->di_size = -1;
-
- for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
- keystr = rb_gdbm_nextkey(dbm, keystr)) {
-
- valstr = rb_gdbm_fetch2(dbm, keystr);
- ret = rb_protect(rb_yield, rb_assoc_new(keystr, valstr), &status);
- if (status != 0) break;
- if (RTEST(ret)) rb_ary_push(ary, keystr);
- GetDBM2(obj, dbmp, dbm);
- }
-
- for (i = 0; i < RARRAY(ary)->len; i++)
- rb_gdbm_delete(obj, RARRAY(ary)->ptr[i]);
- if (status) rb_jump_tag(status);
- if (n > 0) dbmp->di_size = n - RARRAY(ary)->len;
-
- return obj;
-}
-
-static VALUE
-fgdbm_clear(obj)
- VALUE obj;
-{
- datum key, nextkey;
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
-
- rb_gdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- dbmp->di_size = -1;
-
-#if 0
- while (key = gdbm_firstkey(dbm), key.dptr) {
- if (gdbm_delete(dbm, key)) {
- free(key.dptr);
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
- }
- free(key.dptr);
- }
-#else
- while (key = gdbm_firstkey(dbm), key.dptr) {
- for (; key.dptr; key = nextkey) {
- nextkey = gdbm_nextkey(dbm, key);
- if (gdbm_delete(dbm, key)) {
- free(key.dptr);
- if (nextkey.dptr) free(nextkey.dptr);
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
- }
- free(key.dptr);
- }
- }
-#endif
- dbmp->di_size = 0;
-
- return obj;
-}
-
-static VALUE
-fgdbm_invert(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- VALUE keystr, valstr;
- VALUE hash = rb_hash_new();
-
- GetDBM2(obj, dbmp, dbm);
- for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
- keystr = rb_gdbm_nextkey(dbm, keystr)) {
- valstr = rb_gdbm_fetch2(dbm, keystr);
-
- rb_hash_aset(hash, valstr, keystr);
- }
- return hash;
-}
-
-static VALUE each_pair _((VALUE));
-
-static VALUE
-each_pair(obj)
- VALUE obj;
-{
- return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
-}
-
-static VALUE fgdbm_store _((VALUE,VALUE,VALUE));
-
-static VALUE
-update_i(pair, dbm)
- VALUE pair, dbm;
-{
- Check_Type(pair, T_ARRAY);
- if (RARRAY(pair)->len < 2) {
- rb_raise(rb_eArgError, "pair must be [key, value]");
- }
- fgdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]);
- return Qnil;
-}
-
-static VALUE
-fgdbm_update(obj, other)
- VALUE obj, other;
-{
- rb_iterate(each_pair, other, update_i, obj);
- return obj;
-}
-
-static VALUE
-fgdbm_replace(obj, other)
- VALUE obj, other;
-{
- fgdbm_clear(obj);
- rb_iterate(each_pair, other, update_i, obj);
- return obj;
-}
-
-static VALUE
-fgdbm_store(obj, keystr, valstr)
- VALUE obj, keystr, valstr;
-{
- datum key, val;
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
-
- rb_gdbm_modify(obj);
- StringValue(keystr);
- StringValue(valstr);
-
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
-
- val.dptr = RSTRING(valstr)->ptr;
- val.dsize = RSTRING(valstr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- dbmp->di_size = -1;
- if (gdbm_store(dbm, key, val, GDBM_REPLACE)) {
- if (errno == EPERM) rb_sys_fail(0);
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
- }
-
- return valstr;
-}
-
-static VALUE
-fgdbm_length(obj)
- VALUE obj;
-{
- datum key, nextkey;
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- int i = 0;
-
- GetDBM2(obj, dbmp, dbm);
- if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
-
- for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
- nextkey = gdbm_nextkey(dbm, key);
- free(key.dptr);
- i++;
- }
- dbmp->di_size = i;
-
- return INT2FIX(i);
-}
-
-static VALUE
-fgdbm_empty_p(obj)
- VALUE obj;
-{
- datum key;
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
-
- GetDBM(obj, dbmp);
- if (dbmp->di_size < 0) {
- dbm = dbmp->di_dbm;
-
- key = gdbm_firstkey(dbm);
- if (key.dptr) {
- free(key.dptr);
- return Qfalse;
- }
- return Qtrue;
- }
-
- if (dbmp->di_size == 0) return Qtrue;
- return Qfalse;
-}
-
-static VALUE
-fgdbm_each_value(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- VALUE keystr;
-
- GetDBM2(obj, dbmp, dbm);
- for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
- keystr = rb_gdbm_nextkey(dbm, keystr)) {
-
- rb_yield(rb_gdbm_fetch2(dbm, keystr));
- GetDBM2(obj, dbmp, dbm);
- }
- return obj;
-}
-
-static VALUE
-fgdbm_each_key(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- VALUE keystr;
-
- GetDBM2(obj, dbmp, dbm);
- for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
- keystr = rb_gdbm_nextkey(dbm, keystr)) {
-
- rb_yield(keystr);
- GetDBM2(obj, dbmp, dbm);
- }
- return obj;
-}
-
-static VALUE
-fgdbm_each_pair(obj)
- VALUE obj;
-{
- GDBM_FILE dbm;
- struct dbmdata *dbmp;
- VALUE keystr;
-
- GetDBM2(obj, dbmp, dbm);
- for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
- keystr = rb_gdbm_nextkey(dbm, keystr)) {
-
- rb_yield(rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr)));
- GetDBM2(obj, dbmp, dbm);
- }
-
- return obj;
-}
-
-static VALUE
-fgdbm_keys(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- VALUE keystr, ary;
-
- GetDBM2(obj, dbmp, dbm);
- ary = rb_ary_new();
- for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
- keystr = rb_gdbm_nextkey(dbm, keystr)) {
-
- rb_ary_push(ary, keystr);
- }
-
- return ary;
-}
-
-static VALUE
-fgdbm_values(obj)
- VALUE obj;
-{
- datum key, nextkey;
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- VALUE valstr, ary;
-
- GetDBM2(obj, dbmp, dbm);
- ary = rb_ary_new();
- for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
- nextkey = gdbm_nextkey(dbm, key);
- valstr = rb_gdbm_fetch(dbm, key);
- free(key.dptr);
- rb_ary_push(ary, valstr);
- }
-
- return ary;
-}
-
-static VALUE
-fgdbm_has_key(obj, keystr)
- VALUE obj, keystr;
-{
- datum key;
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
-
- StringValue(keystr);
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- if (gdbm_exists(dbm, key))
- return Qtrue;
- return Qfalse;
-}
-
-static VALUE
-fgdbm_has_value(obj, valstr)
- VALUE obj, valstr;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- VALUE keystr, valstr2;
-
- StringValue(valstr);
- GetDBM2(obj, dbmp, dbm);
- for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
- keystr = rb_gdbm_nextkey(dbm, keystr)) {
-
- valstr2 = rb_gdbm_fetch2(dbm, keystr);
-
- if (!NIL_P(valstr2) &&
- RSTRING(valstr)->len == RSTRING(valstr2)->len &&
- memcmp(RSTRING(valstr)->ptr, RSTRING(valstr2)->ptr,
- RSTRING(valstr)->len) == 0) {
- return Qtrue;
- }
- }
- return Qfalse;
-}
-
-static VALUE
-fgdbm_to_a(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- VALUE keystr, ary;
-
- GetDBM2(obj, dbmp, dbm);
- ary = rb_ary_new();
- for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
- keystr = rb_gdbm_nextkey(dbm, keystr)) {
-
- rb_ary_push(ary, rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr)));
- }
-
- return ary;
-}
-
-static VALUE
-fgdbm_reorganize(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
-
- rb_gdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- gdbm_reorganize(dbm);
- return obj;
-}
-
-static VALUE
-fgdbm_sync(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
-
- rb_gdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- gdbm_sync(dbm);
- return obj;
-}
-
-static VALUE
-fgdbm_set_cachesize(obj, val)
- VALUE obj, val;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- int optval;
-
- GetDBM2(obj, dbmp, dbm);
- optval = FIX2INT(val);
- if (gdbm_setopt(dbm, GDBM_CACHESIZE, &optval, sizeof(optval)) == -1) {
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
- }
- return val;
-}
-
-static VALUE
-fgdbm_set_fastmode(obj, val)
- VALUE obj, val;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- int optval;
-
- GetDBM2(obj, dbmp, dbm);
- optval = 0;
- if (RTEST(val))
- optval = 1;
-
- if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
- }
- return val;
-}
-
-static VALUE
-fgdbm_set_syncmode(obj, val)
- VALUE obj, val;
-{
-#if !defined(GDBM_SYNCMODE)
- fgdbm_set_fastmode(obj, RTEST(val) ? Qfalse : Qtrue);
- return val;
-#else
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- int optval;
-
- GetDBM2(obj, dbmp, dbm);
- optval = 0;
- if (RTEST(val))
- optval = 1;
-
- if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
- }
- return val;
-#endif
-}
-
-static VALUE
-fgdbm_to_hash(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
- GDBM_FILE dbm;
- VALUE keystr, hash;
-
- GetDBM2(obj, dbmp, dbm);
- hash = rb_hash_new();
- for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
- keystr = rb_gdbm_nextkey(dbm, keystr)) {
-
- rb_hash_aset(hash, keystr, rb_gdbm_fetch2(dbm, keystr));
- }
-
- return hash;
-}
-
-static VALUE
-fgdbm_reject(obj)
- VALUE obj;
-{
- return rb_hash_delete_if(fgdbm_to_hash(obj));
-}
-
-void
-Init_gdbm()
-{
- rb_cGDBM = rb_define_class("GDBM", rb_cObject);
- rb_eGDBMError = rb_define_class("GDBMError", rb_eStandardError);
- rb_eGDBMFatalError = rb_define_class("GDBMFatalError", rb_eException);
- rb_include_module(rb_cGDBM, rb_mEnumerable);
-
- rb_define_alloc_func(rb_cGDBM, fgdbm_s_alloc);
- rb_define_singleton_method(rb_cGDBM, "open", fgdbm_s_open, -1);
-
- rb_define_method(rb_cGDBM, "initialize", fgdbm_initialize, -1);
- rb_define_method(rb_cGDBM, "close", fgdbm_close, 0);
- rb_define_method(rb_cGDBM, "closed?", fgdbm_closed, 0);
- rb_define_method(rb_cGDBM, "[]", fgdbm_aref, 1);
- rb_define_method(rb_cGDBM, "fetch", fgdbm_fetch_m, -1);
- rb_define_method(rb_cGDBM, "[]=", fgdbm_store, 2);
- rb_define_method(rb_cGDBM, "store", fgdbm_store, 2);
- rb_define_method(rb_cGDBM, "index", fgdbm_index, 1);
- rb_define_method(rb_cGDBM, "indexes", fgdbm_indexes, -1);
- rb_define_method(rb_cGDBM, "indices", fgdbm_indexes, -1);
- rb_define_method(rb_cGDBM, "select", fgdbm_select, -1);
- rb_define_method(rb_cGDBM, "values_at", fgdbm_values_at, -1);
- rb_define_method(rb_cGDBM, "length", fgdbm_length, 0);
- rb_define_method(rb_cGDBM, "size", fgdbm_length, 0);
- rb_define_method(rb_cGDBM, "empty?", fgdbm_empty_p, 0);
- rb_define_method(rb_cGDBM, "each", fgdbm_each_pair, 0);
- rb_define_method(rb_cGDBM, "each_value", fgdbm_each_value, 0);
- rb_define_method(rb_cGDBM, "each_key", fgdbm_each_key, 0);
- rb_define_method(rb_cGDBM, "each_pair", fgdbm_each_pair, 0);
- rb_define_method(rb_cGDBM, "keys", fgdbm_keys, 0);
- rb_define_method(rb_cGDBM, "values", fgdbm_values, 0);
- rb_define_method(rb_cGDBM, "shift", fgdbm_shift, 0);
- rb_define_method(rb_cGDBM, "delete", fgdbm_delete, 1);
- rb_define_method(rb_cGDBM, "delete_if", fgdbm_delete_if, 0);
- rb_define_method(rb_cGDBM, "reject!", fgdbm_delete_if, 0);
- rb_define_method(rb_cGDBM, "reject", fgdbm_reject, 0);
- rb_define_method(rb_cGDBM, "clear", fgdbm_clear, 0);
- rb_define_method(rb_cGDBM,"invert", fgdbm_invert, 0);
- rb_define_method(rb_cGDBM,"update", fgdbm_update, 1);
- rb_define_method(rb_cGDBM,"replace", fgdbm_replace, 1);
- rb_define_method(rb_cGDBM,"reorganize", fgdbm_reorganize, 0);
- rb_define_method(rb_cGDBM,"sync", fgdbm_sync, 0);
- /* rb_define_method(rb_cGDBM,"setopt", fgdbm_setopt, 2); */
- rb_define_method(rb_cGDBM,"cachesize=", fgdbm_set_cachesize, 1);
- rb_define_method(rb_cGDBM,"fastmode=", fgdbm_set_fastmode, 1);
- rb_define_method(rb_cGDBM,"syncmode=", fgdbm_set_syncmode, 1);
-
- rb_define_method(rb_cGDBM, "include?", fgdbm_has_key, 1);
- rb_define_method(rb_cGDBM, "has_key?", fgdbm_has_key, 1);
- rb_define_method(rb_cGDBM, "member?", fgdbm_has_key, 1);
- rb_define_method(rb_cGDBM, "has_value?", fgdbm_has_value, 1);
- rb_define_method(rb_cGDBM, "key?", fgdbm_has_key, 1);
- rb_define_method(rb_cGDBM, "value?", fgdbm_has_value, 1);
-
- rb_define_method(rb_cGDBM, "to_a", fgdbm_to_a, 0);
- rb_define_method(rb_cGDBM, "to_hash", fgdbm_to_hash, 0);
-
- /* flags for gdbm_open() */
- rb_define_const(rb_cGDBM, "READER", INT2FIX(GDBM_READER|RUBY_GDBM_RW_BIT));
- rb_define_const(rb_cGDBM, "WRITER", INT2FIX(GDBM_WRITER|RUBY_GDBM_RW_BIT));
- rb_define_const(rb_cGDBM, "WRCREAT", INT2FIX(GDBM_WRCREAT|RUBY_GDBM_RW_BIT));
- rb_define_const(rb_cGDBM, "NEWDB", INT2FIX(GDBM_NEWDB|RUBY_GDBM_RW_BIT));
-
- rb_define_const(rb_cGDBM, "FAST", INT2FIX(GDBM_FAST));
- /* this flag is obsolete in gdbm 1.8.
- On gdbm 1.8, fast mode is default behavior. */
-
- /* gdbm version 1.8 specific */
-#if defined(GDBM_SYNC)
- rb_define_const(rb_cGDBM, "SYNC", INT2FIX(GDBM_SYNC));
-#endif
-#if defined(GDBM_NOLOCK)
- rb_define_const(rb_cGDBM, "NOLOCK", INT2FIX(GDBM_NOLOCK));
-#endif
- rb_define_const(rb_cGDBM, "VERSION", rb_str_new2(gdbm_version));
-}
diff --git a/ext/iconv/.cvsignore b/ext/iconv/.cvsignore
deleted file mode 100644
index 394787fced..0000000000
--- a/ext/iconv/.cvsignore
+++ /dev/null
@@ -1,5 +0,0 @@
-Makefile
-mkmf.log
-*.def
-iconv.rb
-config.charset
diff --git a/ext/iconv/charset_alias.rb b/ext/iconv/charset_alias.rb
deleted file mode 100644
index aed4644290..0000000000
--- a/ext/iconv/charset_alias.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-#! /usr/bin/ruby
-# :stopdoc:
-require 'rbconfig'
-require 'optparse'
-
-# http://www.ctan.org/tex-archive/macros/texinfo/texinfo/intl/config.charset
-# Fri, 30 May 2003 00:09:00 GMT'
-
-OS = Config::CONFIG["target_os"]
-SHELL = Config::CONFIG['SHELL']
-
-class Hash::Ordered < Hash
- def [](key)
- val = super and val.last
- end
- def []=(key, val)
- ary = fetch(key) {return super(key, [self.size, key, val])} and
- ary << val
- end
- def sort
- values.sort.collect {|i, *rest| rest}
- end
- def each(&block)
- sort.each(&block)
- end
-end
-
-def charset_alias(config_charset, mapfile, target = OS)
- map = Hash::Ordered.new
- comments = []
- open(config_charset) do |input|
- input.find {|line| /^case "\$os" in/ =~ line} or break
- input.find {|line|
- /^\s*([-\w\*]+(?:\s*\|\s*[-\w\*]+)*)(?=\))/ =~ line and
- $&.split('|').any? {|pattern| File.fnmatch?(pattern.strip, target)}
- } or break
- input.find do |line|
- case line
- when /^\s*echo "(?:\$\w+\.)?([-\w*]+)\s+([-\w]+)"/
- sys, can = $1, $2
- can.downcase!
- map[can] = sys
- false
- when /^\s*;;/
- true
- else
- false
- end
- end
- end
- case target
- when /linux|-gnu/
- # map.delete('ascii')
- when /cygwin|os2-emx/
- # get rid of tilde/yen problem.
- map['shift_jis'] = 'cp932'
- end
- st = Hash.new(0)
- map = map.sort.collect do |can, *sys|
- if sys.grep(/^en_us(?=.|$)/i) {break true} == true
- noen = %r"^(?!en_us)\w+_\w+#{Regexp.new($')}$"i #"
- sys.reject! {|s| noen =~ s}
- end
- sys = sys.first
- st[sys] += 1
- [can, sys]
- end
- st.delete_if {|sys, i| i == 1}.empty?
- st.keys.each {|sys| st[sys] = nil}
- st.default = nil
- writer = proc do |f|
- f.puts("require 'iconv.so'")
- f.puts
- f.puts(comments)
- f.puts("class Iconv")
- i = 0
- map.each do |can, sys|
- if s = st[sys]
- sys = s
- elsif st.key?(sys)
- sys = (st[sys] = "sys#{i+=1}") + " = '#{sys}'.freeze"
- else
- sys = "'#{sys}'.freeze"
- end
- f.puts(" charset_map['#{can}'] = #{sys}")
- end
- f.puts("end")
- end
- if mapfile
- open(mapfile, "w", &writer)
- else
- writer[STDOUT]
- end
-end
-
-target = OS
-opt = nil
-ARGV.options do |opt|
- opt.banner << " config.status map.rb"
- opt.on("--target OS") {|t| target = t}
- opt.parse! and (1..2) === ARGV.size
-end or abort opt.to_s
-charset_alias(ARGV[0], ARGV[1], target)
diff --git a/ext/iconv/depend b/ext/iconv/depend
deleted file mode 100644
index 688ddd97b7..0000000000
--- a/ext/iconv/depend
+++ /dev/null
@@ -1,2 +0,0 @@
-iconv.o: iconv.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h \
- $(hdrdir)/intern.h
diff --git a/ext/iconv/extconf.rb b/ext/iconv/extconf.rb
deleted file mode 100644
index a9d0cfb5e6..0000000000
--- a/ext/iconv/extconf.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-require 'mkmf'
-
-dir_config("iconv")
-
-conf = File.exist?(File.join($srcdir, "config.charset"))
-conf = with_config("config-charset", enable_config("config-charset", conf))
-
-if have_func("iconv", "iconv.h") or
- have_library("iconv", "iconv", "iconv.h")
- if checking_for("const of iconv() 2nd argument") do
- create_tmpsrc(cpp_include("iconv.h") + "---> iconv(cd,0,0,0,0) <---")
- src = xpopen(cpp_command("")) {|f|f.read}
- if !(func = src[/^--->\s*(\w+).*\s*<---/, 1])
- Logging::message "iconv function name not found"
- false
- elsif !(second = src[%r"\b#{func}\s*\(.*?,(.*?),.*?\)\s*;"m, 1])
- Logging::message "prototype for #{func}() not found"
- false
- else
- Logging::message $&+"\n"
- /\bconst\b/ =~ second
- end
- end
- $defs.push('-DICONV_INPTR_CONST')
- end
- if conf
- prefix = '$(srcdir)'
- prefix = $nmake ? "{#{prefix}}" : "#{prefix}/"
- if $extout
- wrapper = "$(RUBYARCHDIR)/iconv.rb"
- else
- wrapper = "./iconv.rb"
- $INSTALLFILES = [[wrapper, "$(RUBYARCHDIR)"]]
- end
- if String === conf
- require 'uri'
- scheme = URI.parse(conf).scheme
- else
- conf = "$(srcdir)/config.charset"
- end
- $cleanfiles << wrapper
- end
- create_makefile("iconv")
- if conf
- open("Makefile", "a") do |mf|
- mf.print("\nall: #{wrapper}\n\n#{wrapper}: #{prefix}charset_alias.rb")
- mf.print(" ", conf) unless scheme
- mf.print("\n\t$(RUBY) $(srcdir)/charset_alias.rb #{conf} $@\n")
- end
- end
-end
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
deleted file mode 100644
index 1c9d607de9..0000000000
--- a/ext/iconv/iconv.c
+++ /dev/null
@@ -1,910 +0,0 @@
-/* -*- mode:c; c-file-style:"ruby" -*- */
-/**********************************************************************
-
- iconv.c -
-
- $Author$
- $Date$
- created at: Wed Dec 1 20:28:09 JST 1999
-
- All the files in this distribution are covered under the Ruby's
- license (see the file COPYING).
-
- Documentation by Yukihiro Matsumoto and Gavin Sinclair.
-
-**********************************************************************/
-
-#include "ruby.h"
-#include <errno.h>
-#include <iconv.h>
-#include <assert.h>
-#include "st.h"
-#include "intern.h"
-
-/*
- * Document-class: Iconv
- *
- * == Summary
- *
- * Ruby extension for charset conversion.
- *
- * == Abstract
- *
- * Iconv is a wrapper class for the UNIX 95 <tt>iconv()</tt> function family,
- * which translates string between various encoding systems.
- *
- * See Open Group's on-line documents for more details.
- * * <tt>iconv.h</tt>: http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.h.html
- * * <tt>iconv_open()</tt>: http://www.opengroup.org/onlinepubs/007908799/xsh/iconv_open.html
- * * <tt>iconv()</tt>: http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.html
- * * <tt>iconv_close()</tt>: http://www.opengroup.org/onlinepubs/007908799/xsh/iconv_close.html
- *
- * Which coding systems are available is platform-dependent.
- *
- * == Examples
- *
- * 1. Instantiate a new Iconv and use method Iconv#iconv.
- *
- * cd = Iconv.new(to, from)
- * begin
- * input.each { |s| output << cd.iconv(s) }
- * output << cd.iconv(nil) # Don't forget this!
- * ensure
- * cd.close
- * end
- *
- * 2. Invoke Iconv.open with a block.
- *
- * Iconv.open(to, from) do |cd|
- * input.each { |s| output << cd.iconv(s) }
- * output << cd.iconv(nil)
- * end
- *
- * 3. Shorthand for (2).
- *
- * Iconv.iconv(to, from, *input.to_a)
- *
- * 4. Simple conversion between two charsets.
- *
- * converted_text = Iconv.new('iso-8859-15', 'utf-8').iconv(text)
- */
-
-/* Invalid value for iconv_t is -1 but 0 for VALUE, I hope VALUE is
- big enough to keep iconv_t */
-#define VALUE2ICONV(v) ((iconv_t)((VALUE)(v) ^ -1))
-#define ICONV2VALUE(c) ((VALUE)(c) ^ -1)
-
-struct iconv_env_t
-{
- iconv_t cd;
- int argc;
- VALUE *argv;
- VALUE ret;
- VALUE (*append)_((VALUE, VALUE));
-};
-
-static VALUE rb_eIconvInvalidEncoding;
-static VALUE rb_eIconvFailure;
-static VALUE rb_eIconvIllegalSeq;
-static VALUE rb_eIconvInvalidChar;
-static VALUE rb_eIconvOutOfRange;
-static VALUE rb_eIconvBrokenLibrary;
-
-static ID rb_success, rb_failed;
-static VALUE iconv_fail _((VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env, const char *mesg));
-static VALUE iconv_failure_initialize _((VALUE error, VALUE mesg, VALUE success, VALUE failed));
-static VALUE iconv_failure_success _((VALUE self));
-static VALUE iconv_failure_failed _((VALUE self));
-
-static iconv_t iconv_create _((VALUE to, VALUE from));
-static void iconv_dfree _((void *cd));
-static VALUE iconv_free _((VALUE cd));
-static VALUE iconv_try _((iconv_t cd, const char **inptr, size_t *inlen, char **outptr, size_t *outlen));
-static VALUE rb_str_derive _((VALUE str, const char* ptr, int len));
-static VALUE iconv_convert _((iconv_t cd, VALUE str, int start, int length, struct iconv_env_t* env));
-static VALUE iconv_s_allocate _((VALUE klass));
-static VALUE iconv_initialize _((VALUE self, VALUE to, VALUE from));
-static VALUE iconv_s_open _((VALUE self, VALUE to, VALUE from));
-static VALUE iconv_s_convert _((struct iconv_env_t* env));
-static VALUE iconv_s_iconv _((int argc, VALUE *argv, VALUE self));
-static VALUE iconv_init_state _((VALUE cd));
-static VALUE iconv_finish _((VALUE self));
-static VALUE iconv_iconv _((int argc, VALUE *argv, VALUE self));
-
-static VALUE charset_map;
-
-/*
- * Document-method: charset_map
- * call-seq: Iconv.charset_map
- *
- * Returns the map from canonical name to system dependent name.
- */
-static VALUE charset_map_get _((void))
-{
- return charset_map;
-}
-
-static char *
-map_charset
-#ifdef HAVE_PROTOTYPES
- (VALUE *code)
-#else /* HAVE_PROTOTYPES */
- (code)
- VALUE *code;
-#endif /* HAVE_PROTOTYPES */
-{
- VALUE val = *code;
-
- if (RHASH(charset_map)->tbl && RHASH(charset_map)->tbl->num_entries) {
- VALUE key = rb_funcall2(val, rb_intern("downcase"), 0, 0);
- StringValuePtr(key);
- if (st_lookup(RHASH(charset_map)->tbl, key, &val)) {
- *code = val;
- }
- }
- return StringValuePtr(*code);
-}
-
-static iconv_t
-iconv_create
-#ifdef HAVE_PROTOTYPES
- (VALUE to, VALUE from)
-#else /* HAVE_PROTOTYPES */
- (to, from)
- VALUE to;
- VALUE from;
-#endif /* HAVE_PROTOTYPES */
-{
- const char* tocode = map_charset(&to);
- const char* fromcode = map_charset(&from);
-
- iconv_t cd = iconv_open(tocode, fromcode);
-
- if (cd == (iconv_t)-1) {
- switch (errno) {
- case EMFILE:
- case ENFILE:
- case ENOMEM:
- rb_gc();
- cd = iconv_open(tocode, fromcode);
- }
- if (cd == (iconv_t)-1) {
- int inval = errno == EINVAL;
- char *s = inval ? "invalid encoding " : "iconv";
- volatile VALUE msg = rb_str_new(0, strlen(s) + RSTRING(to)->len +
- RSTRING(from)->len + 8);
-
- sprintf(RSTRING(msg)->ptr, "%s(\"%s\", \"%s\")",
- s, RSTRING(to)->ptr, RSTRING(from)->ptr);
- s = RSTRING(msg)->ptr;
- RSTRING(msg)->len = strlen(s);
- if (!inval) rb_sys_fail(s);
- iconv_fail(rb_eIconvInvalidEncoding,
- Qnil, rb_ary_new3(2, to, from), NULL, s);
- }
- }
-
- return cd;
-}
-
-static void
-iconv_dfree
-#ifdef HAVE_PROTOTYPES
- (void *cd)
-#else /* HAVE_PROTOTYPES */
- (cd)
- void *cd;
-#endif /* HAVE_PROTOTYPES */
-{
- iconv_close(VALUE2ICONV(cd));
-}
-
-#define ICONV_FREE iconv_dfree
-
-static VALUE
-iconv_free
-#ifdef HAVE_PROTOTYPES
- (VALUE cd)
-#else /* HAVE_PROTOTYPES */
- (cd)
- VALUE cd;
-#endif /* HAVE_PROTOTYPES */
-{
- if (cd && iconv_close(VALUE2ICONV(cd)) == -1)
- rb_sys_fail("iconv_close");
- return Qnil;
-}
-
-static VALUE
-check_iconv
-#ifdef HAVE_PROTOTYPES
- (VALUE obj)
-#else /* HAVE_PROTOTYPES */
- (obj)
- VALUE obj;
-#endif /* HAVE_PROTOTYPES */
-{
- Check_Type(obj, T_DATA);
- if (RDATA(obj)->dfree != ICONV_FREE) {
- rb_raise(rb_eArgError, "Iconv expected (%s)", rb_class2name(CLASS_OF(obj)));
- }
- return (VALUE)DATA_PTR(obj);
-}
-
-static VALUE
-iconv_try
-#ifdef HAVE_PROTOTYPES
- (iconv_t cd, const char **inptr, size_t *inlen, char **outptr, size_t *outlen)
-#else /* HAVE_PROTOTYPES */
- (cd, inptr, inlen, outptr, outlen)
- iconv_t cd;
- const char **inptr;
- size_t *inlen;
- char **outptr;
- size_t *outlen;
-#endif /* HAVE_PROTOTYPES */
-{
-#ifdef ICONV_INPTR_CONST
-#define ICONV_INPTR_CAST
-#else
-#define ICONV_INPTR_CAST (char **)
-#endif
- size_t ret;
-
- errno = 0;
- ret = iconv(cd, ICONV_INPTR_CAST inptr, inlen, outptr, outlen);
- if (ret == (size_t)-1) {
- if (!*inlen)
- return Qfalse;
- switch (errno) {
- case E2BIG:
- /* try the left in next loop */
- break;
- case EILSEQ:
- return rb_eIconvIllegalSeq;
- case EINVAL:
- return rb_eIconvInvalidChar;
- case 0:
- return rb_eIconvBrokenLibrary;
- default:
- rb_sys_fail("iconv");
- }
- }
- else if (*inlen > 0) {
- /* something goes wrong */
- return rb_eIconvIllegalSeq;
- }
- else if (ret) {
- return Qnil; /* conversion */
- }
- return Qfalse;
-}
-
-#define FAILED_MAXLEN 16
-
-static VALUE iconv_failure_initialize
-#ifdef HAVE_PROTOTYPES
- (VALUE error, VALUE mesg, VALUE success, VALUE failed)
-#else /* HAVE_PROTOTYPES */
- (error, mesg, success, failed)
- VALUE error, mesg, success, failed;
-#endif /* HAVE_PROTOTYPES */
-{
- rb_call_super(1, &mesg);
- rb_ivar_set(error, rb_success, success);
- rb_ivar_set(error, rb_failed, failed);
- return error;
-}
-
-static VALUE
-iconv_fail
-#ifdef HAVE_PROTOTYPES
- (VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env, const char *mesg)
-#else /* HAVE_PROTOTYPES */
- (error, success, failed, env, mesg)
- VALUE error, success, failed;
- struct iconv_env_t *env;
- const char *mesg;
-#endif /* HAVE_PROTOTYPES */
-{
- VALUE args[3];
-
- if (mesg && *mesg) {
- args[0] = rb_str_new2(mesg);
- }
- else if (TYPE(failed) != T_STRING || RSTRING(failed)->len < FAILED_MAXLEN) {
- args[0] = rb_inspect(failed);
- }
- else {
- args[0] = rb_inspect(rb_str_substr(failed, 0, FAILED_MAXLEN));
- rb_str_cat2(args[0], "...");
- }
- args[1] = success;
- args[2] = failed;
- if (env) {
- args[1] = env->append(rb_obj_dup(env->ret), success);
- if (env->argc > 0) {
- *(env->argv) = failed;
- args[2] = rb_ary_new4(env->argc, env->argv);
- }
- }
- error = rb_class_new_instance(3, args, error);
- if (!rb_block_given_p()) rb_exc_raise(error);
- ruby_errinfo = error;
- return rb_yield(failed);
-}
-
-static VALUE
-rb_str_derive
-#ifdef HAVE_PROTOTYPES
- (VALUE str, const char* ptr, int len)
-#else /* HAVE_PROTOTYPES */
- (str, ptr, len)
- VALUE str;
- const char *ptr;
- int len;
-#endif /* HAVE_PROTOTYPES */
-{
- VALUE ret;
-
- if (NIL_P(str))
- return rb_str_new(ptr, len);
- if (RSTRING(str)->ptr == ptr && RSTRING(str)->len == len)
- return str;
- if (RSTRING(str)->ptr + RSTRING(str)->len == ptr + len)
- ret = rb_str_substr(str, ptr - RSTRING(str)->ptr, len);
- else
- ret = rb_str_new(ptr, len);
- OBJ_INFECT(ret, str);
- return ret;
-}
-
-static VALUE
-iconv_convert
-#ifdef HAVE_PROTOTYPES
- (iconv_t cd, VALUE str, int start, int length, struct iconv_env_t* env)
-#else /* HAVE_PROTOTYPES */
- (cd, str, start, length, env)
- iconv_t cd;
- VALUE str;
- int start;
- int length;
- struct iconv_env_t *env;
-#endif /* HAVE_PROTOTYPES */
-{
- VALUE ret = Qfalse;
- VALUE error = Qfalse;
- VALUE rescue;
- const char *inptr, *instart;
- size_t inlen;
- /* I believe ONE CHARACTER never exceed this. */
- char buffer[BUFSIZ];
- char *outptr;
- size_t outlen;
-
- if (cd == (iconv_t)-1)
- rb_raise(rb_eArgError, "closed iconv");
-
- if (NIL_P(str)) {
- /* Reset output pointer or something. */
- inptr = "";
- inlen = 0;
- outptr = buffer;
- outlen = sizeof(buffer);
- error = iconv_try(cd, &inptr, &inlen, &outptr, &outlen);
- if (RTEST(error)) {
- unsigned int i;
- rescue = iconv_fail(error, Qnil, Qnil, env, 0);
- if (TYPE(rescue) == T_ARRAY) {
- str = RARRAY(rescue)->len > 0 ? RARRAY(rescue)->ptr[0] : Qnil;
- }
- if (FIXNUM_P(str) && (i = FIX2INT(str)) <= 0xff) {
- char c = i;
- str = rb_str_new(&c, 1);
- }
- else if (!NIL_P(str)) {
- StringValue(str);
- }
- }
-
- inptr = NULL;
- length = 0;
- }
- else {
- int slen;
-
- StringValue(str);
- slen = RSTRING(str)->len;
- inptr = RSTRING(str)->ptr;
-
- if (start < 0 ? (start += slen) < 0 : start >= slen)
- length = 0;
- else if (length < 0 && (length += slen + 1) < 0)
- length = 0;
- else if ((length -= start) < 0)
- length = 0;
- else
- inptr += start;
- }
- instart = inptr;
- inlen = length;
-
- do {
- char errmsg[50];
- const char *tmpstart = inptr;
- outptr = buffer;
- outlen = sizeof(buffer);
-
- errmsg[0] = 0;
- error = iconv_try(cd, &inptr, &inlen, &outptr, &outlen);
-
- if (0 <= outlen && outlen <= sizeof(buffer)) {
- outlen = sizeof(buffer) - outlen;
- if (NIL_P(error) || /* something converted */
- outlen > inptr - tmpstart || /* input can't contain output */
- (outlen < inptr - tmpstart && inlen > 0) || /* something skipped */
- memcmp(buffer, tmpstart, outlen)) /* something differs */
- {
- if (NIL_P(str)) {
- ret = rb_str_new(buffer, outlen);
- }
- else {
- if (ret) {
- ret = rb_str_buf_cat(ret, instart, tmpstart - instart);
- }
- else {
- ret = rb_str_new(instart, tmpstart - instart);
- OBJ_INFECT(ret, str);
- }
- ret = rb_str_buf_cat(ret, buffer, outlen);
- instart = inptr;
- }
- }
- else if (!inlen) {
- inptr = tmpstart + outlen;
- }
- }
- else {
- /* Some iconv() have a bug, return *outlen out of range */
- sprintf(errmsg, "bug?(output length = %ld)", (long)(sizeof(buffer) - outlen));
- error = rb_eIconvOutOfRange;
- }
-
- if (RTEST(error)) {
- long len = 0;
-
- if (!ret)
- ret = rb_str_derive(str, instart, inptr - instart);
- else if (inptr > instart)
- rb_str_cat(ret, instart, inptr - instart);
- str = rb_str_derive(str, inptr, inlen);
- rescue = iconv_fail(error, ret, str, env, errmsg);
- if (TYPE(rescue) == T_ARRAY) {
- if ((len = RARRAY(rescue)->len) > 0)
- rb_str_concat(ret, RARRAY(rescue)->ptr[0]);
- if (len > 1 && !NIL_P(str = RARRAY(rescue)->ptr[1])) {
- StringValue(str);
- inlen = length = RSTRING(str)->len;
- instart = inptr = RSTRING(str)->ptr;
- continue;
- }
- }
- else if (!NIL_P(rescue)) {
- rb_str_concat(ret, rescue);
- }
- break;
- }
- } while (inlen > 0);
-
- if (!ret)
- ret = rb_str_derive(str, instart, inptr - instart);
- else if (inptr > instart)
- rb_str_cat(ret, instart, inptr - instart);
- return ret;
-}
-
-static VALUE
-iconv_s_allocate
-#ifdef HAVE_PROTOTYPES
- (VALUE klass)
-#else /* HAVE_PROTOTYPES */
- (klass)
- VALUE klass;
-#endif /* HAVE_PROTOTYPES */
-{
- return Data_Wrap_Struct(klass, 0, ICONV_FREE, 0);
-}
-
-/*
- * Document-method: new
- * call-seq: Iconv.new(to, from)
- *
- * Creates new code converter from a coding-system designated with +from+
- * to another one designated with +to+.
- *
- * === Parameters
- *
- * +to+:: encoding name for destination
- * +from+:: encoding name for source
- *
- * === Exceptions
- *
- * TypeError:: if +to+ or +from+ aren't String
- * InvalidEncoding:: if designated converter couldn't find out
- * SystemCallError:: if <tt>iconv_open(3)</tt> fails
- */
-static VALUE
-iconv_initialize
-#ifdef HAVE_PROTOTYPES
- (VALUE self, VALUE to, VALUE from)
-#else /* HAVE_PROTOTYPES */
- (self, to, from)
- VALUE self;
- VALUE to;
- VALUE from;
-#endif /* HAVE_PROTOTYPES */
-{
- iconv_free(check_iconv(self));
- DATA_PTR(self) = NULL;
- DATA_PTR(self) = (void *)ICONV2VALUE(iconv_create(to, from));
- return self;
-}
-
-/*
- * Document-method: open
- * call-seq: Iconv.open(to, from) { |iconv| ... }
- *
- * Equivalent to Iconv.new except that when it is called with a block, it
- * yields with the new instance and closes it, and returns the result which
- * returned from the block.
- */
-static VALUE
-iconv_s_open
-#ifdef HAVE_PROTOTYPES
- (VALUE self, VALUE to, VALUE from)
-#else /* HAVE_PROTOTYPES */
- (self, to, from)
- VALUE self;
- VALUE to;
- VALUE from;
-#endif /* HAVE_PROTOTYPES */
-{
- VALUE cd = ICONV2VALUE(iconv_create(to, from));
-
- self = Data_Wrap_Struct(self, NULL, ICONV_FREE, (void *)cd);
- if (rb_block_given_p()) {
- return rb_ensure(rb_yield, self, (VALUE(*)())iconv_finish, self);
- }
- else {
- return self;
- }
-}
-
-static VALUE
-iconv_s_convert
-#ifdef HAVE_PROTOTYPES
- (struct iconv_env_t* env)
-#else /* HAVE_PROTOTYPES */
- (env)
- struct iconv_env_t *env;
-#endif /* HAVE_PROTOTYPES */
-{
- VALUE last = 0;
-
- for (; env->argc > 0; --env->argc, ++env->argv) {
- VALUE s = iconv_convert(env->cd, last = *(env->argv), 0, -1, env);
- env->append(env->ret, s);
- }
-
- if (!NIL_P(last)) {
- VALUE s = iconv_convert(env->cd, Qnil, 0, 0, env);
- if (RSTRING(s)->len)
- env->append(env->ret, s);
- }
-
- return env->ret;
-}
-
-/*
- * Document-method: iconv
- * call-seq: Iconv.iconv(to, from, *strs)
- *
- * Shorthand for
- * Iconv.open(to, from) { |cd|
- * (strs + [nil]).collect { |s| cd.iconv(s) }
- * }
- *
- * === Parameters
- *
- * <tt>to, from</tt>:: see Iconv.new
- * <tt>strs</tt>:: strings to be converted
- *
- * === Exceptions
- *
- * Exceptions thrown by Iconv.new, Iconv.open and Iconv#iconv.
- */
-static VALUE
-iconv_s_iconv
-#ifdef HAVE_PROTOTYPES
- (int argc, VALUE *argv, VALUE self)
-#else /* HAVE_PROTOTYPES */
- (argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-#endif /* HAVE_PROTOTYPES */
-{
- struct iconv_env_t arg;
-
- if (argc < 2) /* needs `to' and `from' arguments at least */
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, 2);
-
- arg.argc = argc -= 2;
- arg.argv = argv + 2;
- arg.append = rb_ary_push;
- arg.ret = rb_ary_new2(argc);
- arg.cd = iconv_create(argv[0], argv[1]);
- return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd));
-}
-
-/*
- * Document-method: Iconv::conv
- * call-seq: Iconv.iconv(to, from, *strs)
- *
- * Shorthand for
- * Iconv.iconv(to, from, str).join
- * See Iconv.iconv.
- */
-static VALUE
-iconv_s_conv
-#ifdef HAVE_PROTOTYPES
- (VALUE self, VALUE to, VALUE from, VALUE str)
-#else /* HAVE_PROTOTYPES */
- (self, to, from, str)
- VALUE self, to, from, str;
-#endif /* HAVE_PROTOTYPES */
-{
- struct iconv_env_t arg;
-
- arg.argc = 1;
- arg.argv = &str;
- arg.append = rb_str_append;
- arg.ret = rb_str_new(0, 0);
- arg.cd = iconv_create(to, from);
- return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd));
-}
-
-/*
- * Document-method: close
- *
- * Finishes conversion.
- *
- * After calling this, calling Iconv#iconv will cause an exception, but
- * multiple calls of #close are guaranteed to end successfully.
- *
- * Returns a string containing the byte sequence to change the output buffer to
- * its initial shift state.
- */
-static VALUE
-iconv_init_state
-#ifdef HAVE_PROTOTYPES
- (VALUE cd)
-#else /* HAVE_PROTOTYPES */
- (cd)
- VALUE cd;
-#endif /* HAVE_PROTOTYPES */
-{
- return iconv_convert(VALUE2ICONV(cd), Qnil, 0, 0, NULL);
-}
-
-static VALUE
-iconv_finish
-#ifdef HAVE_PROTOTYPES
- (VALUE self)
-#else /* HAVE_PROTOTYPES */
- (self)
- VALUE self;
-#endif /* HAVE_PROTOTYPES */
-{
- VALUE cd = check_iconv(self);
-
- if (!cd) return Qnil;
- DATA_PTR(self) = NULL;
-
- return rb_ensure(iconv_init_state, cd, iconv_free, cd);
-}
-
-/*
- * Document-method: iconv
- * call-seq: iconv(str, start=0, length=-1)
- *
- * Converts string and returns the result.
- * * If +str+ is a String, converts <tt>str[start, length]</tt> and returns the converted string.
- * * If +str+ is +nil+, places converter itself into initial shift state and
- * just returns a string containing the byte sequence to change the output
- * buffer to its initial shift state.
- * * Otherwise, raises an exception.
- *
- * === Parameters
- *
- * str:: string to be converted, or nil
- * start:: starting offset
- * length:: conversion length; nil or -1 means whole the string from start
- *
- * === Exceptions
- *
- * * IconvIllegalSequence
- * * IconvInvalidCharacter
- * * IconvOutOfRange
- *
- * === Examples
- *
- * See the Iconv documentation.
- */
-static VALUE
-iconv_iconv
-#ifdef HAVE_PROTOTYPES
- (int argc, VALUE *argv, VALUE self)
-#else /* HAVE_PROTOTYPES */
- (argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-#endif /* HAVE_PROTOTYPES */
-{
- VALUE str, n1, n2;
- VALUE cd = check_iconv(self);
-
- n1 = n2 = Qnil;
- rb_scan_args(argc, argv, "12", &str, &n1, &n2);
-
- return iconv_convert(VALUE2ICONV(cd), str,
- NIL_P(n1) ? 0 : NUM2INT(n1),
- NIL_P(n2) ? -1 : NUM2INT(n2),
- NULL);
-}
-
-/*
- * Document-class: Iconv::Failure
- *
- * Base attributes for Iconv exceptions.
- */
-
-/*
- * Document-method: success
- * call-seq: success
- *
- * Returns string(s) translated successfully until the exception occurred.
- * * In the case of failure occurred within Iconv.iconv, returned
- * value is an array of strings translated successfully preceding
- * failure and the last element is string on the way.
- */
-static VALUE
-iconv_failure_success
-#ifdef HAVE_PROTOTYPES
-(VALUE self)
-#else /* HAVE_PROTOTYPES */
- (self)
- VALUE self;
-#endif /* HAVE_PROTOTYPES */
-{
- return rb_attr_get(self, rb_success);
-}
-
-/*
- * Document-method: failed
- * call-seq: failed
- *
- * Returns substring of the original string passed to Iconv that starts at the
- * character caused the exception.
- */
-static VALUE
-iconv_failure_failed
-#ifdef HAVE_PROTOTYPES
-(VALUE self)
-#else /* HAVE_PROTOTYPES */
- (self)
- VALUE self;
-#endif /* HAVE_PROTOTYPES */
-{
- return rb_attr_get(self, rb_failed);
-}
-
-/*
- * Document-method: inspect
- * call-seq: inspect
- *
- * Returns inspected string like as: #<_class_: _success_, _failed_>
- */
-static VALUE
-iconv_failure_inspect
-#ifdef HAVE_PROTOTYPES
- (VALUE self)
-#else /* HAVE_PROTOTYPES */
- (self)
- VALUE self;
-#endif /* HAVE_PROTOTYPES */
-{
- char *cname = rb_class2name(CLASS_OF(self));
- VALUE success = rb_attr_get(self, rb_success);
- VALUE failed = rb_attr_get(self, rb_failed);
- VALUE str = rb_str_buf_cat2(rb_str_new2("#<"), cname);
- str = rb_str_buf_cat(str, ": ", 2);
- str = rb_str_buf_append(str, rb_inspect(success));
- str = rb_str_buf_cat(str, ", ", 2);
- str = rb_str_buf_append(str, rb_inspect(failed));
- return rb_str_buf_cat(str, ">", 1);
-}
-
-/*
- * Document-class: Iconv::InvalidEncoding
- *
- * Requested coding-system is not available on this system.
- */
-
-/*
- * Document-class: Iconv::IllegalSequence
- *
- * Input conversion stopped due to an input byte that does not belong to
- * the input codeset, or the output codeset does not contain the
- * character.
- */
-
-/*
- * Document-class: Iconv::InvalidCharacter
- *
- * Input conversion stopped due to an incomplete character or shift
- * sequence at the end of the input buffer.
- */
-
-/*
- * Document-class: Iconv::OutOfRange
- *
- * Iconv library internal error. Must not occur.
- */
-
-/*
- * Document-class: Iconv::BrokenLibrary
- *
- * Detected a bug of underlying iconv(3) libray.
- * * returns an error without setting errno properly
- */
-
-void
-Init_iconv _((void))
-{
- VALUE rb_cIconv = rb_define_class("Iconv", rb_cData);
-
- rb_define_alloc_func(rb_cIconv, iconv_s_allocate);
- rb_define_singleton_method(rb_cIconv, "open", iconv_s_open, 2);
- rb_define_singleton_method(rb_cIconv, "iconv", iconv_s_iconv, -1);
- rb_define_singleton_method(rb_cIconv, "conv", iconv_s_conv, 3);
- rb_define_method(rb_cIconv, "initialize", iconv_initialize, 2);
- rb_define_method(rb_cIconv, "close", iconv_finish, 0);
- rb_define_method(rb_cIconv, "iconv", iconv_iconv, -1);
-
- rb_eIconvFailure = rb_define_module_under(rb_cIconv, "Failure");
- rb_define_method(rb_eIconvFailure, "initialize", iconv_failure_initialize, 3);
- rb_define_method(rb_eIconvFailure, "success", iconv_failure_success, 0);
- rb_define_method(rb_eIconvFailure, "failed", iconv_failure_failed, 0);
- rb_define_method(rb_eIconvFailure, "inspect", iconv_failure_inspect, 0);
-
- rb_eIconvInvalidEncoding = rb_define_class_under(rb_cIconv, "InvalidEncoding", rb_eArgError);
- rb_eIconvIllegalSeq = rb_define_class_under(rb_cIconv, "IllegalSequence", rb_eArgError);
- rb_eIconvInvalidChar = rb_define_class_under(rb_cIconv, "InvalidCharacter", rb_eArgError);
- rb_eIconvOutOfRange = rb_define_class_under(rb_cIconv, "OutOfRange", rb_eRuntimeError);
- rb_eIconvBrokenLibrary = rb_define_class_under(rb_cIconv, "BrokenLibrary", rb_eRuntimeError);
- rb_include_module(rb_eIconvInvalidEncoding, rb_eIconvFailure);
- rb_include_module(rb_eIconvIllegalSeq, rb_eIconvFailure);
- rb_include_module(rb_eIconvInvalidChar, rb_eIconvFailure);
- rb_include_module(rb_eIconvOutOfRange, rb_eIconvFailure);
- rb_include_module(rb_eIconvBrokenLibrary, rb_eIconvFailure);
-
- rb_success = rb_intern("success");
- rb_failed = rb_intern("failed");
-
- rb_gc_register_address(&charset_map);
- charset_map = rb_hash_new();
- rb_define_singleton_method(rb_cIconv, "charset_map", charset_map_get, 0);
-}
-
diff --git a/ext/io/console/.document b/ext/io/console/.document
new file mode 100644
index 0000000000..945a377256
--- /dev/null
+++ b/ext/io/console/.document
@@ -0,0 +1,2 @@
+console.c
+lib/size.rb
diff --git a/ext/io/console/buildgem.sh b/ext/io/console/buildgem.sh
new file mode 100755
index 0000000000..65fe545e1e
--- /dev/null
+++ b/ext/io/console/buildgem.sh
@@ -0,0 +1,5 @@
+#!/bin/sh -e
+cd ${0%/*}
+trap "mv depend.$$ depend" 0 2
+${RUBY-ruby} -i.$$ -pe 'exit if /^win32_vk/' depend
+${GEM-gem} build io-console.gemspec
diff --git a/ext/io/console/console.c b/ext/io/console/console.c
new file mode 100644
index 0000000000..5f3c9478f7
--- /dev/null
+++ b/ext/io/console/console.c
@@ -0,0 +1,2019 @@
+/* -*- c-file-style: "ruby"; indent-tabs-mode: t -*- */
+/*
+ * console IO module
+ */
+
+static const char *const
+IO_CONSOLE_VERSION = "0.8.2";
+
+#include "ruby.h"
+#include "ruby/io.h"
+#include "ruby/thread.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#if defined HAVE_TERMIOS_H
+# include <termios.h>
+typedef struct termios conmode;
+
+static int
+setattr(int fd, conmode *t)
+{
+ while (tcsetattr(fd, TCSANOW, t)) {
+ if (errno != EINTR) return 0;
+ }
+ return 1;
+}
+# define getattr(fd, t) (tcgetattr(fd, t) == 0)
+#elif defined HAVE_TERMIO_H
+# include <termio.h>
+typedef struct termio conmode;
+# define setattr(fd, t) (ioctl(fd, TCSETAF, t) == 0)
+# define getattr(fd, t) (ioctl(fd, TCGETA, t) == 0)
+#elif defined HAVE_SGTTY_H
+# include <sgtty.h>
+typedef struct sgttyb conmode;
+# ifdef HAVE_STTY
+# define setattr(fd, t) (stty(fd, t) == 0)
+# else
+# define setattr(fd, t) (ioctl((fd), TIOCSETP, (t)) == 0)
+# endif
+# ifdef HAVE_GTTY
+# define getattr(fd, t) (gtty(fd, t) == 0)
+# else
+# define getattr(fd, t) (ioctl((fd), TIOCGETP, (t)) == 0)
+# endif
+#elif defined _WIN32
+#include <winioctl.h>
+#include <conio.h>
+typedef DWORD conmode;
+
+#define LAST_ERROR rb_w32_map_errno(GetLastError())
+#define SET_LAST_ERROR (errno = LAST_ERROR, 0)
+
+static int
+setattr(int fd, conmode *t)
+{
+ int x = SetConsoleMode((HANDLE)rb_w32_get_osfhandle(fd), *t);
+ if (!x) errno = LAST_ERROR;
+ return x;
+}
+
+static int
+getattr(int fd, conmode *t)
+{
+ int x = GetConsoleMode((HANDLE)rb_w32_get_osfhandle(fd), t);
+ if (!x) errno = LAST_ERROR;
+ return x;
+}
+#endif
+#ifndef SET_LAST_ERROR
+#define SET_LAST_ERROR (0)
+#endif
+
+#define CSI "\x1b\x5b"
+
+static ID id_getc, id_close;
+static ID id_gets, id_flush, id_chomp_bang;
+
+#ifndef HAVE_RB_INTERNED_STR_CSTR
+# define rb_str_to_interned_str(str) rb_str_freeze(str)
+# define rb_interned_str_cstr(str) rb_str_freeze(rb_usascii_str_new_cstr(str))
+#endif
+
+#if defined HAVE_RUBY_FIBER_SCHEDULER_H
+# include "ruby/fiber/scheduler.h"
+#elif defined HAVE_RB_SCHEDULER_TIMEOUT
+extern VALUE rb_scheduler_timeout(struct timeval *timeout);
+# define rb_fiber_scheduler_make_timeout rb_scheduler_timeout
+#endif
+
+#ifndef HAVE_RB_IO_DESCRIPTOR
+static int
+io_descriptor_fallback(VALUE io)
+{
+ rb_io_t *fptr;
+ GetOpenFile(io, fptr);
+ return fptr->fd;
+}
+#define rb_io_descriptor io_descriptor_fallback
+#endif
+
+#ifndef HAVE_RB_IO_PATH
+static VALUE
+io_path_fallback(VALUE io)
+{
+ rb_io_t *fptr;
+ GetOpenFile(io, fptr);
+ return fptr->pathv;
+}
+#define rb_io_path io_path_fallback
+#endif
+
+#ifndef HAVE_RB_IO_GET_WRITE_IO
+static VALUE
+io_get_write_io_fallback(VALUE io)
+{
+ rb_io_t *fptr;
+ GetOpenFile(io, fptr);
+ VALUE wio = fptr->tied_io_for_writing;
+ return wio ? wio : io;
+}
+#define rb_io_get_write_io io_get_write_io_fallback
+#endif
+
+#ifndef DHAVE_RB_SYSERR_FAIL_STR
+# define rb_syserr_fail_str(e, mesg) rb_exc_raise(rb_syserr_new_str(e, mesg))
+#endif
+
+#define sys_fail(io) do { \
+ int err = errno; \
+ rb_syserr_fail_str(err, rb_io_path(io)); \
+} while (0)
+
+#ifndef HAVE_RB_F_SEND
+#ifndef RB_PASS_CALLED_KEYWORDS
+# define rb_funcallv_kw(recv, mid, arg, argv, kw_splat) rb_funcallv(recv, mid, arg, argv)
+#endif
+
+static ID id___send__;
+
+static VALUE
+rb_f_send(int argc, VALUE *argv, VALUE recv)
+{
+ VALUE sym = argv[0];
+ ID vid = rb_check_id(&sym);
+ if (vid) {
+ --argc;
+ ++argv;
+ }
+ else {
+ vid = id___send__;
+ }
+ return rb_funcallv_kw(recv, vid, argc, argv, RB_PASS_CALLED_KEYWORDS);
+}
+#endif
+
+enum rawmode_opt_ids {
+ kwd_min,
+ kwd_time,
+ kwd_intr,
+ rawmode_opt_id_count
+};
+static ID rawmode_opt_ids[rawmode_opt_id_count];
+
+typedef struct {
+ int vmin;
+ int vtime;
+ int intr;
+} rawmode_arg_t;
+
+#ifndef UNDEF_P
+# define UNDEF_P(obj) ((obj) == Qundef)
+#endif
+#ifndef NIL_OR_UNDEF_P
+# define NIL_OR_UNDEF_P(obj) (NIL_P(obj) || UNDEF_P(obj))
+#endif
+
+static rawmode_arg_t *
+rawmode_opt(int *argcp, VALUE *argv, int min_argc, int max_argc, rawmode_arg_t *opts)
+{
+ int argc = *argcp;
+ rawmode_arg_t *optp = NULL;
+ VALUE vopts = Qnil;
+ VALUE optvals[rawmode_opt_id_count];
+#ifdef RB_SCAN_ARGS_PASS_CALLED_KEYWORDS
+ argc = rb_scan_args(argc, argv, "*:", NULL, &vopts);
+#else
+ if (argc > min_argc) {
+ vopts = rb_check_hash_type(argv[argc-1]);
+ if (!NIL_P(vopts)) {
+ argv[argc-1] = vopts;
+ vopts = rb_extract_keywords(&argv[argc-1]);
+ if (!argv[argc-1]) *argcp = --argc;
+ if (!vopts) vopts = Qnil;
+ }
+ }
+#endif
+ rb_check_arity(argc, min_argc, max_argc);
+ if (rb_get_kwargs(vopts, rawmode_opt_ids,
+ 0, rawmode_opt_id_count, optvals)) {
+ VALUE vmin = optvals[kwd_min];
+ VALUE vtime = optvals[kwd_time];
+ VALUE intr = optvals[kwd_intr];
+ /* default values by `stty raw` */
+ opts->vmin = 1;
+ opts->vtime = 0;
+ opts->intr = 0;
+ if (!NIL_OR_UNDEF_P(vmin)) {
+ opts->vmin = NUM2INT(vmin);
+ optp = opts;
+ }
+ if (!NIL_OR_UNDEF_P(vtime)) {
+ VALUE v10 = INT2FIX(10);
+ vtime = rb_funcall3(vtime, '*', 1, &v10);
+ opts->vtime = NUM2INT(vtime);
+ optp = opts;
+ }
+ switch (intr) {
+ case Qtrue:
+ opts->intr = 1;
+ optp = opts;
+ break;
+ case Qfalse:
+ opts->intr = 0;
+ optp = opts;
+ break;
+ case Qundef:
+ case Qnil:
+ break;
+ default:
+ rb_raise(rb_eArgError, "true or false expected as intr: %"PRIsVALUE,
+ intr);
+ }
+ }
+ return optp;
+}
+
+static void
+set_rawmode(conmode *t, void *arg)
+{
+#ifdef HAVE_CFMAKERAW
+ cfmakeraw(t);
+ t->c_lflag &= ~(ECHOE|ECHOK);
+#elif defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
+ t->c_iflag &= ~(IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF|IXANY|IMAXBEL);
+ t->c_oflag &= ~OPOST;
+ t->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN|XCASE);
+ t->c_cflag &= ~(CSIZE|PARENB);
+ t->c_cflag |= CS8;
+ t->c_cc[VMIN] = 1;
+ t->c_cc[VTIME] = 0;
+#elif defined HAVE_SGTTY_H
+ t->sg_flags &= ~ECHO;
+ t->sg_flags |= RAW;
+#elif defined _WIN32
+ *t = 0;
+#endif
+ if (arg) {
+ const rawmode_arg_t *r = arg;
+#ifdef VMIN
+ if (r->vmin >= 0) t->c_cc[VMIN] = r->vmin;
+#endif
+#ifdef VTIME
+ if (r->vtime >= 0) t->c_cc[VTIME] = r->vtime;
+#endif
+#ifdef ISIG
+ if (r->intr) {
+ t->c_iflag |= BRKINT;
+ t->c_lflag |= ISIG;
+ t->c_oflag |= OPOST;
+ }
+#endif
+ (void)r;
+ }
+}
+
+static void
+set_cookedmode(conmode *t, void *arg)
+{
+#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
+ t->c_iflag |= (BRKINT|ISTRIP|ICRNL|IXON);
+ t->c_oflag |= OPOST;
+ t->c_lflag |= (ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN);
+#elif defined HAVE_SGTTY_H
+ t->sg_flags |= ECHO;
+ t->sg_flags &= ~RAW;
+#elif defined _WIN32
+ *t |= ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT;
+#endif
+}
+
+static void
+set_noecho(conmode *t, void *arg)
+{
+#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
+ t->c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
+#elif defined HAVE_SGTTY_H
+ t->sg_flags &= ~ECHO;
+#elif defined _WIN32
+ *t &= ~ENABLE_ECHO_INPUT;
+#endif
+}
+
+static void
+set_echo(conmode *t, void *arg)
+{
+#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
+ t->c_lflag |= (ECHO | ECHOE | ECHOK | ECHONL);
+#elif defined HAVE_SGTTY_H
+ t->sg_flags |= ECHO;
+#elif defined _WIN32
+ *t |= ENABLE_ECHO_INPUT;
+#endif
+}
+
+static int
+echo_p(conmode *t)
+{
+#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
+ return (t->c_lflag & (ECHO | ECHONL)) != 0;
+#elif defined HAVE_SGTTY_H
+ return (t->sg_flags & ECHO) != 0;
+#elif defined _WIN32
+ return (*t & ENABLE_ECHO_INPUT) != 0;
+#endif
+}
+
+static int
+set_ttymode(int fd, conmode *t, void (*setter)(conmode *, void *), void *arg)
+{
+ conmode r;
+ if (!getattr(fd, t)) return 0;
+ r = *t;
+ setter(&r, arg);
+ return setattr(fd, &r);
+}
+
+#define GetReadFD(io) rb_io_descriptor(io)
+#define GetWriteFD(io) rb_io_descriptor(rb_io_get_write_io(io))
+
+#define FD_PER_IO 2
+
+static VALUE
+ttymode(VALUE io, VALUE (*func)(VALUE), VALUE farg, void (*setter)(conmode *, void *), void *arg)
+{
+ int status = -1;
+ int error = 0;
+ int fd[FD_PER_IO];
+ conmode t[FD_PER_IO];
+ VALUE result = Qnil;
+
+ fd[0] = GetReadFD(io);
+ if (fd[0] != -1) {
+ if (set_ttymode(fd[0], t+0, setter, arg)) {
+ status = 0;
+ }
+ else {
+ error = errno;
+ fd[0] = -1;
+ }
+ }
+ fd[1] = GetWriteFD(io);
+ if (fd[1] != -1 && fd[1] != fd[0]) {
+ if (set_ttymode(fd[1], t+1, setter, arg)) {
+ status = 0;
+ }
+ else {
+ error = errno;
+ fd[1] = -1;
+ }
+ }
+ if (status == 0) {
+ result = rb_protect(func, farg, &status);
+ }
+ if (fd[0] != -1 && fd[0] == GetReadFD(io)) {
+ if (!setattr(fd[0], t+0)) {
+ error = errno;
+ status = -1;
+ }
+ }
+ if (fd[1] != -1 && fd[1] != fd[0] && fd[1] == GetWriteFD(io)) {
+ if (!setattr(fd[1], t+1)) {
+ error = errno;
+ status = -1;
+ }
+ }
+ if (status) {
+ if (status == -1) {
+ rb_syserr_fail(error, 0);
+ }
+ rb_jump_tag(status);
+ }
+ return result;
+}
+
+#if !defined _WIN32
+struct ttymode_callback_args {
+ VALUE (*func)(VALUE, VALUE);
+ VALUE io;
+ VALUE farg;
+};
+
+static VALUE
+ttymode_callback(VALUE args)
+{
+ struct ttymode_callback_args *argp = (struct ttymode_callback_args *)args;
+ return argp->func(argp->io, argp->farg);
+}
+
+static VALUE
+ttymode_with_io(VALUE io, VALUE (*func)(VALUE, VALUE), VALUE farg, void (*setter)(conmode *, void *), void *arg)
+{
+ struct ttymode_callback_args cargs;
+ cargs.func = func;
+ cargs.io = io;
+ cargs.farg = farg;
+ return ttymode(io, ttymode_callback, (VALUE)&cargs, setter, arg);
+}
+#endif
+
+/*
+ * call-seq:
+ * io.raw(min: nil, time: nil, intr: nil) {|io| }
+ *
+ * Yields +self+ within raw mode, and returns the result of the block.
+ *
+ * STDIN.raw(&:gets)
+ *
+ * will read and return a line without echo back and line editing.
+ *
+ * The parameter +min+ specifies the minimum number of bytes that
+ * should be received when a read operation is performed. (default: 1)
+ *
+ * The parameter +time+ specifies the timeout in _seconds_ with a
+ * precision of 1/10 of a second. (default: 0)
+ *
+ * If the parameter +intr+ is +true+, enables break, interrupt, quit,
+ * and suspend special characters.
+ *
+ * Refer to the manual page of termios for further details.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_raw(int argc, VALUE *argv, VALUE io)
+{
+ rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
+ return ttymode(io, rb_yield, io, set_rawmode, optp);
+}
+
+/*
+ * call-seq:
+ * io.raw!(min: nil, time: nil, intr: nil) -> io
+ *
+ * Enables raw mode, and returns +io+.
+ *
+ * If the terminal mode needs to be back, use <code>io.raw { ... }</code>.
+ *
+ * See IO#raw for details on the parameters.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_set_raw(int argc, VALUE *argv, VALUE io)
+{
+ conmode t;
+ rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
+ int fd = GetReadFD(io);
+ if (!getattr(fd, &t)) sys_fail(io);
+ set_rawmode(&t, optp);
+ if (!setattr(fd, &t)) sys_fail(io);
+ return io;
+}
+
+/*
+ * call-seq:
+ * io.cooked {|io| }
+ *
+ * Yields +self+ within cooked mode.
+ *
+ * STDIN.cooked(&:gets)
+ *
+ * will read and return a line with echo back and line editing.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_cooked(VALUE io)
+{
+ return ttymode(io, rb_yield, io, set_cookedmode, NULL);
+}
+
+/*
+ * call-seq:
+ * io.cooked!
+ *
+ * Enables cooked mode.
+ *
+ * If the terminal mode needs to be back, use io.cooked { ... }.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_set_cooked(VALUE io)
+{
+ conmode t;
+ int fd = GetReadFD(io);
+ if (!getattr(fd, &t)) sys_fail(io);
+ set_cookedmode(&t, NULL);
+ if (!setattr(fd, &t)) sys_fail(io);
+ return io;
+}
+
+#ifndef _WIN32
+static VALUE
+getc_call(VALUE io)
+{
+ return rb_funcallv(io, id_getc, 0, 0);
+}
+#else
+static void *
+nogvl_getch(void *p)
+{
+ int len = 0;
+ wint_t *buf = p, c = _getwch();
+
+ switch (c) {
+ case WEOF:
+ break;
+ case 0x00:
+ case 0xe0:
+ buf[len++] = c;
+ c = _getwch();
+ /* fall through */
+ default:
+ buf[len++] = c;
+ break;
+ }
+ return (void *)(VALUE)len;
+}
+#endif
+
+/*
+ * call-seq:
+ * io.getch(min: nil, time: nil, intr: nil) -> char
+ *
+ * Reads and returns a character in raw mode.
+ *
+ * See IO#raw for details on the parameters.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_getch(int argc, VALUE *argv, VALUE io)
+{
+ rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
+#ifndef _WIN32
+ return ttymode(io, getc_call, io, set_rawmode, optp);
+#else
+ rb_io_t *fptr;
+ VALUE str;
+ wint_t c;
+ int len;
+ char buf[8];
+ wint_t wbuf[2];
+# ifndef HAVE_RB_IO_WAIT
+ struct timeval *to = NULL, tv;
+# else
+ VALUE timeout = Qnil;
+# endif
+
+ GetOpenFile(io, fptr);
+ if (optp) {
+ if (optp->vtime) {
+# ifndef HAVE_RB_IO_WAIT
+ to = &tv;
+# else
+ struct timeval tv;
+# endif
+ tv.tv_sec = optp->vtime / 10;
+ tv.tv_usec = (optp->vtime % 10) * 100000;
+# ifdef HAVE_RB_IO_WAIT
+ timeout = rb_fiber_scheduler_make_timeout(&tv);
+# endif
+ }
+ switch (optp->vmin) {
+ case 1: /* default */
+ break;
+ case 0: /* return nil when timed out */
+ if (optp->vtime) break;
+ /* fallthru */
+ default:
+ rb_warning("min option larger than 1 ignored");
+ }
+ if (optp->intr) {
+# ifndef HAVE_RB_IO_WAIT
+ int w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to);
+ if (w < 0) rb_eof_error();
+ if (!(w & RB_WAITFD_IN)) return Qnil;
+# else
+ VALUE result = rb_io_wait(io, RB_INT2NUM(RUBY_IO_READABLE), timeout);
+ if (!RTEST(result)) return Qnil;
+# endif
+ }
+ else if (optp->vtime) {
+ rb_warning("Non-zero vtime option ignored if intr flag is unset");
+ }
+ }
+ len = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getch, wbuf, RUBY_UBF_IO, 0);
+ switch (len) {
+ case 0:
+ return Qnil;
+ case 2:
+ buf[0] = (char)wbuf[0];
+ c = wbuf[1];
+ len = 1;
+ do {
+ buf[len++] = (unsigned char)c;
+ } while ((c >>= CHAR_BIT) && len < (int)sizeof(buf));
+ return rb_str_new(buf, len);
+ default:
+ c = wbuf[0];
+ len = rb_uv_to_utf8(buf, c);
+ str = rb_utf8_str_new(buf, len);
+ return rb_str_conv_enc(str, NULL, rb_default_external_encoding());
+ }
+#endif
+}
+
+/*
+ * call-seq:
+ * io.noecho {|io| }
+ *
+ * Yields +self+ with disabling echo back.
+ *
+ * STDIN.noecho(&:gets)
+ *
+ * will read and return a line without echo back.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_noecho(VALUE io)
+{
+ return ttymode(io, rb_yield, io, set_noecho, NULL);
+}
+
+/*
+ * call-seq:
+ * io.echo = flag
+ *
+ * Enables/disables echo back.
+ * On some platforms, all combinations of this flags and raw/cooked
+ * mode may not be valid.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_set_echo(VALUE io, VALUE f)
+{
+ conmode t;
+ int fd = GetReadFD(io);
+
+ if (!getattr(fd, &t)) sys_fail(io);
+
+ if (RTEST(f))
+ set_echo(&t, NULL);
+ else
+ set_noecho(&t, NULL);
+
+ if (!setattr(fd, &t)) sys_fail(io);
+
+ return io;
+}
+
+/*
+ * call-seq:
+ * io.echo? -> true or false
+ *
+ * Returns +true+ if echo back is enabled.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_echo_p(VALUE io)
+{
+ conmode t;
+ int fd = GetReadFD(io);
+
+ if (!getattr(fd, &t)) sys_fail(io);
+ return echo_p(&t) ? Qtrue : Qfalse;
+}
+
+static const rb_data_type_t conmode_type = {
+ "console-mode",
+ {0, RUBY_TYPED_DEFAULT_FREE,},
+ 0, 0,
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+static VALUE cConmode;
+
+static VALUE
+conmode_alloc(VALUE klass)
+{
+ return rb_data_typed_object_zalloc(klass, sizeof(conmode), &conmode_type);
+}
+
+static VALUE
+conmode_new(VALUE klass, const conmode *t)
+{
+ VALUE obj = conmode_alloc(klass);
+ *(conmode *)DATA_PTR(obj) = *t;
+ return obj;
+}
+
+static VALUE
+conmode_init_copy(VALUE obj, VALUE obj2)
+{
+ conmode *t = rb_check_typeddata(obj, &conmode_type);
+ conmode *t2 = rb_check_typeddata(obj2, &conmode_type);
+ *t = *t2;
+ return obj;
+}
+
+static VALUE
+conmode_set_echo(VALUE obj, VALUE f)
+{
+ conmode *t = rb_check_typeddata(obj, &conmode_type);
+ if (RTEST(f))
+ set_echo(t, NULL);
+ else
+ set_noecho(t, NULL);
+ return obj;
+}
+
+static VALUE
+conmode_set_raw(int argc, VALUE *argv, VALUE obj)
+{
+ conmode *t = rb_check_typeddata(obj, &conmode_type);
+ rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
+
+ set_rawmode(t, optp);
+ return obj;
+}
+
+static VALUE
+conmode_raw_new(int argc, VALUE *argv, VALUE obj)
+{
+ conmode *r = rb_check_typeddata(obj, &conmode_type);
+ conmode t = *r;
+ rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
+
+ set_rawmode(&t, optp);
+ return conmode_new(rb_obj_class(obj), &t);
+}
+
+/*
+ * call-seq:
+ * io.console_mode -> mode
+ *
+ * Returns a data represents the current console mode.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_conmode_get(VALUE io)
+{
+ conmode t;
+ int fd = GetReadFD(io);
+
+ if (!getattr(fd, &t)) sys_fail(io);
+
+ return conmode_new(cConmode, &t);
+}
+
+/*
+ * call-seq:
+ * io.console_mode = mode
+ *
+ * Sets the console mode to +mode+.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_conmode_set(VALUE io, VALUE mode)
+{
+ conmode *t, r;
+ int fd = GetReadFD(io);
+
+ TypedData_Get_Struct(mode, conmode, &conmode_type, t);
+ r = *t;
+
+ if (!setattr(fd, &r)) sys_fail(io);
+
+ return mode;
+}
+
+#if defined TIOCGWINSZ
+typedef struct winsize rb_console_size_t;
+#define getwinsize(fd, buf) (ioctl((fd), TIOCGWINSZ, (buf)) == 0)
+#define setwinsize(fd, buf) (ioctl((fd), TIOCSWINSZ, (buf)) == 0)
+#define winsize_row(buf) (buf)->ws_row
+#define winsize_col(buf) (buf)->ws_col
+#elif defined _WIN32
+typedef CONSOLE_SCREEN_BUFFER_INFO rb_console_size_t;
+#define getwinsize(fd, buf) ( \
+ GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), (buf)) || \
+ SET_LAST_ERROR)
+#define winsize_row(buf) ((buf)->srWindow.Bottom - (buf)->srWindow.Top + 1)
+#define winsize_col(buf) (buf)->dwSize.X
+#endif
+
+#if defined TIOCGWINSZ || defined _WIN32
+#define USE_CONSOLE_GETSIZE 1
+#endif
+
+#ifdef USE_CONSOLE_GETSIZE
+/*
+ * call-seq:
+ * io.winsize -> [rows, columns]
+ *
+ * Returns console size.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_winsize(VALUE io)
+{
+ rb_console_size_t ws;
+ int fd = GetWriteFD(io);
+ if (!getwinsize(fd, &ws)) sys_fail(io);
+ return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws)));
+}
+
+static VALUE console_scroll(VALUE io, int line);
+static VALUE console_goto(VALUE io, VALUE y, VALUE x);
+
+/*
+ * call-seq:
+ * io.winsize = [rows, columns]
+ *
+ * Tries to set console size. The effect depends on the platform and
+ * the running environment.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_set_winsize(VALUE io, VALUE size)
+{
+ rb_console_size_t ws;
+#if defined _WIN32
+ HANDLE wh;
+ int newrow, newcol;
+ COORD oldsize;
+ SMALL_RECT oldwindow;
+#endif
+ VALUE row, col, xpixel, ypixel;
+ const VALUE *sz;
+ long sizelen;
+ int fd;
+
+ size = rb_Array(size);
+ if ((sizelen = RARRAY_LEN(size)) != 2 && sizelen != 4) {
+ rb_raise(rb_eArgError, "wrong number of arguments (given %ld, expected 2 or 4)", sizelen);
+ }
+ sz = RARRAY_CONST_PTR(size);
+ row = sz[0], col = sz[1], xpixel = ypixel = Qnil;
+ if (sizelen == 4) xpixel = sz[2], ypixel = sz[3];
+ fd = GetWriteFD(io);
+#if defined TIOCSWINSZ
+ ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0;
+#define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
+ SET(row);
+ SET(col);
+ SET(xpixel);
+ SET(ypixel);
+#undef SET
+ if (!setwinsize(fd, &ws)) sys_fail(io);
+#elif defined _WIN32
+ wh = (HANDLE)rb_w32_get_osfhandle(fd);
+#define SET(m) new##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
+ SET(row);
+ SET(col);
+#undef SET
+ if (!NIL_P(xpixel)) (void)NUM2UINT(xpixel);
+ if (!NIL_P(ypixel)) (void)NUM2UINT(ypixel);
+ if (!GetConsoleScreenBufferInfo(wh, &ws)) {
+ rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo");
+ }
+ oldsize = ws.dwSize;
+ oldwindow = ws.srWindow;
+ if (ws.srWindow.Right + 1 < newcol) {
+ ws.dwSize.X = newcol;
+ }
+ if (ws.dwSize.Y < newrow) {
+ ws.dwSize.Y = newrow;
+ }
+ /* expand screen buffer first if needed */
+ if (!SetConsoleScreenBufferSize(wh, ws.dwSize)) {
+ rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
+ }
+ /* refresh ws for new dwMaximumWindowSize */
+ if (!GetConsoleScreenBufferInfo(wh, &ws)) {
+ rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo");
+ }
+ /* check new size before modifying buffer content */
+ if (newrow <= 0 || newcol <= 0 ||
+ newrow > ws.dwMaximumWindowSize.Y ||
+ newcol > ws.dwMaximumWindowSize.X) {
+ SetConsoleScreenBufferSize(wh, oldsize);
+ /* remove scrollbar if possible */
+ SetConsoleWindowInfo(wh, TRUE, &oldwindow);
+ rb_raise(rb_eArgError, "out of range winsize: [%d, %d]", newrow, newcol);
+ }
+ /* shrink screen buffer width */
+ ws.dwSize.X = newcol;
+ /* shrink screen buffer height if window height were the same */
+ if (oldsize.Y == ws.srWindow.Bottom - ws.srWindow.Top + 1) {
+ ws.dwSize.Y = newrow;
+ }
+ ws.srWindow.Left = 0;
+ ws.srWindow.Right = newcol - 1;
+ ws.srWindow.Bottom = ws.srWindow.Top + newrow -1;
+ if (ws.dwCursorPosition.Y > ws.srWindow.Bottom) {
+ console_scroll(io, ws.dwCursorPosition.Y - ws.srWindow.Bottom);
+ ws.dwCursorPosition.Y = ws.srWindow.Bottom;
+ console_goto(io, INT2FIX(ws.dwCursorPosition.Y), INT2FIX(ws.dwCursorPosition.X));
+ }
+ if (ws.srWindow.Bottom > ws.dwSize.Y - 1) {
+ console_scroll(io, ws.srWindow.Bottom - (ws.dwSize.Y - 1));
+ ws.dwCursorPosition.Y -= ws.srWindow.Bottom - (ws.dwSize.Y - 1);
+ console_goto(io, INT2FIX(ws.dwCursorPosition.Y), INT2FIX(ws.dwCursorPosition.X));
+ ws.srWindow.Bottom = ws.dwSize.Y - 1;
+ }
+ ws.srWindow.Top = ws.srWindow.Bottom - (newrow - 1);
+ /* perform changes to winsize */
+ if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
+ int last_error = LAST_ERROR;
+ SetConsoleScreenBufferSize(wh, oldsize);
+ rb_syserr_fail(last_error, "SetConsoleWindowInfo");
+ }
+ /* perform screen buffer shrinking if necessary */
+ if ((ws.dwSize.Y < oldsize.Y || ws.dwSize.X < oldsize.X) &&
+ !SetConsoleScreenBufferSize(wh, ws.dwSize)) {
+ rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
+ }
+ /* remove scrollbar if possible */
+ if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
+ rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo");
+ }
+#endif
+ return io;
+}
+#endif
+
+#ifdef _WIN32
+/*
+ * call-seq:
+ * io.check_winsize_changed { ... } -> io
+ *
+ * Yields while console input events are queued.
+ *
+ * This method is Windows only.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_check_winsize_changed(VALUE io)
+{
+ HANDLE h;
+ DWORD num;
+
+ h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
+ while (GetNumberOfConsoleInputEvents(h, &num) && num > 0) {
+ INPUT_RECORD rec;
+ if (ReadConsoleInput(h, &rec, 1, &num)) {
+ if (rec.EventType == WINDOW_BUFFER_SIZE_EVENT) {
+ rb_yield(Qnil);
+ }
+ }
+ }
+ return io;
+}
+#else
+#define console_check_winsize_changed rb_f_notimplement
+#endif
+
+/*
+ * call-seq:
+ * io.iflush
+ *
+ * Flushes input buffer in kernel.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_iflush(VALUE io)
+{
+#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
+ int fd = GetReadFD(io);
+ if (tcflush(fd, TCIFLUSH)) sys_fail(io);
+#endif
+
+ return io;
+}
+
+/*
+ * call-seq:
+ * io.oflush
+ *
+ * Flushes output buffer in kernel.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_oflush(VALUE io)
+{
+ int fd = GetWriteFD(io);
+#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
+ if (tcflush(fd, TCOFLUSH)) sys_fail(io);
+#endif
+ (void)fd;
+ return io;
+}
+
+/*
+ * call-seq:
+ * io.ioflush
+ *
+ * Flushes input and output buffers in kernel.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_ioflush(VALUE io)
+{
+#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
+ int fd1 = GetReadFD(io);
+ int fd2 = GetWriteFD(io);
+
+ if (fd2 != -1 && fd1 != fd2) {
+ if (tcflush(fd1, TCIFLUSH)) sys_fail(io);
+ if (tcflush(fd2, TCOFLUSH)) sys_fail(io);
+ }
+ else {
+ if (tcflush(fd1, TCIOFLUSH)) sys_fail(io);
+ }
+#endif
+
+ return io;
+}
+
+/*
+ * call-seq:
+ * io.beep
+ *
+ * Beeps on the output console.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_beep(VALUE io)
+{
+#ifdef _WIN32
+ MessageBeep(0);
+#else
+ int fd = GetWriteFD(io);
+ if (write(fd, "\a", 1) < 0) sys_fail(io);
+#endif
+ return io;
+}
+
+static int
+mode_in_range(VALUE val, int high, const char *modename)
+{
+ int mode;
+ if (NIL_P(val)) return 0;
+ if (!RB_INTEGER_TYPE_P(val)) {
+ wrong_value:
+ rb_raise(rb_eArgError, "wrong %s mode: %"PRIsVALUE, modename, val);
+ }
+ if ((mode = NUM2INT(val)) < 0 || mode > high) {
+ goto wrong_value;
+ }
+ return mode;
+}
+
+#if defined _WIN32
+static void
+constat_clear(HANDLE handle, WORD attr, DWORD len, COORD pos)
+{
+ DWORD written;
+
+ FillConsoleOutputAttribute(handle, attr, len, pos, &written);
+ FillConsoleOutputCharacterW(handle, L' ', len, pos, &written);
+}
+
+static VALUE
+console_scroll(VALUE io, int line)
+{
+ HANDLE h;
+ rb_console_size_t ws;
+
+ h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
+ if (!GetConsoleScreenBufferInfo(h, &ws)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+ if (line) {
+ SMALL_RECT scroll;
+ COORD destination;
+ CHAR_INFO fill;
+ scroll.Left = 0;
+ scroll.Top = line > 0 ? line : 0;
+ scroll.Right = winsize_col(&ws) - 1;
+ scroll.Bottom = winsize_row(&ws) - 1 + (line < 0 ? line : 0);
+ destination.X = 0;
+ destination.Y = line < 0 ? -line : 0;
+ fill.Char.UnicodeChar = L' ';
+ fill.Attributes = ws.wAttributes;
+
+ ScrollConsoleScreenBuffer(h, &scroll, NULL, destination, &fill);
+ }
+ return io;
+}
+
+#define GPERF_DOWNCASE 1
+#define GPERF_CASE_STRCMP 1
+#define gperf_case_strcmp STRCASECMP
+#include "win32_vk.inc"
+
+/*
+ * call-seq:
+ * io.pressed?(key) -> bool
+ *
+ * Returns +true+ if +key+ is pressed. +key+ may be a virtual key
+ * code or its name (String or Symbol) with out "VK_" prefix.
+ *
+ * This method is Windows only.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_key_pressed_p(VALUE io, VALUE k)
+{
+ int vk = -1;
+
+ if (FIXNUM_P(k)) {
+ vk = NUM2UINT(k);
+ }
+ else {
+ const struct vktable *t;
+ const char *kn;
+ if (SYMBOL_P(k)) {
+ k = rb_sym2str(k);
+ kn = RSTRING_PTR(k);
+ }
+ else {
+ kn = StringValuePtr(k);
+ }
+ t = console_win32_vk(kn, RSTRING_LEN(k));
+ if (!t || (vk = (short)t->vk) == -1) {
+ rb_raise(rb_eArgError, "unknown virtual key code: % "PRIsVALUE, k);
+ }
+ }
+ return GetKeyState(vk) & 0x80 ? Qtrue : Qfalse;
+}
+#else
+struct query_args {
+ char qstr[6];
+ unsigned char opt;
+};
+
+static int
+direct_query(VALUE io, const struct query_args *query)
+{
+ if (RB_TYPE_P(io, T_FILE)) {
+ VALUE wio = rb_io_get_write_io(io);
+ VALUE s = rb_str_new_cstr(query->qstr);
+ rb_io_write(wio, s);
+ rb_io_flush(wio);
+ return 1;
+ }
+ return 0;
+}
+
+static VALUE
+read_vt_response(VALUE io, VALUE query)
+{
+ struct query_args *qargs = (struct query_args *)query;
+ VALUE result, b;
+ int opt = 0;
+ int num = 0;
+ if (qargs) {
+ opt = qargs->opt;
+ if (!direct_query(io, qargs)) return Qnil;
+ }
+ if (rb_io_getbyte(io) != INT2FIX(0x1b)) return Qnil;
+ if (rb_io_getbyte(io) != INT2FIX('[')) return Qnil;
+ result = rb_ary_new();
+ while (!NIL_P(b = rb_io_getbyte(io))) {
+ int c = NUM2UINT(b);
+ if (c == ';') {
+ rb_ary_push(result, INT2NUM(num));
+ num = 0;
+ }
+ else if (ISDIGIT(c)) {
+ num = num * 10 + c - '0';
+ }
+ else if (opt && c == opt) {
+ opt = 0;
+ }
+ else {
+ char last = (char)c;
+ rb_ary_push(result, INT2NUM(num));
+ b = rb_str_new(&last, 1);
+ break;
+ }
+ }
+ return rb_ary_push(result, b);
+}
+
+static VALUE
+console_vt_response(int argc, VALUE *argv, VALUE io, const struct query_args *qargs)
+{
+ rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 1, &opts);
+ VALUE query = (VALUE)qargs;
+ VALUE ret = ttymode_with_io(io, read_vt_response, query, set_rawmode, optp);
+ return ret;
+}
+
+static VALUE
+console_scroll(VALUE io, int line)
+{
+ if (line) {
+ VALUE s = rb_sprintf(CSI "%d%c", line < 0 ? -line : line,
+ line < 0 ? 'T' : 'S');
+ rb_io_write(io, s);
+ }
+ return io;
+}
+
+# define console_key_pressed_p rb_f_notimplement
+#endif
+
+/*
+ * call-seq:
+ * io.cursor -> [row, column]
+ *
+ * Returns the current cursor position as a two-element array of integers (row, column)
+ *
+ * io.cursor # => [3, 5]
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_cursor_pos(VALUE io)
+{
+#ifdef _WIN32
+ rb_console_size_t ws;
+ int fd = GetWriteFD(io);
+ if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+ return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y - ws.srWindow.Top), UINT2NUM(ws.dwCursorPosition.X));
+#else
+ static const struct query_args query = {"\033[6n", 0};
+ VALUE resp = console_vt_response(0, 0, io, &query);
+ VALUE row, column, term;
+ unsigned int r, c;
+ if (!RB_TYPE_P(resp, T_ARRAY) || RARRAY_LEN(resp) != 3) return Qnil;
+ term = RARRAY_AREF(resp, 2);
+ if (!RB_TYPE_P(term, T_STRING) || RSTRING_LEN(term) != 1) return Qnil;
+ if (RSTRING_PTR(term)[0] != 'R') return Qnil;
+ row = RARRAY_AREF(resp, 0);
+ column = RARRAY_AREF(resp, 1);
+ rb_ary_resize(resp, 2);
+ r = NUM2UINT(row) - 1;
+ c = NUM2UINT(column) - 1;
+ RARRAY_ASET(resp, 0, INT2NUM(r));
+ RARRAY_ASET(resp, 1, INT2NUM(c));
+ return resp;
+#endif
+}
+
+/*
+ * call-seq:
+ * io.goto(line, column) -> io
+ *
+ * Set the cursor position at +line+ and +column+.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_goto(VALUE io, VALUE y, VALUE x)
+{
+#ifdef _WIN32
+ HANDLE h;
+ rb_console_size_t ws;
+ COORD *pos = &ws.dwCursorPosition;
+
+ h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
+ if (!GetConsoleScreenBufferInfo(h, &ws)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+ pos->X = NUM2UINT(x);
+ pos->Y = ws.srWindow.Top + NUM2UINT(y);
+ if (!SetConsoleCursorPosition(h, *pos)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+#else
+ rb_io_write(io, rb_sprintf(CSI "%d;%dH", NUM2UINT(y)+1, NUM2UINT(x)+1));
+#endif
+ return io;
+}
+
+static VALUE
+console_move(VALUE io, int y, int x)
+{
+#ifdef _WIN32
+ HANDLE h;
+ rb_console_size_t ws;
+ COORD *pos = &ws.dwCursorPosition;
+
+ h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
+ if (!GetConsoleScreenBufferInfo(h, &ws)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+ pos->X += x;
+ pos->Y += y;
+ if (!SetConsoleCursorPosition(h, *pos)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+#else
+ if (x || y) {
+ VALUE s = rb_str_new_cstr("");
+ if (y) rb_str_catf(s, CSI "%d%c", y < 0 ? -y : y, y < 0 ? 'A' : 'B');
+ if (x) rb_str_catf(s, CSI "%d%c", x < 0 ? -x : x, x < 0 ? 'D' : 'C');
+ rb_io_write(io, s);
+ rb_io_flush(io);
+ }
+#endif
+ return io;
+}
+
+/*
+ * call-seq:
+ * io.goto_column(column) -> io
+ *
+ * Set the cursor position at +column+ in the same line of the current
+ * position.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_goto_column(VALUE io, VALUE val)
+{
+#ifdef _WIN32
+ HANDLE h;
+ rb_console_size_t ws;
+ COORD *pos = &ws.dwCursorPosition;
+
+ h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
+ if (!GetConsoleScreenBufferInfo(h, &ws)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+ pos->X = NUM2INT(val);
+ if (!SetConsoleCursorPosition(h, *pos)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+#else
+ rb_io_write(io, rb_sprintf(CSI "%dG", NUM2UINT(val)+1));
+#endif
+ return io;
+}
+
+/*
+ * call-seq:
+ * io.erase_line(mode) -> io
+ *
+ * Erases the line at the cursor corresponding to +mode+.
+ * +mode+ may be either:
+ * 0: after cursor
+ * 1: before and cursor
+ * 2: entire line
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_erase_line(VALUE io, VALUE val)
+{
+ int mode = mode_in_range(val, 2, "line erase");
+#ifdef _WIN32
+ HANDLE h;
+ rb_console_size_t ws;
+ COORD *pos = &ws.dwCursorPosition;
+ DWORD w;
+
+ h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
+ if (!GetConsoleScreenBufferInfo(h, &ws)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+ w = winsize_col(&ws);
+ switch (mode) {
+ case 0: /* after cursor */
+ w -= pos->X;
+ break;
+ case 1: /* before *and* cursor */
+ w = pos->X + 1;
+ pos->X = 0;
+ break;
+ case 2: /* entire line */
+ pos->X = 0;
+ break;
+ }
+ constat_clear(h, ws.wAttributes, w, *pos);
+ return io;
+#else
+ rb_io_write(io, rb_sprintf(CSI "%dK", mode));
+#endif
+ return io;
+}
+
+/*
+ * call-seq:
+ * io.erase_screen(mode) -> io
+ *
+ * Erases the screen at the cursor corresponding to +mode+.
+ * +mode+ may be either:
+ * 0: after cursor
+ * 1: before and cursor
+ * 2: entire screen
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_erase_screen(VALUE io, VALUE val)
+{
+ int mode = mode_in_range(val, 3, "screen erase");
+#ifdef _WIN32
+ HANDLE h;
+ rb_console_size_t ws;
+ COORD *pos = &ws.dwCursorPosition;
+ DWORD w;
+
+ h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
+ if (!GetConsoleScreenBufferInfo(h, &ws)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+ w = winsize_col(&ws);
+ switch (mode) {
+ case 0: /* erase after cursor */
+ w = (w * (ws.srWindow.Bottom - pos->Y + 1) - pos->X);
+ break;
+ case 1: /* erase before *and* cursor */
+ w = (w * (pos->Y - ws.srWindow.Top) + pos->X + 1);
+ pos->X = 0;
+ pos->Y = ws.srWindow.Top;
+ break;
+ case 2: /* erase entire screen */
+ w = (w * winsize_row(&ws));
+ pos->X = 0;
+ pos->Y = ws.srWindow.Top;
+ break;
+ case 3: /* erase entire screen */
+ w = (w * ws.dwSize.Y);
+ pos->X = 0;
+ pos->Y = 0;
+ break;
+ }
+ constat_clear(h, ws.wAttributes, w, *pos);
+#else
+ rb_io_write(io, rb_sprintf(CSI "%dJ", mode));
+#endif
+ return io;
+}
+
+/*
+ * call-seq:
+ * io.cursor = [line, column] -> io
+ *
+ * Same as <tt>io.goto(line, column)</tt>
+ *
+ * See IO#goto.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_cursor_set(VALUE io, VALUE cpos)
+{
+ cpos = rb_convert_type(cpos, T_ARRAY, "Array", "to_ary");
+ if (RARRAY_LEN(cpos) != 2) rb_raise(rb_eArgError, "expected 2D coordinate");
+ return console_goto(io, RARRAY_AREF(cpos, 0), RARRAY_AREF(cpos, 1));
+}
+
+/*
+ * call-seq:
+ * io.cursor_up(n) -> io
+ *
+ * Moves the cursor up +n+ lines.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_cursor_up(VALUE io, VALUE val)
+{
+ return console_move(io, -NUM2INT(val), 0);
+}
+
+/*
+ * call-seq:
+ * io.cursor_down(n) -> io
+ *
+ * Moves the cursor down +n+ lines.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_cursor_down(VALUE io, VALUE val)
+{
+ return console_move(io, +NUM2INT(val), 0);
+}
+
+/*
+ * call-seq:
+ * io.cursor_left(n) -> io
+ *
+ * Moves the cursor left +n+ columns.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_cursor_left(VALUE io, VALUE val)
+{
+ return console_move(io, 0, -NUM2INT(val));
+}
+
+/*
+ * call-seq:
+ * io.cursor_right(n) -> io
+ *
+ * Moves the cursor right +n+ columns.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_cursor_right(VALUE io, VALUE val)
+{
+ return console_move(io, 0, +NUM2INT(val));
+}
+
+/*
+ * call-seq:
+ * io.scroll_forward(n) -> io
+ *
+ * Scrolls the entire scrolls forward +n+ lines.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_scroll_forward(VALUE io, VALUE val)
+{
+ return console_scroll(io, +NUM2INT(val));
+}
+
+/*
+ * call-seq:
+ * io.scroll_backward(n) -> io
+ *
+ * Scrolls the entire scrolls backward +n+ lines.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_scroll_backward(VALUE io, VALUE val)
+{
+ return console_scroll(io, -NUM2INT(val));
+}
+
+/*
+ * call-seq:
+ * io.clear_screen -> io
+ *
+ * Clears the entire screen and moves the cursor top-left corner.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_clear_screen(VALUE io)
+{
+ console_erase_screen(io, INT2FIX(2));
+ console_goto(io, INT2FIX(0), INT2FIX(0));
+ return io;
+}
+
+#ifndef HAVE_RB_IO_OPEN_DESCRIPTOR
+static VALUE
+io_open_descriptor_fallback(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, void *encoding)
+{
+ VALUE arguments[2] = {
+ (rb_update_max_fd(descriptor), INT2NUM(descriptor)),
+ INT2FIX(mode),
+ };
+
+ VALUE self = rb_class_new_instance(2, arguments, klass);
+
+ rb_io_t *fptr;
+ GetOpenFile(self, fptr);
+ fptr->pathv = path;
+ fptr->mode |= mode;
+
+ return self;
+}
+#define rb_io_open_descriptor io_open_descriptor_fallback
+#endif
+
+#ifndef HAVE_RB_IO_CLOSED_P
+static VALUE
+rb_io_closed_p(VALUE io)
+{
+ rb_io_t *fptr = RFILE(io)->fptr;
+ return fptr->fd == -1 ? Qtrue : Qfalse;
+}
+#endif
+
+#if defined(RB_EXT_RACTOR_SAFE) && defined(HAVE_RB_RACTOR_LOCAL_STORAGE_VALUE_NEWKEY)
+# define USE_RACTOR_STORAGE 1
+#else
+# define USE_RACTOR_STORAGE 0
+#endif
+
+#if USE_RACTOR_STORAGE
+#include "ruby/ractor.h"
+static rb_ractor_local_key_t key_console_dev;
+
+static bool
+console_dev_get(VALUE klass, VALUE *dev)
+{
+ return rb_ractor_local_storage_value_lookup(key_console_dev, dev);
+}
+
+static void
+console_dev_set(VALUE klass, VALUE value)
+{
+ rb_ractor_local_storage_value_set(key_console_dev, value);
+}
+
+static void
+console_dev_remove(VALUE klass)
+{
+ console_dev_set(klass, Qnil);
+}
+
+#else
+
+static ID id_console;
+
+static int
+console_dev_get(VALUE klass, VALUE *dev)
+{
+ if (rb_const_defined(klass, id_console)) {
+ *dev = rb_const_get(klass, id_console);
+ return 1;
+ }
+ return 0;
+}
+
+static void
+console_dev_set(VALUE klass, VALUE value)
+{
+ rb_const_set(klass, id_console, value);
+}
+
+static void
+console_dev_remove(VALUE klass)
+{
+ rb_const_remove(klass, id_console);
+}
+
+#endif
+
+/*
+ * call-seq:
+ * IO.console -> #<File:/dev/tty>
+ * IO.console(sym, *args)
+ *
+ * Returns an File instance opened console.
+ *
+ * If +sym+ is given, it will be sent to the opened console with
+ * +args+ and the result will be returned instead of the console IO
+ * itself.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_dev(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE con = 0;
+ VALUE sym = 0;
+
+ if (argc) {
+ Check_Type(sym = argv[0], T_SYMBOL);
+ }
+
+ /* Force the class to be File. */
+ if (klass == rb_cIO) klass = rb_cFile;
+
+ if (console_dev_get(klass, &con)) {
+ if (!RB_TYPE_P(con, T_FILE) || RTEST(rb_io_closed_p(con))) {
+ console_dev_remove(klass);
+ con = 0;
+ }
+ }
+
+ if (sym) {
+ if (sym == ID2SYM(id_close) && argc == 1) {
+ if (con) {
+ rb_io_close(con);
+ console_dev_remove(klass);
+ con = 0;
+ }
+ return Qnil;
+ }
+ }
+
+ if (!con) {
+#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H || defined HAVE_SGTTY_H
+# define CONSOLE_DEVICE "/dev/tty"
+#elif defined _WIN32
+# define CONSOLE_DEVICE "con$"
+# define CONSOLE_DEVICE_FOR_READING "conin$"
+# define CONSOLE_DEVICE_FOR_WRITING "conout$"
+#endif
+#ifndef CONSOLE_DEVICE_FOR_READING
+# define CONSOLE_DEVICE_FOR_READING CONSOLE_DEVICE
+#endif
+#ifdef CONSOLE_DEVICE_FOR_WRITING
+ VALUE out;
+#endif
+ int fd;
+ VALUE path = rb_obj_freeze(rb_str_new2(CONSOLE_DEVICE));
+
+#ifdef CONSOLE_DEVICE_FOR_WRITING
+ fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_WRITING, O_RDWR, 0);
+ if (fd < 0) return Qnil;
+ out = rb_io_open_descriptor(klass, fd, FMODE_WRITABLE | FMODE_SYNC, path, Qnil, NULL);
+#endif
+ fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_READING, O_RDWR, 0);
+ if (fd < 0) {
+#ifdef CONSOLE_DEVICE_FOR_WRITING
+ rb_io_close(out);
+#endif
+ return Qnil;
+ }
+
+ con = rb_io_open_descriptor(klass, fd, FMODE_READWRITE | FMODE_SYNC, path, Qnil, NULL);
+#ifdef CONSOLE_DEVICE_FOR_WRITING
+ rb_io_set_write_io(con, out);
+#endif
+ console_dev_set(klass, con);
+ }
+
+ if (sym) {
+ return rb_f_send(argc, argv, con);
+ }
+
+ return con;
+}
+
+/*
+ * call-seq:
+ * io.getch(min: nil, time: nil, intr: nil) -> char
+ *
+ * See IO#getch.
+ */
+static VALUE
+io_getch(int argc, VALUE *argv, VALUE io)
+{
+ return rb_funcallv(io, id_getc, argc, argv);
+}
+
+static VALUE
+puts_call(VALUE io)
+{
+ return rb_io_write(io, rb_default_rs);
+}
+
+static VALUE
+gets_call(VALUE io)
+{
+ return rb_funcallv(io, id_gets, 0, 0);
+}
+
+static VALUE
+getpass_call(VALUE io)
+{
+ return ttymode(io, rb_io_gets, io, set_noecho, NULL);
+}
+
+static void
+prompt(int argc, VALUE *argv, VALUE io)
+{
+ if (argc > 0 && !NIL_P(argv[0])) {
+ VALUE str = argv[0];
+ StringValueCStr(str);
+ rb_io_write(io, str);
+ }
+}
+
+static VALUE
+str_chomp(VALUE str)
+{
+ if (!NIL_P(str)) {
+ const VALUE rs = rb_default_rs; /* rvalue in TruffleRuby */
+ rb_funcallv(str, id_chomp_bang, 1, &rs);
+ }
+ return str;
+}
+
+/*
+ * call-seq:
+ * io.getpass(prompt=nil) -> string
+ *
+ * Reads and returns a line without echo back.
+ * Prints +prompt+ unless it is +nil+.
+ *
+ * The newline character that terminates the
+ * read line is removed from the returned string,
+ * see String#chomp!.
+ *
+ * You must require 'io/console' to use this method.
+ *
+ * require 'io/console'
+ * IO::console.getpass("Enter password:")
+ * Enter password:
+ * # => "mypassword"
+ *
+ */
+static VALUE
+console_getpass(int argc, VALUE *argv, VALUE io)
+{
+ VALUE str, wio;
+
+ rb_check_arity(argc, 0, 1);
+ wio = rb_io_get_write_io(io);
+ if (wio == io && io == rb_stdin) wio = rb_stderr;
+ prompt(argc, argv, wio);
+ rb_io_flush(wio);
+ str = rb_ensure(getpass_call, io, puts_call, wio);
+ return str_chomp(str);
+}
+
+/*
+ * call-seq:
+ * io.getpass(prompt=nil) -> string
+ *
+ * See IO#getpass.
+ */
+static VALUE
+io_getpass(int argc, VALUE *argv, VALUE io)
+{
+ VALUE str;
+
+ rb_check_arity(argc, 0, 1);
+ prompt(argc, argv, io);
+ rb_check_funcall(io, id_flush, 0, 0);
+ str = rb_ensure(gets_call, io, puts_call, io);
+ return str_chomp(str);
+}
+
+#if defined(_WIN32) || defined(HAVE_TTYNAME_R) || defined(HAVE_TTYNAME)
+/*
+ * call-seq:
+ * io.ttyname -> string or nil
+ *
+ * Returns name of associated terminal (tty) if +io+ is not a tty.
+ * Returns +nil+ otherwise.
+ */
+static VALUE
+console_ttyname(VALUE io)
+{
+ int fd = rb_io_descriptor(io);
+ if (!isatty(fd)) return Qnil;
+# if defined _WIN32
+ return rb_usascii_str_new_lit("con");
+# elif defined HAVE_TTYNAME_R
+ {
+ char termname[1024], *tn = termname;
+ size_t size = sizeof(termname);
+ int e;
+ if (ttyname_r(fd, tn, size) == 0)
+ return rb_interned_str_cstr(tn);
+ if ((e = errno) == ERANGE) {
+ VALUE s = rb_str_new(0, size);
+ while (1) {
+ tn = RSTRING_PTR(s);
+ size = rb_str_capacity(s);
+ if (ttyname_r(fd, tn, size) == 0) {
+ return rb_str_to_interned_str(rb_str_resize(s, strlen(tn)));
+ }
+ if ((e = errno) != ERANGE) break;
+ if ((size *= 2) >= INT_MAX/2) break;
+ rb_str_resize(s, size);
+ }
+ }
+ rb_syserr_fail_str(e, rb_sprintf("ttyname_r(%d)", fd));
+ UNREACHABLE_RETURN(Qnil);
+ }
+# elif defined HAVE_TTYNAME
+ {
+ const char *tn = ttyname(fd);
+ if (!tn) {
+ int e = errno;
+ rb_syserr_fail_str(e, rb_sprintf("ttyname(%d)", fd));
+ }
+ return rb_interned_str_cstr(tn);
+ }
+# else
+# error No ttyname function
+# endif
+}
+#else
+# define console_ttyname rb_f_notimplement
+#endif
+
+/*
+ * IO console methods
+ */
+void
+Init_console(void)
+{
+#if USE_RACTOR_STORAGE
+ RB_EXT_RACTOR_SAFE(true);
+#endif
+
+#undef rb_intern
+#if USE_RACTOR_STORAGE
+ key_console_dev = rb_ractor_local_storage_value_newkey();
+#else
+ id_console = rb_intern("console");
+#endif
+ id_getc = rb_intern("getc");
+ id_gets = rb_intern("gets");
+ id_flush = rb_intern("flush");
+ id_chomp_bang = rb_intern("chomp!");
+ id_close = rb_intern("close");
+#define init_rawmode_opt_id(name) \
+ rawmode_opt_ids[kwd_##name] = rb_intern(#name)
+ init_rawmode_opt_id(min);
+ init_rawmode_opt_id(time);
+ init_rawmode_opt_id(intr);
+#ifndef HAVE_RB_F_SEND
+ id___send__ = rb_intern("__send__");
+#endif
+ InitVM(console);
+}
+
+void
+InitVM_console(void)
+{
+ rb_define_method(rb_cIO, "raw", console_raw, -1);
+ rb_define_method(rb_cIO, "raw!", console_set_raw, -1);
+ rb_define_method(rb_cIO, "cooked", console_cooked, 0);
+ rb_define_method(rb_cIO, "cooked!", console_set_cooked, 0);
+ rb_define_method(rb_cIO, "getch", console_getch, -1);
+ rb_define_method(rb_cIO, "echo=", console_set_echo, 1);
+ rb_define_method(rb_cIO, "echo?", console_echo_p, 0);
+ rb_define_method(rb_cIO, "console_mode", console_conmode_get, 0);
+ rb_define_method(rb_cIO, "console_mode=", console_conmode_set, 1);
+ rb_define_method(rb_cIO, "noecho", console_noecho, 0);
+ rb_define_method(rb_cIO, "winsize", console_winsize, 0);
+ rb_define_method(rb_cIO, "winsize=", console_set_winsize, 1);
+ rb_define_method(rb_cIO, "iflush", console_iflush, 0);
+ rb_define_method(rb_cIO, "oflush", console_oflush, 0);
+ rb_define_method(rb_cIO, "ioflush", console_ioflush, 0);
+ rb_define_method(rb_cIO, "beep", console_beep, 0);
+ rb_define_method(rb_cIO, "goto", console_goto, 2);
+ rb_define_method(rb_cIO, "cursor", console_cursor_pos, 0);
+ rb_define_method(rb_cIO, "cursor=", console_cursor_set, 1);
+ rb_define_method(rb_cIO, "cursor_up", console_cursor_up, 1);
+ rb_define_method(rb_cIO, "cursor_down", console_cursor_down, 1);
+ rb_define_method(rb_cIO, "cursor_left", console_cursor_left, 1);
+ rb_define_method(rb_cIO, "cursor_right", console_cursor_right, 1);
+ rb_define_method(rb_cIO, "goto_column", console_goto_column, 1);
+ rb_define_method(rb_cIO, "erase_line", console_erase_line, 1);
+ rb_define_method(rb_cIO, "erase_screen", console_erase_screen, 1);
+ rb_define_method(rb_cIO, "scroll_forward", console_scroll_forward, 1);
+ rb_define_method(rb_cIO, "scroll_backward", console_scroll_backward, 1);
+ rb_define_method(rb_cIO, "clear_screen", console_clear_screen, 0);
+ rb_define_method(rb_cIO, "pressed?", console_key_pressed_p, 1);
+ rb_define_method(rb_cIO, "check_winsize_changed", console_check_winsize_changed, 0);
+ rb_define_method(rb_cIO, "getpass", console_getpass, -1);
+ rb_define_method(rb_cIO, "ttyname", console_ttyname, 0);
+ rb_define_singleton_method(rb_cIO, "console", console_dev, -1);
+ {
+ /* :nodoc: */
+ VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
+ rb_define_method(mReadable, "getch", io_getch, -1);
+ rb_define_method(mReadable, "getpass", io_getpass, -1);
+ }
+ {
+ /* :nodoc: */
+ cConmode = rb_define_class_under(rb_cIO, "ConsoleMode", rb_cObject);
+ rb_define_const(cConmode, "VERSION", rb_obj_freeze(rb_str_new_cstr(IO_CONSOLE_VERSION)));
+ rb_define_alloc_func(cConmode, conmode_alloc);
+ rb_undef_method(cConmode, "initialize");
+ rb_define_method(cConmode, "initialize_copy", conmode_init_copy, 1);
+ rb_define_method(cConmode, "echo=", conmode_set_echo, 1);
+ rb_define_method(cConmode, "raw!", conmode_set_raw, -1);
+ rb_define_method(cConmode, "raw", conmode_raw_new, -1);
+ }
+}
diff --git a/ext/io/console/depend b/ext/io/console/depend
new file mode 100644
index 0000000000..150a138d4d
--- /dev/null
+++ b/ext/io/console/depend
@@ -0,0 +1,199 @@
+# AUTOGENERATED DEPENDENCIES START
+console.o: $(RUBY_EXTCONF_H)
+console.o: $(arch_hdrdir)/ruby/config.h
+console.o: $(hdrdir)/ruby.h
+console.o: $(hdrdir)/ruby/assert.h
+console.o: $(hdrdir)/ruby/backward.h
+console.o: $(hdrdir)/ruby/backward/2/assume.h
+console.o: $(hdrdir)/ruby/backward/2/attributes.h
+console.o: $(hdrdir)/ruby/backward/2/bool.h
+console.o: $(hdrdir)/ruby/backward/2/inttypes.h
+console.o: $(hdrdir)/ruby/backward/2/limits.h
+console.o: $(hdrdir)/ruby/backward/2/long_long.h
+console.o: $(hdrdir)/ruby/backward/2/stdalign.h
+console.o: $(hdrdir)/ruby/backward/2/stdarg.h
+console.o: $(hdrdir)/ruby/defines.h
+console.o: $(hdrdir)/ruby/encoding.h
+console.o: $(hdrdir)/ruby/fiber/scheduler.h
+console.o: $(hdrdir)/ruby/intern.h
+console.o: $(hdrdir)/ruby/internal/abi.h
+console.o: $(hdrdir)/ruby/internal/anyargs.h
+console.o: $(hdrdir)/ruby/internal/arithmetic.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+console.o: $(hdrdir)/ruby/internal/assume.h
+console.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+console.o: $(hdrdir)/ruby/internal/attr/artificial.h
+console.o: $(hdrdir)/ruby/internal/attr/cold.h
+console.o: $(hdrdir)/ruby/internal/attr/const.h
+console.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+console.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+console.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+console.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+console.o: $(hdrdir)/ruby/internal/attr/error.h
+console.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+console.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+console.o: $(hdrdir)/ruby/internal/attr/format.h
+console.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+console.o: $(hdrdir)/ruby/internal/attr/noalias.h
+console.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+console.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+console.o: $(hdrdir)/ruby/internal/attr/noinline.h
+console.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+console.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+console.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+console.o: $(hdrdir)/ruby/internal/attr/pure.h
+console.o: $(hdrdir)/ruby/internal/attr/restrict.h
+console.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+console.o: $(hdrdir)/ruby/internal/attr/warning.h
+console.o: $(hdrdir)/ruby/internal/attr/weakref.h
+console.o: $(hdrdir)/ruby/internal/cast.h
+console.o: $(hdrdir)/ruby/internal/compiler_is.h
+console.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+console.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+console.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+console.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+console.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+console.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+console.o: $(hdrdir)/ruby/internal/compiler_since.h
+console.o: $(hdrdir)/ruby/internal/config.h
+console.o: $(hdrdir)/ruby/internal/constant_p.h
+console.o: $(hdrdir)/ruby/internal/core.h
+console.o: $(hdrdir)/ruby/internal/core/rarray.h
+console.o: $(hdrdir)/ruby/internal/core/rbasic.h
+console.o: $(hdrdir)/ruby/internal/core/rbignum.h
+console.o: $(hdrdir)/ruby/internal/core/rclass.h
+console.o: $(hdrdir)/ruby/internal/core/rdata.h
+console.o: $(hdrdir)/ruby/internal/core/rfile.h
+console.o: $(hdrdir)/ruby/internal/core/rhash.h
+console.o: $(hdrdir)/ruby/internal/core/robject.h
+console.o: $(hdrdir)/ruby/internal/core/rregexp.h
+console.o: $(hdrdir)/ruby/internal/core/rstring.h
+console.o: $(hdrdir)/ruby/internal/core/rstruct.h
+console.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+console.o: $(hdrdir)/ruby/internal/ctype.h
+console.o: $(hdrdir)/ruby/internal/dllexport.h
+console.o: $(hdrdir)/ruby/internal/dosish.h
+console.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+console.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+console.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+console.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+console.o: $(hdrdir)/ruby/internal/encoding/re.h
+console.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+console.o: $(hdrdir)/ruby/internal/encoding/string.h
+console.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+console.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+console.o: $(hdrdir)/ruby/internal/error.h
+console.o: $(hdrdir)/ruby/internal/eval.h
+console.o: $(hdrdir)/ruby/internal/event.h
+console.o: $(hdrdir)/ruby/internal/fl_type.h
+console.o: $(hdrdir)/ruby/internal/gc.h
+console.o: $(hdrdir)/ruby/internal/glob.h
+console.o: $(hdrdir)/ruby/internal/globals.h
+console.o: $(hdrdir)/ruby/internal/has/attribute.h
+console.o: $(hdrdir)/ruby/internal/has/builtin.h
+console.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+console.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+console.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+console.o: $(hdrdir)/ruby/internal/has/extension.h
+console.o: $(hdrdir)/ruby/internal/has/feature.h
+console.o: $(hdrdir)/ruby/internal/has/warning.h
+console.o: $(hdrdir)/ruby/internal/intern/array.h
+console.o: $(hdrdir)/ruby/internal/intern/bignum.h
+console.o: $(hdrdir)/ruby/internal/intern/class.h
+console.o: $(hdrdir)/ruby/internal/intern/compar.h
+console.o: $(hdrdir)/ruby/internal/intern/complex.h
+console.o: $(hdrdir)/ruby/internal/intern/cont.h
+console.o: $(hdrdir)/ruby/internal/intern/dir.h
+console.o: $(hdrdir)/ruby/internal/intern/enum.h
+console.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+console.o: $(hdrdir)/ruby/internal/intern/error.h
+console.o: $(hdrdir)/ruby/internal/intern/eval.h
+console.o: $(hdrdir)/ruby/internal/intern/file.h
+console.o: $(hdrdir)/ruby/internal/intern/hash.h
+console.o: $(hdrdir)/ruby/internal/intern/io.h
+console.o: $(hdrdir)/ruby/internal/intern/load.h
+console.o: $(hdrdir)/ruby/internal/intern/marshal.h
+console.o: $(hdrdir)/ruby/internal/intern/numeric.h
+console.o: $(hdrdir)/ruby/internal/intern/object.h
+console.o: $(hdrdir)/ruby/internal/intern/parse.h
+console.o: $(hdrdir)/ruby/internal/intern/proc.h
+console.o: $(hdrdir)/ruby/internal/intern/process.h
+console.o: $(hdrdir)/ruby/internal/intern/random.h
+console.o: $(hdrdir)/ruby/internal/intern/range.h
+console.o: $(hdrdir)/ruby/internal/intern/rational.h
+console.o: $(hdrdir)/ruby/internal/intern/re.h
+console.o: $(hdrdir)/ruby/internal/intern/ruby.h
+console.o: $(hdrdir)/ruby/internal/intern/select.h
+console.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+console.o: $(hdrdir)/ruby/internal/intern/set.h
+console.o: $(hdrdir)/ruby/internal/intern/signal.h
+console.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+console.o: $(hdrdir)/ruby/internal/intern/string.h
+console.o: $(hdrdir)/ruby/internal/intern/struct.h
+console.o: $(hdrdir)/ruby/internal/intern/thread.h
+console.o: $(hdrdir)/ruby/internal/intern/time.h
+console.o: $(hdrdir)/ruby/internal/intern/variable.h
+console.o: $(hdrdir)/ruby/internal/intern/vm.h
+console.o: $(hdrdir)/ruby/internal/interpreter.h
+console.o: $(hdrdir)/ruby/internal/iterator.h
+console.o: $(hdrdir)/ruby/internal/memory.h
+console.o: $(hdrdir)/ruby/internal/method.h
+console.o: $(hdrdir)/ruby/internal/module.h
+console.o: $(hdrdir)/ruby/internal/newobj.h
+console.o: $(hdrdir)/ruby/internal/scan_args.h
+console.o: $(hdrdir)/ruby/internal/special_consts.h
+console.o: $(hdrdir)/ruby/internal/static_assert.h
+console.o: $(hdrdir)/ruby/internal/stdalign.h
+console.o: $(hdrdir)/ruby/internal/stdbool.h
+console.o: $(hdrdir)/ruby/internal/stdckdint.h
+console.o: $(hdrdir)/ruby/internal/symbol.h
+console.o: $(hdrdir)/ruby/internal/value.h
+console.o: $(hdrdir)/ruby/internal/value_type.h
+console.o: $(hdrdir)/ruby/internal/variable.h
+console.o: $(hdrdir)/ruby/internal/warning_push.h
+console.o: $(hdrdir)/ruby/internal/xmalloc.h
+console.o: $(hdrdir)/ruby/io.h
+console.o: $(hdrdir)/ruby/missing.h
+console.o: $(hdrdir)/ruby/onigmo.h
+console.o: $(hdrdir)/ruby/oniguruma.h
+console.o: $(hdrdir)/ruby/ractor.h
+console.o: $(hdrdir)/ruby/ruby.h
+console.o: $(hdrdir)/ruby/st.h
+console.o: $(hdrdir)/ruby/subst.h
+console.o: $(hdrdir)/ruby/thread.h
+console.o: console.c
+# AUTOGENERATED DEPENDENCIES END
+
+win32_vk.inc: win32_vk.list
+
+.list.inc:
+ ( \
+ $(RUBY) -anF, \
+ -e 'BEGIN {puts "#define UNDEFINED_VK (unsigned short)-1"}' \
+ -e 'n=$$F[1] and (n.strip!; /\AVK_/=~n) and' \
+ -e 'puts(%[#ifndef #{n}\n# define #{n} UNDEFINED_VK\n#endif])' \
+ $< && \
+ gperf --ignore-case -L ANSI-C -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k* $< \
+ | sed -f $(top_srcdir)/tool/gperf.sed \
+ ) > $(@F)
+
+.SUFFIXES: .chksum .list .inc
+
+.list.chksum:
+ @$(RUBY) -I$(top_srcdir)/tool -rchecksum \
+ -e "Checksum.update(ARGV) {|k|k.copy(k.target) rescue k.make(k.target)}" \
+ -- --make=$(MAKE) -I$(srcdir) $(<F) $(@F:.chksum=.inc)
diff --git a/ext/io/console/extconf.rb b/ext/io/console/extconf.rb
new file mode 100644
index 0000000000..dd3d221ae5
--- /dev/null
+++ b/ext/io/console/extconf.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: false
+require 'mkmf'
+
+# `--target-rbconfig` compatibility for Ruby 3.3 or earlier
+# See https://bugs.ruby-lang.org/issues/20345
+MakeMakefile::RbConfig ||= ::RbConfig
+
+have_func("rb_syserr_fail_str(0, Qnil)") or
+have_func("rb_syserr_new_str(0, Qnil)") or
+ abort
+
+have_func("rb_interned_str_cstr")
+have_func("rb_io_path", "ruby/io.h")
+have_func("rb_io_descriptor", "ruby/io.h")
+have_func("rb_io_get_write_io", "ruby/io.h")
+have_func("rb_io_closed_p", "ruby/io.h")
+have_func("rb_io_open_descriptor", "ruby/io.h")
+have_func("rb_ractor_local_storage_value_newkey")
+
+is_wasi = /wasi/ =~ MakeMakefile::RbConfig::CONFIG["platform"]
+# `ok` can be `true`, `false`, or `nil`:
+# * `true` : Required headers and functions available, proceed regular build.
+# * `false`: Required headers or functions not available, abort build.
+# * `nil` : Unsupported compilation target, generate dummy Makefile.
+#
+# Skip building io/console on WASI, as it does not support termios.h.
+ok = true if (RUBY_ENGINE == "ruby" && !is_wasi) || RUBY_ENGINE == "truffleruby"
+hdr = nil
+case
+when macro_defined?("_WIN32", "")
+ # rb_w32_map_errno: 1.8.7
+ vk_header = File.exist?("#$srcdir/win32_vk.list") ? "chksum" : "inc"
+ vk_header = "#{'{$(srcdir)}' if $nmake == ?m}win32_vk.#{vk_header}"
+when hdr = %w"termios.h termio.h".find {|h| have_header(h)}
+ have_func("cfmakeraw", hdr)
+when have_header(hdr = "sgtty.h")
+ %w"stty gtty".each {|f| have_func(f, hdr)}
+else
+ ok = false
+end if ok
+case ok
+when true
+ have_header("sys/ioctl.h") if hdr
+ # rb_check_hash_type: 1.9.3
+ # rb_io_get_write_io: 1.9.1
+ # rb_cloexec_open: 2.0.0
+ # rb_funcallv: 2.1.0
+ # RARRAY_CONST_PTR: 2.1.0
+ # rb_sym2str: 2.2.0
+ if have_macro("HAVE_RUBY_FIBER_SCHEDULER_H")
+ $defs << "-D""HAVE_RB_IO_WAIT=1"
+ elsif have_func("rb_scheduler_timeout") # 3.0
+ have_func("rb_io_wait")
+ end
+ have_func("ttyname_r") or have_func("ttyname")
+ create_makefile("io/console") {|conf|
+ conf << "\n""VK_HEADER = #{vk_header}\n"
+ }
+when nil
+ File.write("Makefile", dummy_makefile($srcdir).join(""))
+end
diff --git a/ext/io/console/io-console.gemspec b/ext/io/console/io-console.gemspec
new file mode 100644
index 0000000000..0a19992734
--- /dev/null
+++ b/ext/io/console/io-console.gemspec
@@ -0,0 +1,53 @@
+# -*- ruby -*-
+_VERSION = ["", "ext/io/console/"].find do |dir|
+ begin
+ break File.open(File.join(__dir__, "#{dir}console.c")) {|f|
+ f.gets("\nIO_CONSOLE_VERSION ")
+ f.gets[/"(.+)"/, 1]
+ }
+ rescue Errno::ENOENT
+ end
+end
+
+Gem::Specification.new do |s|
+ s.name = "io-console"
+ s.version = _VERSION
+ s.summary = "Console interface"
+ s.email = "nobu@ruby-lang.org"
+ s.description = "add console capabilities to IO instances."
+ s.required_ruby_version = ">= 2.6.0"
+ s.homepage = "https://github.com/ruby/io-console"
+ s.metadata["source_code_url"] = s.homepage
+ s.metadata["changelog_uri"] = s.homepage + "/releases"
+ s.authors = ["Nobu Nakada"]
+ s.require_path = %[lib]
+ s.files = %w[
+ .document
+ BSDL
+ COPYING
+ README.md
+ ext/io/console/console.c
+ ext/io/console/extconf.rb
+ ext/io/console/win32_vk.inc
+ lib/io/console/size.rb
+ ]
+ s.extensions = %w[ext/io/console/extconf.rb]
+
+ if Gem::Platform === s.platform and s.platform =~ 'java'
+ s.files.delete_if {|f| f.start_with?("ext/")}
+ s.extensions.clear
+ s.require_paths.unshift('lib/ffi')
+ s.files.concat(%w[
+ lib/ffi/io/console.rb
+ lib/ffi/io/console/bsd_console.rb
+ lib/ffi/io/console/common.rb
+ lib/ffi/io/console/linux_console.rb
+ lib/ffi/io/console/native_console.rb
+ lib/ffi/io/console/stty_console.rb
+ lib/ffi/io/console/stub_console.rb
+ lib/ffi/io/console/version.rb
+ ])
+ end
+
+ s.licenses = ["Ruby", "BSD-2-Clause"]
+end
diff --git a/ext/io/console/lib/console/size.rb b/ext/io/console/lib/console/size.rb
new file mode 100644
index 0000000000..14b9a74b22
--- /dev/null
+++ b/ext/io/console/lib/console/size.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: false
+# fallback to console window size
+def IO.default_console_size
+ [
+ ENV["LINES"].to_i.nonzero? || 25,
+ ENV["COLUMNS"].to_i.nonzero? || 80,
+ ]
+end
+
+begin
+ require 'io/console'
+rescue LoadError
+ class << IO
+ alias console_size default_console_size
+ end
+else
+ # returns console window size
+ def IO.console_size
+ console.winsize
+ rescue NoMethodError
+ default_console_size
+ end
+end
diff --git a/ext/io/console/win32_vk.chksum b/ext/io/console/win32_vk.chksum
new file mode 100644
index 0000000000..bc9fff7560
--- /dev/null
+++ b/ext/io/console/win32_vk.chksum
@@ -0,0 +1 @@
+src="win32_vk.list", len=3269, checksum=34076
diff --git a/ext/io/console/win32_vk.inc b/ext/io/console/win32_vk.inc
new file mode 100644
index 0000000000..348e6be5ed
--- /dev/null
+++ b/ext/io/console/win32_vk.inc
@@ -0,0 +1,1390 @@
+#define UNDEFINED_VK (unsigned short)-1
+#ifndef VK_LBUTTON
+# define VK_LBUTTON UNDEFINED_VK
+#endif
+#ifndef VK_RBUTTON
+# define VK_RBUTTON UNDEFINED_VK
+#endif
+#ifndef VK_CANCEL
+# define VK_CANCEL UNDEFINED_VK
+#endif
+#ifndef VK_MBUTTON
+# define VK_MBUTTON UNDEFINED_VK
+#endif
+#ifndef VK_XBUTTON1
+# define VK_XBUTTON1 UNDEFINED_VK
+#endif
+#ifndef VK_XBUTTON2
+# define VK_XBUTTON2 UNDEFINED_VK
+#endif
+#ifndef VK_BACK
+# define VK_BACK UNDEFINED_VK
+#endif
+#ifndef VK_TAB
+# define VK_TAB UNDEFINED_VK
+#endif
+#ifndef VK_CLEAR
+# define VK_CLEAR UNDEFINED_VK
+#endif
+#ifndef VK_RETURN
+# define VK_RETURN UNDEFINED_VK
+#endif
+#ifndef VK_SHIFT
+# define VK_SHIFT UNDEFINED_VK
+#endif
+#ifndef VK_CONTROL
+# define VK_CONTROL UNDEFINED_VK
+#endif
+#ifndef VK_MENU
+# define VK_MENU UNDEFINED_VK
+#endif
+#ifndef VK_PAUSE
+# define VK_PAUSE UNDEFINED_VK
+#endif
+#ifndef VK_CAPITAL
+# define VK_CAPITAL UNDEFINED_VK
+#endif
+#ifndef VK_KANA
+# define VK_KANA UNDEFINED_VK
+#endif
+#ifndef VK_HANGEUL
+# define VK_HANGEUL UNDEFINED_VK
+#endif
+#ifndef VK_HANGUL
+# define VK_HANGUL UNDEFINED_VK
+#endif
+#ifndef VK_JUNJA
+# define VK_JUNJA UNDEFINED_VK
+#endif
+#ifndef VK_FINAL
+# define VK_FINAL UNDEFINED_VK
+#endif
+#ifndef VK_HANJA
+# define VK_HANJA UNDEFINED_VK
+#endif
+#ifndef VK_KANJI
+# define VK_KANJI UNDEFINED_VK
+#endif
+#ifndef VK_ESCAPE
+# define VK_ESCAPE UNDEFINED_VK
+#endif
+#ifndef VK_CONVERT
+# define VK_CONVERT UNDEFINED_VK
+#endif
+#ifndef VK_NONCONVERT
+# define VK_NONCONVERT UNDEFINED_VK
+#endif
+#ifndef VK_ACCEPT
+# define VK_ACCEPT UNDEFINED_VK
+#endif
+#ifndef VK_MODECHANGE
+# define VK_MODECHANGE UNDEFINED_VK
+#endif
+#ifndef VK_SPACE
+# define VK_SPACE UNDEFINED_VK
+#endif
+#ifndef VK_PRIOR
+# define VK_PRIOR UNDEFINED_VK
+#endif
+#ifndef VK_NEXT
+# define VK_NEXT UNDEFINED_VK
+#endif
+#ifndef VK_END
+# define VK_END UNDEFINED_VK
+#endif
+#ifndef VK_HOME
+# define VK_HOME UNDEFINED_VK
+#endif
+#ifndef VK_LEFT
+# define VK_LEFT UNDEFINED_VK
+#endif
+#ifndef VK_UP
+# define VK_UP UNDEFINED_VK
+#endif
+#ifndef VK_RIGHT
+# define VK_RIGHT UNDEFINED_VK
+#endif
+#ifndef VK_DOWN
+# define VK_DOWN UNDEFINED_VK
+#endif
+#ifndef VK_SELECT
+# define VK_SELECT UNDEFINED_VK
+#endif
+#ifndef VK_PRINT
+# define VK_PRINT UNDEFINED_VK
+#endif
+#ifndef VK_EXECUTE
+# define VK_EXECUTE UNDEFINED_VK
+#endif
+#ifndef VK_SNAPSHOT
+# define VK_SNAPSHOT UNDEFINED_VK
+#endif
+#ifndef VK_INSERT
+# define VK_INSERT UNDEFINED_VK
+#endif
+#ifndef VK_DELETE
+# define VK_DELETE UNDEFINED_VK
+#endif
+#ifndef VK_HELP
+# define VK_HELP UNDEFINED_VK
+#endif
+#ifndef VK_LWIN
+# define VK_LWIN UNDEFINED_VK
+#endif
+#ifndef VK_RWIN
+# define VK_RWIN UNDEFINED_VK
+#endif
+#ifndef VK_APPS
+# define VK_APPS UNDEFINED_VK
+#endif
+#ifndef VK_SLEEP
+# define VK_SLEEP UNDEFINED_VK
+#endif
+#ifndef VK_NUMPAD0
+# define VK_NUMPAD0 UNDEFINED_VK
+#endif
+#ifndef VK_NUMPAD1
+# define VK_NUMPAD1 UNDEFINED_VK
+#endif
+#ifndef VK_NUMPAD2
+# define VK_NUMPAD2 UNDEFINED_VK
+#endif
+#ifndef VK_NUMPAD3
+# define VK_NUMPAD3 UNDEFINED_VK
+#endif
+#ifndef VK_NUMPAD4
+# define VK_NUMPAD4 UNDEFINED_VK
+#endif
+#ifndef VK_NUMPAD5
+# define VK_NUMPAD5 UNDEFINED_VK
+#endif
+#ifndef VK_NUMPAD6
+# define VK_NUMPAD6 UNDEFINED_VK
+#endif
+#ifndef VK_NUMPAD7
+# define VK_NUMPAD7 UNDEFINED_VK
+#endif
+#ifndef VK_NUMPAD8
+# define VK_NUMPAD8 UNDEFINED_VK
+#endif
+#ifndef VK_NUMPAD9
+# define VK_NUMPAD9 UNDEFINED_VK
+#endif
+#ifndef VK_MULTIPLY
+# define VK_MULTIPLY UNDEFINED_VK
+#endif
+#ifndef VK_ADD
+# define VK_ADD UNDEFINED_VK
+#endif
+#ifndef VK_SEPARATOR
+# define VK_SEPARATOR UNDEFINED_VK
+#endif
+#ifndef VK_SUBTRACT
+# define VK_SUBTRACT UNDEFINED_VK
+#endif
+#ifndef VK_DECIMAL
+# define VK_DECIMAL UNDEFINED_VK
+#endif
+#ifndef VK_DIVIDE
+# define VK_DIVIDE UNDEFINED_VK
+#endif
+#ifndef VK_F1
+# define VK_F1 UNDEFINED_VK
+#endif
+#ifndef VK_F2
+# define VK_F2 UNDEFINED_VK
+#endif
+#ifndef VK_F3
+# define VK_F3 UNDEFINED_VK
+#endif
+#ifndef VK_F4
+# define VK_F4 UNDEFINED_VK
+#endif
+#ifndef VK_F5
+# define VK_F5 UNDEFINED_VK
+#endif
+#ifndef VK_F6
+# define VK_F6 UNDEFINED_VK
+#endif
+#ifndef VK_F7
+# define VK_F7 UNDEFINED_VK
+#endif
+#ifndef VK_F8
+# define VK_F8 UNDEFINED_VK
+#endif
+#ifndef VK_F9
+# define VK_F9 UNDEFINED_VK
+#endif
+#ifndef VK_F10
+# define VK_F10 UNDEFINED_VK
+#endif
+#ifndef VK_F11
+# define VK_F11 UNDEFINED_VK
+#endif
+#ifndef VK_F12
+# define VK_F12 UNDEFINED_VK
+#endif
+#ifndef VK_F13
+# define VK_F13 UNDEFINED_VK
+#endif
+#ifndef VK_F14
+# define VK_F14 UNDEFINED_VK
+#endif
+#ifndef VK_F15
+# define VK_F15 UNDEFINED_VK
+#endif
+#ifndef VK_F16
+# define VK_F16 UNDEFINED_VK
+#endif
+#ifndef VK_F17
+# define VK_F17 UNDEFINED_VK
+#endif
+#ifndef VK_F18
+# define VK_F18 UNDEFINED_VK
+#endif
+#ifndef VK_F19
+# define VK_F19 UNDEFINED_VK
+#endif
+#ifndef VK_F20
+# define VK_F20 UNDEFINED_VK
+#endif
+#ifndef VK_F21
+# define VK_F21 UNDEFINED_VK
+#endif
+#ifndef VK_F22
+# define VK_F22 UNDEFINED_VK
+#endif
+#ifndef VK_F23
+# define VK_F23 UNDEFINED_VK
+#endif
+#ifndef VK_F24
+# define VK_F24 UNDEFINED_VK
+#endif
+#ifndef VK_NUMLOCK
+# define VK_NUMLOCK UNDEFINED_VK
+#endif
+#ifndef VK_SCROLL
+# define VK_SCROLL UNDEFINED_VK
+#endif
+#ifndef VK_OEM_NEC_EQUAL
+# define VK_OEM_NEC_EQUAL UNDEFINED_VK
+#endif
+#ifndef VK_OEM_FJ_JISHO
+# define VK_OEM_FJ_JISHO UNDEFINED_VK
+#endif
+#ifndef VK_OEM_FJ_MASSHOU
+# define VK_OEM_FJ_MASSHOU UNDEFINED_VK
+#endif
+#ifndef VK_OEM_FJ_TOUROKU
+# define VK_OEM_FJ_TOUROKU UNDEFINED_VK
+#endif
+#ifndef VK_OEM_FJ_LOYA
+# define VK_OEM_FJ_LOYA UNDEFINED_VK
+#endif
+#ifndef VK_OEM_FJ_ROYA
+# define VK_OEM_FJ_ROYA UNDEFINED_VK
+#endif
+#ifndef VK_LSHIFT
+# define VK_LSHIFT UNDEFINED_VK
+#endif
+#ifndef VK_RSHIFT
+# define VK_RSHIFT UNDEFINED_VK
+#endif
+#ifndef VK_LCONTROL
+# define VK_LCONTROL UNDEFINED_VK
+#endif
+#ifndef VK_RCONTROL
+# define VK_RCONTROL UNDEFINED_VK
+#endif
+#ifndef VK_LMENU
+# define VK_LMENU UNDEFINED_VK
+#endif
+#ifndef VK_RMENU
+# define VK_RMENU UNDEFINED_VK
+#endif
+#ifndef VK_BROWSER_BACK
+# define VK_BROWSER_BACK UNDEFINED_VK
+#endif
+#ifndef VK_BROWSER_FORWARD
+# define VK_BROWSER_FORWARD UNDEFINED_VK
+#endif
+#ifndef VK_BROWSER_REFRESH
+# define VK_BROWSER_REFRESH UNDEFINED_VK
+#endif
+#ifndef VK_BROWSER_STOP
+# define VK_BROWSER_STOP UNDEFINED_VK
+#endif
+#ifndef VK_BROWSER_SEARCH
+# define VK_BROWSER_SEARCH UNDEFINED_VK
+#endif
+#ifndef VK_BROWSER_FAVORITES
+# define VK_BROWSER_FAVORITES UNDEFINED_VK
+#endif
+#ifndef VK_BROWSER_HOME
+# define VK_BROWSER_HOME UNDEFINED_VK
+#endif
+#ifndef VK_VOLUME_MUTE
+# define VK_VOLUME_MUTE UNDEFINED_VK
+#endif
+#ifndef VK_VOLUME_DOWN
+# define VK_VOLUME_DOWN UNDEFINED_VK
+#endif
+#ifndef VK_VOLUME_UP
+# define VK_VOLUME_UP UNDEFINED_VK
+#endif
+#ifndef VK_MEDIA_NEXT_TRACK
+# define VK_MEDIA_NEXT_TRACK UNDEFINED_VK
+#endif
+#ifndef VK_MEDIA_PREV_TRACK
+# define VK_MEDIA_PREV_TRACK UNDEFINED_VK
+#endif
+#ifndef VK_MEDIA_STOP
+# define VK_MEDIA_STOP UNDEFINED_VK
+#endif
+#ifndef VK_MEDIA_PLAY_PAUSE
+# define VK_MEDIA_PLAY_PAUSE UNDEFINED_VK
+#endif
+#ifndef VK_LAUNCH_MAIL
+# define VK_LAUNCH_MAIL UNDEFINED_VK
+#endif
+#ifndef VK_LAUNCH_MEDIA_SELECT
+# define VK_LAUNCH_MEDIA_SELECT UNDEFINED_VK
+#endif
+#ifndef VK_LAUNCH_APP1
+# define VK_LAUNCH_APP1 UNDEFINED_VK
+#endif
+#ifndef VK_LAUNCH_APP2
+# define VK_LAUNCH_APP2 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_1
+# define VK_OEM_1 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_PLUS
+# define VK_OEM_PLUS UNDEFINED_VK
+#endif
+#ifndef VK_OEM_COMMA
+# define VK_OEM_COMMA UNDEFINED_VK
+#endif
+#ifndef VK_OEM_MINUS
+# define VK_OEM_MINUS UNDEFINED_VK
+#endif
+#ifndef VK_OEM_PERIOD
+# define VK_OEM_PERIOD UNDEFINED_VK
+#endif
+#ifndef VK_OEM_2
+# define VK_OEM_2 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_3
+# define VK_OEM_3 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_4
+# define VK_OEM_4 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_5
+# define VK_OEM_5 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_6
+# define VK_OEM_6 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_7
+# define VK_OEM_7 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_8
+# define VK_OEM_8 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_AX
+# define VK_OEM_AX UNDEFINED_VK
+#endif
+#ifndef VK_OEM_102
+# define VK_OEM_102 UNDEFINED_VK
+#endif
+#ifndef VK_ICO_HELP
+# define VK_ICO_HELP UNDEFINED_VK
+#endif
+#ifndef VK_ICO_00
+# define VK_ICO_00 UNDEFINED_VK
+#endif
+#ifndef VK_PROCESSKEY
+# define VK_PROCESSKEY UNDEFINED_VK
+#endif
+#ifndef VK_ICO_CLEAR
+# define VK_ICO_CLEAR UNDEFINED_VK
+#endif
+#ifndef VK_PACKET
+# define VK_PACKET UNDEFINED_VK
+#endif
+#ifndef VK_OEM_RESET
+# define VK_OEM_RESET UNDEFINED_VK
+#endif
+#ifndef VK_OEM_JUMP
+# define VK_OEM_JUMP UNDEFINED_VK
+#endif
+#ifndef VK_OEM_PA1
+# define VK_OEM_PA1 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_PA2
+# define VK_OEM_PA2 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_PA3
+# define VK_OEM_PA3 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_WSCTRL
+# define VK_OEM_WSCTRL UNDEFINED_VK
+#endif
+#ifndef VK_OEM_CUSEL
+# define VK_OEM_CUSEL UNDEFINED_VK
+#endif
+#ifndef VK_OEM_ATTN
+# define VK_OEM_ATTN UNDEFINED_VK
+#endif
+#ifndef VK_OEM_FINISH
+# define VK_OEM_FINISH UNDEFINED_VK
+#endif
+#ifndef VK_OEM_COPY
+# define VK_OEM_COPY UNDEFINED_VK
+#endif
+#ifndef VK_OEM_AUTO
+# define VK_OEM_AUTO UNDEFINED_VK
+#endif
+#ifndef VK_OEM_ENLW
+# define VK_OEM_ENLW UNDEFINED_VK
+#endif
+#ifndef VK_OEM_BACKTAB
+# define VK_OEM_BACKTAB UNDEFINED_VK
+#endif
+#ifndef VK_ATTN
+# define VK_ATTN UNDEFINED_VK
+#endif
+#ifndef VK_CRSEL
+# define VK_CRSEL UNDEFINED_VK
+#endif
+#ifndef VK_EXSEL
+# define VK_EXSEL UNDEFINED_VK
+#endif
+#ifndef VK_EREOF
+# define VK_EREOF UNDEFINED_VK
+#endif
+#ifndef VK_PLAY
+# define VK_PLAY UNDEFINED_VK
+#endif
+#ifndef VK_ZOOM
+# define VK_ZOOM UNDEFINED_VK
+#endif
+#ifndef VK_NONAME
+# define VK_NONAME UNDEFINED_VK
+#endif
+#ifndef VK_PA1
+# define VK_PA1 UNDEFINED_VK
+#endif
+#ifndef VK_OEM_CLEAR
+# define VK_OEM_CLEAR UNDEFINED_VK
+#endif
+/* ANSI-C code produced by gperf version 3.1 */
+/* Command-line: gperf --ignore-case -L ANSI-C -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k'*' win32_vk.list */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
+#endif
+
+#line 1 "win32_vk.list"
+
+struct vktable {short ofs; unsigned short vk;};
+static const struct vktable *console_win32_vk(const char *, size_t);
+#line 5 "win32_vk.list"
+struct vktable;
+/* maximum key range = 245, duplicates = 0 */
+
+#ifndef GPERF_DOWNCASE
+#define GPERF_DOWNCASE 1
+static unsigned char gperf_downcase[256] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
+ 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
+ 255
+ };
+#endif
+
+#ifndef GPERF_CASE_STRCMP
+#define GPERF_CASE_STRCMP 1
+static int
+gperf_case_strcmp (register const char *s1, register const char *s2)
+{
+ for (;;)
+ {
+ unsigned char c1 = gperf_downcase[(unsigned char)*s1++];
+ unsigned char c2 = gperf_downcase[(unsigned char)*s2++];
+ if (c1 != 0 && c1 == c2)
+ continue;
+ return (int)c1 - (int)c2;
+ }
+}
+#endif
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash (register const char *str, register size_t len)
+{
+ static const unsigned short asso_values[] =
+ {
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 51, 74,
+ 80, 116, 127, 124, 95, 140, 77, 53, 7, 3,
+ 257, 257, 257, 257, 257, 1, 11, 1, 55, 1,
+ 25, 84, 31, 33, 13, 16, 2, 28, 8, 1,
+ 6, 10, 1, 1, 3, 4, 45, 18, 73, 79,
+ 30, 257, 257, 257, 257, 5, 257, 1, 11, 1,
+ 55, 1, 25, 84, 31, 33, 13, 16, 2, 28,
+ 8, 1, 6, 10, 1, 1, 3, 4, 45, 18,
+ 73, 79, 30, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257
+ };
+ register unsigned int hval = (unsigned int)len;
+
+ switch (hval)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[18]];
+ /*FALLTHROUGH*/
+ case 18:
+ hval += asso_values[(unsigned char)str[17]];
+ /*FALLTHROUGH*/
+ case 17:
+ hval += asso_values[(unsigned char)str[16]];
+ /*FALLTHROUGH*/
+ case 16:
+ hval += asso_values[(unsigned char)str[15]];
+ /*FALLTHROUGH*/
+ case 15:
+ hval += asso_values[(unsigned char)str[14]];
+ /*FALLTHROUGH*/
+ case 14:
+ hval += asso_values[(unsigned char)str[13]];
+ /*FALLTHROUGH*/
+ case 13:
+ hval += asso_values[(unsigned char)str[12]];
+ /*FALLTHROUGH*/
+ case 12:
+ hval += asso_values[(unsigned char)str[11]];
+ /*FALLTHROUGH*/
+ case 11:
+ hval += asso_values[(unsigned char)str[10]];
+ /*FALLTHROUGH*/
+ case 10:
+ hval += asso_values[(unsigned char)str[9]];
+ /*FALLTHROUGH*/
+ case 9:
+ hval += asso_values[(unsigned char)str[8]];
+ /*FALLTHROUGH*/
+ case 8:
+ hval += asso_values[(unsigned char)str[7]];
+ /*FALLTHROUGH*/
+ case 7:
+ hval += asso_values[(unsigned char)str[6]];
+ /*FALLTHROUGH*/
+ case 6:
+ hval += asso_values[(unsigned char)str[5]];
+ /*FALLTHROUGH*/
+ case 5:
+ hval += asso_values[(unsigned char)str[4]];
+ /*FALLTHROUGH*/
+ case 4:
+ hval += asso_values[(unsigned char)str[3]];
+ /*FALLTHROUGH*/
+ case 3:
+ hval += asso_values[(unsigned char)str[2]+2];
+ /*FALLTHROUGH*/
+ case 2:
+ hval += asso_values[(unsigned char)str[1]];
+ /*FALLTHROUGH*/
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return (unsigned int)hval;
+}
+
+struct stringpool_t
+ {
+ char stringpool_str12[sizeof("UP")];
+ char stringpool_str13[sizeof("APPS")];
+ char stringpool_str14[sizeof("CRSEL")];
+ char stringpool_str15[sizeof("SPACE")];
+ char stringpool_str16[sizeof("SCROLL")];
+ char stringpool_str17[sizeof("ESCAPE")];
+ char stringpool_str18[sizeof("CANCEL")];
+ char stringpool_str19[sizeof("ACCEPT")];
+ char stringpool_str20[sizeof("SEPARATOR")];
+ char stringpool_str21[sizeof("SELECT")];
+ char stringpool_str22[sizeof("CONTROL")];
+ char stringpool_str23[sizeof("OEM_CLEAR")];
+ char stringpool_str24[sizeof("OEM_RESET")];
+ char stringpool_str25[sizeof("OEM_AUTO")];
+ char stringpool_str26[sizeof("OEM_CUSEL")];
+ char stringpool_str28[sizeof("KANA")];
+ char stringpool_str29[sizeof("OEM_PLUS")];
+ char stringpool_str30[sizeof("PRIOR")];
+ char stringpool_str31[sizeof("OEM_ATTN")];
+ char stringpool_str32[sizeof("PAUSE")];
+ char stringpool_str33[sizeof("BACK")];
+ char stringpool_str34[sizeof("PACKET")];
+ char stringpool_str35[sizeof("RCONTROL")];
+ char stringpool_str36[sizeof("LCONTROL")];
+ char stringpool_str37[sizeof("END")];
+ char stringpool_str38[sizeof("HOME")];
+ char stringpool_str39[sizeof("PRINT")];
+ char stringpool_str40[sizeof("NUMLOCK")];
+ char stringpool_str41[sizeof("LEFT")];
+ char stringpool_str42[sizeof("JUNJA")];
+ char stringpool_str43[sizeof("MENU")];
+ char stringpool_str44[sizeof("OEM_WSCTRL")];
+ char stringpool_str45[sizeof("OEM_ENLW")];
+ char stringpool_str46[sizeof("NEXT")];
+ char stringpool_str47[sizeof("RWIN")];
+ char stringpool_str48[sizeof("LWIN")];
+ char stringpool_str49[sizeof("CAPITAL")];
+ char stringpool_str50[sizeof("HELP")];
+ char stringpool_str51[sizeof("NONAME")];
+ char stringpool_str52[sizeof("RBUTTON")];
+ char stringpool_str53[sizeof("LBUTTON")];
+ char stringpool_str54[sizeof("OEM_NEC_EQUAL")];
+ char stringpool_str56[sizeof("INSERT")];
+ char stringpool_str57[sizeof("HANJA")];
+ char stringpool_str60[sizeof("SNAPSHOT")];
+ char stringpool_str61[sizeof("ATTN")];
+ char stringpool_str62[sizeof("TAB")];
+ char stringpool_str63[sizeof("OEM_BACKTAB")];
+ char stringpool_str64[sizeof("ICO_CLEAR")];
+ char stringpool_str65[sizeof("CONVERT")];
+ char stringpool_str66[sizeof("RETURN")];
+ char stringpool_str67[sizeof("OEM_JUMP")];
+ char stringpool_str71[sizeof("BROWSER_STOP")];
+ char stringpool_str72[sizeof("FINAL")];
+ char stringpool_str73[sizeof("ZOOM")];
+ char stringpool_str74[sizeof("KANJI")];
+ char stringpool_str75[sizeof("DELETE")];
+ char stringpool_str76[sizeof("OEM_COMMA")];
+ char stringpool_str77[sizeof("SUBTRACT")];
+ char stringpool_str79[sizeof("MBUTTON")];
+ char stringpool_str80[sizeof("F9")];
+ char stringpool_str81[sizeof("SHIFT")];
+ char stringpool_str82[sizeof("RSHIFT")];
+ char stringpool_str83[sizeof("LSHIFT")];
+ char stringpool_str84[sizeof("ADD")];
+ char stringpool_str85[sizeof("NONCONVERT")];
+ char stringpool_str86[sizeof("EXSEL")];
+ char stringpool_str87[sizeof("OEM_1")];
+ char stringpool_str88[sizeof("OEM_AX")];
+ char stringpool_str89[sizeof("BROWSER_BACK")];
+ char stringpool_str90[sizeof("OEM_8")];
+ char stringpool_str91[sizeof("OEM_MINUS")];
+ char stringpool_str92[sizeof("PLAY")];
+ char stringpool_str93[sizeof("OEM_2")];
+ char stringpool_str94[sizeof("CLEAR")];
+ char stringpool_str95[sizeof("OEM_FJ_TOUROKU")];
+ char stringpool_str96[sizeof("OEM_PA1")];
+ char stringpool_str97[sizeof("ICO_HELP")];
+ char stringpool_str98[sizeof("BROWSER_SEARCH")];
+ char stringpool_str99[sizeof("SLEEP")];
+ char stringpool_str101[sizeof("F1")];
+ char stringpool_str102[sizeof("OEM_PA2")];
+ char stringpool_str103[sizeof("OEM_COPY")];
+ char stringpool_str104[sizeof("F8")];
+ char stringpool_str105[sizeof("F19")];
+ char stringpool_str106[sizeof("RIGHT")];
+ char stringpool_str107[sizeof("F2")];
+ char stringpool_str108[sizeof("OEM_6")];
+ char stringpool_str109[sizeof("F18")];
+ char stringpool_str111[sizeof("VOLUME_UP")];
+ char stringpool_str114[sizeof("MEDIA_STOP")];
+ char stringpool_str115[sizeof("OEM_PERIOD")];
+ char stringpool_str117[sizeof("EREOF")];
+ char stringpool_str121[sizeof("BROWSER_HOME")];
+ char stringpool_str122[sizeof("F6")];
+ char stringpool_str124[sizeof("BROWSER_REFRESH")];
+ char stringpool_str126[sizeof("PA1")];
+ char stringpool_str127[sizeof("PROCESSKEY")];
+ char stringpool_str128[sizeof("DECIMAL")];
+ char stringpool_str129[sizeof("OEM_3")];
+ char stringpool_str130[sizeof("RMENU")];
+ char stringpool_str131[sizeof("LMENU")];
+ char stringpool_str132[sizeof("OEM_FJ_MASSHOU")];
+ char stringpool_str133[sizeof("NUMPAD0")];
+ char stringpool_str134[sizeof("HANGUL")];
+ char stringpool_str135[sizeof("NUMPAD9")];
+ char stringpool_str136[sizeof("HANGEUL")];
+ char stringpool_str137[sizeof("OEM_5")];
+ char stringpool_str138[sizeof("OEM_PA3")];
+ char stringpool_str139[sizeof("VOLUME_MUTE")];
+ char stringpool_str140[sizeof("OEM_4")];
+ char stringpool_str141[sizeof("LAUNCH_MAIL")];
+ char stringpool_str142[sizeof("OEM_FJ_JISHO")];
+ char stringpool_str143[sizeof("F3")];
+ char stringpool_str144[sizeof("OEM_FJ_ROYA")];
+ char stringpool_str145[sizeof("OEM_FJ_LOYA")];
+ char stringpool_str147[sizeof("DOWN")];
+ char stringpool_str149[sizeof("OEM_FINISH")];
+ char stringpool_str151[sizeof("F5")];
+ char stringpool_str153[sizeof("OEM_7")];
+ char stringpool_str154[sizeof("F4")];
+ char stringpool_str155[sizeof("F17")];
+ char stringpool_str156[sizeof("NUMPAD1")];
+ char stringpool_str157[sizeof("ICO_00")];
+ char stringpool_str159[sizeof("NUMPAD8")];
+ char stringpool_str162[sizeof("NUMPAD2")];
+ char stringpool_str164[sizeof("LAUNCH_APP1")];
+ char stringpool_str165[sizeof("BROWSER_FORWARD")];
+ char stringpool_str167[sizeof("F7")];
+ char stringpool_str170[sizeof("LAUNCH_APP2")];
+ char stringpool_str171[sizeof("MULTIPLY")];
+ char stringpool_str174[sizeof("EXECUTE")];
+ char stringpool_str176[sizeof("BROWSER_FAVORITES")];
+ char stringpool_str177[sizeof("NUMPAD6")];
+ char stringpool_str179[sizeof("F16")];
+ char stringpool_str182[sizeof("F10")];
+ char stringpool_str185[sizeof("VOLUME_DOWN")];
+ char stringpool_str188[sizeof("F20")];
+ char stringpool_str189[sizeof("MEDIA_PREV_TRACK")];
+ char stringpool_str191[sizeof("MODECHANGE")];
+ char stringpool_str197[sizeof("F14")];
+ char stringpool_str198[sizeof("NUMPAD3")];
+ char stringpool_str199[sizeof("XBUTTON1")];
+ char stringpool_str203[sizeof("F24")];
+ char stringpool_str205[sizeof("XBUTTON2")];
+ char stringpool_str206[sizeof("NUMPAD5")];
+ char stringpool_str209[sizeof("NUMPAD4")];
+ char stringpool_str215[sizeof("MEDIA_PLAY_PAUSE")];
+ char stringpool_str217[sizeof("LAUNCH_MEDIA_SELECT")];
+ char stringpool_str218[sizeof("F11")];
+ char stringpool_str220[sizeof("OEM_102")];
+ char stringpool_str221[sizeof("MEDIA_NEXT_TRACK")];
+ char stringpool_str222[sizeof("NUMPAD7")];
+ char stringpool_str224[sizeof("F21")];
+ char stringpool_str226[sizeof("F13")];
+ char stringpool_str229[sizeof("F12")];
+ char stringpool_str232[sizeof("F23")];
+ char stringpool_str235[sizeof("F22")];
+ char stringpool_str242[sizeof("F15")];
+ char stringpool_str256[sizeof("DIVIDE")];
+ };
+static const struct stringpool_t stringpool_contents =
+ {
+ "UP",
+ "APPS",
+ "CRSEL",
+ "SPACE",
+ "SCROLL",
+ "ESCAPE",
+ "CANCEL",
+ "ACCEPT",
+ "SEPARATOR",
+ "SELECT",
+ "CONTROL",
+ "OEM_CLEAR",
+ "OEM_RESET",
+ "OEM_AUTO",
+ "OEM_CUSEL",
+ "KANA",
+ "OEM_PLUS",
+ "PRIOR",
+ "OEM_ATTN",
+ "PAUSE",
+ "BACK",
+ "PACKET",
+ "RCONTROL",
+ "LCONTROL",
+ "END",
+ "HOME",
+ "PRINT",
+ "NUMLOCK",
+ "LEFT",
+ "JUNJA",
+ "MENU",
+ "OEM_WSCTRL",
+ "OEM_ENLW",
+ "NEXT",
+ "RWIN",
+ "LWIN",
+ "CAPITAL",
+ "HELP",
+ "NONAME",
+ "RBUTTON",
+ "LBUTTON",
+ "OEM_NEC_EQUAL",
+ "INSERT",
+ "HANJA",
+ "SNAPSHOT",
+ "ATTN",
+ "TAB",
+ "OEM_BACKTAB",
+ "ICO_CLEAR",
+ "CONVERT",
+ "RETURN",
+ "OEM_JUMP",
+ "BROWSER_STOP",
+ "FINAL",
+ "ZOOM",
+ "KANJI",
+ "DELETE",
+ "OEM_COMMA",
+ "SUBTRACT",
+ "MBUTTON",
+ "F9",
+ "SHIFT",
+ "RSHIFT",
+ "LSHIFT",
+ "ADD",
+ "NONCONVERT",
+ "EXSEL",
+ "OEM_1",
+ "OEM_AX",
+ "BROWSER_BACK",
+ "OEM_8",
+ "OEM_MINUS",
+ "PLAY",
+ "OEM_2",
+ "CLEAR",
+ "OEM_FJ_TOUROKU",
+ "OEM_PA1",
+ "ICO_HELP",
+ "BROWSER_SEARCH",
+ "SLEEP",
+ "F1",
+ "OEM_PA2",
+ "OEM_COPY",
+ "F8",
+ "F19",
+ "RIGHT",
+ "F2",
+ "OEM_6",
+ "F18",
+ "VOLUME_UP",
+ "MEDIA_STOP",
+ "OEM_PERIOD",
+ "EREOF",
+ "BROWSER_HOME",
+ "F6",
+ "BROWSER_REFRESH",
+ "PA1",
+ "PROCESSKEY",
+ "DECIMAL",
+ "OEM_3",
+ "RMENU",
+ "LMENU",
+ "OEM_FJ_MASSHOU",
+ "NUMPAD0",
+ "HANGUL",
+ "NUMPAD9",
+ "HANGEUL",
+ "OEM_5",
+ "OEM_PA3",
+ "VOLUME_MUTE",
+ "OEM_4",
+ "LAUNCH_MAIL",
+ "OEM_FJ_JISHO",
+ "F3",
+ "OEM_FJ_ROYA",
+ "OEM_FJ_LOYA",
+ "DOWN",
+ "OEM_FINISH",
+ "F5",
+ "OEM_7",
+ "F4",
+ "F17",
+ "NUMPAD1",
+ "ICO_00",
+ "NUMPAD8",
+ "NUMPAD2",
+ "LAUNCH_APP1",
+ "BROWSER_FORWARD",
+ "F7",
+ "LAUNCH_APP2",
+ "MULTIPLY",
+ "EXECUTE",
+ "BROWSER_FAVORITES",
+ "NUMPAD6",
+ "F16",
+ "F10",
+ "VOLUME_DOWN",
+ "F20",
+ "MEDIA_PREV_TRACK",
+ "MODECHANGE",
+ "F14",
+ "NUMPAD3",
+ "XBUTTON1",
+ "F24",
+ "XBUTTON2",
+ "NUMPAD5",
+ "NUMPAD4",
+ "MEDIA_PLAY_PAUSE",
+ "LAUNCH_MEDIA_SELECT",
+ "F11",
+ "OEM_102",
+ "MEDIA_NEXT_TRACK",
+ "NUMPAD7",
+ "F21",
+ "F13",
+ "F12",
+ "F23",
+ "F22",
+ "F15",
+ "DIVIDE"
+ };
+#define stringpool ((const char *) &stringpool_contents)
+const struct vktable *
+console_win32_vk (register const char *str, register size_t len)
+{
+ enum
+ {
+ TOTAL_KEYWORDS = 160,
+ MIN_WORD_LENGTH = 2,
+ MAX_WORD_LENGTH = 19,
+ MIN_HASH_VALUE = 12,
+ MAX_HASH_VALUE = 256
+ };
+
+ static const struct vktable wordlist[] =
+ {
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+#line 40 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str12, VK_UP},
+#line 52 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str13, VK_APPS},
+#line 159 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str14, VK_CRSEL},
+#line 34 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str15, VK_SPACE},
+#line 95 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str16, VK_SCROLL},
+#line 29 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str17, VK_ESCAPE},
+#line 9 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str18, VK_CANCEL},
+#line 32 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str19, VK_ACCEPT},
+#line 66 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str20, VK_SEPARATOR},
+#line 43 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str21, VK_SELECT},
+#line 18 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str22, VK_CONTROL},
+#line 166 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str23, VK_OEM_CLEAR},
+#line 145 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str24, VK_OEM_RESET},
+#line 155 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str25, VK_OEM_AUTO},
+#line 151 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str26, VK_OEM_CUSEL},
+ {-1},
+#line 22 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str28, VK_KANA},
+#line 127 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str29, VK_OEM_PLUS},
+#line 35 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str30, VK_PRIOR},
+#line 152 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str31, VK_OEM_ATTN},
+#line 20 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str32, VK_PAUSE},
+#line 13 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str33, VK_BACK},
+#line 144 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str34, VK_PACKET},
+#line 105 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str35, VK_RCONTROL},
+#line 104 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str36, VK_LCONTROL},
+#line 37 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str37, VK_END},
+#line 38 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str38, VK_HOME},
+#line 44 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str39, VK_PRINT},
+#line 94 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str40, VK_NUMLOCK},
+#line 39 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str41, VK_LEFT},
+#line 25 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str42, VK_JUNJA},
+#line 19 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str43, VK_MENU},
+#line 150 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str44, VK_OEM_WSCTRL},
+#line 156 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str45, VK_OEM_ENLW},
+#line 36 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str46, VK_NEXT},
+#line 51 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str47, VK_RWIN},
+#line 50 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str48, VK_LWIN},
+#line 21 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str49, VK_CAPITAL},
+#line 49 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str50, VK_HELP},
+#line 164 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str51, VK_NONAME},
+#line 8 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str52, VK_RBUTTON},
+#line 7 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str53, VK_LBUTTON},
+#line 96 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str54, VK_OEM_NEC_EQUAL},
+ {-1},
+#line 47 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str56, VK_INSERT},
+#line 27 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str57, VK_HANJA},
+ {-1}, {-1},
+#line 46 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str60, VK_SNAPSHOT},
+#line 158 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str61, VK_ATTN},
+#line 14 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str62, VK_TAB},
+#line 157 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str63, VK_OEM_BACKTAB},
+#line 143 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str64, VK_ICO_CLEAR},
+#line 30 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str65, VK_CONVERT},
+#line 16 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str66, VK_RETURN},
+#line 146 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str67, VK_OEM_JUMP},
+ {-1}, {-1}, {-1},
+#line 111 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str71, VK_BROWSER_STOP},
+#line 26 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str72, VK_FINAL},
+#line 163 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str73, VK_ZOOM},
+#line 28 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str74, VK_KANJI},
+#line 48 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str75, VK_DELETE},
+#line 128 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str76, VK_OEM_COMMA},
+#line 67 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str77, VK_SUBTRACT},
+ {-1},
+#line 10 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str79, VK_MBUTTON},
+#line 78 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str80, VK_F9},
+#line 17 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str81, VK_SHIFT},
+#line 103 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str82, VK_RSHIFT},
+#line 102 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str83, VK_LSHIFT},
+#line 65 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str84, VK_ADD},
+#line 31 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str85, VK_NONCONVERT},
+#line 160 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str86, VK_EXSEL},
+#line 126 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str87, VK_OEM_1},
+#line 138 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str88, VK_OEM_AX},
+#line 108 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str89, VK_BROWSER_BACK},
+#line 137 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str90, VK_OEM_8},
+#line 129 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str91, VK_OEM_MINUS},
+#line 162 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str92, VK_PLAY},
+#line 131 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str93, VK_OEM_2},
+#line 15 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str94, VK_CLEAR},
+#line 99 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str95, VK_OEM_FJ_TOUROKU},
+#line 147 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str96, VK_OEM_PA1},
+#line 140 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str97, VK_ICO_HELP},
+#line 112 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str98, VK_BROWSER_SEARCH},
+#line 53 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str99, VK_SLEEP},
+ {-1},
+#line 70 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str101, VK_F1},
+#line 148 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str102, VK_OEM_PA2},
+#line 154 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str103, VK_OEM_COPY},
+#line 77 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str104, VK_F8},
+#line 88 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str105, VK_F19},
+#line 41 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str106, VK_RIGHT},
+#line 71 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str107, VK_F2},
+#line 135 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str108, VK_OEM_6},
+#line 87 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str109, VK_F18},
+ {-1},
+#line 117 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str111, VK_VOLUME_UP},
+ {-1}, {-1},
+#line 120 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str114, VK_MEDIA_STOP},
+#line 130 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str115, VK_OEM_PERIOD},
+ {-1},
+#line 161 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str117, VK_EREOF},
+ {-1}, {-1}, {-1},
+#line 114 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str121, VK_BROWSER_HOME},
+#line 75 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str122, VK_F6},
+ {-1},
+#line 110 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str124, VK_BROWSER_REFRESH},
+ {-1},
+#line 165 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str126, VK_PA1},
+#line 142 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str127, VK_PROCESSKEY},
+#line 68 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str128, VK_DECIMAL},
+#line 132 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str129, VK_OEM_3},
+#line 107 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str130, VK_RMENU},
+#line 106 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str131, VK_LMENU},
+#line 98 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str132, VK_OEM_FJ_MASSHOU},
+#line 54 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str133, VK_NUMPAD0},
+#line 24 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str134, VK_HANGUL},
+#line 63 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str135, VK_NUMPAD9},
+#line 23 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str136, VK_HANGEUL},
+#line 134 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str137, VK_OEM_5},
+#line 149 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str138, VK_OEM_PA3},
+#line 115 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str139, VK_VOLUME_MUTE},
+#line 133 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str140, VK_OEM_4},
+#line 122 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str141, VK_LAUNCH_MAIL},
+#line 97 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str142, VK_OEM_FJ_JISHO},
+#line 72 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str143, VK_F3},
+#line 101 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str144, VK_OEM_FJ_ROYA},
+#line 100 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str145, VK_OEM_FJ_LOYA},
+ {-1},
+#line 42 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str147, VK_DOWN},
+ {-1},
+#line 153 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str149, VK_OEM_FINISH},
+ {-1},
+#line 74 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str151, VK_F5},
+ {-1},
+#line 136 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str153, VK_OEM_7},
+#line 73 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str154, VK_F4},
+#line 86 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str155, VK_F17},
+#line 55 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str156, VK_NUMPAD1},
+#line 141 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str157, VK_ICO_00},
+ {-1},
+#line 62 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str159, VK_NUMPAD8},
+ {-1}, {-1},
+#line 56 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str162, VK_NUMPAD2},
+ {-1},
+#line 124 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str164, VK_LAUNCH_APP1},
+#line 109 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str165, VK_BROWSER_FORWARD},
+ {-1},
+#line 76 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str167, VK_F7},
+ {-1}, {-1},
+#line 125 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str170, VK_LAUNCH_APP2},
+#line 64 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str171, VK_MULTIPLY},
+ {-1}, {-1},
+#line 45 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str174, VK_EXECUTE},
+ {-1},
+#line 113 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str176, VK_BROWSER_FAVORITES},
+#line 60 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str177, VK_NUMPAD6},
+ {-1},
+#line 85 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str179, VK_F16},
+ {-1}, {-1},
+#line 79 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str182, VK_F10},
+ {-1}, {-1},
+#line 116 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str185, VK_VOLUME_DOWN},
+ {-1}, {-1},
+#line 89 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str188, VK_F20},
+#line 119 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str189, VK_MEDIA_PREV_TRACK},
+ {-1},
+#line 33 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str191, VK_MODECHANGE},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+#line 83 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str197, VK_F14},
+#line 57 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str198, VK_NUMPAD3},
+#line 11 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str199, VK_XBUTTON1},
+ {-1}, {-1}, {-1},
+#line 93 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str203, VK_F24},
+ {-1},
+#line 12 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str205, VK_XBUTTON2},
+#line 59 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str206, VK_NUMPAD5},
+ {-1}, {-1},
+#line 58 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str209, VK_NUMPAD4},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+#line 121 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str215, VK_MEDIA_PLAY_PAUSE},
+ {-1},
+#line 123 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str217, VK_LAUNCH_MEDIA_SELECT},
+#line 80 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str218, VK_F11},
+ {-1},
+#line 139 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str220, VK_OEM_102},
+#line 118 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str221, VK_MEDIA_NEXT_TRACK},
+#line 61 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str222, VK_NUMPAD7},
+ {-1},
+#line 90 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str224, VK_F21},
+ {-1},
+#line 82 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str226, VK_F13},
+ {-1}, {-1},
+#line 81 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str229, VK_F12},
+ {-1}, {-1},
+#line 92 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str232, VK_F23},
+ {-1}, {-1},
+#line 91 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str235, VK_F22},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 84 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str242, VK_F15},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+#line 69 "win32_vk.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str256, VK_DIVIDE}
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register unsigned int key = hash (str, len);
+
+ if (key <= MAX_HASH_VALUE)
+ {
+ register int o = wordlist[key].ofs;
+ if (o >= 0)
+ {
+ register const char *s = o + stringpool;
+
+ if ((((unsigned char)*str ^ (unsigned char)*s) & ~32) == 0 && !gperf_case_strcmp (str, s))
+ return &wordlist[key];
+ }
+ }
+ }
+ return 0;
+}
diff --git a/ext/io/console/win32_vk.list b/ext/io/console/win32_vk.list
new file mode 100644
index 0000000000..5df3d6da57
--- /dev/null
+++ b/ext/io/console/win32_vk.list
@@ -0,0 +1,166 @@
+%{
+struct vktable {short ofs; unsigned short vk;};
+static const struct vktable *console_win32_vk(const char *, size_t);
+%}
+struct vktable
+%%
+LBUTTON, VK_LBUTTON
+RBUTTON, VK_RBUTTON
+CANCEL, VK_CANCEL
+MBUTTON, VK_MBUTTON
+XBUTTON1, VK_XBUTTON1
+XBUTTON2, VK_XBUTTON2
+BACK, VK_BACK
+TAB, VK_TAB
+CLEAR, VK_CLEAR
+RETURN, VK_RETURN
+SHIFT, VK_SHIFT
+CONTROL, VK_CONTROL
+MENU, VK_MENU
+PAUSE, VK_PAUSE
+CAPITAL, VK_CAPITAL
+KANA, VK_KANA
+HANGEUL, VK_HANGEUL
+HANGUL, VK_HANGUL
+JUNJA, VK_JUNJA
+FINAL, VK_FINAL
+HANJA, VK_HANJA
+KANJI, VK_KANJI
+ESCAPE, VK_ESCAPE
+CONVERT, VK_CONVERT
+NONCONVERT, VK_NONCONVERT
+ACCEPT, VK_ACCEPT
+MODECHANGE, VK_MODECHANGE
+SPACE, VK_SPACE
+PRIOR, VK_PRIOR
+NEXT, VK_NEXT
+END, VK_END
+HOME, VK_HOME
+LEFT, VK_LEFT
+UP, VK_UP
+RIGHT, VK_RIGHT
+DOWN, VK_DOWN
+SELECT, VK_SELECT
+PRINT, VK_PRINT
+EXECUTE, VK_EXECUTE
+SNAPSHOT, VK_SNAPSHOT
+INSERT, VK_INSERT
+DELETE, VK_DELETE
+HELP, VK_HELP
+LWIN, VK_LWIN
+RWIN, VK_RWIN
+APPS, VK_APPS
+SLEEP, VK_SLEEP
+NUMPAD0, VK_NUMPAD0
+NUMPAD1, VK_NUMPAD1
+NUMPAD2, VK_NUMPAD2
+NUMPAD3, VK_NUMPAD3
+NUMPAD4, VK_NUMPAD4
+NUMPAD5, VK_NUMPAD5
+NUMPAD6, VK_NUMPAD6
+NUMPAD7, VK_NUMPAD7
+NUMPAD8, VK_NUMPAD8
+NUMPAD9, VK_NUMPAD9
+MULTIPLY, VK_MULTIPLY
+ADD, VK_ADD
+SEPARATOR, VK_SEPARATOR
+SUBTRACT, VK_SUBTRACT
+DECIMAL, VK_DECIMAL
+DIVIDE, VK_DIVIDE
+F1, VK_F1
+F2, VK_F2
+F3, VK_F3
+F4, VK_F4
+F5, VK_F5
+F6, VK_F6
+F7, VK_F7
+F8, VK_F8
+F9, VK_F9
+F10, VK_F10
+F11, VK_F11
+F12, VK_F12
+F13, VK_F13
+F14, VK_F14
+F15, VK_F15
+F16, VK_F16
+F17, VK_F17
+F18, VK_F18
+F19, VK_F19
+F20, VK_F20
+F21, VK_F21
+F22, VK_F22
+F23, VK_F23
+F24, VK_F24
+NUMLOCK, VK_NUMLOCK
+SCROLL, VK_SCROLL
+OEM_NEC_EQUAL, VK_OEM_NEC_EQUAL
+OEM_FJ_JISHO, VK_OEM_FJ_JISHO
+OEM_FJ_MASSHOU, VK_OEM_FJ_MASSHOU
+OEM_FJ_TOUROKU, VK_OEM_FJ_TOUROKU
+OEM_FJ_LOYA, VK_OEM_FJ_LOYA
+OEM_FJ_ROYA, VK_OEM_FJ_ROYA
+LSHIFT, VK_LSHIFT
+RSHIFT, VK_RSHIFT
+LCONTROL, VK_LCONTROL
+RCONTROL, VK_RCONTROL
+LMENU, VK_LMENU
+RMENU, VK_RMENU
+BROWSER_BACK, VK_BROWSER_BACK
+BROWSER_FORWARD, VK_BROWSER_FORWARD
+BROWSER_REFRESH, VK_BROWSER_REFRESH
+BROWSER_STOP, VK_BROWSER_STOP
+BROWSER_SEARCH, VK_BROWSER_SEARCH
+BROWSER_FAVORITES, VK_BROWSER_FAVORITES
+BROWSER_HOME, VK_BROWSER_HOME
+VOLUME_MUTE, VK_VOLUME_MUTE
+VOLUME_DOWN, VK_VOLUME_DOWN
+VOLUME_UP, VK_VOLUME_UP
+MEDIA_NEXT_TRACK, VK_MEDIA_NEXT_TRACK
+MEDIA_PREV_TRACK, VK_MEDIA_PREV_TRACK
+MEDIA_STOP, VK_MEDIA_STOP
+MEDIA_PLAY_PAUSE, VK_MEDIA_PLAY_PAUSE
+LAUNCH_MAIL, VK_LAUNCH_MAIL
+LAUNCH_MEDIA_SELECT, VK_LAUNCH_MEDIA_SELECT
+LAUNCH_APP1, VK_LAUNCH_APP1
+LAUNCH_APP2, VK_LAUNCH_APP2
+OEM_1, VK_OEM_1
+OEM_PLUS, VK_OEM_PLUS
+OEM_COMMA, VK_OEM_COMMA
+OEM_MINUS, VK_OEM_MINUS
+OEM_PERIOD, VK_OEM_PERIOD
+OEM_2, VK_OEM_2
+OEM_3, VK_OEM_3
+OEM_4, VK_OEM_4
+OEM_5, VK_OEM_5
+OEM_6, VK_OEM_6
+OEM_7, VK_OEM_7
+OEM_8, VK_OEM_8
+OEM_AX, VK_OEM_AX
+OEM_102, VK_OEM_102
+ICO_HELP, VK_ICO_HELP
+ICO_00, VK_ICO_00
+PROCESSKEY, VK_PROCESSKEY
+ICO_CLEAR, VK_ICO_CLEAR
+PACKET, VK_PACKET
+OEM_RESET, VK_OEM_RESET
+OEM_JUMP, VK_OEM_JUMP
+OEM_PA1, VK_OEM_PA1
+OEM_PA2, VK_OEM_PA2
+OEM_PA3, VK_OEM_PA3
+OEM_WSCTRL, VK_OEM_WSCTRL
+OEM_CUSEL, VK_OEM_CUSEL
+OEM_ATTN, VK_OEM_ATTN
+OEM_FINISH, VK_OEM_FINISH
+OEM_COPY, VK_OEM_COPY
+OEM_AUTO, VK_OEM_AUTO
+OEM_ENLW, VK_OEM_ENLW
+OEM_BACKTAB, VK_OEM_BACKTAB
+ATTN, VK_ATTN
+CRSEL, VK_CRSEL
+EXSEL, VK_EXSEL
+EREOF, VK_EREOF
+PLAY, VK_PLAY
+ZOOM, VK_ZOOM
+NONAME, VK_NONAME
+PA1, VK_PA1
+OEM_CLEAR, VK_OEM_CLEAR
diff --git a/ext/io/nonblock/depend b/ext/io/nonblock/depend
new file mode 100644
index 0000000000..e78a05c316
--- /dev/null
+++ b/ext/io/nonblock/depend
@@ -0,0 +1,176 @@
+# AUTOGENERATED DEPENDENCIES START
+nonblock.o: $(RUBY_EXTCONF_H)
+nonblock.o: $(arch_hdrdir)/ruby/config.h
+nonblock.o: $(hdrdir)/ruby.h
+nonblock.o: $(hdrdir)/ruby/assert.h
+nonblock.o: $(hdrdir)/ruby/backward.h
+nonblock.o: $(hdrdir)/ruby/backward/2/assume.h
+nonblock.o: $(hdrdir)/ruby/backward/2/attributes.h
+nonblock.o: $(hdrdir)/ruby/backward/2/bool.h
+nonblock.o: $(hdrdir)/ruby/backward/2/inttypes.h
+nonblock.o: $(hdrdir)/ruby/backward/2/limits.h
+nonblock.o: $(hdrdir)/ruby/backward/2/long_long.h
+nonblock.o: $(hdrdir)/ruby/backward/2/stdalign.h
+nonblock.o: $(hdrdir)/ruby/backward/2/stdarg.h
+nonblock.o: $(hdrdir)/ruby/defines.h
+nonblock.o: $(hdrdir)/ruby/encoding.h
+nonblock.o: $(hdrdir)/ruby/intern.h
+nonblock.o: $(hdrdir)/ruby/internal/abi.h
+nonblock.o: $(hdrdir)/ruby/internal/anyargs.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+nonblock.o: $(hdrdir)/ruby/internal/assume.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/artificial.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/cold.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/const.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/error.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/format.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/noalias.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/noinline.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/pure.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/restrict.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/warning.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/weakref.h
+nonblock.o: $(hdrdir)/ruby/internal/cast.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_since.h
+nonblock.o: $(hdrdir)/ruby/internal/config.h
+nonblock.o: $(hdrdir)/ruby/internal/constant_p.h
+nonblock.o: $(hdrdir)/ruby/internal/core.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rarray.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rbasic.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rbignum.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rclass.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rdata.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rfile.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rhash.h
+nonblock.o: $(hdrdir)/ruby/internal/core/robject.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rregexp.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rstring.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rstruct.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+nonblock.o: $(hdrdir)/ruby/internal/ctype.h
+nonblock.o: $(hdrdir)/ruby/internal/dllexport.h
+nonblock.o: $(hdrdir)/ruby/internal/dosish.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/re.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/string.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+nonblock.o: $(hdrdir)/ruby/internal/error.h
+nonblock.o: $(hdrdir)/ruby/internal/eval.h
+nonblock.o: $(hdrdir)/ruby/internal/event.h
+nonblock.o: $(hdrdir)/ruby/internal/fl_type.h
+nonblock.o: $(hdrdir)/ruby/internal/gc.h
+nonblock.o: $(hdrdir)/ruby/internal/glob.h
+nonblock.o: $(hdrdir)/ruby/internal/globals.h
+nonblock.o: $(hdrdir)/ruby/internal/has/attribute.h
+nonblock.o: $(hdrdir)/ruby/internal/has/builtin.h
+nonblock.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+nonblock.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+nonblock.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+nonblock.o: $(hdrdir)/ruby/internal/has/extension.h
+nonblock.o: $(hdrdir)/ruby/internal/has/feature.h
+nonblock.o: $(hdrdir)/ruby/internal/has/warning.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/array.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/bignum.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/class.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/compar.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/complex.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/cont.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/dir.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/enum.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/error.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/eval.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/file.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/hash.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/io.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/load.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/marshal.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/numeric.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/object.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/parse.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/proc.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/process.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/random.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/range.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/rational.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/re.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/ruby.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/select.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/set.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/signal.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/string.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/struct.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/thread.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/time.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/variable.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/vm.h
+nonblock.o: $(hdrdir)/ruby/internal/interpreter.h
+nonblock.o: $(hdrdir)/ruby/internal/iterator.h
+nonblock.o: $(hdrdir)/ruby/internal/memory.h
+nonblock.o: $(hdrdir)/ruby/internal/method.h
+nonblock.o: $(hdrdir)/ruby/internal/module.h
+nonblock.o: $(hdrdir)/ruby/internal/newobj.h
+nonblock.o: $(hdrdir)/ruby/internal/scan_args.h
+nonblock.o: $(hdrdir)/ruby/internal/special_consts.h
+nonblock.o: $(hdrdir)/ruby/internal/static_assert.h
+nonblock.o: $(hdrdir)/ruby/internal/stdalign.h
+nonblock.o: $(hdrdir)/ruby/internal/stdbool.h
+nonblock.o: $(hdrdir)/ruby/internal/stdckdint.h
+nonblock.o: $(hdrdir)/ruby/internal/symbol.h
+nonblock.o: $(hdrdir)/ruby/internal/value.h
+nonblock.o: $(hdrdir)/ruby/internal/value_type.h
+nonblock.o: $(hdrdir)/ruby/internal/variable.h
+nonblock.o: $(hdrdir)/ruby/internal/warning_push.h
+nonblock.o: $(hdrdir)/ruby/internal/xmalloc.h
+nonblock.o: $(hdrdir)/ruby/io.h
+nonblock.o: $(hdrdir)/ruby/missing.h
+nonblock.o: $(hdrdir)/ruby/onigmo.h
+nonblock.o: $(hdrdir)/ruby/oniguruma.h
+nonblock.o: $(hdrdir)/ruby/ruby.h
+nonblock.o: $(hdrdir)/ruby/st.h
+nonblock.o: $(hdrdir)/ruby/subst.h
+nonblock.o: nonblock.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/io/nonblock/extconf.rb b/ext/io/nonblock/extconf.rb
new file mode 100644
index 0000000000..505c9e6252
--- /dev/null
+++ b/ext/io/nonblock/extconf.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: false
+require 'mkmf'
+target = "io/nonblock"
+
+unless RUBY_ENGINE == 'ruby'
+ File.write("Makefile", dummy_makefile($srcdir).join(""))
+ return
+end
+
+have_func("rb_io_descriptor", "ruby/io.h")
+
+hdr = %w"fcntl.h"
+if have_macro("O_NONBLOCK", hdr) and
+ (have_macro("F_GETFL", hdr) or have_macro("F_SETFL", hdr))
+ create_makefile(target)
+end
diff --git a/ext/io/nonblock/io-nonblock.gemspec b/ext/io/nonblock/io-nonblock.gemspec
new file mode 100644
index 0000000000..4f5b8cef6f
--- /dev/null
+++ b/ext/io/nonblock/io-nonblock.gemspec
@@ -0,0 +1,25 @@
+Gem::Specification.new do |spec|
+ spec.name = "io-nonblock"
+ spec.version = "0.3.2"
+ spec.authors = ["Nobu Nakada"]
+ spec.email = ["nobu@ruby-lang.org"]
+
+ spec.summary = %q{Enables non-blocking mode with IO class}
+ spec.description = %q{Enables non-blocking mode with IO class}
+ spec.homepage = "https://github.com/ruby/io-nonblock"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.0")
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = %w[
+ COPYING
+ README.md
+ ext/io/nonblock/depend
+ ext/io/nonblock/extconf.rb
+ ext/io/nonblock/nonblock.c
+ ]
+ spec.extensions = %w[ext/io/nonblock/extconf.rb]
+ spec.require_paths = ["lib"]
+end
diff --git a/ext/io/nonblock/nonblock.c b/ext/io/nonblock/nonblock.c
new file mode 100644
index 0000000000..cd40ea3335
--- /dev/null
+++ b/ext/io/nonblock/nonblock.c
@@ -0,0 +1,210 @@
+/**********************************************************************
+
+ io/nonblock.c -
+
+ $Author$
+ created at: Tue Jul 14 21:53:18 2009
+
+ All the files in this distribution are covered under the Ruby's
+ license (see the file COPYING).
+
+**********************************************************************/
+
+#include "ruby.h"
+#include "ruby/io.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+
+#ifndef HAVE_RB_IO_DESCRIPTOR
+static int
+io_descriptor_fallback(VALUE io)
+{
+ rb_io_t *fptr;
+ GetOpenFile(io, fptr);
+ return fptr->fd;
+}
+#define rb_io_descriptor io_descriptor_fallback
+#endif
+
+#ifdef F_GETFL
+static int
+get_fcntl_flags(int fd)
+{
+ int f = fcntl(fd, F_GETFL);
+ if (f == -1) rb_sys_fail(0);
+ return f;
+}
+#else
+#define get_fcntl_flags(fd) ((void)(fd), 0)
+#endif
+
+#ifdef F_GETFL
+/*
+ * call-seq:
+ * io.nonblock? -> boolean
+ *
+ * Returns +true+ if an IO object is in non-blocking mode.
+ */
+static VALUE
+rb_io_nonblock_p(VALUE io)
+{
+ if (get_fcntl_flags(rb_io_descriptor(io)) & O_NONBLOCK)
+ return Qtrue;
+ return Qfalse;
+}
+#else
+#define rb_io_nonblock_p rb_f_notimplement
+#endif
+
+#ifdef F_SETFL
+static void
+set_fcntl_flags(int fd, int f)
+{
+ if (fcntl(fd, F_SETFL, f) == -1)
+ rb_sys_fail(0);
+}
+
+#ifndef RUBY_IO_NONBLOCK_METHODS
+
+static int
+io_nonblock_set(int fd, int f, int nb)
+{
+ if (nb) {
+ if ((f & O_NONBLOCK) != 0)
+ return 0;
+ f |= O_NONBLOCK;
+ }
+ else {
+ if ((f & O_NONBLOCK) == 0)
+ return 0;
+ f &= ~O_NONBLOCK;
+ }
+ set_fcntl_flags(fd, f);
+ return 1;
+}
+
+/*
+ * call-seq:
+ * io.nonblock = boolean -> boolean
+ *
+ * Enables non-blocking mode on a stream when set to
+ * +true+, and blocking mode when set to +false+.
+ *
+ * This method set or clear O_NONBLOCK flag for the file descriptor
+ * in <em>ios</em>.
+ *
+ * The behavior of most IO methods is not affected by this flag
+ * because they retry system calls to complete their task
+ * after EAGAIN and partial read/write.
+ * (An exception is IO#syswrite which doesn't retry.)
+ *
+ * This method can be used to clear non-blocking mode of standard I/O.
+ * Since nonblocking methods (read_nonblock, etc.) set non-blocking mode but
+ * they doesn't clear it, this method is usable as follows.
+ *
+ * END { STDOUT.nonblock = false }
+ * STDOUT.write_nonblock("foo")
+ *
+ * Since the flag is shared across processes and
+ * many non-Ruby commands doesn't expect standard I/O with non-blocking mode,
+ * it would be safe to clear the flag before Ruby program exits.
+ *
+ * For example following Ruby program leaves STDIN/STDOUT/STDER non-blocking mode.
+ * (STDIN, STDOUT and STDERR are connected to a terminal.
+ * So making one of them nonblocking-mode effects other two.)
+ * Thus cat command try to read from standard input and
+ * it causes "Resource temporarily unavailable" error (EAGAIN).
+ *
+ * % ruby -e '
+ * STDOUT.write_nonblock("foo\n")'; cat
+ * foo
+ * cat: -: Resource temporarily unavailable
+ *
+ * Clearing the flag makes the behavior of cat command normal.
+ * (cat command waits input from standard input.)
+ *
+ * % ruby -rio/nonblock -e '
+ * END { STDOUT.nonblock = false }
+ * STDOUT.write_nonblock("foo")
+ * '; cat
+ * foo
+ *
+ */
+static VALUE
+rb_io_nonblock_set(VALUE self, VALUE value)
+{
+ if (RTEST(value)) {
+ rb_io_t *fptr;
+ GetOpenFile(self, fptr);
+ rb_io_set_nonblock(fptr);
+ }
+ else {
+ int descriptor = rb_io_descriptor(self);
+ io_nonblock_set(descriptor, get_fcntl_flags(descriptor), RTEST(value));
+ }
+
+ return self;
+}
+
+#endif /* RUBY_IO_NONBLOCK_METHODS */
+
+static VALUE
+io_nonblock_restore(VALUE arg)
+{
+ int *restore = (int *)arg;
+ set_fcntl_flags(restore[0], restore[1]);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * io.nonblock {|io| } -> object
+ * io.nonblock(boolean) {|io| } -> object
+ *
+ * Yields +self+ in non-blocking mode.
+ *
+ * When +false+ is given as an argument, +self+ is yielded in blocking mode.
+ * The original mode is restored after the block is executed.
+ */
+static VALUE
+rb_io_nonblock_block(int argc, VALUE *argv, VALUE self)
+{
+ int nb = 1;
+
+ int descriptor = rb_io_descriptor(self);
+
+ if (argc > 0) {
+ VALUE v;
+ rb_scan_args(argc, argv, "01", &v);
+ nb = RTEST(v);
+ }
+
+ int current_flags = get_fcntl_flags(descriptor);
+ int restore[2] = {descriptor, current_flags};
+
+ if (!io_nonblock_set(descriptor, current_flags, nb))
+ return rb_yield(self);
+
+ return rb_ensure(rb_yield, self, io_nonblock_restore, (VALUE)restore);
+}
+#else
+#define rb_io_nonblock_set rb_f_notimplement
+#define rb_io_nonblock_block rb_f_notimplement
+#endif
+
+void
+Init_nonblock(void)
+{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
+#ifndef RUBY_IO_NONBLOCK_METHODS
+ rb_define_method(rb_cIO, "nonblock?", rb_io_nonblock_p, 0);
+ rb_define_method(rb_cIO, "nonblock=", rb_io_nonblock_set, 1);
+#endif
+
+ rb_define_method(rb_cIO, "nonblock", rb_io_nonblock_block, -1);
+}
diff --git a/ext/io/wait/.cvsignore b/ext/io/wait/.cvsignore
deleted file mode 100644
index fc802ff1c2..0000000000
--- a/ext/io/wait/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-mkmf.log
diff --git a/ext/io/wait/depend b/ext/io/wait/depend
new file mode 100644
index 0000000000..41d53c1400
--- /dev/null
+++ b/ext/io/wait/depend
@@ -0,0 +1,176 @@
+# AUTOGENERATED DEPENDENCIES START
+wait.o: $(RUBY_EXTCONF_H)
+wait.o: $(arch_hdrdir)/ruby/config.h
+wait.o: $(hdrdir)/ruby.h
+wait.o: $(hdrdir)/ruby/assert.h
+wait.o: $(hdrdir)/ruby/backward.h
+wait.o: $(hdrdir)/ruby/backward/2/assume.h
+wait.o: $(hdrdir)/ruby/backward/2/attributes.h
+wait.o: $(hdrdir)/ruby/backward/2/bool.h
+wait.o: $(hdrdir)/ruby/backward/2/inttypes.h
+wait.o: $(hdrdir)/ruby/backward/2/limits.h
+wait.o: $(hdrdir)/ruby/backward/2/long_long.h
+wait.o: $(hdrdir)/ruby/backward/2/stdalign.h
+wait.o: $(hdrdir)/ruby/backward/2/stdarg.h
+wait.o: $(hdrdir)/ruby/defines.h
+wait.o: $(hdrdir)/ruby/encoding.h
+wait.o: $(hdrdir)/ruby/intern.h
+wait.o: $(hdrdir)/ruby/internal/abi.h
+wait.o: $(hdrdir)/ruby/internal/anyargs.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+wait.o: $(hdrdir)/ruby/internal/assume.h
+wait.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+wait.o: $(hdrdir)/ruby/internal/attr/artificial.h
+wait.o: $(hdrdir)/ruby/internal/attr/cold.h
+wait.o: $(hdrdir)/ruby/internal/attr/const.h
+wait.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+wait.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+wait.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+wait.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+wait.o: $(hdrdir)/ruby/internal/attr/error.h
+wait.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+wait.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+wait.o: $(hdrdir)/ruby/internal/attr/format.h
+wait.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+wait.o: $(hdrdir)/ruby/internal/attr/noalias.h
+wait.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+wait.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+wait.o: $(hdrdir)/ruby/internal/attr/noinline.h
+wait.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+wait.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+wait.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+wait.o: $(hdrdir)/ruby/internal/attr/pure.h
+wait.o: $(hdrdir)/ruby/internal/attr/restrict.h
+wait.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+wait.o: $(hdrdir)/ruby/internal/attr/warning.h
+wait.o: $(hdrdir)/ruby/internal/attr/weakref.h
+wait.o: $(hdrdir)/ruby/internal/cast.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+wait.o: $(hdrdir)/ruby/internal/compiler_since.h
+wait.o: $(hdrdir)/ruby/internal/config.h
+wait.o: $(hdrdir)/ruby/internal/constant_p.h
+wait.o: $(hdrdir)/ruby/internal/core.h
+wait.o: $(hdrdir)/ruby/internal/core/rarray.h
+wait.o: $(hdrdir)/ruby/internal/core/rbasic.h
+wait.o: $(hdrdir)/ruby/internal/core/rbignum.h
+wait.o: $(hdrdir)/ruby/internal/core/rclass.h
+wait.o: $(hdrdir)/ruby/internal/core/rdata.h
+wait.o: $(hdrdir)/ruby/internal/core/rfile.h
+wait.o: $(hdrdir)/ruby/internal/core/rhash.h
+wait.o: $(hdrdir)/ruby/internal/core/robject.h
+wait.o: $(hdrdir)/ruby/internal/core/rregexp.h
+wait.o: $(hdrdir)/ruby/internal/core/rstring.h
+wait.o: $(hdrdir)/ruby/internal/core/rstruct.h
+wait.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+wait.o: $(hdrdir)/ruby/internal/ctype.h
+wait.o: $(hdrdir)/ruby/internal/dllexport.h
+wait.o: $(hdrdir)/ruby/internal/dosish.h
+wait.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+wait.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+wait.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+wait.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+wait.o: $(hdrdir)/ruby/internal/encoding/re.h
+wait.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+wait.o: $(hdrdir)/ruby/internal/encoding/string.h
+wait.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+wait.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+wait.o: $(hdrdir)/ruby/internal/error.h
+wait.o: $(hdrdir)/ruby/internal/eval.h
+wait.o: $(hdrdir)/ruby/internal/event.h
+wait.o: $(hdrdir)/ruby/internal/fl_type.h
+wait.o: $(hdrdir)/ruby/internal/gc.h
+wait.o: $(hdrdir)/ruby/internal/glob.h
+wait.o: $(hdrdir)/ruby/internal/globals.h
+wait.o: $(hdrdir)/ruby/internal/has/attribute.h
+wait.o: $(hdrdir)/ruby/internal/has/builtin.h
+wait.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+wait.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+wait.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+wait.o: $(hdrdir)/ruby/internal/has/extension.h
+wait.o: $(hdrdir)/ruby/internal/has/feature.h
+wait.o: $(hdrdir)/ruby/internal/has/warning.h
+wait.o: $(hdrdir)/ruby/internal/intern/array.h
+wait.o: $(hdrdir)/ruby/internal/intern/bignum.h
+wait.o: $(hdrdir)/ruby/internal/intern/class.h
+wait.o: $(hdrdir)/ruby/internal/intern/compar.h
+wait.o: $(hdrdir)/ruby/internal/intern/complex.h
+wait.o: $(hdrdir)/ruby/internal/intern/cont.h
+wait.o: $(hdrdir)/ruby/internal/intern/dir.h
+wait.o: $(hdrdir)/ruby/internal/intern/enum.h
+wait.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+wait.o: $(hdrdir)/ruby/internal/intern/error.h
+wait.o: $(hdrdir)/ruby/internal/intern/eval.h
+wait.o: $(hdrdir)/ruby/internal/intern/file.h
+wait.o: $(hdrdir)/ruby/internal/intern/hash.h
+wait.o: $(hdrdir)/ruby/internal/intern/io.h
+wait.o: $(hdrdir)/ruby/internal/intern/load.h
+wait.o: $(hdrdir)/ruby/internal/intern/marshal.h
+wait.o: $(hdrdir)/ruby/internal/intern/numeric.h
+wait.o: $(hdrdir)/ruby/internal/intern/object.h
+wait.o: $(hdrdir)/ruby/internal/intern/parse.h
+wait.o: $(hdrdir)/ruby/internal/intern/proc.h
+wait.o: $(hdrdir)/ruby/internal/intern/process.h
+wait.o: $(hdrdir)/ruby/internal/intern/random.h
+wait.o: $(hdrdir)/ruby/internal/intern/range.h
+wait.o: $(hdrdir)/ruby/internal/intern/rational.h
+wait.o: $(hdrdir)/ruby/internal/intern/re.h
+wait.o: $(hdrdir)/ruby/internal/intern/ruby.h
+wait.o: $(hdrdir)/ruby/internal/intern/select.h
+wait.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+wait.o: $(hdrdir)/ruby/internal/intern/set.h
+wait.o: $(hdrdir)/ruby/internal/intern/signal.h
+wait.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+wait.o: $(hdrdir)/ruby/internal/intern/string.h
+wait.o: $(hdrdir)/ruby/internal/intern/struct.h
+wait.o: $(hdrdir)/ruby/internal/intern/thread.h
+wait.o: $(hdrdir)/ruby/internal/intern/time.h
+wait.o: $(hdrdir)/ruby/internal/intern/variable.h
+wait.o: $(hdrdir)/ruby/internal/intern/vm.h
+wait.o: $(hdrdir)/ruby/internal/interpreter.h
+wait.o: $(hdrdir)/ruby/internal/iterator.h
+wait.o: $(hdrdir)/ruby/internal/memory.h
+wait.o: $(hdrdir)/ruby/internal/method.h
+wait.o: $(hdrdir)/ruby/internal/module.h
+wait.o: $(hdrdir)/ruby/internal/newobj.h
+wait.o: $(hdrdir)/ruby/internal/scan_args.h
+wait.o: $(hdrdir)/ruby/internal/special_consts.h
+wait.o: $(hdrdir)/ruby/internal/static_assert.h
+wait.o: $(hdrdir)/ruby/internal/stdalign.h
+wait.o: $(hdrdir)/ruby/internal/stdbool.h
+wait.o: $(hdrdir)/ruby/internal/stdckdint.h
+wait.o: $(hdrdir)/ruby/internal/symbol.h
+wait.o: $(hdrdir)/ruby/internal/value.h
+wait.o: $(hdrdir)/ruby/internal/value_type.h
+wait.o: $(hdrdir)/ruby/internal/variable.h
+wait.o: $(hdrdir)/ruby/internal/warning_push.h
+wait.o: $(hdrdir)/ruby/internal/xmalloc.h
+wait.o: $(hdrdir)/ruby/io.h
+wait.o: $(hdrdir)/ruby/missing.h
+wait.o: $(hdrdir)/ruby/onigmo.h
+wait.o: $(hdrdir)/ruby/oniguruma.h
+wait.o: $(hdrdir)/ruby/ruby.h
+wait.o: $(hdrdir)/ruby/st.h
+wait.o: $(hdrdir)/ruby/subst.h
+wait.o: wait.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/io/wait/extconf.rb b/ext/io/wait/extconf.rb
index 1352ef202e..00c455a45c 100644
--- a/ext/io/wait/extconf.rb
+++ b/ext/io/wait/extconf.rb
@@ -1,17 +1,4 @@
+# frozen_string_literal: false
require 'mkmf'
-target = "io/wait"
-unless macro_defined?("DOSISH", "#include <ruby.h>")
- fionread = %w[sys/ioctl.h sys/filio.h].find do |h|
- checking_for("FIONREAD") {have_macro("FIONREAD", h)}
- end
- if fionread
- $defs << "-DFIONREAD_HEADER=\"<#{fionread}>\""
- create_makefile(target)
- end
-else
- if have_func("rb_w32_ioctlsocket", "ruby.h")
- have_func("rb_w32_is_socket", "ruby.h")
- create_makefile(target)
- end
-end
+create_makefile("io/wait")
diff --git a/ext/io/wait/io-wait.gemspec b/ext/io/wait/io-wait.gemspec
new file mode 100644
index 0000000000..c1c6172589
--- /dev/null
+++ b/ext/io/wait/io-wait.gemspec
@@ -0,0 +1,39 @@
+_VERSION = "0.4.0"
+
+Gem::Specification.new do |spec|
+ spec.name = "io-wait"
+ spec.version = _VERSION
+ spec.authors = ["Nobu Nakada", "Charles Oliver Nutter"]
+ spec.email = ["nobu@ruby-lang.org", "headius@headius.com"]
+
+ spec.summary = %q{Waits until IO is readable or writable without blocking.}
+ spec.description = %q{Waits until IO is readable or writable without blocking.}
+ spec.homepage = "https://github.com/ruby/io-wait"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.2")
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ jruby = true if Gem::Platform.new('java') =~ spec.platform or RUBY_ENGINE == 'jruby'
+ dir, gemspec = File.split(__FILE__)
+ excludes = [
+ *%w[:^/.git* :^/Gemfile* :^/Rakefile* :^/bin/ :^/test/ :^/rakelib/ :^*.java],
+ *(jruby ? %w[:^/ext/io] : %w[:^/ext/java]),
+ ":(exclude,literal,top)#{gemspec}"
+ ]
+ files = IO.popen(%w[git ls-files -z --] + excludes, chdir: dir, &:read).split("\x0")
+
+ spec.files = files
+ spec.bindir = "exe"
+ spec.executables = []
+ spec.require_paths = ["lib"]
+
+ if jruby
+ spec.platform = 'java'
+ spec.files << "lib/io/wait.jar"
+ spec.require_paths += ["ext/java/lib"]
+ else
+ spec.extensions = %w[ext/io/wait/extconf.rb]
+ end
+end
diff --git a/ext/io/wait/lib/nonblock.rb b/ext/io/wait/lib/nonblock.rb
deleted file mode 100644
index 2103fdf25b..0000000000
--- a/ext/io/wait/lib/nonblock.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require "fcntl"
-class IO
- def nonblock?
- (fcntl(Fcntl::F_GETFL) & File::NONBLOCK) != 0
- end
-
- def nonblock=(nb)
- f = fcntl(Fcntl::F_GETFL)
- if nb
- f |= File::NONBLOCK
- else
- f &= ~File::NONBLOCK
- end
- fcntl(Fcntl::F_SETFL, f)
- end
-
- def nonblock(nb = true)
- nb, self.nonblock = nonblock?, nb
- yield
- ensure
- self.nonblock = nb
- end
-end if defined?(Fcntl::F_GETFL)
diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c
index 61d6527b36..f7575191fe 100644
--- a/ext/io/wait/wait.c
+++ b/ext/io/wait/wait.c
@@ -1,9 +1,9 @@
+/* -*- c-file-style: "ruby"; indent-tabs-mode: t -*- */
/**********************************************************************
io/wait.c -
$Author$
- $Date$
created at: Tue Aug 28 09:08:06 JST 2001
All the files in this distribution are covered under the Ruby's
@@ -11,116 +11,13 @@
**********************************************************************/
-#include "ruby.h"
-#include "rubyio.h"
-
-#include <sys/types.h>
-#if defined(FIONREAD_HEADER)
-#include FIONREAD_HEADER
-#endif
-
-#ifdef HAVE_RB_W32_IOCTLSOCKET
-#define ioctl ioctlsocket
-#define ioctl_arg u_long
-#define ioctl_arg2num(i) ULONG2NUM(i)
-#else
-#define ioctl_arg int
-#define ioctl_arg2num(i) INT2NUM(i)
-#endif
-
-#ifdef HAVE_RB_W32_IS_SOCKET
-#define FIONREAD_POSSIBLE_P(fd) rb_w32_is_socket(fd)
-#else
-#define FIONREAD_POSSIBLE_P(fd) ((fd),Qtrue)
-#endif
-
-static VALUE io_ready_p _((VALUE io));
-static VALUE io_wait _((int argc, VALUE *argv, VALUE io));
-void Init_wait _((void));
-
-EXTERN struct timeval rb_time_interval _((VALUE time));
+#include "ruby.h" /* abi_version */
/*
-=begin
-= IO wait methods.
-=end
+ * IO wait methods are built in ruby now, just for backward compatibility.
*/
-/*
-=begin
---- IO#ready?
- returns non-nil if input available without blocking, or nil.
-=end
-*/
-static VALUE
-io_ready_p(io)
- VALUE io;
-{
- OpenFile *fptr;
- FILE *fp;
- ioctl_arg n;
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
- if (!FIONREAD_POSSIBLE_P(fileno(fptr->f))) return Qfalse;
- fp = fptr->f;
- if (feof(fp)) return Qfalse;
- if (rb_read_pending(fp)) return Qtrue;
- if (ioctl(fileno(fp), FIONREAD, &n)) rb_sys_fail(0);
- if (n > 0) return ioctl_arg2num(n);
- return Qnil;
-}
-
-/*
-=begin
---- IO#wait([timeout])
- waits until input available or timed out and returns self, or nil
- when EOF reached.
-=end
-*/
-static VALUE
-io_wait(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- OpenFile *fptr;
- fd_set rd;
- FILE *fp;
- int fd;
- ioctl_arg n;
- VALUE timeout;
- struct timeval *tp, timerec;
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
- rb_scan_args(argc, argv, "01", &timeout);
- if (NIL_P(timeout)) {
- tp = 0;
- }
- else {
- timerec = rb_time_interval(timeout);
- tp = &timerec;
- }
-
- fp = fptr->f;
- if (feof(fp)) return Qfalse;
- if (rb_read_pending(fp)) return Qtrue;
- fd = fileno(fp);
- FD_ZERO(&rd);
- FD_SET(fd, &rd);
- if (rb_thread_select(fd + 1, &rd, NULL, NULL, tp) < 0)
- rb_sys_fail(0);
- rb_io_check_closed(fptr);
- if (!FIONREAD_POSSIBLE_P(fileno(fptr->f))) return Qfalse;
- if (ioctl(fileno(fp), FIONREAD, &n)) rb_sys_fail(0);
- if (n > 0) return io;
- return Qnil;
-}
-
void
-Init_wait()
+Init_wait(void)
{
- rb_define_method(rb_cIO, "ready?", io_ready_p, 0);
- rb_define_method(rb_cIO, "wait", io_wait, -1);
}
diff --git a/ext/json/depend b/ext/json/depend
new file mode 100644
index 0000000000..0301ce074c
--- /dev/null
+++ b/ext/json/depend
@@ -0,0 +1,2 @@
+# AUTOGENERATED DEPENDENCIES START
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/json/extconf.rb b/ext/json/extconf.rb
new file mode 100644
index 0000000000..8a99b6a5c8
--- /dev/null
+++ b/ext/json/extconf.rb
@@ -0,0 +1,3 @@
+require 'mkmf'
+
+create_makefile('json')
diff --git a/ext/json/fbuffer/fbuffer.h b/ext/json/fbuffer/fbuffer.h
new file mode 100644
index 0000000000..b4f5266ca5
--- /dev/null
+++ b/ext/json/fbuffer/fbuffer.h
@@ -0,0 +1,260 @@
+#ifndef _FBUFFER_H_
+#define _FBUFFER_H_
+
+#include "../json.h"
+#include "../vendor/jeaiii-ltoa.h"
+
+enum fbuffer_type {
+ FBUFFER_HEAP_ALLOCATED = 0,
+ FBUFFER_STACK_ALLOCATED = 1,
+};
+
+typedef struct FBufferStruct {
+ enum fbuffer_type type;
+ size_t initial_length;
+ size_t len;
+ size_t capa;
+#if JSON_DEBUG
+ size_t requested;
+#endif
+ char *ptr;
+ VALUE io;
+} FBuffer;
+
+#define FBUFFER_STACK_SIZE 512
+#define FBUFFER_IO_BUFFER_SIZE (16384 - 1)
+#define FBUFFER_INITIAL_LENGTH_DEFAULT 1024
+
+#define FBUFFER_PTR(fb) ((fb)->ptr)
+#define FBUFFER_LEN(fb) ((fb)->len)
+#define FBUFFER_CAPA(fb) ((fb)->capa)
+#define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb)
+
+static void fbuffer_free(FBuffer *fb);
+static void fbuffer_clear(FBuffer *fb);
+static void fbuffer_append(FBuffer *fb, const char *newstr, size_t len);
+static void fbuffer_append_long(FBuffer *fb, long number);
+static inline void fbuffer_append_char(FBuffer *fb, char newchr);
+static VALUE fbuffer_finalize(FBuffer *fb);
+
+static void fbuffer_stack_init(FBuffer *fb, size_t initial_length, char *stack_buffer, size_t stack_buffer_size)
+{
+ fb->initial_length = (initial_length > 0) ? initial_length : FBUFFER_INITIAL_LENGTH_DEFAULT;
+ if (stack_buffer) {
+ fb->type = FBUFFER_STACK_ALLOCATED;
+ fb->ptr = stack_buffer;
+ fb->capa = stack_buffer_size;
+ }
+#if JSON_DEBUG
+ fb->requested = 0;
+#endif
+}
+
+static inline void fbuffer_consumed(FBuffer *fb, size_t consumed)
+{
+#if JSON_DEBUG
+ if (consumed > fb->requested) {
+ rb_bug("fbuffer: Out of bound write");
+ }
+ fb->requested = 0;
+#endif
+ fb->len += consumed;
+}
+
+static void fbuffer_free(FBuffer *fb)
+{
+ if (fb->ptr && fb->type == FBUFFER_HEAP_ALLOCATED) {
+ JSON_SIZED_FREE_N(fb->ptr, fb->capa);
+ }
+}
+
+static void fbuffer_clear(FBuffer *fb)
+{
+ fb->len = 0;
+}
+
+static void fbuffer_flush(FBuffer *fb)
+{
+ rb_io_write(fb->io, rb_utf8_str_new(fb->ptr, fb->len));
+ fbuffer_clear(fb);
+}
+
+static void fbuffer_realloc(FBuffer *fb, size_t required)
+{
+ if (required > fb->capa) {
+ if (fb->type == FBUFFER_STACK_ALLOCATED) {
+ const char *old_buffer = fb->ptr;
+ fb->ptr = ALLOC_N(char, required);
+ fb->type = FBUFFER_HEAP_ALLOCATED;
+ MEMCPY(fb->ptr, old_buffer, char, fb->len);
+ } else {
+ JSON_SIZED_REALLOC_N(fb->ptr, char, required, fb->capa);
+ }
+ fb->capa = required;
+ }
+}
+
+static void fbuffer_do_inc_capa(FBuffer *fb, size_t requested)
+{
+ if (RB_UNLIKELY(fb->io)) {
+ if (fb->capa < FBUFFER_IO_BUFFER_SIZE) {
+ fbuffer_realloc(fb, FBUFFER_IO_BUFFER_SIZE);
+ } else {
+ fbuffer_flush(fb);
+ }
+
+ if (RB_LIKELY(requested < fb->capa)) {
+ return;
+ }
+ }
+
+ size_t required;
+
+ if (RB_UNLIKELY(!fb->ptr)) {
+ fb->ptr = ALLOC_N(char, fb->initial_length);
+ fb->capa = fb->initial_length;
+ }
+
+ for (required = fb->capa; requested > required - fb->len; required <<= 1);
+
+ fbuffer_realloc(fb, required);
+}
+
+static inline void fbuffer_inc_capa(FBuffer *fb, size_t requested)
+{
+#if JSON_DEBUG
+ fb->requested = requested;
+#endif
+
+ if (RB_UNLIKELY(requested > fb->capa - fb->len)) {
+ fbuffer_do_inc_capa(fb, requested);
+ }
+}
+
+static inline size_t fbuffer_size_mul_or_raise(size_t a, size_t b)
+{
+ size_t result = a * b;
+ if (RB_UNLIKELY(a != 0 && (result / a) != b)) {
+ rb_raise(rb_eArgError, "Buffer overflow, the resulting document is too large to be generated");
+ }
+ return result;
+}
+
+static inline void fbuffer_append_reserved(FBuffer *fb, const char *newstr, size_t len)
+{
+ MEMCPY(fb->ptr + fb->len, newstr, char, len);
+ fbuffer_consumed(fb, len);
+}
+
+static inline void fbuffer_append(FBuffer *fb, const char *newstr, size_t len)
+{
+ if (len > 0) {
+ fbuffer_inc_capa(fb, len);
+ fbuffer_append_reserved(fb, newstr, len);
+ }
+}
+
+/* Appends a character into a buffer. The buffer needs to have sufficient capacity, via fbuffer_inc_capa(...). */
+static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr)
+{
+#if JSON_DEBUG
+ if (fb->requested < 1) {
+ rb_bug("fbuffer: unreserved write");
+ }
+ fb->requested--;
+#endif
+
+ fb->ptr[fb->len] = chr;
+ fb->len++;
+}
+
+static void fbuffer_append_str(FBuffer *fb, VALUE str)
+{
+ const char *ptr;
+ size_t len;
+ RSTRING_GETMEM(str, ptr, len);
+
+ fbuffer_append(fb, ptr, len);
+ RB_GC_GUARD(str);
+}
+
+static void fbuffer_append_str_repeat(FBuffer *fb, VALUE str, size_t repeat)
+{
+ const char *ptr;
+ size_t len;
+ RSTRING_GETMEM(str, ptr, len);
+
+ fbuffer_inc_capa(fb, fbuffer_size_mul_or_raise(repeat, len));
+ while (repeat) {
+#if JSON_DEBUG
+ fb->requested = len;
+#endif
+ fbuffer_append_reserved(fb, ptr, len);
+ repeat--;
+ }
+ RB_GC_GUARD(str);
+}
+
+static inline void fbuffer_append_char(FBuffer *fb, char newchr)
+{
+ fbuffer_inc_capa(fb, 1);
+ *(fb->ptr + fb->len) = newchr;
+ fbuffer_consumed(fb, 1);
+}
+
+static inline char *fbuffer_cursor(FBuffer *fb)
+{
+ return fb->ptr + fb->len;
+}
+
+static inline void fbuffer_advance_to(FBuffer *fb, char *end)
+{
+ fbuffer_consumed(fb, (end - fb->ptr) - fb->len);
+}
+
+/*
+ * Appends the decimal string representation of \a number into the buffer.
+ */
+static void fbuffer_append_long(FBuffer *fb, long number)
+{
+ /*
+ * The jeaiii_ultoa() function produces digits left-to-right,
+ * allowing us to write directly into the buffer, but we don't know
+ * the number of resulting characters.
+ *
+ * We do know, however, that the `number` argument is always in the
+ * range 0xc000000000000000 to 0x3fffffffffffffff, or, in decimal,
+ * -4611686018427387904 to 4611686018427387903. The max number of chars
+ * generated is therefore 20 (including a potential sign character).
+ */
+
+ static const int MAX_CHARS_FOR_LONG = 20;
+
+ fbuffer_inc_capa(fb, MAX_CHARS_FOR_LONG);
+
+ if (number < 0) {
+ fbuffer_append_reserved_char(fb, '-');
+
+ /*
+ * Since number is always > LONG_MIN, `-number` will not overflow
+ * and is always the positive abs() value.
+ */
+ number = -number;
+ }
+
+ char *end = jeaiii_ultoa(fbuffer_cursor(fb), number);
+ fbuffer_advance_to(fb, end);
+}
+
+static VALUE fbuffer_finalize(FBuffer *fb)
+{
+ if (fb->io) {
+ fbuffer_flush(fb);
+ rb_io_flush(fb->io);
+ return fb->io;
+ } else {
+ return rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
+ }
+}
+
+#endif // _FBUFFER_H_
diff --git a/ext/json/generator/depend b/ext/json/generator/depend
new file mode 100644
index 0000000000..3ba4acfdd2
--- /dev/null
+++ b/ext/json/generator/depend
@@ -0,0 +1,186 @@
+$(OBJS): $(ruby_headers)
+generator.o: generator.c $(srcdir)/../fbuffer/fbuffer.h
+
+# AUTOGENERATED DEPENDENCIES START
+generator.o: $(RUBY_EXTCONF_H)
+generator.o: $(arch_hdrdir)/ruby/config.h
+generator.o: $(hdrdir)/ruby.h
+generator.o: $(hdrdir)/ruby/assert.h
+generator.o: $(hdrdir)/ruby/backward.h
+generator.o: $(hdrdir)/ruby/backward/2/assume.h
+generator.o: $(hdrdir)/ruby/backward/2/attributes.h
+generator.o: $(hdrdir)/ruby/backward/2/bool.h
+generator.o: $(hdrdir)/ruby/backward/2/inttypes.h
+generator.o: $(hdrdir)/ruby/backward/2/limits.h
+generator.o: $(hdrdir)/ruby/backward/2/long_long.h
+generator.o: $(hdrdir)/ruby/backward/2/stdalign.h
+generator.o: $(hdrdir)/ruby/backward/2/stdarg.h
+generator.o: $(hdrdir)/ruby/defines.h
+generator.o: $(hdrdir)/ruby/encoding.h
+generator.o: $(hdrdir)/ruby/intern.h
+generator.o: $(hdrdir)/ruby/internal/abi.h
+generator.o: $(hdrdir)/ruby/internal/anyargs.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+generator.o: $(hdrdir)/ruby/internal/assume.h
+generator.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+generator.o: $(hdrdir)/ruby/internal/attr/artificial.h
+generator.o: $(hdrdir)/ruby/internal/attr/cold.h
+generator.o: $(hdrdir)/ruby/internal/attr/const.h
+generator.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+generator.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+generator.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+generator.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+generator.o: $(hdrdir)/ruby/internal/attr/error.h
+generator.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+generator.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+generator.o: $(hdrdir)/ruby/internal/attr/format.h
+generator.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+generator.o: $(hdrdir)/ruby/internal/attr/noalias.h
+generator.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+generator.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+generator.o: $(hdrdir)/ruby/internal/attr/noinline.h
+generator.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+generator.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+generator.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+generator.o: $(hdrdir)/ruby/internal/attr/pure.h
+generator.o: $(hdrdir)/ruby/internal/attr/restrict.h
+generator.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+generator.o: $(hdrdir)/ruby/internal/attr/warning.h
+generator.o: $(hdrdir)/ruby/internal/attr/weakref.h
+generator.o: $(hdrdir)/ruby/internal/cast.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+generator.o: $(hdrdir)/ruby/internal/compiler_since.h
+generator.o: $(hdrdir)/ruby/internal/config.h
+generator.o: $(hdrdir)/ruby/internal/constant_p.h
+generator.o: $(hdrdir)/ruby/internal/core.h
+generator.o: $(hdrdir)/ruby/internal/core/rarray.h
+generator.o: $(hdrdir)/ruby/internal/core/rbasic.h
+generator.o: $(hdrdir)/ruby/internal/core/rbignum.h
+generator.o: $(hdrdir)/ruby/internal/core/rclass.h
+generator.o: $(hdrdir)/ruby/internal/core/rdata.h
+generator.o: $(hdrdir)/ruby/internal/core/rfile.h
+generator.o: $(hdrdir)/ruby/internal/core/rhash.h
+generator.o: $(hdrdir)/ruby/internal/core/rmatch.h
+generator.o: $(hdrdir)/ruby/internal/core/robject.h
+generator.o: $(hdrdir)/ruby/internal/core/rregexp.h
+generator.o: $(hdrdir)/ruby/internal/core/rstring.h
+generator.o: $(hdrdir)/ruby/internal/core/rstruct.h
+generator.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+generator.o: $(hdrdir)/ruby/internal/ctype.h
+generator.o: $(hdrdir)/ruby/internal/dllexport.h
+generator.o: $(hdrdir)/ruby/internal/dosish.h
+generator.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+generator.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+generator.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+generator.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+generator.o: $(hdrdir)/ruby/internal/encoding/re.h
+generator.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+generator.o: $(hdrdir)/ruby/internal/encoding/string.h
+generator.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+generator.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+generator.o: $(hdrdir)/ruby/internal/error.h
+generator.o: $(hdrdir)/ruby/internal/eval.h
+generator.o: $(hdrdir)/ruby/internal/event.h
+generator.o: $(hdrdir)/ruby/internal/fl_type.h
+generator.o: $(hdrdir)/ruby/internal/gc.h
+generator.o: $(hdrdir)/ruby/internal/glob.h
+generator.o: $(hdrdir)/ruby/internal/globals.h
+generator.o: $(hdrdir)/ruby/internal/has/attribute.h
+generator.o: $(hdrdir)/ruby/internal/has/builtin.h
+generator.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+generator.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+generator.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+generator.o: $(hdrdir)/ruby/internal/has/extension.h
+generator.o: $(hdrdir)/ruby/internal/has/feature.h
+generator.o: $(hdrdir)/ruby/internal/has/warning.h
+generator.o: $(hdrdir)/ruby/internal/intern/array.h
+generator.o: $(hdrdir)/ruby/internal/intern/bignum.h
+generator.o: $(hdrdir)/ruby/internal/intern/class.h
+generator.o: $(hdrdir)/ruby/internal/intern/compar.h
+generator.o: $(hdrdir)/ruby/internal/intern/complex.h
+generator.o: $(hdrdir)/ruby/internal/intern/cont.h
+generator.o: $(hdrdir)/ruby/internal/intern/dir.h
+generator.o: $(hdrdir)/ruby/internal/intern/enum.h
+generator.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+generator.o: $(hdrdir)/ruby/internal/intern/error.h
+generator.o: $(hdrdir)/ruby/internal/intern/eval.h
+generator.o: $(hdrdir)/ruby/internal/intern/file.h
+generator.o: $(hdrdir)/ruby/internal/intern/hash.h
+generator.o: $(hdrdir)/ruby/internal/intern/io.h
+generator.o: $(hdrdir)/ruby/internal/intern/load.h
+generator.o: $(hdrdir)/ruby/internal/intern/marshal.h
+generator.o: $(hdrdir)/ruby/internal/intern/numeric.h
+generator.o: $(hdrdir)/ruby/internal/intern/object.h
+generator.o: $(hdrdir)/ruby/internal/intern/parse.h
+generator.o: $(hdrdir)/ruby/internal/intern/proc.h
+generator.o: $(hdrdir)/ruby/internal/intern/process.h
+generator.o: $(hdrdir)/ruby/internal/intern/random.h
+generator.o: $(hdrdir)/ruby/internal/intern/range.h
+generator.o: $(hdrdir)/ruby/internal/intern/rational.h
+generator.o: $(hdrdir)/ruby/internal/intern/re.h
+generator.o: $(hdrdir)/ruby/internal/intern/ruby.h
+generator.o: $(hdrdir)/ruby/internal/intern/select.h
+generator.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+generator.o: $(hdrdir)/ruby/internal/intern/set.h
+generator.o: $(hdrdir)/ruby/internal/intern/signal.h
+generator.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+generator.o: $(hdrdir)/ruby/internal/intern/string.h
+generator.o: $(hdrdir)/ruby/internal/intern/struct.h
+generator.o: $(hdrdir)/ruby/internal/intern/thread.h
+generator.o: $(hdrdir)/ruby/internal/intern/time.h
+generator.o: $(hdrdir)/ruby/internal/intern/variable.h
+generator.o: $(hdrdir)/ruby/internal/intern/vm.h
+generator.o: $(hdrdir)/ruby/internal/interpreter.h
+generator.o: $(hdrdir)/ruby/internal/iterator.h
+generator.o: $(hdrdir)/ruby/internal/memory.h
+generator.o: $(hdrdir)/ruby/internal/method.h
+generator.o: $(hdrdir)/ruby/internal/module.h
+generator.o: $(hdrdir)/ruby/internal/newobj.h
+generator.o: $(hdrdir)/ruby/internal/scan_args.h
+generator.o: $(hdrdir)/ruby/internal/special_consts.h
+generator.o: $(hdrdir)/ruby/internal/static_assert.h
+generator.o: $(hdrdir)/ruby/internal/stdalign.h
+generator.o: $(hdrdir)/ruby/internal/stdbool.h
+generator.o: $(hdrdir)/ruby/internal/stdckdint.h
+generator.o: $(hdrdir)/ruby/internal/symbol.h
+generator.o: $(hdrdir)/ruby/internal/value.h
+generator.o: $(hdrdir)/ruby/internal/value_type.h
+generator.o: $(hdrdir)/ruby/internal/variable.h
+generator.o: $(hdrdir)/ruby/internal/warning_push.h
+generator.o: $(hdrdir)/ruby/internal/xmalloc.h
+generator.o: $(hdrdir)/ruby/missing.h
+generator.o: $(hdrdir)/ruby/onigmo.h
+generator.o: $(hdrdir)/ruby/oniguruma.h
+generator.o: $(hdrdir)/ruby/re.h
+generator.o: $(hdrdir)/ruby/regex.h
+generator.o: $(hdrdir)/ruby/ruby.h
+generator.o: $(hdrdir)/ruby/st.h
+generator.o: $(hdrdir)/ruby/subst.h
+generator.o: $(srcdir)/../fbuffer/fbuffer.h
+generator.o: $(srcdir)/../json.h
+generator.o: $(srcdir)/../simd/simd.h
+generator.o: $(srcdir)/../vendor/fpconv.c
+generator.o: $(srcdir)/../vendor/jeaiii-ltoa.h
+generator.o: generator.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/json/generator/extconf.rb b/ext/json/generator/extconf.rb
new file mode 100644
index 0000000000..33af03ea30
--- /dev/null
+++ b/ext/json/generator/extconf.rb
@@ -0,0 +1,19 @@
+require 'mkmf'
+
+if RUBY_ENGINE == 'truffleruby'
+ # The pure-Ruby generator is faster on TruffleRuby, so skip compiling the generator extension
+ File.write('Makefile', dummy_makefile("").join)
+else
+ append_cflags("-std=c99")
+ have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3
+ have_func("ruby_xfree_sized", "ruby.h") # RUBY_VERSION >= 4.1
+
+ $defs << "-DJSON_GENERATOR"
+ $defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
+
+ if enable_config('generator-use-simd', default=!ENV["JSON_DISABLE_SIMD"])
+ load __dir__ + "/../simd/conf.rb"
+ end
+
+ create_makefile 'json/ext/generator'
+end
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
new file mode 100644
index 0000000000..110b5f6b32
--- /dev/null
+++ b/ext/json/generator/generator.c
@@ -0,0 +1,1997 @@
+#include "../json.h"
+#include "../fbuffer/fbuffer.h"
+#include "../vendor/fpconv.c"
+
+#include <math.h>
+#include <ctype.h>
+
+#include "../simd/simd.h"
+
+/* ruby api and some helpers */
+
+enum duplicate_key_action {
+ JSON_DEPRECATED = 0,
+ JSON_IGNORE,
+ JSON_RAISE,
+};
+
+typedef struct JSON_Generator_StateStruct {
+ VALUE indent;
+ VALUE space;
+ VALUE space_before;
+ VALUE object_nl;
+ VALUE array_nl;
+ VALUE as_json;
+
+ long max_nesting;
+ long depth;
+ long buffer_initial_length;
+
+ enum duplicate_key_action on_duplicate_key;
+
+ bool as_json_single_arg;
+ bool allow_nan;
+ bool ascii_only;
+ bool script_safe;
+ bool strict;
+} JSON_Generator_State;
+
+static VALUE mJSON, cState, cFragment, eGeneratorError, eNestingError, Encoding_UTF_8;
+
+static ID i_to_s, i_to_json, i_new, i_encode;
+static VALUE sym_indent, sym_space, sym_space_before, sym_object_nl, sym_array_nl, sym_max_nesting, sym_allow_nan, sym_allow_duplicate_key,
+ sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe, sym_escape_slash, sym_strict, sym_as_json;
+
+
+#define GET_STATE_TO(self, state) \
+ TypedData_Get_Struct(self, JSON_Generator_State, &JSON_Generator_State_type, state)
+
+#define GET_STATE(self) \
+ JSON_Generator_State *state; \
+ GET_STATE_TO(self, state)
+
+struct generate_json_data;
+
+typedef void (*generator_func)(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+
+struct generate_json_data {
+ FBuffer *buffer;
+ VALUE vstate;
+ JSON_Generator_State *state;
+ VALUE obj;
+ generator_func func;
+ long depth;
+};
+
+static SIMD_Implementation simd_impl;
+
+static VALUE cState_from_state_s(VALUE self, VALUE opts);
+static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func, VALUE io);
+static void generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+
+static int usascii_encindex, utf8_encindex, binary_encindex;
+
+NORETURN(static void) raise_generator_error_str(VALUE invalid_object, VALUE str)
+{
+ rb_enc_associate_index(str, utf8_encindex);
+ VALUE exc = rb_exc_new_str(eGeneratorError, str);
+ rb_ivar_set(exc, rb_intern("@invalid_object"), invalid_object);
+ rb_exc_raise(exc);
+}
+
+#ifdef RBIMPL_ATTR_FORMAT
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
+#endif
+NORETURN(static void) raise_generator_error(VALUE invalid_object, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ VALUE str = rb_vsprintf(fmt, args);
+ va_end(args);
+ raise_generator_error_str(invalid_object, str);
+}
+
+// 0 - single byte char that don't need to be escaped.
+// (x | 8) - char that needs to be escaped.
+static const unsigned char CHAR_LENGTH_MASK = 7;
+static const unsigned char ESCAPE_MASK = 8;
+
+typedef struct _search_state {
+ const char *ptr;
+ const char *end;
+ const char *cursor;
+ FBuffer *buffer;
+
+#ifdef HAVE_SIMD
+ const char *chunk_base;
+ const char *chunk_end;
+ bool has_matches;
+
+#if defined(HAVE_SIMD_NEON)
+ uint64_t matches_mask;
+#elif defined(HAVE_SIMD_SSE2)
+ int matches_mask;
+#else
+#error "Unknown SIMD Implementation."
+#endif /* HAVE_SIMD_NEON */
+#endif /* HAVE_SIMD */
+} search_state;
+
+ALWAYS_INLINE(static) void search_flush(search_state *search)
+{
+ // Do not remove this conditional without profiling, specifically escape-heavy text.
+ // escape_UTF8_char_basic will advance search->ptr and search->cursor (effectively a search_flush).
+ // For back-to-back characters that need to be escaped, specifically for the SIMD code paths, this method
+ // will be called just before calling escape_UTF8_char_basic. There will be no characters to append for the
+ // consecutive characters that need to be escaped. While the fbuffer_append is a no-op if
+ // nothing needs to be flushed, we can save a few memory references with this conditional.
+ if (search->ptr > search->cursor) {
+ fbuffer_append(search->buffer, search->cursor, search->ptr - search->cursor);
+ search->cursor = search->ptr;
+ }
+}
+
+static const unsigned char escape_table_basic[256] = {
+ // ASCII Control Characters
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ // ASCII Characters
+ 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // '"'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, // '\\'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static inline unsigned char search_escape_basic(search_state *search)
+{
+ while (search->ptr < search->end) {
+ if (RB_UNLIKELY(escape_table_basic[(const unsigned char)*search->ptr])) {
+ search_flush(search);
+ return 1;
+ } else {
+ search->ptr++;
+ }
+ }
+ search_flush(search);
+ return 0;
+}
+
+ALWAYS_INLINE(static) void escape_UTF8_char_basic(search_state *search)
+{
+ const unsigned char ch = (unsigned char)*search->ptr;
+ switch (ch) {
+ case '"': fbuffer_append(search->buffer, "\\\"", 2); break;
+ case '\\': fbuffer_append(search->buffer, "\\\\", 2); break;
+ case '/': fbuffer_append(search->buffer, "\\/", 2); break;
+ case '\b': fbuffer_append(search->buffer, "\\b", 2); break;
+ case '\f': fbuffer_append(search->buffer, "\\f", 2); break;
+ case '\n': fbuffer_append(search->buffer, "\\n", 2); break;
+ case '\r': fbuffer_append(search->buffer, "\\r", 2); break;
+ case '\t': fbuffer_append(search->buffer, "\\t", 2); break;
+ default: {
+ const char *hexdig = "0123456789abcdef";
+ char scratch[6] = { '\\', 'u', '0', '0', 0, 0 };
+ scratch[4] = hexdig[(ch >> 4) & 0xf];
+ scratch[5] = hexdig[ch & 0xf];
+ fbuffer_append(search->buffer, scratch, 6);
+ break;
+ }
+ }
+ search->ptr++;
+ search->cursor = search->ptr;
+}
+
+/* Converts in_string to a JSON string (without the wrapping '"'
+ * characters) in FBuffer out_buffer.
+ *
+ * Character are JSON-escaped according to:
+ *
+ * - Always: ASCII control characters (0x00-0x1F), dquote, and
+ * backslash.
+ *
+ * - If out_ascii_only: non-ASCII characters (>0x7F)
+ *
+ * - If script_safe: forwardslash (/), line separator (U+2028), and
+ * paragraph separator (U+2029)
+ *
+ * Everything else (should be UTF-8) is just passed through and
+ * appended to the result.
+ */
+
+
+#if defined(HAVE_SIMD_NEON)
+static inline unsigned char search_escape_basic_neon(search_state *search);
+#elif defined(HAVE_SIMD_SSE2)
+static inline unsigned char search_escape_basic_sse2(search_state *search);
+#endif
+
+static inline unsigned char search_escape_basic(search_state *search);
+
+static inline void convert_UTF8_to_JSON(search_state *search)
+{
+#ifdef HAVE_SIMD
+#if defined(HAVE_SIMD_NEON)
+ while (search_escape_basic_neon(search)) {
+ escape_UTF8_char_basic(search);
+ }
+#elif defined(HAVE_SIMD_SSE2)
+ if (simd_impl == SIMD_SSE2) {
+ while (search_escape_basic_sse2(search)) {
+ escape_UTF8_char_basic(search);
+ }
+ return;
+ }
+ while (search_escape_basic(search)) {
+ escape_UTF8_char_basic(search);
+ }
+#endif
+#else
+ while (search_escape_basic(search)) {
+ escape_UTF8_char_basic(search);
+ }
+#endif /* HAVE_SIMD */
+}
+
+static inline void escape_UTF8_char(search_state *search, unsigned char ch_len)
+{
+ const unsigned char ch = (unsigned char)*search->ptr;
+ switch (ch_len) {
+ case 1: {
+ switch (ch) {
+ case '"': fbuffer_append(search->buffer, "\\\"", 2); break;
+ case '\\': fbuffer_append(search->buffer, "\\\\", 2); break;
+ case '/': fbuffer_append(search->buffer, "\\/", 2); break;
+ case '\b': fbuffer_append(search->buffer, "\\b", 2); break;
+ case '\f': fbuffer_append(search->buffer, "\\f", 2); break;
+ case '\n': fbuffer_append(search->buffer, "\\n", 2); break;
+ case '\r': fbuffer_append(search->buffer, "\\r", 2); break;
+ case '\t': fbuffer_append(search->buffer, "\\t", 2); break;
+ default: {
+ const char *hexdig = "0123456789abcdef";
+ char scratch[6] = { '\\', 'u', '0', '0', 0, 0 };
+ scratch[4] = hexdig[(ch >> 4) & 0xf];
+ scratch[5] = hexdig[ch & 0xf];
+ fbuffer_append(search->buffer, scratch, 6);
+ break;
+ }
+ }
+ break;
+ }
+ case 3: {
+ if (search->ptr[2] & 1) {
+ fbuffer_append(search->buffer, "\\u2029", 6);
+ } else {
+ fbuffer_append(search->buffer, "\\u2028", 6);
+ }
+ break;
+ }
+ }
+ search->cursor = (search->ptr += ch_len);
+}
+
+#ifdef HAVE_SIMD
+
+ALWAYS_INLINE(static) char *copy_remaining_bytes(search_state *search, unsigned long vec_len, unsigned long len)
+{
+ RBIMPL_ASSERT_OR_ASSUME(len < vec_len);
+
+ // Flush the buffer so everything up until the last 'len' characters are unflushed.
+ search_flush(search);
+
+ FBuffer *buf = search->buffer;
+ fbuffer_inc_capa(buf, vec_len);
+
+ char *s = (buf->ptr + buf->len);
+
+ // Pad the buffer with dummy characters that won't need escaping.
+ // This seem wasteful at first sight, but memset of vector length is very fast.
+ // This is a space as it can be directly represented as an immediate on AArch64.
+ memset(s, ' ', vec_len);
+
+ // Optimistically copy the remaining 'len' characters to the output FBuffer. If there are no characters
+ // to escape, then everything ends up in the correct spot. Otherwise it was convenient temporary storage.
+ if (vec_len == 16) {
+ RBIMPL_ASSERT_OR_ASSUME(len >= SIMD_MINIMUM_THRESHOLD);
+ json_fast_memcpy16(s, search->ptr, len);
+ } else {
+ MEMCPY(s, search->ptr, char, len);
+ }
+
+ return s;
+}
+
+#ifdef HAVE_SIMD_NEON
+
+ALWAYS_INLINE(static) unsigned char neon_next_match(search_state *search)
+{
+ uint64_t mask = search->matches_mask;
+ uint32_t index = trailing_zeros64(mask) >> 2;
+
+ // It is assumed escape_UTF8_char_basic will only ever increase search->ptr by at most one character.
+ // If we want to use a similar approach for full escaping we'll need to ensure:
+ // search->chunk_base + index >= search->ptr
+ // However, since we know escape_UTF8_char_basic only increases search->ptr by one, if the next match
+ // is one byte after the previous match then:
+ // search->chunk_base + index == search->ptr
+ search->ptr = search->chunk_base + index;
+ mask &= mask - 1;
+ search->matches_mask = mask;
+ search_flush(search);
+ return 1;
+}
+
+static inline unsigned char search_escape_basic_neon(search_state *search)
+{
+ if (RB_UNLIKELY(search->has_matches)) {
+ // There are more matches if search->matches_mask > 0.
+ if (search->matches_mask > 0) {
+ return neon_next_match(search);
+ } else {
+ // neon_next_match will only advance search->ptr up to the last matching character.
+ // Skip over any characters in the last chunk that occur after the last match.
+ search->has_matches = false;
+ search->ptr = search->chunk_end;
+ }
+ }
+
+ /*
+ * The code below implements an SIMD-based algorithm to determine if N bytes at a time
+ * need to be escaped.
+ *
+ * Assume the ptr = "Te\sting!" (the double quotes are included in the string)
+ *
+ * The explanation will be limited to the first 8 bytes of the string for simplicity. However
+ * the vector insructions may work on larger vectors.
+ *
+ * First, we load three constants 'lower_bound', 'backslash' and 'dblquote" in vector registers.
+ *
+ * lower_bound: [20 20 20 20 20 20 20 20]
+ * backslash: [5C 5C 5C 5C 5C 5C 5C 5C]
+ * dblquote: [22 22 22 22 22 22 22 22]
+ *
+ * Next we load the first chunk of the ptr:
+ * [22 54 65 5C 73 74 69 6E] (" T e \ s t i n)
+ *
+ * First we check if any byte in chunk is less than 32 (0x20). This returns the following vector
+ * as no bytes are less than 32 (0x20):
+ * [0 0 0 0 0 0 0 0]
+ *
+ * Next, we check if any byte in chunk is equal to a backslash:
+ * [0 0 0 FF 0 0 0 0]
+ *
+ * Finally we check if any byte in chunk is equal to a double quote:
+ * [FF 0 0 0 0 0 0 0]
+ *
+ * Now we have three vectors where each byte indicates if the corresponding byte in chunk
+ * needs to be escaped. We combine these vectors with a series of logical OR instructions.
+ * This is the needs_escape vector and it is equal to:
+ * [FF 0 0 FF 0 0 0 0]
+ *
+ * Next we compute the bitwise AND between each byte and 0x1 and compute the horizontal sum of
+ * the values in the vector. This computes how many bytes need to be escaped within this chunk.
+ *
+ * Finally we compute a mask that indicates which bytes need to be escaped. If the mask is 0 then,
+ * no bytes need to be escaped and we can continue to the next chunk. If the mask is not 0 then we
+ * have at least one byte that needs to be escaped.
+ */
+
+ if (string_scan_simd_neon(&search->ptr, search->end, &search->matches_mask)) {
+ search->has_matches = true;
+ search->chunk_base = search->ptr;
+ search->chunk_end = search->ptr + sizeof(uint8x16_t);
+ return neon_next_match(search);
+ }
+
+ // There are fewer than 16 bytes left.
+ unsigned long remaining = (search->end - search->ptr);
+ if (remaining >= SIMD_MINIMUM_THRESHOLD) {
+ char *s = copy_remaining_bytes(search, sizeof(uint8x16_t), remaining);
+
+ uint64_t mask = compute_chunk_mask_neon(s);
+
+ if (!mask) {
+ // Nothing to escape, ensure search_flush doesn't do anything by setting
+ // search->cursor to search->ptr.
+ fbuffer_consumed(search->buffer, remaining);
+ search->ptr = search->end;
+ search->cursor = search->end;
+ return 0;
+ }
+
+ search->matches_mask = mask;
+ search->has_matches = true;
+ search->chunk_end = search->end;
+ search->chunk_base = search->ptr;
+ return neon_next_match(search);
+ }
+
+ if (search->ptr < search->end) {
+ return search_escape_basic(search);
+ }
+
+ search_flush(search);
+ return 0;
+}
+#endif /* HAVE_SIMD_NEON */
+
+#ifdef HAVE_SIMD_SSE2
+
+ALWAYS_INLINE(static) unsigned char sse2_next_match(search_state *search)
+{
+ int mask = search->matches_mask;
+ int index = trailing_zeros(mask);
+
+ // It is assumed escape_UTF8_char_basic will only ever increase search->ptr by at most one character.
+ // If we want to use a similar approach for full escaping we'll need to ensure:
+ // search->chunk_base + index >= search->ptr
+ // However, since we know escape_UTF8_char_basic only increases search->ptr by one, if the next match
+ // is one byte after the previous match then:
+ // search->chunk_base + index == search->ptr
+ search->ptr = search->chunk_base + index;
+ mask &= mask - 1;
+ search->matches_mask = mask;
+ search_flush(search);
+ return 1;
+}
+
+#if defined(__clang__) || defined(__GNUC__)
+#define TARGET_SSE2 __attribute__((target("sse2")))
+#else
+#define TARGET_SSE2
+#endif
+
+ALWAYS_INLINE(static) TARGET_SSE2 unsigned char search_escape_basic_sse2(search_state *search)
+{
+ if (RB_UNLIKELY(search->has_matches)) {
+ // There are more matches if search->matches_mask > 0.
+ if (search->matches_mask > 0) {
+ return sse2_next_match(search);
+ } else {
+ // sse2_next_match will only advance search->ptr up to the last matching character.
+ // Skip over any characters in the last chunk that occur after the last match.
+ search->has_matches = false;
+ if (RB_UNLIKELY(search->chunk_base + sizeof(__m128i) >= search->end)) {
+ search->ptr = search->end;
+ } else {
+ search->ptr = search->chunk_base + sizeof(__m128i);
+ }
+ }
+ }
+
+ if (string_scan_simd_sse2(&search->ptr, search->end, &search->matches_mask)) {
+ search->has_matches = true;
+ search->chunk_base = search->ptr;
+ search->chunk_end = search->ptr + sizeof(__m128i);
+ return sse2_next_match(search);
+ }
+
+ // There are fewer than 16 bytes left.
+ unsigned long remaining = (search->end - search->ptr);
+ if (remaining >= SIMD_MINIMUM_THRESHOLD) {
+ char *s = copy_remaining_bytes(search, sizeof(__m128i), remaining);
+
+ int needs_escape_mask = compute_chunk_mask_sse2(s);
+
+ if (needs_escape_mask == 0) {
+ // Nothing to escape, ensure search_flush doesn't do anything by setting
+ // search->cursor to search->ptr.
+ fbuffer_consumed(search->buffer, remaining);
+ search->ptr = search->end;
+ search->cursor = search->end;
+ return 0;
+ }
+
+ search->has_matches = true;
+ search->matches_mask = needs_escape_mask;
+ search->chunk_base = search->ptr;
+ return sse2_next_match(search);
+ }
+
+ if (search->ptr < search->end) {
+ return search_escape_basic(search);
+ }
+
+ search_flush(search);
+ return 0;
+}
+
+#endif /* HAVE_SIMD_SSE2 */
+
+#endif /* HAVE_SIMD */
+
+static const unsigned char script_safe_escape_table[256] = {
+ // ASCII Control Characters
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ // ASCII Characters
+ 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, // '"' and '/'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, // '\\'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ // Continuation byte
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ // First byte of a 2-byte code point
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ // First byte of a 3-byte code point
+ 3, 3,11, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xE2 is the start of \u2028 and \u2029
+ //First byte of a 4+ byte code point
+ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 9, 9,
+};
+
+static inline unsigned char search_script_safe_escape(search_state *search)
+{
+ while (search->ptr < search->end) {
+ unsigned char ch = (unsigned char)*search->ptr;
+ unsigned char ch_len = script_safe_escape_table[ch];
+
+ if (RB_UNLIKELY(ch_len)) {
+ if (ch_len & ESCAPE_MASK) {
+ if (RB_UNLIKELY(ch_len == 11)) {
+ const unsigned char *uptr = (const unsigned char *)search->ptr;
+ if (!(uptr[1] == 0x80 && (uptr[2] >> 1) == 0x54)) {
+ search->ptr += 3;
+ continue;
+ }
+ }
+ search_flush(search);
+ return ch_len & CHAR_LENGTH_MASK;
+ } else {
+ search->ptr += ch_len;
+ }
+ } else {
+ search->ptr++;
+ }
+ }
+ search_flush(search);
+ return 0;
+}
+
+static void convert_UTF8_to_script_safe_JSON(search_state *search)
+{
+ unsigned char ch_len;
+ while ((ch_len = search_script_safe_escape(search))) {
+ escape_UTF8_char(search, ch_len);
+ }
+}
+
+static const unsigned char ascii_only_escape_table[256] = {
+ // ASCII Control Characters
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ // ASCII Characters
+ 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // '"'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, // '\\'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ // Continuation byte
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ // First byte of a 2-byte code point
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ // First byte of a 3-byte code point
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ //First byte of a 4+ byte code point
+ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 9, 9,
+};
+
+static inline unsigned char search_ascii_only_escape(search_state *search, const unsigned char escape_table[256])
+{
+ while (search->ptr < search->end) {
+ unsigned char ch = (unsigned char)*search->ptr;
+ unsigned char ch_len = escape_table[ch];
+
+ if (RB_UNLIKELY(ch_len)) {
+ search_flush(search);
+ return ch_len & CHAR_LENGTH_MASK;
+ } else {
+ search->ptr++;
+ }
+ }
+ search_flush(search);
+ return 0;
+}
+
+static inline void full_escape_UTF8_char(search_state *search, unsigned char ch_len)
+{
+ const unsigned char ch = (unsigned char)*search->ptr;
+ switch (ch_len) {
+ case 1: {
+ switch (ch) {
+ case '"': fbuffer_append(search->buffer, "\\\"", 2); break;
+ case '\\': fbuffer_append(search->buffer, "\\\\", 2); break;
+ case '/': fbuffer_append(search->buffer, "\\/", 2); break;
+ case '\b': fbuffer_append(search->buffer, "\\b", 2); break;
+ case '\f': fbuffer_append(search->buffer, "\\f", 2); break;
+ case '\n': fbuffer_append(search->buffer, "\\n", 2); break;
+ case '\r': fbuffer_append(search->buffer, "\\r", 2); break;
+ case '\t': fbuffer_append(search->buffer, "\\t", 2); break;
+ default: {
+ const char *hexdig = "0123456789abcdef";
+ char scratch[6] = { '\\', 'u', '0', '0', 0, 0 };
+ scratch[4] = hexdig[(ch >> 4) & 0xf];
+ scratch[5] = hexdig[ch & 0xf];
+ fbuffer_append(search->buffer, scratch, 6);
+ break;
+ }
+ }
+ break;
+ }
+ default: {
+ const char *hexdig = "0123456789abcdef";
+ char scratch[12] = { '\\', 'u', 0, 0, 0, 0, '\\', 'u' };
+
+ uint32_t wchar = 0;
+
+ switch (ch_len) {
+ case 2:
+ wchar = ch & 0x1F;
+ break;
+ case 3:
+ wchar = ch & 0x0F;
+ break;
+ case 4:
+ wchar = ch & 0x07;
+ break;
+ }
+
+ for (short i = 1; i < ch_len; i++) {
+ wchar = (wchar << 6) | (search->ptr[i] & 0x3F);
+ }
+
+ if (wchar <= 0xFFFF) {
+ scratch[2] = hexdig[wchar >> 12];
+ scratch[3] = hexdig[(wchar >> 8) & 0xf];
+ scratch[4] = hexdig[(wchar >> 4) & 0xf];
+ scratch[5] = hexdig[wchar & 0xf];
+ fbuffer_append(search->buffer, scratch, 6);
+ } else {
+ uint16_t hi, lo;
+ wchar -= 0x10000;
+ hi = 0xD800 + (uint16_t)(wchar >> 10);
+ lo = 0xDC00 + (uint16_t)(wchar & 0x3FF);
+
+ scratch[2] = hexdig[hi >> 12];
+ scratch[3] = hexdig[(hi >> 8) & 0xf];
+ scratch[4] = hexdig[(hi >> 4) & 0xf];
+ scratch[5] = hexdig[hi & 0xf];
+
+ scratch[8] = hexdig[lo >> 12];
+ scratch[9] = hexdig[(lo >> 8) & 0xf];
+ scratch[10] = hexdig[(lo >> 4) & 0xf];
+ scratch[11] = hexdig[lo & 0xf];
+
+ fbuffer_append(search->buffer, scratch, 12);
+ }
+
+ break;
+ }
+ }
+ search->cursor = (search->ptr += ch_len);
+}
+
+static void convert_UTF8_to_ASCII_only_JSON(search_state *search, const unsigned char escape_table[256])
+{
+ unsigned char ch_len;
+ while ((ch_len = search_ascii_only_escape(search, escape_table))) {
+ full_escape_UTF8_char(search, ch_len);
+ }
+}
+
+static void State_mark(void *ptr)
+{
+ JSON_Generator_State *state = ptr;
+ rb_gc_mark_movable(state->indent);
+ rb_gc_mark_movable(state->space);
+ rb_gc_mark_movable(state->space_before);
+ rb_gc_mark_movable(state->object_nl);
+ rb_gc_mark_movable(state->array_nl);
+ rb_gc_mark_movable(state->as_json);
+}
+
+static void State_compact(void *ptr)
+{
+ JSON_Generator_State *state = ptr;
+ state->indent = rb_gc_location(state->indent);
+ state->space = rb_gc_location(state->space);
+ state->space_before = rb_gc_location(state->space_before);
+ state->object_nl = rb_gc_location(state->object_nl);
+ state->array_nl = rb_gc_location(state->array_nl);
+ state->as_json = rb_gc_location(state->as_json);
+}
+
+static size_t State_memsize(const void *ptr)
+{
+ return sizeof(JSON_Generator_State);
+}
+
+static const rb_data_type_t JSON_Generator_State_type = {
+ .wrap_struct_name = "JSON/Generator/State",
+ .function = {
+ .dmark = State_mark,
+ .dfree = RUBY_DEFAULT_FREE,
+ .dsize = State_memsize,
+ .dcompact = State_compact,
+ },
+ .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_EMBEDDABLE,
+};
+
+static void state_init(JSON_Generator_State *state)
+{
+ state->max_nesting = 100;
+ state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
+}
+
+static VALUE cState_s_allocate(VALUE klass)
+{
+ JSON_Generator_State *state;
+ VALUE obj = TypedData_Make_Struct(klass, JSON_Generator_State, &JSON_Generator_State_type, state);
+ state_init(state);
+ return obj;
+}
+
+static void vstate_spill(struct generate_json_data *data)
+{
+ VALUE vstate = cState_s_allocate(cState);
+ GET_STATE(vstate);
+ MEMCPY(state, data->state, JSON_Generator_State, 1);
+ data->state = state;
+ data->vstate = vstate;
+ RB_OBJ_WRITTEN(vstate, Qundef, state->indent);
+ RB_OBJ_WRITTEN(vstate, Qundef, state->space);
+ RB_OBJ_WRITTEN(vstate, Qundef, state->space_before);
+ RB_OBJ_WRITTEN(vstate, Qundef, state->object_nl);
+ RB_OBJ_WRITTEN(vstate, Qundef, state->array_nl);
+ RB_OBJ_WRITTEN(vstate, Qundef, state->as_json);
+}
+
+static inline VALUE json_call_to_json(struct generate_json_data *data, VALUE obj)
+{
+ if (RB_UNLIKELY(!data->vstate)) {
+ vstate_spill(data);
+ }
+ GET_STATE(data->vstate);
+ state->depth = data->depth;
+ VALUE tmp = rb_funcall(obj, i_to_json, 1, data->vstate);
+ // no need to restore state->depth, vstate is just a temporary State
+ return tmp;
+}
+
+static VALUE
+json_call_as_json(JSON_Generator_State *state, VALUE object, VALUE is_key)
+{
+ VALUE proc_args[2] = {object, is_key};
+ return rb_proc_call_with_block(state->as_json, 2, proc_args, Qnil);
+}
+
+static VALUE
+convert_string_subclass(VALUE key)
+{
+ VALUE key_to_s = rb_funcall(key, i_to_s, 0);
+
+ if (RB_UNLIKELY(!RB_TYPE_P(key_to_s, T_STRING))) {
+ VALUE cname = rb_obj_class(key);
+ rb_raise(rb_eTypeError,
+ "can't convert %"PRIsVALUE" to %s (%"PRIsVALUE"#%s gives %"PRIsVALUE")",
+ cname, "String", cname, "to_s", rb_obj_class(key_to_s));
+ }
+
+ return key_to_s;
+}
+
+static bool enc_utf8_compatible_p(int enc_idx)
+{
+ if (enc_idx == usascii_encindex) return true;
+ if (enc_idx == utf8_encindex) return true;
+ return false;
+}
+
+static VALUE encode_json_string_try(VALUE str)
+{
+ return rb_funcall(str, i_encode, 1, Encoding_UTF_8);
+}
+
+static VALUE encode_json_string_rescue(VALUE str, VALUE exception)
+{
+ raise_generator_error_str(str, rb_funcall(exception, rb_intern("message"), 0));
+ return Qundef;
+}
+
+static inline int json_str_coderange(VALUE str) {
+ int coderange = RB_ENC_CODERANGE(str);
+ if (coderange == RUBY_ENC_CODERANGE_UNKNOWN) {
+ coderange = rb_enc_str_coderange(str);
+ }
+ return coderange;
+}
+
+static inline bool valid_json_string_p(VALUE str)
+{
+ int coderange = json_str_coderange(str);
+
+ if (RB_LIKELY(coderange == ENC_CODERANGE_7BIT)) {
+ return true;
+ }
+
+ if (RB_LIKELY(coderange == ENC_CODERANGE_VALID)) {
+ return enc_utf8_compatible_p(RB_ENCODING_GET_INLINED(str));
+ }
+
+ return false;
+}
+
+NOINLINE(static) VALUE convert_invalid_encoding(struct generate_json_data *data, VALUE str, bool as_json_called, bool is_key)
+{
+ if (!as_json_called && data->state->strict && RTEST(data->state->as_json)) {
+ VALUE coerced_str = json_call_as_json(data->state, str, Qfalse);
+ if (coerced_str != str) {
+ if (RB_TYPE_P(coerced_str, T_STRING)) {
+ if (!valid_json_string_p(coerced_str)) {
+ raise_generator_error(str, "source sequence is illegal/malformed utf-8");
+ }
+ } else {
+ // as_json could return another type than T_STRING
+ if (is_key) {
+ raise_generator_error(coerced_str, "%"PRIsVALUE" not allowed as object key in JSON", CLASS_OF(coerced_str));
+ }
+ }
+
+ return coerced_str;
+ }
+ }
+
+ if (RB_ENCODING_GET_INLINED(str) == binary_encindex) {
+ VALUE utf8_string = rb_enc_associate_index(rb_str_dup(str), utf8_encindex);
+ switch (rb_enc_str_coderange(utf8_string)) {
+ case ENC_CODERANGE_7BIT:
+ return utf8_string;
+ case ENC_CODERANGE_VALID:
+ // For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
+ // TODO: Raise in 3.0.0
+ rb_warn("JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0");
+ return utf8_string;
+ break;
+ }
+ }
+
+ return rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str);
+}
+
+ALWAYS_INLINE(static) VALUE ensure_valid_encoding(struct generate_json_data *data, VALUE str, bool as_json_called, bool is_key)
+{
+ if (RB_LIKELY(valid_json_string_p(str))) {
+ return str;
+ }
+ else {
+ return convert_invalid_encoding(data, str, as_json_called, is_key);
+ }
+}
+
+static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ fbuffer_append_char(buffer, '"');
+
+ long len;
+ search_state search;
+ search.buffer = buffer;
+ RSTRING_GETMEM(obj, search.ptr, len);
+ search.cursor = search.ptr;
+ search.end = search.ptr + len;
+
+#ifdef HAVE_SIMD
+ search.matches_mask = 0;
+ search.has_matches = false;
+ search.chunk_base = NULL;
+ search.chunk_end = NULL;
+#endif /* HAVE_SIMD */
+
+ switch (json_str_coderange(obj)) {
+ case ENC_CODERANGE_7BIT:
+ case ENC_CODERANGE_VALID:
+ if (RB_UNLIKELY(data->state->ascii_only)) {
+ convert_UTF8_to_ASCII_only_JSON(&search, data->state->script_safe ? script_safe_escape_table : ascii_only_escape_table);
+ } else if (RB_UNLIKELY(data->state->script_safe)) {
+ convert_UTF8_to_script_safe_JSON(&search);
+ } else {
+ convert_UTF8_to_JSON(&search);
+ }
+ break;
+ default:
+ raise_generator_error(obj, "source sequence is illegal/malformed utf-8");
+ break;
+ }
+ fbuffer_append_char(buffer, '"');
+}
+
+static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ obj = ensure_valid_encoding(data, obj, false, false);
+ raw_generate_json_string(buffer, data, obj);
+}
+
+struct hash_foreach_arg {
+ VALUE hash;
+ struct generate_json_data *data;
+ int first_key_type;
+ bool first;
+ bool mixed_keys_encountered;
+};
+
+NOINLINE(static) void
+json_inspect_hash_with_mixed_keys(struct hash_foreach_arg *arg)
+{
+ if (arg->mixed_keys_encountered) {
+ return;
+ }
+ arg->mixed_keys_encountered = true;
+
+ JSON_Generator_State *state = arg->data->state;
+ if (state->on_duplicate_key != JSON_IGNORE) {
+ VALUE do_raise = state->on_duplicate_key == JSON_RAISE ? Qtrue : Qfalse;
+ rb_funcall(mJSON, rb_intern("on_mixed_keys_hash"), 2, arg->hash, do_raise);
+ }
+}
+
+static int
+json_object_i(VALUE key, VALUE val, VALUE _arg)
+{
+ struct hash_foreach_arg *arg = (struct hash_foreach_arg *)_arg;
+ struct generate_json_data *data = arg->data;
+
+ FBuffer *buffer = data->buffer;
+ JSON_Generator_State *state = data->state;
+
+ long depth = data->depth;
+ int key_type = rb_type(key);
+
+ if (arg->first) {
+ arg->first = false;
+ arg->first_key_type = key_type;
+ }
+ else {
+ fbuffer_append_char(buffer, ',');
+ }
+
+ if (RB_UNLIKELY(data->state->object_nl)) {
+ fbuffer_append_str(buffer, data->state->object_nl);
+ }
+ if (RB_UNLIKELY(data->state->indent)) {
+ fbuffer_append_str_repeat(buffer, data->state->indent, depth);
+ }
+
+ VALUE key_to_s;
+ bool as_json_called = false;
+
+ start:
+ switch (key_type) {
+ case T_STRING:
+ if (RB_UNLIKELY(arg->first_key_type != T_STRING)) {
+ json_inspect_hash_with_mixed_keys(arg);
+ }
+
+ if (RB_LIKELY(RBASIC_CLASS(key) == rb_cString)) {
+ key_to_s = key;
+ } else {
+ key_to_s = convert_string_subclass(key);
+ }
+ break;
+ case T_SYMBOL:
+ if (RB_UNLIKELY(arg->first_key_type != T_SYMBOL)) {
+ json_inspect_hash_with_mixed_keys(arg);
+ }
+
+ key_to_s = rb_sym2str(key);
+ break;
+ default:
+ if (data->state->strict) {
+ if (RTEST(data->state->as_json) && !as_json_called) {
+ key = json_call_as_json(data->state, key, Qtrue);
+ key_type = rb_type(key);
+ as_json_called = true;
+ goto start;
+ } else {
+ raise_generator_error(key, "%"PRIsVALUE" not allowed as object key in JSON", CLASS_OF(key));
+ }
+ }
+ key_to_s = rb_convert_type(key, T_STRING, "String", "to_s");
+ break;
+ }
+
+ key_to_s = ensure_valid_encoding(data, key_to_s, as_json_called, true);
+
+ if (RB_LIKELY(RBASIC_CLASS(key_to_s) == rb_cString)) {
+ raw_generate_json_string(buffer, data, key_to_s);
+ } else {
+ generate_json(buffer, data, key_to_s);
+ }
+ if (RB_UNLIKELY(state->space_before)) fbuffer_append_str(buffer, data->state->space_before);
+ fbuffer_append_char(buffer, ':');
+ if (RB_UNLIKELY(state->space)) fbuffer_append_str(buffer, data->state->space);
+ generate_json(buffer, data, val);
+
+ return ST_CONTINUE;
+}
+
+static inline long increase_depth(struct generate_json_data *data)
+{
+ JSON_Generator_State *state = data->state;
+ long depth = ++data->depth;
+ if (RB_UNLIKELY(depth > state->max_nesting && state->max_nesting)) {
+ rb_raise(eNestingError, "nesting of %ld is too deep. Did you try to serialize objects with circular references?", --data->depth);
+ }
+ return depth;
+}
+
+static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ long depth = increase_depth(data);
+
+ if (RHASH_SIZE(obj) == 0) {
+ fbuffer_append(buffer, "{}", 2);
+ --data->depth;
+ return;
+ }
+
+ fbuffer_append_char(buffer, '{');
+
+ struct hash_foreach_arg arg = {
+ .hash = obj,
+ .data = data,
+ .first = true,
+ };
+ rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
+
+ depth = --data->depth;
+ if (RB_UNLIKELY(data->state->object_nl)) {
+ fbuffer_append_str(buffer, data->state->object_nl);
+ if (RB_UNLIKELY(data->state->indent)) {
+ fbuffer_append_str_repeat(buffer, data->state->indent, depth);
+ }
+ }
+ fbuffer_append_char(buffer, '}');
+}
+
+static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ long depth = increase_depth(data);
+
+ if (RARRAY_LEN(obj) == 0) {
+ fbuffer_append(buffer, "[]", 2);
+ --data->depth;
+ return;
+ }
+
+ fbuffer_append_char(buffer, '[');
+ if (RB_UNLIKELY(data->state->array_nl)) fbuffer_append_str(buffer, data->state->array_nl);
+ for (int i = 0; i < RARRAY_LEN(obj); i++) {
+ if (i > 0) {
+ fbuffer_append_char(buffer, ',');
+ if (RB_UNLIKELY(data->state->array_nl)) fbuffer_append_str(buffer, data->state->array_nl);
+ }
+ if (RB_UNLIKELY(data->state->indent)) {
+ fbuffer_append_str_repeat(buffer, data->state->indent, depth);
+ }
+ generate_json(buffer, data, RARRAY_AREF(obj, i));
+ }
+ data->depth = --depth;
+ if (RB_UNLIKELY(data->state->array_nl)) {
+ fbuffer_append_str(buffer, data->state->array_nl);
+ if (RB_UNLIKELY(data->state->indent)) {
+ fbuffer_append_str_repeat(buffer, data->state->indent, depth);
+ }
+ }
+ fbuffer_append_char(buffer, ']');
+}
+
+static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ VALUE tmp;
+ if (rb_respond_to(obj, i_to_json)) {
+ tmp = json_call_to_json(data, obj);
+ Check_Type(tmp, T_STRING);
+ fbuffer_append_str(buffer, tmp);
+ } else {
+ tmp = rb_funcall(obj, i_to_s, 0);
+ Check_Type(tmp, T_STRING);
+ generate_json_string(buffer, data, tmp);
+ }
+}
+
+static inline void generate_json_symbol(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ if (data->state->strict) {
+ generate_json_string(buffer, data, rb_sym2str(obj));
+ } else {
+ generate_json_fallback(buffer, data, obj);
+ }
+}
+
+static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ fbuffer_append(buffer, "null", 4);
+}
+
+static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ fbuffer_append(buffer, "false", 5);
+}
+
+static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ fbuffer_append(buffer, "true", 4);
+}
+
+static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ fbuffer_append_long(buffer, FIX2LONG(obj));
+}
+
+static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ VALUE tmp = rb_funcall(obj, i_to_s, 0);
+ fbuffer_append_str(buffer, StringValue(tmp));
+}
+
+static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ double value = RFLOAT_VALUE(obj);
+ char allow_nan = data->state->allow_nan;
+ if (isinf(value) || isnan(value)) {
+ /* for NaN and Infinity values we either raise an error or rely on Float#to_s. */
+ if (!allow_nan) {
+ if (data->state->strict && data->state->as_json) {
+ VALUE casted_obj = json_call_as_json(data->state, obj, Qfalse);
+ if (casted_obj != obj) {
+ increase_depth(data);
+ generate_json(buffer, data, casted_obj);
+ data->depth--;
+ return;
+ }
+ }
+ raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON", rb_funcall(obj, i_to_s, 0));
+ }
+
+ VALUE tmp = rb_funcall(obj, i_to_s, 0);
+ fbuffer_append_str(buffer, tmp);
+ return;
+ }
+
+ /* This implementation writes directly into the buffer. We reserve
+ * the 32 characters that fpconv_dtoa states as its maximum.
+ */
+ fbuffer_inc_capa(buffer, 32);
+ char* d = buffer->ptr + buffer->len;
+ int len = fpconv_dtoa(value, d);
+ /* fpconv_dtoa converts a float to its shortest string representation,
+ * but it adds a ".0" if this is a plain integer.
+ */
+ fbuffer_consumed(buffer, len);
+}
+
+static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ VALUE fragment = RSTRUCT_GET(obj, 0);
+ Check_Type(fragment, T_STRING);
+ fbuffer_append_str(buffer, fragment);
+}
+
+static inline void generate_json_general(FBuffer *buffer, struct generate_json_data *data, VALUE obj, bool fallback)
+{
+ bool as_json_called = false;
+start:
+ if (obj == Qnil) {
+ generate_json_null(buffer, data, obj);
+ } else if (obj == Qfalse) {
+ generate_json_false(buffer, data, obj);
+ } else if (obj == Qtrue) {
+ generate_json_true(buffer, data, obj);
+ } else if (RB_SPECIAL_CONST_P(obj)) {
+ if (RB_FIXNUM_P(obj)) {
+ generate_json_fixnum(buffer, data, obj);
+ } else if (RB_FLONUM_P(obj)) {
+ generate_json_float(buffer, data, obj);
+ } else if (RB_STATIC_SYM_P(obj)) {
+ generate_json_symbol(buffer, data, obj);
+ } else {
+ goto general;
+ }
+ } else {
+ VALUE klass = RBASIC_CLASS(obj);
+ switch (RB_BUILTIN_TYPE(obj)) {
+ case T_BIGNUM:
+ generate_json_bignum(buffer, data, obj);
+ break;
+ case T_HASH:
+ if (fallback && klass != rb_cHash) goto general;
+ generate_json_object(buffer, data, obj);
+ break;
+ case T_ARRAY:
+ if (fallback && klass != rb_cArray) goto general;
+ generate_json_array(buffer, data, obj);
+ break;
+ case T_STRING:
+ if (fallback && klass != rb_cString) goto general;
+
+ if (RB_LIKELY(valid_json_string_p(obj))) {
+ raw_generate_json_string(buffer, data, obj);
+ } else if (as_json_called) {
+ raise_generator_error(obj, "source sequence is illegal/malformed utf-8");
+ } else {
+ obj = ensure_valid_encoding(data, obj, false, false);
+ as_json_called = true;
+ goto start;
+ }
+ break;
+ case T_SYMBOL:
+ generate_json_symbol(buffer, data, obj);
+ break;
+ case T_FLOAT:
+ if (fallback && klass != rb_cFloat) goto general;
+ generate_json_float(buffer, data, obj);
+ break;
+ case T_STRUCT:
+ if (klass != cFragment) goto general;
+ generate_json_fragment(buffer, data, obj);
+ break;
+ default:
+ general:
+ if (data->state->strict) {
+ if (RTEST(data->state->as_json) && !as_json_called) {
+ obj = json_call_as_json(data->state, obj, Qfalse);
+ as_json_called = true;
+ goto start;
+ } else {
+ raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON", CLASS_OF(obj));
+ }
+ } else {
+ generate_json_fallback(buffer, data, obj);
+ }
+ }
+ }
+}
+
+static void generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ generate_json_general(buffer, data, obj, true);
+}
+
+static void generate_json_no_fallback(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ generate_json_general(buffer, data, obj, false);
+}
+
+static VALUE generate_json_try(VALUE d)
+{
+ struct generate_json_data *data = (struct generate_json_data *)d;
+
+ data->func(data->buffer, data, data->obj);
+
+ return fbuffer_finalize(data->buffer);
+}
+
+static VALUE generate_json_ensure(VALUE d)
+{
+ struct generate_json_data *data = (struct generate_json_data *)d;
+ fbuffer_free(data->buffer);
+
+ return Qundef;
+}
+
+static inline VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func, VALUE io)
+{
+ GET_STATE(self);
+
+ char stack_buffer[FBUFFER_STACK_SIZE];
+ FBuffer buffer = {
+ .io = RTEST(io) ? io : Qfalse,
+ };
+ fbuffer_stack_init(&buffer, state->buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
+
+ struct generate_json_data data = {
+ .buffer = &buffer,
+ .vstate = Qfalse, // don't use self as it may be frozen and its depth is mutated when calling to_json
+ .state = state,
+ .depth = state->depth,
+ .obj = obj,
+ .func = func
+ };
+ return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
+}
+
+/* call-seq:
+ * generate(obj) -> String
+ * generate(obj, anIO) -> anIO
+ *
+ * Generates a valid JSON document from object +obj+ and returns the
+ * result. If no valid JSON document can be created this method raises a
+ * GeneratorError exception.
+ */
+static VALUE cState_generate(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 1, 2);
+ VALUE obj = argv[0];
+ VALUE io = argc > 1 ? argv[1] : Qnil;
+ return cState_partial_generate(self, obj, generate_json, io);
+}
+
+/* :nodoc: */
+static VALUE cState_generate_no_fallback(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 1, 2);
+ VALUE obj = argv[0];
+ VALUE io = argc > 1 ? argv[1] : Qnil;
+ return cState_partial_generate(self, obj, generate_json_no_fallback, io);
+}
+
+static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
+{
+ rb_warn("The json gem extension was loaded with the stdlib ruby code. You should upgrade rubygems with `gem update --system`");
+ return self;
+}
+
+/*
+ * call-seq: initialize_copy(orig)
+ *
+ * Initializes this object from orig if it can be duplicated/cloned and returns
+ * it.
+*/
+static VALUE cState_init_copy(VALUE obj, VALUE orig)
+{
+ JSON_Generator_State *objState, *origState;
+
+ if (obj == orig) return obj;
+ GET_STATE_TO(obj, objState);
+ GET_STATE_TO(orig, origState);
+ if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
+
+ MEMCPY(objState, origState, JSON_Generator_State, 1);
+
+ RB_OBJ_WRITTEN(obj, Qundef, objState->indent);
+ RB_OBJ_WRITTEN(obj, Qundef, objState->space);
+ RB_OBJ_WRITTEN(obj, Qundef, objState->space_before);
+ RB_OBJ_WRITTEN(obj, Qundef, objState->object_nl);
+ RB_OBJ_WRITTEN(obj, Qundef, objState->array_nl);
+ RB_OBJ_WRITTEN(obj, Qundef, objState->as_json);
+
+ return obj;
+}
+
+/*
+ * call-seq: from_state(opts)
+ *
+ * Creates a State object from _opts_, which ought to be Hash to create a
+ * new State instance configured by _opts_, something else to create an
+ * unconfigured instance. If _opts_ is a State object, it is just returned.
+ */
+static VALUE cState_from_state_s(VALUE self, VALUE opts)
+{
+ if (rb_obj_is_kind_of(opts, self)) {
+ return opts;
+ } else if (rb_obj_is_kind_of(opts, rb_cHash)) {
+ return rb_funcall(self, i_new, 1, opts);
+ } else {
+ return rb_class_new_instance(0, NULL, cState);
+ }
+}
+
+/*
+ * call-seq: indent()
+ *
+ * Returns the string that is used to indent levels in the JSON text.
+ */
+static VALUE cState_indent(VALUE self)
+{
+ GET_STATE(self);
+ return state->indent ? state->indent : rb_str_freeze(rb_utf8_str_new("", 0));
+}
+
+static VALUE string_config(VALUE config)
+{
+ if (RTEST(config)) {
+ Check_Type(config, T_STRING);
+ if (RSTRING_LEN(config)) {
+ return rb_str_new_frozen(config);
+ }
+ }
+ return Qfalse;
+}
+
+/*
+ * call-seq: indent=(indent)
+ *
+ * Sets the string that is used to indent levels in the JSON text.
+ */
+static VALUE cState_indent_set(VALUE self, VALUE indent)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ RB_OBJ_WRITE(self, &state->indent, string_config(indent));
+ return Qnil;
+}
+
+/*
+ * call-seq: space()
+ *
+ * Returns the string that is used to insert a space between the tokens in a JSON
+ * string.
+ */
+static VALUE cState_space(VALUE self)
+{
+ GET_STATE(self);
+ return state->space ? state->space : rb_str_freeze(rb_utf8_str_new("", 0));
+}
+
+/*
+ * call-seq: space=(space)
+ *
+ * Sets _space_ to the string that is used to insert a space between the tokens in a JSON
+ * string.
+ */
+static VALUE cState_space_set(VALUE self, VALUE space)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ RB_OBJ_WRITE(self, &state->space, string_config(space));
+ return Qnil;
+}
+
+/*
+ * call-seq: space_before()
+ *
+ * Returns the string that is used to insert a space before the ':' in JSON objects.
+ */
+static VALUE cState_space_before(VALUE self)
+{
+ GET_STATE(self);
+ return state->space_before ? state->space_before : rb_str_freeze(rb_utf8_str_new("", 0));
+}
+
+/*
+ * call-seq: space_before=(space_before)
+ *
+ * Sets the string that is used to insert a space before the ':' in JSON objects.
+ */
+static VALUE cState_space_before_set(VALUE self, VALUE space_before)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ RB_OBJ_WRITE(self, &state->space_before, string_config(space_before));
+ return Qnil;
+}
+
+/*
+ * call-seq: object_nl()
+ *
+ * This string is put at the end of a line that holds a JSON object (or
+ * Hash).
+ */
+static VALUE cState_object_nl(VALUE self)
+{
+ GET_STATE(self);
+ return state->object_nl ? state->object_nl : rb_str_freeze(rb_utf8_str_new("", 0));
+}
+
+/*
+ * call-seq: object_nl=(object_nl)
+ *
+ * This string is put at the end of a line that holds a JSON object (or
+ * Hash).
+ */
+static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ RB_OBJ_WRITE(self, &state->object_nl, string_config(object_nl));
+ return Qnil;
+}
+
+/*
+ * call-seq: array_nl()
+ *
+ * This string is put at the end of a line that holds a JSON array.
+ */
+static VALUE cState_array_nl(VALUE self)
+{
+ GET_STATE(self);
+ return state->array_nl ? state->array_nl : rb_str_freeze(rb_utf8_str_new("", 0));
+}
+
+/*
+ * call-seq: array_nl=(array_nl)
+ *
+ * This string is put at the end of a line that holds a JSON array.
+ */
+static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ RB_OBJ_WRITE(self, &state->array_nl, string_config(array_nl));
+ return Qnil;
+}
+
+/*
+ * call-seq: as_json()
+ *
+ * This string is put at the end of a line that holds a JSON array.
+ */
+static VALUE cState_as_json(VALUE self)
+{
+ GET_STATE(self);
+ return state->as_json;
+}
+
+/*
+ * call-seq: as_json=(as_json)
+ *
+ * This string is put at the end of a line that holds a JSON array.
+ */
+static VALUE cState_as_json_set(VALUE self, VALUE as_json)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ RB_OBJ_WRITE(self, &state->as_json, rb_convert_type(as_json, T_DATA, "Proc", "to_proc"));
+ return Qnil;
+}
+
+/*
+* call-seq: check_circular?
+*
+* Returns true, if circular data structures should be checked,
+* otherwise returns false.
+*/
+static VALUE cState_check_circular_p(VALUE self)
+{
+ GET_STATE(self);
+ return state->max_nesting ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq: max_nesting
+ *
+ * This integer returns the maximum level of data structure nesting in
+ * the generated JSON, max_nesting = 0 if no maximum is checked.
+ */
+static VALUE cState_max_nesting(VALUE self)
+{
+ GET_STATE(self);
+ return LONG2FIX(state->max_nesting);
+}
+
+static long long_config(VALUE num)
+{
+ return RTEST(num) ? NUM2LONG(num) : 0;
+}
+
+// depth must never be negative; reject early with a clear error.
+static long depth_config(VALUE num)
+{
+ if (!RTEST(num)) return 0;
+ long d = NUM2LONG(num);
+ if (RB_UNLIKELY(d < 0)) {
+ rb_raise(rb_eArgError, "depth must be >= 0 (got %ld)", d);
+ }
+ if (RB_UNLIKELY(d > INT_MAX)) {
+ rb_raise(rb_eArgError, "depth is too large (got %ld)", d);
+ }
+ return d;
+}
+
+/*
+ * call-seq: max_nesting=(depth)
+ *
+ * This sets the maximum level of data structure nesting in the generated JSON
+ * to the integer depth, max_nesting = 0 if no maximum should be checked.
+ */
+static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ state->max_nesting = long_config(depth);
+ return Qnil;
+}
+
+/*
+ * call-seq: script_safe
+ *
+ * If this boolean is true, the forward slashes will be escaped in
+ * the json output.
+ */
+static VALUE cState_script_safe(VALUE self)
+{
+ GET_STATE(self);
+ return state->script_safe ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq: script_safe=(enable)
+ *
+ * This sets whether or not the forward slashes will be escaped in
+ * the json output.
+ */
+static VALUE cState_script_safe_set(VALUE self, VALUE enable)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ state->script_safe = RTEST(enable);
+ return Qnil;
+}
+
+/*
+ * call-seq: strict
+ *
+ * If this boolean is false, types unsupported by the JSON format will
+ * be serialized as strings.
+ * If this boolean is true, types unsupported by the JSON format will
+ * raise a JSON::GeneratorError.
+ */
+static VALUE cState_strict(VALUE self)
+{
+ GET_STATE(self);
+ return state->strict ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq: strict=(enable)
+ *
+ * This sets whether or not to serialize types unsupported by the
+ * JSON format as strings.
+ * If this boolean is false, types unsupported by the JSON format will
+ * be serialized as strings.
+ * If this boolean is true, types unsupported by the JSON format will
+ * raise a JSON::GeneratorError.
+ */
+static VALUE cState_strict_set(VALUE self, VALUE enable)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ state->strict = RTEST(enable);
+ return Qnil;
+}
+
+/*
+ * call-seq: allow_nan?
+ *
+ * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
+ * returns false.
+ */
+static VALUE cState_allow_nan_p(VALUE self)
+{
+ GET_STATE(self);
+ return state->allow_nan ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq: allow_nan=(enable)
+ *
+ * This sets whether or not to serialize NaN, Infinity, and -Infinity
+ */
+static VALUE cState_allow_nan_set(VALUE self, VALUE enable)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ state->allow_nan = RTEST(enable);
+ return Qnil;
+}
+
+/*
+ * call-seq: ascii_only?
+ *
+ * Returns true, if only ASCII characters should be generated. Otherwise
+ * returns false.
+ */
+static VALUE cState_ascii_only_p(VALUE self)
+{
+ GET_STATE(self);
+ return state->ascii_only ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq: ascii_only=(enable)
+ *
+ * This sets whether only ASCII characters should be generated.
+ */
+static VALUE cState_ascii_only_set(VALUE self, VALUE enable)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ state->ascii_only = RTEST(enable);
+ return Qnil;
+}
+
+static VALUE cState_allow_duplicate_key_p(VALUE self)
+{
+ GET_STATE(self);
+ switch (state->on_duplicate_key) {
+ case JSON_IGNORE:
+ return Qtrue;
+ case JSON_DEPRECATED:
+ return Qnil;
+ default:
+ return Qfalse;
+ }
+}
+
+/*
+ * call-seq: depth
+ *
+ * This integer returns the current depth of data structure nesting.
+ */
+static VALUE cState_depth(VALUE self)
+{
+ GET_STATE(self);
+ return LONG2FIX(state->depth);
+}
+
+/*
+ * call-seq: depth=(depth)
+ *
+ * This sets the maximum level of data structure nesting in the generated JSON
+ * to the integer depth, max_nesting = 0 if no maximum should be checked.
+ */
+static VALUE cState_depth_set(VALUE self, VALUE depth)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ state->depth = depth_config(depth);
+ return Qnil;
+}
+
+/*
+ * call-seq: buffer_initial_length
+ *
+ * This integer returns the current initial length of the buffer.
+ */
+static VALUE cState_buffer_initial_length(VALUE self)
+{
+ GET_STATE(self);
+ return LONG2FIX(state->buffer_initial_length);
+}
+
+static void buffer_initial_length_set(JSON_Generator_State *state, VALUE buffer_initial_length)
+{
+ Check_Type(buffer_initial_length, T_FIXNUM);
+ long initial_length = FIX2LONG(buffer_initial_length);
+ if (initial_length > 0) {
+ state->buffer_initial_length = initial_length;
+ }
+}
+
+/*
+ * call-seq: buffer_initial_length=(length)
+ *
+ * This sets the initial length of the buffer to +length+, if +length+ > 0,
+ * otherwise its value isn't changed.
+ */
+static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_length)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ buffer_initial_length_set(state, buffer_initial_length);
+ return Qnil;
+}
+
+struct configure_state_data {
+ JSON_Generator_State *state;
+ VALUE vstate; // Ruby object that owns the state, or Qfalse if stack-allocated
+};
+
+static inline void state_write_value(struct configure_state_data *data, VALUE *field, VALUE value)
+{
+ if (RTEST(data->vstate)) {
+ RB_OBJ_WRITE(data->vstate, field, value);
+ } else {
+ *field = value;
+ }
+}
+
+static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
+{
+ struct configure_state_data *data = (struct configure_state_data *)_arg;
+ JSON_Generator_State *state = data->state;
+
+ if (key == sym_indent) { state_write_value(data, &state->indent, string_config(val)); }
+ else if (key == sym_space) { state_write_value(data, &state->space, string_config(val)); }
+ else if (key == sym_space_before) { state_write_value(data, &state->space_before, string_config(val)); }
+ else if (key == sym_object_nl) { state_write_value(data, &state->object_nl, string_config(val)); }
+ else if (key == sym_array_nl) { state_write_value(data, &state->array_nl, string_config(val)); }
+ else if (key == sym_max_nesting) { state->max_nesting = long_config(val); }
+ else if (key == sym_allow_nan) { state->allow_nan = RTEST(val); }
+ else if (key == sym_ascii_only) { state->ascii_only = RTEST(val); }
+ else if (key == sym_depth) { state->depth = depth_config(val); }
+ else if (key == sym_buffer_initial_length) { buffer_initial_length_set(state, val); }
+ else if (key == sym_script_safe) { state->script_safe = RTEST(val); }
+ else if (key == sym_escape_slash) { state->script_safe = RTEST(val); }
+ else if (key == sym_strict) { state->strict = RTEST(val); }
+ else if (key == sym_allow_duplicate_key) { state->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; }
+ else if (key == sym_as_json) {
+ VALUE proc = RTEST(val) ? rb_convert_type(val, T_DATA, "Proc", "to_proc") : Qfalse;
+ state->as_json_single_arg = proc && rb_proc_arity(proc) == 1;
+ state_write_value(data, &state->as_json, proc);
+ }
+ return ST_CONTINUE;
+}
+
+static void configure_state(JSON_Generator_State *state, VALUE vstate, VALUE config)
+{
+ if (!RTEST(config)) return;
+
+ Check_Type(config, T_HASH);
+
+ if (!RHASH_SIZE(config)) return;
+
+ struct configure_state_data data = {
+ .state = state,
+ .vstate = vstate
+ };
+
+ // We assume in most cases few keys are set so it's faster to go over
+ // the provided keys than to check all possible keys.
+ rb_hash_foreach(config, configure_state_i, (VALUE)&data);
+}
+
+static VALUE cState_configure(VALUE self, VALUE opts)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ configure_state(state, self, opts);
+ return self;
+}
+
+static VALUE cState_m_do_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io, generator_func func)
+{
+ JSON_Generator_State state = {0};
+ state_init(&state);
+ configure_state(&state, Qfalse, opts);
+
+ char stack_buffer[FBUFFER_STACK_SIZE];
+ FBuffer buffer = {
+ .io = RTEST(io) ? io : Qfalse,
+ };
+ fbuffer_stack_init(&buffer, state.buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
+
+ struct generate_json_data data = {
+ .buffer = &buffer,
+ .vstate = Qfalse,
+ .state = &state,
+ .depth = state.depth,
+ .obj = obj,
+ .func = func,
+ };
+ return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
+}
+
+static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io)
+{
+ return cState_m_do_generate(klass, obj, opts, io, generate_json);
+}
+
+static VALUE cState_m_generate_no_fallback(VALUE klass, VALUE obj, VALUE opts, VALUE io)
+{
+ return cState_m_do_generate(klass, obj, opts, io, generate_json_no_fallback);
+}
+
+void Init_generator(void)
+{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
+#undef rb_intern
+ rb_require("json/common");
+
+ mJSON = rb_define_module("JSON");
+
+ rb_global_variable(&cFragment);
+ cFragment = rb_const_get(mJSON, rb_intern("Fragment"));
+
+ VALUE mExt = rb_define_module_under(mJSON, "Ext");
+ VALUE mGenerator = rb_define_module_under(mExt, "Generator");
+
+ rb_global_variable(&eGeneratorError);
+ eGeneratorError = rb_path2class("JSON::GeneratorError");
+
+ rb_global_variable(&eNestingError);
+ eNestingError = rb_path2class("JSON::NestingError");
+
+ cState = rb_define_class_under(mGenerator, "State", rb_cObject);
+ rb_define_alloc_func(cState, cState_s_allocate);
+ rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
+ rb_define_method(cState, "initialize", cState_initialize, -1);
+ rb_define_alias(cState, "initialize", "initialize"); // avoid method redefinition warnings
+ rb_define_private_method(cState, "_configure", cState_configure, 1);
+
+ rb_define_method(cState, "initialize_copy", cState_init_copy, 1);
+ rb_define_method(cState, "indent", cState_indent, 0);
+ rb_define_method(cState, "indent=", cState_indent_set, 1);
+ rb_define_method(cState, "space", cState_space, 0);
+ rb_define_method(cState, "space=", cState_space_set, 1);
+ rb_define_method(cState, "space_before", cState_space_before, 0);
+ rb_define_method(cState, "space_before=", cState_space_before_set, 1);
+ rb_define_method(cState, "object_nl", cState_object_nl, 0);
+ rb_define_method(cState, "object_nl=", cState_object_nl_set, 1);
+ rb_define_method(cState, "array_nl", cState_array_nl, 0);
+ rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
+ rb_define_method(cState, "as_json", cState_as_json, 0);
+ rb_define_method(cState, "as_json=", cState_as_json_set, 1);
+ rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
+ rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
+ rb_define_method(cState, "script_safe", cState_script_safe, 0);
+ rb_define_method(cState, "script_safe?", cState_script_safe, 0);
+ rb_define_method(cState, "script_safe=", cState_script_safe_set, 1);
+ rb_define_alias(cState, "escape_slash", "script_safe");
+ rb_define_alias(cState, "escape_slash?", "script_safe?");
+ rb_define_alias(cState, "escape_slash=", "script_safe=");
+ rb_define_method(cState, "strict", cState_strict, 0);
+ rb_define_method(cState, "strict?", cState_strict, 0);
+ rb_define_method(cState, "strict=", cState_strict_set, 1);
+ rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
+ rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
+ rb_define_method(cState, "allow_nan=", cState_allow_nan_set, 1);
+ rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
+ rb_define_method(cState, "ascii_only=", cState_ascii_only_set, 1);
+ rb_define_method(cState, "depth", cState_depth, 0);
+ rb_define_method(cState, "depth=", cState_depth_set, 1);
+ rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
+ rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
+ rb_define_method(cState, "generate", cState_generate, -1);
+ rb_define_method(cState, "_generate_no_fallback", cState_generate_no_fallback, -1);
+
+ rb_define_private_method(cState, "allow_duplicate_key?", cState_allow_duplicate_key_p, 0);
+
+ rb_define_singleton_method(cState, "generate", cState_m_generate, 3);
+ rb_define_singleton_method(cState, "_generate_no_fallback", cState_m_generate_no_fallback, 3);
+
+ rb_global_variable(&Encoding_UTF_8);
+ Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8"));
+
+ i_to_s = rb_intern("to_s");
+ i_to_json = rb_intern("to_json");
+ i_new = rb_intern("new");
+ i_encode = rb_intern("encode");
+
+ sym_indent = ID2SYM(rb_intern("indent"));
+ sym_space = ID2SYM(rb_intern("space"));
+ sym_space_before = ID2SYM(rb_intern("space_before"));
+ sym_object_nl = ID2SYM(rb_intern("object_nl"));
+ sym_array_nl = ID2SYM(rb_intern("array_nl"));
+ sym_max_nesting = ID2SYM(rb_intern("max_nesting"));
+ sym_allow_nan = ID2SYM(rb_intern("allow_nan"));
+ sym_ascii_only = ID2SYM(rb_intern("ascii_only"));
+ sym_depth = ID2SYM(rb_intern("depth"));
+ sym_buffer_initial_length = ID2SYM(rb_intern("buffer_initial_length"));
+ sym_script_safe = ID2SYM(rb_intern("script_safe"));
+ sym_escape_slash = ID2SYM(rb_intern("escape_slash"));
+ sym_strict = ID2SYM(rb_intern("strict"));
+ sym_as_json = ID2SYM(rb_intern("as_json"));
+ sym_allow_duplicate_key = ID2SYM(rb_intern("allow_duplicate_key"));
+
+ usascii_encindex = rb_usascii_encindex();
+ utf8_encindex = rb_utf8_encindex();
+ binary_encindex = rb_ascii8bit_encindex();
+
+ rb_require("json/ext/generator/state");
+
+ simd_impl = find_simd_implementation();
+}
diff --git a/ext/json/json.gemspec b/ext/json/json.gemspec
new file mode 100644
index 0000000000..5575731025
--- /dev/null
+++ b/ext/json/json.gemspec
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+version = File.foreach(File.join(__dir__, "lib/json/version.rb")) do |line|
+ /^\s*VERSION\s*=\s*'(.*)'/ =~ line and break $1
+end rescue nil
+
+spec = Gem::Specification.new do |s|
+ java_ext = Gem::Platform === s.platform && s.platform =~ 'java' || RUBY_ENGINE == 'jruby'
+
+ s.name = "json"
+ s.version = version
+
+ s.summary = "JSON Implementation for Ruby"
+ s.homepage = "https://github.com/ruby/json"
+ s.metadata = {
+ 'bug_tracker_uri' => 'https://github.com/ruby/json/issues',
+ 'changelog_uri' => 'https://github.com/ruby/json/blob/master/CHANGES.md',
+ 'documentation_uri' => 'https://docs.ruby-lang.org/en/master/JSON.html',
+ 'homepage_uri' => s.homepage,
+ 'source_code_uri' => 'https://github.com/ruby/json',
+ }
+
+ s.required_ruby_version = Gem::Requirement.new(">= 2.7")
+
+ if java_ext
+ s.description = "A JSON implementation as a JRuby extension."
+ s.author = "Daniel Luz"
+ s.email = "dev+ruby@mernen.com"
+ else
+ s.description = "This is a JSON implementation as a Ruby extension in C."
+ s.authors = ["Florian Frank"]
+ s.email = "flori@ping.de"
+ end
+
+ s.licenses = ["Ruby"]
+
+ s.extra_rdoc_files = ["README.md"]
+ s.rdoc_options = ["--title", "JSON implementation for Ruby", "--main", "README.md"]
+
+ s.files = [
+ "CHANGES.md",
+ "COPYING",
+ "BSDL",
+ "LEGAL",
+ "README.md",
+ "json.gemspec",
+ ] + Dir.glob("lib/**/*.rb", base: File.expand_path("..", __FILE__))
+
+ if java_ext
+ s.platform = 'java'
+ s.files += Dir["lib/json/ext/**/*.jar"]
+ else
+ s.extensions = Dir["ext/json/**/extconf.rb"]
+ s.files += Dir["ext/json/**/*.{c,h,rb}"]
+ end
+end
+
+if RUBY_ENGINE == 'jruby' && $0 == __FILE__
+ Gem::Builder.new(spec).build
+else
+ spec
+end
diff --git a/ext/json/json.h b/ext/json/json.h
new file mode 100644
index 0000000000..cf9420d4dd
--- /dev/null
+++ b/ext/json/json.h
@@ -0,0 +1,134 @@
+#ifndef _JSON_H_
+#define _JSON_H_
+
+#include "ruby.h"
+#include "ruby/encoding.h"
+#include <stdint.h>
+
+#ifndef RBIMPL_ASSERT_OR_ASSUME
+# define RBIMPL_ASSERT_OR_ASSUME(x)
+#endif
+
+#if defined(RUBY_DEBUG) && RUBY_DEBUG
+# define JSON_ASSERT RUBY_ASSERT
+#else
+# ifdef JSON_DEBUG
+# include <assert.h>
+# define JSON_ASSERT(x) assert(x)
+# else
+# define JSON_ASSERT(x)
+# endif
+#endif
+
+/* shims */
+
+#if SIZEOF_UINT64_T == SIZEOF_LONG_LONG
+# define INT64T2NUM(x) LL2NUM(x)
+# define UINT64T2NUM(x) ULL2NUM(x)
+#elif SIZEOF_UINT64_T == SIZEOF_LONG
+# define INT64T2NUM(x) LONG2NUM(x)
+# define UINT64T2NUM(x) ULONG2NUM(x)
+#else
+# error No uint64_t conversion
+#endif
+
+/* This is the fallback definition from Ruby 3.4 */
+#ifndef RBIMPL_STDBOOL_H
+#if defined(__cplusplus)
+# if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L)
+# include <cstdbool>
+# endif
+#elif defined(HAVE_STDBOOL_H)
+# include <stdbool.h>
+#elif !defined(HAVE__BOOL)
+typedef unsigned char _Bool;
+# define bool _Bool
+# define true ((_Bool)+1)
+# define false ((_Bool)+0)
+# define __bool_true_false_are_defined
+#endif
+#endif
+
+#ifndef HAVE_RUBY_XFREE_SIZED
+static inline void ruby_xfree_sized(void *ptr, size_t oldsize)
+{
+ ruby_xfree(ptr);
+}
+
+static inline void *ruby_xrealloc2_sized(void *ptr, size_t new_elems, size_t elem_size, size_t old_elems)
+{
+ return ruby_xrealloc2(ptr, new_elems, elem_size);
+}
+#endif
+
+# define JSON_SIZED_REALLOC_N(v, T, m, n) \
+ ((v) = (T *)ruby_xrealloc2_sized((void *)(v), (m), sizeof(T), (n)))
+
+# define JSON_SIZED_FREE(v) ruby_xfree_sized((void *)(v), sizeof(*(v)))
+# define JSON_SIZED_FREE_N(v, n) ruby_xfree_sized((void *)(v), sizeof(*(v)) * (n))
+
+#ifndef HAVE_RB_EXT_RACTOR_SAFE
+# undef RUBY_TYPED_FROZEN_SHAREABLE
+# define RUBY_TYPED_FROZEN_SHAREABLE 0
+#endif
+
+#ifdef RUBY_TYPED_EMBEDDABLE
+# define HAVE_RUBY_TYPED_EMBEDDABLE 1
+#else
+# ifdef HAVE_CONST_RUBY_TYPED_EMBEDDABLE
+# define RUBY_TYPED_EMBEDDABLE RUBY_TYPED_EMBEDDABLE
+# define HAVE_RUBY_TYPED_EMBEDDABLE 1
+# else
+# define RUBY_TYPED_EMBEDDABLE 0
+# endif
+#endif
+
+#ifndef NORETURN
+#if defined(__has_attribute) && __has_attribute(noreturn)
+#define NORETURN(x) __attribute__((noreturn)) x
+#else
+#define NORETURN(x) x
+#endif
+#endif
+
+#ifndef NOINLINE
+#if defined(__has_attribute) && __has_attribute(noinline)
+#define NOINLINE(x) __attribute__((noinline)) x
+#else
+#define NOINLINE(x) x
+#endif
+#endif
+
+#ifndef ALWAYS_INLINE
+#if defined(__has_attribute) && __has_attribute(always_inline)
+#define ALWAYS_INLINE(x) inline __attribute__((always_inline)) x
+#else
+#define ALWAYS_INLINE(x) inline x
+#endif
+#endif
+
+#ifndef RB_UNLIKELY
+#define RB_UNLIKELY(expr) expr
+#endif
+
+#ifndef RB_LIKELY
+#define RB_LIKELY(expr) expr
+#endif
+
+#ifndef MAYBE_UNUSED
+# define MAYBE_UNUSED(x) x
+#endif
+
+#ifdef RUBY_DEBUG
+#ifndef JSON_DEBUG
+#define JSON_DEBUG RUBY_DEBUG
+#endif
+#endif
+
+#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && INTPTR_MAX == INT64_MAX
+#define JSON_CPU_LITTLE_ENDIAN_64BITS 1
+#else
+#define JSON_CPU_LITTLE_ENDIAN_64BITS 0
+#endif
+
+#endif // _JSON_H_
diff --git a/ext/json/lib/json.rb b/ext/json/lib/json.rb
new file mode 100644
index 0000000000..26d601926f
--- /dev/null
+++ b/ext/json/lib/json.rb
@@ -0,0 +1,675 @@
+# frozen_string_literal: true
+require 'json/common'
+
+##
+# = JavaScript \Object Notation (\JSON)
+#
+# \JSON is a lightweight data-interchange format.
+#
+# \JSON is easy for us humans to read and write,
+# and equally simple for machines to read (parse) and write (generate).
+#
+# \JSON is language-independent, making it an ideal interchange format
+# for applications in differing programming languages
+# and on differing operating systems.
+#
+# == \JSON Values
+#
+# A \JSON value is one of the following:
+# - Double-quoted text: <tt>"foo"</tt>.
+# - Number: +1+, +1.0+, +2.0e2+.
+# - Boolean: +true+, +false+.
+# - Null: +null+.
+# - \Array: an ordered list of values, enclosed by square brackets:
+# ["foo", 1, 1.0, 2.0e2, true, false, null]
+#
+# - \Object: a collection of name/value pairs, enclosed by curly braces;
+# each name is double-quoted text;
+# the values may be any \JSON values:
+# {"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}
+#
+# A \JSON array or object may contain nested arrays, objects, and scalars
+# to any depth:
+# {"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}
+# [{"foo": 0, "bar": 1}, ["baz", 2]]
+#
+# == Using \Module \JSON
+#
+# To make module \JSON available in your code, begin with:
+# require 'json'
+#
+# All examples here assume that this has been done.
+#
+# === Parsing \JSON
+#
+# You can parse a \String containing \JSON data using
+# either of two methods:
+# - <tt>JSON.parse(source, opts)</tt>
+# - <tt>JSON.parse!(source, opts)</tt>
+#
+# where
+# - +source+ is a Ruby object.
+# - +opts+ is a \Hash object containing options
+# that control both input allowed and output formatting.
+#
+# The difference between the two methods
+# is that JSON.parse! omits some checks
+# and may not be safe for some +source+ data;
+# use it only for data from trusted sources.
+# Use the safer method JSON.parse for less trusted sources.
+#
+# ==== Parsing \JSON Arrays
+#
+# When +source+ is a \JSON array, JSON.parse by default returns a Ruby \Array:
+# json = '["foo", 1, 1.0, 2.0e2, true, false, null]'
+# ruby = JSON.parse(json)
+# ruby # => ["foo", 1, 1.0, 200.0, true, false, nil]
+# ruby.class # => Array
+#
+# The \JSON array may contain nested arrays, objects, and scalars
+# to any depth:
+# json = '[{"foo": 0, "bar": 1}, ["baz", 2]]'
+# JSON.parse(json) # => [{"foo"=>0, "bar"=>1}, ["baz", 2]]
+#
+# ==== Parsing \JSON \Objects
+#
+# When the source is a \JSON object, JSON.parse by default returns a Ruby \Hash:
+# json = '{"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}'
+# ruby = JSON.parse(json)
+# ruby # => {"a"=>"foo", "b"=>1, "c"=>1.0, "d"=>200.0, "e"=>true, "f"=>false, "g"=>nil}
+# ruby.class # => Hash
+#
+# The \JSON object may contain nested arrays, objects, and scalars
+# to any depth:
+# json = '{"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}'
+# JSON.parse(json) # => {"foo"=>{"bar"=>1, "baz"=>2}, "bat"=>[0, 1, 2]}
+#
+# ==== Parsing \JSON Scalars
+#
+# When the source is a \JSON scalar (not an array or object),
+# JSON.parse returns a Ruby scalar.
+#
+# \String:
+# ruby = JSON.parse('"foo"')
+# ruby # => 'foo'
+# ruby.class # => String
+# \Integer:
+# ruby = JSON.parse('1')
+# ruby # => 1
+# ruby.class # => Integer
+# \Float:
+# ruby = JSON.parse('1.0')
+# ruby # => 1.0
+# ruby.class # => Float
+# ruby = JSON.parse('2.0e2')
+# ruby # => 200
+# ruby.class # => Float
+# Boolean:
+# ruby = JSON.parse('true')
+# ruby # => true
+# ruby.class # => TrueClass
+# ruby = JSON.parse('false')
+# ruby # => false
+# ruby.class # => FalseClass
+# Null:
+# ruby = JSON.parse('null')
+# ruby # => nil
+# ruby.class # => NilClass
+#
+# ==== Parsing Options
+#
+# ====== Input Options
+#
+# Option +max_nesting+ (\Integer) specifies the maximum nesting depth allowed;
+# defaults to +100+; specify +false+ to disable depth checking.
+#
+# With the default, +false+:
+# source = '[0, [1, [2, [3]]]]'
+# ruby = JSON.parse(source)
+# ruby # => [0, [1, [2, [3]]]]
+# Too deep:
+# # Raises JSON::NestingError (nesting of 2 is too deep):
+# JSON.parse(source, {max_nesting: 1})
+# Bad value:
+# # Raises TypeError (wrong argument type Symbol (expected Fixnum)):
+# JSON.parse(source, {max_nesting: :foo})
+#
+# ---
+#
+# Option +allow_duplicate_key+ specifies whether duplicate keys in objects
+# should be ignored or cause an error to be raised:
+#
+# When not specified:
+# # The last value is used and a deprecation warning emitted.
+# JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
+# # warning: detected duplicate keys in JSON object.
+# # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
+#
+# When set to `+true+`
+# # The last value is used.
+# JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
+#
+# When set to `+false+`, the future default:
+# JSON.parse('{"a": 1, "a":2}') => duplicate key at line 1 column 1 (JSON::ParserError)
+#
+# ---
+#
+# Option +allow_nan+ (boolean) specifies whether to allow
+# NaN, Infinity, and MinusInfinity in +source+;
+# defaults to +false+.
+#
+# With the default, +false+:
+# # Raises JSON::ParserError (225: unexpected token at '[NaN]'):
+# JSON.parse('[NaN]')
+# # Raises JSON::ParserError (232: unexpected token at '[Infinity]'):
+# JSON.parse('[Infinity]')
+# # Raises JSON::ParserError (248: unexpected token at '[-Infinity]'):
+# JSON.parse('[-Infinity]')
+# Allow:
+# source = '[NaN, Infinity, -Infinity]'
+# ruby = JSON.parse(source, {allow_nan: true})
+# ruby # => [NaN, Infinity, -Infinity]
+#
+# ---
+#
+# Option +allow_trailing_comma+ (boolean) specifies whether to allow
+# trailing commas in objects and arrays;
+# defaults to +false+.
+#
+# With the default, +false+:
+# JSON.parse('[1,]') # unexpected character: ']' at line 1 column 4 (JSON::ParserError)
+#
+# When enabled:
+# JSON.parse('[1,]', allow_trailing_comma: true) # => [1]
+#
+# ---
+#
+# Option +allow_control_characters+ (boolean) specifies whether to allow
+# unescaped ASCII control characters, such as newlines, in strings;
+# defaults to +false+.
+#
+# With the default, +false+:
+# JSON.parse(%{"Hello\nWorld"}) # invalid ASCII control character in string (JSON::ParserError)
+#
+# When enabled:
+# JSON.parse(%{"Hello\nWorld"}, allow_control_characters: true) # => "Hello\nWorld"
+#
+# ---
+#
+# Option +allow_invalid_escape+ (boolean) specifies whether to ignore backslahes that are followed
+# by an invalid escape character in strings;
+# defaults to +false+.
+#
+# With the default, +false+:
+# JSON.parse('"Hell\o"') # invalid escape character in string (JSON::ParserError)
+#
+# When enabled:
+# JSON.parse('"Hell\o"', allow_invalid_escape: true) # => "Hello"
+#
+# ====== Output Options
+#
+# Option +freeze+ (boolean) specifies whether the returned objects will be frozen;
+# defaults to +false+.
+#
+# Option +symbolize_names+ (boolean) specifies whether returned \Hash keys
+# should be Symbols;
+# defaults to +false+ (use Strings).
+#
+# With the default, +false+:
+# source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
+# ruby = JSON.parse(source)
+# ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
+# Use Symbols:
+# ruby = JSON.parse(source, {symbolize_names: true})
+# ruby # => {:a=>"foo", :b=>1.0, :c=>true, :d=>false, :e=>nil}
+#
+# ---
+#
+# Option +object_class+ (\Class) specifies the Ruby class to be used
+# for each \JSON object;
+# defaults to \Hash.
+#
+# With the default, \Hash:
+# source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
+# ruby = JSON.parse(source)
+# ruby.class # => Hash
+# Use class \OpenStruct:
+# ruby = JSON.parse(source, {object_class: OpenStruct})
+# ruby # => #<OpenStruct a="foo", b=1.0, c=true, d=false, e=nil>
+#
+# ---
+#
+# Option +array_class+ (\Class) specifies the Ruby class to be used
+# for each \JSON array;
+# defaults to \Array.
+#
+# With the default, \Array:
+# source = '["foo", 1.0, true, false, null]'
+# ruby = JSON.parse(source)
+# ruby.class # => Array
+# Use class \Set:
+# ruby = JSON.parse(source, {array_class: Set})
+# ruby # => #<Set: {"foo", 1.0, true, false, nil}>
+#
+# ---
+#
+# Option +create_additions+ (boolean) specifies whether to use \JSON additions in parsing.
+# See {\JSON Additions}[#module-JSON-label-JSON+Additions].
+#
+# === Generating \JSON
+#
+# To generate a Ruby \String containing \JSON data,
+# use method <tt>JSON.generate(source, opts)</tt>, where
+# - +source+ is a Ruby object.
+# - +opts+ is a \Hash object containing options
+# that control both input allowed and output formatting.
+#
+# ==== Generating \JSON from Arrays
+#
+# When the source is a Ruby \Array, JSON.generate returns
+# a \String containing a \JSON array:
+# ruby = [0, 's', :foo]
+# json = JSON.generate(ruby)
+# json # => '[0,"s","foo"]'
+#
+# The Ruby \Array array may contain nested arrays, hashes, and scalars
+# to any depth:
+# ruby = [0, [1, 2], {foo: 3, bar: 4}]
+# json = JSON.generate(ruby)
+# json # => '[0,[1,2],{"foo":3,"bar":4}]'
+#
+# ==== Generating \JSON from Hashes
+#
+# When the source is a Ruby \Hash, JSON.generate returns
+# a \String containing a \JSON object:
+# ruby = {foo: 0, bar: 's', baz: :bat}
+# json = JSON.generate(ruby)
+# json # => '{"foo":0,"bar":"s","baz":"bat"}'
+#
+# The Ruby \Hash array may contain nested arrays, hashes, and scalars
+# to any depth:
+# ruby = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad}
+# json = JSON.generate(ruby)
+# json # => '{"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}'
+#
+# ==== Generating \JSON from Other Objects
+#
+# When the source is neither an \Array nor a \Hash,
+# the generated \JSON data depends on the class of the source.
+#
+# When the source is a Ruby \Integer or \Float, JSON.generate returns
+# a \String containing a \JSON number:
+# JSON.generate(42) # => '42'
+# JSON.generate(0.42) # => '0.42'
+#
+# When the source is a Ruby \String, JSON.generate returns
+# a \String containing a \JSON string (with double-quotes):
+# JSON.generate('A string') # => '"A string"'
+#
+# When the source is +true+, +false+ or +nil+, JSON.generate returns
+# a \String containing the corresponding \JSON token:
+# JSON.generate(true) # => 'true'
+# JSON.generate(false) # => 'false'
+# JSON.generate(nil) # => 'null'
+#
+# When the source is none of the above, JSON.generate returns
+# a \String containing a \JSON string representation of the source:
+# JSON.generate(:foo) # => '"foo"'
+# JSON.generate(Complex(0, 0)) # => '"0+0i"'
+# JSON.generate(Dir.new('.')) # => '"#<Dir>"'
+#
+# ==== Generating Options
+#
+# ====== Input Options
+#
+# Option +allow_nan+ (boolean) specifies whether
+# +NaN+, +Infinity+, and <tt>-Infinity</tt> may be generated;
+# defaults to +false+.
+#
+# With the default, +false+:
+# # Raises JSON::GeneratorError (920: NaN not allowed in JSON):
+# JSON.generate(JSON::NaN)
+# # Raises JSON::GeneratorError (917: Infinity not allowed in JSON):
+# JSON.generate(JSON::Infinity)
+# # Raises JSON::GeneratorError (917: -Infinity not allowed in JSON):
+# JSON.generate(JSON::MinusInfinity)
+#
+# Allow:
+# ruby = [Float::NAN, Float::INFINITY, JSON::NaN, JSON::Infinity, JSON::MinusInfinity]
+# JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,NaN,Infinity,-Infinity]'
+#
+# ---
+#
+# Option +allow_duplicate_key+ (boolean) specifies whether
+# hashes with duplicate keys should be allowed or produce an error.
+# defaults to emit a deprecation warning.
+#
+# With the default, (not set):
+# Warning[:deprecated] = true
+# JSON.generate({ foo: 1, "foo" => 2 })
+# # warning: detected duplicate key "foo" in {foo: 1, "foo" => 2}.
+# # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
+# # => '{"foo":1,"foo":2}'
+#
+# With <tt>false</tt>
+# JSON.generate({ foo: 1, "foo" => 2 }, allow_duplicate_key: false)
+# # detected duplicate key "foo" in {foo: 1, "foo" => 2} (JSON::GeneratorError)
+#
+# In version 3.0, <tt>false</tt> will become the default.
+#
+# ---
+#
+# Option +max_nesting+ (\Integer) specifies the maximum nesting depth
+# in +obj+; defaults to +100+.
+#
+# With the default, +100+:
+# obj = [[[[[[0]]]]]]
+# JSON.generate(obj) # => '[[[[[[0]]]]]]'
+#
+# Too deep:
+# # Raises JSON::NestingError (nesting of 2 is too deep):
+# JSON.generate(obj, max_nesting: 2)
+#
+# ====== Escaping Options
+#
+# Options +script_safe+ (boolean) specifies wether <tt>'\u2028'</tt>, <tt>'\u2029'</tt>
+# and <tt>'/'</tt> should be escaped as to make the JSON object safe to interpolate in script
+# tags.
+#
+# Options +ascii_only+ (boolean) specifies wether all characters outside the ASCII range
+# should be escaped.
+#
+# ====== Output Options
+#
+# The default formatting options generate the most compact
+# \JSON data, all on one line and with no whitespace.
+#
+# You can use these formatting options to generate
+# \JSON data in a more open format, using whitespace.
+# See also JSON.pretty_generate.
+#
+# - Option +array_nl+ (\String) specifies a string (usually a newline)
+# to be inserted after each \JSON array; defaults to the empty \String, <tt>''</tt>.
+# - Option +object_nl+ (\String) specifies a string (usually a newline)
+# to be inserted after each \JSON object; defaults to the empty \String, <tt>''</tt>.
+# - Option +indent+ (\String) specifies the string (usually spaces) to be
+# used for indentation; defaults to the empty \String, <tt>''</tt>;
+# defaults to the empty \String, <tt>''</tt>;
+# has no effect unless options +array_nl+ or +object_nl+ specify newlines.
+# - Option +space+ (\String) specifies a string (usually a space) to be
+# inserted after the colon in each \JSON object's pair;
+# defaults to the empty \String, <tt>''</tt>.
+# - Option +space_before+ (\String) specifies a string (usually a space) to be
+# inserted before the colon in each \JSON object's pair;
+# defaults to the empty \String, <tt>''</tt>.
+#
+# In this example, +obj+ is used first to generate the shortest
+# \JSON data (no whitespace), then again with all formatting options
+# specified:
+#
+# obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
+# json = JSON.generate(obj)
+# puts 'Compact:', json
+# opts = {
+# array_nl: "\n",
+# object_nl: "\n",
+# indent: ' ',
+# space_before: ' ',
+# space: ' '
+# }
+# puts 'Open:', JSON.generate(obj, opts)
+#
+# Output:
+# Compact:
+# {"foo":["bar","baz"],"bat":{"bam":0,"bad":1}}
+# Open:
+# {
+# "foo" : [
+# "bar",
+# "baz"
+# ],
+# "bat" : {
+# "bam" : 0,
+# "bad" : 1
+# }
+# }
+#
+# == \JSON Additions
+#
+# Note that JSON Additions must only be used with trusted data, and is
+# deprecated.
+#
+# When you "round trip" a non-\String object from Ruby to \JSON and back,
+# you have a new \String, instead of the object you began with:
+# ruby0 = Range.new(0, 2)
+# json = JSON.generate(ruby0)
+# json # => '0..2"'
+# ruby1 = JSON.parse(json)
+# ruby1 # => '0..2'
+# ruby1.class # => String
+#
+# You can use \JSON _additions_ to preserve the original object.
+# The addition is an extension of a ruby class, so that:
+# - \JSON.generate stores more information in the \JSON string.
+# - \JSON.parse, called with option +create_additions+,
+# uses that information to create a proper Ruby object.
+#
+# This example shows a \Range being generated into \JSON
+# and parsed back into Ruby, both without and with
+# the addition for \Range:
+# ruby = Range.new(0, 2)
+# # This passage does not use the addition for Range.
+# json0 = JSON.generate(ruby)
+# ruby0 = JSON.parse(json0)
+# # This passage uses the addition for Range.
+# require 'json/add/range'
+# json1 = JSON.generate(ruby)
+# ruby1 = JSON.parse(json1, create_additions: true)
+# # Make a nice display.
+# display = <<~EOT
+# Generated JSON:
+# Without addition: #{json0} (#{json0.class})
+# With addition: #{json1} (#{json1.class})
+# Parsed JSON:
+# Without addition: #{ruby0.inspect} (#{ruby0.class})
+# With addition: #{ruby1.inspect} (#{ruby1.class})
+# EOT
+# puts display
+#
+# This output shows the different results:
+# Generated JSON:
+# Without addition: "0..2" (String)
+# With addition: {"json_class":"Range","a":[0,2,false]} (String)
+# Parsed JSON:
+# Without addition: "0..2" (String)
+# With addition: 0..2 (Range)
+#
+# The \JSON module includes additions for certain classes.
+# You can also craft custom additions.
+# See {Custom \JSON Additions}[#module-JSON-label-Custom+JSON+Additions].
+#
+# === Built-in Additions
+#
+# The \JSON module includes additions for certain classes.
+# To use an addition, +require+ its source:
+# - BigDecimal: <tt>require 'json/add/bigdecimal'</tt>
+# - Complex: <tt>require 'json/add/complex'</tt>
+# - Date: <tt>require 'json/add/date'</tt>
+# - DateTime: <tt>require 'json/add/date_time'</tt>
+# - Exception: <tt>require 'json/add/exception'</tt>
+# - OpenStruct: <tt>require 'json/add/ostruct'</tt>
+# - Range: <tt>require 'json/add/range'</tt>
+# - Rational: <tt>require 'json/add/rational'</tt>
+# - Regexp: <tt>require 'json/add/regexp'</tt>
+# - Set: <tt>require 'json/add/set'</tt>
+# - Struct: <tt>require 'json/add/struct'</tt>
+# - Symbol: <tt>require 'json/add/symbol'</tt>
+# - Time: <tt>require 'json/add/time'</tt>
+#
+# To reduce punctuation clutter, the examples below
+# show the generated \JSON via +puts+, rather than the usual +inspect+,
+#
+# \BigDecimal:
+# require 'json/add/bigdecimal'
+# ruby0 = BigDecimal(0) # 0.0
+# json = JSON.generate(ruby0) # {"json_class":"BigDecimal","b":"27:0.0"}
+# ruby1 = JSON.parse(json, create_additions: true) # 0.0
+# ruby1.class # => BigDecimal
+#
+# \Complex:
+# require 'json/add/complex'
+# ruby0 = Complex(1+0i) # 1+0i
+# json = JSON.generate(ruby0) # {"json_class":"Complex","r":1,"i":0}
+# ruby1 = JSON.parse(json, create_additions: true) # 1+0i
+# ruby1.class # Complex
+#
+# \Date:
+# require 'json/add/date'
+# ruby0 = Date.today # 2020-05-02
+# json = JSON.generate(ruby0) # {"json_class":"Date","y":2020,"m":5,"d":2,"sg":2299161.0}
+# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02
+# ruby1.class # Date
+#
+# \DateTime:
+# require 'json/add/date_time'
+# ruby0 = DateTime.now # 2020-05-02T10:38:13-05:00
+# json = JSON.generate(ruby0) # {"json_class":"DateTime","y":2020,"m":5,"d":2,"H":10,"M":38,"S":13,"of":"-5/24","sg":2299161.0}
+# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02T10:38:13-05:00
+# ruby1.class # DateTime
+#
+# \Exception (and its subclasses including \RuntimeError):
+# require 'json/add/exception'
+# ruby0 = Exception.new('A message') # A message
+# json = JSON.generate(ruby0) # {"json_class":"Exception","m":"A message","b":null}
+# ruby1 = JSON.parse(json, create_additions: true) # A message
+# ruby1.class # Exception
+# ruby0 = RuntimeError.new('Another message') # Another message
+# json = JSON.generate(ruby0) # {"json_class":"RuntimeError","m":"Another message","b":null}
+# ruby1 = JSON.parse(json, create_additions: true) # Another message
+# ruby1.class # RuntimeError
+#
+# \OpenStruct:
+# require 'json/add/ostruct'
+# ruby0 = OpenStruct.new(name: 'Matz', language: 'Ruby') # #<OpenStruct name="Matz", language="Ruby">
+# json = JSON.generate(ruby0) # {"json_class":"OpenStruct","t":{"name":"Matz","language":"Ruby"}}
+# ruby1 = JSON.parse(json, create_additions: true) # #<OpenStruct name="Matz", language="Ruby">
+# ruby1.class # OpenStruct
+#
+# \Range:
+# require 'json/add/range'
+# ruby0 = Range.new(0, 2) # 0..2
+# json = JSON.generate(ruby0) # {"json_class":"Range","a":[0,2,false]}
+# ruby1 = JSON.parse(json, create_additions: true) # 0..2
+# ruby1.class # Range
+#
+# \Rational:
+# require 'json/add/rational'
+# ruby0 = Rational(1, 3) # 1/3
+# json = JSON.generate(ruby0) # {"json_class":"Rational","n":1,"d":3}
+# ruby1 = JSON.parse(json, create_additions: true) # 1/3
+# ruby1.class # Rational
+#
+# \Regexp:
+# require 'json/add/regexp'
+# ruby0 = Regexp.new('foo') # (?-mix:foo)
+# json = JSON.generate(ruby0) # {"json_class":"Regexp","o":0,"s":"foo"}
+# ruby1 = JSON.parse(json, create_additions: true) # (?-mix:foo)
+# ruby1.class # Regexp
+#
+# \Set:
+# require 'json/add/set'
+# ruby0 = Set.new([0, 1, 2]) # #<Set: {0, 1, 2}>
+# json = JSON.generate(ruby0) # {"json_class":"Set","a":[0,1,2]}
+# ruby1 = JSON.parse(json, create_additions: true) # #<Set: {0, 1, 2}>
+# ruby1.class # Set
+#
+# \Struct:
+# require 'json/add/struct'
+# Customer = Struct.new(:name, :address) # Customer
+# ruby0 = Customer.new("Dave", "123 Main") # #<struct Customer name="Dave", address="123 Main">
+# json = JSON.generate(ruby0) # {"json_class":"Customer","v":["Dave","123 Main"]}
+# ruby1 = JSON.parse(json, create_additions: true) # #<struct Customer name="Dave", address="123 Main">
+# ruby1.class # Customer
+#
+# \Symbol:
+# require 'json/add/symbol'
+# ruby0 = :foo # foo
+# json = JSON.generate(ruby0) # {"json_class":"Symbol","s":"foo"}
+# ruby1 = JSON.parse(json, create_additions: true) # foo
+# ruby1.class # Symbol
+#
+# \Time:
+# require 'json/add/time'
+# ruby0 = Time.now # 2020-05-02 11:28:26 -0500
+# json = JSON.generate(ruby0) # {"json_class":"Time","s":1588436906,"n":840560000}
+# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 11:28:26 -0500
+# ruby1.class # Time
+#
+#
+# === Custom \JSON Additions
+#
+# In addition to the \JSON additions provided,
+# you can craft \JSON additions of your own,
+# either for Ruby built-in classes or for user-defined classes.
+#
+# Here's a user-defined class +Foo+:
+# class Foo
+# attr_accessor :bar, :baz
+# def initialize(bar, baz)
+# self.bar = bar
+# self.baz = baz
+# end
+# end
+#
+# Here's the \JSON addition for it:
+# # Extend class Foo with JSON addition.
+# class Foo
+# # Serialize Foo object with its class name and arguments
+# def to_json(*args)
+# {
+# JSON.create_id => self.class.name,
+# 'a' => [ bar, baz ]
+# }.to_json(*args)
+# end
+# # Deserialize JSON string by constructing new Foo object with arguments.
+# def self.json_create(object)
+# new(*object['a'])
+# end
+# end
+#
+# Demonstration:
+# require 'json'
+# # This Foo object has no custom addition.
+# foo0 = Foo.new(0, 1)
+# json0 = JSON.generate(foo0)
+# obj0 = JSON.parse(json0)
+# # Lood the custom addition.
+# require_relative 'foo_addition'
+# # This foo has the custom addition.
+# foo1 = Foo.new(0, 1)
+# json1 = JSON.generate(foo1)
+# obj1 = JSON.parse(json1, create_additions: true)
+# # Make a nice display.
+# display = <<~EOT
+# Generated JSON:
+# Without custom addition: #{json0} (#{json0.class})
+# With custom addition: #{json1} (#{json1.class})
+# Parsed JSON:
+# Without custom addition: #{obj0.inspect} (#{obj0.class})
+# With custom addition: #{obj1.inspect} (#{obj1.class})
+# EOT
+# puts display
+#
+# Output:
+#
+# Generated JSON:
+# Without custom addition: "#<Foo:0x0000000006534e80>" (String)
+# With custom addition: {"json_class":"Foo","a":[0,1]} (String)
+# Parsed JSON:
+# Without custom addition: "#<Foo:0x0000000006534e80>" (String)
+# With custom addition: #<Foo:0x0000000006473bb8 @bar=0, @baz=1> (Foo)
+#
+module JSON
+ require 'json/version'
+ require 'json/ext'
+end
diff --git a/ext/json/lib/json/add/bigdecimal.rb b/ext/json/lib/json/add/bigdecimal.rb
new file mode 100644
index 0000000000..dc84572f31
--- /dev/null
+++ b/ext/json/lib/json/add/bigdecimal.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+begin
+ require 'bigdecimal'
+rescue LoadError
+end
+
+class BigDecimal
+
+ # See #as_json.
+ def self.json_create(object)
+ BigDecimal._load object['b']
+ end
+
+ # Methods <tt>BigDecimal#as_json</tt> and +BigDecimal.json_create+ may be used
+ # to serialize and deserialize a \BigDecimal object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>BigDecimal#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/bigdecimal'
+ # x = BigDecimal(2).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
+ # y = BigDecimal(2.0, 4).as_json # => {"json_class"=>"BigDecimal", "b"=>"36:0.2e1"}
+ # z = BigDecimal(Complex(2, 0)).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \BigDecimal object:
+ #
+ # BigDecimal.json_create(x) # => 0.2e1
+ # BigDecimal.json_create(y) # => 0.2e1
+ # BigDecimal.json_create(z) # => 0.2e1
+ #
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'b' => _dump.force_encoding(Encoding::UTF_8),
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/bigdecimal'
+ # puts BigDecimal(2).to_json
+ # puts BigDecimal(2.0, 4).to_json
+ # puts BigDecimal(Complex(2, 0)).to_json
+ #
+ # Output:
+ #
+ # {"json_class":"BigDecimal","b":"27:0.2e1"}
+ # {"json_class":"BigDecimal","b":"36:0.2e1"}
+ # {"json_class":"BigDecimal","b":"27:0.2e1"}
+ #
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end if defined?(::BigDecimal)
diff --git a/ext/json/lib/json/add/complex.rb b/ext/json/lib/json/add/complex.rb
new file mode 100644
index 0000000000..9e3c6f2d0a
--- /dev/null
+++ b/ext/json/lib/json/add/complex.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+class Complex
+
+ # See #as_json.
+ def self.json_create(object)
+ Complex(object['r'], object['i'])
+ end
+
+ # Methods <tt>Complex#as_json</tt> and +Complex.json_create+ may be used
+ # to serialize and deserialize a \Complex object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Complex#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/complex'
+ # x = Complex(2).as_json # => {"json_class"=>"Complex", "r"=>2, "i"=>0}
+ # y = Complex(2.0, 4).as_json # => {"json_class"=>"Complex", "r"=>2.0, "i"=>4}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Complex object:
+ #
+ # Complex.json_create(x) # => (2+0i)
+ # Complex.json_create(y) # => (2.0+4i)
+ #
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'r' => real,
+ 'i' => imag,
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/complex'
+ # puts Complex(2).to_json
+ # puts Complex(2.0, 4).to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Complex","r":2,"i":0}
+ # {"json_class":"Complex","r":2.0,"i":4}
+ #
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/add/core.rb b/ext/json/lib/json/add/core.rb
new file mode 100644
index 0000000000..61ff454212
--- /dev/null
+++ b/ext/json/lib/json/add/core.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+# This file requires the implementations of ruby core's custom objects for
+# serialisation/deserialisation.
+
+require 'json/add/date'
+require 'json/add/date_time'
+require 'json/add/exception'
+require 'json/add/range'
+require 'json/add/regexp'
+require 'json/add/string'
+require 'json/add/struct'
+require 'json/add/symbol'
+require 'json/add/time'
diff --git a/ext/json/lib/json/add/date.rb b/ext/json/lib/json/add/date.rb
new file mode 100644
index 0000000000..88a098b637
--- /dev/null
+++ b/ext/json/lib/json/add/date.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+require 'date'
+
+class Date
+
+ # See #as_json.
+ def self.json_create(object)
+ civil(*object.values_at('y', 'm', 'd', 'sg'))
+ end
+
+ alias start sg unless method_defined?(:start)
+
+ # Methods <tt>Date#as_json</tt> and +Date.json_create+ may be used
+ # to serialize and deserialize a \Date object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Date#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/date'
+ # x = Date.today.as_json
+ # # => {"json_class"=>"Date", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Date object:
+ #
+ # Date.json_create(x)
+ # # => #<Date: 2023-11-21 ((2460270j,0s,0n),+0s,2299161j)>
+ #
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'y' => year,
+ 'm' => month,
+ 'd' => day,
+ 'sg' => start,
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/date'
+ # puts Date.today.to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Date","y":2023,"m":11,"d":21,"sg":2299161.0}
+ #
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/add/date_time.rb b/ext/json/lib/json/add/date_time.rb
new file mode 100644
index 0000000000..8b0bb5d181
--- /dev/null
+++ b/ext/json/lib/json/add/date_time.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+require 'date'
+
+class DateTime
+
+ # See #as_json.
+ def self.json_create(object)
+ args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
+ of_a, of_b = object['of'].split('/')
+ if of_b and of_b != '0'
+ args << Rational(of_a.to_i, of_b.to_i)
+ else
+ args << of_a
+ end
+ args << object['sg']
+ civil(*args)
+ end
+
+ alias start sg unless method_defined?(:start)
+
+ # Methods <tt>DateTime#as_json</tt> and +DateTime.json_create+ may be used
+ # to serialize and deserialize a \DateTime object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>DateTime#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/datetime'
+ # x = DateTime.now.as_json
+ # # => {"json_class"=>"DateTime", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \DateTime object:
+ #
+ # DateTime.json_create(x) # BUG? Raises Date::Error "invalid date"
+ #
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'y' => year,
+ 'm' => month,
+ 'd' => day,
+ 'H' => hour,
+ 'M' => min,
+ 'S' => sec,
+ 'of' => offset.to_s,
+ 'sg' => start,
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/datetime'
+ # puts DateTime.now.to_json
+ #
+ # Output:
+ #
+ # {"json_class":"DateTime","y":2023,"m":11,"d":21,"sg":2299161.0}
+ #
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
+
+
diff --git a/ext/json/lib/json/add/exception.rb b/ext/json/lib/json/add/exception.rb
new file mode 100644
index 0000000000..e85d404982
--- /dev/null
+++ b/ext/json/lib/json/add/exception.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+class Exception
+
+ # See #as_json.
+ def self.json_create(object)
+ result = new(object['m'])
+ result.set_backtrace object['b']
+ result
+ end
+
+ # Methods <tt>Exception#as_json</tt> and +Exception.json_create+ may be used
+ # to serialize and deserialize a \Exception object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Exception#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/exception'
+ # x = Exception.new('Foo').as_json # => {"json_class"=>"Exception", "m"=>"Foo", "b"=>nil}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Exception object:
+ #
+ # Exception.json_create(x) # => #<Exception: Foo>
+ #
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'm' => message,
+ 'b' => backtrace,
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/exception'
+ # puts Exception.new('Foo').to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Exception","m":"Foo","b":null}
+ #
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/add/ostruct.rb b/ext/json/lib/json/add/ostruct.rb
new file mode 100644
index 0000000000..7750498144
--- /dev/null
+++ b/ext/json/lib/json/add/ostruct.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+begin
+ require 'ostruct'
+rescue LoadError
+end
+
+class OpenStruct
+
+ # See #as_json.
+ def self.json_create(object)
+ new(object['t'] || object[:t])
+ end
+
+ # Methods <tt>OpenStruct#as_json</tt> and +OpenStruct.json_create+ may be used
+ # to serialize and deserialize a \OpenStruct object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>OpenStruct#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/ostruct'
+ # x = OpenStruct.new('name' => 'Rowdy', :age => nil).as_json
+ # # => {"json_class"=>"OpenStruct", "t"=>{:name=>'Rowdy', :age=>nil}}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \OpenStruct object:
+ #
+ # OpenStruct.json_create(x)
+ # # => #<OpenStruct name='Rowdy', age=nil>
+ #
+ def as_json(*)
+ klass = self.class.name
+ klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
+ {
+ JSON.create_id => klass,
+ 't' => table,
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/ostruct'
+ # puts OpenStruct.new('name' => 'Rowdy', :age => nil).to_json
+ #
+ # Output:
+ #
+ # {"json_class":"OpenStruct","t":{'name':'Rowdy',"age":null}}
+ #
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end if defined?(::OpenStruct)
diff --git a/ext/json/lib/json/add/range.rb b/ext/json/lib/json/add/range.rb
new file mode 100644
index 0000000000..408d2c32f6
--- /dev/null
+++ b/ext/json/lib/json/add/range.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+class Range
+
+ # See #as_json.
+ def self.json_create(object)
+ new(*object['a'])
+ end
+
+ # Methods <tt>Range#as_json</tt> and +Range.json_create+ may be used
+ # to serialize and deserialize a \Range object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Range#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/range'
+ # x = (1..4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, false]}
+ # y = (1...4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, true]}
+ # z = ('a'..'d').as_json # => {"json_class"=>"Range", "a"=>["a", "d", false]}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Range object:
+ #
+ # Range.json_create(x) # => 1..4
+ # Range.json_create(y) # => 1...4
+ # Range.json_create(z) # => "a".."d"
+ #
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'a' => [ first, last, exclude_end? ]
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/range'
+ # puts (1..4).to_json
+ # puts (1...4).to_json
+ # puts ('a'..'d').to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Range","a":[1,4,false]}
+ # {"json_class":"Range","a":[1,4,true]}
+ # {"json_class":"Range","a":["a","d",false]}
+ #
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/add/rational.rb b/ext/json/lib/json/add/rational.rb
new file mode 100644
index 0000000000..c95812ea8e
--- /dev/null
+++ b/ext/json/lib/json/add/rational.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+class Rational
+
+ # See #as_json.
+ def self.json_create(object)
+ Rational(object['n'], object['d'])
+ end
+
+ # Methods <tt>Rational#as_json</tt> and +Rational.json_create+ may be used
+ # to serialize and deserialize a \Rational object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Rational#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/rational'
+ # x = Rational(2, 3).as_json
+ # # => {"json_class"=>"Rational", "n"=>2, "d"=>3}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Rational object:
+ #
+ # Rational.json_create(x)
+ # # => (2/3)
+ #
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'n' => numerator,
+ 'd' => denominator,
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/rational'
+ # puts Rational(2, 3).to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Rational","n":2,"d":3}
+ #
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/add/regexp.rb b/ext/json/lib/json/add/regexp.rb
new file mode 100644
index 0000000000..aebfb2db5c
--- /dev/null
+++ b/ext/json/lib/json/add/regexp.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+class Regexp
+
+ # See #as_json.
+ def self.json_create(object)
+ new(object['s'], object['o'])
+ end
+
+ # Methods <tt>Regexp#as_json</tt> and +Regexp.json_create+ may be used
+ # to serialize and deserialize a \Regexp object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Regexp#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/regexp'
+ # x = /foo/.as_json
+ # # => {"json_class"=>"Regexp", "o"=>0, "s"=>"foo"}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Regexp object:
+ #
+ # Regexp.json_create(x) # => /foo/
+ #
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'o' => options,
+ 's' => source,
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/regexp'
+ # puts /foo/.to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Regexp","o":0,"s":"foo"}
+ #
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/add/set.rb b/ext/json/lib/json/add/set.rb
new file mode 100644
index 0000000000..1918353187
--- /dev/null
+++ b/ext/json/lib/json/add/set.rb
@@ -0,0 +1,48 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+defined?(::Set) or require 'set'
+
+class Set
+
+ # See #as_json.
+ def self.json_create(object)
+ new object['a']
+ end
+
+ # Methods <tt>Set#as_json</tt> and +Set.json_create+ may be used
+ # to serialize and deserialize a \Set object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Set#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/set'
+ # x = Set.new(%w/foo bar baz/).as_json
+ # # => {"json_class"=>"Set", "a"=>["foo", "bar", "baz"]}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Set object:
+ #
+ # Set.json_create(x) # => #<Set: {"foo", "bar", "baz"}>
+ #
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'a' => to_a,
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/set'
+ # puts Set.new(%w/foo bar baz/).to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Set","a":["foo","bar","baz"]}
+ #
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
+
diff --git a/ext/json/lib/json/add/string.rb b/ext/json/lib/json/add/string.rb
new file mode 100644
index 0000000000..9c3bde27fb
--- /dev/null
+++ b/ext/json/lib/json/add/string.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+class String
+ # call-seq: json_create(o)
+ #
+ # Raw Strings are JSON Objects (the raw bytes are stored in an array for the
+ # key "raw"). The Ruby String can be created by this class method.
+ def self.json_create(object)
+ object["raw"].pack("C*")
+ end
+
+ # call-seq: to_json_raw_object()
+ #
+ # This method creates a raw object hash, that can be nested into
+ # other data structures and will be generated as a raw string. This
+ # method should be used, if you want to convert raw strings to JSON
+ # instead of UTF-8 strings, e. g. binary data.
+ def to_json_raw_object
+ {
+ JSON.create_id => self.class.name,
+ "raw" => unpack("C*"),
+ }
+ end
+
+ # call-seq: to_json_raw(*args)
+ #
+ # This method creates a JSON text from the result of a call to
+ # to_json_raw_object of this String.
+ def to_json_raw(...)
+ to_json_raw_object.to_json(...)
+ end
+end
diff --git a/ext/json/lib/json/add/struct.rb b/ext/json/lib/json/add/struct.rb
new file mode 100644
index 0000000000..6760c3d86c
--- /dev/null
+++ b/ext/json/lib/json/add/struct.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+class Struct
+
+ # See #as_json.
+ def self.json_create(object)
+ new(*object['v'])
+ end
+
+ # Methods <tt>Struct#as_json</tt> and +Struct.json_create+ may be used
+ # to serialize and deserialize a \Struct object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Struct#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/struct'
+ # Customer = Struct.new('Customer', :name, :address, :zip)
+ # x = Struct::Customer.new.as_json
+ # # => {"json_class"=>"Struct::Customer", "v"=>[nil, nil, nil]}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Struct object:
+ #
+ # Struct::Customer.json_create(x)
+ # # => #<struct Struct::Customer name=nil, address=nil, zip=nil>
+ #
+ def as_json(*)
+ klass = self.class.name
+ klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
+ {
+ JSON.create_id => klass,
+ 'v' => values,
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/struct'
+ # Customer = Struct.new('Customer', :name, :address, :zip)
+ # puts Struct::Customer.new.to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Struct","t":{'name':'Rowdy',"age":null}}
+ #
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/add/symbol.rb b/ext/json/lib/json/add/symbol.rb
new file mode 100644
index 0000000000..806be4f025
--- /dev/null
+++ b/ext/json/lib/json/add/symbol.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+class Symbol
+
+ # Methods <tt>Symbol#as_json</tt> and +Symbol.json_create+ may be used
+ # to serialize and deserialize a \Symbol object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Symbol#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/symbol'
+ # x = :foo.as_json
+ # # => {"json_class"=>"Symbol", "s"=>"foo"}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Symbol object:
+ #
+ # Symbol.json_create(x) # => :foo
+ #
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 's' => to_s,
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/symbol'
+ # puts :foo.to_json
+ #
+ # Output:
+ #
+ # # {"json_class":"Symbol","s":"foo"}
+ #
+ def to_json(state = nil, *a)
+ state = ::JSON::State.from_state(state)
+ if state.strict?
+ super
+ else
+ as_json.to_json(state, *a)
+ end
+ end
+
+ # See #as_json.
+ def self.json_create(o)
+ o['s'].to_sym
+ end
+end
diff --git a/ext/json/lib/json/add/time.rb b/ext/json/lib/json/add/time.rb
new file mode 100644
index 0000000000..b03d4ff251
--- /dev/null
+++ b/ext/json/lib/json/add/time.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+class Time
+
+ # See #as_json.
+ def self.json_create(object)
+ if usec = object.delete('u') # used to be tv_usec -> tv_nsec
+ object['n'] = usec * 1000
+ end
+ at(object['s'], Rational(object['n'], 1000))
+ end
+
+ # Methods <tt>Time#as_json</tt> and +Time.json_create+ may be used
+ # to serialize and deserialize a \Time object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Time#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/time'
+ # x = Time.now.as_json
+ # # => {"json_class"=>"Time", "s"=>1700931656, "n"=>472846644}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Time object:
+ #
+ # Time.json_create(x)
+ # # => 2023-11-25 11:00:56.472846644 -0600
+ #
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 's' => tv_sec,
+ 'n' => tv_nsec,
+ }
+ end
+
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/time'
+ # puts Time.now.to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Time","s":1700931678,"n":980650786}
+ #
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb
new file mode 100644
index 0000000000..230bf08012
--- /dev/null
+++ b/ext/json/lib/json/common.rb
@@ -0,0 +1,1173 @@
+# frozen_string_literal: true
+
+require 'json/version'
+
+module JSON
+ autoload :GenericObject, 'json/generic_object'
+
+ module ParserOptions # :nodoc:
+ class << self
+ def prepare(opts)
+ if opts[:object_class] || opts[:array_class]
+ opts = opts.dup
+ on_load = opts[:on_load]
+
+ on_load = object_class_proc(opts[:object_class], on_load) if opts[:object_class]
+ on_load = array_class_proc(opts[:array_class], on_load) if opts[:array_class]
+ opts[:on_load] = on_load
+ end
+
+ if opts.fetch(:create_additions, false) != false
+ opts = create_additions_proc(opts)
+ end
+
+ opts
+ end
+
+ private
+
+ def object_class_proc(object_class, on_load)
+ ->(obj) do
+ if Hash === obj
+ object = object_class.new
+ obj.each { |k, v| object[k] = v }
+ obj = object
+ end
+ on_load.nil? ? obj : on_load.call(obj)
+ end
+ end
+
+ def array_class_proc(array_class, on_load)
+ ->(obj) do
+ if Array === obj
+ array = array_class.new
+ obj.each { |v| array << v }
+ obj = array
+ end
+ on_load.nil? ? obj : on_load.call(obj)
+ end
+ end
+
+ # TODO: extract :create_additions support to another gem for version 3.0
+ def create_additions_proc(opts)
+ if opts[:symbolize_names]
+ raise ArgumentError, "options :symbolize_names and :create_additions cannot be used in conjunction"
+ end
+
+ opts = opts.dup
+ create_additions = opts.fetch(:create_additions, false)
+ on_load = opts[:on_load]
+ object_class = opts[:object_class] || Hash
+
+ opts[:on_load] = ->(object) do
+ case object
+ when String
+ opts[:match_string]&.each do |pattern, klass|
+ if match = pattern.match(object)
+ create_additions_warning if create_additions.nil?
+ object = klass.json_create(object)
+ break
+ end
+ end
+ when object_class
+ if opts[:create_additions] != false
+ if class_path = object[JSON.create_id]
+ klass = begin
+ Object.const_get(class_path)
+ rescue NameError => e
+ raise ArgumentError, "can't get const #{class_path}: #{e}"
+ end
+
+ if klass.respond_to?(:json_creatable?) ? klass.json_creatable? : klass.respond_to?(:json_create)
+ create_additions_warning if create_additions.nil?
+ object = klass.json_create(object)
+ end
+ end
+ end
+ end
+
+ on_load.nil? ? object : on_load.call(object)
+ end
+
+ opts
+ end
+
+ def create_additions_warning
+ JSON.deprecation_warning "JSON.load implicit support for `create_additions: true` is deprecated " \
+ "and will be removed in 3.0, use JSON.unsafe_load or explicitly " \
+ "pass `create_additions: true`"
+ end
+ end
+ end
+
+ class << self
+ def deprecation_warning(message, uplevel = 3) # :nodoc:
+ gem_root = File.expand_path("..", __dir__) + "/"
+ caller_locations(uplevel, 10).each do |frame|
+ if frame.path.nil? || frame.path.start_with?(gem_root) || frame.path.end_with?("/truffle/cext_ruby.rb", ".c")
+ uplevel += 1
+ else
+ break
+ end
+ end
+
+ if RUBY_VERSION >= "3.0"
+ warn(message, uplevel: uplevel, category: :deprecated)
+ else
+ warn(message, uplevel: uplevel)
+ end
+ end
+
+ # :call-seq:
+ # JSON[object] -> new_array or new_string
+ #
+ # If +object+ is a \String,
+ # calls JSON.parse with +object+ and +opts+ (see method #parse):
+ # json = '[0, 1, null]'
+ # JSON[json]# => [0, 1, nil]
+ #
+ # Otherwise, calls JSON.generate with +object+ and +opts+ (see method #generate):
+ # ruby = [0, 1, nil]
+ # JSON[ruby] # => '[0,1,null]'
+ def [](object, opts = nil)
+ if object.is_a?(String)
+ return JSON.parse(object, opts)
+ elsif object.respond_to?(:to_str)
+ str = object.to_str
+ if str.is_a?(String)
+ return JSON.parse(str, opts)
+ end
+ end
+
+ JSON.generate(object, opts)
+ end
+
+ # Returns the JSON parser class that is used by JSON.
+ attr_reader :parser
+
+ # Set the JSON parser class _parser_ to be used by JSON.
+ def parser=(parser) # :nodoc:
+ @parser = parser
+ remove_const :Parser if const_defined?(:Parser, false)
+ const_set :Parser, parser
+ end
+
+ # Set the module _generator_ to be used by JSON.
+ def generator=(generator) # :nodoc:
+ old, $VERBOSE = $VERBOSE, nil
+ @generator = generator
+ if generator.const_defined?(:GeneratorMethods)
+ generator_methods = generator::GeneratorMethods
+ for const in generator_methods.constants
+ klass = const_get(const)
+ modul = generator_methods.const_get(const)
+ klass.class_eval do
+ instance_methods(false).each do |m|
+ m.to_s == 'to_json' and remove_method m
+ end
+ include modul
+ end
+ end
+ end
+ self.state = generator::State
+ const_set :State, state
+ ensure
+ $VERBOSE = old
+ end
+
+ # Returns the JSON generator module that is used by JSON.
+ attr_reader :generator
+
+ # Sets or Returns the JSON generator state class that is used by JSON.
+ attr_accessor :state
+
+ private
+
+ # Called from the extension when a hash has both string and symbol keys
+ def on_mixed_keys_hash(hash, do_raise)
+ set = {}
+ hash.each_key do |key|
+ key_str = key.to_s
+
+ if set[key_str]
+ message = "detected duplicate key #{key_str.inspect} in #{hash.inspect}"
+ if do_raise
+ raise GeneratorError, message
+ else
+ deprecation_warning("#{message}.\nThis will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`")
+ end
+ else
+ set[key_str] = true
+ end
+ end
+ end
+
+ def deprecated_singleton_attr_accessor(*attrs)
+ args = RUBY_VERSION >= "3.0" ? ", category: :deprecated" : ""
+ attrs.each do |attr|
+ singleton_class.class_eval <<~RUBY
+ def #{attr}
+ warn "JSON.#{attr} is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args}
+ @#{attr}
+ end
+
+ def #{attr}=(val)
+ warn "JSON.#{attr}= is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args}
+ @#{attr} = val
+ end
+
+ def _#{attr}
+ @#{attr}
+ end
+ RUBY
+ end
+ end
+ end
+
+ # Sets create identifier, which is used to decide if the _json_create_
+ # hook of a class should be called; initial value is +json_class+:
+ # JSON.create_id # => 'json_class'
+ def self.create_id=(new_value)
+ Thread.current[:"JSON.create_id"] = new_value.dup.freeze
+ end
+
+ # Returns the current create identifier.
+ # See also JSON.create_id=.
+ def self.create_id
+ Thread.current[:"JSON.create_id"] || 'json_class'
+ end
+
+ NaN = Float::NAN
+
+ Infinity = Float::INFINITY
+
+ MinusInfinity = -Infinity
+
+ # The base exception for JSON errors.
+ class JSONError < StandardError; end
+
+ # This exception is raised if a parser error occurs.
+ class ParserError < JSONError
+ attr_reader :line, :column
+ end
+
+ # This exception is raised if the nesting of parsed data structures is too
+ # deep.
+ class NestingError < ParserError; end
+
+ # This exception is raised if a generator or unparser error occurs.
+ class GeneratorError < JSONError
+ attr_reader :invalid_object
+
+ def initialize(message, invalid_object = nil)
+ super(message)
+ @invalid_object = invalid_object
+ end
+
+ def detailed_message(...)
+ # Exception#detailed_message doesn't exist until Ruby 3.2
+ super_message = defined?(super) ? super : message
+
+ if @invalid_object.nil?
+ super_message
+ else
+ "#{super_message}\nInvalid object: #{@invalid_object.inspect}"
+ end
+ end
+ end
+
+ # Fragment of JSON document that is to be included as is:
+ # fragment = JSON::Fragment.new("[1, 2, 3]")
+ # JSON.generate({ count: 3, items: fragments })
+ #
+ # This allows to easily assemble multiple JSON fragments that have
+ # been persisted somewhere without having to parse them nor resorting
+ # to string interpolation.
+ #
+ # Note: no validation is performed on the provided string. It is the
+ # responsibility of the caller to ensure the string contains valid JSON.
+ Fragment = Struct.new(:json) do
+ def initialize(json)
+ unless string = String.try_convert(json)
+ raise TypeError, " no implicit conversion of #{json.class} into String"
+ end
+
+ super(string)
+ end
+
+ def to_json(state = nil, *)
+ json
+ end
+ end
+
+ module_function
+
+ # :call-seq:
+ # JSON.parse(source, opts) -> object
+ #
+ # Returns the Ruby objects created by parsing the given +source+.
+ #
+ # Argument +source+ contains the \String to be parsed.
+ #
+ # Argument +opts+, if given, contains a \Hash of options for the parsing.
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options].
+ #
+ # ---
+ #
+ # When +source+ is a \JSON array, returns a Ruby \Array:
+ # source = '["foo", 1.0, true, false, null]'
+ # ruby = JSON.parse(source)
+ # ruby # => ["foo", 1.0, true, false, nil]
+ # ruby.class # => Array
+ #
+ # When +source+ is a \JSON object, returns a Ruby \Hash:
+ # source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
+ # ruby = JSON.parse(source)
+ # ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
+ # ruby.class # => Hash
+ #
+ # For examples of parsing for all \JSON data types, see
+ # {Parsing \JSON}[#module-JSON-label-Parsing+JSON].
+ #
+ # Parses nested JSON objects:
+ # source = <<~JSON
+ # {
+ # "name": "Dave",
+ # "age" :40,
+ # "hats": [
+ # "Cattleman's",
+ # "Panama",
+ # "Tophat"
+ # ]
+ # }
+ # JSON
+ # ruby = JSON.parse(source)
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # ---
+ #
+ # Raises an exception if +source+ is not valid JSON:
+ # # Raises JSON::ParserError (783: unexpected token at ''):
+ # JSON.parse('')
+ #
+ def parse(source, opts = nil)
+ opts = ParserOptions.prepare(opts) unless opts.nil?
+ Parser.parse(source, opts)
+ end
+
+ PARSE_L_OPTIONS = {
+ max_nesting: false,
+ allow_nan: true,
+ }.freeze
+ private_constant :PARSE_L_OPTIONS
+
+ # :call-seq:
+ # JSON.parse!(source, opts) -> object
+ #
+ # Calls
+ # parse(source, opts)
+ # with +source+ and possibly modified +opts+.
+ #
+ # Differences from JSON.parse:
+ # - Option +max_nesting+, if not provided, defaults to +false+,
+ # which disables checking for nesting depth.
+ # - Option +allow_nan+, if not provided, defaults to +true+.
+ def parse!(source, opts = nil)
+ if opts.nil?
+ parse(source, PARSE_L_OPTIONS)
+ else
+ parse(source, PARSE_L_OPTIONS.merge(opts))
+ end
+ end
+
+ # :call-seq:
+ # JSON.load_file(path, opts={}) -> object
+ #
+ # Calls:
+ # parse(File.read(path), opts)
+ #
+ # See method #parse.
+ def load_file(filespec, opts = nil)
+ parse(File.read(filespec, encoding: Encoding::UTF_8), opts)
+ end
+
+ # :call-seq:
+ # JSON.load_file!(path, opts = {})
+ #
+ # Calls:
+ # JSON.parse!(File.read(path, opts))
+ #
+ # See method #parse!
+ def load_file!(filespec, opts = nil)
+ parse!(File.read(filespec, encoding: Encoding::UTF_8), opts)
+ end
+
+ # :call-seq:
+ # JSON.generate(obj, opts = nil) -> new_string
+ #
+ # Returns a \String containing the generated \JSON data.
+ #
+ # See also JSON.pretty_generate.
+ #
+ # Argument +obj+ is the Ruby object to be converted to \JSON.
+ #
+ # Argument +opts+, if given, contains a \Hash of options for the generation.
+ # See {Generating Options}[#module-JSON-label-Generating+Options].
+ #
+ # ---
+ #
+ # When +obj+ is an \Array, returns a \String containing a \JSON array:
+ # obj = ["foo", 1.0, true, false, nil]
+ # json = JSON.generate(obj)
+ # json # => '["foo",1.0,true,false,null]'
+ #
+ # When +obj+ is a \Hash, returns a \String containing a \JSON object:
+ # obj = {foo: 0, bar: 's', baz: :bat}
+ # json = JSON.generate(obj)
+ # json # => '{"foo":0,"bar":"s","baz":"bat"}'
+ #
+ # For examples of generating from other Ruby objects, see
+ # {Generating \JSON from Other Objects}[#module-JSON-label-Generating+JSON+from+Other+Objects].
+ #
+ # ---
+ #
+ # Raises an exception if any formatting option is not a \String.
+ #
+ # Raises an exception if +obj+ contains circular references:
+ # a = []; b = []; a.push(b); b.push(a)
+ # # Raises JSON::NestingError (nesting of 100 is too deep):
+ # JSON.generate(a)
+ #
+ def generate(obj, opts = nil)
+ if State === opts
+ opts.generate(obj)
+ else
+ State.generate(obj, opts, nil)
+ end
+ end
+
+ # :call-seq:
+ # JSON.fast_generate(obj, opts) -> new_string
+ #
+ # Arguments +obj+ and +opts+ here are the same as
+ # arguments +obj+ and +opts+ in JSON.generate.
+ #
+ # By default, generates \JSON data without checking
+ # for circular references in +obj+ (option +max_nesting+ set to +false+, disabled).
+ #
+ # Raises an exception if +obj+ contains circular references:
+ # a = []; b = []; a.push(b); b.push(a)
+ # # Raises SystemStackError (stack level too deep):
+ # JSON.fast_generate(a)
+ def fast_generate(obj, opts = nil)
+ if RUBY_VERSION >= "3.0"
+ warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
+ else
+ warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
+ end
+ generate(obj, opts)
+ end
+
+ PRETTY_GENERATE_OPTIONS = {
+ indent: ' ',
+ space: ' ',
+ object_nl: "\n",
+ array_nl: "\n",
+ }.freeze
+ private_constant :PRETTY_GENERATE_OPTIONS
+
+ # :call-seq:
+ # JSON.pretty_generate(obj, opts = nil) -> new_string
+ #
+ # Arguments +obj+ and +opts+ here are the same as
+ # arguments +obj+ and +opts+ in JSON.generate.
+ #
+ # Default options are:
+ # {
+ # indent: ' ', # Two spaces
+ # space: ' ', # One space
+ # array_nl: "\n", # Newline
+ # object_nl: "\n" # Newline
+ # }
+ #
+ # Example:
+ # obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
+ # json = JSON.pretty_generate(obj)
+ # puts json
+ # Output:
+ # {
+ # "foo": [
+ # "bar",
+ # "baz"
+ # ],
+ # "bat": {
+ # "bam": 0,
+ # "bad": 1
+ # }
+ # }
+ #
+ def pretty_generate(obj, opts = nil)
+ return opts.generate(obj) if State === opts
+
+ options = PRETTY_GENERATE_OPTIONS
+
+ if opts
+ unless opts.is_a?(Hash)
+ if opts.respond_to? :to_hash
+ opts = opts.to_hash
+ elsif opts.respond_to? :to_h
+ opts = opts.to_h
+ else
+ raise TypeError, "can't convert #{opts.class} into Hash"
+ end
+ end
+ options = options.merge(opts)
+ end
+
+ State.generate(obj, options, nil)
+ end
+
+ # Sets or returns default options for the JSON.unsafe_load method.
+ # Initially:
+ # opts = JSON.load_default_options
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
+ deprecated_singleton_attr_accessor :unsafe_load_default_options
+
+ @unsafe_load_default_options = {
+ :max_nesting => false,
+ :allow_nan => true,
+ :allow_blank => true,
+ :create_additions => true,
+ }
+
+ # Sets or returns default options for the JSON.load method.
+ # Initially:
+ # opts = JSON.load_default_options
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
+ deprecated_singleton_attr_accessor :load_default_options
+
+ @load_default_options = {
+ :allow_nan => true,
+ :allow_blank => true,
+ :create_additions => nil,
+ }
+ # :call-seq:
+ # JSON.unsafe_load(source, options = {}) -> object
+ # JSON.unsafe_load(source, proc = nil, options = {}) -> object
+ #
+ # Returns the Ruby objects created by parsing the given +source+.
+ #
+ # BEWARE: This method is meant to serialise data from trusted user input,
+ # like from your own database server or clients under your control, it could
+ # be dangerous to allow untrusted users to pass JSON sources into it.
+ #
+ # - Argument +source+ must be, or be convertible to, a \String:
+ # - If +source+ responds to instance method +to_str+,
+ # <tt>source.to_str</tt> becomes the source.
+ # - If +source+ responds to instance method +to_io+,
+ # <tt>source.to_io.read</tt> becomes the source.
+ # - If +source+ responds to instance method +read+,
+ # <tt>source.read</tt> becomes the source.
+ # - If both of the following are true, source becomes the \String <tt>'null'</tt>:
+ # - Option +allow_blank+ specifies a truthy value.
+ # - The source, as defined above, is +nil+ or the empty \String <tt>''</tt>.
+ # - Otherwise, +source+ remains the source.
+ # - Argument +proc+, if given, must be a \Proc that accepts one argument.
+ # It will be called recursively with each result (depth-first order).
+ # See details below.
+ # - Argument +opts+, if given, contains a \Hash of options for the parsing.
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options].
+ # The default options can be changed via method JSON.unsafe_load_default_options=.
+ #
+ # ---
+ #
+ # When no +proc+ is given, modifies +source+ as above and returns the result of
+ # <tt>parse(source, opts)</tt>; see #parse.
+ #
+ # Source for following examples:
+ # source = <<~JSON
+ # {
+ # "name": "Dave",
+ # "age" :40,
+ # "hats": [
+ # "Cattleman's",
+ # "Panama",
+ # "Tophat"
+ # ]
+ # }
+ # JSON
+ #
+ # Load a \String:
+ # ruby = JSON.unsafe_load(source)
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # Load an \IO object:
+ # require 'stringio'
+ # object = JSON.unsafe_load(StringIO.new(source))
+ # object # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # Load a \File object:
+ # path = 't.json'
+ # File.write(path, source)
+ # File.open(path) do |file|
+ # JSON.unsafe_load(file)
+ # end # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # ---
+ #
+ # When +proc+ is given:
+ # - Modifies +source+ as above.
+ # - Gets the +result+ from calling <tt>parse(source, opts)</tt>.
+ # - Recursively calls <tt>proc(result)</tt>.
+ # - Returns the final result.
+ #
+ # Example:
+ # require 'json'
+ #
+ # # Some classes for the example.
+ # class Base
+ # def initialize(attributes)
+ # @attributes = attributes
+ # end
+ # end
+ # class User < Base; end
+ # class Account < Base; end
+ # class Admin < Base; end
+ # # The JSON source.
+ # json = <<-EOF
+ # {
+ # "users": [
+ # {"type": "User", "username": "jane", "email": "jane@example.com"},
+ # {"type": "User", "username": "john", "email": "john@example.com"}
+ # ],
+ # "accounts": [
+ # {"account": {"type": "Account", "paid": true, "account_id": "1234"}},
+ # {"account": {"type": "Account", "paid": false, "account_id": "1235"}}
+ # ],
+ # "admins": {"type": "Admin", "password": "0wn3d"}
+ # }
+ # EOF
+ # # Deserializer method.
+ # def deserialize_obj(obj, safe_types = %w(User Account Admin))
+ # type = obj.is_a?(Hash) && obj["type"]
+ # safe_types.include?(type) ? Object.const_get(type).new(obj) : obj
+ # end
+ # # Call to JSON.unsafe_load
+ # ruby = JSON.unsafe_load(json, proc {|obj|
+ # case obj
+ # when Hash
+ # obj.each {|k, v| obj[k] = deserialize_obj v }
+ # when Array
+ # obj.map! {|v| deserialize_obj v }
+ # end
+ # obj
+ # })
+ # pp ruby
+ # Output:
+ # {"users"=>
+ # [#<User:0x00000000064c4c98
+ # @attributes=
+ # {"type"=>"User", "username"=>"jane", "email"=>"jane@example.com"}>,
+ # #<User:0x00000000064c4bd0
+ # @attributes=
+ # {"type"=>"User", "username"=>"john", "email"=>"john@example.com"}>],
+ # "accounts"=>
+ # [{"account"=>
+ # #<Account:0x00000000064c4928
+ # @attributes={"type"=>"Account", "paid"=>true, "account_id"=>"1234"}>},
+ # {"account"=>
+ # #<Account:0x00000000064c4680
+ # @attributes={"type"=>"Account", "paid"=>false, "account_id"=>"1235"}>}],
+ # "admins"=>
+ # #<Admin:0x00000000064c41f8
+ # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
+ #
+ def unsafe_load(source, proc = nil, options = nil)
+ opts = if options.nil?
+ if proc && proc.is_a?(Hash)
+ options, proc = proc, nil
+ options
+ else
+ _unsafe_load_default_options
+ end
+ else
+ _unsafe_load_default_options.merge(options)
+ end
+
+ unless source.is_a?(String)
+ if source.respond_to? :to_str
+ source = source.to_str
+ elsif source.respond_to? :to_io
+ source = source.to_io.read
+ elsif source.respond_to?(:read)
+ source = source.read
+ end
+ end
+
+ if opts[:allow_blank] && (source.nil? || source.empty?)
+ source = 'null'
+ end
+
+ if proc
+ opts = opts.dup
+ opts[:on_load] = proc.to_proc
+ end
+
+ parse(source, opts)
+ end
+
+ # :call-seq:
+ # JSON.load(source, options = {}) -> object
+ # JSON.load(source, proc = nil, options = {}) -> object
+ #
+ # Returns the Ruby objects created by parsing the given +source+.
+ #
+ # BEWARE: This method is meant to serialise data from trusted user input,
+ # like from your own database server or clients under your control, it could
+ # be dangerous to allow untrusted users to pass JSON sources into it.
+ # If you must use it, use JSON.unsafe_load instead to make it clear.
+ #
+ # Since JSON version 2.8.0, `load` emits a deprecation warning when a
+ # non native type is deserialized, without `create_additions` being explicitly
+ # enabled, and in JSON version 3.0, `load` will have `create_additions` disabled
+ # by default.
+ #
+ # - Argument +source+ must be, or be convertible to, a \String:
+ # - If +source+ responds to instance method +to_str+,
+ # <tt>source.to_str</tt> becomes the source.
+ # - If +source+ responds to instance method +to_io+,
+ # <tt>source.to_io.read</tt> becomes the source.
+ # - If +source+ responds to instance method +read+,
+ # <tt>source.read</tt> becomes the source.
+ # - If both of the following are true, source becomes the \String <tt>'null'</tt>:
+ # - Option +allow_blank+ specifies a truthy value.
+ # - The source, as defined above, is +nil+ or the empty \String <tt>''</tt>.
+ # - Otherwise, +source+ remains the source.
+ # - Argument +proc+, if given, must be a \Proc that accepts one argument.
+ # It will be called recursively with each result (depth-first order).
+ # See details below.
+ # - Argument +opts+, if given, contains a \Hash of options for the parsing.
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options].
+ # The default options can be changed via method JSON.load_default_options=.
+ #
+ # ---
+ #
+ # When no +proc+ is given, modifies +source+ as above and returns the result of
+ # <tt>parse(source, opts)</tt>; see #parse.
+ #
+ # Source for following examples:
+ # source = <<~JSON
+ # {
+ # "name": "Dave",
+ # "age" :40,
+ # "hats": [
+ # "Cattleman's",
+ # "Panama",
+ # "Tophat"
+ # ]
+ # }
+ # JSON
+ #
+ # Load a \String:
+ # ruby = JSON.load(source)
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # Load an \IO object:
+ # require 'stringio'
+ # object = JSON.load(StringIO.new(source))
+ # object # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # Load a \File object:
+ # path = 't.json'
+ # File.write(path, source)
+ # File.open(path) do |file|
+ # JSON.load(file)
+ # end # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # ---
+ #
+ # When +proc+ is given:
+ # - Modifies +source+ as above.
+ # - Gets the +result+ from calling <tt>parse(source, opts)</tt>.
+ # - Recursively calls <tt>proc(result)</tt>.
+ # - Returns the final result.
+ #
+ # Example:
+ # require 'json'
+ #
+ # # Some classes for the example.
+ # class Base
+ # def initialize(attributes)
+ # @attributes = attributes
+ # end
+ # end
+ # class User < Base; end
+ # class Account < Base; end
+ # class Admin < Base; end
+ # # The JSON source.
+ # json = <<-EOF
+ # {
+ # "users": [
+ # {"type": "User", "username": "jane", "email": "jane@example.com"},
+ # {"type": "User", "username": "john", "email": "john@example.com"}
+ # ],
+ # "accounts": [
+ # {"account": {"type": "Account", "paid": true, "account_id": "1234"}},
+ # {"account": {"type": "Account", "paid": false, "account_id": "1235"}}
+ # ],
+ # "admins": {"type": "Admin", "password": "0wn3d"}
+ # }
+ # EOF
+ # # Deserializer method.
+ # def deserialize_obj(obj, safe_types = %w(User Account Admin))
+ # type = obj.is_a?(Hash) && obj["type"]
+ # safe_types.include?(type) ? Object.const_get(type).new(obj) : obj
+ # end
+ # # Call to JSON.load
+ # ruby = JSON.load(json, proc {|obj|
+ # case obj
+ # when Hash
+ # obj.each {|k, v| obj[k] = deserialize_obj v }
+ # when Array
+ # obj.map! {|v| deserialize_obj v }
+ # end
+ # obj
+ # })
+ # pp ruby
+ # Output:
+ # {"users"=>
+ # [#<User:0x00000000064c4c98
+ # @attributes=
+ # {"type"=>"User", "username"=>"jane", "email"=>"jane@example.com"}>,
+ # #<User:0x00000000064c4bd0
+ # @attributes=
+ # {"type"=>"User", "username"=>"john", "email"=>"john@example.com"}>],
+ # "accounts"=>
+ # [{"account"=>
+ # #<Account:0x00000000064c4928
+ # @attributes={"type"=>"Account", "paid"=>true, "account_id"=>"1234"}>},
+ # {"account"=>
+ # #<Account:0x00000000064c4680
+ # @attributes={"type"=>"Account", "paid"=>false, "account_id"=>"1235"}>}],
+ # "admins"=>
+ # #<Admin:0x00000000064c41f8
+ # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
+ #
+ def load(source, proc = nil, options = nil)
+ if proc && options.nil? && proc.is_a?(Hash)
+ options = proc
+ proc = nil
+ end
+
+ opts = if options.nil?
+ if proc && proc.is_a?(Hash)
+ options, proc = proc, nil
+ options
+ else
+ _load_default_options
+ end
+ else
+ _load_default_options.merge(options)
+ end
+
+ unless source.is_a?(String)
+ if source.respond_to? :to_str
+ source = source.to_str
+ elsif source.respond_to? :to_io
+ source = source.to_io.read
+ elsif source.respond_to?(:read)
+ source = source.read
+ end
+ end
+
+ if opts[:allow_blank] && (source.nil? || (String === source && source.empty?))
+ source = 'null'
+ end
+
+ if proc
+ opts = opts.dup
+ opts[:on_load] = proc.to_proc
+ end
+
+ parse(source, opts)
+ end
+
+ # Sets or returns the default options for the JSON.dump method.
+ # Initially:
+ # opts = JSON.dump_default_options
+ # opts # => {:max_nesting=>false, :allow_nan=>true}
+ deprecated_singleton_attr_accessor :dump_default_options
+ @dump_default_options = {
+ :max_nesting => false,
+ :allow_nan => true,
+ }
+
+ # :call-seq:
+ # JSON.dump(obj, io = nil, limit = nil)
+ #
+ # Dumps +obj+ as a \JSON string, i.e. calls generate on the object and returns the result.
+ #
+ # The default options can be changed via method JSON.dump_default_options.
+ #
+ # - Argument +io+, if given, should respond to method +write+;
+ # the \JSON \String is written to +io+, and +io+ is returned.
+ # If +io+ is not given, the \JSON \String is returned.
+ # - Argument +limit+, if given, is passed to JSON.generate as option +max_nesting+.
+ #
+ # ---
+ #
+ # When argument +io+ is not given, returns the \JSON \String generated from +obj+:
+ # obj = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad}
+ # json = JSON.dump(obj)
+ # json # => "{\"foo\":[0,1],\"bar\":{\"baz\":2,\"bat\":3},\"bam\":\"bad\"}"
+ #
+ # When argument +io+ is given, writes the \JSON \String to +io+ and returns +io+:
+ # path = 't.json'
+ # File.open(path, 'w') do |file|
+ # JSON.dump(obj, file)
+ # end # => #<File:t.json (closed)>
+ # puts File.read(path)
+ # Output:
+ # {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
+ def dump(obj, anIO = nil, limit = nil, kwargs = nil)
+ if kwargs.nil?
+ if limit.nil?
+ if anIO.is_a?(Hash)
+ kwargs = anIO
+ anIO = nil
+ end
+ elsif limit.is_a?(Hash)
+ kwargs = limit
+ limit = nil
+ end
+ end
+
+ unless anIO.nil?
+ if anIO.respond_to?(:to_io)
+ anIO = anIO.to_io
+ elsif limit.nil? && !anIO.respond_to?(:write)
+ anIO, limit = nil, anIO
+ end
+ end
+
+ opts = JSON._dump_default_options
+ opts = opts.merge(:max_nesting => limit) if limit
+ opts = opts.merge(kwargs) if kwargs
+
+ begin
+ State.generate(obj, opts, anIO)
+ rescue JSON::NestingError
+ raise ArgumentError, "exceed depth limit"
+ end
+ end
+
+ # :stopdoc:
+ # All these were meant to be deprecated circa 2009, but were just set as undocumented
+ # so usage still exist in the wild.
+ def unparse(...)
+ if RUBY_VERSION >= "3.0"
+ warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
+ else
+ warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
+ end
+ generate(...)
+ end
+ module_function :unparse
+
+ def fast_unparse(...)
+ if RUBY_VERSION >= "3.0"
+ warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
+ else
+ warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
+ end
+ generate(...)
+ end
+ module_function :fast_unparse
+
+ def pretty_unparse(...)
+ if RUBY_VERSION >= "3.0"
+ warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1, category: :deprecated
+ else
+ warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1
+ end
+ pretty_generate(...)
+ end
+ module_function :fast_unparse
+
+ def restore(...)
+ if RUBY_VERSION >= "3.0"
+ warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1, category: :deprecated
+ else
+ warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1
+ end
+ load(...)
+ end
+ module_function :restore
+
+ class << self
+ private
+
+ def const_missing(const_name)
+ case const_name
+ when :PRETTY_STATE_PROTOTYPE
+ if RUBY_VERSION >= "3.0"
+ warn "JSON::PRETTY_STATE_PROTOTYPE is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1, category: :deprecated
+ else
+ warn "JSON::PRETTY_STATE_PROTOTYPE is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1
+ end
+ state.new(PRETTY_GENERATE_OPTIONS)
+ else
+ super
+ end
+ end
+ end
+ # :startdoc:
+
+ # JSON::Coder holds a parser and generator configuration.
+ #
+ # module MyApp
+ # JSONC_CODER = JSON::Coder.new(
+ # allow_trailing_comma: true
+ # )
+ # end
+ #
+ # MyApp::JSONC_CODER.load(document)
+ #
+ class Coder
+ # :call-seq:
+ # JSON.new(options = nil, &block)
+ #
+ # Argument +options+, if given, contains a \Hash of options for both parsing and generating.
+ # See {Parsing Options}[rdoc-ref:JSON@Parsing+Options],
+ # and {Generating Options}[rdoc-ref:JSON@Generating+Options].
+ #
+ # For generation, the <tt>strict: true</tt> option is always set. When a Ruby object with no native \JSON counterpart is
+ # encountered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
+ # \JSON counterpart:
+ #
+ # module MyApp
+ # API_JSON_CODER = JSON::Coder.new do |object|
+ # case object
+ # when Time
+ # object.iso8601(3)
+ # else
+ # object # Unknown type, will raise
+ # end
+ # end
+ # end
+ #
+ # puts MyApp::API_JSON_CODER.dump(Time.now.utc) # => "2025-01-21T08:41:44.286Z"
+ #
+ def initialize(options = nil, &as_json)
+ if options.nil?
+ options = { strict: true }
+ else
+ options = options.dup
+ options[:strict] = true
+ end
+ options[:as_json] = as_json if as_json
+
+ @state = State.new(options).freeze
+ @parser_config = Ext::Parser::Config.new(ParserOptions.prepare(options)).freeze
+ end
+
+ # call-seq:
+ # dump(object) -> String
+ # dump(object, io) -> io
+ #
+ # Serialize the given object into a \JSON document.
+ def dump(object, io = nil)
+ @state.generate(object, io)
+ end
+ alias_method :generate, :dump
+
+ # call-seq:
+ # load(string) -> Object
+ #
+ # Parse the given \JSON document and return an equivalent Ruby object.
+ def load(source)
+ @parser_config.parse(source)
+ end
+ alias_method :parse, :load
+
+ # call-seq:
+ # load(path) -> Object
+ #
+ # Parse the given \JSON document and return an equivalent Ruby object.
+ def load_file(path)
+ load(File.read(path, encoding: Encoding::UTF_8))
+ end
+ end
+
+ module GeneratorMethods
+ # call-seq: to_json(*)
+ #
+ # Converts this object into a JSON string.
+ # If this object doesn't directly maps to a JSON native type,
+ # first convert it to a string (calling #to_s), then converts
+ # it to a JSON string, and returns the result.
+ # This is a fallback, if no special method #to_json was defined for some object.
+ def to_json(state = nil, *)
+ obj = case self
+ when nil, false, true, Integer, Float, Array, Hash
+ self
+ else
+ "#{self}"
+ end
+
+ if state.nil?
+ JSON::State._generate_no_fallback(obj, nil, nil)
+ else
+ JSON::State.from_state(state)._generate_no_fallback(obj)
+ end
+ end
+ end
+end
+
+module ::Kernel
+ private
+
+ # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
+ # one line.
+ def j(*objs)
+ if RUBY_VERSION >= "3.0"
+ warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
+ else
+ warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1
+ end
+
+ objs.each do |obj|
+ puts JSON.generate(obj, :allow_nan => true, :max_nesting => false)
+ end
+ nil
+ end
+
+ # Outputs _objs_ to STDOUT as JSON strings in a pretty format, with
+ # indentation and over many lines.
+ def jj(*objs)
+ if RUBY_VERSION >= "3.0"
+ warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
+ else
+ warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1
+ end
+
+ objs.each do |obj|
+ puts JSON.pretty_generate(obj, :allow_nan => true, :max_nesting => false)
+ end
+ nil
+ end
+
+ # If _object_ is string-like, parse the string and return the parsed result as
+ # a Ruby data structure. Otherwise, generate a JSON text from the Ruby data
+ # structure object and return it.
+ #
+ # The _opts_ argument is passed through to generate/parse respectively. See
+ # generate and parse for their documentation.
+ def JSON(object, opts = nil)
+ JSON[object, opts]
+ end
+end
+
+class Object
+ include JSON::GeneratorMethods
+end
diff --git a/ext/json/lib/json/ext.rb b/ext/json/lib/json/ext.rb
new file mode 100644
index 0000000000..5bacc5e371
--- /dev/null
+++ b/ext/json/lib/json/ext.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'json/common'
+
+module JSON
+ # This module holds all the modules/classes that implement JSON's
+ # functionality as C extensions.
+ module Ext
+ class Parser
+ class << self
+ def parse(...)
+ new(...).parse
+ end
+ alias_method :parse, :parse # Allow redefinition by extensions
+ end
+
+ def initialize(source, opts = nil)
+ @source = source
+ @config = Config.new(opts)
+ end
+
+ def source
+ @source.dup
+ end
+
+ def parse
+ @config.parse(@source)
+ end
+ end
+
+ require 'json/ext/parser'
+ Ext::Parser::Config = Ext::ParserConfig
+ JSON.parser = Ext::Parser
+
+ if RUBY_ENGINE == 'truffleruby'
+ require 'json/truffle_ruby/generator'
+ JSON.generator = JSON::TruffleRuby::Generator
+ else
+ require 'json/ext/generator'
+ JSON.generator = Generator
+ end
+ end
+
+ JSON_LOADED = true unless defined?(JSON::JSON_LOADED)
+end
diff --git a/ext/json/lib/json/ext/generator/state.rb b/ext/json/lib/json/ext/generator/state.rb
new file mode 100644
index 0000000000..e4f425af6a
--- /dev/null
+++ b/ext/json/lib/json/ext/generator/state.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+module JSON
+ module Ext
+ module Generator
+ class State
+ # call-seq: new(opts = {})
+ #
+ # Instantiates a new State object, configured by _opts_.
+ #
+ # Argument +opts+, if given, contains a \Hash of options for the generation.
+ # See {Generating Options}[rdoc-ref:JSON@Generating+Options].
+ def initialize(opts = nil)
+ if opts && !opts.empty?
+ configure(opts)
+ end
+ end
+
+ # call-seq: configure(opts)
+ #
+ # Configure this State instance with the Hash _opts_, and return
+ # itself.
+ def configure(opts)
+ unless opts.is_a?(Hash)
+ if opts.respond_to?(:to_hash)
+ opts = opts.to_hash
+ elsif opts.respond_to?(:to_h)
+ opts = opts.to_h
+ else
+ raise TypeError, "can't convert #{opts.class} into Hash"
+ end
+ end
+ _configure(opts)
+ end
+
+ alias_method :merge, :configure
+
+ # call-seq: to_h
+ #
+ # Returns the configuration instance variables as a hash, that can be
+ # passed to the configure method.
+ def to_h
+ result = {
+ indent: indent,
+ space: space,
+ space_before: space_before,
+ object_nl: object_nl,
+ array_nl: array_nl,
+ as_json: as_json,
+ allow_nan: allow_nan?,
+ ascii_only: ascii_only?,
+ max_nesting: max_nesting,
+ script_safe: script_safe?,
+ strict: strict?,
+ depth: depth,
+ buffer_initial_length: buffer_initial_length,
+ }
+
+ allow_duplicate_key = allow_duplicate_key?
+ unless allow_duplicate_key.nil?
+ result[:allow_duplicate_key] = allow_duplicate_key
+ end
+
+ instance_variables.each do |iv|
+ iv = iv.to_s[1..-1]
+ result[iv.to_sym] = self[iv]
+ end
+
+ result
+ end
+
+ alias_method :to_hash, :to_h
+
+ # call-seq: [](name)
+ #
+ # Returns the value returned by method +name+.
+ def [](name)
+ ::JSON.deprecation_warning("JSON::State#[] is deprecated and will be removed in json 3.0.0")
+
+ if respond_to?(name)
+ __send__(name)
+ else
+ instance_variable_get("@#{name}") if
+ instance_variables.include?("@#{name}".to_sym) # avoid warning
+ end
+ end
+
+ # call-seq: []=(name, value)
+ #
+ # Sets the attribute name to value.
+ def []=(name, value)
+ ::JSON.deprecation_warning("JSON::State#[]= is deprecated and will be removed in json 3.0.0")
+
+ if respond_to?(name_writer = "#{name}=")
+ __send__ name_writer, value
+ else
+ instance_variable_set "@#{name}", value
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/ext/json/lib/json/generic_object.rb b/ext/json/lib/json/generic_object.rb
new file mode 100644
index 0000000000..5c8ace354b
--- /dev/null
+++ b/ext/json/lib/json/generic_object.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+begin
+ require 'ostruct'
+rescue LoadError
+ warn "JSON::GenericObject requires 'ostruct'. Please install it with `gem install ostruct`."
+end
+
+module JSON
+ class GenericObject < OpenStruct
+ class << self
+ alias [] new
+
+ def json_creatable?
+ @json_creatable
+ end
+
+ attr_writer :json_creatable
+
+ def json_create(data)
+ data = data.dup
+ data.delete JSON.create_id
+ self[data]
+ end
+
+ def from_hash(object)
+ case
+ when object.respond_to?(:to_hash)
+ result = new
+ object.to_hash.each do |key, value|
+ result[key] = from_hash(value)
+ end
+ result
+ when object.respond_to?(:to_ary)
+ object.to_ary.map { |a| from_hash(a) }
+ else
+ object
+ end
+ end
+
+ def load(source, proc = nil, opts = {})
+ result = ::JSON.load(source, proc, opts.merge(:object_class => self))
+ result.nil? ? new : result
+ end
+
+ def dump(obj, *args)
+ ::JSON.dump(obj, *args)
+ end
+ end
+ self.json_creatable = false
+
+ def to_hash
+ table
+ end
+
+ def |(other)
+ self.class[other.to_hash.merge(to_hash)]
+ end
+
+ def as_json(*)
+ { JSON.create_id => self.class.name }.merge to_hash
+ end
+
+ def to_json(*a)
+ as_json.to_json(*a)
+ end
+ end if defined?(::OpenStruct)
+end
diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb
new file mode 100644
index 0000000000..30c0a71d2f
--- /dev/null
+++ b/ext/json/lib/json/version.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+module JSON
+ VERSION = '2.19.8'
+end
diff --git a/ext/json/parser/depend b/ext/json/parser/depend
new file mode 100644
index 0000000000..d4737b1dfb
--- /dev/null
+++ b/ext/json/parser/depend
@@ -0,0 +1,182 @@
+$(OBJS): $(ruby_headers)
+parser.o: parser.c $(srcdir)/../fbuffer/fbuffer.h
+
+# AUTOGENERATED DEPENDENCIES START
+parser.o: $(RUBY_EXTCONF_H)
+parser.o: $(arch_hdrdir)/ruby/config.h
+parser.o: $(hdrdir)/ruby.h
+parser.o: $(hdrdir)/ruby/assert.h
+parser.o: $(hdrdir)/ruby/backward.h
+parser.o: $(hdrdir)/ruby/backward/2/assume.h
+parser.o: $(hdrdir)/ruby/backward/2/attributes.h
+parser.o: $(hdrdir)/ruby/backward/2/bool.h
+parser.o: $(hdrdir)/ruby/backward/2/inttypes.h
+parser.o: $(hdrdir)/ruby/backward/2/limits.h
+parser.o: $(hdrdir)/ruby/backward/2/long_long.h
+parser.o: $(hdrdir)/ruby/backward/2/stdalign.h
+parser.o: $(hdrdir)/ruby/backward/2/stdarg.h
+parser.o: $(hdrdir)/ruby/defines.h
+parser.o: $(hdrdir)/ruby/encoding.h
+parser.o: $(hdrdir)/ruby/intern.h
+parser.o: $(hdrdir)/ruby/internal/abi.h
+parser.o: $(hdrdir)/ruby/internal/anyargs.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+parser.o: $(hdrdir)/ruby/internal/assume.h
+parser.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+parser.o: $(hdrdir)/ruby/internal/attr/artificial.h
+parser.o: $(hdrdir)/ruby/internal/attr/cold.h
+parser.o: $(hdrdir)/ruby/internal/attr/const.h
+parser.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+parser.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+parser.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+parser.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+parser.o: $(hdrdir)/ruby/internal/attr/error.h
+parser.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+parser.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+parser.o: $(hdrdir)/ruby/internal/attr/format.h
+parser.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+parser.o: $(hdrdir)/ruby/internal/attr/noalias.h
+parser.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+parser.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+parser.o: $(hdrdir)/ruby/internal/attr/noinline.h
+parser.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+parser.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+parser.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+parser.o: $(hdrdir)/ruby/internal/attr/pure.h
+parser.o: $(hdrdir)/ruby/internal/attr/restrict.h
+parser.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+parser.o: $(hdrdir)/ruby/internal/attr/warning.h
+parser.o: $(hdrdir)/ruby/internal/attr/weakref.h
+parser.o: $(hdrdir)/ruby/internal/cast.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+parser.o: $(hdrdir)/ruby/internal/compiler_since.h
+parser.o: $(hdrdir)/ruby/internal/config.h
+parser.o: $(hdrdir)/ruby/internal/constant_p.h
+parser.o: $(hdrdir)/ruby/internal/core.h
+parser.o: $(hdrdir)/ruby/internal/core/rarray.h
+parser.o: $(hdrdir)/ruby/internal/core/rbasic.h
+parser.o: $(hdrdir)/ruby/internal/core/rbignum.h
+parser.o: $(hdrdir)/ruby/internal/core/rclass.h
+parser.o: $(hdrdir)/ruby/internal/core/rdata.h
+parser.o: $(hdrdir)/ruby/internal/core/rfile.h
+parser.o: $(hdrdir)/ruby/internal/core/rhash.h
+parser.o: $(hdrdir)/ruby/internal/core/robject.h
+parser.o: $(hdrdir)/ruby/internal/core/rregexp.h
+parser.o: $(hdrdir)/ruby/internal/core/rstring.h
+parser.o: $(hdrdir)/ruby/internal/core/rstruct.h
+parser.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+parser.o: $(hdrdir)/ruby/internal/ctype.h
+parser.o: $(hdrdir)/ruby/internal/dllexport.h
+parser.o: $(hdrdir)/ruby/internal/dosish.h
+parser.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+parser.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+parser.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+parser.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+parser.o: $(hdrdir)/ruby/internal/encoding/re.h
+parser.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+parser.o: $(hdrdir)/ruby/internal/encoding/string.h
+parser.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+parser.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+parser.o: $(hdrdir)/ruby/internal/error.h
+parser.o: $(hdrdir)/ruby/internal/eval.h
+parser.o: $(hdrdir)/ruby/internal/event.h
+parser.o: $(hdrdir)/ruby/internal/fl_type.h
+parser.o: $(hdrdir)/ruby/internal/gc.h
+parser.o: $(hdrdir)/ruby/internal/glob.h
+parser.o: $(hdrdir)/ruby/internal/globals.h
+parser.o: $(hdrdir)/ruby/internal/has/attribute.h
+parser.o: $(hdrdir)/ruby/internal/has/builtin.h
+parser.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+parser.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+parser.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+parser.o: $(hdrdir)/ruby/internal/has/extension.h
+parser.o: $(hdrdir)/ruby/internal/has/feature.h
+parser.o: $(hdrdir)/ruby/internal/has/warning.h
+parser.o: $(hdrdir)/ruby/internal/intern/array.h
+parser.o: $(hdrdir)/ruby/internal/intern/bignum.h
+parser.o: $(hdrdir)/ruby/internal/intern/class.h
+parser.o: $(hdrdir)/ruby/internal/intern/compar.h
+parser.o: $(hdrdir)/ruby/internal/intern/complex.h
+parser.o: $(hdrdir)/ruby/internal/intern/cont.h
+parser.o: $(hdrdir)/ruby/internal/intern/dir.h
+parser.o: $(hdrdir)/ruby/internal/intern/enum.h
+parser.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+parser.o: $(hdrdir)/ruby/internal/intern/error.h
+parser.o: $(hdrdir)/ruby/internal/intern/eval.h
+parser.o: $(hdrdir)/ruby/internal/intern/file.h
+parser.o: $(hdrdir)/ruby/internal/intern/hash.h
+parser.o: $(hdrdir)/ruby/internal/intern/io.h
+parser.o: $(hdrdir)/ruby/internal/intern/load.h
+parser.o: $(hdrdir)/ruby/internal/intern/marshal.h
+parser.o: $(hdrdir)/ruby/internal/intern/numeric.h
+parser.o: $(hdrdir)/ruby/internal/intern/object.h
+parser.o: $(hdrdir)/ruby/internal/intern/parse.h
+parser.o: $(hdrdir)/ruby/internal/intern/proc.h
+parser.o: $(hdrdir)/ruby/internal/intern/process.h
+parser.o: $(hdrdir)/ruby/internal/intern/random.h
+parser.o: $(hdrdir)/ruby/internal/intern/range.h
+parser.o: $(hdrdir)/ruby/internal/intern/rational.h
+parser.o: $(hdrdir)/ruby/internal/intern/re.h
+parser.o: $(hdrdir)/ruby/internal/intern/ruby.h
+parser.o: $(hdrdir)/ruby/internal/intern/select.h
+parser.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+parser.o: $(hdrdir)/ruby/internal/intern/set.h
+parser.o: $(hdrdir)/ruby/internal/intern/signal.h
+parser.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+parser.o: $(hdrdir)/ruby/internal/intern/string.h
+parser.o: $(hdrdir)/ruby/internal/intern/struct.h
+parser.o: $(hdrdir)/ruby/internal/intern/thread.h
+parser.o: $(hdrdir)/ruby/internal/intern/time.h
+parser.o: $(hdrdir)/ruby/internal/intern/variable.h
+parser.o: $(hdrdir)/ruby/internal/intern/vm.h
+parser.o: $(hdrdir)/ruby/internal/interpreter.h
+parser.o: $(hdrdir)/ruby/internal/iterator.h
+parser.o: $(hdrdir)/ruby/internal/memory.h
+parser.o: $(hdrdir)/ruby/internal/method.h
+parser.o: $(hdrdir)/ruby/internal/module.h
+parser.o: $(hdrdir)/ruby/internal/newobj.h
+parser.o: $(hdrdir)/ruby/internal/scan_args.h
+parser.o: $(hdrdir)/ruby/internal/special_consts.h
+parser.o: $(hdrdir)/ruby/internal/static_assert.h
+parser.o: $(hdrdir)/ruby/internal/stdalign.h
+parser.o: $(hdrdir)/ruby/internal/stdbool.h
+parser.o: $(hdrdir)/ruby/internal/stdckdint.h
+parser.o: $(hdrdir)/ruby/internal/symbol.h
+parser.o: $(hdrdir)/ruby/internal/value.h
+parser.o: $(hdrdir)/ruby/internal/value_type.h
+parser.o: $(hdrdir)/ruby/internal/variable.h
+parser.o: $(hdrdir)/ruby/internal/warning_push.h
+parser.o: $(hdrdir)/ruby/internal/xmalloc.h
+parser.o: $(hdrdir)/ruby/missing.h
+parser.o: $(hdrdir)/ruby/onigmo.h
+parser.o: $(hdrdir)/ruby/oniguruma.h
+parser.o: $(hdrdir)/ruby/ruby.h
+parser.o: $(hdrdir)/ruby/st.h
+parser.o: $(hdrdir)/ruby/subst.h
+parser.o: $(srcdir)/../fbuffer/fbuffer.h
+parser.o: $(srcdir)/../json.h
+parser.o: $(srcdir)/../simd/simd.h
+parser.o: $(srcdir)/../vendor/ryu.h
+parser.o: parser.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/json/parser/extconf.rb b/ext/json/parser/extconf.rb
new file mode 100644
index 0000000000..a9d740c755
--- /dev/null
+++ b/ext/json/parser/extconf.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+require 'mkmf'
+
+$defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
+have_func("rb_enc_interned_str", "ruby/encoding.h") # RUBY_VERSION >= 3.0
+have_func("rb_str_to_interned_str", "ruby.h") # RUBY_VERSION >= 3.0
+have_func("rb_hash_new_capa", "ruby.h") # RUBY_VERSION >= 3.2
+have_func("rb_hash_bulk_insert", "ruby.h") # Missing on TruffleRuby
+have_func("ruby_xfree_sized", "ruby.h") # RUBY_VERSION >= 4.1
+
+if RUBY_ENGINE == "ruby"
+ have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3
+end
+
+append_cflags("-std=c99")
+
+if enable_config('parser-use-simd', default=!ENV["JSON_DISABLE_SIMD"])
+ load __dir__ + "/../simd/conf.rb"
+end
+
+create_makefile 'json/ext/parser'
diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c
new file mode 100644
index 0000000000..eb7dc9aa82
--- /dev/null
+++ b/ext/json/parser/parser.c
@@ -0,0 +1,2038 @@
+#include "../json.h"
+#include "../vendor/ryu.h"
+#include "../simd/simd.h"
+
+static VALUE mJSON, eNestingError, Encoding_UTF_8;
+static VALUE CNaN, CInfinity, CMinusInfinity;
+
+static ID i_new, i_try_convert, i_uminus, i_encode;
+
+static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_allow_control_characters,
+ sym_allow_invalid_escape, sym_symbolize_names, sym_freeze, sym_decimal_class, sym_on_load,
+ sym_allow_duplicate_key;
+
+static int binary_encindex;
+static int utf8_encindex;
+
+#ifndef HAVE_RB_HASH_BULK_INSERT
+// For TruffleRuby
+static void
+rb_hash_bulk_insert(long count, const VALUE *pairs, VALUE hash)
+{
+ long index = 0;
+ while (index < count) {
+ VALUE name = pairs[index++];
+ VALUE value = pairs[index++];
+ rb_hash_aset(hash, name, value);
+ }
+ RB_GC_GUARD(hash);
+}
+#endif
+
+#ifndef HAVE_RB_HASH_NEW_CAPA
+#define rb_hash_new_capa(n) rb_hash_new()
+#endif
+
+#ifndef HAVE_RB_STR_TO_INTERNED_STR
+static VALUE rb_str_to_interned_str(VALUE str)
+{
+ return rb_funcall(rb_str_freeze(str), i_uminus, 0);
+}
+#endif
+
+/* name cache */
+
+#include <string.h>
+#include <ctype.h>
+
+// Object names are likely to be repeated, and are frozen.
+// As such we can re-use them if we keep a cache of the ones we've seen so far,
+// and save much more expensive lookups into the global fstring table.
+// This cache implementation is deliberately simple, as we're optimizing for compactness,
+// to be able to fit safely on the stack.
+// As such, binary search into a sorted array gives a good tradeoff between compactness and
+// performance.
+#define JSON_RVALUE_CACHE_CAPA 63
+typedef struct rvalue_cache_struct {
+ int length;
+ VALUE entries[JSON_RVALUE_CACHE_CAPA];
+} rvalue_cache;
+
+static rb_encoding *enc_utf8;
+
+#define JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH 55
+
+static inline VALUE build_interned_string(const char *str, const long length)
+{
+# ifdef HAVE_RB_ENC_INTERNED_STR
+ return rb_enc_interned_str(str, length, enc_utf8);
+# else
+ VALUE rstring = rb_utf8_str_new(str, length);
+ return rb_funcall(rb_str_freeze(rstring), i_uminus, 0);
+# endif
+}
+
+static inline VALUE build_symbol(const char *str, const long length)
+{
+ return rb_str_intern(build_interned_string(str, length));
+}
+
+static void rvalue_cache_insert_at(rvalue_cache *cache, int index, VALUE rstring)
+{
+ MEMMOVE(&cache->entries[index + 1], &cache->entries[index], VALUE, cache->length - index);
+ cache->length++;
+ cache->entries[index] = rstring;
+}
+
+#define rstring_cache_memcmp memcmp
+
+#if JSON_CPU_LITTLE_ENDIAN_64BITS
+#if __has_builtin(__builtin_bswap64)
+#undef rstring_cache_memcmp
+ALWAYS_INLINE(static) int rstring_cache_memcmp(const char *str, const char *rptr, const long length)
+{
+ // The libc memcmp has numerous complex optimizations, but in this particular case,
+ // we know the string is small (JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH), so being able to
+ // inline a simpler memcmp outperforms calling the libc version.
+ long i = 0;
+
+ for (; i + 8 <= length; i += 8) {
+ uint64_t a, b;
+ memcpy(&a, str + i, 8);
+ memcpy(&b, rptr + i, 8);
+ if (a != b) {
+ a = __builtin_bswap64(a);
+ b = __builtin_bswap64(b);
+ return (a < b) ? -1 : 1;
+ }
+ }
+
+ for (; i < length; i++) {
+ if (str[i] != rptr[i]) {
+ return (str[i] < rptr[i]) ? -1 : 1;
+ }
+ }
+
+ return 0;
+}
+#endif
+#endif
+
+ALWAYS_INLINE(static) int rstring_cache_cmp(const char *str, const long length, VALUE rstring)
+{
+ const char *rstring_ptr;
+ long rstring_length;
+
+ RSTRING_GETMEM(rstring, rstring_ptr, rstring_length);
+
+ if (length == rstring_length) {
+ return rstring_cache_memcmp(str, rstring_ptr, length);
+ } else {
+ return (int)(length - rstring_length);
+ }
+}
+
+ALWAYS_INLINE(static) VALUE rstring_cache_fetch(rvalue_cache *cache, const char *str, const long length)
+{
+ int low = 0;
+ int high = cache->length - 1;
+
+ while (low <= high) {
+ int mid = (high + low) >> 1;
+ VALUE entry = cache->entries[mid];
+ int cmp = rstring_cache_cmp(str, length, entry);
+
+ if (cmp == 0) {
+ return entry;
+ } else if (cmp > 0) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+
+ VALUE rstring = build_interned_string(str, length);
+
+ if (cache->length < JSON_RVALUE_CACHE_CAPA) {
+ rvalue_cache_insert_at(cache, low, rstring);
+ }
+ return rstring;
+}
+
+static VALUE rsymbol_cache_fetch(rvalue_cache *cache, const char *str, const long length)
+{
+ int low = 0;
+ int high = cache->length - 1;
+
+ while (low <= high) {
+ int mid = (high + low) >> 1;
+ VALUE entry = cache->entries[mid];
+ int cmp = rstring_cache_cmp(str, length, rb_sym2str(entry));
+
+ if (cmp == 0) {
+ return entry;
+ } else if (cmp > 0) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+
+ VALUE rsymbol = build_symbol(str, length);
+
+ if (cache->length < JSON_RVALUE_CACHE_CAPA) {
+ rvalue_cache_insert_at(cache, low, rsymbol);
+ }
+ return rsymbol;
+}
+
+/* rvalue stack */
+
+#define RVALUE_STACK_INITIAL_CAPA 128
+
+enum rvalue_stack_type {
+ RVALUE_STACK_HEAP_ALLOCATED = 0,
+ RVALUE_STACK_STACK_ALLOCATED = 1,
+};
+
+typedef struct rvalue_stack_struct {
+ enum rvalue_stack_type type;
+ long capa;
+ long head;
+ VALUE *ptr;
+} rvalue_stack;
+
+static rvalue_stack *rvalue_stack_spill(rvalue_stack *old_stack, VALUE *handle, rvalue_stack **stack_ref);
+
+static rvalue_stack *rvalue_stack_grow(rvalue_stack *stack, VALUE *handle, rvalue_stack **stack_ref)
+{
+ long required = stack->capa * 2;
+
+ if (stack->type == RVALUE_STACK_STACK_ALLOCATED) {
+ stack = rvalue_stack_spill(stack, handle, stack_ref);
+ } else {
+ JSON_SIZED_REALLOC_N(stack->ptr, VALUE, required, stack->capa);
+ stack->capa = required;
+ }
+ return stack;
+}
+
+static VALUE rvalue_stack_push(rvalue_stack *stack, VALUE value, VALUE *handle, rvalue_stack **stack_ref)
+{
+ if (RB_UNLIKELY(stack->head >= stack->capa)) {
+ stack = rvalue_stack_grow(stack, handle, stack_ref);
+ }
+ stack->ptr[stack->head] = value;
+ stack->head++;
+ return value;
+}
+
+static inline VALUE *rvalue_stack_peek(rvalue_stack *stack, long count)
+{
+ return stack->ptr + (stack->head - count);
+}
+
+static inline void rvalue_stack_pop(rvalue_stack *stack, long count)
+{
+ stack->head -= count;
+}
+
+static void rvalue_stack_mark(void *ptr)
+{
+ rvalue_stack *stack = (rvalue_stack *)ptr;
+ long index;
+ if (stack && stack->ptr) {
+ for (index = 0; index < stack->head; index++) {
+ rb_gc_mark(stack->ptr[index]);
+ }
+ }
+}
+
+static void rvalue_stack_free_buffer(rvalue_stack *stack)
+{
+ JSON_SIZED_FREE_N(stack->ptr, stack->capa);
+ stack->ptr = NULL;
+}
+
+static void rvalue_stack_free(void *ptr)
+{
+ rvalue_stack *stack = (rvalue_stack *)ptr;
+ if (stack) {
+ rvalue_stack_free_buffer(stack);
+#ifndef HAVE_RUBY_TYPED_EMBEDDABLE
+ JSON_SIZED_FREE(stack);
+#endif
+ }
+}
+
+static size_t rvalue_stack_memsize(const void *ptr)
+{
+ const rvalue_stack *stack = (const rvalue_stack *)ptr;
+ return sizeof(rvalue_stack) + sizeof(VALUE) * stack->capa;
+}
+
+static const rb_data_type_t JSON_Parser_rvalue_stack_type = {
+ .wrap_struct_name = "JSON::Ext::Parser/rvalue_stack",
+ .function = {
+ .dmark = rvalue_stack_mark,
+ .dfree = rvalue_stack_free,
+ .dsize = rvalue_stack_memsize,
+ },
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE,
+};
+
+static rvalue_stack *rvalue_stack_spill(rvalue_stack *old_stack, VALUE *handle, rvalue_stack **stack_ref)
+{
+ rvalue_stack *stack;
+ *handle = TypedData_Make_Struct(0, rvalue_stack, &JSON_Parser_rvalue_stack_type, stack);
+ *stack_ref = stack;
+ MEMCPY(stack, old_stack, rvalue_stack, 1);
+
+ stack->capa = old_stack->capa << 1;
+ stack->ptr = ALLOC_N(VALUE, stack->capa);
+ stack->type = RVALUE_STACK_HEAP_ALLOCATED;
+ MEMCPY(stack->ptr, old_stack->ptr, VALUE, old_stack->head);
+ return stack;
+}
+
+static void rvalue_stack_eagerly_release(VALUE handle)
+{
+ if (handle) {
+ rvalue_stack *stack;
+ TypedData_Get_Struct(handle, rvalue_stack, &JSON_Parser_rvalue_stack_type, stack);
+#ifdef HAVE_RUBY_TYPED_EMBEDDABLE
+ rvalue_stack_free_buffer(stack);
+#else
+ rvalue_stack_free(stack);
+ RTYPEDDATA_DATA(handle) = NULL;
+#endif
+ }
+}
+
+/* frame stack */
+
+// Iterative (non-recursive) parsing keeps an explicit stack of the containers
+// currently being built, instead of relying on the C call stack. Each frame
+// only needs enough bookkeeping to close its container: which kind it is, the
+// rvalue_stack position where its children start (so we know how many to pop),
+// and the cursor at its opening brace (used to rewind for duplicate key
+// errors). Frames hold no VALUEs, so this stack needs no GC marking; it reuses
+// the same stack-allocated-with-heap-spill strategy as the rvalue_stack so that
+// it's freed even if parsing raises.
+//
+// The lifecycle helpers below (grow/push/peek/pop/spill/free/eagerly_release
+// and the rb_data_type_t) deliberately mirror their rvalue_stack counterparts
+// -- the element type and the absence of a mark function are the only real
+// differences. Keep the two in sync: a fix to the spill/release or
+// HAVE_RUBY_TYPED_EMBEDDABLE handling in one almost certainly belongs in the
+// other.
+#define JSON_FRAME_STACK_INITIAL_CAPA 32
+
+enum json_frame_type {
+ JSON_FRAME_ROOT,
+ JSON_FRAME_ARRAY,
+ JSON_FRAME_OBJECT,
+};
+
+// Where a frame is within its container's grammar. This is the entirety of the
+// parser's "what to do next" state: json_parse_any dispatches on the top
+// frame's phase and holds no resume state in C locals, so a parse can stop at
+// any value boundary and be resumed purely from the (persistable) frame stack.
+enum json_frame_phase {
+ JSON_PHASE_VALUE, // expecting a value (document root, array element, or object value after ':')
+ JSON_PHASE_ARRAY_COMMA, // after a value: expecting ',' or the closing ']'
+ JSON_PHASE_OBJECT_KEY, // expecting a '"' key (after '{' or ',')
+ JSON_PHASE_OBJECT_COMMA, // after a value: expecting ',' or the closing '}'
+ JSON_PHASE_OBJECT_COLON, // object only: after a key, expecting ':'
+ JSON_PHASE_DONE, // root only: the document value has been parsed
+};
+
+typedef struct json_frame_struct {
+ enum json_frame_type type;
+ enum json_frame_phase phase;
+ long value_stack_head; // rvalue_stack->head when this container opened
+ const char *start_cursor; // object frames only (the '{'); NULL otherwise
+} json_frame;
+
+typedef struct json_frame_stack_struct {
+ enum rvalue_stack_type type; // shared with rvalue_stack: is ptr stack- or heap-allocated
+ long capa;
+ long head;
+ json_frame *ptr;
+} json_frame_stack;
+
+enum duplicate_key_action {
+ JSON_DEPRECATED = 0,
+ JSON_IGNORE,
+ JSON_RAISE,
+};
+
+typedef struct JSON_ParserStruct {
+ VALUE on_load_proc;
+ VALUE decimal_class;
+ ID decimal_method_id;
+ enum duplicate_key_action on_duplicate_key;
+ int max_nesting;
+ bool allow_nan;
+ bool allow_trailing_comma;
+ bool allow_control_characters;
+ bool allow_invalid_escape;
+ bool symbolize_names;
+ bool freeze;
+} JSON_ParserConfig;
+
+typedef struct JSON_ParserStateStruct {
+ VALUE *value_stack_handle;
+ VALUE *frame_stack_handle;
+ const char *start;
+ const char *cursor;
+ const char *end;
+ rvalue_stack *value_stack;
+ json_frame_stack *frames;
+ rvalue_cache name_cache;
+ int in_array;
+ int current_nesting;
+ unsigned int emitted_deprecations;
+} JSON_ParserState;
+
+static json_frame_stack *json_frame_stack_spill(json_frame_stack *old_stack, VALUE *handle, json_frame_stack **stack_ref);
+
+static json_frame_stack *json_frame_stack_grow(json_frame_stack *stack, VALUE *handle, json_frame_stack **stack_ref)
+{
+ long required = stack->capa * 2;
+
+ if (stack->type == RVALUE_STACK_STACK_ALLOCATED) {
+ stack = json_frame_stack_spill(stack, handle, stack_ref);
+ } else {
+ JSON_SIZED_REALLOC_N(stack->ptr, json_frame, required, stack->capa);
+ stack->capa = required;
+ }
+ return stack;
+}
+
+static json_frame *json_frame_stack_push(JSON_ParserState *state, json_frame frame)
+{
+ json_frame_stack *stack = state->frames;
+ if (RB_UNLIKELY(stack->head >= stack->capa)) {
+ stack = json_frame_stack_grow(stack, state->frame_stack_handle, &state->frames);
+ }
+
+ json_frame *frame_ptr = &stack->ptr[stack->head++];
+ *frame_ptr = frame;
+ return frame_ptr;
+}
+
+static inline json_frame *json_frame_stack_peek(json_frame_stack *stack)
+{
+ return &stack->ptr[stack->head - 1];
+}
+
+static inline void json_frame_stack_pop(json_frame_stack *stack)
+{
+ stack->head--;
+}
+
+static void json_frame_stack_free_buffer(json_frame_stack *stack)
+{
+ JSON_SIZED_FREE_N(stack->ptr, stack->capa);
+ stack->ptr = NULL;
+}
+
+static void json_frame_stack_free(void *ptr)
+{
+ json_frame_stack *stack = (json_frame_stack *)ptr;
+ if (stack) {
+ json_frame_stack_free_buffer(stack);
+#ifndef HAVE_RUBY_TYPED_EMBEDDABLE
+ JSON_SIZED_FREE(stack);
+#endif
+ }
+}
+
+static size_t json_frame_stack_memsize(const void *ptr)
+{
+ const json_frame_stack *stack = (const json_frame_stack *)ptr;
+ return sizeof(json_frame_stack) + sizeof(json_frame) * stack->capa;
+}
+
+static const rb_data_type_t JSON_Parser_frame_stack_type = {
+ .wrap_struct_name = "JSON::Ext::Parser/frame_stack",
+ .function = {
+ .dmark = NULL,
+ .dfree = json_frame_stack_free,
+ .dsize = json_frame_stack_memsize,
+ },
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE,
+};
+
+static json_frame_stack *json_frame_stack_spill(json_frame_stack *old_stack, VALUE *handle, json_frame_stack **stack_ref)
+{
+ json_frame_stack *stack;
+ *handle = TypedData_Make_Struct(0, json_frame_stack, &JSON_Parser_frame_stack_type, stack);
+ *stack_ref = stack;
+ MEMCPY(stack, old_stack, json_frame_stack, 1);
+
+ stack->capa = old_stack->capa << 1;
+ stack->ptr = ALLOC_N(json_frame, stack->capa);
+ stack->type = RVALUE_STACK_HEAP_ALLOCATED;
+ MEMCPY(stack->ptr, old_stack->ptr, json_frame, old_stack->head);
+ return stack;
+}
+
+static void json_frame_stack_eagerly_release(VALUE handle)
+{
+ if (handle) {
+ json_frame_stack *stack;
+ TypedData_Get_Struct(handle, json_frame_stack, &JSON_Parser_frame_stack_type, stack);
+#ifdef HAVE_RUBY_TYPED_EMBEDDABLE
+ json_frame_stack_free_buffer(stack);
+#else
+ json_frame_stack_free(stack);
+ RTYPEDDATA_DATA(handle) = NULL;
+#endif
+ }
+}
+
+static int convert_UTF32_to_UTF8(char *buf, uint32_t ch)
+{
+ int len = 1;
+ if (ch <= 0x7F) {
+ buf[0] = (char) ch;
+ } else if (ch <= 0x07FF) {
+ buf[0] = (char) ((ch >> 6) | 0xC0);
+ buf[1] = (char) ((ch & 0x3F) | 0x80);
+ len++;
+ } else if (ch <= 0xFFFF) {
+ buf[0] = (char) ((ch >> 12) | 0xE0);
+ buf[1] = (char) (((ch >> 6) & 0x3F) | 0x80);
+ buf[2] = (char) ((ch & 0x3F) | 0x80);
+ len += 2;
+ } else if (ch <= 0x1fffff) {
+ buf[0] =(char) ((ch >> 18) | 0xF0);
+ buf[1] =(char) (((ch >> 12) & 0x3F) | 0x80);
+ buf[2] =(char) (((ch >> 6) & 0x3F) | 0x80);
+ buf[3] =(char) ((ch & 0x3F) | 0x80);
+ len += 3;
+ } else {
+ buf[0] = '?';
+ }
+ return len;
+}
+
+static inline size_t rest(JSON_ParserState *state) {
+ return state->end - state->cursor;
+}
+
+static inline bool eos(JSON_ParserState *state) {
+ return state->cursor >= state->end;
+}
+
+static inline char peek(JSON_ParserState *state)
+{
+ if (RB_UNLIKELY(eos(state))) {
+ return 0;
+ }
+ return *state->cursor;
+}
+
+static void cursor_position(JSON_ParserState *state, long *line_out, long *column_out)
+{
+ JSON_ASSERT(state->cursor <= state->end);
+
+ // Redundant but helpful for hardening
+ if (RB_UNLIKELY(state->cursor > state->end)) {
+ state->cursor = state->end;
+ }
+
+ const char *cursor = state->cursor;
+ long column = 0;
+ long line = 1;
+
+ while (cursor >= state->start) {
+ if (*cursor-- == '\n') {
+ break;
+ }
+ column++;
+ }
+
+ while (cursor >= state->start) {
+ if (*cursor-- == '\n') {
+ line++;
+ }
+ }
+ *line_out = line;
+ *column_out = column;
+}
+
+static void emit_parse_warning(const char *message, JSON_ParserState *state)
+{
+ long line, column;
+ cursor_position(state, &line, &column);
+
+ VALUE warning = rb_sprintf("%s at line %ld column %ld", message, line, column);
+ rb_funcall(mJSON, rb_intern("deprecation_warning"), 1, warning);
+}
+
+#define PARSE_ERROR_FRAGMENT_LEN 32
+
+static VALUE build_parse_error_message(const char *format, JSON_ParserState *state, long line, long column)
+{
+ unsigned char buffer[PARSE_ERROR_FRAGMENT_LEN + 3];
+
+ const char *ptr = "EOF";
+ if (state->cursor && state->cursor < state->end) {
+ ptr = state->cursor;
+ size_t len = 0;
+ while (len < PARSE_ERROR_FRAGMENT_LEN) {
+ char ch = ptr[len];
+ if (!ch || ch == '\n' || ch == ' ' || ch == '\t' || ch == '\r') {
+ break;
+ }
+ len++;
+ }
+
+ if (len) {
+ buffer[0] = '\'';
+ MEMCPY(buffer + 1, ptr, char, len);
+
+ while (buffer[len] >= 0x80 && buffer[len] < 0xC0) { // Is continuation byte
+ len--;
+ }
+
+ if (buffer[len] >= 0xC0) { // multibyte character start
+ len--;
+ }
+
+ buffer[len + 1] = '\'';
+ buffer[len + 2] = '\0';
+ ptr = (const char *)buffer;
+ }
+ }
+
+ VALUE message = rb_enc_sprintf(enc_utf8, format, ptr);
+ rb_str_catf(message, " at line %ld column %ld", line, column);
+ return message;
+}
+
+static VALUE parse_error_new(VALUE message, long line, long column)
+{
+ VALUE exc = rb_exc_new_str(rb_path2class("JSON::ParserError"), message);
+ rb_ivar_set(exc, rb_intern("@line"), LONG2NUM(line));
+ rb_ivar_set(exc, rb_intern("@column"), LONG2NUM(column));
+ return exc;
+}
+
+NORETURN(static) void raise_parse_error(const char *format, JSON_ParserState *state)
+{
+ long line, column;
+ cursor_position(state, &line, &column);
+ VALUE message = build_parse_error_message(format, state, line, column);
+ rb_exc_raise(parse_error_new(message, line, column));
+}
+
+NORETURN(static) void raise_parse_error_at(const char *format, JSON_ParserState *state, const char *at)
+{
+ state->cursor = at;
+ raise_parse_error(format, state);
+}
+
+/* unicode */
+
+static const signed char digit_values[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
+ -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1
+};
+
+static uint32_t unescape_unicode(JSON_ParserState *state, const char *sp, const char *spe)
+{
+ if (RB_UNLIKELY(sp > spe - 4)) {
+ raise_parse_error_at("incomplete unicode character escape sequence at %s", state, sp - 2);
+ }
+
+ const unsigned char *p = (const unsigned char *)sp;
+
+ const signed char b0 = digit_values[p[0]];
+ const signed char b1 = digit_values[p[1]];
+ const signed char b2 = digit_values[p[2]];
+ const signed char b3 = digit_values[p[3]];
+
+ if (RB_UNLIKELY((signed char)(b0 | b1 | b2 | b3) < 0)) {
+ raise_parse_error_at("incomplete unicode character escape sequence at %s", state, sp - 2);
+ }
+
+ return ((uint32_t)b0 << 12) | ((uint32_t)b1 << 8) | ((uint32_t)b2 << 4) | (uint32_t)b3;
+}
+
+#define GET_PARSER_CONFIG \
+ JSON_ParserConfig *config; \
+ TypedData_Get_Struct(self, JSON_ParserConfig, &JSON_ParserConfig_type, config)
+
+static const rb_data_type_t JSON_ParserConfig_type;
+
+NOINLINE(static) void
+json_eat_comments(JSON_ParserState *state)
+{
+ const char *start = state->cursor;
+ state->cursor++;
+
+ switch (peek(state)) {
+ case '/': {
+ state->cursor = memchr(state->cursor, '\n', state->end - state->cursor);
+ if (!state->cursor) {
+ state->cursor = state->end;
+ } else {
+ state->cursor++;
+ }
+ break;
+ }
+ case '*': {
+ state->cursor++;
+
+ while (true) {
+ const char *next_match = memchr(state->cursor, '*', state->end - state->cursor);
+ if (!next_match) {
+ raise_parse_error_at("unterminated comment, expected closing '*/'", state, start);
+ }
+
+ state->cursor = next_match + 1;
+ if (peek(state) == '/') {
+ state->cursor++;
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ raise_parse_error_at("unexpected token %s", state, start);
+ break;
+ }
+}
+
+ALWAYS_INLINE(static) void
+json_eat_whitespace(JSON_ParserState *state)
+{
+ while (true) {
+ switch (peek(state)) {
+ case ' ':
+ state->cursor++;
+ break;
+ case '\n':
+ state->cursor++;
+
+ // Heuristic: if we see a newline, there is likely consecutive spaces after it.
+#if JSON_CPU_LITTLE_ENDIAN_64BITS
+ while (rest(state) > 8) {
+ uint64_t chunk;
+ memcpy(&chunk, state->cursor, sizeof(uint64_t));
+ if (chunk == 0x2020202020202020) {
+ state->cursor += 8;
+ continue;
+ }
+
+ uint32_t consecutive_spaces = trailing_zeros64(chunk ^ 0x2020202020202020) / CHAR_BIT;
+ state->cursor += consecutive_spaces;
+ break;
+ }
+#endif
+ break;
+ case '\t':
+ case '\r':
+ state->cursor++;
+ break;
+ case '/':
+ json_eat_comments(state);
+ break;
+
+ default:
+ return;
+ }
+ }
+}
+
+static inline VALUE build_string(const char *start, const char *end, bool intern, bool symbolize)
+{
+ if (symbolize) {
+ intern = true;
+ }
+ VALUE result;
+# ifdef HAVE_RB_ENC_INTERNED_STR
+ if (intern) {
+ result = rb_enc_interned_str(start, (long)(end - start), enc_utf8);
+ } else {
+ result = rb_utf8_str_new(start, (long)(end - start));
+ }
+# else
+ result = rb_utf8_str_new(start, (long)(end - start));
+ if (intern) {
+ result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
+ }
+# endif
+
+ if (symbolize) {
+ result = rb_str_intern(result);
+ }
+
+ return result;
+}
+
+static inline bool json_string_cacheable_p(const char *string, size_t length)
+{
+ // We mostly want to cache strings that are likely to be repeated.
+ // Simple heuristics:
+ // - Common names aren't likely to be very long. So we just don't cache names above an arbitrary threshold.
+ // - If the first character isn't a letter, we're much less likely to see this string again.
+ return length <= JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH && rb_isalpha(string[0]);
+}
+
+static inline VALUE json_string_fastpath(JSON_ParserState *state, JSON_ParserConfig *config, const char *string, const char *stringEnd, bool is_name)
+{
+ bool intern = is_name || config->freeze;
+ bool symbolize = is_name && config->symbolize_names;
+ size_t bufferSize = stringEnd - string;
+
+ if (is_name && state->in_array && RB_LIKELY(json_string_cacheable_p(string, bufferSize))) {
+ VALUE cached_key;
+ if (RB_UNLIKELY(symbolize)) {
+ cached_key = rsymbol_cache_fetch(&state->name_cache, string, bufferSize);
+ } else {
+ cached_key = rstring_cache_fetch(&state->name_cache, string, bufferSize);
+ }
+
+ if (RB_LIKELY(cached_key)) {
+ return cached_key;
+ }
+ }
+
+ return build_string(string, stringEnd, intern, symbolize);
+}
+
+#define JSON_MAX_UNESCAPE_POSITIONS 16
+typedef struct _json_unescape_positions {
+ long size;
+ const char **positions;
+ unsigned long additional_backslashes;
+} JSON_UnescapePositions;
+
+static inline const char *json_next_backslash(const char *pe, const char *stringEnd, JSON_UnescapePositions *positions)
+{
+ while (positions->size) {
+ positions->size--;
+ const char *next_position = positions->positions[0];
+ positions->positions++;
+ if (next_position >= pe) {
+ return next_position;
+ }
+ }
+
+ if (positions->additional_backslashes) {
+ positions->additional_backslashes--;
+ return memchr(pe, '\\', stringEnd - pe);
+ }
+
+ return NULL;
+}
+
+NOINLINE(static) VALUE json_string_unescape(JSON_ParserState *state, JSON_ParserConfig *config, const char *string, const char *stringEnd, bool is_name, JSON_UnescapePositions *positions)
+{
+ bool intern = is_name || config->freeze;
+ bool symbolize = is_name && config->symbolize_names;
+ size_t bufferSize = stringEnd - string;
+ const char *p = string, *pe = string, *bufferStart;
+ char *buffer;
+
+ VALUE result = rb_str_buf_new(bufferSize);
+ rb_enc_associate_index(result, utf8_encindex);
+ buffer = RSTRING_PTR(result);
+ bufferStart = buffer;
+
+#define APPEND_CHAR(chr) *buffer++ = chr; p = ++pe;
+
+ while (pe < stringEnd && (pe = json_next_backslash(pe, stringEnd, positions))) {
+ if (pe > p) {
+ MEMCPY(buffer, p, char, pe - p);
+ buffer += pe - p;
+ }
+ switch (*++pe) {
+ case '"':
+ case '/':
+ p = pe; // nothing to unescape just need to skip the backslash
+ break;
+ case '\\':
+ APPEND_CHAR('\\');
+ break;
+ case 'n':
+ APPEND_CHAR('\n');
+ break;
+ case 'r':
+ APPEND_CHAR('\r');
+ break;
+ case 't':
+ APPEND_CHAR('\t');
+ break;
+ case 'b':
+ APPEND_CHAR('\b');
+ break;
+ case 'f':
+ APPEND_CHAR('\f');
+ break;
+ case 'u': {
+ uint32_t ch = unescape_unicode(state, ++pe, stringEnd);
+ pe += 3;
+ /* To handle values above U+FFFF, we take a sequence of
+ * \uXXXX escapes in the U+D800..U+DBFF then
+ * U+DC00..U+DFFF ranges, take the low 10 bits from each
+ * to make a 20-bit number, then add 0x10000 to get the
+ * final codepoint.
+ *
+ * See Unicode 15: 3.8 "Surrogates", 5.3 "Handling
+ * Surrogate Pairs in UTF-16", and 23.6 "Surrogates
+ * Area".
+ */
+ if ((ch & 0xFC00) == 0xD800) {
+ pe++;
+ if (RB_LIKELY((pe <= stringEnd - 6) && memcmp(pe, "\\u", 2) == 0)) {
+ uint32_t sur = unescape_unicode(state, pe + 2, stringEnd);
+
+ if (RB_UNLIKELY((sur & 0xFC00) != 0xDC00)) {
+ raise_parse_error_at("invalid surrogate pair at %s", state, p);
+ }
+
+ ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16) | (sur & 0x3FF));
+ pe += 5;
+ } else {
+ raise_parse_error_at("incomplete surrogate pair at %s", state, p);
+ break;
+ }
+ }
+
+ int unescape_len = convert_UTF32_to_UTF8(buffer, ch);
+ buffer += unescape_len;
+ p = ++pe;
+ break;
+ }
+ default:
+ if ((unsigned char)*pe < 0x20) {
+ if (!config->allow_control_characters) {
+ if (*pe == '\n') {
+ raise_parse_error_at("Invalid unescaped newline character (\\n) in string: %s", state, pe - 1);
+ }
+ raise_parse_error_at("invalid ASCII control character in string: %s", state, pe - 1);
+ }
+ }
+
+ if (config->allow_invalid_escape) {
+ APPEND_CHAR(*pe);
+ } else {
+ raise_parse_error_at("invalid escape character in string: %s", state, pe - 1);
+ }
+ break;
+ }
+ }
+#undef APPEND_CHAR
+
+ if (stringEnd > p) {
+ MEMCPY(buffer, p, char, stringEnd - p);
+ buffer += stringEnd - p;
+ }
+ rb_str_set_len(result, buffer - bufferStart);
+
+ if (symbolize) {
+ result = rb_str_intern(result);
+ } else if (intern) {
+ result = rb_str_to_interned_str(result);
+ }
+
+ return result;
+}
+
+#define MAX_FAST_INTEGER_SIZE 18
+#define MAX_NUMBER_STACK_BUFFER 128
+
+typedef VALUE (*json_number_decode_func_t)(const char *ptr);
+
+static inline VALUE json_decode_large_number(const char *start, long len, json_number_decode_func_t func)
+{
+ if (RB_LIKELY(len < MAX_NUMBER_STACK_BUFFER)) {
+ char buffer[MAX_NUMBER_STACK_BUFFER];
+ MEMCPY(buffer, start, char, len);
+ buffer[len] = '\0';
+ return func(buffer);
+ } else {
+ VALUE buffer_v = rb_str_tmp_new(len);
+ char *buffer = RSTRING_PTR(buffer_v);
+ MEMCPY(buffer, start, char, len);
+ buffer[len] = '\0';
+ VALUE number = func(buffer);
+ RB_GC_GUARD(buffer_v);
+ return number;
+ }
+}
+
+static VALUE json_decode_inum(const char *buffer)
+{
+ return rb_cstr2inum(buffer, 10);
+}
+
+NOINLINE(static) VALUE json_decode_large_integer(const char *start, long len)
+{
+ return json_decode_large_number(start, len, json_decode_inum);
+}
+
+static inline VALUE json_decode_integer(uint64_t mantissa, int mantissa_digits, bool negative, const char *start, const char *end)
+{
+ if (RB_LIKELY(mantissa_digits < MAX_FAST_INTEGER_SIZE)) {
+ if (negative) {
+ return INT64T2NUM(-((int64_t)mantissa));
+ }
+ return UINT64T2NUM(mantissa);
+ }
+
+ return json_decode_large_integer(start, end - start);
+}
+
+static VALUE json_decode_dnum(const char *buffer)
+{
+ return DBL2NUM(rb_cstr_to_dbl(buffer, 1));
+}
+
+NOINLINE(static) VALUE json_decode_large_float(const char *start, long len)
+{
+ return json_decode_large_number(start, len, json_decode_dnum);
+}
+
+/* Ruby JSON optimized float decoder using vendored Ryu algorithm
+ * Accepts pre-extracted mantissa and exponent from first-pass validation
+ */
+static inline VALUE json_decode_float(JSON_ParserConfig *config, uint64_t mantissa, int mantissa_digits, int64_t exponent, bool negative,
+ const char *start, const char *end)
+{
+ if (RB_UNLIKELY(config->decimal_class)) {
+ VALUE text = rb_str_new(start, end - start);
+ return rb_funcallv(config->decimal_class, config->decimal_method_id, 1, &text);
+ }
+
+ if (RB_UNLIKELY(exponent > INT32_MAX)) {
+ return negative ? CMinusInfinity : CInfinity;
+ }
+
+ if (RB_UNLIKELY(exponent < INT32_MIN)) {
+ return rb_float_new(negative ? -0.0 : 0.0);
+ }
+
+ // Fall back to rb_cstr_to_dbl for potential subnormals (rare edge case)
+ // Ryu has rounding issues with subnormals around 1e-310 (< 2.225e-308)
+ if (RB_UNLIKELY(mantissa_digits > 17 || mantissa_digits + exponent < -307)) {
+ return json_decode_large_float(start, end - start);
+ }
+
+ return DBL2NUM(ryu_s2d_from_parts(mantissa, mantissa_digits, (int32_t)exponent, negative));
+}
+
+static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig *config, long count)
+{
+ VALUE array = rb_ary_new_from_values(count, rvalue_stack_peek(state->value_stack, count));
+ rvalue_stack_pop(state->value_stack, count);
+
+ if (config->freeze) {
+ RB_OBJ_FREEZE(array);
+ }
+
+ return array;
+}
+
+static VALUE json_find_duplicated_key(size_t count, const VALUE *pairs)
+{
+ VALUE set = rb_hash_new_capa(count / 2);
+ for (size_t index = 0; index < count; index += 2) {
+ size_t before = RHASH_SIZE(set);
+ VALUE key = pairs[index];
+ rb_hash_aset(set, key, Qtrue);
+ if (RHASH_SIZE(set) == before) {
+ if (RB_SYMBOL_P(key)) {
+ return rb_sym2str(key);
+ }
+ return key;
+ }
+ }
+ return Qfalse;
+}
+
+NOINLINE(static) void emit_duplicate_key_warning(JSON_ParserState *state, VALUE duplicate_key)
+{
+ VALUE message = rb_sprintf(
+ "detected duplicate key %"PRIsVALUE" in JSON object. This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`",
+ rb_inspect(duplicate_key)
+ );
+
+ emit_parse_warning(RSTRING_PTR(message), state);
+ RB_GC_GUARD(message);
+}
+
+NORETURN(static) void raise_duplicate_key_error(JSON_ParserState *state, VALUE duplicate_key)
+{
+ VALUE message = rb_sprintf(
+ "duplicate key %"PRIsVALUE,
+ rb_inspect(duplicate_key)
+ );
+
+ long line, column;
+ cursor_position(state, &line, &column);
+ rb_str_concat(message, build_parse_error_message("", state, line, column)) ;
+ rb_exc_raise(parse_error_new(message, line, column));
+}
+
+NOINLINE(static) void json_on_duplicate_key(JSON_ParserState *state, JSON_ParserConfig *config, size_t count, const VALUE *pairs)
+{
+ switch (config->on_duplicate_key) {
+ case JSON_IGNORE:
+ return;
+
+ case JSON_DEPRECATED:
+ // Only emit the first few deprecations to avoid spamming.
+ if (state->emitted_deprecations < 5) {
+ emit_duplicate_key_warning(state, json_find_duplicated_key(count, pairs));
+ state->emitted_deprecations++;
+ }
+ return;
+
+ case JSON_RAISE:
+ raise_duplicate_key_error(state, json_find_duplicated_key(count, pairs));
+ return;
+ }
+ UNREACHABLE;
+}
+
+static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfig *config, size_t count)
+{
+ size_t entries_count = count / 2;
+ VALUE object = rb_hash_new_capa(entries_count);
+ const VALUE *pairs = rvalue_stack_peek(state->value_stack, count);
+ rb_hash_bulk_insert(count, pairs, object);
+
+ if (RB_UNLIKELY(RHASH_SIZE(object) < entries_count)) {
+ json_on_duplicate_key(state, config, count, pairs);
+ }
+
+ rvalue_stack_pop(state->value_stack, count);
+
+ if (config->freeze) {
+ RB_OBJ_FREEZE(object);
+ }
+
+ return object;
+}
+
+static inline VALUE json_push_value(JSON_ParserState *state, JSON_ParserConfig *config, VALUE value)
+{
+ if (RB_UNLIKELY(config->on_load_proc)) {
+ value = rb_proc_call_with_block(config->on_load_proc, 1, &value, Qnil);
+ }
+ rvalue_stack_push(state->value_stack, value, state->value_stack_handle, &state->value_stack);
+ return value;
+}
+
+static const bool string_scan_table[256] = {
+ // ASCII Control Characters
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ // ASCII Characters
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // '"'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, // '\\'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+#ifdef HAVE_SIMD
+static SIMD_Implementation simd_impl = SIMD_NONE;
+#endif /* HAVE_SIMD */
+
+ALWAYS_INLINE(static) bool string_scan(JSON_ParserState *state)
+{
+#ifdef HAVE_SIMD
+#if defined(HAVE_SIMD_NEON)
+
+ uint64_t mask = 0;
+ if (string_scan_simd_neon(&state->cursor, state->end, &mask)) {
+ state->cursor += trailing_zeros64(mask) >> 2;
+ return true;
+ }
+
+#elif defined(HAVE_SIMD_SSE2)
+ if (simd_impl == SIMD_SSE2) {
+ int mask = 0;
+ if (string_scan_simd_sse2(&state->cursor, state->end, &mask)) {
+ state->cursor += trailing_zeros(mask);
+ return true;
+ }
+ }
+#endif /* HAVE_SIMD_NEON or HAVE_SIMD_SSE2 */
+#endif /* HAVE_SIMD */
+
+ while (!eos(state)) {
+ if (RB_UNLIKELY(string_scan_table[(unsigned char)*state->cursor])) {
+ return true;
+ }
+ state->cursor++;
+ }
+
+ // If the string ended with an unterminated escape sequence, we might
+ // have gone past the end.
+ if (RB_UNLIKELY(state->cursor > state->end)) {
+ state->cursor = state->end;
+ }
+
+ return false;
+}
+
+static VALUE json_parse_escaped_string(JSON_ParserState *state, JSON_ParserConfig *config, bool is_name, const char *start)
+{
+ const char *backslashes[JSON_MAX_UNESCAPE_POSITIONS];
+ JSON_UnescapePositions positions = {
+ .size = 0,
+ .positions = backslashes,
+ .additional_backslashes = 0,
+ };
+
+ do {
+ switch (*state->cursor) {
+ case '"': {
+ VALUE string = json_string_unescape(state, config, start, state->cursor, is_name, &positions);
+ state->cursor++;
+ return json_push_value(state, config, string);
+ }
+ case '\\': {
+ if (RB_LIKELY(positions.size < JSON_MAX_UNESCAPE_POSITIONS)) {
+ backslashes[positions.size] = state->cursor;
+ positions.size++;
+ } else {
+ positions.additional_backslashes++;
+ }
+ state->cursor++;
+ break;
+ }
+ default:
+ if (!config->allow_control_characters) {
+ raise_parse_error("invalid ASCII control character in string: %s", state);
+ }
+ break;
+ }
+
+ state->cursor++;
+ } while (string_scan(state));
+
+ raise_parse_error("unexpected end of input, expected closing \"", state);
+ return Qfalse;
+}
+
+ALWAYS_INLINE(static) VALUE json_parse_string(JSON_ParserState *state, JSON_ParserConfig *config, bool is_name)
+{
+ state->cursor++;
+ const char *start = state->cursor;
+
+ if (RB_UNLIKELY(!string_scan(state))) {
+ raise_parse_error("unexpected end of input, expected closing \"", state);
+ }
+
+ if (RB_LIKELY(*state->cursor == '"')) {
+ VALUE string = json_string_fastpath(state, config, start, state->cursor, is_name);
+ state->cursor++;
+ return json_push_value(state, config, string);
+ }
+ return json_parse_escaped_string(state, config, is_name, start);
+}
+
+#if JSON_CPU_LITTLE_ENDIAN_64BITS
+// From: https://lemire.me/blog/2022/01/21/swar-explained-parsing-eight-digits/
+// Additional References:
+// https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
+// http://0x80.pl/notesen/2014-10-12-parsing-decimal-numbers-part-1-swar.html
+static inline uint64_t decode_8digits_unrolled(uint64_t val) {
+ const uint64_t mask = 0x000000FF000000FF;
+ const uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32)
+ const uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32)
+ val -= 0x3030303030303030;
+ val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8;
+ val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32;
+ return val;
+}
+
+static inline uint64_t decode_4digits_unrolled(uint32_t val) {
+ const uint32_t mask = 0x000000FF;
+ const uint32_t mul1 = 100;
+ val -= 0x30303030;
+ val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8;
+ val = ((val & mask) * mul1) + (((val >> 16) & mask));
+ return val;
+}
+#endif
+
+static inline int json_parse_digits(JSON_ParserState *state, uint64_t *accumulator)
+{
+ const char *start = state->cursor;
+
+#if JSON_CPU_LITTLE_ENDIAN_64BITS
+ while (rest(state) >= sizeof(uint64_t)) {
+ uint64_t next_8bytes;
+ memcpy(&next_8bytes, state->cursor, sizeof(uint64_t));
+
+ // From: https://github.com/simdjson/simdjson/blob/32b301893c13d058095a07d9868edaaa42ee07aa/include/simdjson/generic/numberparsing.h#L333
+ // Branchless version of: http://0x80.pl/articles/swar-digits-validate.html
+ uint64_t match = (next_8bytes & 0xF0F0F0F0F0F0F0F0) | (((next_8bytes + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0) >> 4);
+
+ if (match == 0x3333333333333333) { // 8 consecutive digits
+ *accumulator = (*accumulator * 100000000) + decode_8digits_unrolled(next_8bytes);
+ state->cursor += 8;
+ continue;
+ }
+
+ uint32_t consecutive_digits = trailing_zeros64(match ^ 0x3333333333333333) / CHAR_BIT;
+
+ if (consecutive_digits >= 4) {
+ *accumulator = (*accumulator * 10000) + decode_4digits_unrolled((uint32_t)next_8bytes);
+ state->cursor += 4;
+ consecutive_digits -= 4;
+ }
+
+ while (consecutive_digits) {
+ *accumulator = *accumulator * 10 + (*state->cursor - '0');
+ consecutive_digits--;
+ state->cursor++;
+ }
+
+ return (int)(state->cursor - start);
+ }
+#endif
+
+ char next_char;
+ while (rb_isdigit(next_char = peek(state))) {
+ *accumulator = *accumulator * 10 + (next_char - '0');
+ state->cursor++;
+ }
+ return (int)(state->cursor - start);
+}
+
+static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig *config, bool negative, const char *start)
+{
+ bool integer = true;
+ const char first_digit = *state->cursor;
+
+ // Variables for Ryu optimization - extract digits during parsing
+ int64_t exponent = 0;
+ int decimal_point_pos = -1;
+ uint64_t mantissa = 0;
+
+ // Parse integer part and extract mantissa digits
+ int mantissa_digits = json_parse_digits(state, &mantissa);
+
+ if (RB_UNLIKELY((first_digit == '0' && mantissa_digits > 1) || (negative && mantissa_digits == 0))) {
+ raise_parse_error_at("invalid number: %s", state, start);
+ }
+
+ // Parse fractional part
+ if (peek(state) == '.') {
+ integer = false;
+ decimal_point_pos = mantissa_digits; // Remember position of decimal point
+ state->cursor++;
+
+ int fractional_digits = json_parse_digits(state, &mantissa);
+ mantissa_digits += fractional_digits;
+
+ if (RB_UNLIKELY(!fractional_digits)) {
+ raise_parse_error_at("invalid number: %s", state, start);
+ }
+ }
+
+ // Parse exponent
+ if (rb_tolower(peek(state)) == 'e') {
+ integer = false;
+ state->cursor++;
+
+ bool negative_exponent = false;
+ const char next_char = peek(state);
+ if (next_char == '-' || next_char == '+') {
+ negative_exponent = next_char == '-';
+ state->cursor++;
+ }
+
+ uint64_t abs_exponent = 0;
+ int exponent_digits = json_parse_digits(state, &abs_exponent);
+
+ if (RB_UNLIKELY(!exponent_digits)) {
+ raise_parse_error_at("invalid number: %s", state, start);
+ }
+
+ if (RB_UNLIKELY(exponent_digits >= 20 || abs_exponent > (uint64_t)INT64_MAX)) {
+ exponent = negative_exponent ? INT64_MIN : INT64_MAX;
+ } else {
+ exponent = negative_exponent ? -(int64_t)abs_exponent : (int64_t)abs_exponent;
+ }
+ }
+
+ if (integer) {
+ return json_decode_integer(mantissa, mantissa_digits, negative, start, state->cursor);
+ }
+
+ // Adjust exponent based on decimal point position
+ if (decimal_point_pos >= 0) {
+ exponent -= (mantissa_digits - decimal_point_pos);
+ }
+
+ return json_decode_float(config, mantissa, mantissa_digits, exponent, negative, start, state->cursor);
+}
+
+static inline VALUE json_parse_positive_number(JSON_ParserState *state, JSON_ParserConfig *config)
+{
+ return json_parse_number(state, config, false, state->cursor);
+}
+
+static inline VALUE json_parse_negative_number(JSON_ParserState *state, JSON_ParserConfig *config)
+{
+ const char *start = state->cursor;
+ state->cursor++;
+ return json_parse_number(state, config, true, start);
+}
+
+// How many values (array elements, or interleaved object keys+values) have been
+// pushed onto the rvalue stack since this container opened. Used to size the
+// bulk decode on close, and to tell the first key/colon from later ones.
+static inline long json_frame_entry_count(const json_frame *frame, const rvalue_stack *value_stack)
+{
+ return value_stack->head - frame->value_stack_head;
+}
+
+// A complete value now sits on top of the rvalue stack. Advance the frame that
+// was waiting for it: the root document is done, or the enclosing container
+// moves on to expecting a ',' or its closing bracket. The caller passes the
+// frame it already has in hand -- the one that was expecting the value -- which
+// after a container close is the freshly re-exposed parent.
+static inline void json_value_completed(json_frame *frame)
+{
+ switch (frame->type) {
+ case JSON_FRAME_ROOT:
+ frame->phase = JSON_PHASE_DONE;
+ return;
+ case JSON_FRAME_ARRAY:
+ frame->phase = JSON_PHASE_ARRAY_COMMA;
+ return;
+ case JSON_FRAME_OBJECT:
+ frame->phase = JSON_PHASE_OBJECT_COMMA;
+ return;
+ }
+ UNREACHABLE;
+}
+
+// Parse an arbitrary JSON value iteratively. This is a state machine driven
+// entirely by the top frame's phase so it can stop at any value boundary and
+// resume purely from the frame stack. A JSON_FRAME_ROOT frame sits at the
+// bottom of the stack, so the stack is never empty mid-parse and the document
+// itself is just another frame whose value, once parsed, leaves its phase DONE.
+static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
+{
+ while (true) {
+ json_frame *frame = json_frame_stack_peek(state->frames);
+
+ switch (frame->phase) {
+ case JSON_PHASE_DONE: {
+ // The root document value is parsed; it is the lone survivor on
+ // the rvalue stack.
+ return *rvalue_stack_peek(state->value_stack, 1);
+ }
+
+ case JSON_PHASE_VALUE: {
+ JSON_PHASE_VALUE:
+ json_eat_whitespace(state);
+
+ switch (peek(state)) {
+ case 'n':
+ if (rest(state) >= 4 && (memcmp(state->cursor, "null", 4) == 0)) {
+ state->cursor += 4;
+ json_push_value(state, config, Qnil);
+ json_value_completed(frame);
+ break;
+ }
+
+ raise_parse_error("unexpected token %s", state);
+ case 't':
+ if (rest(state) >= 4 && (memcmp(state->cursor, "true", 4) == 0)) {
+ state->cursor += 4;
+ json_push_value(state, config, Qtrue);
+ json_value_completed(frame);
+ break;
+ }
+
+ raise_parse_error("unexpected token %s", state);
+ case 'f':
+ // Note: memcmp with a small power of two compile to an integer comparison
+ if (rest(state) >= 5 && (memcmp(state->cursor + 1, "alse", 4) == 0)) {
+ state->cursor += 5;
+ json_push_value(state, config, Qfalse);
+ json_value_completed(frame);
+ break;
+ }
+
+ raise_parse_error("unexpected token %s", state);
+ case 'N':
+ // Note: memcmp with a small power of two compile to an integer comparison
+ if (config->allow_nan && rest(state) >= 3 && (memcmp(state->cursor + 1, "aN", 2) == 0)) {
+ state->cursor += 3;
+ json_push_value(state, config, CNaN);
+ json_value_completed(frame);
+ break;
+ }
+
+ raise_parse_error("unexpected token %s", state);
+ case 'I':
+ if (config->allow_nan && rest(state) >= 8 && (memcmp(state->cursor, "Infinity", 8) == 0)) {
+ state->cursor += 8;
+ json_push_value(state, config, CInfinity);
+ json_value_completed(frame);
+ break;
+ }
+
+ raise_parse_error("unexpected token %s", state);
+ case '-': {
+ // Note: memcmp with a small power of two compile to an integer comparison
+ if (rest(state) >= 9 && (memcmp(state->cursor + 1, "Infinity", 8) == 0)) {
+ if (config->allow_nan) {
+ state->cursor += 9;
+ json_push_value(state, config, CMinusInfinity);
+ json_value_completed(frame);
+ break;
+ } else {
+ raise_parse_error("unexpected token %s", state);
+ }
+ }
+ json_push_value(state, config, json_parse_negative_number(state, config));
+ json_value_completed(frame);
+ break;
+ }
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+ json_push_value(state, config, json_parse_positive_number(state, config));
+ json_value_completed(frame);
+ break;
+ case '"':
+ // %r{\A"[^"\\\t\n\x00]*(?:\\[bfnrtu\\/"][^"\\]*)*"}
+ json_parse_string(state, config, false);
+ json_value_completed(frame);
+ break;
+ case '[': {
+ state->cursor++;
+ json_eat_whitespace(state);
+
+ if (peek(state) == ']') {
+ state->cursor++;
+ json_push_value(state, config, json_decode_array(state, config, 0));
+ json_value_completed(frame);
+ break;
+ }
+
+ state->current_nesting++;
+ if (RB_UNLIKELY(config->max_nesting && (config->max_nesting < state->current_nesting))) {
+ rb_raise(eNestingError, "nesting of %d is too deep", state->current_nesting);
+ }
+ state->in_array++;
+
+ // Phase stays VALUE: the next iteration reads the first element.
+ frame = json_frame_stack_push(state, (json_frame){
+ .type = JSON_FRAME_ARRAY,
+ .phase = JSON_PHASE_VALUE,
+ .value_stack_head = state->value_stack->head,
+ });
+ goto JSON_PHASE_VALUE;
+ break;
+ }
+ case '{': {
+ const char *object_start_cursor = state->cursor;
+
+ state->cursor++;
+ json_eat_whitespace(state);
+
+ if (peek(state) == '}') {
+ state->cursor++;
+ json_push_value(state, config, json_decode_object(state, config, 0));
+ json_value_completed(frame);
+ break;
+ }
+
+ state->current_nesting++;
+ if (RB_UNLIKELY(config->max_nesting && (config->max_nesting < state->current_nesting))) {
+ rb_raise(eNestingError, "nesting of %d is too deep", state->current_nesting);
+ }
+
+ // Phase KEY: the next iteration reads the first key.
+ frame = json_frame_stack_push(state, (json_frame){
+ .type = JSON_FRAME_OBJECT,
+ .phase = JSON_PHASE_OBJECT_KEY,
+ .value_stack_head = state->value_stack->head,
+ .start_cursor = object_start_cursor,
+ });
+ goto JSON_PHASE_OBJECT_KEY;
+ break;
+ }
+
+ case 0:
+ raise_parse_error("unexpected end of input", state);
+
+ default:
+ raise_parse_error("unexpected character: %s", state);
+ }
+ break;
+ }
+
+ case JSON_PHASE_OBJECT_KEY: {
+ JSON_PHASE_OBJECT_KEY:
+ JSON_ASSERT(frame->type == JSON_FRAME_OBJECT);
+
+ json_eat_whitespace(state);
+
+ if (RB_LIKELY(peek(state) == '"')) {
+ json_parse_string(state, config, true);
+ frame->phase = JSON_PHASE_OBJECT_COLON;
+ goto JSON_PHASE_OBJECT_COLON;
+ } else {
+ // The message differs for the first key vs. a key after a
+ // ',': the first is the only one reached with nothing pushed
+ // for this object yet.
+ if (json_frame_entry_count(frame, state->value_stack) == 0) {
+ raise_parse_error("expected object key, got %s", state);
+ } else {
+ raise_parse_error("expected object key, got: %s", state);
+ }
+ }
+ break;
+ }
+
+ case JSON_PHASE_OBJECT_COLON: {
+ JSON_PHASE_OBJECT_COLON:
+ JSON_ASSERT(frame->type == JSON_FRAME_OBJECT);
+
+ json_eat_whitespace(state);
+
+ if (RB_LIKELY(peek(state) == ':')) {
+ state->cursor++;
+ frame->phase = JSON_PHASE_VALUE;
+ goto JSON_PHASE_VALUE;
+ } else {
+ // First colon (only the first pair's key is pushed, nothing
+ // else) vs. a later one.
+ if (json_frame_entry_count(frame, state->value_stack) == 1) {
+ raise_parse_error("expected ':' after object key", state);
+ } else {
+ raise_parse_error("expected ':' after object key, got: %s", state);
+ }
+ }
+ break;
+ }
+
+ case JSON_PHASE_ARRAY_COMMA: {
+ JSON_ASSERT(frame->type == JSON_FRAME_ARRAY);
+
+ json_eat_whitespace(state);
+
+ const char next_char = peek(state);
+
+ if (RB_LIKELY(next_char == ',')) {
+ state->cursor++;
+ if (config->allow_trailing_comma) {
+ json_eat_whitespace(state);
+ if (peek(state) == ']') {
+ // Trailing comma: stay in COMMA to close on the next iteration.
+ break;
+ }
+ }
+ frame->phase = JSON_PHASE_VALUE;
+ goto JSON_PHASE_VALUE;
+ } else if (next_char == ']') {
+ state->cursor++;
+ long count = json_frame_entry_count(frame, state->value_stack);
+ state->current_nesting--;
+ state->in_array--;
+ json_frame_stack_pop(state->frames);
+ json_push_value(state, config, json_decode_array(state, config, count));
+ json_value_completed(json_frame_stack_peek(state->frames));
+ } else {
+ raise_parse_error("expected ',' or ']' after array value", state);
+ }
+ break;
+ }
+
+ case JSON_PHASE_OBJECT_COMMA: {
+ JSON_ASSERT(frame->type == JSON_FRAME_OBJECT);
+
+ json_eat_whitespace(state);
+ const char next_char = peek(state);
+
+ if (RB_LIKELY(next_char == ',')) {
+ state->cursor++;
+ json_eat_whitespace(state);
+
+ if (config->allow_trailing_comma) {
+ if (peek(state) == '}') {
+ // Trailing comma: stay in COMMA to close on the next iteration.
+ break;
+ }
+ }
+
+ frame->phase = JSON_PHASE_OBJECT_KEY;
+ goto JSON_PHASE_OBJECT_KEY;
+
+ break;
+ } else if (next_char == '}') {
+ state->cursor++;
+ state->current_nesting--;
+ size_t count = json_frame_entry_count(frame, state->value_stack);
+
+ // Temporary rewind cursor in case an error is raised
+ const char *final_cursor = state->cursor;
+ state->cursor = frame->start_cursor;
+ VALUE object = json_decode_object(state, config, count);
+ state->cursor = final_cursor;
+
+ json_frame_stack_pop(state->frames);
+ json_push_value(state, config, object);
+ json_value_completed(json_frame_stack_peek(state->frames));
+ break;
+ } else {
+ raise_parse_error("expected ',' or '}' after object value, got: %s", state);
+ }
+ }
+ }
+ }
+}
+
+static void json_ensure_eof(JSON_ParserState *state)
+{
+ json_eat_whitespace(state);
+ if (!eos(state)) {
+ raise_parse_error("unexpected token at end of stream %s", state);
+ }
+}
+
+/*
+ * Document-class: JSON::Ext::Parser
+ *
+ * This is the JSON parser implemented as a C extension. It can be configured
+ * to be used by setting
+ *
+ * JSON.parser = JSON::Ext::Parser
+ *
+ * with the method parser= in JSON.
+ *
+ */
+
+static VALUE convert_encoding(VALUE source)
+{
+ StringValue(source);
+ int encindex = RB_ENCODING_GET(source);
+
+ if (RB_LIKELY(encindex == utf8_encindex)) {
+ return source;
+ }
+
+ if (encindex == binary_encindex) {
+ // For historical reason, we silently reinterpret binary strings as UTF-8
+ return rb_enc_associate_index(rb_str_dup(source), utf8_encindex);
+ }
+
+ source = rb_funcall(source, i_encode, 1, Encoding_UTF_8);
+ StringValue(source);
+ return source;
+}
+
+struct parser_config_init_args {
+ JSON_ParserConfig *config;
+ VALUE self;
+};
+
+static void parser_config_wb_write(VALUE self, VALUE *dest, VALUE val)
+{
+ *dest = val;
+ if (self) RB_OBJ_WRITTEN(self, Qundef, val);
+}
+
+static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
+{
+ struct parser_config_init_args *args = (struct parser_config_init_args *)data;
+ JSON_ParserConfig *config = args->config;
+ VALUE self = args->self;
+
+ if (key == sym_max_nesting) { config->max_nesting = RTEST(val) ? FIX2INT(val) : 0; }
+ else if (key == sym_allow_nan) { config->allow_nan = RTEST(val); }
+ else if (key == sym_allow_trailing_comma) { config->allow_trailing_comma = RTEST(val); }
+ else if (key == sym_allow_control_characters) { config->allow_control_characters = RTEST(val); }
+ else if (key == sym_allow_invalid_escape) { config->allow_invalid_escape = RTEST(val); }
+ else if (key == sym_symbolize_names) { config->symbolize_names = RTEST(val); }
+ else if (key == sym_freeze) { config->freeze = RTEST(val); }
+ else if (key == sym_on_load) { parser_config_wb_write(self, &config->on_load_proc, RTEST(val) ? val : Qfalse); }
+ else if (key == sym_allow_duplicate_key) { config->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; }
+ else if (key == sym_decimal_class) {
+ if (RTEST(val)) {
+ if (rb_respond_to(val, i_try_convert)) {
+ parser_config_wb_write(self, &config->decimal_class, val);
+ config->decimal_method_id = i_try_convert;
+ } else if (rb_respond_to(val, i_new)) {
+ parser_config_wb_write(self, &config->decimal_class, val);
+ config->decimal_method_id = i_new;
+ } else if (RB_TYPE_P(val, T_CLASS)) {
+ VALUE name = rb_class_name(val);
+ const char *name_cstr = RSTRING_PTR(name);
+ const char *last_colon = strrchr(name_cstr, ':');
+ if (last_colon) {
+ const char *mod_path_end = last_colon - 1;
+ VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
+ parser_config_wb_write(self, &config->decimal_class, rb_path_to_class(mod_path));
+
+ const char *method_name_beg = last_colon + 1;
+ long before_len = method_name_beg - name_cstr;
+ long len = RSTRING_LEN(name) - before_len;
+ VALUE method_name = rb_str_substr(name, before_len, len);
+ config->decimal_method_id = SYM2ID(rb_str_intern(method_name));
+ } else {
+ parser_config_wb_write(self, &config->decimal_class, rb_mKernel);
+ config->decimal_method_id = SYM2ID(rb_str_intern(name));
+ }
+ }
+ }
+ }
+
+ return ST_CONTINUE;
+}
+
+static void parser_config_init(JSON_ParserConfig *config, VALUE opts, VALUE self)
+{
+ config->max_nesting = 100;
+
+ struct parser_config_init_args args = {
+ .config = config,
+ .self = self,
+ };
+
+ if (!NIL_P(opts)) {
+ Check_Type(opts, T_HASH);
+ if (RHASH_SIZE(opts) > 0) {
+ // We assume in most cases few keys are set so it's faster to go over
+ // the provided keys than to check all possible keys.
+ rb_hash_foreach(opts, parser_config_init_i, (VALUE)&args);
+ }
+
+ }
+}
+
+/*
+ * call-seq: new(opts => {})
+ *
+ * Creates a new JSON::Ext::ParserConfig instance.
+ *
+ * It will be configured by the _opts_ hash. _opts_ can have the following
+ * keys:
+ *
+ * _opts_ can have the following keys:
+ * * *max_nesting*: The maximum depth of nesting allowed in the parsed data
+ * structures. Disable depth checking with :max_nesting => false|nil|0, it
+ * defaults to 100.
+ * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
+ * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
+ * false.
+ * * *symbolize_names*: If set to true, returns symbols for the names
+ * (keys) in a JSON object. Otherwise strings are returned, which is
+ * also the default. It's not possible to use this option in
+ * conjunction with the *create_additions* option.
+ * * *decimal_class*: Specifies which class to use instead of the default
+ * (Float) when parsing decimal numbers. This class must accept a single
+ * string argument in its constructor.
+ */
+static VALUE cParserConfig_initialize(VALUE self, VALUE opts)
+{
+ rb_check_frozen(self);
+ GET_PARSER_CONFIG;
+
+ parser_config_init(config, opts, self);
+
+ return self;
+}
+
+static VALUE cParser_parse(JSON_ParserConfig *config, VALUE src)
+{
+ VALUE Vsource = convert_encoding(src);
+
+ // Ensure the string isn't mutated under us.
+ // The classic API to use is `rb_str_locktmp`, but then we'd
+ // need to use `rb_protect` to make sure we always unlock.
+ if (Vsource == src) {
+ Vsource = rb_str_new_frozen(Vsource);
+ }
+
+ VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA];
+ rvalue_stack value_stack = {
+ .type = RVALUE_STACK_STACK_ALLOCATED,
+ .ptr = rvalue_stack_buffer,
+ .capa = RVALUE_STACK_INITIAL_CAPA,
+ };
+
+ // Seed the frame stack with the root frame, establishing the invariant that
+ // json_parse_any always has a top frame to dispatch on (so the stack is never
+ // empty mid-parse).
+ json_frame frame_stack_buffer[JSON_FRAME_STACK_INITIAL_CAPA];
+ frame_stack_buffer[0] = (json_frame){
+ .type = JSON_FRAME_ROOT,
+ .phase = JSON_PHASE_VALUE,
+ };
+ json_frame_stack frames = {
+ .type = RVALUE_STACK_STACK_ALLOCATED,
+ .ptr = frame_stack_buffer,
+ .capa = JSON_FRAME_STACK_INITIAL_CAPA,
+ .head = 1,
+ };
+
+ long len;
+ const char *start;
+
+ RSTRING_GETMEM(Vsource, start, len);
+
+ VALUE value_stack_handle = 0;
+ VALUE frame_stack_handle = 0;
+ JSON_ParserState _state = {
+ .start = start,
+ .cursor = start,
+ .end = start + len,
+ .value_stack = &value_stack,
+ .value_stack_handle = &value_stack_handle,
+ .frames = &frames,
+ .frame_stack_handle = &frame_stack_handle,
+ };
+ JSON_ParserState *state = &_state;
+
+ VALUE result = json_parse_any(state, config);
+
+ // This may be skipped in case of exception, but
+ // it won't cause a leak.
+ rvalue_stack_eagerly_release(value_stack_handle);
+ json_frame_stack_eagerly_release(frame_stack_handle);
+ RB_GC_GUARD(value_stack_handle);
+ RB_GC_GUARD(frame_stack_handle);
+ RB_GC_GUARD(Vsource);
+ json_ensure_eof(state);
+
+ return result;
+}
+
+/*
+ * call-seq: parse(source)
+ *
+ * Parses the current JSON text _source_ and returns the complete data
+ * structure as a result.
+ * It raises JSON::ParserError if fail to parse.
+ */
+static VALUE cParserConfig_parse(VALUE self, VALUE Vsource)
+{
+ GET_PARSER_CONFIG;
+ return cParser_parse(config, Vsource);
+}
+
+static VALUE cParser_m_parse(VALUE klass, VALUE Vsource, VALUE opts)
+{
+ JSON_ParserConfig _config = {0};
+ JSON_ParserConfig *config = &_config;
+ parser_config_init(config, opts, false);
+
+ return cParser_parse(config, Vsource);
+}
+
+static void JSON_ParserConfig_mark(void *ptr)
+{
+ JSON_ParserConfig *config = ptr;
+ rb_gc_mark(config->on_load_proc);
+ rb_gc_mark(config->decimal_class);
+}
+
+static size_t JSON_ParserConfig_memsize(const void *ptr)
+{
+ return sizeof(JSON_ParserConfig);
+}
+
+static const rb_data_type_t JSON_ParserConfig_type = {
+ .wrap_struct_name = "JSON::Ext::Parser/ParserConfig",
+ .function = {
+ JSON_ParserConfig_mark,
+ RUBY_DEFAULT_FREE,
+ JSON_ParserConfig_memsize,
+ },
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_EMBEDDABLE,
+};
+
+static VALUE cJSON_parser_s_allocate(VALUE klass)
+{
+ JSON_ParserConfig *config;
+ return TypedData_Make_Struct(klass, JSON_ParserConfig, &JSON_ParserConfig_type, config);
+}
+
+void Init_parser(void)
+{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
+#undef rb_intern
+ rb_require("json/common");
+ mJSON = rb_define_module("JSON");
+ VALUE mExt = rb_define_module_under(mJSON, "Ext");
+ VALUE cParserConfig = rb_define_class_under(mExt, "ParserConfig", rb_cObject);
+ eNestingError = rb_path2class("JSON::NestingError");
+ rb_gc_register_mark_object(eNestingError);
+ rb_define_alloc_func(cParserConfig, cJSON_parser_s_allocate);
+ rb_define_method(cParserConfig, "initialize", cParserConfig_initialize, 1);
+ rb_define_method(cParserConfig, "parse", cParserConfig_parse, 1);
+
+ VALUE cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
+ rb_define_singleton_method(cParser, "parse", cParser_m_parse, 2);
+
+ CNaN = rb_const_get(mJSON, rb_intern("NaN"));
+ rb_gc_register_mark_object(CNaN);
+
+ CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
+ rb_gc_register_mark_object(CInfinity);
+
+ CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
+ rb_gc_register_mark_object(CMinusInfinity);
+
+ rb_global_variable(&Encoding_UTF_8);
+ Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8"));
+
+ sym_max_nesting = ID2SYM(rb_intern("max_nesting"));
+ sym_allow_nan = ID2SYM(rb_intern("allow_nan"));
+ sym_allow_trailing_comma = ID2SYM(rb_intern("allow_trailing_comma"));
+ sym_allow_control_characters = ID2SYM(rb_intern("allow_control_characters"));
+ sym_allow_invalid_escape = ID2SYM(rb_intern("allow_invalid_escape"));
+ sym_symbolize_names = ID2SYM(rb_intern("symbolize_names"));
+ sym_freeze = ID2SYM(rb_intern("freeze"));
+ sym_on_load = ID2SYM(rb_intern("on_load"));
+ sym_decimal_class = ID2SYM(rb_intern("decimal_class"));
+ sym_allow_duplicate_key = ID2SYM(rb_intern("allow_duplicate_key"));
+
+ i_new = rb_intern("new");
+ i_try_convert = rb_intern("try_convert");
+ i_uminus = rb_intern("-@");
+ i_encode = rb_intern("encode");
+
+ binary_encindex = rb_ascii8bit_encindex();
+ utf8_encindex = rb_utf8_encindex();
+ enc_utf8 = rb_utf8_encoding();
+
+#ifdef HAVE_SIMD
+ simd_impl = find_simd_implementation();
+#endif
+}
diff --git a/ext/json/simd/conf.rb b/ext/json/simd/conf.rb
new file mode 100644
index 0000000000..76f774bc97
--- /dev/null
+++ b/ext/json/simd/conf.rb
@@ -0,0 +1,24 @@
+case RbConfig::CONFIG['host_cpu']
+when /^(arm|aarch64)/
+ # Try to compile a small program using NEON instructions
+ header, type, init, extra = 'arm_neon.h', 'uint8x16_t', 'vdupq_n_u8(32)', nil
+when /^(x86_64|x64)/
+ header, type, init, extra = 'x86intrin.h', '__m128i', '_mm_set1_epi8(32)', 'if (__builtin_cpu_supports("sse2")) { printf("OK"); }'
+end
+if header
+ if have_header(header) && try_compile(<<~SRC, '-Werror=implicit-function-declaration')
+ #{cpp_include(header)}
+ int main(int argc, char **argv) {
+ #{type} test = #{init};
+ #{extra}
+ if (argc > 100000) printf("%p", &test);
+ return 0;
+ }
+ SRC
+ $defs.push("-DJSON_ENABLE_SIMD")
+ else
+ puts "Disable SIMD"
+ end
+end
+
+have_header('cpuid.h')
diff --git a/ext/json/simd/simd.h b/ext/json/simd/simd.h
new file mode 100644
index 0000000000..611b41b066
--- /dev/null
+++ b/ext/json/simd/simd.h
@@ -0,0 +1,208 @@
+#include "../json.h"
+
+typedef enum {
+ SIMD_NONE,
+ SIMD_NEON,
+ SIMD_SSE2
+} SIMD_Implementation;
+
+#ifndef __has_builtin // Optional of course.
+ #define __has_builtin(x) 0 // Compatibility with non-clang compilers.
+#endif
+
+#ifdef __clang__
+# if __has_builtin(__builtin_ctzll)
+# define HAVE_BUILTIN_CTZLL 1
+# else
+# define HAVE_BUILTIN_CTZLL 0
+# endif
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+# define HAVE_BUILTIN_CTZLL 1
+#else
+# define HAVE_BUILTIN_CTZLL 0
+#endif
+
+static inline uint32_t trailing_zeros64(uint64_t input)
+{
+ JSON_ASSERT(input > 0); // __builtin_ctz(0) is undefined behavior
+
+#if HAVE_BUILTIN_CTZLL
+ return __builtin_ctzll(input);
+#else
+ uint32_t trailing_zeros = 0;
+ uint64_t temp = input;
+ while ((temp & 1) == 0 && temp > 0) {
+ trailing_zeros++;
+ temp >>= 1;
+ }
+ return trailing_zeros;
+#endif
+}
+
+static inline int trailing_zeros(int input)
+{
+ JSON_ASSERT(input > 0); // __builtin_ctz(0) is undefined behavior
+
+#if HAVE_BUILTIN_CTZLL
+ return __builtin_ctz(input);
+#else
+ int trailing_zeros = 0;
+ int temp = input;
+ while ((temp & 1) == 0 && temp > 0) {
+ trailing_zeros++;
+ temp >>= 1;
+ }
+ return trailing_zeros;
+#endif
+}
+
+#ifdef JSON_ENABLE_SIMD
+
+#define SIMD_MINIMUM_THRESHOLD 4
+
+ALWAYS_INLINE(static) void json_fast_memcpy16(char *dst, const char *src, size_t len)
+{
+ RBIMPL_ASSERT_OR_ASSUME(len < 16);
+ RBIMPL_ASSERT_OR_ASSUME(len >= SIMD_MINIMUM_THRESHOLD); // 4
+#if defined(__has_builtin) && __has_builtin(__builtin_memcpy)
+ // If __builtin_memcpy is available, use it to copy between SIMD_MINIMUM_THRESHOLD (4) and vec_len-1 (15) bytes.
+ // These copies overlap. The first copy will copy the first 8 (or 4) bytes. The second copy will copy
+ // the last 8 (or 4) bytes but overlap with the first copy. The overlapping bytes will be in the correct
+ // position in both copies.
+
+ // Please do not attempt to replace __builtin_memcpy with memcpy without profiling and/or looking at the
+ // generated assembly. On clang-specifically (tested on Apple clang version 17.0.0 (clang-1700.0.13.3)),
+ // when using memcpy, the compiler will notice the only difference is a 4 or 8 and generate a conditional
+ // select instruction instead of direct loads and stores with a branch. This ends up slower than the branch
+ // plus two loads and stores generated when using __builtin_memcpy.
+ if (len >= 8) {
+ __builtin_memcpy(dst, src, 8);
+ __builtin_memcpy(dst + len - 8, src + len - 8, 8);
+ } else {
+ __builtin_memcpy(dst, src, 4);
+ __builtin_memcpy(dst + len - 4, src + len - 4, 4);
+ }
+#else
+ MEMCPY(dst, src, char, len);
+#endif
+}
+
+#if defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(__aarch64__) || defined(_M_ARM64)
+#include <arm_neon.h>
+
+#define FIND_SIMD_IMPLEMENTATION_DEFINED 1
+static inline SIMD_Implementation find_simd_implementation(void)
+{
+ return SIMD_NEON;
+}
+
+#define HAVE_SIMD 1
+#define HAVE_SIMD_NEON 1
+
+// See: https://community.arm.com/arm-community-blogs/b/servers-and-cloud-computing-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon
+ALWAYS_INLINE(static) uint64_t neon_match_mask(uint8x16_t matches)
+{
+ const uint8x8_t res = vshrn_n_u16(vreinterpretq_u16_u8(matches), 4);
+ const uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(res), 0);
+ return mask & 0x8888888888888888ull;
+}
+
+ALWAYS_INLINE(static) uint64_t compute_chunk_mask_neon(const char *ptr)
+{
+ uint8x16_t chunk = vld1q_u8((const unsigned char *)ptr);
+
+ // Trick: c < 32 || c == 34 can be factored as c ^ 2 < 33
+ // https://lemire.me/blog/2025/04/13/detect-control-characters-quotes-and-backslashes-efficiently-using-swar/
+ const uint8x16_t too_low_or_dbl_quote = vcltq_u8(veorq_u8(chunk, vdupq_n_u8(2)), vdupq_n_u8(33));
+
+ uint8x16_t has_backslash = vceqq_u8(chunk, vdupq_n_u8('\\'));
+ uint8x16_t needs_escape = vorrq_u8(too_low_or_dbl_quote, has_backslash);
+ return neon_match_mask(needs_escape);
+}
+
+ALWAYS_INLINE(static) int string_scan_simd_neon(const char **ptr, const char *end, uint64_t *mask)
+{
+ while (*ptr + sizeof(uint8x16_t) <= end) {
+ uint64_t chunk_mask = compute_chunk_mask_neon(*ptr);
+ if (chunk_mask) {
+ *mask = chunk_mask;
+ return 1;
+ }
+ *ptr += sizeof(uint8x16_t);
+ }
+ return 0;
+}
+
+#endif /* ARM Neon Support.*/
+
+#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
+
+#ifdef HAVE_X86INTRIN_H
+#include <x86intrin.h>
+
+#define HAVE_SIMD 1
+#define HAVE_SIMD_SSE2 1
+
+#ifdef HAVE_CPUID_H
+#define FIND_SIMD_IMPLEMENTATION_DEFINED 1
+
+#if defined(__clang__) || defined(__GNUC__)
+#define TARGET_SSE2 __attribute__((target("sse2")))
+#else
+#define TARGET_SSE2
+#endif
+
+#define _mm_cmpge_epu8(a, b) _mm_cmpeq_epi8(_mm_max_epu8(a, b), a)
+#define _mm_cmple_epu8(a, b) _mm_cmpge_epu8(b, a)
+#define _mm_cmpgt_epu8(a, b) _mm_xor_si128(_mm_cmple_epu8(a, b), _mm_set1_epi8(-1))
+#define _mm_cmplt_epu8(a, b) _mm_cmpgt_epu8(b, a)
+
+ALWAYS_INLINE(static) TARGET_SSE2 int compute_chunk_mask_sse2(const char *ptr)
+{
+ __m128i chunk = _mm_loadu_si128((__m128i const*)ptr);
+ // Trick: c < 32 || c == 34 can be factored as c ^ 2 < 33
+ // https://lemire.me/blog/2025/04/13/detect-control-characters-quotes-and-backslashes-efficiently-using-swar/
+ __m128i too_low_or_dbl_quote = _mm_cmplt_epu8(_mm_xor_si128(chunk, _mm_set1_epi8(2)), _mm_set1_epi8(33));
+ __m128i has_backslash = _mm_cmpeq_epi8(chunk, _mm_set1_epi8('\\'));
+ __m128i needs_escape = _mm_or_si128(too_low_or_dbl_quote, has_backslash);
+ return _mm_movemask_epi8(needs_escape);
+}
+
+ALWAYS_INLINE(static) TARGET_SSE2 int string_scan_simd_sse2(const char **ptr, const char *end, int *mask)
+{
+ while (*ptr + sizeof(__m128i) <= end) {
+ int chunk_mask = compute_chunk_mask_sse2(*ptr);
+ if (chunk_mask) {
+ *mask = chunk_mask;
+ return 1;
+ }
+ *ptr += sizeof(__m128i);
+ }
+
+ return 0;
+}
+
+#include <cpuid.h>
+#endif /* HAVE_CPUID_H */
+
+static inline SIMD_Implementation find_simd_implementation(void)
+{
+ // TODO Revisit. I think the SSE version now only uses SSE2 instructions.
+ if (__builtin_cpu_supports("sse2")) {
+ return SIMD_SSE2;
+ }
+
+ return SIMD_NONE;
+}
+
+#endif /* HAVE_X86INTRIN_H */
+#endif /* X86_64 Support */
+
+#endif /* JSON_ENABLE_SIMD */
+
+#ifndef FIND_SIMD_IMPLEMENTATION_DEFINED
+static inline SIMD_Implementation find_simd_implementation(void)
+{
+ return SIMD_NONE;
+}
+#endif
diff --git a/ext/json/vendor/fpconv.c b/ext/json/vendor/fpconv.c
new file mode 100644
index 0000000000..6c9bc2c103
--- /dev/null
+++ b/ext/json/vendor/fpconv.c
@@ -0,0 +1,480 @@
+// Boost Software License - Version 1.0 - August 17th, 2003
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+// The contents of this file is extracted from https://github.com/night-shift/fpconv
+// It was slightly modified to append ".0" to plain floats, for use with the https://github.com/ruby/json package.
+
+#include <stdbool.h>
+#include <string.h>
+#include <stdint.h>
+
+#if JSON_DEBUG
+#include <assert.h>
+#endif
+
+#define npowers 87
+#define steppowers 8
+#define firstpower -348 /* 10 ^ -348 */
+
+#define expmax -32
+#define expmin -60
+
+typedef struct Fp {
+ uint64_t frac;
+ int exp;
+} Fp;
+
+static const Fp powers_ten[] = {
+ { 18054884314459144840U, -1220 }, { 13451937075301367670U, -1193 },
+ { 10022474136428063862U, -1166 }, { 14934650266808366570U, -1140 },
+ { 11127181549972568877U, -1113 }, { 16580792590934885855U, -1087 },
+ { 12353653155963782858U, -1060 }, { 18408377700990114895U, -1034 },
+ { 13715310171984221708U, -1007 }, { 10218702384817765436U, -980 },
+ { 15227053142812498563U, -954 }, { 11345038669416679861U, -927 },
+ { 16905424996341287883U, -901 }, { 12595523146049147757U, -874 },
+ { 9384396036005875287U, -847 }, { 13983839803942852151U, -821 },
+ { 10418772551374772303U, -794 }, { 15525180923007089351U, -768 },
+ { 11567161174868858868U, -741 }, { 17236413322193710309U, -715 },
+ { 12842128665889583758U, -688 }, { 9568131466127621947U, -661 },
+ { 14257626930069360058U, -635 }, { 10622759856335341974U, -608 },
+ { 15829145694278690180U, -582 }, { 11793632577567316726U, -555 },
+ { 17573882009934360870U, -529 }, { 13093562431584567480U, -502 },
+ { 9755464219737475723U, -475 }, { 14536774485912137811U, -449 },
+ { 10830740992659433045U, -422 }, { 16139061738043178685U, -396 },
+ { 12024538023802026127U, -369 }, { 17917957937422433684U, -343 },
+ { 13349918974505688015U, -316 }, { 9946464728195732843U, -289 },
+ { 14821387422376473014U, -263 }, { 11042794154864902060U, -236 },
+ { 16455045573212060422U, -210 }, { 12259964326927110867U, -183 },
+ { 18268770466636286478U, -157 }, { 13611294676837538539U, -130 },
+ { 10141204801825835212U, -103 }, { 15111572745182864684U, -77 },
+ { 11258999068426240000U, -50 }, { 16777216000000000000U, -24 },
+ { 12500000000000000000U, 3 }, { 9313225746154785156U, 30 },
+ { 13877787807814456755U, 56 }, { 10339757656912845936U, 83 },
+ { 15407439555097886824U, 109 }, { 11479437019748901445U, 136 },
+ { 17105694144590052135U, 162 }, { 12744735289059618216U, 189 },
+ { 9495567745759798747U, 216 }, { 14149498560666738074U, 242 },
+ { 10542197943230523224U, 269 }, { 15709099088952724970U, 295 },
+ { 11704190886730495818U, 322 }, { 17440603504673385349U, 348 },
+ { 12994262207056124023U, 375 }, { 9681479787123295682U, 402 },
+ { 14426529090290212157U, 428 }, { 10748601772107342003U, 455 },
+ { 16016664761464807395U, 481 }, { 11933345169920330789U, 508 },
+ { 17782069995880619868U, 534 }, { 13248674568444952270U, 561 },
+ { 9871031767461413346U, 588 }, { 14708983551653345445U, 614 },
+ { 10959046745042015199U, 641 }, { 16330252207878254650U, 667 },
+ { 12166986024289022870U, 694 }, { 18130221999122236476U, 720 },
+ { 13508068024458167312U, 747 }, { 10064294952495520794U, 774 },
+ { 14996968138956309548U, 800 }, { 11173611982879273257U, 827 },
+ { 16649979327439178909U, 853 }, { 12405201291620119593U, 880 },
+ { 9242595204427927429U, 907 }, { 13772540099066387757U, 933 },
+ { 10261342003245940623U, 960 }, { 15290591125556738113U, 986 },
+ { 11392378155556871081U, 1013 }, { 16975966327722178521U, 1039 },
+ { 12648080533535911531U, 1066 }
+};
+
+static Fp find_cachedpow10(int exp, int* k)
+{
+ const double one_log_ten = 0.30102999566398114;
+
+ int approx = (int)(-(exp + npowers) * one_log_ten);
+ int idx = (approx - firstpower) / steppowers;
+
+ while(1) {
+ int current = exp + powers_ten[idx].exp + 64;
+
+ if(current < expmin) {
+ idx++;
+ continue;
+ }
+
+ if(current > expmax) {
+ idx--;
+ continue;
+ }
+
+ *k = (firstpower + idx * steppowers);
+
+ return powers_ten[idx];
+ }
+}
+
+#define fracmask 0x000FFFFFFFFFFFFFU
+#define expmask 0x7FF0000000000000U
+#define hiddenbit 0x0010000000000000U
+#define signmask 0x8000000000000000U
+#define expbias (1023 + 52)
+
+#define absv(n) ((n) < 0 ? -(n) : (n))
+#define minv(a, b) ((a) < (b) ? (a) : (b))
+
+static const uint64_t tens[] = {
+ 10000000000000000000U, 1000000000000000000U, 100000000000000000U,
+ 10000000000000000U, 1000000000000000U, 100000000000000U,
+ 10000000000000U, 1000000000000U, 100000000000U,
+ 10000000000U, 1000000000U, 100000000U,
+ 10000000U, 1000000U, 100000U,
+ 10000U, 1000U, 100U,
+ 10U, 1U
+};
+
+static inline uint64_t get_dbits(double d)
+{
+ union {
+ double dbl;
+ uint64_t i;
+ } dbl_bits = { d };
+
+ return dbl_bits.i;
+}
+
+static Fp build_fp(double d)
+{
+ uint64_t bits = get_dbits(d);
+
+ Fp fp;
+ fp.frac = bits & fracmask;
+ fp.exp = (bits & expmask) >> 52;
+
+ if(fp.exp) {
+ fp.frac += hiddenbit;
+ fp.exp -= expbias;
+
+ } else {
+ fp.exp = -expbias + 1;
+ }
+
+ return fp;
+}
+
+static void normalize(Fp* fp)
+{
+ while ((fp->frac & hiddenbit) == 0) {
+ fp->frac <<= 1;
+ fp->exp--;
+ }
+
+ int shift = 64 - 52 - 1;
+ fp->frac <<= shift;
+ fp->exp -= shift;
+}
+
+static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper)
+{
+ upper->frac = (fp->frac << 1) + 1;
+ upper->exp = fp->exp - 1;
+
+ while ((upper->frac & (hiddenbit << 1)) == 0) {
+ upper->frac <<= 1;
+ upper->exp--;
+ }
+
+ int u_shift = 64 - 52 - 2;
+
+ upper->frac <<= u_shift;
+ upper->exp = upper->exp - u_shift;
+
+
+ int l_shift = fp->frac == hiddenbit ? 2 : 1;
+
+ lower->frac = (fp->frac << l_shift) - 1;
+ lower->exp = fp->exp - l_shift;
+
+
+ lower->frac <<= lower->exp - upper->exp;
+ lower->exp = upper->exp;
+}
+
+static Fp multiply(Fp* a, Fp* b)
+{
+ const uint64_t lomask = 0x00000000FFFFFFFF;
+
+ uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask);
+ uint64_t al_bh = (a->frac & lomask) * (b->frac >> 32);
+ uint64_t al_bl = (a->frac & lomask) * (b->frac & lomask);
+ uint64_t ah_bh = (a->frac >> 32) * (b->frac >> 32);
+
+ uint64_t tmp = (ah_bl & lomask) + (al_bh & lomask) + (al_bl >> 32);
+ /* round up */
+ tmp += 1U << 31;
+
+ Fp fp = {
+ ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32),
+ a->exp + b->exp + 64
+ };
+
+ return fp;
+}
+
+static void round_digit(char* digits, int ndigits, uint64_t delta, uint64_t rem, uint64_t kappa, uint64_t frac)
+{
+ while (rem < frac && delta - rem >= kappa &&
+ (rem + kappa < frac || frac - rem > rem + kappa - frac)) {
+
+ digits[ndigits - 1]--;
+ rem += kappa;
+ }
+}
+
+static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
+{
+ uint64_t wfrac = upper->frac - fp->frac;
+ uint64_t delta = upper->frac - lower->frac;
+
+ Fp one;
+ one.frac = 1ULL << -upper->exp;
+ one.exp = upper->exp;
+
+ uint64_t part1 = upper->frac >> -one.exp;
+ uint64_t part2 = upper->frac & (one.frac - 1);
+
+ int idx = 0, kappa = 10;
+ const uint64_t* divp;
+ /* 1000000000 */
+ for(divp = tens + 10; kappa > 0; divp++) {
+
+ uint64_t div = *divp;
+ unsigned digit = (unsigned) (part1 / div);
+
+ if (digit || idx) {
+ digits[idx++] = digit + '0';
+ }
+
+ part1 -= digit * div;
+ kappa--;
+
+ uint64_t tmp = (part1 <<-one.exp) + part2;
+ if (tmp <= delta) {
+ *K += kappa;
+ round_digit(digits, idx, delta, tmp, div << -one.exp, wfrac);
+
+ return idx;
+ }
+ }
+
+ /* 10 */
+ const uint64_t* unit = tens + 18;
+
+ while(true) {
+ part2 *= 10;
+ delta *= 10;
+ kappa--;
+
+ unsigned digit = (unsigned) (part2 >> -one.exp);
+ if (digit || idx) {
+ digits[idx++] = digit + '0';
+ }
+
+ part2 &= one.frac - 1;
+ if (part2 < delta) {
+ *K += kappa;
+ round_digit(digits, idx, delta, part2, one.frac, wfrac * *unit);
+
+ return idx;
+ }
+
+ unit--;
+ }
+}
+
+static int grisu2(double d, char* digits, int* K)
+{
+ Fp w = build_fp(d);
+
+ Fp lower, upper;
+ get_normalized_boundaries(&w, &lower, &upper);
+
+ normalize(&w);
+
+ int k;
+ Fp cp = find_cachedpow10(upper.exp, &k);
+
+ w = multiply(&w, &cp);
+ upper = multiply(&upper, &cp);
+ lower = multiply(&lower, &cp);
+
+ lower.frac++;
+ upper.frac--;
+
+ *K = -k;
+
+ return generate_digits(&w, &upper, &lower, digits, K);
+}
+
+static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg)
+{
+ int exp = absv(K + ndigits - 1);
+
+ if(K >= 0 && exp < 15) {
+ memcpy(dest, digits, ndigits);
+ memset(dest + ndigits, '0', K);
+
+ /* add a .0 to mark this as a float. */
+ dest[ndigits + K] = '.';
+ dest[ndigits + K + 1] = '0';
+
+ return ndigits + K + 2;
+ }
+
+ /* write decimal w/o scientific notation */
+ if(K < 0 && (K > -7 || exp < 10)) {
+ int offset = ndigits - absv(K);
+ /* fp < 1.0 -> write leading zero */
+ if(offset <= 0) {
+ offset = -offset;
+ dest[0] = '0';
+ dest[1] = '.';
+ memset(dest + 2, '0', offset);
+ memcpy(dest + offset + 2, digits, ndigits);
+
+ return ndigits + 2 + offset;
+
+ /* fp > 1.0 */
+ } else {
+ memcpy(dest, digits, offset);
+ dest[offset] = '.';
+ memcpy(dest + offset + 1, digits + offset, ndigits - offset);
+
+ return ndigits + 1;
+ }
+ }
+
+ /* write decimal w/ scientific notation */
+ ndigits = minv(ndigits, 18 - neg);
+
+ int idx = 0;
+ dest[idx++] = digits[0];
+
+ if(ndigits > 1) {
+ dest[idx++] = '.';
+ memcpy(dest + idx, digits + 1, ndigits - 1);
+ idx += ndigits - 1;
+ }
+
+ dest[idx++] = 'e';
+
+ char sign = K + ndigits - 1 < 0 ? '-' : '+';
+ dest[idx++] = sign;
+
+ int cent = 0;
+
+ if(exp > 99) {
+ cent = exp / 100;
+ dest[idx++] = cent + '0';
+ exp -= cent * 100;
+ }
+ if(exp > 9) {
+ int dec = exp / 10;
+ dest[idx++] = dec + '0';
+ exp -= dec * 10;
+
+ } else if(cent) {
+ dest[idx++] = '0';
+ }
+
+ dest[idx++] = exp % 10 + '0';
+
+ return idx;
+}
+
+static int filter_special(double fp, char* dest)
+{
+ if(fp == 0.0) {
+ dest[0] = '0';
+ dest[1] = '.';
+ dest[2] = '0';
+ return 3;
+ }
+
+ uint64_t bits = get_dbits(fp);
+
+ bool nan = (bits & expmask) == expmask;
+
+ if(!nan) {
+ return 0;
+ }
+
+ if(bits & fracmask) {
+ dest[0] = 'n'; dest[1] = 'a'; dest[2] = 'n';
+
+ } else {
+ dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f';
+ }
+
+ return 3;
+}
+
+/* Fast and accurate double to string conversion based on Florian Loitsch's
+ * Grisu-algorithm[1].
+ *
+ * Input:
+ * fp -> the double to convert, dest -> destination buffer.
+ * The generated string will never be longer than 32 characters.
+ * Make sure to pass a pointer to at least 32 bytes of memory.
+ * The emitted string will not be null terminated.
+ *
+ *
+ *
+ * Output:
+ * The number of written characters.
+ *
+ * Exemplary usage:
+ *
+ * void print(double d)
+ * {
+ * char buf[28 + 1] // plus null terminator
+ * int str_len = fpconv_dtoa(d, buf);
+ *
+ * buf[str_len] = '\0';
+ * printf("%s", buf);
+ * }
+ *
+ */
+static int fpconv_dtoa(double d, char dest[32])
+{
+ char digits[18];
+
+ int str_len = 0;
+ bool neg = false;
+
+ if(get_dbits(d) & signmask) {
+ dest[0] = '-';
+ str_len++;
+ neg = true;
+ }
+
+ int spec = filter_special(d, dest + str_len);
+
+ if(spec) {
+ return str_len + spec;
+ }
+
+ int K = 0;
+ int ndigits = grisu2(d, digits, &K);
+
+ str_len += emit_digits(digits, ndigits, dest + str_len, K, neg);
+#if JSON_DEBUG
+ assert(str_len <= 32);
+#endif
+
+ return str_len;
+}
diff --git a/ext/json/vendor/jeaiii-ltoa.h b/ext/json/vendor/jeaiii-ltoa.h
new file mode 100644
index 0000000000..ba4f497fc8
--- /dev/null
+++ b/ext/json/vendor/jeaiii-ltoa.h
@@ -0,0 +1,267 @@
+/*
+
+This file is released under the terms of the MIT License. It is based on the
+work of James Edward Anhalt III, with the original license listed below.
+
+MIT License
+
+Copyright (c) 2024,2025 Enrico Thierbach - https://github.com/radiospiel
+Copyright (c) 2022 James Edward Anhalt III - https://github.com/jeaiii/itoa
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef JEAIII_TO_TEXT_H_
+#define JEAIII_TO_TEXT_H_
+
+#include <stdint.h>
+
+typedef uint_fast32_t u32_t;
+typedef uint_fast64_t u64_t;
+
+#define u32(x) ((u32_t)(x))
+#define u64(x) ((u64_t)(x))
+
+struct digit_pair
+{
+ char dd[2];
+};
+
+static const struct digit_pair *digits_dd = (struct digit_pair *)(
+ "00" "01" "02" "03" "04" "05" "06" "07" "08" "09"
+ "10" "11" "12" "13" "14" "15" "16" "17" "18" "19"
+ "20" "21" "22" "23" "24" "25" "26" "27" "28" "29"
+ "30" "31" "32" "33" "34" "35" "36" "37" "38" "39"
+ "40" "41" "42" "43" "44" "45" "46" "47" "48" "49"
+ "50" "51" "52" "53" "54" "55" "56" "57" "58" "59"
+ "60" "61" "62" "63" "64" "65" "66" "67" "68" "69"
+ "70" "71" "72" "73" "74" "75" "76" "77" "78" "79"
+ "80" "81" "82" "83" "84" "85" "86" "87" "88" "89"
+ "90" "91" "92" "93" "94" "95" "96" "97" "98" "99"
+);
+
+static const struct digit_pair *digits_fd = (struct digit_pair *)(
+ "0_" "1_" "2_" "3_" "4_" "5_" "6_" "7_" "8_" "9_"
+ "10" "11" "12" "13" "14" "15" "16" "17" "18" "19"
+ "20" "21" "22" "23" "24" "25" "26" "27" "28" "29"
+ "30" "31" "32" "33" "34" "35" "36" "37" "38" "39"
+ "40" "41" "42" "43" "44" "45" "46" "47" "48" "49"
+ "50" "51" "52" "53" "54" "55" "56" "57" "58" "59"
+ "60" "61" "62" "63" "64" "65" "66" "67" "68" "69"
+ "70" "71" "72" "73" "74" "75" "76" "77" "78" "79"
+ "80" "81" "82" "83" "84" "85" "86" "87" "88" "89"
+ "90" "91" "92" "93" "94" "95" "96" "97" "98" "99"
+);
+
+static const u64_t mask24 = (u64(1) << 24) - 1;
+static const u64_t mask32 = (u64(1) << 32) - 1;
+static const u64_t mask57 = (u64(1) << 57) - 1;
+
+#define COPY(buffer, digits) memcpy(buffer, &(digits), sizeof(struct digit_pair))
+
+static char *
+jeaiii_ultoa(char *b, u64_t n)
+{
+ if (n < u32(1e2)) {
+ COPY(b, digits_fd[n]);
+ return n < 10 ? b + 1 : b + 2;
+ }
+
+ if (n < u32(1e6)) {
+ if (n < u32(1e4)) {
+ u32_t f0 = u32((10 * (1 << 24) / 1e3 + 1) * n);
+ COPY(b, digits_fd[f0 >> 24]);
+
+ b -= n < u32(1e3);
+ u32_t f2 = (f0 & mask24) * 100;
+ COPY(b + 2, digits_dd[f2 >> 24]);
+
+ return b + 4;
+ }
+
+ u64_t f0 = u64(10 * (1ull << 32ull)/ 1e5 + 1) * n;
+ COPY(b, digits_fd[f0 >> 32]);
+
+ b -= n < u32(1e5);
+ u64_t f2 = (f0 & mask32) * 100;
+ COPY(b + 2, digits_dd[f2 >> 32]);
+
+ u64_t f4 = (f2 & mask32) * 100;
+ COPY(b + 4, digits_dd[f4 >> 32]);
+ return b + 6;
+ }
+
+ if (n < u64(1ull << 32ull)) {
+ if (n < u32(1e8)) {
+ u64_t f0 = u64(10 * (1ull << 48ull) / 1e7 + 1) * n >> 16;
+ COPY(b, digits_fd[f0 >> 32]);
+
+ b -= n < u32(1e7);
+ u64_t f2 = (f0 & mask32) * 100;
+ COPY(b + 2, digits_dd[f2 >> 32]);
+
+ u64_t f4 = (f2 & mask32) * 100;
+ COPY(b + 4, digits_dd[f4 >> 32]);
+
+ u64_t f6 = (f4 & mask32) * 100;
+ COPY(b + 6, digits_dd[f6 >> 32]);
+
+ return b + 8;
+ }
+
+ u64_t f0 = u64(10 * (1ull << 57ull) / 1e9 + 1) * n;
+ COPY(b, digits_fd[f0 >> 57]);
+
+ b -= n < u32(1e9);
+ u64_t f2 = (f0 & mask57) * 100;
+ COPY(b + 2, digits_dd[f2 >> 57]);
+
+ u64_t f4 = (f2 & mask57) * 100;
+ COPY(b + 4, digits_dd[f4 >> 57]);
+
+ u64_t f6 = (f4 & mask57) * 100;
+ COPY(b + 6, digits_dd[f6 >> 57]);
+
+ u64_t f8 = (f6 & mask57) * 100;
+ COPY(b + 8, digits_dd[f8 >> 57]);
+
+ return b + 10;
+ }
+
+ // if we get here U must be u64 but some compilers don't know that, so reassign n to a u64 to avoid warnings
+ u32_t z = n % u32(1e8);
+ u64_t u = n / u32(1e8);
+
+ if (u < u32(1e2)) {
+ // u can't be 1 digit (if u < 10 it would have been handled above as a 9 digit 32bit number)
+ COPY(b, digits_dd[u]);
+ b += 2;
+ }
+ else if (u < u32(1e6)) {
+ if (u < u32(1e4)) {
+ u32_t f0 = u32((10 * (1 << 24) / 1e3 + 1) * u);
+ COPY(b, digits_fd[f0 >> 24]);
+
+ b -= u < u32(1e3);
+ u32_t f2 = (f0 & mask24) * 100;
+ COPY(b + 2, digits_dd[f2 >> 24]);
+ b += 4;
+ }
+ else {
+ u64_t f0 = u64(10 * (1ull << 32ull) / 1e5 + 1) * u;
+ COPY(b, digits_fd[f0 >> 32]);
+
+ b -= u < u32(1e5);
+ u64_t f2 = (f0 & mask32) * 100;
+ COPY(b + 2, digits_dd[f2 >> 32]);
+
+ u64_t f4 = (f2 & mask32) * 100;
+ COPY(b + 4, digits_dd[f4 >> 32]);
+ b += 6;
+ }
+ }
+ else if (u < u32(1e8)) {
+ u64_t f0 = u64(10 * (1ull << 48ull) / 1e7 + 1) * u >> 16;
+ COPY(b, digits_fd[f0 >> 32]);
+
+ b -= u < u32(1e7);
+ u64_t f2 = (f0 & mask32) * 100;
+ COPY(b + 2, digits_dd[f2 >> 32]);
+
+ u64_t f4 = (f2 & mask32) * 100;
+ COPY(b + 4, digits_dd[f4 >> 32]);
+
+ u64_t f6 = (f4 & mask32) * 100;
+ COPY(b + 6, digits_dd[f6 >> 32]);
+
+ b += 8;
+ }
+ else if (u < u64(1ull << 32ull)) {
+ u64_t f0 = u64(10 * (1ull << 57ull) / 1e9 + 1) * u;
+ COPY(b, digits_fd[f0 >> 57]);
+
+ b -= u < u32(1e9);
+ u64_t f2 = (f0 & mask57) * 100;
+ COPY(b + 2, digits_dd[f2 >> 57]);
+
+ u64_t f4 = (f2 & mask57) * 100;
+ COPY(b + 4, digits_dd[f4 >> 57]);
+
+ u64_t f6 = (f4 & mask57) * 100;
+ COPY(b + 6, digits_dd[f6 >> 57]);
+
+ u64_t f8 = (f6 & mask57) * 100;
+ COPY(b + 8, digits_dd[f8 >> 57]);
+ b += 10;
+ }
+ else {
+ u32_t y = u % u32(1e8);
+ u /= u32(1e8);
+
+ // u is 2, 3, or 4 digits (if u < 10 it would have been handled above)
+ if (u < u32(1e2)) {
+ COPY(b, digits_dd[u]);
+ b += 2;
+ }
+ else {
+ u32_t f0 = u32((10 * (1 << 24) / 1e3 + 1) * u);
+ COPY(b, digits_fd[f0 >> 24]);
+
+ b -= u < u32(1e3);
+ u32_t f2 = (f0 & mask24) * 100;
+ COPY(b + 2, digits_dd[f2 >> 24]);
+
+ b += 4;
+ }
+ // do 8 digits
+ u64_t f0 = (u64((1ull << 48ull) / 1e6 + 1) * y >> 16) + 1;
+ COPY(b, digits_dd[f0 >> 32]);
+
+ u64_t f2 = (f0 & mask32) * 100;
+ COPY(b + 2, digits_dd[f2 >> 32]);
+
+ u64_t f4 = (f2 & mask32) * 100;
+ COPY(b + 4, digits_dd[f4 >> 32]);
+
+ u64_t f6 = (f4 & mask32) * 100;
+ COPY(b + 6, digits_dd[f6 >> 32]);
+ b += 8;
+ }
+
+ // do 8 digits
+ u64_t f0 = (u64((1ull << 48ull) / 1e6 + 1) * z >> 16) + 1;
+ COPY(b, digits_dd[f0 >> 32]);
+
+ u64_t f2 = (f0 & mask32) * 100;
+ COPY(b + 2, digits_dd[f2 >> 32]);
+
+ u64_t f4 = (f2 & mask32) * 100;
+ COPY(b + 4, digits_dd[f4 >> 32]);
+
+ u64_t f6 = (f4 & mask32) * 100;
+ COPY(b + 6, digits_dd[f6 >> 32]);
+
+ return b + 8;
+}
+
+#undef u32
+#undef u64
+#undef COPY
+
+#endif // JEAIII_TO_TEXT_H_
diff --git a/ext/json/vendor/ryu.h b/ext/json/vendor/ryu.h
new file mode 100644
index 0000000000..f06ec814b4
--- /dev/null
+++ b/ext/json/vendor/ryu.h
@@ -0,0 +1,819 @@
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+//
+// ---
+//
+// Apache License
+// Version 2.0, January 2004
+// http://www.apache.org/licenses/
+//
+// TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+//
+// 1. Definitions.
+//
+// "License" shall mean the terms and conditions for use, reproduction,
+// and distribution as defined by Sections 1 through 9 of this document.
+//
+// "Licensor" shall mean the copyright owner or entity authorized by
+// the copyright owner that is granting the License.
+//
+// "Legal Entity" shall mean the union of the acting entity and all
+// other entities that control, are controlled by, or are under common
+// control with that entity. For the purposes of this definition,
+// "control" means (i) the power, direct or indirect, to cause the
+// direction or management of such entity, whether by contract or
+// otherwise, or (ii) ownership of fifty percent (50%) or more of the
+// outstanding shares, or (iii) beneficial ownership of such entity.
+//
+// "You" (or "Your") shall mean an individual or Legal Entity
+// exercising permissions granted by this License.
+//
+// "Source" form shall mean the preferred form for making modifications,
+// including but not limited to software source code, documentation
+// source, and configuration files.
+//
+// "Object" form shall mean any form resulting from mechanical
+// transformation or translation of a Source form, including but
+// not limited to compiled object code, generated documentation,
+// and conversions to other media types.
+//
+// "Work" shall mean the work of authorship, whether in Source or
+// Object form, made available under the License, as indicated by a
+// copyright notice that is included in or attached to the work
+// (an example is provided in the Appendix below).
+//
+// "Derivative Works" shall mean any work, whether in Source or Object
+// form, that is based on (or derived from) the Work and for which the
+// editorial revisions, annotations, elaborations, or other modifications
+// represent, as a whole, an original work of authorship. For the purposes
+// of this License, Derivative Works shall not include works that remain
+// separable from, or merely link (or bind by name) to the interfaces of,
+// the Work and Derivative Works thereof.
+//
+// "Contribution" shall mean any work of authorship, including
+// the original version of the Work and any modifications or additions
+// to that Work or Derivative Works thereof, that is intentionally
+// submitted to Licensor for inclusion in the Work by the copyright owner
+// or by an individual or Legal Entity authorized to submit on behalf of
+// the copyright owner. For the purposes of this definition, "submitted"
+// means any form of electronic, verbal, or written communication sent
+// to the Licensor or its representatives, including but not limited to
+// communication on electronic mailing lists, source code control systems,
+// and issue tracking systems that are managed by, or on behalf of, the
+// Licensor for the purpose of discussing and improving the Work, but
+// excluding communication that is conspicuously marked or otherwise
+// designated in writing by the copyright owner as "Not a Contribution."
+//
+// "Contributor" shall mean Licensor and any individual or Legal Entity
+// on behalf of whom a Contribution has been received by Licensor and
+// subsequently incorporated within the Work.
+//
+// 2. Grant of Copyright License. Subject to the terms and conditions of
+// this License, each Contributor hereby grants to You a perpetual,
+// worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+// copyright license to reproduce, prepare Derivative Works of,
+// publicly display, publicly perform, sublicense, and distribute the
+// Work and such Derivative Works in Source or Object form.
+//
+// 3. Grant of Patent License. Subject to the terms and conditions of
+// this License, each Contributor hereby grants to You a perpetual,
+// worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+// (except as stated in this section) patent license to make, have made,
+// use, offer to sell, sell, import, and otherwise transfer the Work,
+// where such license applies only to those patent claims licensable
+// by such Contributor that are necessarily infringed by their
+// Contribution(s) alone or by combination of their Contribution(s)
+// with the Work to which such Contribution(s) was submitted. If You
+// institute patent litigation against any entity (including a
+// cross-claim or counterclaim in a lawsuit) alleging that the Work
+// or a Contribution incorporated within the Work constitutes direct
+// or contributory patent infringement, then any patent licenses
+// granted to You under this License for that Work shall terminate
+// as of the date such litigation is filed.
+//
+// 4. Redistribution. You may reproduce and distribute copies of the
+// Work or Derivative Works thereof in any medium, with or without
+// modifications, and in Source or Object form, provided that You
+// meet the following conditions:
+//
+// (a) You must give any other recipients of the Work or
+// Derivative Works a copy of this License; and
+//
+// (b) You must cause any modified files to carry prominent notices
+// stating that You changed the files; and
+//
+// (c) You must retain, in the Source form of any Derivative Works
+// that You distribute, all copyright, patent, trademark, and
+// attribution notices from the Source form of the Work,
+// excluding those notices that do not pertain to any part of
+// the Derivative Works; and
+//
+// (d) If the Work includes a "NOTICE" text file as part of its
+// distribution, then any Derivative Works that You distribute must
+// include a readable copy of the attribution notices contained
+// within such NOTICE file, excluding those notices that do not
+// pertain to any part of the Derivative Works, in at least one
+// of the following places: within a NOTICE text file distributed
+// as part of the Derivative Works; within the Source form or
+// documentation, if provided along with the Derivative Works; or,
+// within a display generated by the Derivative Works, if and
+// wherever such third-party notices normally appear. The contents
+// of the NOTICE file are for informational purposes only and
+// do not modify the License. You may add Your own attribution
+// notices within Derivative Works that You distribute, alongside
+// or as an addendum to the NOTICE text from the Work, provided
+// that such additional attribution notices cannot be construed
+// as modifying the License.
+//
+// You may add Your own copyright statement to Your modifications and
+// may provide additional or different license terms and conditions
+// for use, reproduction, or distribution of Your modifications, or
+// for any such Derivative Works as a whole, provided Your use,
+// reproduction, and distribution of the Work otherwise complies with
+// the conditions stated in this License.
+//
+// 5. Submission of Contributions. Unless You explicitly state otherwise,
+// any Contribution intentionally submitted for inclusion in the Work
+// by You to the Licensor shall be under the terms and conditions of
+// this License, without any additional terms or conditions.
+// Notwithstanding the above, nothing herein shall supersede or modify
+// the terms of any separate license agreement you may have executed
+// with Licensor regarding such Contributions.
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor,
+// except as required for reasonable and customary use in describing the
+// origin of the Work and reproducing the content of the NOTICE file.
+//
+// 7. Disclaimer of Warranty. Unless required by applicable law or
+// agreed to in writing, Licensor provides the Work (and each
+// Contributor provides its Contributions) on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied, including, without limitation, any warranties or conditions
+// of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+// PARTICULAR PURPOSE. You are solely responsible for determining the
+// appropriateness of using or redistributing the Work and assume any
+// risks associated with Your exercise of permissions under this License.
+//
+// 8. Limitation of Liability. In no event and under no legal theory,
+// whether in tort (including negligence), contract, or otherwise,
+// unless required by applicable law (such as deliberate and grossly
+// negligent acts) or agreed to in writing, shall any Contributor be
+// liable to You for damages, including any direct, indirect, special,
+// incidental, or consequential damages of any character arising as a
+// result of this License or out of the use or inability to use the
+// Work (including but not limited to damages for loss of goodwill,
+// work stoppage, computer failure or malfunction, or any and all
+// other commercial damages or losses), even if such Contributor
+// has been advised of the possibility of such damages.
+//
+// 9. Accepting Warranty or Additional Liability. While redistributing
+// the Work or Derivative Works thereof, You may choose to offer,
+// and charge a fee for, acceptance of support, warranty, indemnity,
+// or other liability obligations and/or rights consistent with this
+// License. However, in accepting such obligations, You may act only
+// on Your own behalf and on Your sole responsibility, not on behalf
+// of any other Contributor, and only if You agree to indemnify,
+// defend, and hold each Contributor harmless for any liability
+// incurred by, or claims asserted against, such Contributor by reason
+// of your accepting any such warranty or additional liability.
+//
+// END OF TERMS AND CONDITIONS
+//
+// APPENDIX: How to apply the Apache License to your work.
+//
+// To apply the Apache License to your work, attach the following
+// boilerplate notice, with the fields enclosed by brackets "[]"
+// replaced with your own identifying information. (Don't include
+// the brackets!) The text should be enclosed in the appropriate
+// comment syntax for the file format. We also recommend that a
+// file or class name and description of purpose be included on the
+// same "printed page" as the copyright notice for easier
+// identification within third-party archives.
+//
+// Copyright [yyyy] [name of copyright owner]
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// ---
+//
+// Boost Software License - Version 1.0 - August 17th, 2003
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// ---
+// Minimal Ryu implementation adapted for Ruby JSON gem by Josef Šimánek
+// Optimized for pre-extracted mantissa/exponent from JSON parsing
+// This is a stripped-down version containing only what's needed for
+// converting decimal mantissa+exponent to IEEE 754 double precision.
+
+#ifndef RYU_H
+#define RYU_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+// Detect __builtin_clzll availability (for floor_log2)
+// Note: MSVC doesn't have __builtin_clzll, so we provide a fallback
+#ifdef __clang__
+ #if __has_builtin(__builtin_clzll)
+ #define RYU_HAVE_BUILTIN_CLZLL 1
+ #else
+ #define RYU_HAVE_BUILTIN_CLZLL 0
+ #endif
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+ #define RYU_HAVE_BUILTIN_CLZLL 1
+#else
+ #define RYU_HAVE_BUILTIN_CLZLL 0
+#endif
+
+// Count leading zeros (for floor_log2)
+static inline uint32_t ryu_leading_zeros64(uint64_t input)
+{
+#if RYU_HAVE_BUILTIN_CLZLL
+ return __builtin_clzll(input);
+#else
+ // Fallback: binary search for the highest set bit
+ // This works on MSVC and other compilers without __builtin_clzll
+ if (input == 0) return 64;
+ uint32_t n = 0;
+ if (input <= 0x00000000FFFFFFFFULL) { n += 32; input <<= 32; }
+ if (input <= 0x0000FFFFFFFFFFFFULL) { n += 16; input <<= 16; }
+ if (input <= 0x00FFFFFFFFFFFFFFULL) { n += 8; input <<= 8; }
+ if (input <= 0x0FFFFFFFFFFFFFFFULL) { n += 4; input <<= 4; }
+ if (input <= 0x3FFFFFFFFFFFFFFFULL) { n += 2; input <<= 2; }
+ if (input <= 0x7FFFFFFFFFFFFFFFULL) { n += 1; }
+ return n;
+#endif
+}
+
+// These tables are generated by PrintDoubleLookupTable.
+#define DOUBLE_POW5_INV_BITCOUNT 125
+#define DOUBLE_POW5_BITCOUNT 125
+
+#define DOUBLE_POW5_INV_TABLE_SIZE 342
+#define DOUBLE_POW5_TABLE_SIZE 326
+
+static const uint64_t DOUBLE_POW5_INV_SPLIT[DOUBLE_POW5_INV_TABLE_SIZE][2] = {
+ { 1u, 2305843009213693952u }, { 11068046444225730970u, 1844674407370955161u },
+ { 5165088340638674453u, 1475739525896764129u }, { 7821419487252849886u, 1180591620717411303u },
+ { 8824922364862649494u, 1888946593147858085u }, { 7059937891890119595u, 1511157274518286468u },
+ { 13026647942995916322u, 1208925819614629174u }, { 9774590264567735146u, 1934281311383406679u },
+ { 11509021026396098440u, 1547425049106725343u }, { 16585914450600699399u, 1237940039285380274u },
+ { 15469416676735388068u, 1980704062856608439u }, { 16064882156130220778u, 1584563250285286751u },
+ { 9162556910162266299u, 1267650600228229401u }, { 7281393426775805432u, 2028240960365167042u },
+ { 16893161185646375315u, 1622592768292133633u }, { 2446482504291369283u, 1298074214633706907u },
+ { 7603720821608101175u, 2076918743413931051u }, { 2393627842544570617u, 1661534994731144841u },
+ { 16672297533003297786u, 1329227995784915872u }, { 11918280793837635165u, 2126764793255865396u },
+ { 5845275820328197809u, 1701411834604692317u }, { 15744267100488289217u, 1361129467683753853u },
+ { 3054734472329800808u, 2177807148294006166u }, { 17201182836831481939u, 1742245718635204932u },
+ { 6382248639981364905u, 1393796574908163946u }, { 2832900194486363201u, 2230074519853062314u },
+ { 5955668970331000884u, 1784059615882449851u }, { 1075186361522890384u, 1427247692705959881u },
+ { 12788344622662355584u, 2283596308329535809u }, { 13920024512871794791u, 1826877046663628647u },
+ { 3757321980813615186u, 1461501637330902918u }, { 10384555214134712795u, 1169201309864722334u },
+ { 5547241898389809503u, 1870722095783555735u }, { 4437793518711847602u, 1496577676626844588u },
+ { 10928932444453298728u, 1197262141301475670u }, { 17486291911125277965u, 1915619426082361072u },
+ { 6610335899416401726u, 1532495540865888858u }, { 12666966349016942027u, 1225996432692711086u },
+ { 12888448528943286597u, 1961594292308337738u }, { 17689456452638449924u, 1569275433846670190u },
+ { 14151565162110759939u, 1255420347077336152u }, { 7885109000409574610u, 2008672555323737844u },
+ { 9997436015069570011u, 1606938044258990275u }, { 7997948812055656009u, 1285550435407192220u },
+ { 12796718099289049614u, 2056880696651507552u }, { 2858676849947419045u, 1645504557321206042u },
+ { 13354987924183666206u, 1316403645856964833u }, { 17678631863951955605u, 2106245833371143733u },
+ { 3074859046935833515u, 1684996666696914987u }, { 13527933681774397782u, 1347997333357531989u },
+ { 10576647446613305481u, 2156795733372051183u }, { 15840015586774465031u, 1725436586697640946u },
+ { 8982663654677661702u, 1380349269358112757u }, { 18061610662226169046u, 2208558830972980411u },
+ { 10759939715039024913u, 1766847064778384329u }, { 12297300586773130254u, 1413477651822707463u },
+ { 15986332124095098083u, 2261564242916331941u }, { 9099716884534168143u, 1809251394333065553u },
+ { 14658471137111155161u, 1447401115466452442u }, { 4348079280205103483u, 1157920892373161954u },
+ { 14335624477811986218u, 1852673427797059126u }, { 7779150767507678651u, 1482138742237647301u },
+ { 2533971799264232598u, 1185710993790117841u }, { 15122401323048503126u, 1897137590064188545u },
+ { 12097921058438802501u, 1517710072051350836u }, { 5988988032009131678u, 1214168057641080669u },
+ { 16961078480698431330u, 1942668892225729070u }, { 13568862784558745064u, 1554135113780583256u },
+ { 7165741412905085728u, 1243308091024466605u }, { 11465186260648137165u, 1989292945639146568u },
+ { 16550846638002330379u, 1591434356511317254u }, { 16930026125143774626u, 1273147485209053803u },
+ { 4951948911778577463u, 2037035976334486086u }, { 272210314680951647u, 1629628781067588869u },
+ { 3907117066486671641u, 1303703024854071095u }, { 6251387306378674625u, 2085924839766513752u },
+ { 16069156289328670670u, 1668739871813211001u }, { 9165976216721026213u, 1334991897450568801u },
+ { 7286864317269821294u, 2135987035920910082u }, { 16897537898041588005u, 1708789628736728065u },
+ { 13518030318433270404u, 1367031702989382452u }, { 6871453250525591353u, 2187250724783011924u },
+ { 9186511415162383406u, 1749800579826409539u }, { 11038557946871817048u, 1399840463861127631u },
+ { 10282995085511086630u, 2239744742177804210u }, { 8226396068408869304u, 1791795793742243368u },
+ { 13959814484210916090u, 1433436634993794694u }, { 11267656730511734774u, 2293498615990071511u },
+ { 5324776569667477496u, 1834798892792057209u }, { 7949170070475892320u, 1467839114233645767u },
+ { 17427382500606444826u, 1174271291386916613u }, { 5747719112518849781u, 1878834066219066582u },
+ { 15666221734240810795u, 1503067252975253265u }, { 12532977387392648636u, 1202453802380202612u },
+ { 5295368560860596524u, 1923926083808324180u }, { 4236294848688477220u, 1539140867046659344u },
+ { 7078384693692692099u, 1231312693637327475u }, { 11325415509908307358u, 1970100309819723960u },
+ { 9060332407926645887u, 1576080247855779168u }, { 14626963555825137356u, 1260864198284623334u },
+ { 12335095245094488799u, 2017382717255397335u }, { 9868076196075591040u, 1613906173804317868u },
+ { 15273158586344293478u, 1291124939043454294u }, { 13369007293925138595u, 2065799902469526871u },
+ { 7005857020398200553u, 1652639921975621497u }, { 16672732060544291412u, 1322111937580497197u },
+ { 11918976037903224966u, 2115379100128795516u }, { 5845832015580669650u, 1692303280103036413u },
+ { 12055363241948356366u, 1353842624082429130u }, { 841837113407818570u, 2166148198531886609u },
+ { 4362818505468165179u, 1732918558825509287u }, { 14558301248600263113u, 1386334847060407429u },
+ { 12225235553534690011u, 2218135755296651887u }, { 2401490813343931363u, 1774508604237321510u },
+ { 1921192650675145090u, 1419606883389857208u }, { 17831303500047873437u, 2271371013423771532u },
+ { 6886345170554478103u, 1817096810739017226u }, { 1819727321701672159u, 1453677448591213781u },
+ { 16213177116328979020u, 1162941958872971024u }, { 14873036941900635463u, 1860707134196753639u },
+ { 15587778368262418694u, 1488565707357402911u }, { 8780873879868024632u, 1190852565885922329u },
+ { 2981351763563108441u, 1905364105417475727u }, { 13453127855076217722u, 1524291284333980581u },
+ { 7073153469319063855u, 1219433027467184465u }, { 11317045550910502167u, 1951092843947495144u },
+ { 12742985255470312057u, 1560874275157996115u }, { 10194388204376249646u, 1248699420126396892u },
+ { 1553625868034358140u, 1997919072202235028u }, { 8621598323911307159u, 1598335257761788022u },
+ { 17965325103354776697u, 1278668206209430417u }, { 13987124906400001422u, 2045869129935088668u },
+ { 121653480894270168u, 1636695303948070935u }, { 97322784715416134u, 1309356243158456748u },
+ { 14913111714512307107u, 2094969989053530796u }, { 8241140556867935363u, 1675975991242824637u },
+ { 17660958889720079260u, 1340780792994259709u }, { 17189487779326395846u, 2145249268790815535u },
+ { 13751590223461116677u, 1716199415032652428u }, { 18379969808252713988u, 1372959532026121942u },
+ { 14650556434236701088u, 2196735251241795108u }, { 652398703163629901u, 1757388200993436087u },
+ { 11589965406756634890u, 1405910560794748869u }, { 7475898206584884855u, 2249456897271598191u },
+ { 2291369750525997561u, 1799565517817278553u }, { 9211793429904618695u, 1439652414253822842u },
+ { 18428218302589300235u, 2303443862806116547u }, { 7363877012587619542u, 1842755090244893238u },
+ { 13269799239553916280u, 1474204072195914590u }, { 10615839391643133024u, 1179363257756731672u },
+ { 2227947767661371545u, 1886981212410770676u }, { 16539753473096738529u, 1509584969928616540u },
+ { 13231802778477390823u, 1207667975942893232u }, { 6413489186596184024u, 1932268761508629172u },
+ { 16198837793502678189u, 1545815009206903337u }, { 5580372605318321905u, 1236652007365522670u },
+ { 8928596168509315048u, 1978643211784836272u }, { 18210923379033183008u, 1582914569427869017u },
+ { 7190041073742725760u, 1266331655542295214u }, { 436019273762630246u, 2026130648867672343u },
+ { 7727513048493924843u, 1620904519094137874u }, { 9871359253537050198u, 1296723615275310299u },
+ { 4726128361433549347u, 2074757784440496479u }, { 7470251503888749801u, 1659806227552397183u },
+ { 13354898832594820487u, 1327844982041917746u }, { 13989140502667892133u, 2124551971267068394u },
+ { 14880661216876224029u, 1699641577013654715u }, { 11904528973500979224u, 1359713261610923772u },
+ { 4289851098633925465u, 2175541218577478036u }, { 18189276137874781665u, 1740432974861982428u },
+ { 3483374466074094362u, 1392346379889585943u }, { 1884050330976640656u, 2227754207823337509u },
+ { 5196589079523222848u, 1782203366258670007u }, { 15225317707844309248u, 1425762693006936005u },
+ { 5913764258841343181u, 2281220308811097609u }, { 8420360221814984868u, 1824976247048878087u },
+ { 17804334621677718864u, 1459980997639102469u }, { 17932816512084085415u, 1167984798111281975u },
+ { 10245762345624985047u, 1868775676978051161u }, { 4507261061758077715u, 1495020541582440929u },
+ { 7295157664148372495u, 1196016433265952743u }, { 7982903447895485668u, 1913626293225524389u },
+ { 10075671573058298858u, 1530901034580419511u }, { 4371188443704728763u, 1224720827664335609u },
+ { 14372599139411386667u, 1959553324262936974u }, { 15187428126271019657u, 1567642659410349579u },
+ { 15839291315758726049u, 1254114127528279663u }, { 3206773216762499739u, 2006582604045247462u },
+ { 13633465017635730761u, 1605266083236197969u }, { 14596120828850494932u, 1284212866588958375u },
+ { 4907049252451240275u, 2054740586542333401u }, { 236290587219081897u, 1643792469233866721u },
+ { 14946427728742906810u, 1315033975387093376u }, { 16535586736504830250u, 2104054360619349402u },
+ { 5849771759720043554u, 1683243488495479522u }, { 15747863852001765813u, 1346594790796383617u },
+ { 10439186904235184007u, 2154551665274213788u }, { 15730047152871967852u, 1723641332219371030u },
+ { 12584037722297574282u, 1378913065775496824u }, { 9066413911450387881u, 2206260905240794919u },
+ { 10942479943902220628u, 1765008724192635935u }, { 8753983955121776503u, 1412006979354108748u },
+ { 10317025513452932081u, 2259211166966573997u }, { 874922781278525018u, 1807368933573259198u },
+ { 8078635854506640661u, 1445895146858607358u }, { 13841606313089133175u, 1156716117486885886u },
+ { 14767872471458792434u, 1850745787979017418u }, { 746251532941302978u, 1480596630383213935u },
+ { 597001226353042382u, 1184477304306571148u }, { 15712597221132509104u, 1895163686890513836u },
+ { 8880728962164096960u, 1516130949512411069u }, { 10793931984473187891u, 1212904759609928855u },
+ { 17270291175157100626u, 1940647615375886168u }, { 2748186495899949531u, 1552518092300708935u },
+ { 2198549196719959625u, 1242014473840567148u }, { 18275073973719576693u, 1987223158144907436u },
+ { 10930710364233751031u, 1589778526515925949u }, { 12433917106128911148u, 1271822821212740759u },
+ { 8826220925580526867u, 2034916513940385215u }, { 7060976740464421494u, 1627933211152308172u },
+ { 16716827836597268165u, 1302346568921846537u }, { 11989529279587987770u, 2083754510274954460u },
+ { 9591623423670390216u, 1667003608219963568u }, { 15051996368420132820u, 1333602886575970854u },
+ { 13015147745246481542u, 2133764618521553367u }, { 3033420566713364587u, 1707011694817242694u },
+ { 6116085268112601993u, 1365609355853794155u }, { 9785736428980163188u, 2184974969366070648u },
+ { 15207286772667951197u, 1747979975492856518u }, { 1097782973908629988u, 1398383980394285215u },
+ { 1756452758253807981u, 2237414368630856344u }, { 5094511021344956708u, 1789931494904685075u },
+ { 4075608817075965366u, 1431945195923748060u }, { 6520974107321544586u, 2291112313477996896u },
+ { 1527430471115325346u, 1832889850782397517u }, { 12289990821117991246u, 1466311880625918013u },
+ { 17210690286378213644u, 1173049504500734410u }, { 9090360384495590213u, 1876879207201175057u },
+ { 18340334751822203140u, 1501503365760940045u }, { 14672267801457762512u, 1201202692608752036u },
+ { 16096930852848599373u, 1921924308174003258u }, { 1809498238053148529u, 1537539446539202607u },
+ { 12515645034668249793u, 1230031557231362085u }, { 1578287981759648052u, 1968050491570179337u },
+ { 12330676829633449412u, 1574440393256143469u }, { 13553890278448669853u, 1259552314604914775u },
+ { 3239480371808320148u, 2015283703367863641u }, { 17348979556414297411u, 1612226962694290912u },
+ { 6500486015647617283u, 1289781570155432730u }, { 10400777625036187652u, 2063650512248692368u },
+ { 15699319729512770768u, 1650920409798953894u }, { 16248804598352126938u, 1320736327839163115u },
+ { 7551343283653851484u, 2113178124542660985u }, { 6041074626923081187u, 1690542499634128788u },
+ { 12211557331022285596u, 1352433999707303030u }, { 1091747655926105338u, 2163894399531684849u },
+ { 4562746939482794594u, 1731115519625347879u }, { 7339546366328145998u, 1384892415700278303u },
+ { 8053925371383123274u, 2215827865120445285u }, { 6443140297106498619u, 1772662292096356228u },
+ { 12533209867169019542u, 1418129833677084982u }, { 5295740528502789974u, 2269007733883335972u },
+ { 15304638867027962949u, 1815206187106668777u }, { 4865013464138549713u, 1452164949685335022u },
+ { 14960057215536570740u, 1161731959748268017u }, { 9178696285890871890u, 1858771135597228828u },
+ { 14721654658196518159u, 1487016908477783062u }, { 4398626097073393881u, 1189613526782226450u },
+ { 7037801755317430209u, 1903381642851562320u }, { 5630241404253944167u, 1522705314281249856u },
+ { 814844308661245011u, 1218164251424999885u }, { 1303750893857992017u, 1949062802279999816u },
+ { 15800395974054034906u, 1559250241823999852u }, { 5261619149759407279u, 1247400193459199882u },
+ { 12107939454356961969u, 1995840309534719811u }, { 5997002748743659252u, 1596672247627775849u },
+ { 8486951013736837725u, 1277337798102220679u }, { 2511075177753209390u, 2043740476963553087u },
+ { 13076906586428298482u, 1634992381570842469u }, { 14150874083884549109u, 1307993905256673975u },
+ { 4194654460505726958u, 2092790248410678361u }, { 18113118827372222859u, 1674232198728542688u },
+ { 3422448617672047318u, 1339385758982834151u }, { 16543964232501006678u, 2143017214372534641u },
+ { 9545822571258895019u, 1714413771498027713u }, { 15015355686490936662u, 1371531017198422170u },
+ { 5577825024675947042u, 2194449627517475473u }, { 11840957649224578280u, 1755559702013980378u },
+ { 16851463748863483271u, 1404447761611184302u }, { 12204946739213931940u, 2247116418577894884u },
+ { 13453306206113055875u, 1797693134862315907u }, { 3383947335406624054u, 1438154507889852726u },
+ { 16482362180876329456u, 2301047212623764361u }, { 9496540929959153242u, 1840837770099011489u },
+ { 11286581558709232917u, 1472670216079209191u }, { 5339916432225476010u, 1178136172863367353u },
+ { 4854517476818851293u, 1885017876581387765u }, { 3883613981455081034u, 1508014301265110212u },
+ { 14174937629389795797u, 1206411441012088169u }, { 11611853762797942306u, 1930258305619341071u },
+ { 5600134195496443521u, 1544206644495472857u }, { 15548153800622885787u, 1235365315596378285u },
+ { 6430302007287065643u, 1976584504954205257u }, { 16212288050055383484u, 1581267603963364205u },
+ { 12969830440044306787u, 1265014083170691364u }, { 9683682259845159889u, 2024022533073106183u },
+ { 15125643437359948558u, 1619218026458484946u }, { 8411165935146048523u, 1295374421166787957u },
+ { 17147214310975587960u, 2072599073866860731u }, { 10028422634038560045u, 1658079259093488585u },
+ { 8022738107230848036u, 1326463407274790868u }, { 9147032156827446534u, 2122341451639665389u },
+ { 11006974540203867551u, 1697873161311732311u }, { 5116230817421183718u, 1358298529049385849u },
+ { 15564666937357714594u, 2173277646479017358u }, { 1383687105660440706u, 1738622117183213887u },
+ { 12174996128754083534u, 1390897693746571109u }, { 8411947361780802685u, 2225436309994513775u },
+ { 6729557889424642148u, 1780349047995611020u }, { 5383646311539713719u, 1424279238396488816u },
+ { 1235136468979721303u, 2278846781434382106u }, { 15745504434151418335u, 1823077425147505684u },
+ { 16285752362063044992u, 1458461940118004547u }, { 5649904260166615347u, 1166769552094403638u },
+ { 5350498001524674232u, 1866831283351045821u }, { 591049586477829062u, 1493465026680836657u },
+ { 11540886113407994219u, 1194772021344669325u }, { 18673707743239135u, 1911635234151470921u },
+ { 14772334225162232601u, 1529308187321176736u }, { 8128518565387875758u, 1223446549856941389u },
+ { 1937583260394870242u, 1957514479771106223u }, { 8928764237799716840u, 1566011583816884978u },
+ { 14521709019723594119u, 1252809267053507982u }, { 8477339172590109297u, 2004494827285612772u },
+ { 17849917782297818407u, 1603595861828490217u }, { 6901236596354434079u, 1282876689462792174u },
+ { 18420676183650915173u, 2052602703140467478u }, { 3668494502695001169u, 1642082162512373983u },
+ { 10313493231639821582u, 1313665730009899186u }, { 9122891541139893884u, 2101865168015838698u },
+ { 14677010862395735754u, 1681492134412670958u }, { 673562245690857633u, 1345193707530136767u }
+};
+
+static const uint64_t DOUBLE_POW5_SPLIT[DOUBLE_POW5_TABLE_SIZE][2] = {
+ { 0u, 1152921504606846976u }, { 0u, 1441151880758558720u },
+ { 0u, 1801439850948198400u }, { 0u, 2251799813685248000u },
+ { 0u, 1407374883553280000u }, { 0u, 1759218604441600000u },
+ { 0u, 2199023255552000000u }, { 0u, 1374389534720000000u },
+ { 0u, 1717986918400000000u }, { 0u, 2147483648000000000u },
+ { 0u, 1342177280000000000u }, { 0u, 1677721600000000000u },
+ { 0u, 2097152000000000000u }, { 0u, 1310720000000000000u },
+ { 0u, 1638400000000000000u }, { 0u, 2048000000000000000u },
+ { 0u, 1280000000000000000u }, { 0u, 1600000000000000000u },
+ { 0u, 2000000000000000000u }, { 0u, 1250000000000000000u },
+ { 0u, 1562500000000000000u }, { 0u, 1953125000000000000u },
+ { 0u, 1220703125000000000u }, { 0u, 1525878906250000000u },
+ { 0u, 1907348632812500000u }, { 0u, 1192092895507812500u },
+ { 0u, 1490116119384765625u }, { 4611686018427387904u, 1862645149230957031u },
+ { 9799832789158199296u, 1164153218269348144u }, { 12249790986447749120u, 1455191522836685180u },
+ { 15312238733059686400u, 1818989403545856475u }, { 14528612397897220096u, 2273736754432320594u },
+ { 13692068767113150464u, 1421085471520200371u }, { 12503399940464050176u, 1776356839400250464u },
+ { 15629249925580062720u, 2220446049250313080u }, { 9768281203487539200u, 1387778780781445675u },
+ { 7598665485932036096u, 1734723475976807094u }, { 274959820560269312u, 2168404344971008868u },
+ { 9395221924704944128u, 1355252715606880542u }, { 2520655369026404352u, 1694065894508600678u },
+ { 12374191248137781248u, 2117582368135750847u }, { 14651398557727195136u, 1323488980084844279u },
+ { 13702562178731606016u, 1654361225106055349u }, { 3293144668132343808u, 2067951531382569187u },
+ { 18199116482078572544u, 1292469707114105741u }, { 8913837547316051968u, 1615587133892632177u },
+ { 15753982952572452864u, 2019483917365790221u }, { 12152082354571476992u, 1262177448353618888u },
+ { 15190102943214346240u, 1577721810442023610u }, { 9764256642163156992u, 1972152263052529513u },
+ { 17631875447420442880u, 1232595164407830945u }, { 8204786253993389888u, 1540743955509788682u },
+ { 1032610780636961552u, 1925929944387235853u }, { 2951224747111794922u, 1203706215242022408u },
+ { 3689030933889743652u, 1504632769052528010u }, { 13834660704216955373u, 1880790961315660012u },
+ { 17870034976990372916u, 1175494350822287507u }, { 17725857702810578241u, 1469367938527859384u },
+ { 3710578054803671186u, 1836709923159824231u }, { 26536550077201078u, 2295887403949780289u },
+ { 11545800389866720434u, 1434929627468612680u }, { 14432250487333400542u, 1793662034335765850u },
+ { 8816941072311974870u, 2242077542919707313u }, { 17039803216263454053u, 1401298464324817070u },
+ { 12076381983474541759u, 1751623080406021338u }, { 5872105442488401391u, 2189528850507526673u },
+ { 15199280947623720629u, 1368455531567204170u }, { 9775729147674874978u, 1710569414459005213u },
+ { 16831347453020981627u, 2138211768073756516u }, { 1296220121283337709u, 1336382355046097823u },
+ { 15455333206886335848u, 1670477943807622278u }, { 10095794471753144002u, 2088097429759527848u },
+ { 6309871544845715001u, 1305060893599704905u }, { 12499025449484531656u, 1631326116999631131u },
+ { 11012095793428276666u, 2039157646249538914u }, { 11494245889320060820u, 1274473528905961821u },
+ { 532749306367912313u, 1593091911132452277u }, { 5277622651387278295u, 1991364888915565346u },
+ { 7910200175544436838u, 1244603055572228341u }, { 14499436237857933952u, 1555753819465285426u },
+ { 8900923260467641632u, 1944692274331606783u }, { 12480606065433357876u, 1215432671457254239u },
+ { 10989071563364309441u, 1519290839321567799u }, { 9124653435777998898u, 1899113549151959749u },
+ { 8008751406574943263u, 1186945968219974843u }, { 5399253239791291175u, 1483682460274968554u },
+ { 15972438586593889776u, 1854603075343710692u }, { 759402079766405302u, 1159126922089819183u },
+ { 14784310654990170340u, 1448908652612273978u }, { 9257016281882937117u, 1811135815765342473u },
+ { 16182956370781059300u, 2263919769706678091u }, { 7808504722524468110u, 1414949856066673807u },
+ { 5148944884728197234u, 1768687320083342259u }, { 1824495087482858639u, 2210859150104177824u },
+ { 1140309429676786649u, 1381786968815111140u }, { 1425386787095983311u, 1727233711018888925u },
+ { 6393419502297367043u, 2159042138773611156u }, { 13219259225790630210u, 1349401336733506972u },
+ { 16524074032238287762u, 1686751670916883715u }, { 16043406521870471799u, 2108439588646104644u },
+ { 803757039314269066u, 1317774742903815403u }, { 14839754354425000045u, 1647218428629769253u },
+ { 4714634887749086344u, 2059023035787211567u }, { 9864175832484260821u, 1286889397367007229u },
+ { 16941905809032713930u, 1608611746708759036u }, { 2730638187581340797u, 2010764683385948796u },
+ { 10930020904093113806u, 1256727927116217997u }, { 18274212148543780162u, 1570909908895272496u },
+ { 4396021111970173586u, 1963637386119090621u }, { 5053356204195052443u, 1227273366324431638u },
+ { 15540067292098591362u, 1534091707905539547u }, { 14813398096695851299u, 1917614634881924434u },
+ { 13870059828862294966u, 1198509146801202771u }, { 12725888767650480803u, 1498136433501503464u },
+ { 15907360959563101004u, 1872670541876879330u }, { 14553786618154326031u, 1170419088673049581u },
+ { 4357175217410743827u, 1463023860841311977u }, { 10058155040190817688u, 1828779826051639971u },
+ { 7961007781811134206u, 2285974782564549964u }, { 14199001900486734687u, 1428734239102843727u },
+ { 13137066357181030455u, 1785917798878554659u }, { 11809646928048900164u, 2232397248598193324u },
+ { 16604401366885338411u, 1395248280373870827u }, { 16143815690179285109u, 1744060350467338534u },
+ { 10956397575869330579u, 2180075438084173168u }, { 6847748484918331612u, 1362547148802608230u },
+ { 17783057643002690323u, 1703183936003260287u }, { 17617136035325974999u, 2128979920004075359u },
+ { 17928239049719816230u, 1330612450002547099u }, { 17798612793722382384u, 1663265562503183874u },
+ { 13024893955298202172u, 2079081953128979843u }, { 5834715712847682405u, 1299426220705612402u },
+ { 16516766677914378815u, 1624282775882015502u }, { 11422586310538197711u, 2030353469852519378u },
+ { 11750802462513761473u, 1268970918657824611u }, { 10076817059714813937u, 1586213648322280764u },
+ { 12596021324643517422u, 1982767060402850955u }, { 5566670318688504437u, 1239229412751781847u },
+ { 2346651879933242642u, 1549036765939727309u }, { 7545000868343941206u, 1936295957424659136u },
+ { 4715625542714963254u, 1210184973390411960u }, { 5894531928393704067u, 1512731216738014950u },
+ { 16591536947346905892u, 1890914020922518687u }, { 17287239619732898039u, 1181821263076574179u },
+ { 16997363506238734644u, 1477276578845717724u }, { 2799960309088866689u, 1846595723557147156u },
+ { 10973347230035317489u, 1154122327223216972u }, { 13716684037544146861u, 1442652909029021215u },
+ { 12534169028502795672u, 1803316136286276519u }, { 11056025267201106687u, 2254145170357845649u },
+ { 18439230838069161439u, 1408840731473653530u }, { 13825666510731675991u, 1761050914342066913u },
+ { 3447025083132431277u, 2201313642927583642u }, { 6766076695385157452u, 1375821026829739776u },
+ { 8457595869231446815u, 1719776283537174720u }, { 10571994836539308519u, 2149720354421468400u },
+ { 6607496772837067824u, 1343575221513417750u }, { 17482743002901110588u, 1679469026891772187u },
+ { 17241742735199000331u, 2099336283614715234u }, { 15387775227926763111u, 1312085177259197021u },
+ { 5399660979626290177u, 1640106471573996277u }, { 11361262242960250625u, 2050133089467495346u },
+ { 11712474920277544544u, 1281333180917184591u }, { 10028907631919542777u, 1601666476146480739u },
+ { 7924448521472040567u, 2002083095183100924u }, { 14176152362774801162u, 1251301934489438077u },
+ { 3885132398186337741u, 1564127418111797597u }, { 9468101516160310080u, 1955159272639746996u },
+ { 15140935484454969608u, 1221974545399841872u }, { 479425281859160394u, 1527468181749802341u },
+ { 5210967620751338397u, 1909335227187252926u }, { 17091912818251750210u, 1193334516992033078u },
+ { 12141518985959911954u, 1491668146240041348u }, { 15176898732449889943u, 1864585182800051685u },
+ { 11791404716994875166u, 1165365739250032303u }, { 10127569877816206054u, 1456707174062540379u },
+ { 8047776328842869663u, 1820883967578175474u }, { 836348374198811271u, 2276104959472719343u },
+ { 7440246761515338900u, 1422565599670449589u }, { 13911994470321561530u, 1778206999588061986u },
+ { 8166621051047176104u, 2222758749485077483u }, { 2798295147690791113u, 1389224218428173427u },
+ { 17332926989895652603u, 1736530273035216783u }, { 17054472718942177850u, 2170662841294020979u },
+ { 8353202440125167204u, 1356664275808763112u }, { 10441503050156459005u, 1695830344760953890u },
+ { 3828506775840797949u, 2119787930951192363u }, { 86973725686804766u, 1324867456844495227u },
+ { 13943775212390669669u, 1656084321055619033u }, { 3594660960206173375u, 2070105401319523792u },
+ { 2246663100128858359u, 1293815875824702370u }, { 12031700912015848757u, 1617269844780877962u },
+ { 5816254103165035138u, 2021587305976097453u }, { 5941001823691840913u, 1263492066235060908u },
+ { 7426252279614801142u, 1579365082793826135u }, { 4671129331091113523u, 1974206353492282669u },
+ { 5225298841145639904u, 1233878970932676668u }, { 6531623551432049880u, 1542348713665845835u },
+ { 3552843420862674446u, 1927935892082307294u }, { 16055585193321335241u, 1204959932551442058u },
+ { 10846109454796893243u, 1506199915689302573u }, { 18169322836923504458u, 1882749894611628216u },
+ { 11355826773077190286u, 1176718684132267635u }, { 9583097447919099954u, 1470898355165334544u },
+ { 11978871809898874942u, 1838622943956668180u }, { 14973589762373593678u, 2298278679945835225u },
+ { 2440964573842414192u, 1436424174966147016u }, { 3051205717303017741u, 1795530218707683770u },
+ { 13037379183483547984u, 2244412773384604712u }, { 8148361989677217490u, 1402757983365377945u },
+ { 14797138505523909766u, 1753447479206722431u }, { 13884737113477499304u, 2191809349008403039u },
+ { 15595489723564518921u, 1369880843130251899u }, { 14882676136028260747u, 1712351053912814874u },
+ { 9379973133180550126u, 2140438817391018593u }, { 17391698254306313589u, 1337774260869386620u },
+ { 3292878744173340370u, 1672217826086733276u }, { 4116098430216675462u, 2090272282608416595u },
+ { 266718509671728212u, 1306420176630260372u }, { 333398137089660265u, 1633025220787825465u },
+ { 5028433689789463235u, 2041281525984781831u }, { 10060300083759496378u, 1275800953740488644u },
+ { 12575375104699370472u, 1594751192175610805u }, { 1884160825592049379u, 1993438990219513507u },
+ { 17318501580490888525u, 1245899368887195941u }, { 7813068920331446945u, 1557374211108994927u },
+ { 5154650131986920777u, 1946717763886243659u }, { 915813323278131534u, 1216698602428902287u },
+ { 14979824709379828129u, 1520873253036127858u }, { 9501408849870009354u, 1901091566295159823u },
+ { 12855909558809837702u, 1188182228934474889u }, { 2234828893230133415u, 1485227786168093612u },
+ { 2793536116537666769u, 1856534732710117015u }, { 8663489100477123587u, 1160334207943823134u },
+ { 1605989338741628675u, 1450417759929778918u }, { 11230858710281811652u, 1813022199912223647u },
+ { 9426887369424876662u, 2266277749890279559u }, { 12809333633531629769u, 1416423593681424724u },
+ { 16011667041914537212u, 1770529492101780905u }, { 6179525747111007803u, 2213161865127226132u },
+ { 13085575628799155685u, 1383226165704516332u }, { 16356969535998944606u, 1729032707130645415u },
+ { 15834525901571292854u, 2161290883913306769u }, { 2979049660840976177u, 1350806802445816731u },
+ { 17558870131333383934u, 1688508503057270913u }, { 8113529608884566205u, 2110635628821588642u },
+ { 9682642023980241782u, 1319147268013492901u }, { 16714988548402690132u, 1648934085016866126u },
+ { 11670363648648586857u, 2061167606271082658u }, { 11905663298832754689u, 1288229753919426661u },
+ { 1047021068258779650u, 1610287192399283327u }, { 15143834390605638274u, 2012858990499104158u },
+ { 4853210475701136017u, 1258036869061940099u }, { 1454827076199032118u, 1572546086327425124u },
+ { 1818533845248790147u, 1965682607909281405u }, { 3442426662494187794u, 1228551629943300878u },
+ { 13526405364972510550u, 1535689537429126097u }, { 3072948650933474476u, 1919611921786407622u },
+ { 15755650962115585259u, 1199757451116504763u }, { 15082877684217093670u, 1499696813895630954u },
+ { 9630225068416591280u, 1874621017369538693u }, { 8324733676974063502u, 1171638135855961683u },
+ { 5794231077790191473u, 1464547669819952104u }, { 7242788847237739342u, 1830684587274940130u },
+ { 18276858095901949986u, 2288355734093675162u }, { 16034722328366106645u, 1430222333808546976u },
+ { 1596658836748081690u, 1787777917260683721u }, { 6607509564362490017u, 2234722396575854651u },
+ { 1823850468512862308u, 1396701497859909157u }, { 6891499104068465790u, 1745876872324886446u },
+ { 17837745916940358045u, 2182346090406108057u }, { 4231062170446641922u, 1363966306503817536u },
+ { 5288827713058302403u, 1704957883129771920u }, { 6611034641322878003u, 2131197353912214900u },
+ { 13355268687681574560u, 1331998346195134312u }, { 16694085859601968200u, 1664997932743917890u },
+ { 11644235287647684442u, 2081247415929897363u }, { 4971804045566108824u, 1300779634956185852u },
+ { 6214755056957636030u, 1625974543695232315u }, { 3156757802769657134u, 2032468179619040394u },
+ { 6584659645158423613u, 1270292612261900246u }, { 17454196593302805324u, 1587865765327375307u },
+ { 17206059723201118751u, 1984832206659219134u }, { 6142101308573311315u, 1240520129162011959u },
+ { 3065940617289251240u, 1550650161452514949u }, { 8444111790038951954u, 1938312701815643686u },
+ { 665883850346957067u, 1211445438634777304u }, { 832354812933696334u, 1514306798293471630u },
+ { 10263815553021896226u, 1892883497866839537u }, { 17944099766707154901u, 1183052186166774710u },
+ { 13206752671529167818u, 1478815232708468388u }, { 16508440839411459773u, 1848519040885585485u },
+ { 12623618533845856310u, 1155324400553490928u }, { 15779523167307320387u, 1444155500691863660u },
+ { 1277659885424598868u, 1805194375864829576u }, { 1597074856780748586u, 2256492969831036970u },
+ { 5609857803915355770u, 1410308106144398106u }, { 16235694291748970521u, 1762885132680497632u },
+ { 1847873790976661535u, 2203606415850622041u }, { 12684136165428883219u, 1377254009906638775u },
+ { 11243484188358716120u, 1721567512383298469u }, { 219297180166231438u, 2151959390479123087u },
+ { 7054589765244976505u, 1344974619049451929u }, { 13429923224983608535u, 1681218273811814911u },
+ { 12175718012802122765u, 2101522842264768639u }, { 14527352785642408584u, 1313451776415480399u },
+ { 13547504963625622826u, 1641814720519350499u }, { 12322695186104640628u, 2052268400649188124u },
+ { 16925056528170176201u, 1282667750405742577u }, { 7321262604930556539u, 1603334688007178222u },
+ { 18374950293017971482u, 2004168360008972777u }, { 4566814905495150320u, 1252605225005607986u },
+ { 14931890668723713708u, 1565756531257009982u }, { 9441491299049866327u, 1957195664071262478u },
+ { 1289246043478778550u, 1223247290044539049u }, { 6223243572775861092u, 1529059112555673811u },
+ { 3167368447542438461u, 1911323890694592264u }, { 1979605279714024038u, 1194577431684120165u },
+ { 7086192618069917952u, 1493221789605150206u }, { 18081112809442173248u, 1866527237006437757u },
+ { 13606538515115052232u, 1166579523129023598u }, { 7784801107039039482u, 1458224403911279498u },
+ { 507629346944023544u, 1822780504889099373u }, { 5246222702107417334u, 2278475631111374216u },
+ { 3278889188817135834u, 1424047269444608885u }, { 8710297504448807696u, 1780059086805761106u }
+};
+
+// IEEE 754 double precision constants
+#define DOUBLE_MANTISSA_BITS 52
+#define DOUBLE_EXPONENT_BITS 11
+#define DOUBLE_EXPONENT_BIAS 1023
+
+// Helper: floor(log2(value)) using ryu_leading_zeros64
+static inline uint32_t floor_log2(const uint64_t value) {
+ return 63 - ryu_leading_zeros64(value);
+}
+
+// Helper: log2(5^e) approximation
+static inline int32_t log2pow5(const int32_t e) {
+ return (int32_t) ((((uint32_t) e) * 1217359) >> 19);
+}
+
+// Helper: ceil(log2(5^e))
+static inline int32_t ceil_log2pow5(const int32_t e) {
+ return log2pow5(e) + 1;
+}
+
+// Helper: max of two int32
+static inline int32_t max32(int32_t a, int32_t b) {
+ return a < b ? b : a;
+}
+
+// Helper: convert uint64 bits to double
+static inline double int64Bits2Double(uint64_t bits) {
+ double f;
+ memcpy(&f, &bits, sizeof(double));
+ return f;
+}
+
+// Check if value is multiple of 2^p
+static inline bool multipleOfPowerOf2(const uint64_t value, const uint32_t p) {
+ return (value & ((1ull << p) - 1)) == 0;
+}
+
+// Count how many times value is divisible by 5
+// Uses modular inverse to avoid expensive division
+static inline uint32_t pow5Factor(uint64_t value) {
+ const uint64_t m_inv_5 = 14757395258967641293u; // 5 * m_inv_5 = 1 (mod 2^64)
+ const uint64_t n_div_5 = 3689348814741910323u; // 2^64 / 5
+ uint32_t count = 0;
+ for (;;) {
+ value *= m_inv_5;
+ if (value > n_div_5)
+ break;
+ ++count;
+ }
+ return count;
+}
+
+// Check if value is multiple of 5^p
+// Optimized: uses modular inverse instead of division
+static inline bool multipleOfPowerOf5(const uint64_t value, const uint32_t p) {
+ return pow5Factor(value) >= p;
+}
+
+// 128-bit multiplication with shift
+// This is the core operation for converting decimal to binary
+#if defined(__SIZEOF_INT128__)
+// Use native 128-bit integers if available (GCC/Clang)
+static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
+ const unsigned __int128 b0 = ((unsigned __int128) m) * mul[0];
+ const unsigned __int128 b2 = ((unsigned __int128) m) * mul[1];
+ return (uint64_t) (((b0 >> 64) + b2) >> (j - 64));
+}
+#else
+// Fallback for systems without 128-bit integers
+static inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) {
+ const uint32_t aLo = (uint32_t)a;
+ const uint32_t aHi = (uint32_t)(a >> 32);
+ const uint32_t bLo = (uint32_t)b;
+ const uint32_t bHi = (uint32_t)(b >> 32);
+
+ const uint64_t b00 = (uint64_t)aLo * bLo;
+ const uint64_t b01 = (uint64_t)aLo * bHi;
+ const uint64_t b10 = (uint64_t)aHi * bLo;
+ const uint64_t b11 = (uint64_t)aHi * bHi;
+
+ const uint32_t b00Lo = (uint32_t)b00;
+ const uint32_t b00Hi = (uint32_t)(b00 >> 32);
+
+ const uint64_t mid1 = b10 + b00Hi;
+ const uint32_t mid1Lo = (uint32_t)(mid1);
+ const uint32_t mid1Hi = (uint32_t)(mid1 >> 32);
+
+ const uint64_t mid2 = b01 + mid1Lo;
+ const uint32_t mid2Lo = (uint32_t)(mid2);
+ const uint32_t mid2Hi = (uint32_t)(mid2 >> 32);
+
+ const uint64_t pHi = b11 + mid1Hi + mid2Hi;
+ const uint64_t pLo = ((uint64_t)mid2Lo << 32) | b00Lo;
+
+ *productHi = pHi;
+ return pLo;
+}
+
+static inline uint64_t shiftright128(const uint64_t lo, const uint64_t hi, const uint32_t dist) {
+ return (hi << (64 - dist)) | (lo >> dist);
+}
+
+static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
+ uint64_t high1;
+ const uint64_t low1 = umul128(m, mul[1], &high1);
+ uint64_t high0;
+ umul128(m, mul[0], &high0);
+ const uint64_t sum = high0 + low1;
+ if (sum < high0) {
+ ++high1;
+ }
+ return shiftright128(sum, high1, j - 64);
+}
+#endif
+
+// Main conversion function: decimal mantissa+exponent to IEEE 754 double
+// Optimized for JSON parsing with fast paths for edge cases
+static inline double ryu_s2d_from_parts(uint64_t m10, int m10digits, int32_t e10, bool signedM) {
+ // Fast path: handle zero explicitly (e.g., "0.0", "0e0")
+ if (m10 == 0) {
+ return int64Bits2Double(((uint64_t) signedM) << 63);
+ }
+
+ // Fast path: handle overflow/underflow early
+ if (m10digits + e10 <= -324) {
+ // Underflow to zero
+ return int64Bits2Double(((uint64_t) signedM) << 63);
+ }
+
+ if (m10digits + e10 >= 310) {
+ // Overflow to infinity
+ return int64Bits2Double((((uint64_t) signedM) << 63) | 0x7ff0000000000000ULL);
+ }
+
+ // Convert decimal to binary: m10 * 10^e10 = m2 * 2^e2
+ int32_t e2;
+ uint64_t m2;
+ bool trailingZeros;
+
+ if (e10 >= 0) {
+ // Positive exponent: multiply by 5^e10 and adjust binary exponent
+ e2 = floor_log2(m10) + e10 + log2pow5(e10) - (DOUBLE_MANTISSA_BITS + 1);
+ int j = e2 - e10 - ceil_log2pow5(e10) + DOUBLE_POW5_BITCOUNT;
+ m2 = mulShift64(m10, DOUBLE_POW5_SPLIT[e10], j);
+ trailingZeros = e2 < e10 || (e2 - e10 < 64 && multipleOfPowerOf2(m10, e2 - e10));
+ } else {
+ // Negative exponent: divide by 5^(-e10)
+ e2 = floor_log2(m10) + e10 - ceil_log2pow5(-e10) - (DOUBLE_MANTISSA_BITS + 1);
+ int j = e2 - e10 + ceil_log2pow5(-e10) - 1 + DOUBLE_POW5_INV_BITCOUNT;
+ m2 = mulShift64(m10, DOUBLE_POW5_INV_SPLIT[-e10], j);
+ trailingZeros = multipleOfPowerOf5(m10, -e10);
+ }
+
+ // Compute IEEE 754 exponent
+ uint32_t ieee_e2 = (uint32_t) max32(0, e2 + DOUBLE_EXPONENT_BIAS + floor_log2(m2));
+
+ if (ieee_e2 > 0x7fe) {
+ // Overflow to infinity
+ return int64Bits2Double((((uint64_t) signedM) << 63) | 0x7ff0000000000000ULL);
+ }
+
+ // Compute shift amount for rounding
+ int32_t shift = (ieee_e2 == 0 ? 1 : ieee_e2) - e2 - DOUBLE_EXPONENT_BIAS - DOUBLE_MANTISSA_BITS;
+
+ // IEEE 754 round-to-even (banker's rounding)
+ trailingZeros &= (m2 & ((1ull << (shift - 1)) - 1)) == 0;
+ uint64_t lastRemovedBit = (m2 >> (shift - 1)) & 1;
+ bool roundUp = (lastRemovedBit != 0) && (!trailingZeros || (((m2 >> shift) & 1) != 0));
+
+ uint64_t ieee_m2 = (m2 >> shift) + roundUp;
+ ieee_m2 &= (1ull << DOUBLE_MANTISSA_BITS) - 1;
+
+ if (ieee_m2 == 0 && roundUp) {
+ ieee_e2++;
+ }
+
+ // Pack sign, exponent, and mantissa into IEEE 754 format
+ // Match original Ryu: group sign+exponent, then shift and add mantissa
+ uint64_t ieee = (((((uint64_t) signedM) << DOUBLE_EXPONENT_BITS) | (uint64_t)ieee_e2) << DOUBLE_MANTISSA_BITS) | ieee_m2;
+ return int64Bits2Double(ieee);
+}
+
+#endif // RYU_H
diff --git a/ext/nkf/.cvsignore b/ext/nkf/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/nkf/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/nkf/depend b/ext/nkf/depend
deleted file mode 100644
index 0ed8fea8d2..0000000000
--- a/ext/nkf/depend
+++ /dev/null
@@ -1 +0,0 @@
-nkf.o : nkf.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h $(srcdir)/nkf-utf8/nkf.c $(srcdir)/nkf-utf8/utf8tbl.c $(srcdir)/nkf-utf8/config.h
diff --git a/ext/nkf/extconf.rb b/ext/nkf/extconf.rb
deleted file mode 100644
index 710662f19c..0000000000
--- a/ext/nkf/extconf.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require 'mkmf'
-create_makefile('nkf')
diff --git a/ext/nkf/lib/kconv.rb b/ext/nkf/lib/kconv.rb
deleted file mode 100644
index 091b88b1c0..0000000000
--- a/ext/nkf/lib/kconv.rb
+++ /dev/null
@@ -1,367 +0,0 @@
-#
-# kconv.rb - Kanji Converter.
-#
-# $Id$
-#
-# ----
-#
-# kconv.rb implements the Kconv class for Kanji Converter. Additionally,
-# some methods in String classes are added to allow easy conversion.
-#
-
-require 'nkf'
-
-#
-# Kanji Converter for Ruby.
-#
-module Kconv
- #
- # Public Constants
- #
-
- #Constant of Encoding
-
- # Auto-Detect
- AUTO = NKF::AUTO
- # ISO-2022-JP
- JIS = NKF::JIS
- # EUC-JP
- EUC = NKF::EUC
- # Shift_JIS
- SJIS = NKF::SJIS
- # BINARY
- BINARY = NKF::BINARY
- # NOCONV
- NOCONV = NKF::NOCONV
- # ASCII
- ASCII = NKF::ASCII
- # UTF-8
- UTF8 = NKF::UTF8
- # UTF-16
- UTF16 = NKF::UTF16
- # UTF-32
- UTF32 = NKF::UTF32
- # UNKNOWN
- UNKNOWN = NKF::UNKNOWN
-
- #
- # Private Constants
- #
-
- # Revision of kconv.rb
- REVISION = %q$Revision$
-
- #Regexp of Encoding
-
- # Regexp of Shift_JIS string (private constant)
- RegexpShiftjis = /\A(?:
- [\x00-\x7f\xa1-\xdf] |
- [\x81-\x9f\xe0-\xfc][\x40-\x7e\x80-\xfc]
- )*\z/nx
-
- # Regexp of EUC-JP string (private constant)
- RegexpEucjp = /\A(?:
- [\x00-\x7f] |
- \x8e [\xa1-\xdf] |
- \x8f [\xa1-\xdf] [\xa1-\xfe] |
- [\xa1-\xdf] [\xa1-\xfe]
- )*\z/nx
-
- # Regexp of UTF-8 string (private constant)
- RegexpUtf8 = /\A(?:
- [\x00-\x7f] |
- [\xc2-\xdf] [\x80-\xbf] |
- \xe0 [\xa0-\xbf] [\x80-\xbf] |
- [\xe1-\xef] [\x80-\xbf] [\x80-\xbf] |
- \xf0 [\x90-\xbf] [\x80-\xbf] [\x80-\xbf] |
- [\xf1-\xf3] [\x80-\xbf] [\x80-\xbf] [\x80-\xbf] |
- \xf4 [\x80-\x8f] [\x80-\xbf] [\x80-\xbf]
- )*\z/nx
-
- #
- # Public Methods
- #
-
- # call-seq:
- # Kconv.kconv(str, out_code, in_code = Kconv::AUTO)
- #
- # Convert <code>str</code> to out_code.
- # <code>out_code</code> and <code>in_code</code> are given as constants of Kconv.
- #
- # *Note*
- # This method decode MIME encoded string and
- # convert halfwidth katakana to fullwidth katakana.
- # If you don't want to decode them, use NKF.nkf.
- def kconv(str, out_code, in_code = AUTO)
- opt = '-'
- case in_code
- when ::NKF::JIS
- opt << 'J'
- when ::NKF::EUC
- opt << 'E'
- when ::NKF::SJIS
- opt << 'S'
- when ::NKF::UTF8
- opt << 'W'
- when ::NKF::UTF16
- opt << 'W16'
- end
-
- case out_code
- when ::NKF::JIS
- opt << 'j'
- when ::NKF::EUC
- opt << 'e'
- when ::NKF::SJIS
- opt << 's'
- when ::NKF::UTF8
- opt << 'w'
- when ::NKF::UTF16
- opt << 'w16'
- when ::NKF::NOCONV
- return str
- end
-
- opt = '' if opt == '-'
-
- ::NKF::nkf(opt, str)
- end
- module_function :kconv
-
- #
- # Encode to
- #
-
- # call-seq:
- # Kconv.tojis(str) -> string
- #
- # Convert <code>str</code> to ISO-2022-JP
- #
- # *Note*
- # This method decode MIME encoded string and
- # convert halfwidth katakana to fullwidth katakana.
- # If you don't want it, use NKF.nkf('-jxm0', str).
- def tojis(str)
- ::NKF::nkf('-jm', str)
- end
- module_function :tojis
-
- # call-seq:
- # Kconv.toeuc(str) -> string
- #
- # Convert <code>str</code> to EUC-JP
- #
- # *Note*
- # This method decode MIME encoded string and
- # convert halfwidth katakana to fullwidth katakana.
- # If you don't want it, use NKF.nkf('-exm0', str).
- def toeuc(str)
- ::NKF::nkf('-em0', str)
- end
- module_function :toeuc
-
- # call-seq:
- # Kconv.tosjis(str) -> string
- #
- # Convert <code>str</code> to Shift_JIS
- #
- # *Note*
- # This method decode MIME encoded string and
- # convert halfwidth katakana to fullwidth katakana.
- # If you don't want it, use NKF.nkf('-sxm0', str).
- def tosjis(str)
- ::NKF::nkf('-sm', str)
- end
- module_function :tosjis
-
- # call-seq:
- # Kconv.toutf8(str) -> string
- #
- # Convert <code>str</code> to UTF-8
- #
- # *Note*
- # This method decode MIME encoded string and
- # convert halfwidth katakana to fullwidth katakana.
- # If you don't want it, use NKF.nkf('-wxm0', str).
- def toutf8(str)
- ::NKF::nkf('-wm', str)
- end
- module_function :toutf8
-
- # call-seq:
- # Kconv.toutf16(str) -> string
- #
- # Convert <code>str</code> to UTF-16
- #
- # *Note*
- # This method decode MIME encoded string and
- # convert halfwidth katakana to fullwidth katakana.
- # If you don't want it, use NKF.nkf('-w16xm0', str).
- def toutf16(str)
- ::NKF::nkf('-w16m', str)
- end
- module_function :toutf16
-
- #
- # guess
- #
-
- # call-seq:
- # Kconv.guess(str) -> integer
- #
- # Guess input encoding by NKF.guess2
- def guess(str)
- ::NKF::guess(str)
- end
- module_function :guess
-
- # call-seq:
- # Kconv.guess_old(str) -> integer
- #
- # Guess input encoding by NKF.guess1
- def guess_old(str)
- ::NKF::guess1(str)
- end
- module_function :guess_old
-
- #
- # isEncoding
- #
-
- # call-seq:
- # Kconv.iseuc(str) -> obj or nil
- #
- # Returns whether input encoding is EUC-JP or not.
- #
- # *Note* don't expect this return value is MatchData.
- def iseuc(str)
- RegexpEucjp.match( str )
- end
- module_function :iseuc
-
- # call-seq:
- # Kconv.issjis(str) -> obj or nil
- #
- # Returns whether input encoding is Shift_JIS or not.
- #
- # *Note* don't expect this return value is MatchData.
- def issjis(str)
- RegexpShiftjis.match( str )
- end
- module_function :issjis
-
- # call-seq:
- # Kconv.isutf8(str) -> obj or nil
- #
- # Returns whether input encoding is UTF-8 or not.
- #
- # *Note* don't expect this return value is MatchData.
- def isutf8(str)
- RegexpUtf8.match( str )
- end
- module_function :isutf8
-
-end
-
-class String
- # call-seq:
- # String#kconv(out_code, in_code = Kconv::AUTO)
- #
- # Convert <code>self</code> to out_code.
- # <code>out_code</code> and <code>in_code</code> are given as constants of Kconv.
- #
- # *Note*
- # This method decode MIME encoded string and
- # convert halfwidth katakana to fullwidth katakana.
- # If you don't want to decode them, use NKF.nkf.
- def kconv(out_code, in_code=Kconv::AUTO)
- Kconv::kconv(self, out_code, in_code)
- end
-
- #
- # to Encoding
- #
-
- # call-seq:
- # String#tojis -> string
- #
- # Convert <code>self</code> to ISO-2022-JP
- #
- # *Note*
- # This method decode MIME encoded string and
- # convert halfwidth katakana to fullwidth katakana.
- # If you don't want it, use NKF.nkf('-jxm0', str).
- def tojis; Kconv.tojis(self) end
-
- # call-seq:
- # String#toeuc -> string
- #
- # Convert <code>self</code> to EUC-JP
- #
- # *Note*
- # This method decode MIME encoded string and
- # convert halfwidth katakana to fullwidth katakana.
- # If you don't want it, use NKF.nkf('-exm0', str).
- def toeuc; Kconv.toeuc(self) end
-
- # call-seq:
- # String#tosjis -> string
- #
- # Convert <code>self</code> to Shift_JIS
- #
- # *Note*
- # This method decode MIME encoded string and
- # convert halfwidth katakana to fullwidth katakana.
- # If you don't want it, use NKF.nkf('-sxm0', str).
- def tosjis; Kconv.tosjis(self) end
-
- # call-seq:
- # String#toutf8 -> string
- #
- # Convert <code>self</code> to UTF-8
- #
- # *Note*
- # This method decode MIME encoded string and
- # convert halfwidth katakana to fullwidth katakana.
- # If you don't want it, use NKF.nkf('-wxm0', str).
- def toutf8; Kconv.toutf8(self) end
-
- # call-seq:
- # String#toutf16 -> string
- #
- # Convert <code>self</code> to UTF-16
- #
- # *Note*
- # This method decode MIME encoded string and
- # convert halfwidth katakana to fullwidth katakana.
- # If you don't want it, use NKF.nkf('-w16xm0', str).
- def toutf16; Kconv.toutf16(self) end
-
- #
- # is Encoding
- #
-
- # call-seq:
- # String#iseuc -> obj or nil
- #
- # Returns whether <code>self</code>'s encoding is EUC-JP or not.
- #
- # *Note* don't expect this return value is MatchData.
- def iseuc; Kconv.iseuc(self) end
-
- # call-seq:
- # String#issjis -> obj or nil
- #
- # Returns whether <code>self</code>'s encoding is Shift_JIS or not.
- #
- # *Note* don't expect this return value is MatchData.
- def issjis; Kconv.issjis(self) end
-
- # call-seq:
- # String#isutf8 -> obj or nil
- #
- # Returns whether <code>self</code>'s encoding is UTF-8 or not.
- #
- # *Note* don't expect this return value is MatchData.
- def isutf8; Kconv.isutf8(self) end
-end
diff --git a/ext/nkf/nkf-utf8/config.h b/ext/nkf/nkf-utf8/config.h
deleted file mode 100644
index 9da82c6aee..0000000000
--- a/ext/nkf/nkf-utf8/config.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef _CONFIG_H_
-#define _CONFIG_H_
-
-/* UTF8 $BF~=PNO(B */
-#define UTF8_INPUT_ENABLE
-#define UTF8_OUTPUT_ENABLE
-
-/* Shift_JIS $BHO0O30$NJ8;z$r!"(BCP932 $B$GF1CM$JJ8;z$KFI$_49$($k(B */
-#define SHIFTJIS_CP932
-
-/* $B%*%W%7%g%s$GF~NO$r;XDj$7$?;~$K!"J8;z%3!<%I$r8GDj$9$k(B */
-#define INPUT_CODE_FIX
-
-/* --overwrite $B%*%W%7%g%s(B */
-/* by Satoru Takabayashi <ccsatoru@vega.aichi-u.ac.jp> */
-#define OVERWRITE
-
-/* --cap-input, --url-input $B%*%W%7%g%s(B */
-#define INPUT_OPTION
-
-/* --numchar-input $B%*%W%7%g%s(B */
-#define NUMCHAR_OPTION
-
-/* --debug, --no-output $B%*%W%7%g%s(B */
-#define CHECK_OPTION
-
-/* JIS X0212 */
-#define X0212_ENABLE
-
-/* --exec-in, --exec-out $B%*%W%7%g%s(B
- * pipe, fork, execvp $B$"$?$j$,L5$$$HF0$-$^$;$s!#(B
- * MS-DOS, MinGW $B$J$I$G$O(B undef $B$K$7$F$/$@$5$$(B
- * child process $B=*N;;~$N=hM}$,$$$$$+$2$s$J$N$G!"(B
- * $B%G%U%)%k%H$GL58z$K$7$F$$$^$9!#(B
- */
-/* #define EXEC_IO */
-
-/* SunOS $B$N(B cc $B$r;H$&$H$-$O(B undef $B$K$7$F$/$@$5$$(B */
-#define ANSI_C_PROTOTYPE
-
-/* int $B$,(B 32bit $BL$K~$N4D6-$G(B NUMCHAR_OPTION $B$r;H$&$K$O!"(B
- * $B%3%a%s%H$r30$7$F$/$@$5$$!#(B
- */
-/* #define INT_IS_SHORT */
-
-
-#if defined(INT_IS_SHORT)
-typedef long nkf_char;
-typedef unsigned char nkf_nfchar;
-#else
-typedef int nkf_char;
-typedef int nkf_nfchar;
-#endif
-
-/* Unicode Normalization */
-#define UNICODE_NORMALIZATION
-
-#ifndef WIN32DLL
-/******************************/
-/* $B%G%U%)%k%H$N=PNO%3!<%IA*Br(B */
-/* Select DEFAULT_CODE */
-#define DEFAULT_CODE_JIS
-/* #define DEFAULT_CODE_SJIS */
-/* #define DEFAULT_CODE_EUC */
-/* #define DEFAULT_CODE_UTF8 */
-/******************************/
-#else
-#define DEFAULT_CODE_SJIS
-#endif
-
-#if defined(NUMCHAR_OPTION) && !defined(UTF8_INPUT_ENABLE)
-#define UTF8_INPUT_ENABLE
-#endif
-
-#ifdef UNICODE_NORMALIZATION
-#ifndef UTF8_INPUT_ENABLE
-#define UTF8_INPUT_ENABLE
-#endif
-#define NORMALIZATION_TABLE_LENGTH 942
-#define NORMALIZATION_TABLE_NFC_LENGTH 3
-#define NORMALIZATION_TABLE_NFD_LENGTH 9
-struct normalization_pair{
- const nkf_nfchar nfc[NORMALIZATION_TABLE_NFC_LENGTH];
- const nkf_nfchar nfd[NORMALIZATION_TABLE_NFD_LENGTH];
-};
-#endif
-
-#endif /* _CONFIG_H_ */
diff --git a/ext/nkf/nkf-utf8/nkf.c b/ext/nkf/nkf-utf8/nkf.c
deleted file mode 100644
index a0cdb81eab..0000000000
--- a/ext/nkf/nkf-utf8/nkf.c
+++ /dev/null
@@ -1,5633 +0,0 @@
-/** Network Kanji Filter. (PDS Version)
-************************************************************************
-** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
-** $BO"Mm@h!'(B $B!J3t!KIY;NDL8&5f=j!!%=%U%H#38&!!;T@n!!;j(B
-** $B!J(BE-Mail Address: ichikawa@flab.fujitsu.co.jp$B!K(B
-** Copyright (C) 1996,1998
-** Copyright (C) 2002
-** $BO"Mm@h!'(B $BN05eBg3X>pJs9)3X2J(B $B2OLn(B $B??<#(B mime/X0208 support
-** $B!J(BE-Mail Address: kono@ie.u-ryukyu.ac.jp$B!K(B
-** $BO"Mm@h!'(B COW for DOS & Win16 & Win32 & OS/2
-** $B!J(BE-Mail Address: GHG00637@niftyserve.or.p$B!K(B
-**
-** $B$3$N%=!<%9$N$$$+$J$kJ#<L!$2~JQ!$=$@5$b5vBz$7$^$9!#$?$@$7!"(B
-** $B$=$N:]$K$O!"C/$,9W8%$7$?$r<($9$3$NItJ,$r;D$9$3$H!#(B
-** $B:FG[I[$d;(;o$NIUO?$J$I$NLd$$9g$o$;$bI,MW$"$j$^$;$s!#(B
-** $B1DMxMxMQ$b>e5-$KH?$7$J$$HO0O$G5v2D$7$^$9!#(B
-** $B%P%$%J%j$NG[I[$N:]$K$O(Bversion message$B$rJ]B8$9$k$3$H$r>r7o$H$7$^$9!#(B
-** $B$3$N%W%m%0%i%`$K$D$$$F$OFC$K2?$NJ]>Z$b$7$J$$!"0-$7$+$i$:!#(B
-**
-** Everyone is permitted to do anything on this program
-** including copying, modifying, improving,
-** as long as you don't try to pretend that you wrote it.
-** i.e., the above copyright notice has to appear in all copies.
-** Binary distribution requires original version messages.
-** You don't have to ask before copying, redistribution or publishing.
-** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
-***********************************************************************/
-
-/***********************************************************************
-** UTF-8 $B%5%]!<%H$K$D$$$F(B
-** $B=>Mh$N(B nkf $B$HF~$l$+$($F$=$N$^$^;H$($k$h$&$K$J$C$F$$$^$9(B
-** nkf -e $B$J$I$H$7$F5/F0$9$k$H!"<+F0H=JL$G(B UTF-8 $B$HH=Dj$5$l$l$P!"(B
-** $B$=$N$^$^(B euc-jp $B$KJQ49$5$l$^$9(B
-**
-** $B$^$@%P%0$,$"$k2DG=@-$,9b$$$G$9!#(B
-** ($BFC$K<+F0H=JL!"%3!<%I:.:_!"%(%i!<=hM}7O(B)
-**
-** $B2?$+LdBj$r8+$D$1$?$i!"(B
-** E-Mail: furukawa@tcp-ip.or.jp
-** $B$^$G8fO"Mm$r$*4j$$$7$^$9!#(B
-***********************************************************************/
-/* $Id$ */
-#define NKF_VERSION "2.0.7"
-#define NKF_RELEASE_DATE "2006-06-13"
-#include "config.h"
-#include "utf8tbl.h"
-
-#define COPY_RIGHT \
- "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),2000 S. Kono, COW\n" \
- "Copyright (C) 2002-2006 Kono, Furukawa, Naruse, mastodon"
-
-
-/*
-**
-**
-**
-** USAGE: nkf [flags] [file]
-**
-** Flags:
-** b Output is buffered (DEFAULT)
-** u Output is unbuffered
-**
-** t no operation
-**
-** j Outout code is JIS 7 bit (DEFAULT SELECT)
-** s Output code is MS Kanji (DEFAULT SELECT)
-** e Output code is AT&T JIS (DEFAULT SELECT)
-** w Output code is AT&T JIS (DEFAULT SELECT)
-** l Output code is JIS 7bit and ISO8859-1 Latin-1
-**
-** m MIME conversion for ISO-2022-JP
-** I Convert non ISO-2022-JP charactor to GETA by Pekoe <pekoe@lair.net>
-** i_ Output sequence to designate JIS-kanji (DEFAULT_J)
-** o_ Output sequence to designate single-byte roman characters (DEFAULT_R)
-** M MIME output conversion
-**
-** r {de/en}crypt ROT13/47
-**
-** v display Version
-**
-** T Text mode output (for MS-DOS)
-**
-** x Do not convert X0201 kana into X0208
-** Z Convert X0208 alphabet to ASCII
-**
-** f60 fold option
-**
-** m MIME decode
-** B try to fix broken JIS, missing Escape
-** B[1-9] broken level
-**
-** O Output to 'nkf.out' file or last file name
-** d Delete \r in line feed
-** c Add \r in line feed
-** -- other long option
-** -- ignore following option (don't use with -O )
-**
-**/
-
-#if (defined(__TURBOC__) || defined(_MSC_VER) || defined(LSI_C) || defined(__MINGW32__) || defined(__EMX__) || defined(__MSDOS__) || defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)) && !defined(MSDOS)
-#define MSDOS
-#if (defined(__Win32__) || defined(_WIN32)) && !defined(__WIN32__)
-#define __WIN32__
-#endif
-#endif
-
-#ifdef PERL_XS
-#undef OVERWRITE
-#endif
-
-#ifndef PERL_XS
-#include <stdio.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#if defined(MSDOS) || defined(__OS2__)
-#include <fcntl.h>
-#include <io.h>
-#if defined(_MSC_VER) || defined(__WATCOMC__)
-#define mktemp _mktemp
-#endif
-#endif
-
-#ifdef MSDOS
-#ifdef LSI_C
-#define setbinmode(fp) fsetbin(fp)
-#elif defined(__DJGPP__)
-#include <libc/dosio.h>
-#define setbinmode(fp) djgpp_setbinmode(fp)
-#else /* Microsoft C, Turbo C */
-#define setbinmode(fp) setmode(fileno(fp), O_BINARY)
-#endif
-#else /* UNIX */
-#define setbinmode(fp)
-#endif
-
-#if defined(__DJGPP__)
-void djgpp_setbinmode(FILE *fp)
-{
- /* we do not use libc's setmode(), which changes COOKED/RAW mode in device. */
- int fd, m;
- fd = fileno(fp);
- m = (__file_handle_modes[fd] & (~O_TEXT)) | O_BINARY;
- __file_handle_set(fd, m);
-}
-#endif
-
-#ifdef _IOFBF /* SysV and MSDOS, Windows */
-#define setvbuffer(fp, buf, size) setvbuf(fp, buf, _IOFBF, size)
-#else /* BSD */
-#define setvbuffer(fp, buf, size) setbuffer(fp, buf, size)
-#endif
-
-/*Borland C++ 4.5 EasyWin*/
-#if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */
-#define EASYWIN
-#ifndef __WIN16__
-#define __WIN16__
-#endif
-#include <windows.h>
-#endif
-
-#ifdef OVERWRITE
-/* added by satoru@isoternet.org */
-#if defined(__EMX__)
-#include <sys/types.h>
-#endif
-#include <sys/stat.h>
-#if !defined(MSDOS) || defined(__DJGPP__) /* UNIX, djgpp */
-#include <unistd.h>
-#if defined(__WATCOMC__)
-#include <sys/utime.h>
-#else
-#include <utime.h>
-#endif
-#else /* defined(MSDOS) */
-#ifdef __WIN32__
-#ifdef __BORLANDC__ /* BCC32 */
-#include <utime.h>
-#else /* !defined(__BORLANDC__) */
-#include <sys/utime.h>
-#endif /* (__BORLANDC__) */
-#else /* !defined(__WIN32__) */
-#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__WATCOMC__) || defined(__OS2__) || defined(__EMX__) || defined(__IBMC__) || defined(__IBMCPP__) /* VC++, MinGW, Watcom, emx+gcc, IBM VAC++ */
-#include <sys/utime.h>
-#elif defined(__TURBOC__) /* BCC */
-#include <utime.h>
-#elif defined(LSI_C) /* LSI C */
-#endif /* (__WIN32__) */
-#endif
-#endif
-#endif
-
-#define FALSE 0
-#define TRUE 1
-
-/* state of output_mode and input_mode
-
- c2 0 means ASCII
- X0201
- ISO8859_1
- X0208
- EOF all termination
- c1 32bit data
-
- */
-
-#define ASCII 0
-#define X0208 1
-#define X0201 2
-#define ISO8859_1 8
-#define NO_X0201 3
-#define X0212 0x2844
-#define X0213_1 0x284F
-#define X0213_2 0x2850
-
-/* Input Assumption */
-
-#define JIS_INPUT 4
-#define SJIS_INPUT 5
-#define LATIN1_INPUT 6
-#define FIXED_MIME 7
-#define STRICT_MIME 8
-
-/* MIME ENCODE */
-
-#define ISO2022JP 9
-#define JAPANESE_EUC 10
-#define SHIFT_JIS 11
-
-#define UTF8 12
-#define UTF8_INPUT 13
-#define UTF16BE_INPUT 14
-#define UTF16LE_INPUT 15
-
-#define WISH_TRUE 15
-
-/* ASCII CODE */
-
-#define BS 0x08
-#define TAB 0x09
-#define NL 0x0a
-#define CR 0x0d
-#define ESC 0x1b
-#define SPACE 0x20
-#define AT 0x40
-#define SSP 0xa0
-#define DEL 0x7f
-#define SI 0x0f
-#define SO 0x0e
-#define SSO 0x8e
-#define SS3 0x8f
-
-#define is_alnum(c) \
- (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))
-
-/* I don't trust portablity of toupper */
-#define nkf_toupper(c) (('a'<=c && c<='z')?(c-('a'-'A')):c)
-#define nkf_isoctal(c) ('0'<=c && c<='7')
-#define nkf_isdigit(c) ('0'<=c && c<='9')
-#define nkf_isxdigit(c) (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
-#define nkf_isblank(c) (c == SPACE || c == TAB)
-#define nkf_isspace(c) (nkf_isblank(c) || c == CR || c == NL)
-#define nkf_isalpha(c) (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
-#define nkf_isalnum(c) (nkf_isdigit(c) || nkf_isalpha(c))
-#define nkf_isprint(c) (' '<=c && c<='~')
-#define nkf_isgraph(c) ('!'<=c && c<='~')
-#define hex2bin(c) (('0'<=c&&c<='9') ? (c-'0') : \
- ('A'<=c&&c<='F') ? (c-'A'+10) : \
- ('a'<=c&&c<='f') ? (c-'a'+10) : 0 )
-#define is_eucg3(c2) (((unsigned short)c2 >> 8) == SS3)
-
-#define CP932_TABLE_BEGIN 0xFA
-#define CP932_TABLE_END 0xFC
-#define CP932INV_TABLE_BEGIN 0xED
-#define CP932INV_TABLE_END 0xEE
-#define is_ibmext_in_sjis(c2) (CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END)
-
-#define HOLD_SIZE 1024
-#if defined(INT_IS_SHORT)
-#define IOBUF_SIZE 2048
-#else
-#define IOBUF_SIZE 16384
-#endif
-
-#define DEFAULT_J 'B'
-#define DEFAULT_R 'B'
-
-#define SJ0162 0x00e1 /* 01 - 62 ku offset */
-#define SJ6394 0x0161 /* 63 - 94 ku offset */
-
-#define RANGE_NUM_MAX 18
-#define GETA1 0x22
-#define GETA2 0x2e
-
-
-#if defined(UTF8_OUTPUT_ENABLE) || defined(UTF8_INPUT_ENABLE)
-#define sizeof_euc_to_utf8_1byte 94
-#define sizeof_euc_to_utf8_2bytes 94
-#define sizeof_utf8_to_euc_C2 64
-#define sizeof_utf8_to_euc_E5B8 64
-#define sizeof_utf8_to_euc_2bytes 112
-#define sizeof_utf8_to_euc_3bytes 16
-#endif
-
-/* MIME preprocessor */
-
-#ifdef EASYWIN /*Easy Win */
-extern POINT _BufferSize;
-#endif
-
-struct input_code{
- char *name;
- nkf_char stat;
- nkf_char score;
- nkf_char index;
- nkf_char buf[3];
- void (*status_func)(struct input_code *, nkf_char);
- nkf_char (*iconv_func)(nkf_char c2, nkf_char c1, nkf_char c0);
- int _file_stat;
-};
-
-static char *input_codename = "";
-
-#ifndef PERL_XS
-static const char *CopyRight = COPY_RIGHT;
-#endif
-#if !defined(PERL_XS) && !defined(WIN32DLL)
-static nkf_char noconvert(FILE *f);
-#endif
-static void module_connection(void);
-static nkf_char kanji_convert(FILE *f);
-static nkf_char h_conv(FILE *f,nkf_char c2,nkf_char c1);
-static nkf_char push_hold_buf(nkf_char c2);
-static void set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0));
-static nkf_char s_iconv(nkf_char c2,nkf_char c1,nkf_char c0);
-static nkf_char s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1);
-static nkf_char e_iconv(nkf_char c2,nkf_char c1,nkf_char c0);
-#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
-/* UCS Mapping
- * 0: Shift_JIS, eucJP-ascii
- * 1: eucJP-ms
- * 2: CP932, CP51932
- */
-#define UCS_MAP_ASCII 0
-#define UCS_MAP_MS 1
-#define UCS_MAP_CP932 2
-static int ms_ucs_map_f = UCS_MAP_ASCII;
-#endif
-#ifdef UTF8_INPUT_ENABLE
-/* no NEC special, NEC-selected IBM extended and IBM extended characters */
-static int no_cp932ext_f = FALSE;
-/* ignore ZERO WIDTH NO-BREAK SPACE */
-static int ignore_zwnbsp_f = TRUE;
-static int no_best_fit_chars_f = FALSE;
-static nkf_char unicode_subchar = '?'; /* the regular substitution character */
-static void nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c);
-static void encode_fallback_html(nkf_char c);
-static void encode_fallback_xml(nkf_char c);
-static void encode_fallback_java(nkf_char c);
-static void encode_fallback_perl(nkf_char c);
-static void encode_fallback_subchar(nkf_char c);
-static void (*encode_fallback)(nkf_char c) = NULL;
-static nkf_char w2e_conv(nkf_char c2,nkf_char c1,nkf_char c0,nkf_char *p2,nkf_char *p1);
-static nkf_char w_iconv(nkf_char c2,nkf_char c1,nkf_char c0);
-static nkf_char w_iconv16(nkf_char c2,nkf_char c1,nkf_char c0);
-static nkf_char unicode_to_jis_common(nkf_char c2,nkf_char c1,nkf_char c0,nkf_char *p2,nkf_char *p1);
-static nkf_char w_iconv_common(nkf_char c1,nkf_char c0,const unsigned short *const *pp,nkf_char psize,nkf_char *p2,nkf_char *p1);
-static void w16w_conv(nkf_char val, nkf_char *p2, nkf_char *p1, nkf_char *p0);
-static nkf_char ww16_conv(nkf_char c2, nkf_char c1, nkf_char c0);
-static nkf_char w16e_conv(nkf_char val,nkf_char *p2,nkf_char *p1);
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
-static int unicode_bom_f= 0; /* Output Unicode BOM */
-static int w_oconv16_LE = 0; /* utf-16 little endian */
-static nkf_char e2w_conv(nkf_char c2,nkf_char c1);
-static void w_oconv(nkf_char c2,nkf_char c1);
-static void w_oconv16(nkf_char c2,nkf_char c1);
-#endif
-static void e_oconv(nkf_char c2,nkf_char c1);
-static nkf_char e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1);
-static void s_oconv(nkf_char c2,nkf_char c1);
-static void j_oconv(nkf_char c2,nkf_char c1);
-static void fold_conv(nkf_char c2,nkf_char c1);
-static void cr_conv(nkf_char c2,nkf_char c1);
-static void z_conv(nkf_char c2,nkf_char c1);
-static void rot_conv(nkf_char c2,nkf_char c1);
-static void hira_conv(nkf_char c2,nkf_char c1);
-static void base64_conv(nkf_char c2,nkf_char c1);
-static void iso2022jp_check_conv(nkf_char c2,nkf_char c1);
-static void no_connection(nkf_char c2,nkf_char c1);
-static nkf_char no_connection2(nkf_char c2,nkf_char c1,nkf_char c0);
-
-static void code_score(struct input_code *ptr);
-static void code_status(nkf_char c);
-
-static void std_putc(nkf_char c);
-static nkf_char std_getc(FILE *f);
-static nkf_char std_ungetc(nkf_char c,FILE *f);
-
-static nkf_char broken_getc(FILE *f);
-static nkf_char broken_ungetc(nkf_char c,FILE *f);
-
-static nkf_char mime_begin(FILE *f);
-static nkf_char mime_getc(FILE *f);
-static nkf_char mime_ungetc(nkf_char c,FILE *f);
-
-static void switch_mime_getc(void);
-static void unswitch_mime_getc(void);
-static nkf_char mime_begin_strict(FILE *f);
-static nkf_char mime_getc_buf(FILE *f);
-static nkf_char mime_ungetc_buf(nkf_char c,FILE *f);
-static nkf_char mime_integrity(FILE *f,const unsigned char *p);
-
-static nkf_char base64decode(nkf_char c);
-static void mime_prechar(nkf_char c2, nkf_char c1);
-static void mime_putc(nkf_char c);
-static void open_mime(nkf_char c);
-static void close_mime(void);
-static void eof_mime(void);
-static void mimeout_addchar(nkf_char c);
-#ifndef PERL_XS
-static void usage(void);
-static void version(void);
-#endif
-static void options(unsigned char *c);
-#if defined(PERL_XS) || defined(WIN32DLL)
-static void reinit(void);
-#endif
-
-/* buffers */
-
-#if !defined(PERL_XS) && !defined(WIN32DLL)
-static unsigned char stdibuf[IOBUF_SIZE];
-static unsigned char stdobuf[IOBUF_SIZE];
-#endif
-static unsigned char hold_buf[HOLD_SIZE*2];
-static int hold_count;
-
-/* MIME preprocessor fifo */
-
-#define MIME_BUF_SIZE (1024) /* 2^n ring buffer */
-#define MIME_BUF_MASK (MIME_BUF_SIZE-1)
-#define Fifo(n) mime_buf[(n)&MIME_BUF_MASK]
-static unsigned char mime_buf[MIME_BUF_SIZE];
-static unsigned int mime_top = 0;
-static unsigned int mime_last = 0; /* decoded */
-static unsigned int mime_input = 0; /* undecoded */
-static nkf_char (*mime_iconv_back)(nkf_char c2,nkf_char c1,nkf_char c0) = NULL;
-
-/* flags */
-static int unbuf_f = FALSE;
-static int estab_f = FALSE;
-static int nop_f = FALSE;
-static int binmode_f = TRUE; /* binary mode */
-static int rot_f = FALSE; /* rot14/43 mode */
-static int hira_f = FALSE; /* hira/kata henkan */
-static int input_f = FALSE; /* non fixed input code */
-static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */
-static int mime_f = STRICT_MIME; /* convert MIME B base64 or Q */
-static int mime_decode_f = FALSE; /* mime decode is explicitly on */
-static int mimebuf_f = FALSE; /* MIME buffered input */
-static int broken_f = FALSE; /* convert ESC-less broken JIS */
-static int iso8859_f = FALSE; /* ISO8859 through */
-static int mimeout_f = FALSE; /* base64 mode */
-#if defined(MSDOS) || defined(__OS2__)
-static int x0201_f = TRUE; /* Assume JISX0201 kana */
-#else
-static int x0201_f = NO_X0201; /* Assume NO JISX0201 */
-#endif
-static int iso2022jp_f = FALSE; /* convert ISO-2022-JP */
-
-#ifdef UNICODE_NORMALIZATION
-static int nfc_f = FALSE;
-static nkf_char (*i_nfc_getc)(FILE *) = std_getc; /* input of ugetc */
-static nkf_char (*i_nfc_ungetc)(nkf_char c ,FILE *f) = std_ungetc;
-static nkf_char nfc_getc(FILE *f);
-static nkf_char nfc_ungetc(nkf_char c,FILE *f);
-#endif
-
-#ifdef INPUT_OPTION
-static int cap_f = FALSE;
-static nkf_char (*i_cgetc)(FILE *) = std_getc; /* input of cgetc */
-static nkf_char (*i_cungetc)(nkf_char c ,FILE *f) = std_ungetc;
-static nkf_char cap_getc(FILE *f);
-static nkf_char cap_ungetc(nkf_char c,FILE *f);
-
-static int url_f = FALSE;
-static nkf_char (*i_ugetc)(FILE *) = std_getc; /* input of ugetc */
-static nkf_char (*i_uungetc)(nkf_char c ,FILE *f) = std_ungetc;
-static nkf_char url_getc(FILE *f);
-static nkf_char url_ungetc(nkf_char c,FILE *f);
-#endif
-
-#if defined(INT_IS_SHORT)
-#define NKF_INT32_C(n) (n##L)
-#else
-#define NKF_INT32_C(n) (n)
-#endif
-#define PREFIX_EUCG3 NKF_INT32_C(0x8F00)
-#define CLASS_MASK NKF_INT32_C(0xFF000000)
-#define CLASS_UTF16 NKF_INT32_C(0x01000000)
-#define VALUE_MASK NKF_INT32_C(0x00FFFFFF)
-#define UNICODE_MAX NKF_INT32_C(0x0010FFFF)
-#define is_unicode_capsule(c) ((c & CLASS_MASK) == CLASS_UTF16)
-#define is_unicode_bmp(c) ((c & VALUE_MASK) <= NKF_INT32_C(0xFFFF))
-
-#ifdef NUMCHAR_OPTION
-static int numchar_f = FALSE;
-static nkf_char (*i_ngetc)(FILE *) = std_getc; /* input of ugetc */
-static nkf_char (*i_nungetc)(nkf_char c ,FILE *f) = std_ungetc;
-static nkf_char numchar_getc(FILE *f);
-static nkf_char numchar_ungetc(nkf_char c,FILE *f);
-#endif
-
-#ifdef CHECK_OPTION
-static int noout_f = FALSE;
-static void no_putc(nkf_char c);
-static nkf_char debug_f = FALSE;
-static void debug(const char *str);
-static nkf_char (*iconv_for_check)(nkf_char c2,nkf_char c1,nkf_char c0) = 0;
-#endif
-
-static int guess_f = FALSE;
-#if !defined PERL_XS
-static void print_guessed_code(char *filename);
-#endif
-static void set_input_codename(char *codename);
-static int is_inputcode_mixed = FALSE;
-static int is_inputcode_set = FALSE;
-
-#ifdef EXEC_IO
-static int exec_f = 0;
-#endif
-
-#ifdef SHIFTJIS_CP932
-/* invert IBM extended characters to others */
-static int cp51932_f = TRUE;
-
-/* invert NEC-selected IBM extended characters to IBM extended characters */
-static int cp932inv_f = TRUE;
-
-/* static nkf_char cp932_conv(nkf_char c2, nkf_char c1); */
-#endif /* SHIFTJIS_CP932 */
-
-#ifdef X0212_ENABLE
-static int x0212_f = FALSE;
-static nkf_char x0212_shift(nkf_char c);
-static nkf_char x0212_unshift(nkf_char c);
-#endif
-static int x0213_f = FALSE;
-
-static unsigned char prefix_table[256];
-
-static void set_code_score(struct input_code *ptr, nkf_char score);
-static void clr_code_score(struct input_code *ptr, nkf_char score);
-static void status_disable(struct input_code *ptr);
-static void status_push_ch(struct input_code *ptr, nkf_char c);
-static void status_clear(struct input_code *ptr);
-static void status_reset(struct input_code *ptr);
-static void status_reinit(struct input_code *ptr);
-static void status_check(struct input_code *ptr, nkf_char c);
-static void e_status(struct input_code *, nkf_char);
-static void s_status(struct input_code *, nkf_char);
-
-#ifdef UTF8_INPUT_ENABLE
-static void w_status(struct input_code *, nkf_char);
-static void w16_status(struct input_code *, nkf_char);
-static int utf16_mode = UTF16BE_INPUT;
-#endif
-
-struct input_code input_code_list[] = {
- {"EUC-JP", 0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0},
- {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0},
-#ifdef UTF8_INPUT_ENABLE
- {"UTF-8", 0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0},
- {"UTF-16", 0, 0, 0, {0, 0, 0}, w16_status, w_iconv16, 0},
-#endif
- {0}
-};
-
-static int mimeout_mode = 0;
-static int base64_count = 0;
-
-/* X0208 -> ASCII converter */
-
-/* fold parameter */
-static int f_line = 0; /* chars in line */
-static int f_prev = 0;
-static int fold_preserve_f = FALSE; /* preserve new lines */
-static int fold_f = FALSE;
-static int fold_len = 0;
-
-/* options */
-static unsigned char kanji_intro = DEFAULT_J;
-static unsigned char ascii_intro = DEFAULT_R;
-
-/* Folding */
-
-#define FOLD_MARGIN 10
-#define DEFAULT_FOLD 60
-
-static int fold_margin = FOLD_MARGIN;
-
-/* converters */
-
-#ifdef DEFAULT_CODE_JIS
-# define DEFAULT_CONV j_oconv
-#endif
-#ifdef DEFAULT_CODE_SJIS
-# define DEFAULT_CONV s_oconv
-#endif
-#ifdef DEFAULT_CODE_EUC
-# define DEFAULT_CONV e_oconv
-#endif
-#ifdef DEFAULT_CODE_UTF8
-# define DEFAULT_CONV w_oconv
-#endif
-
-/* process default */
-static void (*output_conv)(nkf_char c2,nkf_char c1) = DEFAULT_CONV;
-
-static void (*oconv)(nkf_char c2,nkf_char c1) = no_connection;
-/* s_iconv or oconv */
-static nkf_char (*iconv)(nkf_char c2,nkf_char c1,nkf_char c0) = no_connection2;
-
-static void (*o_zconv)(nkf_char c2,nkf_char c1) = no_connection;
-static void (*o_fconv)(nkf_char c2,nkf_char c1) = no_connection;
-static void (*o_crconv)(nkf_char c2,nkf_char c1) = no_connection;
-static void (*o_rot_conv)(nkf_char c2,nkf_char c1) = no_connection;
-static void (*o_hira_conv)(nkf_char c2,nkf_char c1) = no_connection;
-static void (*o_base64conv)(nkf_char c2,nkf_char c1) = no_connection;
-static void (*o_iso2022jp_check_conv)(nkf_char c2,nkf_char c1) = no_connection;
-
-/* static redirections */
-
-static void (*o_putc)(nkf_char c) = std_putc;
-
-static nkf_char (*i_getc)(FILE *f) = std_getc; /* general input */
-static nkf_char (*i_ungetc)(nkf_char c,FILE *f) =std_ungetc;
-
-static nkf_char (*i_bgetc)(FILE *) = std_getc; /* input of mgetc */
-static nkf_char (*i_bungetc)(nkf_char c ,FILE *f) = std_ungetc;
-
-static void (*o_mputc)(nkf_char c) = std_putc ; /* output of mputc */
-
-static nkf_char (*i_mgetc)(FILE *) = std_getc; /* input of mgetc */
-static nkf_char (*i_mungetc)(nkf_char c ,FILE *f) = std_ungetc;
-
-/* for strict mime */
-static nkf_char (*i_mgetc_buf)(FILE *) = std_getc; /* input of mgetc_buf */
-static nkf_char (*i_mungetc_buf)(nkf_char c,FILE *f) = std_ungetc;
-
-/* Global states */
-static int output_mode = ASCII, /* output kanji mode */
- input_mode = ASCII, /* input kanji mode */
- shift_mode = FALSE; /* TRUE shift out, or X0201 */
-static int mime_decode_mode = FALSE; /* MIME mode B base64, Q hex */
-
-/* X0201 / X0208 conversion tables */
-
-/* X0201 kana conversion table */
-/* 90-9F A0-DF */
-static const
-unsigned char cv[]= {
- 0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
- 0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
- 0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
- 0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,
- 0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,
- 0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,
- 0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,
- 0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,
- 0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,
- 0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,
- 0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,
- 0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,
- 0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,
- 0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,
- 0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,
- 0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,
- 0x00,0x00};
-
-
-/* X0201 kana conversion table for daguten */
-/* 90-9F A0-DF */
-static const
-unsigned char dv[]= {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x74,
- 0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,
- 0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,
- 0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,
- 0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,
- 0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,
- 0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
-
-/* X0201 kana conversion table for han-daguten */
-/* 90-9F A0-DF */
-static const
-unsigned char ev[]= {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54,
- 0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
-
-
-/* X0208 kigou conversion table */
-/* 0x8140 - 0x819e */
-static const
-unsigned char fv[] = {
-
- 0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
- 0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
- 0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
- 0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,
- 0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,
- 0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,
- 0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-} ;
-
-
-#define CRLF 1
-
-static int file_out_f = FALSE;
-#ifdef OVERWRITE
-static int overwrite_f = FALSE;
-static int preserve_time_f = FALSE;
-static int backup_f = FALSE;
-static char *backup_suffix = "";
-static char *get_backup_filename(const char *suffix, const char *filename);
-#endif
-
-static int crmode_f = 0; /* CR, NL, CRLF */
-#ifdef EASYWIN /*Easy Win */
-static int end_check;
-#endif /*Easy Win */
-
-#define STD_GC_BUFSIZE (256)
-nkf_char std_gc_buf[STD_GC_BUFSIZE];
-nkf_char std_gc_ndx;
-
-#ifdef WIN32DLL
-#include "nkf32dll.c"
-#elif defined(PERL_XS)
-#else /* WIN32DLL */
-int main(int argc, char **argv)
-{
- FILE *fin;
- unsigned char *cp;
-
- char *outfname = NULL;
- char *origfname;
-
-#ifdef EASYWIN /*Easy Win */
- _BufferSize.y = 400;/*Set Scroll Buffer Size*/
-#endif
-
- for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
- cp = (unsigned char *)*argv;
- options(cp);
-#ifdef EXEC_IO
- if (exec_f){
- int fds[2], pid;
- if (pipe(fds) < 0 || (pid = fork()) < 0){
- abort();
- }
- if (pid == 0){
- if (exec_f > 0){
- close(fds[0]);
- dup2(fds[1], 1);
- }else{
- close(fds[1]);
- dup2(fds[0], 0);
- }
- execvp(argv[1], &argv[1]);
- }
- if (exec_f > 0){
- close(fds[1]);
- dup2(fds[0], 0);
- }else{
- close(fds[0]);
- dup2(fds[1], 1);
- }
- argc = 0;
- break;
- }
-#endif
- }
- if(x0201_f == WISH_TRUE)
- x0201_f = ((!iso2022jp_f)? TRUE : NO_X0201);
-
- if (binmode_f == TRUE)
-#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
- if (freopen("","wb",stdout) == NULL)
- return (-1);
-#else
- setbinmode(stdout);
-#endif
-
- if (unbuf_f)
- setbuf(stdout, (char *) NULL);
- else
- setvbuffer(stdout, (char *) stdobuf, IOBUF_SIZE);
-
- if (argc == 0) {
- if (binmode_f == TRUE)
-#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
- if (freopen("","rb",stdin) == NULL) return (-1);
-#else
- setbinmode(stdin);
-#endif
- setvbuffer(stdin, (char *) stdibuf, IOBUF_SIZE);
- if (nop_f)
- noconvert(stdin);
- else {
- kanji_convert(stdin);
- if (guess_f) print_guessed_code(NULL);
- }
- } else {
- int nfiles = argc;
- while (argc--) {
- is_inputcode_mixed = FALSE;
- is_inputcode_set = FALSE;
- input_codename = "";
-#ifdef CHECK_OPTION
- iconv_for_check = 0;
-#endif
- if ((fin = fopen((origfname = *argv++), "r")) == NULL) {
- perror(*--argv);
- return(-1);
- } else {
-#ifdef OVERWRITE
- int fd = 0;
- int fd_backup = 0;
-#endif
-
-/* reopen file for stdout */
- if (file_out_f == TRUE) {
-#ifdef OVERWRITE
- if (overwrite_f){
- outfname = malloc(strlen(origfname)
- + strlen(".nkftmpXXXXXX")
- + 1);
- if (!outfname){
- perror(origfname);
- return -1;
- }
- strcpy(outfname, origfname);
-#ifdef MSDOS
- {
- int i;
- for (i = strlen(outfname); i; --i){
- if (outfname[i - 1] == '/'
- || outfname[i - 1] == '\\'){
- break;
- }
- }
- outfname[i] = '\0';
- }
- strcat(outfname, "ntXXXXXX");
- mktemp(outfname);
- fd = open(outfname, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
- S_IREAD | S_IWRITE);
-#else
- strcat(outfname, ".nkftmpXXXXXX");
- fd = mkstemp(outfname);
-#endif
- if (fd < 0
- || (fd_backup = dup(fileno(stdout))) < 0
- || dup2(fd, fileno(stdout)) < 0
- ){
- perror(origfname);
- return -1;
- }
- }else
-#endif
- if(argc == 1 ) {
- outfname = *argv++;
- argc--;
- } else {
- outfname = "nkf.out";
- }
-
- if(freopen(outfname, "w", stdout) == NULL) {
- perror (outfname);
- return (-1);
- }
- if (binmode_f == TRUE) {
-#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
- if (freopen("","wb",stdout) == NULL)
- return (-1);
-#else
- setbinmode(stdout);
-#endif
- }
- }
- if (binmode_f == TRUE)
-#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
- if (freopen("","rb",fin) == NULL)
- return (-1);
-#else
- setbinmode(fin);
-#endif
- setvbuffer(fin, (char *) stdibuf, IOBUF_SIZE);
- if (nop_f)
- noconvert(fin);
- else {
- char *filename = NULL;
- kanji_convert(fin);
- if (nfiles > 1) filename = origfname;
- if (guess_f) print_guessed_code(filename);
- }
- fclose(fin);
-#ifdef OVERWRITE
- if (overwrite_f) {
- struct stat sb;
-#if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__)
- time_t tb[2];
-#else
- struct utimbuf tb;
-#endif
-
- fflush(stdout);
- close(fd);
- if (dup2(fd_backup, fileno(stdout)) < 0){
- perror("dup2");
- }
- if (stat(origfname, &sb)) {
- fprintf(stderr, "Can't stat %s\n", origfname);
- }
- /* $B%Q!<%_%C%7%g%s$rI|85(B */
- if (chmod(outfname, sb.st_mode)) {
- fprintf(stderr, "Can't set permission %s\n", outfname);
- }
-
- /* $B%?%$%`%9%?%s%W$rI|85(B */
- if(preserve_time_f){
-#if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__)
- tb[0] = tb[1] = sb.st_mtime;
- if (utime(outfname, tb)) {
- fprintf(stderr, "Can't set timestamp %s\n", outfname);
- }
-#else
- tb.actime = sb.st_atime;
- tb.modtime = sb.st_mtime;
- if (utime(outfname, &tb)) {
- fprintf(stderr, "Can't set timestamp %s\n", outfname);
- }
-#endif
- }
- if(backup_f){
- char *backup_filename = get_backup_filename(backup_suffix, origfname);
-#ifdef MSDOS
- unlink(backup_filename);
-#endif
- if (rename(origfname, backup_filename)) {
- perror(backup_filename);
- fprintf(stderr, "Can't rename %s to %s\n",
- origfname, backup_filename);
- }
- }else{
-#ifdef MSDOS
- if (unlink(origfname)){
- perror(origfname);
- }
-#endif
- }
- if (rename(outfname, origfname)) {
- perror(origfname);
- fprintf(stderr, "Can't rename %s to %s\n",
- outfname, origfname);
- }
- free(outfname);
- }
-#endif
- }
- }
- }
-#ifdef EASYWIN /*Easy Win */
- if (file_out_f == FALSE)
- scanf("%d",&end_check);
- else
- fclose(stdout);
-#else /* for Other OS */
- if (file_out_f == TRUE)
- fclose(stdout);
-#endif /*Easy Win */
- return (0);
-}
-#endif /* WIN32DLL */
-
-#ifdef OVERWRITE
-char *get_backup_filename(const char *suffix, const char *filename)
-{
- char *backup_filename;
- int asterisk_count = 0;
- int i, j;
- int filename_length = strlen(filename);
-
- for(i = 0; suffix[i]; i++){
- if(suffix[i] == '*') asterisk_count++;
- }
-
- if(asterisk_count){
- backup_filename = malloc(strlen(suffix) + (asterisk_count * (filename_length - 1)) + 1);
- if (!backup_filename){
- perror("Can't malloc backup filename.");
- return NULL;
- }
-
- for(i = 0, j = 0; suffix[i];){
- if(suffix[i] == '*'){
- backup_filename[j] = '\0';
- strncat(backup_filename, filename, filename_length);
- i++;
- j += filename_length;
- }else{
- backup_filename[j++] = suffix[i++];
- }
- }
- backup_filename[j] = '\0';
- }else{
- j = strlen(suffix) + filename_length;
- backup_filename = malloc( + 1);
- strcpy(backup_filename, filename);
- strcat(backup_filename, suffix);
- backup_filename[j] = '\0';
- }
- return backup_filename;
-}
-#endif
-
-static const
-struct {
- const char *name;
- const char *alias;
-} long_option[] = {
- {"ic=", ""},
- {"oc=", ""},
- {"base64","jMB"},
- {"euc","e"},
- {"euc-input","E"},
- {"fj","jm"},
- {"help","v"},
- {"jis","j"},
- {"jis-input","J"},
- {"mac","sLm"},
- {"mime","jM"},
- {"mime-input","m"},
- {"msdos","sLw"},
- {"sjis","s"},
- {"sjis-input","S"},
- {"unix","eLu"},
- {"version","V"},
- {"windows","sLw"},
- {"hiragana","h1"},
- {"katakana","h2"},
- {"katakana-hiragana","h3"},
- {"guess", "g"},
- {"cp932", ""},
- {"no-cp932", ""},
-#ifdef X0212_ENABLE
- {"x0212", ""},
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- {"utf8", "w"},
- {"utf16", "w16"},
- {"ms-ucs-map", ""},
- {"fb-skip", ""},
- {"fb-html", ""},
- {"fb-xml", ""},
- {"fb-perl", ""},
- {"fb-java", ""},
- {"fb-subchar", ""},
- {"fb-subchar=", ""},
-#endif
-#ifdef UTF8_INPUT_ENABLE
- {"utf8-input", "W"},
- {"utf16-input", "W16"},
- {"no-cp932ext", ""},
- {"no-best-fit-chars",""},
-#endif
-#ifdef UNICODE_NORMALIZATION
- {"utf8mac-input", ""},
-#endif
-#ifdef OVERWRITE
- {"overwrite", ""},
- {"overwrite=", ""},
- {"in-place", ""},
- {"in-place=", ""},
-#endif
-#ifdef INPUT_OPTION
- {"cap-input", ""},
- {"url-input", ""},
-#endif
-#ifdef NUMCHAR_OPTION
- {"numchar-input", ""},
-#endif
-#ifdef CHECK_OPTION
- {"no-output", ""},
- {"debug", ""},
-#endif
-#ifdef SHIFTJIS_CP932
- {"cp932inv", ""},
-#endif
-#ifdef EXEC_IO
- {"exec-in", ""},
- {"exec-out", ""},
-#endif
- {"prefix=", ""},
-};
-
-static int option_mode = 0;
-
-void options(unsigned char *cp)
-{
- nkf_char i, j;
- unsigned char *p;
- unsigned char *cp_back = NULL;
- char codeset[32];
-
- if (option_mode==1)
- return;
- while(*cp && *cp++!='-');
- while (*cp || cp_back) {
- if(!*cp){
- cp = cp_back;
- cp_back = NULL;
- continue;
- }
- p = 0;
- switch (*cp++) {
- case '-': /* literal options */
- if (!*cp || *cp == SPACE) { /* ignore the rest of arguments */
- option_mode = 1;
- return;
- }
- for (i=0;i<sizeof(long_option)/sizeof(long_option[0]);i++) {
- p = (unsigned char *)long_option[i].name;
- for (j=0;*p && *p != '=' && *p == cp[j];p++, j++);
- if (*p == cp[j] || cp[j] == ' '){
- p = &cp[j] + 1;
- break;
- }
- p = 0;
- }
- if (p == 0) return;
- while(*cp && *cp != SPACE && cp++);
- if (long_option[i].alias[0]){
- cp_back = cp;
- cp = (unsigned char *)long_option[i].alias;
- }else{
- if (strcmp(long_option[i].name, "ic=") == 0){
- for (i=0; i < 16 && SPACE < p[i] && p[i] < DEL; i++){
- codeset[i] = nkf_toupper(p[i]);
- }
- codeset[i] = 0;
- if(strcmp(codeset, "ISO-2022-JP") == 0 ||
- strcmp(codeset, "X-ISO2022JP-CP932") == 0 ||
- strcmp(codeset, "CP50220") == 0 ||
- strcmp(codeset, "CP50221") == 0 ||
- strcmp(codeset, "CP50222") == 0 ||
- strcmp(codeset, "ISO-2022-JP-MS") == 0){
- input_f = JIS_INPUT;
- }else if(strcmp(codeset, "ISO-2022-JP-1") == 0){
- input_f = JIS_INPUT;
-#ifdef X0212_ENABLE
- x0212_f = TRUE;
-#endif
- }else if(strcmp(codeset, "ISO-2022-JP-3") == 0){
- input_f = JIS_INPUT;
-#ifdef X0212_ENABLE
- x0212_f = TRUE;
-#endif
- x0213_f = TRUE;
- }else if(strcmp(codeset, "SHIFT_JIS") == 0){
- input_f = SJIS_INPUT;
- if (x0201_f==NO_X0201) x0201_f=TRUE;
- }else if(strcmp(codeset, "WINDOWS-31J") == 0 ||
- strcmp(codeset, "CSWINDOWS31J") == 0 ||
- strcmp(codeset, "CP932") == 0 ||
- strcmp(codeset, "MS932") == 0){
- input_f = SJIS_INPUT;
- x0201_f = FALSE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- }else if(strcmp(codeset, "EUCJP") == 0 ||
- strcmp(codeset, "EUC-JP") == 0){
- input_f = JIS_INPUT;
- }else if(strcmp(codeset, "CP51932") == 0){
- input_f = JIS_INPUT;
- x0201_f = FALSE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- }else if(strcmp(codeset, "EUC-JP-MS") == 0 ||
- strcmp(codeset, "EUCJP-MS") == 0 ||
- strcmp(codeset, "EUCJPMS") == 0){
- input_f = JIS_INPUT;
- x0201_f = FALSE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_MS;
-#endif
- }else if(strcmp(codeset, "EUC-JP-ASCII") == 0 ||
- strcmp(codeset, "EUCJP-ASCII") == 0){
- input_f = JIS_INPUT;
- x0201_f = FALSE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_ASCII;
-#endif
- }else if(strcmp(codeset, "SHIFT_JISX0213") == 0 ||
- strcmp(codeset, "SHIFT_JIS-2004") == 0){
- input_f = SJIS_INPUT;
- x0213_f = TRUE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
- cp932inv_f = FALSE;
-#endif
- if (x0201_f==NO_X0201) x0201_f=TRUE;
- }else if(strcmp(codeset, "EUC-JISX0213") == 0 ||
- strcmp(codeset, "EUC-JIS-2004") == 0){
- input_f = JIS_INPUT;
- x0201_f = FALSE;
- x0213_f = TRUE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
- cp932inv_f = FALSE;
-#endif
-#ifdef UTF8_INPUT_ENABLE
- }else if(strcmp(codeset, "UTF-8") == 0 ||
- strcmp(codeset, "UTF-8N") == 0 ||
- strcmp(codeset, "UTF-8-BOM") == 0){
- input_f = UTF8_INPUT;
-#ifdef UNICODE_NORMALIZATION
- }else if(strcmp(codeset, "UTF8-MAC") == 0 ||
- strcmp(codeset, "UTF-8-MAC") == 0){
- input_f = UTF8_INPUT;
- nfc_f = TRUE;
-#endif
- }else if(strcmp(codeset, "UTF-16") == 0){
- input_f = UTF16BE_INPUT;
- utf16_mode = UTF16BE_INPUT;
- }else if(strcmp(codeset, "UTF-16BE") == 0 ||
- strcmp(codeset, "UTF-16BE-BOM") == 0){
- input_f = UTF16BE_INPUT;
- utf16_mode = UTF16BE_INPUT;
- }else if(strcmp(codeset, "UTF-16LE") == 0 ||
- strcmp(codeset, "UTF-16LE-BOM") == 0){
- input_f = UTF16LE_INPUT;
- utf16_mode = UTF16LE_INPUT;
-#endif
- }
- continue;
- }
- if (strcmp(long_option[i].name, "oc=") == 0){
- for (i=0; i < 16 && SPACE < p[i] && p[i] < DEL; i++){
- codeset[i] = nkf_toupper(p[i]);
- }
- codeset[i] = 0;
- if(strcmp(codeset, "ISO-2022-JP") == 0 ||
- strcmp(codeset, "CP50220") == 0){
- output_conv = j_oconv;
- }else if(strcmp(codeset, "X-ISO2022JP-CP932") == 0){
- output_conv = j_oconv;
- no_cp932ext_f = TRUE;
- }else if(strcmp(codeset, "CP50221") == 0 ||
- strcmp(codeset, "ISO-2022-JP-MS") == 0){
- output_conv = j_oconv;
- x0201_f = FALSE;
- }else if(strcmp(codeset, "ISO-2022-JP-1") == 0){
- output_conv = j_oconv;
-#ifdef X0212_ENABLE
- x0212_f = TRUE;
-#endif
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
- }else if(strcmp(codeset, "ISO-2022-JP-3") == 0){
- output_conv = j_oconv;
-#ifdef X0212_ENABLE
- x0212_f = TRUE;
-#endif
- x0213_f = TRUE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
- }else if(strcmp(codeset, "ISO-2022-JP-MS") == 0){
- output_conv = j_oconv;
- x0201_f = FALSE;
-#ifdef X0212_ENABLE
- x0212_f = TRUE;
-#endif
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
- }else if(strcmp(codeset, "SHIFT_JIS") == 0){
- output_conv = s_oconv;
- }else if(strcmp(codeset, "WINDOWS-31J") == 0 ||
- strcmp(codeset, "CSWINDOWS31J") == 0 ||
- strcmp(codeset, "CP932") == 0 ||
- strcmp(codeset, "MS932") == 0){
- output_conv = s_oconv;
- x0201_f = FALSE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
- cp932inv_f = TRUE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- }else if(strcmp(codeset, "EUCJP") == 0 ||
- strcmp(codeset, "EUC-JP") == 0){
- output_conv = e_oconv;
- }else if(strcmp(codeset, "CP51932") == 0){
- output_conv = e_oconv;
- x0201_f = FALSE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- }else if(strcmp(codeset, "EUC-JP-MS") == 0 ||
- strcmp(codeset, "EUCJP-MS") == 0 ||
- strcmp(codeset, "EUCJPMS") == 0){
- output_conv = e_oconv;
- x0201_f = FALSE;
-#ifdef X0212_ENABLE
- x0212_f = TRUE;
-#endif
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_MS;
-#endif
- }else if(strcmp(codeset, "EUC-JP-ASCII") == 0 ||
- strcmp(codeset, "EUCJP-ASCII") == 0){
- output_conv = e_oconv;
- x0201_f = FALSE;
-#ifdef X0212_ENABLE
- x0212_f = TRUE;
-#endif
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_ASCII;
-#endif
- }else if(strcmp(codeset, "SHIFT_JISX0213") == 0 ||
- strcmp(codeset, "SHIFT_JIS-2004") == 0){
- output_conv = s_oconv;
- x0213_f = TRUE;
-#ifdef SHIFTJIS_CP932
- cp932inv_f = FALSE;
-#endif
- }else if(strcmp(codeset, "EUC-JISX0213") == 0 ||
- strcmp(codeset, "EUC-JIS-2004") == 0){
- output_conv = e_oconv;
-#ifdef X0212_ENABLE
- x0212_f = TRUE;
-#endif
- x0213_f = TRUE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- }else if(strcmp(codeset, "UTF-8") == 0){
- output_conv = w_oconv;
- }else if(strcmp(codeset, "UTF-8N") == 0){
- output_conv = w_oconv;
- unicode_bom_f=1;
- }else if(strcmp(codeset, "UTF-8-BOM") == 0){
- output_conv = w_oconv;
- unicode_bom_f=2;
- }else if(strcmp(codeset, "UTF-16BE") == 0){
- output_conv = w_oconv16;
- unicode_bom_f=1;
- }else if(strcmp(codeset, "UTF-16") == 0 ||
- strcmp(codeset, "UTF-16BE-BOM") == 0){
- output_conv = w_oconv16;
- unicode_bom_f=2;
- }else if(strcmp(codeset, "UTF-16LE") == 0){
- output_conv = w_oconv16;
- w_oconv16_LE = 1;
- unicode_bom_f=1;
- }else if(strcmp(codeset, "UTF-16LE-BOM") == 0){
- output_conv = w_oconv16;
- w_oconv16_LE = 1;
- unicode_bom_f=2;
-#endif
- }
- continue;
- }
-#ifdef OVERWRITE
- if (strcmp(long_option[i].name, "overwrite") == 0){
- file_out_f = TRUE;
- overwrite_f = TRUE;
- preserve_time_f = TRUE;
- continue;
- }
- if (strcmp(long_option[i].name, "overwrite=") == 0){
- file_out_f = TRUE;
- overwrite_f = TRUE;
- preserve_time_f = TRUE;
- backup_f = TRUE;
- backup_suffix = malloc(strlen((char *) p) + 1);
- strcpy(backup_suffix, (char *) p);
- continue;
- }
- if (strcmp(long_option[i].name, "in-place") == 0){
- file_out_f = TRUE;
- overwrite_f = TRUE;
- preserve_time_f = FALSE;
- continue;
- }
- if (strcmp(long_option[i].name, "in-place=") == 0){
- file_out_f = TRUE;
- overwrite_f = TRUE;
- preserve_time_f = FALSE;
- backup_f = TRUE;
- backup_suffix = malloc(strlen((char *) p) + 1);
- strcpy(backup_suffix, (char *) p);
- continue;
- }
-#endif
-#ifdef INPUT_OPTION
- if (strcmp(long_option[i].name, "cap-input") == 0){
- cap_f = TRUE;
- continue;
- }
- if (strcmp(long_option[i].name, "url-input") == 0){
- url_f = TRUE;
- continue;
- }
-#endif
-#ifdef NUMCHAR_OPTION
- if (strcmp(long_option[i].name, "numchar-input") == 0){
- numchar_f = TRUE;
- continue;
- }
-#endif
-#ifdef CHECK_OPTION
- if (strcmp(long_option[i].name, "no-output") == 0){
- noout_f = TRUE;
- continue;
- }
- if (strcmp(long_option[i].name, "debug") == 0){
- debug_f = TRUE;
- continue;
- }
-#endif
- if (strcmp(long_option[i].name, "cp932") == 0){
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
- cp932inv_f = TRUE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- continue;
- }
- if (strcmp(long_option[i].name, "no-cp932") == 0){
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
- cp932inv_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_ASCII;
-#endif
- continue;
- }
-#ifdef SHIFTJIS_CP932
- if (strcmp(long_option[i].name, "cp932inv") == 0){
- cp932inv_f = TRUE;
- continue;
- }
-#endif
-
-#ifdef X0212_ENABLE
- if (strcmp(long_option[i].name, "x0212") == 0){
- x0212_f = TRUE;
- continue;
- }
-#endif
-
-#ifdef EXEC_IO
- if (strcmp(long_option[i].name, "exec-in") == 0){
- exec_f = 1;
- return;
- }
- if (strcmp(long_option[i].name, "exec-out") == 0){
- exec_f = -1;
- return;
- }
-#endif
-#if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE)
- if (strcmp(long_option[i].name, "no-cp932ext") == 0){
- no_cp932ext_f = TRUE;
- continue;
- }
- if (strcmp(long_option[i].name, "no-best-fit-chars") == 0){
- no_best_fit_chars_f = TRUE;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-skip") == 0){
- encode_fallback = NULL;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-html") == 0){
- encode_fallback = encode_fallback_html;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-xml" ) == 0){
- encode_fallback = encode_fallback_xml;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-java") == 0){
- encode_fallback = encode_fallback_java;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-perl") == 0){
- encode_fallback = encode_fallback_perl;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-subchar") == 0){
- encode_fallback = encode_fallback_subchar;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-subchar=") == 0){
- encode_fallback = encode_fallback_subchar;
- unicode_subchar = 0;
- if (p[0] != '0'){
- /* decimal number */
- for (i = 0; i < 7 && nkf_isdigit(p[i]); i++){
- unicode_subchar *= 10;
- unicode_subchar += hex2bin(p[i]);
- }
- }else if(p[1] == 'x' || p[1] == 'X'){
- /* hexadecimal number */
- for (i = 2; i < 8 && nkf_isxdigit(p[i]); i++){
- unicode_subchar <<= 4;
- unicode_subchar |= hex2bin(p[i]);
- }
- }else{
- /* octal number */
- for (i = 1; i < 8 && nkf_isoctal(p[i]); i++){
- unicode_subchar *= 8;
- unicode_subchar += hex2bin(p[i]);
- }
- }
- w16e_conv(unicode_subchar, &i, &j);
- unicode_subchar = i<<8 | j;
- continue;
- }
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- if (strcmp(long_option[i].name, "ms-ucs-map") == 0){
- ms_ucs_map_f = UCS_MAP_MS;
- continue;
- }
-#endif
-#ifdef UNICODE_NORMALIZATION
- if (strcmp(long_option[i].name, "utf8mac-input") == 0){
- input_f = UTF8_INPUT;
- nfc_f = TRUE;
- continue;
- }
-#endif
- if (strcmp(long_option[i].name, "prefix=") == 0){
- if (nkf_isgraph(p[0])){
- for (i = 1; nkf_isgraph(p[i]); i++){
- prefix_table[p[i]] = p[0];
- }
- }
- continue;
- }
- }
- continue;
- case 'b': /* buffered mode */
- unbuf_f = FALSE;
- continue;
- case 'u': /* non bufferd mode */
- unbuf_f = TRUE;
- continue;
- case 't': /* transparent mode */
- if (*cp=='1') {
- /* alias of -t */
- nop_f = TRUE;
- *cp++;
- } else if (*cp=='2') {
- /*
- * -t with put/get
- *
- * nkf -t2MB hoge.bin | nkf -t2mB | diff -s - hoge.bin
- *
- */
- nop_f = 2;
- *cp++;
- } else
- nop_f = TRUE;
- continue;
- case 'j': /* JIS output */
- case 'n':
- output_conv = j_oconv;
- continue;
- case 'e': /* AT&T EUC output */
- output_conv = e_oconv;
- continue;
- case 's': /* SJIS output */
- output_conv = s_oconv;
- continue;
- case 'l': /* ISO8859 Latin-1 support, no conversion */
- iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */
- input_f = LATIN1_INPUT;
- continue;
- case 'i': /* Kanji IN ESC-$-@/B */
- if (*cp=='@'||*cp=='B')
- kanji_intro = *cp++;
- continue;
- case 'o': /* ASCII IN ESC-(-J/B */
- if (*cp=='J'||*cp=='B'||*cp=='H')
- ascii_intro = *cp++;
- continue;
- case 'h':
- /*
- bit:1 katakana->hiragana
- bit:2 hiragana->katakana
- */
- if ('9'>= *cp && *cp>='0')
- hira_f |= (*cp++ -'0');
- else
- hira_f |= 1;
- continue;
- case 'r':
- rot_f = TRUE;
- continue;
-#if defined(MSDOS) || defined(__OS2__)
- case 'T':
- binmode_f = FALSE;
- continue;
-#endif
-#ifndef PERL_XS
- case 'V':
- version();
- exit(1);
- break;
- case 'v':
- usage();
- exit(1);
- break;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- case 'w': /* UTF-8 output */
- if ('1'== cp[0] && '6'==cp[1]) {
- output_conv = w_oconv16; cp+=2;
- if (cp[0]=='L') {
- unicode_bom_f=2; cp++;
- w_oconv16_LE = 1;
- if (cp[0] == '0'){
- unicode_bom_f=1; cp++;
- }
- } else if (cp[0] == 'B') {
- unicode_bom_f=2; cp++;
- if (cp[0] == '0'){
- unicode_bom_f=1; cp++;
- }
- }
- } else if (cp[0] == '8') {
- output_conv = w_oconv; cp++;
- unicode_bom_f=2;
- if (cp[0] == '0'){
- unicode_bom_f=1; cp++;
- }
- } else
- output_conv = w_oconv;
- continue;
-#endif
-#ifdef UTF8_INPUT_ENABLE
- case 'W': /* UTF-8 input */
- if ('1'== cp[0] && '6'==cp[1]) {
- input_f = UTF16BE_INPUT;
- utf16_mode = UTF16BE_INPUT;
- cp += 2;
- if (cp[0]=='L') {
- cp++;
- input_f = UTF16LE_INPUT;
- utf16_mode = UTF16LE_INPUT;
- } else if (cp[0] == 'B') {
- cp++;
- input_f = UTF16BE_INPUT;
- utf16_mode = UTF16BE_INPUT;
- }
- } else if (cp[0] == '8') {
- cp++;
- input_f = UTF8_INPUT;
- } else
- input_f = UTF8_INPUT;
- continue;
-#endif
- /* Input code assumption */
- case 'J': /* JIS input */
- case 'E': /* AT&T EUC input */
- input_f = JIS_INPUT;
- continue;
- case 'S': /* MS Kanji input */
- input_f = SJIS_INPUT;
- if (x0201_f==NO_X0201) x0201_f=TRUE;
- continue;
- case 'Z': /* Convert X0208 alphabet to asii */
- /* bit:0 Convert X0208
- bit:1 Convert Kankaku to one space
- bit:2 Convert Kankaku to two spaces
- bit:3 Convert HTML Entity
- */
- if ('9'>= *cp && *cp>='0')
- alpha_f |= 1<<(*cp++ -'0');
- else
- alpha_f |= TRUE;
- continue;
- case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */
- x0201_f = FALSE; /* No X0201->X0208 conversion */
- /* accept X0201
- ESC-(-I in JIS, EUC, MS Kanji
- SI/SO in JIS, EUC, MS Kanji
- SSO in EUC, JIS, not in MS Kanji
- MS Kanji (0xa0-0xdf)
- output X0201
- ESC-(-I in JIS (0x20-0x5f)
- SSO in EUC (0xa0-0xdf)
- 0xa0-0xd in MS Kanji (0xa0-0xdf)
- */
- continue;
- case 'X': /* Assume X0201 kana */
- /* Default value is NO_X0201 for EUC/MS-Kanji mix */
- x0201_f = TRUE;
- continue;
- case 'F': /* prserve new lines */
- fold_preserve_f = TRUE;
- case 'f': /* folding -f60 or -f */
- fold_f = TRUE;
- fold_len = 0;
- while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
- fold_len *= 10;
- fold_len += *cp++ - '0';
- }
- if (!(0<fold_len && fold_len<BUFSIZ))
- fold_len = DEFAULT_FOLD;
- if (*cp=='-') {
- fold_margin = 0;
- cp++;
- while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
- fold_margin *= 10;
- fold_margin += *cp++ - '0';
- }
- }
- continue;
- case 'm': /* MIME support */
- /* mime_decode_f = TRUE; */ /* this has too large side effects... */
- if (*cp=='B'||*cp=='Q') {
- mime_decode_mode = *cp++;
- mimebuf_f = FIXED_MIME;
- } else if (*cp=='N') {
- mime_f = TRUE; cp++;
- } else if (*cp=='S') {
- mime_f = STRICT_MIME; cp++;
- } else if (*cp=='0') {
- mime_decode_f = FALSE;
- mime_f = FALSE; cp++;
- }
- continue;
- case 'M': /* MIME output */
- if (*cp=='B') {
- mimeout_mode = 'B';
- mimeout_f = FIXED_MIME; cp++;
- } else if (*cp=='Q') {
- mimeout_mode = 'Q';
- mimeout_f = FIXED_MIME; cp++;
- } else {
- mimeout_f = TRUE;
- }
- continue;
- case 'B': /* Broken JIS support */
- /* bit:0 no ESC JIS
- bit:1 allow any x on ESC-(-x or ESC-$-x
- bit:2 reset to ascii on NL
- */
- if ('9'>= *cp && *cp>='0')
- broken_f |= 1<<(*cp++ -'0');
- else
- broken_f |= TRUE;
- continue;
-#ifndef PERL_XS
- case 'O':/* for Output file */
- file_out_f = TRUE;
- continue;
-#endif
- case 'c':/* add cr code */
- crmode_f = CRLF;
- continue;
- case 'd':/* delete cr code */
- crmode_f = NL;
- continue;
- case 'I': /* ISO-2022-JP output */
- iso2022jp_f = TRUE;
- continue;
- case 'L': /* line mode */
- if (*cp=='u') { /* unix */
- crmode_f = NL; cp++;
- } else if (*cp=='m') { /* mac */
- crmode_f = CR; cp++;
- } else if (*cp=='w') { /* windows */
- crmode_f = CRLF; cp++;
- } else if (*cp=='0') { /* no conversion */
- crmode_f = 0; cp++;
- }
- continue;
- case 'g':
-#ifndef PERL_XS
- guess_f = TRUE;
-#endif
- continue;
- case ' ':
- /* module muliple options in a string are allowed for Perl moudle */
- while(*cp && *cp++!='-');
- continue;
- default:
- /* bogus option but ignored */
- continue;
- }
- }
-}
-
-#ifdef ANSI_C_PROTOTYPE
-struct input_code * find_inputcode_byfunc(nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
-#else
-struct input_code * find_inputcode_byfunc(iconv_func)
- nkf_char (*iconv_func)();
-#endif
-{
- if (iconv_func){
- struct input_code *p = input_code_list;
- while (p->name){
- if (iconv_func == p->iconv_func){
- return p;
- }
- p++;
- }
- }
- return 0;
-}
-
-void set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
-{
-#ifdef INPUT_CODE_FIX
- if (f || !input_f)
-#endif
- if (estab_f != f){
- estab_f = f;
- }
-
- if (iconv_func
-#ifdef INPUT_CODE_FIX
- && (f == -TRUE || !input_f) /* -TRUE means "FORCE" */
-#endif
- ){
- iconv = iconv_func;
- }
-#ifdef CHECK_OPTION
- if (estab_f && iconv_for_check != iconv){
- struct input_code *p = find_inputcode_byfunc(iconv);
- if (p){
- set_input_codename(p->name);
- debug(input_codename);
- }
- iconv_for_check = iconv;
- }
-#endif
-}
-
-#define SCORE_L2 (1) /* $BBh(B2$B?e=`4A;z(B */
-#define SCORE_KANA (SCORE_L2 << 1) /* $B$$$o$f$kH>3Q%+%J(B */
-#define SCORE_DEPEND (SCORE_KANA << 1) /* $B5!<o0MB8J8;z(B */
-#ifdef SHIFTJIS_CP932
-#define SCORE_CP932 (SCORE_DEPEND << 1) /* CP932 $B$K$h$kFI$_49$((B */
-#define SCORE_NO_EXIST (SCORE_CP932 << 1) /* $BB8:_$7$J$$J8;z(B */
-#else
-#define SCORE_NO_EXIST (SCORE_DEPEND << 1) /* $BB8:_$7$J$$J8;z(B */
-#endif
-#define SCORE_iMIME (SCORE_NO_EXIST << 1) /* MIME $B$K$h$k;XDj(B */
-#define SCORE_ERROR (SCORE_iMIME << 1) /* $B%(%i!<(B */
-
-#define SCORE_INIT (SCORE_iMIME)
-
-const nkf_char score_table_A0[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
- SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_NO_EXIST,
-};
-
-const nkf_char score_table_F0[] = {
- SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2,
- SCORE_L2, SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST,
- SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
- SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST, SCORE_ERROR,
-};
-
-void set_code_score(struct input_code *ptr, nkf_char score)
-{
- if (ptr){
- ptr->score |= score;
- }
-}
-
-void clr_code_score(struct input_code *ptr, nkf_char score)
-{
- if (ptr){
- ptr->score &= ~score;
- }
-}
-
-void code_score(struct input_code *ptr)
-{
- nkf_char c2 = ptr->buf[0];
-#ifdef UTF8_OUTPUT_ENABLE
- nkf_char c1 = ptr->buf[1];
-#endif
- if (c2 < 0){
- set_code_score(ptr, SCORE_ERROR);
- }else if (c2 == SSO){
- set_code_score(ptr, SCORE_KANA);
-#ifdef UTF8_OUTPUT_ENABLE
- }else if (!e2w_conv(c2, c1)){
- set_code_score(ptr, SCORE_NO_EXIST);
-#endif
- }else if ((c2 & 0x70) == 0x20){
- set_code_score(ptr, score_table_A0[c2 & 0x0f]);
- }else if ((c2 & 0x70) == 0x70){
- set_code_score(ptr, score_table_F0[c2 & 0x0f]);
- }else if ((c2 & 0x70) >= 0x50){
- set_code_score(ptr, SCORE_L2);
- }
-}
-
-void status_disable(struct input_code *ptr)
-{
- ptr->stat = -1;
- ptr->buf[0] = -1;
- code_score(ptr);
- if (iconv == ptr->iconv_func) set_iconv(FALSE, 0);
-}
-
-void status_push_ch(struct input_code *ptr, nkf_char c)
-{
- ptr->buf[ptr->index++] = c;
-}
-
-void status_clear(struct input_code *ptr)
-{
- ptr->stat = 0;
- ptr->index = 0;
-}
-
-void status_reset(struct input_code *ptr)
-{
- status_clear(ptr);
- ptr->score = SCORE_INIT;
-}
-
-void status_reinit(struct input_code *ptr)
-{
- status_reset(ptr);
- ptr->_file_stat = 0;
-}
-
-void status_check(struct input_code *ptr, nkf_char c)
-{
- if (c <= DEL && estab_f){
- status_reset(ptr);
- }
-}
-
-void s_status(struct input_code *ptr, nkf_char c)
-{
- switch(ptr->stat){
- case -1:
- status_check(ptr, c);
- break;
- case 0:
- if (c <= DEL){
- break;
-#ifdef NUMCHAR_OPTION
- }else if (is_unicode_capsule(c)){
- break;
-#endif
- }else if (0xa1 <= c && c <= 0xdf){
- status_push_ch(ptr, SSO);
- status_push_ch(ptr, c);
- code_score(ptr);
- status_clear(ptr);
- }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xef)){
- ptr->stat = 1;
- status_push_ch(ptr, c);
-#ifdef SHIFTJIS_CP932
- }else if (cp51932_f
- && is_ibmext_in_sjis(c)){
- ptr->stat = 2;
- status_push_ch(ptr, c);
-#endif /* SHIFTJIS_CP932 */
-#ifdef X0212_ENABLE
- }else if (x0212_f && 0xf0 <= c && c <= 0xfc){
- ptr->stat = 1;
- status_push_ch(ptr, c);
-#endif /* X0212_ENABLE */
- }else{
- status_disable(ptr);
- }
- break;
- case 1:
- if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
- status_push_ch(ptr, c);
- s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
- code_score(ptr);
- status_clear(ptr);
- }else{
- status_disable(ptr);
- }
- break;
- case 2:
-#ifdef SHIFTJIS_CP932
- if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
- status_push_ch(ptr, c);
- if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0){
- set_code_score(ptr, SCORE_CP932);
- status_clear(ptr);
- break;
- }
- }
-#endif /* SHIFTJIS_CP932 */
-#ifndef X0212_ENABLE
- status_disable(ptr);
-#endif
- break;
- }
-}
-
-void e_status(struct input_code *ptr, nkf_char c)
-{
- switch (ptr->stat){
- case -1:
- status_check(ptr, c);
- break;
- case 0:
- if (c <= DEL){
- break;
-#ifdef NUMCHAR_OPTION
- }else if (is_unicode_capsule(c)){
- break;
-#endif
- }else if (SSO == c || (0xa1 <= c && c <= 0xfe)){
- ptr->stat = 1;
- status_push_ch(ptr, c);
-#ifdef X0212_ENABLE
- }else if (0x8f == c){
- ptr->stat = 2;
- status_push_ch(ptr, c);
-#endif /* X0212_ENABLE */
- }else{
- status_disable(ptr);
- }
- break;
- case 1:
- if (0xa1 <= c && c <= 0xfe){
- status_push_ch(ptr, c);
- code_score(ptr);
- status_clear(ptr);
- }else{
- status_disable(ptr);
- }
- break;
-#ifdef X0212_ENABLE
- case 2:
- if (0xa1 <= c && c <= 0xfe){
- ptr->stat = 1;
- status_push_ch(ptr, c);
- }else{
- status_disable(ptr);
- }
-#endif /* X0212_ENABLE */
- }
-}
-
-#ifdef UTF8_INPUT_ENABLE
-void w16_status(struct input_code *ptr, nkf_char c)
-{
- switch (ptr->stat){
- case -1:
- break;
- case 0:
- if (ptr->_file_stat == 0){
- if (c == 0xfe || c == 0xff){
- ptr->stat = c;
- status_push_ch(ptr, c);
- ptr->_file_stat = 1;
- }else{
- status_disable(ptr);
- ptr->_file_stat = -1;
- }
- }else if (ptr->_file_stat > 0){
- ptr->stat = 1;
- status_push_ch(ptr, c);
- }else if (ptr->_file_stat < 0){
- status_disable(ptr);
- }
- break;
-
- case 1:
- if (c == EOF){
- status_disable(ptr);
- ptr->_file_stat = -1;
- }else{
- status_push_ch(ptr, c);
- status_clear(ptr);
- }
- break;
-
- case 0xfe:
- case 0xff:
- if (ptr->stat != c && (c == 0xfe || c == 0xff)){
- status_push_ch(ptr, c);
- status_clear(ptr);
- }else{
- status_disable(ptr);
- ptr->_file_stat = -1;
- }
- break;
- }
-}
-
-void w_status(struct input_code *ptr, nkf_char c)
-{
- switch (ptr->stat){
- case -1:
- status_check(ptr, c);
- break;
- case 0:
- if (c <= DEL){
- break;
-#ifdef NUMCHAR_OPTION
- }else if (is_unicode_capsule(c)){
- break;
-#endif
- }else if (0xc0 <= c && c <= 0xdf){
- ptr->stat = 1;
- status_push_ch(ptr, c);
- }else if (0xe0 <= c && c <= 0xef){
- ptr->stat = 2;
- status_push_ch(ptr, c);
- }else{
- status_disable(ptr);
- }
- break;
- case 1:
- case 2:
- if (0x80 <= c && c <= 0xbf){
- status_push_ch(ptr, c);
- if (ptr->index > ptr->stat){
- int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
- && ptr->buf[2] == 0xbf);
- w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
- &ptr->buf[0], &ptr->buf[1]);
- if (!bom){
- code_score(ptr);
- }
- status_clear(ptr);
- }
- }else{
- status_disable(ptr);
- }
- break;
- }
-}
-#endif
-
-void code_status(nkf_char c)
-{
- int action_flag = 1;
- struct input_code *result = 0;
- struct input_code *p = input_code_list;
- while (p->name){
- (p->status_func)(p, c);
- if (p->stat > 0){
- action_flag = 0;
- }else if(p->stat == 0){
- if (result){
- action_flag = 0;
- }else{
- result = p;
- }
- }
- ++p;
- }
-
- if (action_flag){
- if (result && !estab_f){
- set_iconv(TRUE, result->iconv_func);
- }else if (c <= DEL){
- struct input_code *ptr = input_code_list;
- while (ptr->name){
- status_reset(ptr);
- ++ptr;
- }
- }
- }
-}
-
-#ifndef WIN32DLL
-nkf_char std_getc(FILE *f)
-{
- if (std_gc_ndx){
- return std_gc_buf[--std_gc_ndx];
- }
- return getc(f);
-}
-#endif /*WIN32DLL*/
-
-nkf_char std_ungetc(nkf_char c, FILE *f)
-{
- if (std_gc_ndx == STD_GC_BUFSIZE){
- return EOF;
- }
- std_gc_buf[std_gc_ndx++] = c;
- return c;
-}
-
-#ifndef WIN32DLL
-void std_putc(nkf_char c)
-{
- if(c!=EOF)
- putchar(c);
-}
-#endif /*WIN32DLL*/
-
-#if !defined(PERL_XS) && !defined(WIN32DLL)
-nkf_char noconvert(FILE *f)
-{
- nkf_char c;
-
- if (nop_f == 2)
- module_connection();
- while ((c = (*i_getc)(f)) != EOF)
- (*o_putc)(c);
- (*o_putc)(EOF);
- return 1;
-}
-#endif
-
-void module_connection(void)
-{
- oconv = output_conv;
- o_putc = std_putc;
-
- /* replace continucation module, from output side */
-
- /* output redicrection */
-#ifdef CHECK_OPTION
- if (noout_f || guess_f){
- o_putc = no_putc;
- }
-#endif
- if (mimeout_f) {
- o_mputc = o_putc;
- o_putc = mime_putc;
- if (mimeout_f == TRUE) {
- o_base64conv = oconv; oconv = base64_conv;
- }
- /* base64_count = 0; */
- }
-
- if (crmode_f) {
- o_crconv = oconv; oconv = cr_conv;
- }
- if (rot_f) {
- o_rot_conv = oconv; oconv = rot_conv;
- }
- if (iso2022jp_f) {
- o_iso2022jp_check_conv = oconv; oconv = iso2022jp_check_conv;
- }
- if (hira_f) {
- o_hira_conv = oconv; oconv = hira_conv;
- }
- if (fold_f) {
- o_fconv = oconv; oconv = fold_conv;
- f_line = 0;
- }
- if (alpha_f || x0201_f) {
- o_zconv = oconv; oconv = z_conv;
- }
-
- i_getc = std_getc;
- i_ungetc = std_ungetc;
- /* input redicrection */
-#ifdef INPUT_OPTION
- if (cap_f){
- i_cgetc = i_getc; i_getc = cap_getc;
- i_cungetc = i_ungetc; i_ungetc= cap_ungetc;
- }
- if (url_f){
- i_ugetc = i_getc; i_getc = url_getc;
- i_uungetc = i_ungetc; i_ungetc= url_ungetc;
- }
-#endif
-#ifdef NUMCHAR_OPTION
- if (numchar_f){
- i_ngetc = i_getc; i_getc = numchar_getc;
- i_nungetc = i_ungetc; i_ungetc= numchar_ungetc;
- }
-#endif
-#ifdef UNICODE_NORMALIZATION
- if (nfc_f && input_f == UTF8_INPUT){
- i_nfc_getc = i_getc; i_getc = nfc_getc;
- i_nfc_ungetc = i_ungetc; i_ungetc= nfc_ungetc;
- }
-#endif
- if (mime_f && mimebuf_f==FIXED_MIME) {
- i_mgetc = i_getc; i_getc = mime_getc;
- i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
- }
- if (broken_f & 1) {
- i_bgetc = i_getc; i_getc = broken_getc;
- i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
- }
- if (input_f == JIS_INPUT || input_f == LATIN1_INPUT) {
- set_iconv(-TRUE, e_iconv);
- } else if (input_f == SJIS_INPUT) {
- set_iconv(-TRUE, s_iconv);
-#ifdef UTF8_INPUT_ENABLE
- } else if (input_f == UTF8_INPUT) {
- set_iconv(-TRUE, w_iconv);
- } else if (input_f == UTF16BE_INPUT) {
- set_iconv(-TRUE, w_iconv16);
- } else if (input_f == UTF16LE_INPUT) {
- set_iconv(-TRUE, w_iconv16);
-#endif
- } else {
- set_iconv(FALSE, e_iconv);
- }
-
- {
- struct input_code *p = input_code_list;
- while (p->name){
- status_reinit(p++);
- }
- }
-}
-
-/*
- Conversion main loop. Code detection only.
- */
-
-nkf_char kanji_convert(FILE *f)
-{
- nkf_char c1,
- c2, c3;
- int is_8bit = FALSE;
-
- module_connection();
- c2 = 0;
-
- if(input_f == SJIS_INPUT
-#ifdef UTF8_INPUT_ENABLE
- || input_f == UTF8_INPUT || input_f == UTF16BE_INPUT || input_f == UTF16LE_INPUT
-#endif
- ){
- is_8bit = TRUE;
- }
-
-
- input_mode = ASCII;
- output_mode = ASCII;
- shift_mode = FALSE;
-
-#define NEXT continue /* no output, get next */
-#define SEND ; /* output c1 and c2, get next */
-#define LAST break /* end of loop, go closing */
-
- while ((c1 = (*i_getc)(f)) != EOF) {
-#ifdef INPUT_CODE_FIX
- if (!input_f)
-#endif
- code_status(c1);
- if (c2) {
- /* second byte */
- if (c2 > DEL) {
- /* in case of 8th bit is on */
- if (!estab_f&&!mime_decode_mode) {
- /* in case of not established yet */
- /* It is still ambiguious */
- if (h_conv(f, c2, c1)==EOF)
- LAST;
- else
- c2 = 0;
- NEXT;
- } else
- /* in case of already established */
- if (c1 < AT) {
- /* ignore bogus code */
- c2 = 0;
- NEXT;
- } else
- SEND;
- } else
- /* second byte, 7 bit code */
- /* it might be kanji shitfted */
- if ((c1 == DEL) || (c1 <= SPACE)) {
- /* ignore bogus first code */
- c2 = 0;
- NEXT;
- } else
- SEND;
- } else {
- /* first byte */
- if (
-#ifdef UTF8_INPUT_ENABLE
- iconv == w_iconv16
-#else
- 0
-#endif
- ) {
- c2 = c1;
- c1 = (*i_getc)(f);
- SEND;
-#ifdef NUMCHAR_OPTION
- } else if (is_unicode_capsule(c1)){
- SEND;
-#endif
- } else if (c1 > DEL) {
- /* 8 bit code */
- if (!estab_f && !iso8859_f) {
- /* not established yet */
- if (!is_8bit) is_8bit = TRUE;
- c2 = c1;
- NEXT;
- } else { /* estab_f==TRUE */
- if (iso8859_f) {
- c2 = ISO8859_1;
- c1 &= 0x7f;
- SEND;
- } else if (SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
- /* SJIS X0201 Case... */
- if(iso2022jp_f && x0201_f==NO_X0201) {
- (*oconv)(GETA1, GETA2);
- NEXT;
- } else {
- c2 = X0201;
- c1 &= 0x7f;
- SEND;
- }
- } else if (c1==SSO && iconv != s_iconv) {
- /* EUC X0201 Case */
- c1 = (*i_getc)(f); /* skip SSO */
- code_status(c1);
- if (SSP<=c1 && c1<0xe0) {
- if(iso2022jp_f && x0201_f==NO_X0201) {
- (*oconv)(GETA1, GETA2);
- NEXT;
- } else {
- c2 = X0201;
- c1 &= 0x7f;
- SEND;
- }
- } else { /* bogus code, skip SSO and one byte */
- NEXT;
- }
- } else {
- /* already established */
- c2 = c1;
- NEXT;
- }
- }
- } else if ((c1 > SPACE) && (c1 != DEL)) {
- /* in case of Roman characters */
- if (shift_mode) {
- /* output 1 shifted byte */
- if (iso8859_f) {
- c2 = ISO8859_1;
- SEND;
- } else if (SPACE<=c1 && c1<(0xe0&0x7f) ){
- /* output 1 shifted byte */
- if(iso2022jp_f && x0201_f==NO_X0201) {
- (*oconv)(GETA1, GETA2);
- NEXT;
- } else {
- c2 = X0201;
- SEND;
- }
- } else {
- /* look like bogus code */
- NEXT;
- }
- } else if (input_mode == X0208 || input_mode == X0212 ||
- input_mode == X0213_1 || input_mode == X0213_2) {
- /* in case of Kanji shifted */
- c2 = c1;
- NEXT;
- } else if (c1 == '=' && mime_f && !mime_decode_mode ) {
- /* Check MIME code */
- if ((c1 = (*i_getc)(f)) == EOF) {
- (*oconv)(0, '=');
- LAST;
- } else if (c1 == '?') {
- /* =? is mime conversion start sequence */
- if(mime_f == STRICT_MIME) {
- /* check in real detail */
- if (mime_begin_strict(f) == EOF)
- LAST;
- else
- NEXT;
- } else if (mime_begin(f) == EOF)
- LAST;
- else
- NEXT;
- } else {
- (*oconv)(0, '=');
- (*i_ungetc)(c1,f);
- NEXT;
- }
- } else {
- /* normal ASCII code */
- SEND;
- }
- } else if (!is_8bit && c1 == SI) {
- shift_mode = FALSE;
- NEXT;
- } else if (!is_8bit && c1 == SO) {
- shift_mode = TRUE;
- NEXT;
- } else if (!is_8bit && c1 == ESC ) {
- if ((c1 = (*i_getc)(f)) == EOF) {
- /* (*oconv)(0, ESC); don't send bogus code */
- LAST;
- } else if (c1 == '$') {
- if ((c1 = (*i_getc)(f)) == EOF) {
- /*
- (*oconv)(0, ESC); don't send bogus code
- (*oconv)(0, '$'); */
- LAST;
- } else if (c1 == '@'|| c1 == 'B') {
- /* This is kanji introduction */
- input_mode = X0208;
- shift_mode = FALSE;
- set_input_codename("ISO-2022-JP");
-#ifdef CHECK_OPTION
- debug(input_codename);
-#endif
- NEXT;
- } else if (c1 == '(') {
- if ((c1 = (*i_getc)(f)) == EOF) {
- /* don't send bogus code
- (*oconv)(0, ESC);
- (*oconv)(0, '$');
- (*oconv)(0, '(');
- */
- LAST;
- } else if (c1 == '@'|| c1 == 'B') {
- /* This is kanji introduction */
- input_mode = X0208;
- shift_mode = FALSE;
- NEXT;
-#ifdef X0212_ENABLE
- } else if (c1 == 'D'){
- input_mode = X0212;
- shift_mode = FALSE;
- NEXT;
-#endif /* X0212_ENABLE */
- } else if (c1 == (X0213_1&0x7F)){
- input_mode = X0213_1;
- shift_mode = FALSE;
- NEXT;
- } else if (c1 == (X0213_2&0x7F)){
- input_mode = X0213_2;
- shift_mode = FALSE;
- NEXT;
- } else {
- /* could be some special code */
- (*oconv)(0, ESC);
- (*oconv)(0, '$');
- (*oconv)(0, '(');
- (*oconv)(0, c1);
- NEXT;
- }
- } else if (broken_f&0x2) {
- /* accept any ESC-(-x as broken code ... */
- input_mode = X0208;
- shift_mode = FALSE;
- NEXT;
- } else {
- (*oconv)(0, ESC);
- (*oconv)(0, '$');
- (*oconv)(0, c1);
- NEXT;
- }
- } else if (c1 == '(') {
- if ((c1 = (*i_getc)(f)) == EOF) {
- /* don't send bogus code
- (*oconv)(0, ESC);
- (*oconv)(0, '('); */
- LAST;
- } else {
- if (c1 == 'I') {
- /* This is X0201 kana introduction */
- input_mode = X0201; shift_mode = X0201;
- NEXT;
- } else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
- /* This is X0208 kanji introduction */
- input_mode = ASCII; shift_mode = FALSE;
- NEXT;
- } else if (broken_f&0x2) {
- input_mode = ASCII; shift_mode = FALSE;
- NEXT;
- } else {
- (*oconv)(0, ESC);
- (*oconv)(0, '(');
- /* maintain various input_mode here */
- SEND;
- }
- }
- } else if ( c1 == 'N' || c1 == 'n' ){
- /* SS2 */
- c3 = (*i_getc)(f); /* skip SS2 */
- if ( (SPACE<=c3 && c3 < 0x60) || (0xa0<=c3 && c3 < 0xe0)){
- c1 = c3;
- c2 = X0201;
- SEND;
- }else{
- (*i_ungetc)(c3, f);
- /* lonely ESC */
- (*oconv)(0, ESC);
- SEND;
- }
- } else {
- /* lonely ESC */
- (*oconv)(0, ESC);
- SEND;
- }
- } else if ((c1 == NL || c1 == CR) && broken_f&4) {
- input_mode = ASCII; set_iconv(FALSE, 0);
- SEND;
- } else if (c1 == NL && mime_decode_f && !mime_decode_mode ) {
- if ((c1=(*i_getc)(f))!=EOF && c1 == SPACE) {
- i_ungetc(SPACE,f);
- continue;
- } else {
- i_ungetc(c1,f);
- }
- c1 = NL;
- SEND;
- } else if (c1 == CR && mime_decode_f && !mime_decode_mode ) {
- if ((c1=(*i_getc)(f))!=EOF) {
- if (c1==SPACE) {
- i_ungetc(SPACE,f);
- continue;
- } else if (c1 == NL && (c1=(*i_getc)(f))!=EOF && c1 == SPACE) {
- i_ungetc(SPACE,f);
- continue;
- } else {
- i_ungetc(c1,f);
- }
- i_ungetc(NL,f);
- } else {
- i_ungetc(c1,f);
- }
- c1 = CR;
- SEND;
- } else
- SEND;
- }
- /* send: */
- switch(input_mode){
- case ASCII:
- if ((*iconv)(c2, c1, 0) < 0){ /* can be EUC/SJIS */
- nkf_char c0 = (*i_getc)(f);
- if (c0 != EOF){
- code_status(c0);
- (*iconv)(c2, c1, c0);
- }
- }
- break;
- case X0208:
- case X0213_1:
- (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
- break;
-#ifdef X0212_ENABLE
- case X0212:
- (*oconv)(PREFIX_EUCG3 | c2, c1);
- break;
-#endif /* X0212_ENABLE */
- case X0213_2:
- (*oconv)(PREFIX_EUCG3 | c2, c1);
- break;
- default:
- (*oconv)(input_mode, c1); /* other special case */
- }
-
- c2 = 0;
- continue;
- /* goto next_word */
- }
-
- /* epilogue */
- (*iconv)(EOF, 0, 0);
- if (!is_inputcode_set)
- {
- if (is_8bit) {
- struct input_code *p = input_code_list;
- struct input_code *result = p;
- while (p->name){
- if (p->score < result->score) result = p;
- ++p;
- }
- set_input_codename(result->name);
- }
- }
- return 1;
-}
-
-nkf_char
-h_conv(FILE *f, nkf_char c2, nkf_char c1)
-{
- nkf_char wc,c3;
-
-
- /** it must NOT be in the kanji shifte sequence */
- /** it must NOT be written in JIS7 */
- /** and it must be after 2 byte 8bit code */
-
- hold_count = 0;
- push_hold_buf(c2);
- push_hold_buf(c1);
-
- while ((c1 = (*i_getc)(f)) != EOF) {
- if (c1 == ESC){
- (*i_ungetc)(c1,f);
- break;
- }
- code_status(c1);
- if (push_hold_buf(c1) == EOF || estab_f){
- break;
- }
- }
-
- if (!estab_f){
- struct input_code *p = input_code_list;
- struct input_code *result = p;
- if (c1 == EOF){
- code_status(c1);
- }
- while (p->name){
- if (p->score < result->score){
- result = p;
- }
- ++p;
- }
- set_iconv(FALSE, result->iconv_func);
- }
-
-
- /** now,
- ** 1) EOF is detected, or
- ** 2) Code is established, or
- ** 3) Buffer is FULL (but last word is pushed)
- **
- ** in 1) and 3) cases, we continue to use
- ** Kanji codes by oconv and leave estab_f unchanged.
- **/
-
- c3=c1;
- wc = 0;
- while (wc < hold_count){
- c2 = hold_buf[wc++];
- if (c2 <= DEL
-#ifdef NUMCHAR_OPTION
- || is_unicode_capsule(c2)
-#endif
- ){
- (*iconv)(0, c2, 0);
- continue;
- }else if (iconv == s_iconv && 0xa1 <= c2 && c2 <= 0xdf){
- (*iconv)(X0201, c2, 0);
- continue;
- }
- if (wc < hold_count){
- c1 = hold_buf[wc++];
- }else{
- c1 = (*i_getc)(f);
- if (c1 == EOF){
- c3 = EOF;
- break;
- }
- code_status(c1);
- }
- if ((*iconv)(c2, c1, 0) < 0){
- nkf_char c0;
- if (wc < hold_count){
- c0 = hold_buf[wc++];
- }else{
- c0 = (*i_getc)(f);
- if (c0 == EOF){
- c3 = EOF;
- break;
- }
- code_status(c0);
- }
- (*iconv)(c2, c1, c0);
- }
- }
- return c3;
-}
-
-
-
-nkf_char
-push_hold_buf(nkf_char c2)
-{
- if (hold_count >= HOLD_SIZE*2)
- return (EOF);
- hold_buf[hold_count++] = (unsigned char)c2;
- return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
-}
-
-nkf_char s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
-{
-#if defined(SHIFTJIS_CP932) || defined(X0212_ENABLE)
- nkf_char val;
-#endif
- static const nkf_char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} };
-#ifdef SHIFTJIS_CP932
- if (cp51932_f && is_ibmext_in_sjis(c2)){
-#if 0
- extern const unsigned short shiftjis_cp932[3][189];
-#endif
- val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
- if (val){
- c2 = val >> 8;
- c1 = val & 0xff;
- }
- }
-#endif /* SHIFTJIS_CP932 */
-#ifdef X0212_ENABLE
- if (!x0213_f && is_ibmext_in_sjis(c2)){
-#if 0
- extern const unsigned short shiftjis_x0212[3][189];
-#endif
- val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40];
- if (val){
- if (val > 0x7FFF){
- c2 = PREFIX_EUCG3 | (val >> 8);
- c1 = val & 0xff;
- }else{
- c2 = val >> 8;
- c1 = val & 0xff;
- }
- if (p2) *p2 = c2;
- if (p1) *p1 = c1;
- return 0;
- }
- }
-#endif
- if(c2 >= 0x80){
- if(x0213_f && c2 >= 0xF0){
- if(c2 <= 0xF3 || (c2 == 0xF4 && c1 < 0x9F)){ /* k=1, 3<=k<=5, k=8, 12<=k<=15 */
- c2 = PREFIX_EUCG3 | 0x20 | shift_jisx0213_s1a3_table[c2 - 0xF0][0x9E < c1];
- }else{ /* 78<=k<=94 */
- c2 = PREFIX_EUCG3 | (c2 * 2 - 0x17B);
- if (0x9E < c1) c2++;
- }
- }else{
- c2 = c2 + c2 - ((c2 <= 0x9F) ? SJ0162 : SJ6394);
- if (0x9E < c1) c2++;
- }
- if (c1 < 0x9F)
- c1 = c1 - ((c1 > DEL) ? SPACE : 0x1F);
- else {
- c1 = c1 - 0x7E;
- }
- }
-
-#ifdef X0212_ENABLE
- c2 = x0212_unshift(c2);
-#endif
- if (p2) *p2 = c2;
- if (p1) *p1 = c1;
- return 0;
-}
-
-nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
-{
- if (c2 == X0201) {
- c1 &= 0x7f;
- } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
- /* NOP */
- } else {
- nkf_char ret = s2e_conv(c2, c1, &c2, &c1);
- if (ret) return ret;
- }
- (*oconv)(c2, c1);
- return 0;
-}
-
-nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
-{
- if (c2 == X0201) {
- c1 &= 0x7f;
-#ifdef X0212_ENABLE
- }else if (c2 == 0x8f){
- if (c0 == 0){
- return -1;
- }
- c2 = (c2 << 8) | (c1 & 0x7f);
- c1 = c0 & 0x7f;
-#ifdef SHIFTJIS_CP932
- if (cp51932_f){
- nkf_char s2, s1;
- if (e2s_conv(c2, c1, &s2, &s1) == 0){
- s2e_conv(s2, s1, &c2, &c1);
- if (c2 < 0x100){
- c1 &= 0x7f;
- c2 &= 0x7f;
- }
- }
- }
-#endif /* SHIFTJIS_CP932 */
-#endif /* X0212_ENABLE */
- } else if (c2 == SSO){
- c2 = X0201;
- c1 &= 0x7f;
- } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
- /* NOP */
- } else {
- c1 &= 0x7f;
- c2 &= 0x7f;
- }
- (*oconv)(c2, c1);
- return 0;
-}
-
-#ifdef UTF8_INPUT_ENABLE
-nkf_char w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
-{
- nkf_char ret = 0;
-
- if (!c1){
- *p2 = 0;
- *p1 = c2;
- }else if (0xc0 <= c2 && c2 <= 0xef) {
- ret = unicode_to_jis_common(c2, c1, c0, p2, p1);
-#ifdef NUMCHAR_OPTION
- if (ret > 0){
- if (p2) *p2 = 0;
- if (p1) *p1 = CLASS_UTF16 | ww16_conv(c2, c1, c0);
- ret = 0;
- }
-#endif
- }
- return ret;
-}
-
-nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
-{
- nkf_char ret = 0;
-
- /* throw away ZERO WIDTH NO-BREAK SPACE (U+FEFF) */
- if(ignore_zwnbsp_f){
- ignore_zwnbsp_f = FALSE;
- if(c2 == 0xef && c1 == 0xbb && c0 == 0xbf)
- return 0;
- }
-
- if (c2 == 0) /* 0x00-0x7f */
- c1 &= 0x7F; /* 1byte */
- else if (c0 == 0){
- if ((c2 & 0xe0) == 0xc0){ /* 0xc0-0xdf */
- /* 2ytes */
- if((c2 & 0xFE) == 0xC0 || c1 < 0x80 || 0xBF < c1) return 0;
- }else if ((c2 & 0xf0) == 0xe0) /* 0xe0-0xef */
- return -1; /* 3bytes */
-#ifdef __COMMENT__
- else if (0xf0 <= c2)
- return 0; /* 4,5,6bytes */
- else if ((c2 & 0xc0) == 0x80) /* 0x80-0xbf */
- return 0; /* trail byte */
-#endif
- else return 0;
- }else{
- /* must be 3bytes */
- if(c2 == 0xE0){
- if(c1 < 0xA0 || 0xBF < c1 || c0 < 0x80 || 0xBF < c0)
- return 0;
- }else if(c2 == 0xED){
- if(c1 < 0x80 || 0x9F < c1 || c0 < 0x80 || 0xBF < c0)
- return 0;
- }else if((c2 & 0xf0) == 0xe0){
- if(c1 < 0x80 || 0xBF < c1 || c0 < 0x80 || 0xBF < c0)
- return 0;
- }else return 0;
- }
- if (c2 == 0 || c2 == EOF){
- } else {
- ret = w2e_conv(c2, c1, c0, &c2, &c1);
- }
- if (ret == 0){
- (*oconv)(c2, c1);
- }
- return ret;
-}
-#endif
-
-#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
-void w16w_conv(nkf_char val, nkf_char *p2, nkf_char *p1, nkf_char *p0)
-{
- val &= VALUE_MASK;
- if (val < 0x80){
- *p2 = val;
- *p1 = 0;
- *p0 = 0;
- }else if (val < 0x800){
- *p2 = 0xc0 | (val >> 6);
- *p1 = 0x80 | (val & 0x3f);
- *p0 = 0;
- } else if (val <= NKF_INT32_C(0xFFFF)) {
- *p2 = 0xe0 | (val >> 12);
- *p1 = 0x80 | ((val >> 6) & 0x3f);
- *p0 = 0x80 | (val & 0x3f);
- } else {
- *p2 = 0;
- *p1 = 0;
- *p0 = 0;
- }
-}
-#endif
-
-#ifdef UTF8_INPUT_ENABLE
-nkf_char ww16_conv(nkf_char c2, nkf_char c1, nkf_char c0)
-{
- nkf_char val;
- if (c2 >= 0xf0){
- val = -1;
- }else if (c2 >= 0xe0){
- val = (c2 & 0x0f) << 12;
- val |= (c1 & 0x3f) << 6;
- val |= (c0 & 0x3f);
- }else if (c2 >= 0xc0){
- val = (c2 & 0x1f) << 6;
- val |= (c1 & 0x3f);
- }else{
- val = c2;
- }
- return val;
-}
-
-nkf_char w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1)
-{
- nkf_char c2, c1, c0;
- nkf_char ret = 0;
- val &= VALUE_MASK;
- if (val < 0x80){
- *p2 = 0;
- *p1 = val;
- }else{
- w16w_conv(val, &c2, &c1, &c0);
- ret = unicode_to_jis_common(c2, c1, c0, p2, p1);
-#ifdef NUMCHAR_OPTION
- if (ret > 0){
- *p2 = 0;
- *p1 = CLASS_UTF16 | val;
- ret = 0;
- }
-#endif
- }
- return ret;
-}
-#endif
-
-#ifdef UTF8_INPUT_ENABLE
-nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0)
-{
- nkf_char ret;
-
- /* throw away ZERO WIDTH NO-BREAK SPACE (U+FEFF) */
- if(ignore_zwnbsp_f){
- ignore_zwnbsp_f = FALSE;
- if (c2==0376 && c1==0377){
- utf16_mode = UTF16BE_INPUT;
- return 0;
- }else if(c2==0377 && c1==0376){
- utf16_mode = UTF16LE_INPUT;
- return 0;
- }
- }
- if (c2 != EOF && utf16_mode == UTF16LE_INPUT) {
- nkf_char tmp;
- tmp=c1; c1=c2; c2=tmp;
- }
- if ((c2==0 && c1 < 0x80) || c2==EOF) {
- (*oconv)(c2, c1);
- return 0;
- }else if((c2>>3)==27){ /* surrogate pair */
- return 1;
- }else ret = w16e_conv(((c2 & 0xff)<<8) + c1, &c2, &c1);
- if (ret) return ret;
- (*oconv)(c2, c1);
- return 0;
-}
-
-nkf_char unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
-{
-#if 0
- extern const unsigned short *const utf8_to_euc_2bytes[];
- extern const unsigned short *const utf8_to_euc_2bytes_ms[];
- extern const unsigned short *const utf8_to_euc_2bytes_932[];
- extern const unsigned short *const *const utf8_to_euc_3bytes[];
- extern const unsigned short *const *const utf8_to_euc_3bytes_ms[];
- extern const unsigned short *const *const utf8_to_euc_3bytes_932[];
-#endif
- const unsigned short *const *pp;
- const unsigned short *const *const *ppp;
- static const int no_best_fit_chars_table_C2[] =
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 2, 1, 1, 2,
- 0, 0, 1, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1, 1, 1};
- static const int no_best_fit_chars_table_C2_ms[] =
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0,
- 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0};
- static const int no_best_fit_chars_table_932_C2[] =
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0};
- static const int no_best_fit_chars_table_932_C3[] =
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1};
- nkf_char ret = 0;
-
- if(c2 < 0x80){
- *p2 = 0;
- *p1 = c2;
- }else if(c2 < 0xe0){
- if(no_best_fit_chars_f){
- if(ms_ucs_map_f == UCS_MAP_CP932){
- switch(c2){
- case 0xC2:
- if(no_best_fit_chars_table_932_C2[c1&0x3F]) return 1;
- break;
- case 0xC3:
- if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
- break;
- }
- }else if(cp51932_f){
- switch(c2){
- case 0xC2:
- if(no_best_fit_chars_table_C2[c1&0x3F]) return 1;
- break;
- case 0xC3:
- if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
- break;
- }
- }else if(ms_ucs_map_f == UCS_MAP_MS){
- if(c2 == 0xC2 && no_best_fit_chars_table_C2_ms[c1&0x3F]) return 1;
- }
- }
- pp =
- ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_2bytes_932 :
- ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_2bytes_ms :
- utf8_to_euc_2bytes;
- ret = w_iconv_common(c2, c1, pp, sizeof_utf8_to_euc_2bytes, p2, p1);
- }else if(c0 < 0xF0){
- if(no_best_fit_chars_f){
- if(ms_ucs_map_f == UCS_MAP_CP932){
- if(c2 == 0xE3 && c1 == 0x82 && c0 == 0x94) return 1;
- }else if(ms_ucs_map_f == UCS_MAP_MS){
- switch(c2){
- case 0xE2:
- switch(c1){
- case 0x80:
- if(c0 == 0x94 || c0 == 0x96 || c0 == 0xBE) return 1;
- break;
- case 0x88:
- if(c0 == 0x92) return 1;
- break;
- }
- break;
- case 0xE3:
- if(c1 == 0x80 || c0 == 0x9C) return 1;
- break;
- }
- }else{
- switch(c2){
- case 0xE2:
- switch(c1){
- case 0x80:
- if(c0 == 0x95) return 1;
- break;
- case 0x88:
- if(c0 == 0xA5) return 1;
- break;
- }
- break;
- case 0xEF:
- switch(c1){
- case 0xBC:
- if(c0 == 0x8D) return 1;
- break;
- case 0xBD:
- if(c0 == 0x9E && cp51932_f) return 1;
- break;
- case 0xBF:
- if(0xA0 <= c0 && c0 <= 0xA5) return 1;
- break;
- }
- break;
- }
- }
- }
- ppp =
- ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_3bytes_932 :
- ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_3bytes_ms :
- utf8_to_euc_3bytes;
- ret = w_iconv_common(c1, c0, ppp[c2 - 0xE0], sizeof_utf8_to_euc_C2, p2, p1);
- }else return -1;
-#ifdef SHIFTJIS_CP932
- if (!ret && cp51932_f && is_eucg3(*p2)) {
- nkf_char s2, s1;
- if (e2s_conv(*p2, *p1, &s2, &s1) == 0) {
- s2e_conv(s2, s1, p2, p1);
- }else{
- ret = 1;
- }
- }
-#endif
- return ret;
-}
-
-nkf_char w_iconv_common(nkf_char c1, nkf_char c0, const unsigned short *const *pp, nkf_char psize, nkf_char *p2, nkf_char *p1)
-{
- nkf_char c2;
- const unsigned short *p;
- unsigned short val;
-
- if (pp == 0) return 1;
-
- c1 -= 0x80;
- if (c1 < 0 || psize <= c1) return 1;
- p = pp[c1];
- if (p == 0) return 1;
-
- c0 -= 0x80;
- if (c0 < 0 || sizeof_utf8_to_euc_C2 <= c0) return 1;
- val = p[c0];
- if (val == 0) return 1;
- if (no_cp932ext_f && (
- (val>>8) == 0x2D || /* NEC special characters */
- val > NKF_INT32_C(0xF300) /* IBM extended characters */
- )) return 1;
-
- c2 = val >> 8;
- if (val > 0x7FFF){
- c2 &= 0x7f;
- c2 |= PREFIX_EUCG3;
- }
- if (c2 == SO) c2 = X0201;
- c1 = val & 0x7f;
- if (p2) *p2 = c2;
- if (p1) *p1 = c1;
- return 0;
-}
-
-void nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c)
-{
- const char *hex = "0123456789ABCDEF";
- int shift = 20;
- c &= VALUE_MASK;
- while(shift >= 0){
- if(c >= 1<<shift){
- while(shift >= 0){
- (*f)(0, hex[(c>>shift)&0xF]);
- shift -= 4;
- }
- }else{
- shift -= 4;
- }
- }
- return;
-}
-
-void encode_fallback_html(nkf_char c)
-{
- (*oconv)(0, '&');
- (*oconv)(0, '#');
- c &= VALUE_MASK;
- if(c >= NKF_INT32_C(1000000))
- (*oconv)(0, 0x30+(c/NKF_INT32_C(1000000))%10);
- if(c >= NKF_INT32_C(100000))
- (*oconv)(0, 0x30+(c/NKF_INT32_C(100000) )%10);
- if(c >= 10000)
- (*oconv)(0, 0x30+(c/10000 )%10);
- if(c >= 1000)
- (*oconv)(0, 0x30+(c/1000 )%10);
- if(c >= 100)
- (*oconv)(0, 0x30+(c/100 )%10);
- if(c >= 10)
- (*oconv)(0, 0x30+(c/10 )%10);
- if(c >= 0)
- (*oconv)(0, 0x30+ c %10);
- (*oconv)(0, ';');
- return;
-}
-
-void encode_fallback_xml(nkf_char c)
-{
- (*oconv)(0, '&');
- (*oconv)(0, '#');
- (*oconv)(0, 'x');
- nkf_each_char_to_hex(oconv, c);
- (*oconv)(0, ';');
- return;
-}
-
-void encode_fallback_java(nkf_char c)
-{
- const char *hex = "0123456789ABCDEF";
- (*oconv)(0, '\\');
- c &= VALUE_MASK;
- if(!is_unicode_bmp(c)){
- (*oconv)(0, 'U');
- (*oconv)(0, '0');
- (*oconv)(0, '0');
- (*oconv)(0, hex[(c>>20)&0xF]);
- (*oconv)(0, hex[(c>>16)&0xF]);
- }else{
- (*oconv)(0, 'u');
- }
- (*oconv)(0, hex[(c>>12)&0xF]);
- (*oconv)(0, hex[(c>> 8)&0xF]);
- (*oconv)(0, hex[(c>> 4)&0xF]);
- (*oconv)(0, hex[ c &0xF]);
- return;
-}
-
-void encode_fallback_perl(nkf_char c)
-{
- (*oconv)(0, '\\');
- (*oconv)(0, 'x');
- (*oconv)(0, '{');
- nkf_each_char_to_hex(oconv, c);
- (*oconv)(0, '}');
- return;
-}
-
-void encode_fallback_subchar(nkf_char c)
-{
- c = unicode_subchar;
- (*oconv)((c>>8)&0xFF, c&0xFF);
- return;
-}
-#endif
-
-#ifdef UTF8_OUTPUT_ENABLE
-nkf_char e2w_conv(nkf_char c2, nkf_char c1)
-{
-#if 0
- extern const unsigned short euc_to_utf8_1byte[];
- extern const unsigned short *const euc_to_utf8_2bytes[];
- extern const unsigned short *const euc_to_utf8_2bytes_ms[];
- extern const unsigned short *const x0212_to_utf8_2bytes[];
-#endif
- const unsigned short *p;
-
- if (c2 == X0201) {
- p = euc_to_utf8_1byte;
-#ifdef X0212_ENABLE
- } else if (is_eucg3(c2)){
- if(ms_ucs_map_f == UCS_MAP_ASCII&& c2 == NKF_INT32_C(0x8F22) && c1 == 0x43){
- return 0xA6;
- }
- c2 = (c2&0x7f) - 0x21;
- if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
- p = x0212_to_utf8_2bytes[c2];
- else
- return 0;
-#endif
- } else {
- c2 &= 0x7f;
- c2 = (c2&0x7f) - 0x21;
- if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
- p = ms_ucs_map_f != UCS_MAP_ASCII ? euc_to_utf8_2bytes_ms[c2] : euc_to_utf8_2bytes[c2];
- else
- return 0;
- }
- if (!p) return 0;
- c1 = (c1 & 0x7f) - 0x21;
- if (0<=c1 && c1<sizeof_euc_to_utf8_1byte)
- return p[c1];
- return 0;
-}
-
-void w_oconv(nkf_char c2, nkf_char c1)
-{
- nkf_char c0;
- nkf_char val;
- if (c2 == EOF) {
- (*o_putc)(EOF);
- return;
- }
-
- if (unicode_bom_f==2) {
- (*o_putc)('\357');
- (*o_putc)('\273');
- (*o_putc)('\277');
- unicode_bom_f=1;
- }
-
-#ifdef NUMCHAR_OPTION
- if (c2 == 0 && is_unicode_capsule(c1)){
- val = c1 & VALUE_MASK;
- if (val < 0x80){
- (*o_putc)(val);
- }else if (val < 0x800){
- (*o_putc)(0xC0 | (val >> 6));
- (*o_putc)(0x80 | (val & 0x3f));
- } else if (val <= NKF_INT32_C(0xFFFF)) {
- (*o_putc)(0xE0 | (val >> 12));
- (*o_putc)(0x80 | ((val >> 6) & 0x3f));
- (*o_putc)(0x80 | (val & 0x3f));
- } else if (val <= NKF_INT32_C(0x10FFFF)) {
- (*o_putc)(0xE0 | ( val>>18));
- (*o_putc)(0x80 | ((val>>12) & 0x3f));
- (*o_putc)(0x80 | ((val>> 6) & 0x3f));
- (*o_putc)(0x80 | ( val & 0x3f));
- }
- return;
- }
-#endif
-
- if (c2 == 0) {
- output_mode = ASCII;
- (*o_putc)(c1);
- } else if (c2 == ISO8859_1) {
- output_mode = ISO8859_1;
- (*o_putc)(c1 | 0x080);
- } else {
- output_mode = UTF8;
- val = e2w_conv(c2, c1);
- if (val){
- w16w_conv(val, &c2, &c1, &c0);
- (*o_putc)(c2);
- if (c1){
- (*o_putc)(c1);
- if (c0) (*o_putc)(c0);
- }
- }
- }
-}
-
-void w_oconv16(nkf_char c2, nkf_char c1)
-{
- if (c2 == EOF) {
- (*o_putc)(EOF);
- return;
- }
-
- if (unicode_bom_f==2) {
- if (w_oconv16_LE){
- (*o_putc)((unsigned char)'\377');
- (*o_putc)('\376');
- }else{
- (*o_putc)('\376');
- (*o_putc)((unsigned char)'\377');
- }
- unicode_bom_f=1;
- }
-
- if (c2 == ISO8859_1) {
- c2 = 0;
- c1 |= 0x80;
-#ifdef NUMCHAR_OPTION
- } else if (c2 == 0 && is_unicode_capsule(c1)) {
- if (is_unicode_bmp(c1)) {
- c2 = (c1 >> 8) & 0xff;
- c1 &= 0xff;
- } else {
- c1 &= VALUE_MASK;
- if (c1 <= UNICODE_MAX) {
- c2 = (c1 >> 10) + NKF_INT32_C(0xD7C0); /* high surrogate */
- c1 = (c1 & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */
- if (w_oconv16_LE){
- (*o_putc)(c2 & 0xff);
- (*o_putc)((c2 >> 8) & 0xff);
- (*o_putc)(c1 & 0xff);
- (*o_putc)((c1 >> 8) & 0xff);
- }else{
- (*o_putc)((c2 >> 8) & 0xff);
- (*o_putc)(c2 & 0xff);
- (*o_putc)((c1 >> 8) & 0xff);
- (*o_putc)(c1 & 0xff);
- }
- }
- return;
- }
-#endif
- } else if (c2) {
- nkf_char val = e2w_conv(c2, c1);
- c2 = (val >> 8) & 0xff;
- c1 = val & 0xff;
- }
- if (w_oconv16_LE){
- (*o_putc)(c1);
- (*o_putc)(c2);
- }else{
- (*o_putc)(c2);
- (*o_putc)(c1);
- }
-}
-
-#endif
-
-void e_oconv(nkf_char c2, nkf_char c1)
-{
-#ifdef NUMCHAR_OPTION
- if (c2 == 0 && is_unicode_capsule(c1)){
- w16e_conv(c1, &c2, &c1);
- if (c2 == 0 && is_unicode_capsule(c1)){
- if(encode_fallback)(*encode_fallback)(c1);
- return;
- }
- }
-#endif
- if (c2 == EOF) {
- (*o_putc)(EOF);
- return;
- } else if (c2 == 0) {
- output_mode = ASCII;
- (*o_putc)(c1);
- } else if (c2 == X0201) {
- output_mode = JAPANESE_EUC;
- (*o_putc)(SSO); (*o_putc)(c1|0x80);
- } else if (c2 == ISO8859_1) {
- output_mode = ISO8859_1;
- (*o_putc)(c1 | 0x080);
-#ifdef X0212_ENABLE
- } else if (is_eucg3(c2)){
- output_mode = JAPANESE_EUC;
-#ifdef SHIFTJIS_CP932
- if (cp51932_f){
- nkf_char s2, s1;
- if (e2s_conv(c2, c1, &s2, &s1) == 0){
- s2e_conv(s2, s1, &c2, &c1);
- }
- }
-#endif
- if (c2 == 0) {
- output_mode = ASCII;
- (*o_putc)(c1);
- }else if (is_eucg3(c2)){
- if (x0212_f){
- (*o_putc)(0x8f);
- (*o_putc)((c2 & 0x7f) | 0x080);
- (*o_putc)(c1 | 0x080);
- }
- }else{
- (*o_putc)((c2 & 0x7f) | 0x080);
- (*o_putc)(c1 | 0x080);
- }
-#endif
- } else {
- if (!nkf_isgraph(c1) || !nkf_isgraph(c2)) {
- set_iconv(FALSE, 0);
- return; /* too late to rescue this char */
- }
- output_mode = JAPANESE_EUC;
- (*o_putc)(c2 | 0x080);
- (*o_putc)(c1 | 0x080);
- }
-}
-
-#ifdef X0212_ENABLE
-nkf_char x0212_shift(nkf_char c)
-{
- nkf_char ret = c;
- c &= 0x7f;
- if (is_eucg3(ret)){
- if (0x75 <= c && c <= 0x7f){
- ret = c + (0x109 - 0x75);
- }
- }else{
- if (0x75 <= c && c <= 0x7f){
- ret = c + (0x113 - 0x75);
- }
- }
- return ret;
-}
-
-
-nkf_char x0212_unshift(nkf_char c)
-{
- nkf_char ret = c;
- if (0x7f <= c && c <= 0x88){
- ret = c + (0x75 - 0x7f);
- }else if (0x89 <= c && c <= 0x92){
- ret = PREFIX_EUCG3 | 0x80 | (c + (0x75 - 0x89));
- }
- return ret;
-}
-#endif /* X0212_ENABLE */
-
-nkf_char e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
-{
- nkf_char ndx;
- if (is_eucg3(c2)){
- ndx = c2 & 0xff;
- if (x0213_f){
- if((0x21 <= ndx && ndx <= 0x2F)){
- if (p2) *p2 = ((ndx - 1) >> 1) + 0xec - ndx / 8 * 3;
- if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
- return 0;
- }else if(0x6E <= ndx && ndx <= 0x7E){
- if (p2) *p2 = ((ndx - 1) >> 1) + 0xbe;
- if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
- return 0;
- }
- return 1;
- }
-#ifdef X0212_ENABLE
- else if(nkf_isgraph(ndx)){
- nkf_char val = 0;
- const unsigned short *ptr;
-#if 0
- extern const unsigned short *const x0212_shiftjis[];
-#endif
- ptr = x0212_shiftjis[ndx - 0x21];
- if (ptr){
- val = ptr[(c1 & 0x7f) - 0x21];
- }
- if (val){
- c2 = val >> 8;
- c1 = val & 0xff;
- if (p2) *p2 = c2;
- if (p1) *p1 = c1;
- return 0;
- }
- c2 = x0212_shift(c2);
- }
-#endif /* X0212_ENABLE */
- }
- if(0x7F < c2) return 1;
- if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1);
- if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
- return 0;
-}
-
-void s_oconv(nkf_char c2, nkf_char c1)
-{
-#ifdef NUMCHAR_OPTION
- if (c2 == 0 && is_unicode_capsule(c1)){
- w16e_conv(c1, &c2, &c1);
- if (c2 == 0 && is_unicode_capsule(c1)){
- if(encode_fallback)(*encode_fallback)(c1);
- return;
- }
- }
-#endif
- if (c2 == EOF) {
- (*o_putc)(EOF);
- return;
- } else if (c2 == 0) {
- output_mode = ASCII;
- (*o_putc)(c1);
- } else if (c2 == X0201) {
- output_mode = SHIFT_JIS;
- (*o_putc)(c1|0x80);
- } else if (c2 == ISO8859_1) {
- output_mode = ISO8859_1;
- (*o_putc)(c1 | 0x080);
-#ifdef X0212_ENABLE
- } else if (is_eucg3(c2)){
- output_mode = SHIFT_JIS;
- if (e2s_conv(c2, c1, &c2, &c1) == 0){
- (*o_putc)(c2);
- (*o_putc)(c1);
- }
-#endif
- } else {
- if (!nkf_isprint(c1) || !nkf_isprint(c2)) {
- set_iconv(FALSE, 0);
- return; /* too late to rescue this char */
- }
- output_mode = SHIFT_JIS;
- e2s_conv(c2, c1, &c2, &c1);
-
-#ifdef SHIFTJIS_CP932
- if (cp932inv_f
- && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
-#if 0
- extern const unsigned short cp932inv[2][189];
-#endif
- nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
- if (c){
- c2 = c >> 8;
- c1 = c & 0xff;
- }
- }
-#endif /* SHIFTJIS_CP932 */
-
- (*o_putc)(c2);
- if (prefix_table[(unsigned char)c1]){
- (*o_putc)(prefix_table[(unsigned char)c1]);
- }
- (*o_putc)(c1);
- }
-}
-
-void j_oconv(nkf_char c2, nkf_char c1)
-{
-#ifdef NUMCHAR_OPTION
- if (c2 == 0 && is_unicode_capsule(c1)){
- w16e_conv(c1, &c2, &c1);
- if (c2 == 0 && is_unicode_capsule(c1)){
- if(encode_fallback)(*encode_fallback)(c1);
- return;
- }
- }
-#endif
- if (c2 == EOF) {
- if (output_mode !=ASCII && output_mode!=ISO8859_1) {
- (*o_putc)(ESC);
- (*o_putc)('(');
- (*o_putc)(ascii_intro);
- output_mode = ASCII;
- }
- (*o_putc)(EOF);
-#ifdef X0212_ENABLE
- } else if (is_eucg3(c2)){
- if(x0213_f){
- if(output_mode!=X0213_2){
- output_mode = X0213_2;
- (*o_putc)(ESC);
- (*o_putc)('$');
- (*o_putc)('(');
- (*o_putc)(X0213_2&0x7F);
- }
- }else{
- if(output_mode!=X0212){
- output_mode = X0212;
- (*o_putc)(ESC);
- (*o_putc)('$');
- (*o_putc)('(');
- (*o_putc)(X0212&0x7F);
- }
- }
- (*o_putc)(c2 & 0x7f);
- (*o_putc)(c1);
-#endif
- } else if (c2==X0201) {
- if (output_mode!=X0201) {
- output_mode = X0201;
- (*o_putc)(ESC);
- (*o_putc)('(');
- (*o_putc)('I');
- }
- (*o_putc)(c1);
- } else if (c2==ISO8859_1) {
- /* iso8859 introduction, or 8th bit on */
- /* Can we convert in 7bit form using ESC-'-'-A ?
- Is this popular? */
- output_mode = ISO8859_1;
- (*o_putc)(c1|0x80);
- } else if (c2 == 0) {
- if (output_mode !=ASCII && output_mode!=ISO8859_1) {
- (*o_putc)(ESC);
- (*o_putc)('(');
- (*o_putc)(ascii_intro);
- output_mode = ASCII;
- }
- (*o_putc)(c1);
- } else {
- if(c2<0x20 || 0x7e<c2 || c1<0x20 || 0x7e<c1) return;
- if(x0213_f){
- if (output_mode!=X0213_1) {
- output_mode = X0213_1;
- (*o_putc)(ESC);
- (*o_putc)('$');
- (*o_putc)('(');
- (*o_putc)(X0213_1&0x7F);
- }
- }else if (output_mode != X0208) {
- output_mode = X0208;
- (*o_putc)(ESC);
- (*o_putc)('$');
- (*o_putc)(kanji_intro);
- }
- (*o_putc)(c2);
- (*o_putc)(c1);
- }
-}
-
-void base64_conv(nkf_char c2, nkf_char c1)
-{
- mime_prechar(c2, c1);
- (*o_base64conv)(c2,c1);
-}
-
-
-static nkf_char broken_buf[3];
-static int broken_counter = 0;
-static int broken_last = 0;
-nkf_char broken_getc(FILE *f)
-{
- nkf_char c,c1;
-
- if (broken_counter>0) {
- return broken_buf[--broken_counter];
- }
- c= (*i_bgetc)(f);
- if (c=='$' && broken_last != ESC
- && (input_mode==ASCII || input_mode==X0201)) {
- c1= (*i_bgetc)(f);
- broken_last = 0;
- if (c1=='@'|| c1=='B') {
- broken_buf[0]=c1; broken_buf[1]=c;
- broken_counter=2;
- return ESC;
- } else {
- (*i_bungetc)(c1,f);
- return c;
- }
- } else if (c=='(' && broken_last != ESC
- && (input_mode==X0208 || input_mode==X0201)) { /* ) */
- c1= (*i_bgetc)(f);
- broken_last = 0;
- if (c1=='J'|| c1=='B') {
- broken_buf[0]=c1; broken_buf[1]=c;
- broken_counter=2;
- return ESC;
- } else {
- (*i_bungetc)(c1,f);
- return c;
- }
- } else {
- broken_last = c;
- return c;
- }
-}
-
-nkf_char broken_ungetc(nkf_char c, FILE *f)
-{
- if (broken_counter<2)
- broken_buf[broken_counter++]=c;
- return c;
-}
-
-static nkf_char prev_cr = 0;
-
-void cr_conv(nkf_char c2, nkf_char c1)
-{
- if (prev_cr) {
- prev_cr = 0;
- if (! (c2==0&&c1==NL) ) {
- cr_conv(0,'\n');
- }
- }
- if (c2) {
- (*o_crconv)(c2,c1);
- } else if (c1=='\r') {
- prev_cr = c1;
- } else if (c1=='\n') {
- if (crmode_f==CRLF) {
- (*o_crconv)(0,'\r');
- } else if (crmode_f==CR) {
- (*o_crconv)(0,'\r');
- return;
- }
- (*o_crconv)(0,NL);
- } else if (c1!='\032' || crmode_f!=NL){
- (*o_crconv)(c2,c1);
- }
-}
-
-/*
- Return value of fold_conv()
-
- \n add newline and output char
- \r add newline and output nothing
- ' ' space
- 0 skip
- 1 (or else) normal output
-
- fold state in prev (previous character)
-
- >0x80 Japanese (X0208/X0201)
- <0x80 ASCII
- \n new line
- ' ' space
-
- This fold algorthm does not preserve heading space in a line.
- This is the main difference from fmt.
-*/
-
-#define char_size(c2,c1) (c2?2:1)
-
-void fold_conv(nkf_char c2, nkf_char c1)
-{
- nkf_char prev0;
- nkf_char fold_state;
-
- if (c1== '\r' && !fold_preserve_f) {
- fold_state=0; /* ignore cr */
- }else if (c1== '\n'&&f_prev=='\r' && fold_preserve_f) {
- f_prev = '\n';
- fold_state=0; /* ignore cr */
- } else if (c1== BS) {
- if (f_line>0) f_line--;
- fold_state = 1;
- } else if (c2==EOF && f_line != 0) { /* close open last line */
- fold_state = '\n';
- } else if ((c1=='\n' && !fold_preserve_f)
- || ((c1=='\r'||(c1=='\n'&&f_prev!='\r'))
- && fold_preserve_f)) {
- /* new line */
- if (fold_preserve_f) {
- f_prev = c1;
- f_line = 0;
- fold_state = '\r';
- } else if ((f_prev == c1 && !fold_preserve_f)
- || (f_prev == '\n' && fold_preserve_f)
- ) { /* duplicate newline */
- if (f_line) {
- f_line = 0;
- fold_state = '\n'; /* output two newline */
- } else {
- f_line = 0;
- fold_state = 1;
- }
- } else {
- if (f_prev&0x80) { /* Japanese? */
- f_prev = c1;
- fold_state = 0; /* ignore given single newline */
- } else if (f_prev==' ') {
- fold_state = 0;
- } else {
- f_prev = c1;
- if (++f_line<=fold_len)
- fold_state = ' ';
- else {
- f_line = 0;
- fold_state = '\r'; /* fold and output nothing */
- }
- }
- }
- } else if (c1=='\f') {
- f_prev = '\n';
- f_line = 0;
- fold_state = '\n'; /* output newline and clear */
- } else if ( (c2==0 && c1==' ')||
- (c2==0 && c1=='\t')||
- (c2=='!'&& c1=='!')) {
- /* X0208 kankaku or ascii space */
- if (f_prev == ' ') {
- fold_state = 0; /* remove duplicate spaces */
- } else {
- f_prev = ' ';
- if (++f_line<=fold_len)
- fold_state = ' '; /* output ASCII space only */
- else {
- f_prev = ' '; f_line = 0;
- fold_state = '\r'; /* fold and output nothing */
- }
- }
- } else {
- prev0 = f_prev; /* we still need this one... , but almost done */
- f_prev = c1;
- if (c2 || c2==X0201)
- f_prev |= 0x80; /* this is Japanese */
- f_line += char_size(c2,c1);
- if (f_line<=fold_len) { /* normal case */
- fold_state = 1;
- } else {
- if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */
- f_line = char_size(c2,c1);
- fold_state = '\n'; /* We can't wait, do fold now */
- } else if (c2==X0201) {
- /* simple kinsoku rules return 1 means no folding */
- if (c1==(0xde&0x7f)) fold_state = 1; /* $B!+(B*/
- else if (c1==(0xdf&0x7f)) fold_state = 1; /* $B!,(B*/
- else if (c1==(0xa4&0x7f)) fold_state = 1; /* $B!#(B*/
- else if (c1==(0xa3&0x7f)) fold_state = 1; /* $B!$(B*/
- else if (c1==(0xa1&0x7f)) fold_state = 1; /* $B!W(B*/
- else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
- else if (SPACE<=c1 && c1<=(0xdf&0x7f)) { /* X0201 */
- f_line = 1;
- fold_state = '\n';/* add one new f_line before this character */
- } else {
- f_line = 1;
- fold_state = '\n';/* add one new f_line before this character */
- }
- } else if (c2==0) {
- /* kinsoku point in ASCII */
- if ( c1==')'|| /* { [ ( */
- c1==']'||
- c1=='}'||
- c1=='.'||
- c1==','||
- c1=='!'||
- c1=='?'||
- c1=='/'||
- c1==':'||
- c1==';' ) {
- fold_state = 1;
- /* just after special */
- } else if (!is_alnum(prev0)) {
- f_line = char_size(c2,c1);
- fold_state = '\n';
- } else if ((prev0==' ') || /* ignored new f_line */
- (prev0=='\n')|| /* ignored new f_line */
- (prev0&0x80)) { /* X0208 - ASCII */
- f_line = char_size(c2,c1);
- fold_state = '\n';/* add one new f_line before this character */
- } else {
- fold_state = 1; /* default no fold in ASCII */
- }
- } else {
- if (c2=='!') {
- if (c1=='"') fold_state = 1; /* $B!"(B */
- else if (c1=='#') fold_state = 1; /* $B!#(B */
- else if (c1=='W') fold_state = 1; /* $B!W(B */
- else if (c1=='K') fold_state = 1; /* $B!K(B */
- else if (c1=='$') fold_state = 1; /* $B!$(B */
- else if (c1=='%') fold_state = 1; /* $B!%(B */
- else if (c1=='\'') fold_state = 1; /* $B!\(B */
- else if (c1=='(') fold_state = 1; /* $B!((B */
- else if (c1==')') fold_state = 1; /* $B!)(B */
- else if (c1=='*') fold_state = 1; /* $B!*(B */
- else if (c1=='+') fold_state = 1; /* $B!+(B */
- else if (c1==',') fold_state = 1; /* $B!,(B */
- /* default no fold in kinsoku */
- else {
- fold_state = '\n';
- f_line = char_size(c2,c1);
- /* add one new f_line before this character */
- }
- } else {
- f_line = char_size(c2,c1);
- fold_state = '\n';
- /* add one new f_line before this character */
- }
- }
- }
- }
- /* terminator process */
- switch(fold_state) {
- case '\n':
- (*o_fconv)(0,'\n');
- (*o_fconv)(c2,c1);
- break;
- case 0:
- return;
- case '\r':
- (*o_fconv)(0,'\n');
- break;
- case '\t':
- case ' ':
- (*o_fconv)(0,' ');
- break;
- default:
- (*o_fconv)(c2,c1);
- }
-}
-
-nkf_char z_prev2=0,z_prev1=0;
-
-void z_conv(nkf_char c2, nkf_char c1)
-{
-
- /* if (c2) c1 &= 0x7f; assertion */
-
- if (x0201_f && z_prev2==X0201) { /* X0201 */
- if (c1==(0xde&0x7f)) { /* $BByE@(B */
- z_prev2=0;
- (*o_zconv)(dv[(z_prev1-SPACE)*2],dv[(z_prev1-SPACE)*2+1]);
- return;
- } else if (c1==(0xdf&0x7f)&&ev[(z_prev1-SPACE)*2]) { /* $BH>ByE@(B */
- z_prev2=0;
- (*o_zconv)(ev[(z_prev1-SPACE)*2],ev[(z_prev1-SPACE)*2+1]);
- return;
- } else {
- z_prev2=0;
- (*o_zconv)(cv[(z_prev1-SPACE)*2],cv[(z_prev1-SPACE)*2+1]);
- }
- }
-
- if (c2==EOF) {
- (*o_zconv)(c2,c1);
- return;
- }
-
- if (x0201_f && c2==X0201) {
- if (dv[(c1-SPACE)*2]||ev[(c1-SPACE)*2]) {
- /* wait for $BByE@(B or $BH>ByE@(B */
- z_prev1 = c1; z_prev2 = c2;
- return;
- } else {
- (*o_zconv)(cv[(c1-SPACE)*2],cv[(c1-SPACE)*2+1]);
- return;
- }
- }
-
- /* JISX0208 Alphabet */
- if (alpha_f && c2 == 0x23 ) {
- c2 = 0;
- } else if (alpha_f && c2 == 0x21 ) {
- /* JISX0208 Kigou */
- if (0x21==c1) {
- if (alpha_f&0x2) {
- c1 = ' ';
- c2 = 0;
- } else if (alpha_f&0x4) {
- (*o_zconv)(0,' ');
- (*o_zconv)(0,' ');
- return;
- }
- } else if (0x20<c1 && c1<0x7f && fv[c1-0x20]) {
- c1 = fv[c1-0x20];
- c2 = 0;
- if (alpha_f&0x8) {
- char *entity = 0;
- switch (c1){
- case '>': entity = "&gt;"; break;
- case '<': entity = "&lt;"; break;
- case '\"': entity = "&quot;"; break;
- case '&': entity = "&amp;"; break;
- }
- if (entity){
- while (*entity) (*o_zconv)(0, *entity++);
- return;
- }
- }
- }
- }
- (*o_zconv)(c2,c1);
-}
-
-
-#define rot13(c) ( \
- ( c < 'A' ) ? c: \
- (c <= 'M') ? (c + 13): \
- (c <= 'Z') ? (c - 13): \
- (c < 'a') ? (c): \
- (c <= 'm') ? (c + 13): \
- (c <= 'z') ? (c - 13): \
- (c) \
-)
-
-#define rot47(c) ( \
- ( c < '!' ) ? c: \
- ( c <= 'O' ) ? (c + 47) : \
- ( c <= '~' ) ? (c - 47) : \
- c \
-)
-
-void rot_conv(nkf_char c2, nkf_char c1)
-{
- if (c2==0 || c2==X0201 || c2==ISO8859_1) {
- c1 = rot13(c1);
- } else if (c2) {
- c1 = rot47(c1);
- c2 = rot47(c2);
- }
- (*o_rot_conv)(c2,c1);
-}
-
-void hira_conv(nkf_char c2, nkf_char c1)
-{
- if (hira_f & 1) {
- if (c2 == 0x25) {
- if (0x20 < c1 && c1 < 0x74) {
- c2 = 0x24;
- (*o_hira_conv)(c2,c1);
- return;
- } else if (c1 == 0x74 && (output_conv == w_oconv || output_conv == w_oconv16)) {
- c2 = 0;
- c1 = CLASS_UTF16 | 0x3094;
- (*o_hira_conv)(c2,c1);
- return;
- }
- } else if (c2 == 0x21 && (c1 == 0x33 || c1 == 0x34)) {
- c1 += 2;
- (*o_hira_conv)(c2,c1);
- return;
- }
- }
- if (hira_f & 2) {
- if (c2 == 0 && c1 == (CLASS_UTF16 | 0x3094)) {
- c2 = 0x25;
- c1 = 0x74;
- } else if (c2 == 0x24 && 0x20 < c1 && c1 < 0x74) {
- c2 = 0x25;
- } else if (c2 == 0x21 && (c1 == 0x35 || c1 == 0x36)) {
- c1 -= 2;
- }
- }
- (*o_hira_conv)(c2,c1);
-}
-
-
-void iso2022jp_check_conv(nkf_char c2, nkf_char c1)
-{
- static const nkf_char range[RANGE_NUM_MAX][2] = {
- {0x222f, 0x2239,},
- {0x2242, 0x2249,},
- {0x2251, 0x225b,},
- {0x226b, 0x2271,},
- {0x227a, 0x227d,},
- {0x2321, 0x232f,},
- {0x233a, 0x2340,},
- {0x235b, 0x2360,},
- {0x237b, 0x237e,},
- {0x2474, 0x247e,},
- {0x2577, 0x257e,},
- {0x2639, 0x2640,},
- {0x2659, 0x267e,},
- {0x2742, 0x2750,},
- {0x2772, 0x277e,},
- {0x2841, 0x287e,},
- {0x4f54, 0x4f7e,},
- {0x7425, 0x747e},
- };
- nkf_char i;
- nkf_char start, end, c;
-
- if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) {
- c2 = GETA1;
- c1 = GETA2;
- }
- if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) {
- c2 = GETA1;
- c1 = GETA2;
- }
-
- for (i = 0; i < RANGE_NUM_MAX; i++) {
- start = range[i][0];
- end = range[i][1];
- c = (c2 << 8) + c1;
- if (c >= start && c <= end) {
- c2 = GETA1;
- c1 = GETA2;
- }
- }
- (*o_iso2022jp_check_conv)(c2,c1);
-}
-
-
-/* This converts =?ISO-2022-JP?B?HOGE HOGE?= */
-
-const unsigned char *mime_pattern[] = {
- (const unsigned char *)"\075?EUC-JP?B?",
- (const unsigned char *)"\075?SHIFT_JIS?B?",
- (const unsigned char *)"\075?ISO-8859-1?Q?",
- (const unsigned char *)"\075?ISO-8859-1?B?",
- (const unsigned char *)"\075?ISO-2022-JP?B?",
- (const unsigned char *)"\075?ISO-2022-JP?Q?",
-#if defined(UTF8_INPUT_ENABLE)
- (const unsigned char *)"\075?UTF-8?B?",
- (const unsigned char *)"\075?UTF-8?Q?",
-#endif
- (const unsigned char *)"\075?US-ASCII?Q?",
- NULL
-};
-
-
-/* $B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u(B */
-nkf_char (*mime_priority_func[])(nkf_char c2, nkf_char c1, nkf_char c0) = {
- e_iconv, s_iconv, 0, 0, 0, 0,
-#if defined(UTF8_INPUT_ENABLE)
- w_iconv, w_iconv,
-#endif
- 0,
-};
-
-const nkf_char mime_encode[] = {
- JAPANESE_EUC, SHIFT_JIS,ISO8859_1, ISO8859_1, X0208, X0201,
-#if defined(UTF8_INPUT_ENABLE)
- UTF8, UTF8,
-#endif
- ASCII,
- 0
-};
-
-const nkf_char mime_encode_method[] = {
- 'B', 'B','Q', 'B', 'B', 'Q',
-#if defined(UTF8_INPUT_ENABLE)
- 'B', 'Q',
-#endif
- 'Q',
- 0
-};
-
-
-#define MAXRECOVER 20
-
-void switch_mime_getc(void)
-{
- if (i_getc!=mime_getc) {
- i_mgetc = i_getc; i_getc = mime_getc;
- i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
- if(mime_f==STRICT_MIME) {
- i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf;
- i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf;
- }
- }
-}
-
-void unswitch_mime_getc(void)
-{
- if(mime_f==STRICT_MIME) {
- i_mgetc = i_mgetc_buf;
- i_mungetc = i_mungetc_buf;
- }
- i_getc = i_mgetc;
- i_ungetc = i_mungetc;
- if(mime_iconv_back)set_iconv(FALSE, mime_iconv_back);
- mime_iconv_back = NULL;
-}
-
-nkf_char mime_begin_strict(FILE *f)
-{
- nkf_char c1 = 0;
- int i,j,k;
- const unsigned char *p,*q;
- nkf_char r[MAXRECOVER]; /* recovery buffer, max mime pattern length */
-
- mime_decode_mode = FALSE;
- /* =? has been checked */
- j = 0;
- p = mime_pattern[j];
- r[0]='='; r[1]='?';
-
- for(i=2;p[i]>' ';i++) { /* start at =? */
- if ( ((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i] ) {
- /* pattern fails, try next one */
- q = p;
- while (mime_pattern[++j]) {
- p = mime_pattern[j];
- for(k=2;k<i;k++) /* assume length(p) > i */
- if (p[k]!=q[k]) break;
- if (k==i && nkf_toupper(c1)==p[k]) break;
- }
- p = mime_pattern[j];
- if (p) continue; /* found next one, continue */
- /* all fails, output from recovery buffer */
- (*i_ungetc)(c1,f);
- for(j=0;j<i;j++) {
- (*oconv)(0,r[j]);
- }
- return c1;
- }
- }
- mime_decode_mode = p[i-2];
-
- mime_iconv_back = iconv;
- set_iconv(FALSE, mime_priority_func[j]);
- clr_code_score(find_inputcode_byfunc(mime_priority_func[j]), SCORE_iMIME);
-
- if (mime_decode_mode=='B') {
- mimebuf_f = unbuf_f;
- if (!unbuf_f) {
- /* do MIME integrity check */
- return mime_integrity(f,mime_pattern[j]);
- }
- }
- switch_mime_getc();
- mimebuf_f = TRUE;
- return c1;
-}
-
-nkf_char mime_getc_buf(FILE *f)
-{
- /* we don't keep eof of Fifo, becase it contains ?= as
- a terminator. It was checked in mime_integrity. */
- return ((mimebuf_f)?
- (*i_mgetc_buf)(f):Fifo(mime_input++));
-}
-
-nkf_char mime_ungetc_buf(nkf_char c, FILE *f)
-{
- if (mimebuf_f)
- (*i_mungetc_buf)(c,f);
- else
- Fifo(--mime_input) = (unsigned char)c;
- return c;
-}
-
-nkf_char mime_begin(FILE *f)
-{
- nkf_char c1;
- int i,k;
-
- /* In NONSTRICT mode, only =? is checked. In case of failure, we */
- /* re-read and convert again from mime_buffer. */
-
- /* =? has been checked */
- k = mime_last;
- Fifo(mime_last++)='='; Fifo(mime_last++)='?';
- for(i=2;i<MAXRECOVER;i++) { /* start at =? */
- /* We accept any character type even if it is breaked by new lines */
- c1 = (*i_getc)(f); Fifo(mime_last++) = (unsigned char)c1;
- if (c1=='\n'||c1==' '||c1=='\r'||
- c1=='-'||c1=='_'||is_alnum(c1) ) continue;
- if (c1=='=') {
- /* Failed. But this could be another MIME preemble */
- (*i_ungetc)(c1,f);
- mime_last--;
- break;
- }
- if (c1!='?') break;
- else {
- /* c1=='?' */
- c1 = (*i_getc)(f); Fifo(mime_last++) = (unsigned char)c1;
- if (!(++i<MAXRECOVER) || c1==EOF) break;
- if (c1=='b'||c1=='B') {
- mime_decode_mode = 'B';
- } else if (c1=='q'||c1=='Q') {
- mime_decode_mode = 'Q';
- } else {
- break;
- }
- c1 = (*i_getc)(f); Fifo(mime_last++) = (unsigned char)c1;
- if (!(++i<MAXRECOVER) || c1==EOF) break;
- if (c1!='?') {
- mime_decode_mode = FALSE;
- }
- break;
- }
- }
- switch_mime_getc();
- if (!mime_decode_mode) {
- /* false MIME premble, restart from mime_buffer */
- mime_decode_mode = 1; /* no decode, but read from the mime_buffer */
- /* Since we are in MIME mode until buffer becomes empty, */
- /* we never go into mime_begin again for a while. */
- return c1;
- }
- /* discard mime preemble, and goto MIME mode */
- mime_last = k;
- /* do no MIME integrity check */
- return c1; /* used only for checking EOF */
-}
-
-#ifdef CHECK_OPTION
-void no_putc(nkf_char c)
-{
- ;
-}
-
-void debug(const char *str)
-{
- if (debug_f){
- fprintf(stderr, "%s\n", str);
- }
-}
-#endif
-
-void set_input_codename(char *codename)
-{
- if (guess_f &&
- is_inputcode_set &&
- strcmp(codename, "") != 0 &&
- strcmp(codename, input_codename) != 0)
- {
- is_inputcode_mixed = TRUE;
- }
- input_codename = codename;
- is_inputcode_set = TRUE;
-}
-
-#if !defined(PERL_XS) && !defined(WIN32DLL)
-void print_guessed_code(char *filename)
-{
- char *codename = "BINARY";
- if (!is_inputcode_mixed) {
- if (strcmp(input_codename, "") == 0) {
- codename = "ASCII";
- } else {
- codename = input_codename;
- }
- }
- if (filename != NULL) printf("%s:", filename);
- printf("%s\n", codename);
-}
-#endif /*WIN32DLL*/
-
-#ifdef INPUT_OPTION
-
-nkf_char hex_getc(nkf_char ch, FILE *f, nkf_char (*g)(FILE *f), nkf_char (*u)(nkf_char c, FILE *f))
-{
- nkf_char c1, c2, c3;
- c1 = (*g)(f);
- if (c1 != ch){
- return c1;
- }
- c2 = (*g)(f);
- if (!nkf_isxdigit(c2)){
- (*u)(c2, f);
- return c1;
- }
- c3 = (*g)(f);
- if (!nkf_isxdigit(c3)){
- (*u)(c2, f);
- (*u)(c3, f);
- return c1;
- }
- return (hex2bin(c2) << 4) | hex2bin(c3);
-}
-
-nkf_char cap_getc(FILE *f)
-{
- return hex_getc(':', f, i_cgetc, i_cungetc);
-}
-
-nkf_char cap_ungetc(nkf_char c, FILE *f)
-{
- return (*i_cungetc)(c, f);
-}
-
-nkf_char url_getc(FILE *f)
-{
- return hex_getc('%', f, i_ugetc, i_uungetc);
-}
-
-nkf_char url_ungetc(nkf_char c, FILE *f)
-{
- return (*i_uungetc)(c, f);
-}
-#endif
-
-#ifdef NUMCHAR_OPTION
-nkf_char numchar_getc(FILE *f)
-{
- nkf_char (*g)(FILE *) = i_ngetc;
- nkf_char (*u)(nkf_char c ,FILE *f) = i_nungetc;
- int i = 0, j;
- nkf_char buf[8];
- long c = -1;
-
- buf[i] = (*g)(f);
- if (buf[i] == '&'){
- buf[++i] = (*g)(f);
- if (buf[i] == '#'){
- c = 0;
- buf[++i] = (*g)(f);
- if (buf[i] == 'x' || buf[i] == 'X'){
- for (j = 0; j < 7; j++){
- buf[++i] = (*g)(f);
- if (!nkf_isxdigit(buf[i])){
- if (buf[i] != ';'){
- c = -1;
- }
- break;
- }
- c <<= 4;
- c |= hex2bin(buf[i]);
- }
- }else{
- for (j = 0; j < 8; j++){
- if (j){
- buf[++i] = (*g)(f);
- }
- if (!nkf_isdigit(buf[i])){
- if (buf[i] != ';'){
- c = -1;
- }
- break;
- }
- c *= 10;
- c += hex2bin(buf[i]);
- }
- }
- }
- }
- if (c != -1){
- return CLASS_UTF16 | c;
- }
- while (i > 0){
- (*u)(buf[i], f);
- --i;
- }
- return buf[0];
-}
-
-nkf_char numchar_ungetc(nkf_char c, FILE *f)
-{
- return (*i_nungetc)(c, f);
-}
-#endif
-
-#ifdef UNICODE_NORMALIZATION
-
-/* Normalization Form C */
-nkf_char nfc_getc(FILE *f)
-{
- nkf_char (*g)(FILE *f) = i_nfc_getc;
- nkf_char (*u)(nkf_char c ,FILE *f) = i_nfc_ungetc;
- int i=0, j, k=1, lower, upper;
- nkf_char buf[9];
- const nkf_nfchar *array;
-#if 0
- extern const struct normalization_pair normalization_table[];
-#endif
-
- buf[i] = (*g)(f);
- while (k > 0 && ((buf[i] & 0xc0) != 0x80)){
- lower=0, upper=NORMALIZATION_TABLE_LENGTH-1;
- while (upper >= lower) {
- j = (lower+upper) / 2;
- array = normalization_table[j].nfd;
- for (k=0; k < NORMALIZATION_TABLE_NFD_LENGTH && array[k]; k++){
- if (array[k] != buf[k]){
- array[k] < buf[k] ? (lower = j + 1) : (upper = j - 1);
- k = 0;
- break;
- } else if (k >= i)
- buf[++i] = (*g)(f);
- }
- if (k > 0){
- array = normalization_table[j].nfc;
- for (i=0; i < NORMALIZATION_TABLE_NFC_LENGTH && array[i]; i++)
- buf[i] = (nkf_char)(array[i]);
- i--;
- break;
- }
- }
- while (i > 0)
- (*u)(buf[i--], f);
- }
- return buf[0];
-}
-
-nkf_char nfc_ungetc(nkf_char c, FILE *f)
-{
- return (*i_nfc_ungetc)(c, f);
-}
-#endif /* UNICODE_NORMALIZATION */
-
-
-nkf_char
-mime_getc(FILE *f)
-{
- nkf_char c1, c2, c3, c4, cc;
- nkf_char t1, t2, t3, t4, mode, exit_mode;
- nkf_char lwsp_count;
- char *lwsp_buf;
- char *lwsp_buf_new;
- nkf_char lwsp_size = 128;
-
- if (mime_top != mime_last) { /* Something is in FIFO */
- return Fifo(mime_top++);
- }
- if (mime_decode_mode==1 ||mime_decode_mode==FALSE) {
- mime_decode_mode=FALSE;
- unswitch_mime_getc();
- return (*i_getc)(f);
- }
-
- if (mimebuf_f == FIXED_MIME)
- exit_mode = mime_decode_mode;
- else
- exit_mode = FALSE;
- if (mime_decode_mode == 'Q') {
- if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
-restart_mime_q:
- if (c1=='_' && mimebuf_f != FIXED_MIME) return ' ';
- if (c1<=' ' || DEL<=c1) {
- mime_decode_mode = exit_mode; /* prepare for quit */
- return c1;
- }
- if (c1!='=' && (c1!='?' || mimebuf_f == FIXED_MIME)) {
- return c1;
- }
-
- mime_decode_mode = exit_mode; /* prepare for quit */
- if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
- if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
- /* end Q encoding */
- input_mode = exit_mode;
- lwsp_count = 0;
- lwsp_buf = malloc((lwsp_size+5)*sizeof(char));
- if (lwsp_buf==NULL) {
- perror("can't malloc");
- return -1;
- }
- while ((c1=(*i_getc)(f))!=EOF) {
- switch (c1) {
- case NL:
- case CR:
- if (c1==NL) {
- if ((c1=(*i_getc)(f))!=EOF && (c1==SPACE||c1==TAB)) {
- i_ungetc(SPACE,f);
- continue;
- } else {
- i_ungetc(c1,f);
- }
- c1 = NL;
- } else {
- if ((c1=(*i_getc)(f))!=EOF && c1 == NL) {
- if ((c1=(*i_getc)(f))!=EOF && (c1==SPACE||c1==TAB)) {
- i_ungetc(SPACE,f);
- continue;
- } else {
- i_ungetc(c1,f);
- }
- i_ungetc(NL,f);
- } else {
- i_ungetc(c1,f);
- }
- c1 = CR;
- }
- break;
- case SPACE:
- case TAB:
- lwsp_buf[lwsp_count] = (unsigned char)c1;
- if (lwsp_count++>lwsp_size){
- lwsp_size <<= 1;
- lwsp_buf_new = realloc(lwsp_buf, (lwsp_size+5)*sizeof(char));
- if (lwsp_buf_new==NULL) {
- free(lwsp_buf);
- perror("can't realloc");
- return -1;
- }
- lwsp_buf = lwsp_buf_new;
- }
- continue;
- }
- break;
- }
- if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SPACE && lwsp_buf[lwsp_count-1] != TAB))) {
- i_ungetc(c1,f);
- for(lwsp_count--;lwsp_count>0;lwsp_count--)
- i_ungetc(lwsp_buf[lwsp_count],f);
- c1 = lwsp_buf[0];
- }
- free(lwsp_buf);
- return c1;
- }
- if (c1=='='&&c2<' ') { /* this is soft wrap */
- while((c1 = (*i_mgetc)(f)) <=' ') {
- if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
- }
- mime_decode_mode = 'Q'; /* still in MIME */
- goto restart_mime_q;
- }
- if (c1=='?') {
- mime_decode_mode = 'Q'; /* still in MIME */
- (*i_mungetc)(c2,f);
- return c1;
- }
- if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
- if (c2<=' ') return c2;
- mime_decode_mode = 'Q'; /* still in MIME */
- return ((hex2bin(c2)<<4) + hex2bin(c3));
- }
-
- if (mime_decode_mode != 'B') {
- mime_decode_mode = FALSE;
- return (*i_mgetc)(f);
- }
-
-
- /* Base64 encoding */
- /*
- MIME allows line break in the middle of
- Base64, but we are very pessimistic in decoding
- in unbuf mode because MIME encoded code may broken by
- less or editor's control sequence (such as ESC-[-K in unbuffered
- mode. ignore incomplete MIME.
- */
- mode = mime_decode_mode;
- mime_decode_mode = exit_mode; /* prepare for quit */
-
- while ((c1 = (*i_mgetc)(f))<=' ') {
- if (c1==EOF)
- return (EOF);
- }
-mime_c2_retry:
- if ((c2 = (*i_mgetc)(f))<=' ') {
- if (c2==EOF)
- return (EOF);
- if (mime_f != STRICT_MIME) goto mime_c2_retry;
- if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
- return c2;
- }
- if ((c1 == '?') && (c2 == '=')) {
- input_mode = ASCII;
- lwsp_count = 0;
- lwsp_buf = malloc((lwsp_size+5)*sizeof(char));
- if (lwsp_buf==NULL) {
- perror("can't malloc");
- return -1;
- }
- while ((c1=(*i_getc)(f))!=EOF) {
- switch (c1) {
- case NL:
- case CR:
- if (c1==NL) {
- if ((c1=(*i_getc)(f))!=EOF && (c1==SPACE||c1==TAB)) {
- i_ungetc(SPACE,f);
- continue;
- } else {
- i_ungetc(c1,f);
- }
- c1 = NL;
- } else {
- if ((c1=(*i_getc)(f))!=EOF) {
- if (c1==SPACE) {
- i_ungetc(SPACE,f);
- continue;
- } else if ((c1=(*i_getc)(f))!=EOF && (c1==SPACE||c1==TAB)) {
- i_ungetc(SPACE,f);
- continue;
- } else {
- i_ungetc(c1,f);
- }
- i_ungetc(NL,f);
- } else {
- i_ungetc(c1,f);
- }
- c1 = CR;
- }
- break;
- case SPACE:
- case TAB:
- lwsp_buf[lwsp_count] = (unsigned char)c1;
- if (lwsp_count++>lwsp_size){
- lwsp_size <<= 1;
- lwsp_buf_new = realloc(lwsp_buf, (lwsp_size+5)*sizeof(char));
- if (lwsp_buf_new==NULL) {
- free(lwsp_buf);
- perror("can't realloc");
- return -1;
- }
- lwsp_buf = lwsp_buf_new;
- }
- continue;
- }
- break;
- }
- if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SPACE && lwsp_buf[lwsp_count-1] != TAB))) {
- i_ungetc(c1,f);
- for(lwsp_count--;lwsp_count>0;lwsp_count--)
- i_ungetc(lwsp_buf[lwsp_count],f);
- c1 = lwsp_buf[0];
- }
- free(lwsp_buf);
- return c1;
- }
-mime_c3_retry:
- if ((c3 = (*i_mgetc)(f))<=' ') {
- if (c3==EOF)
- return (EOF);
- if (mime_f != STRICT_MIME) goto mime_c3_retry;
- if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
- return c3;
- }
-mime_c4_retry:
- if ((c4 = (*i_mgetc)(f))<=' ') {
- if (c4==EOF)
- return (EOF);
- if (mime_f != STRICT_MIME) goto mime_c4_retry;
- if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
- return c4;
- }
-
- mime_decode_mode = mode; /* still in MIME sigh... */
-
- /* BASE 64 decoding */
-
- t1 = 0x3f & base64decode(c1);
- t2 = 0x3f & base64decode(c2);
- t3 = 0x3f & base64decode(c3);
- t4 = 0x3f & base64decode(c4);
- cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
- if (c2 != '=') {
- Fifo(mime_last++) = (unsigned char)cc;
- cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
- if (c3 != '=') {
- Fifo(mime_last++) = (unsigned char)cc;
- cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
- if (c4 != '=')
- Fifo(mime_last++) = (unsigned char)cc;
- }
- } else {
- return c1;
- }
- return Fifo(mime_top++);
-}
-
-nkf_char mime_ungetc(nkf_char c, FILE *f)
-{
- Fifo(--mime_top) = (unsigned char)c;
- return c;
-}
-
-nkf_char mime_integrity(FILE *f, const unsigned char *p)
-{
- nkf_char c,d;
- unsigned int q;
- /* In buffered mode, read until =? or NL or buffer full
- */
- mime_input = mime_top;
- mime_last = mime_top;
-
- while(*p) Fifo(mime_input++) = *p++;
- d = 0;
- q = mime_input;
- while((c=(*i_getc)(f))!=EOF) {
- if (((mime_input-mime_top)&MIME_BUF_MASK)==0) {
- break; /* buffer full */
- }
- if (c=='=' && d=='?') {
- /* checked. skip header, start decode */
- Fifo(mime_input++) = (unsigned char)c;
- /* mime_last_input = mime_input; */
- mime_input = q;
- switch_mime_getc();
- return 1;
- }
- if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
- break;
- /* Should we check length mod 4? */
- Fifo(mime_input++) = (unsigned char)c;
- d=c;
- }
- /* In case of Incomplete MIME, no MIME decode */
- Fifo(mime_input++) = (unsigned char)c;
- mime_last = mime_input; /* point undecoded buffer */
- mime_decode_mode = 1; /* no decode on Fifo last in mime_getc */
- switch_mime_getc(); /* anyway we need buffered getc */
- return 1;
-}
-
-nkf_char base64decode(nkf_char c)
-{
- int i;
- if (c > '@') {
- if (c < '[') {
- i = c - 'A'; /* A..Z 0-25 */
- } else {
- i = c - 'G' /* - 'a' + 26 */ ; /* a..z 26-51 */
- }
- } else if (c > '/') {
- i = c - '0' + '4' /* - '0' + 52 */ ; /* 0..9 52-61 */
- } else if (c == '+') {
- i = '>' /* 62 */ ; /* + 62 */
- } else {
- i = '?' /* 63 */ ; /* / 63 */
- }
- return (i);
-}
-
-static const char basis_64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static nkf_char b64c;
-#define MIMEOUT_BUF_LENGTH (60)
-char mimeout_buf[MIMEOUT_BUF_LENGTH+1];
-int mimeout_buf_count = 0;
-int mimeout_preserve_space = 0;
-#define itoh4(c) (c>=10?c+'A'-10:c+'0')
-
-void open_mime(nkf_char mode)
-{
- const unsigned char *p;
- int i;
- int j;
- p = mime_pattern[0];
- for(i=0;mime_encode[i];i++) {
- if (mode == mime_encode[i]) {
- p = mime_pattern[i];
- break;
- }
- }
- mimeout_mode = mime_encode_method[i];
-
- i = 0;
- if (base64_count>45) {
- if (mimeout_buf_count>0 && nkf_isblank(mimeout_buf[i])){
- (*o_mputc)(mimeout_buf[i]);
- i++;
- }
- (*o_mputc)(NL);
- (*o_mputc)(SPACE);
- base64_count = 1;
- if (!mimeout_preserve_space && mimeout_buf_count>0
- && (mimeout_buf[i]==SPACE || mimeout_buf[i]==TAB
- || mimeout_buf[i]==CR || mimeout_buf[i]==NL )) {
- i++;
- }
- }
- if (!mimeout_preserve_space) {
- for (;i<mimeout_buf_count;i++) {
- if (mimeout_buf[i]==SPACE || mimeout_buf[i]==TAB
- || mimeout_buf[i]==CR || mimeout_buf[i]==NL ) {
- (*o_mputc)(mimeout_buf[i]);
- base64_count ++;
- } else {
- break;
- }
- }
- }
- mimeout_preserve_space = FALSE;
-
- while(*p) {
- (*o_mputc)(*p++);
- base64_count ++;
- }
- j = mimeout_buf_count;
- mimeout_buf_count = 0;
- for (;i<j;i++) {
- mime_putc(mimeout_buf[i]);
- }
-}
-
-void close_mime(void)
-{
- (*o_mputc)('?');
- (*o_mputc)('=');
- base64_count += 2;
- mimeout_mode = 0;
-}
-
-void eof_mime(void)
-{
- switch(mimeout_mode) {
- case 'Q':
- case 'B':
- break;
- case 2:
- (*o_mputc)(basis_64[((b64c & 0x3)<< 4)]);
- (*o_mputc)('=');
- (*o_mputc)('=');
- base64_count += 3;
- break;
- case 1:
- (*o_mputc)(basis_64[((b64c & 0xF) << 2)]);
- (*o_mputc)('=');
- base64_count += 2;
- break;
- }
- if (mimeout_mode) {
- if (mimeout_f!=FIXED_MIME) {
- close_mime();
- } else if (mimeout_mode != 'Q')
- mimeout_mode = 'B';
- }
-}
-
-void mimeout_addchar(nkf_char c)
-{
- switch(mimeout_mode) {
- case 'Q':
- if (c==CR||c==NL) {
- (*o_mputc)(c);
- base64_count = 0;
- } else if(!nkf_isalnum(c)) {
- (*o_mputc)('=');
- (*o_mputc)(itoh4(((c>>4)&0xf)));
- (*o_mputc)(itoh4((c&0xf)));
- base64_count += 3;
- } else {
- (*o_mputc)(c);
- base64_count++;
- }
- break;
- case 'B':
- b64c=c;
- (*o_mputc)(basis_64[c>>2]);
- mimeout_mode=2;
- base64_count ++;
- break;
- case 2:
- (*o_mputc)(basis_64[((b64c & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
- b64c=c;
- mimeout_mode=1;
- base64_count ++;
- break;
- case 1:
- (*o_mputc)(basis_64[((b64c & 0xF) << 2) | ((c & 0xC0) >>6)]);
- (*o_mputc)(basis_64[c & 0x3F]);
- mimeout_mode='B';
- base64_count += 2;
- break;
- default:
- (*o_mputc)(c);
- base64_count++;
- break;
- }
-}
-
-nkf_char mime_lastchar2, mime_lastchar1;
-
-void mime_prechar(nkf_char c2, nkf_char c1)
-{
- if (mimeout_mode){
- if (c2){
- if (base64_count + mimeout_buf_count/3*4> 66){
- (*o_base64conv)(EOF,0);
- (*o_base64conv)(0,NL);
- (*o_base64conv)(0,SPACE);
- }
- }/*else if (mime_lastchar2){
- if (c1 <=DEL && !nkf_isspace(c1)){
- (*o_base64conv)(0,SPACE);
- }
- }*/
- }/*else{
- if (c2 && mime_lastchar2 == 0
- && mime_lastchar1 && !nkf_isspace(mime_lastchar1)){
- (*o_base64conv)(0,SPACE);
- }
- }*/
- mime_lastchar2 = c2;
- mime_lastchar1 = c1;
-}
-
-void mime_putc(nkf_char c)
-{
- int i, j;
- nkf_char lastchar;
-
- if (mimeout_f == FIXED_MIME){
- if (mimeout_mode == 'Q'){
- if (base64_count > 71){
- if (c!=CR && c!=NL) {
- (*o_mputc)('=');
- (*o_mputc)(NL);
- }
- base64_count = 0;
- }
- }else{
- if (base64_count > 71){
- eof_mime();
- (*o_mputc)(NL);
- base64_count = 0;
- }
- if (c == EOF) { /* c==EOF */
- eof_mime();
- }
- }
- if (c != EOF) { /* c==EOF */
- mimeout_addchar(c);
- }
- return;
- }
-
- /* mimeout_f != FIXED_MIME */
-
- if (c == EOF) { /* c==EOF */
- j = mimeout_buf_count;
- mimeout_buf_count = 0;
- i = 0;
- if (mimeout_mode) {
- for (;i<j;i++) {
- if (nkf_isspace(mimeout_buf[i]) && base64_count < 71){
- break;
- }
- mimeout_addchar(mimeout_buf[i]);
- }
- eof_mime();
- for (;i<j;i++) {
- mimeout_addchar(mimeout_buf[i]);
- }
- } else {
- for (;i<j;i++) {
- mimeout_addchar(mimeout_buf[i]);
- }
- }
- return;
- }
-
- if (mimeout_mode=='Q') {
- if (c <= DEL && (output_mode==ASCII ||output_mode == ISO8859_1 ) ) {
- if (c <= SPACE) {
- close_mime();
- (*o_mputc)(SPACE);
- base64_count++;
- }
- (*o_mputc)(c);
- base64_count++;
- }
- return;
- }
-
- if (mimeout_buf_count > 0){
- lastchar = mimeout_buf[mimeout_buf_count - 1];
- }else{
- lastchar = -1;
- }
-
- if (!mimeout_mode) {
- if (c <= DEL && (output_mode==ASCII ||output_mode == ISO8859_1)) {
- if (nkf_isspace(c)) {
- if (c==CR || c==NL) {
- base64_count=0;
- }
- for (i=0;i<mimeout_buf_count;i++) {
- (*o_mputc)(mimeout_buf[i]);
- if (mimeout_buf[i] == CR || mimeout_buf[i] == NL){
- base64_count = 0;
- }else{
- base64_count++;
- }
- }
- mimeout_buf[0] = (char)c;
- mimeout_buf_count = 1;
- }else{
- if (base64_count > 1
- && base64_count + mimeout_buf_count > 76){
- (*o_mputc)(NL);
- base64_count = 0;
- if (!nkf_isspace(mimeout_buf[0])){
- (*o_mputc)(SPACE);
- base64_count++;
- }
- }
- mimeout_buf[mimeout_buf_count++] = (char)c;
- if (mimeout_buf_count>MIMEOUT_BUF_LENGTH) {
- open_mime(output_mode);
- }
- }
- return;
- }else{
- if (lastchar==CR || lastchar == NL){
- for (i=0;i<mimeout_buf_count;i++) {
- (*o_mputc)(mimeout_buf[i]);
- }
- base64_count = 0;
- mimeout_buf_count = 0;
- }
- if (lastchar==SPACE) {
- for (i=0;i<mimeout_buf_count-1;i++) {
- (*o_mputc)(mimeout_buf[i]);
- base64_count++;
- }
- mimeout_buf[0] = SPACE;
- mimeout_buf_count = 1;
- }
- open_mime(output_mode);
- }
- }else{
- /* mimeout_mode == 'B', 1, 2 */
- if ( c<=DEL && (output_mode==ASCII ||output_mode == ISO8859_1 ) ) {
- if (lastchar == CR || lastchar == NL){
- if (nkf_isblank(c)) {
- for (i=0;i<mimeout_buf_count;i++) {
- mimeout_addchar(mimeout_buf[i]);
- }
- mimeout_buf_count = 0;
- } else if (SPACE<c && c<DEL) {
- eof_mime();
- for (i=0;i<mimeout_buf_count;i++) {
- (*o_mputc)(mimeout_buf[i]);
- }
- base64_count = 0;
- mimeout_buf_count = 0;
- }
- }
- if (c==SPACE || c==TAB || c==CR || c==NL) {
- for (i=0;i<mimeout_buf_count;i++) {
- if (SPACE<mimeout_buf[i] && mimeout_buf[i]<DEL) {
- eof_mime();
- for (i=0;i<mimeout_buf_count;i++) {
- (*o_mputc)(mimeout_buf[i]);
- base64_count++;
- }
- mimeout_buf_count = 0;
- }
- }
- mimeout_buf[mimeout_buf_count++] = (char)c;
- if (mimeout_buf_count>MIMEOUT_BUF_LENGTH) {
- eof_mime();
- for (i=0;i<mimeout_buf_count;i++) {
- (*o_mputc)(mimeout_buf[i]);
- base64_count++;
- }
- mimeout_buf_count = 0;
- }
- return;
- }
- if (mimeout_buf_count>0 && SPACE<c && c!='=') {
- mimeout_buf[mimeout_buf_count++] = (char)c;
- if (mimeout_buf_count>MIMEOUT_BUF_LENGTH) {
- j = mimeout_buf_count;
- mimeout_buf_count = 0;
- for (i=0;i<j;i++) {
- mimeout_addchar(mimeout_buf[i]);
- }
- }
- return;
- }
- }
- }
- if (mimeout_buf_count>0) {
- j = mimeout_buf_count;
- mimeout_buf_count = 0;
- for (i=0;i<j;i++) {
- if (mimeout_buf[i]==CR || mimeout_buf[i]==NL)
- break;
- mimeout_addchar(mimeout_buf[i]);
- }
- if (i<j) {
- eof_mime();
- base64_count=0;
- for (;i<j;i++) {
- (*o_mputc)(mimeout_buf[i]);
- }
- open_mime(output_mode);
- }
- }
- mimeout_addchar(c);
-}
-
-
-#if defined(PERL_XS) || defined(WIN32DLL)
-void reinit(void)
-{
- {
- struct input_code *p = input_code_list;
- while (p->name){
- status_reinit(p++);
- }
- }
- unbuf_f = FALSE;
- estab_f = FALSE;
- nop_f = FALSE;
- binmode_f = TRUE;
- rot_f = FALSE;
- hira_f = FALSE;
- input_f = FALSE;
- alpha_f = FALSE;
- mime_f = STRICT_MIME;
- mime_decode_f = FALSE;
- mimebuf_f = FALSE;
- broken_f = FALSE;
- iso8859_f = FALSE;
- mimeout_f = FALSE;
-#if defined(MSDOS) || defined(__OS2__)
- x0201_f = TRUE;
-#else
- x0201_f = NO_X0201;
-#endif
- iso2022jp_f = FALSE;
-#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
- ms_ucs_map_f = UCS_MAP_ASCII;
-#endif
-#ifdef UTF8_INPUT_ENABLE
- no_cp932ext_f = FALSE;
- ignore_zwnbsp_f = TRUE;
- no_best_fit_chars_f = FALSE;
- encode_fallback = NULL;
- unicode_subchar = '?';
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- unicode_bom_f = 0;
- w_oconv16_LE = 0;
-#endif
-#ifdef UNICODE_NORMALIZATION
- nfc_f = FALSE;
-#endif
-#ifdef INPUT_OPTION
- cap_f = FALSE;
- url_f = FALSE;
- numchar_f = FALSE;
-#endif
-#ifdef CHECK_OPTION
- noout_f = FALSE;
- debug_f = FALSE;
-#endif
- guess_f = FALSE;
- is_inputcode_mixed = FALSE;
- is_inputcode_set = FALSE;
-#ifdef EXEC_IO
- exec_f = 0;
-#endif
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
- cp932inv_f = TRUE;
-#endif
-#ifdef X0212_ENABLE
- x0212_f = FALSE;
- x0213_f = FALSE;
-#endif
- {
- int i;
- for (i = 0; i < 256; i++){
- prefix_table[i] = 0;
- }
- }
-#ifdef UTF8_INPUT_ENABLE
- utf16_mode = UTF16BE_INPUT;
-#endif
- mimeout_buf_count = 0;
- mimeout_mode = 0;
- base64_count = 0;
- f_line = 0;
- f_prev = 0;
- fold_preserve_f = FALSE;
- fold_f = FALSE;
- fold_len = 0;
- kanji_intro = DEFAULT_J;
- ascii_intro = DEFAULT_R;
- fold_margin = FOLD_MARGIN;
- output_conv = DEFAULT_CONV;
- oconv = DEFAULT_CONV;
- o_zconv = no_connection;
- o_fconv = no_connection;
- o_crconv = no_connection;
- o_rot_conv = no_connection;
- o_hira_conv = no_connection;
- o_base64conv = no_connection;
- o_iso2022jp_check_conv = no_connection;
- o_putc = std_putc;
- i_getc = std_getc;
- i_ungetc = std_ungetc;
- i_bgetc = std_getc;
- i_bungetc = std_ungetc;
- o_mputc = std_putc;
- i_mgetc = std_getc;
- i_mungetc = std_ungetc;
- i_mgetc_buf = std_getc;
- i_mungetc_buf = std_ungetc;
- output_mode = ASCII;
- input_mode = ASCII;
- shift_mode = FALSE;
- mime_decode_mode = FALSE;
- file_out_f = FALSE;
- crmode_f = 0;
- option_mode = 0;
- broken_counter = 0;
- broken_last = 0;
- z_prev2=0,z_prev1=0;
-#ifdef CHECK_OPTION
- iconv_for_check = 0;
-#endif
- input_codename = "";
-#ifdef WIN32DLL
- reinitdll();
-#endif /*WIN32DLL*/
-}
-#endif
-
-void no_connection(nkf_char c2, nkf_char c1)
-{
- no_connection2(c2,c1,0);
-}
-
-nkf_char no_connection2(nkf_char c2, nkf_char c1, nkf_char c0)
-{
- fprintf(stderr,"nkf internal module connection failure.\n");
- exit(1);
- return 0; /* LINT */
-}
-
-#ifndef PERL_XS
-#ifdef WIN32DLL
-#define fprintf dllprintf
-#endif
-void usage(void)
-{
- fprintf(stderr,"USAGE: nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");
- fprintf(stderr,"Flags:\n");
- fprintf(stderr,"b,u Output is buffered (DEFAULT),Output is unbuffered\n");
-#ifdef DEFAULT_CODE_SJIS
- fprintf(stderr,"j,s,e,w Outout code is JIS 7 bit, Shift_JIS (DEFAULT), EUC-JP, UTF-8N\n");
-#endif
-#ifdef DEFAULT_CODE_JIS
- fprintf(stderr,"j,s,e,w Outout code is JIS 7 bit (DEFAULT), Shift JIS, EUC-JP, UTF-8N\n");
-#endif
-#ifdef DEFAULT_CODE_EUC
- fprintf(stderr,"j,s,e,w Outout code is JIS 7 bit, Shift JIS, EUC-JP (DEFAULT), UTF-8N\n");
-#endif
-#ifdef DEFAULT_CODE_UTF8
- fprintf(stderr,"j,s,e,w Outout code is JIS 7 bit, Shift JIS, EUC-JP, UTF-8N (DEFAULT)\n");
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- fprintf(stderr," After 'w' you can add more options. -w[ 8 [0], 16 [[BL] [0]] ]\n");
-#endif
- fprintf(stderr,"J,S,E,W Input assumption is JIS 7 bit , Shift JIS, EUC-JP, UTF-8\n");
-#ifdef UTF8_INPUT_ENABLE
- fprintf(stderr," After 'W' you can add more options. -W[ 8, 16 [BL] ] \n");
-#endif
- fprintf(stderr,"t no conversion\n");
- fprintf(stderr,"i[@B] Specify the Esc Seq for JIS X 0208-1978/83 (DEFAULT B)\n");
- fprintf(stderr,"o[BJH] Specify the Esc Seq for ASCII/Roman (DEFAULT B)\n");
- fprintf(stderr,"r {de/en}crypt ROT13/47\n");
- fprintf(stderr,"h 1 katakana->hiragana, 2 hiragana->katakana, 3 both\n");
- fprintf(stderr,"v Show this usage. V: show version\n");
- fprintf(stderr,"m[BQN0] MIME decode [B:base64,Q:quoted,N:non-strict,0:no decode]\n");
- fprintf(stderr,"M[BQ] MIME encode [B:base64 Q:quoted]\n");
- fprintf(stderr,"l ISO8859-1 (Latin-1) support\n");
- fprintf(stderr,"f/F Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n");
- fprintf(stderr,"Z[0-3] Convert X0208 alphabet to ASCII\n");
- fprintf(stderr," 1: Kankaku to 1 space 2: to 2 spaces 3: Convert to HTML Entity\n");
- fprintf(stderr,"X,x Assume X0201 kana in MS-Kanji, -x preserves X0201\n");
- fprintf(stderr,"B[0-2] Broken input 0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");
-#ifdef MSDOS
- fprintf(stderr,"T Text mode output\n");
-#endif
- fprintf(stderr,"O Output to File (DEFAULT 'nkf.out')\n");
- fprintf(stderr,"I Convert non ISO-2022-JP charactor to GETA\n");
- fprintf(stderr,"d,c Convert line breaks -d: LF -c: CRLF\n");
- fprintf(stderr,"-L[uwm] line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n");
- fprintf(stderr,"\n");
- fprintf(stderr,"Long name options\n");
- fprintf(stderr," --ic=<input codeset> --oc=<output codeset>\n");
- fprintf(stderr," Specify the input or output codeset\n");
- fprintf(stderr," --fj --unix --mac --windows\n");
- fprintf(stderr," --jis --euc --sjis --utf8 --utf16 --mime --base64\n");
- fprintf(stderr," Convert for the system or code\n");
- fprintf(stderr," --hiragana --katakana --katakana-hiragana\n");
- fprintf(stderr," To Hiragana/Katakana Conversion\n");
- fprintf(stderr," --prefix= Insert escape before troublesome characters of Shift_JIS\n");
-#ifdef INPUT_OPTION
- fprintf(stderr," --cap-input, --url-input Convert hex after ':' or '%%'\n");
-#endif
-#ifdef NUMCHAR_OPTION
- fprintf(stderr," --numchar-input Convert Unicode Character Reference\n");
-#endif
-#ifdef UTF8_INPUT_ENABLE
- fprintf(stderr," --fb-{skip, html, xml, perl, java, subchar}\n");
- fprintf(stderr," Specify how nkf handles unassigned characters\n");
-#endif
-#ifdef OVERWRITE
- fprintf(stderr," --in-place[=SUFFIX] --overwrite[=SUFFIX]\n");
- fprintf(stderr," Overwrite original listed files by filtered result\n");
- fprintf(stderr," --overwrite preserves timestamp of original files\n");
-#endif
- fprintf(stderr," -g --guess Guess the input code\n");
- fprintf(stderr," --help --version Show this help/the version\n");
- fprintf(stderr," For more information, see also man nkf\n");
- fprintf(stderr,"\n");
- version();
-}
-
-void version(void)
-{
- fprintf(stderr,"Network Kanji Filter Version %s (%s) "
-#if defined(MSDOS) && !defined(__WIN32__) && !defined(__WIN16__) && !defined(__OS2__)
- "for DOS"
-#endif
-#if defined(MSDOS) && defined(__WIN16__)
- "for Win16"
-#endif
-#if defined(MSDOS) && defined(__WIN32__)
- "for Win32"
-#endif
-#ifdef __OS2__
- "for OS/2"
-#endif
- ,NKF_VERSION,NKF_RELEASE_DATE);
- fprintf(stderr,"\n%s\n",CopyRight);
-}
-#endif /*PERL_XS*/
-
-/**
- ** $B%Q%C%A@):n<T(B
- ** void@merope.pleiades.or.jp (Kusakabe Youichi)
- ** NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
- ** ohta@src.ricoh.co.jp (Junn Ohta)
- ** inouet@strl.nhk.or.jp (Tomoyuki Inoue)
- ** kiri@pulser.win.or.jp (Tetsuaki Kiriyama)
- ** Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp>
- ** a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
- ** kono@ie.u-ryukyu.ac.jp (Shinji Kono)
- ** GHG00637@nifty-serve.or.jp (COW)
- **
- **/
-
-/* end */
diff --git a/ext/nkf/nkf-utf8/utf8tbl.c b/ext/nkf/nkf-utf8/utf8tbl.c
deleted file mode 100644
index 9e59956a0a..0000000000
--- a/ext/nkf/nkf-utf8/utf8tbl.c
+++ /dev/null
@@ -1,8500 +0,0 @@
-#include "config.h"
-
-#ifdef UTF8_OUTPUT_ENABLE
-const unsigned short euc_to_utf8_A1[] = {
- 0x3000, 0x3001, 0x3002, 0xFF0C, 0xFF0E, 0x30FB, 0xFF1A,
- 0xFF1B, 0xFF1F, 0xFF01, 0x309B, 0x309C, 0x00B4, 0xFF40, 0x00A8,
- 0xFF3E, 0x203E, 0xFF3F, 0x30FD, 0x30FE, 0x309D, 0x309E, 0x3003,
- 0x4EDD, 0x3005, 0x3006, 0x3007, 0x30FC, 0x2014, 0x2010, 0xFF0F,
- 0xFF3C, 0x301C, 0x2016, 0xFF5C, 0x2026, 0x2025, 0x2018, 0x2019,
- 0x201C, 0x201D, 0xFF08, 0xFF09, 0x3014, 0x3015, 0xFF3B, 0xFF3D,
- 0xFF5B, 0xFF5D, 0x3008, 0x3009, 0x300A, 0x300B, 0x300C, 0x300D,
- 0x300E, 0x300F, 0x3010, 0x3011, 0xFF0B, 0x2212, 0x00B1, 0x00D7,
- 0x00F7, 0xFF1D, 0x2260, 0xFF1C, 0xFF1E, 0x2266, 0x2267, 0x221E,
- 0x2234, 0x2642, 0x2640, 0x00B0, 0x2032, 0x2033, 0x2103, 0x00A5,
- 0xFF04, 0x00A2, 0x00A3, 0xFF05, 0xFF03, 0xFF06, 0xFF0A, 0xFF20,
- 0x00A7, 0x2606, 0x2605, 0x25CB, 0x25CF, 0x25CE, 0x25C7,
-};
-
-/* Microsoft UCS Mapping Compatible */
-const unsigned short euc_to_utf8_A1_ms[] = {
- 0x3000, 0x3001, 0x3002, 0xFF0C, 0xFF0E, 0x30FB, 0xFF1A,
- 0xFF1B, 0xFF1F, 0xFF01, 0x309B, 0x309C, 0x00B4, 0xFF40, 0x00A8,
- 0xFF3E, 0xFFE3, 0xFF3F, 0x30FD, 0x30FE, 0x309D, 0x309E, 0x3003,
- 0x4EDD, 0x3005, 0x3006, 0x3007, 0x30FC, 0x2015, 0x2010, 0xFF0F,
- 0xFF3C, 0xFF5E, 0x2225, 0xFF5C, 0x2026, 0x2025, 0x2018, 0x2019,
- 0x201C, 0x201D, 0xFF08, 0xFF09, 0x3014, 0x3015, 0xFF3B, 0xFF3D,
- 0xFF5B, 0xFF5D, 0x3008, 0x3009, 0x300A, 0x300B, 0x300C, 0x300D,
- 0x300E, 0x300F, 0x3010, 0x3011, 0xFF0B, 0xFF0D, 0x00B1, 0x00D7,
- 0x00F7, 0xFF1D, 0x2260, 0xFF1C, 0xFF1E, 0x2266, 0x2267, 0x221E,
- 0x2234, 0x2642, 0x2640, 0x00B0, 0x2032, 0x2033, 0x2103, 0xFFE5,
- 0xFF04, 0xFFE0, 0xFFE1, 0xFF05, 0xFF03, 0xFF06, 0xFF0A, 0xFF20,
- 0x00A7, 0x2606, 0x2605, 0x25CB, 0x25CF, 0x25CE, 0x25C7,
-};
-const unsigned short euc_to_utf8_A2[] = {
- 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC,
- 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283,
- 0x222A, 0x2229, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2227, 0x2228, 0x00AC, 0x21D2, 0x21D4, 0x2200,
- 0x2203, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2220, 0x22A5, 0x2312, 0x2202,
- 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D,
- 0x2235, 0x222B, 0x222C, 0, 0, 0, 0, 0,
- 0, 0, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020,
- 0x2021, 0x00B6, 0, 0, 0, 0, 0x25EF,
-};
-
-/* Microsoft UCS Mapping Compatible */
-const unsigned short euc_to_utf8_A2_ms[] = {
- 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC,
- 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283,
- 0x222A, 0x2229, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2227, 0x2228, 0xFFE2, 0x21D2, 0x21D4, 0x2200,
- 0x2203, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2220, 0x22A5, 0x2312, 0x2202,
- 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D,
- 0x2235, 0x222B, 0x222C, 0, 0, 0, 0, 0,
- 0, 0, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020,
- 0x2021, 0x00B6, 0, 0, 0, 0, 0x25EF,
-};
-const unsigned short euc_to_utf8_A3[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
- 0xFF18, 0xFF19, 0, 0, 0, 0, 0, 0,
- 0, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27,
- 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F,
- 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37,
- 0xFF38, 0xFF39, 0xFF3A, 0, 0, 0, 0, 0,
- 0, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
- 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
- 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
- 0xFF58, 0xFF59, 0xFF5A, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_A4[] = {
- 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047,
- 0x3048, 0x3049, 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F,
- 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057,
- 0x3058, 0x3059, 0x305A, 0x305B, 0x305C, 0x305D, 0x305E, 0x305F,
- 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067,
- 0x3068, 0x3069, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F,
- 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077,
- 0x3078, 0x3079, 0x307A, 0x307B, 0x307C, 0x307D, 0x307E, 0x307F,
- 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087,
- 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308E, 0x308F,
- 0x3090, 0x3091, 0x3092, 0x3093, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_A5[] = {
- 0x30A1, 0x30A2, 0x30A3, 0x30A4, 0x30A5, 0x30A6, 0x30A7,
- 0x30A8, 0x30A9, 0x30AA, 0x30AB, 0x30AC, 0x30AD, 0x30AE, 0x30AF,
- 0x30B0, 0x30B1, 0x30B2, 0x30B3, 0x30B4, 0x30B5, 0x30B6, 0x30B7,
- 0x30B8, 0x30B9, 0x30BA, 0x30BB, 0x30BC, 0x30BD, 0x30BE, 0x30BF,
- 0x30C0, 0x30C1, 0x30C2, 0x30C3, 0x30C4, 0x30C5, 0x30C6, 0x30C7,
- 0x30C8, 0x30C9, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF,
- 0x30D0, 0x30D1, 0x30D2, 0x30D3, 0x30D4, 0x30D5, 0x30D6, 0x30D7,
- 0x30D8, 0x30D9, 0x30DA, 0x30DB, 0x30DC, 0x30DD, 0x30DE, 0x30DF,
- 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7,
- 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF,
- 0x30F0, 0x30F1, 0x30F2, 0x30F3, 0x30F4, 0x30F5, 0x30F6, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_A6[] = {
- 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
- 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
- 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8,
- 0x03A9, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
- 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
- 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
- 0x03C9, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_A7[] = {
- 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401,
- 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D,
- 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
- 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D,
- 0x042E, 0x042F, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451,
- 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D,
- 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
- 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D,
- 0x044E, 0x044F, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_A8[] = {
- 0x2500, 0x2502, 0x250C, 0x2510, 0x2518, 0x2514, 0x251C,
- 0x252C, 0x2524, 0x2534, 0x253C, 0x2501, 0x2503, 0x250F, 0x2513,
- 0x251B, 0x2517, 0x2523, 0x2533, 0x252B, 0x253B, 0x254B, 0x2520,
- 0x252F, 0x2528, 0x2537, 0x253F, 0x251D, 0x2530, 0x2525, 0x2538,
- 0x2542, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_A9[] = {
- 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466,
- 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E,
- 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x2474,
- 0x2475, 0x2476, 0x2477, 0x2478, 0x2479, 0x247A, 0x247B, 0x247C,
- 0x247D, 0x247E, 0x247F, 0x2480, 0x2481, 0x2482, 0x2483, 0x2484,
- 0x2485, 0x2486, 0x2487, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2776, 0x2777, 0x2778,
- 0x2779, 0x277A, 0x277B, 0x277C, 0x277D, 0x277E, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2488, 0x2489, 0x248A, 0x248B, 0x248C, 0x248D,
- 0x248E, 0x248F, 0x2490, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_AA[] = {
- 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166,
- 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2170, 0x2171, 0x2172,
- 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A,
- 0x217B, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x249C, 0x249D, 0x249E,
- 0x249F, 0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6,
- 0x24A7, 0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE,
- 0x24AF, 0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_AB[] = {
- 0x339C, 0x339F, 0x339D, 0x33A0, 0x33A4, 0, 0x33A1,
- 0x33A5, 0x339E, 0x33A2, 0x338E, 0, 0x338F, 0x33C4, 0x3396,
- 0x3397, 0x2113, 0x3398, 0x33B3, 0x33B2, 0x33B1, 0x33B0, 0x2109,
- 0x33D4, 0x33CB, 0x3390, 0x3385, 0x3386, 0x3387, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2116, 0x33CD, 0x2121, 0,
-};
-const unsigned short euc_to_utf8_AC[] = {
- 0x2664, 0x2667, 0x2661, 0x2662, 0x2660, 0x2663, 0x2665,
- 0x2666, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x3020, 0x260E, 0x3004,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x261E, 0x261C, 0x261D, 0x261F, 0x21C6, 0x21C4, 0x21C5,
- 0, 0x21E8, 0x21E6, 0x21E7, 0x21E9, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_AD[] = {
- 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466,
- 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E,
- 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0x2160, 0x2161, 0x2162,
- 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0,
- 0x3349, 0x3314, 0x3322, 0x334D, 0x3318, 0x3327, 0x3303, 0x3336,
- 0x3351, 0x3357, 0x330D, 0x3326, 0x3323, 0x332B, 0x334A, 0x333B,
- 0x339C, 0x339D, 0x339E, 0x338E, 0x338F, 0x33C4, 0x33A1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x337B,
- 0x301D, 0x301F, 0x2116, 0x33CD, 0x2121, 0x32A4, 0x32A5, 0x32A6,
- 0x32A7, 0x32A8, 0x3231, 0x3232, 0x3239, 0x337E, 0x337D, 0x337C,
- 0x2252, 0x2261, 0x222B, 0x222E, 0x2211, 0x221A, 0x22A5, 0x2220,
- 0x221F, 0x22BF, 0x2235, 0x2229, 0x222A, 0, 0x3299,
-};
-const unsigned short euc_to_utf8_AE[] = {
- 0x3349, 0x3322, 0x334D, 0x3314, 0x3316, 0x3305, 0x3333,
- 0x334E, 0x3303, 0x3336, 0x3318, 0x3315, 0x3327, 0x3351, 0x334A,
- 0x3339, 0x3357, 0x330D, 0x3342, 0x3323, 0x3326, 0x333B, 0x332B,
- 0, 0, 0, 0, 0, 0, 0, 0x3300,
- 0x331E, 0x332A, 0x3331, 0x3347, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x337E,
- 0x337D, 0x337C, 0x337B, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x337F, 0, 0,
-};
-const unsigned short euc_to_utf8_AF[] = {
- 0x222E, 0x221F, 0x22BF, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x301D, 0x301F, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x3094, 0, 0x30F7, 0x30F8, 0x30F9, 0x30FA, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_B0[] = {
- 0x4E9C, 0x5516, 0x5A03, 0x963F, 0x54C0, 0x611B, 0x6328,
- 0x59F6, 0x9022, 0x8475, 0x831C, 0x7A50, 0x60AA, 0x63E1, 0x6E25,
- 0x65ED, 0x8466, 0x82A6, 0x9BF5, 0x6893, 0x5727, 0x65A1, 0x6271,
- 0x5B9B, 0x59D0, 0x867B, 0x98F4, 0x7D62, 0x7DBE, 0x9B8E, 0x6216,
- 0x7C9F, 0x88B7, 0x5B89, 0x5EB5, 0x6309, 0x6697, 0x6848, 0x95C7,
- 0x978D, 0x674F, 0x4EE5, 0x4F0A, 0x4F4D, 0x4F9D, 0x5049, 0x56F2,
- 0x5937, 0x59D4, 0x5A01, 0x5C09, 0x60DF, 0x610F, 0x6170, 0x6613,
- 0x6905, 0x70BA, 0x754F, 0x7570, 0x79FB, 0x7DAD, 0x7DEF, 0x80C3,
- 0x840E, 0x8863, 0x8B02, 0x9055, 0x907A, 0x533B, 0x4E95, 0x4EA5,
- 0x57DF, 0x80B2, 0x90C1, 0x78EF, 0x4E00, 0x58F1, 0x6EA2, 0x9038,
- 0x7A32, 0x8328, 0x828B, 0x9C2F, 0x5141, 0x5370, 0x54BD, 0x54E1,
- 0x56E0, 0x59FB, 0x5F15, 0x98F2, 0x6DEB, 0x80E4, 0x852D,
-};
-const unsigned short euc_to_utf8_B1[] = {
- 0x9662, 0x9670, 0x96A0, 0x97FB, 0x540B, 0x53F3, 0x5B87,
- 0x70CF, 0x7FBD, 0x8FC2, 0x96E8, 0x536F, 0x9D5C, 0x7ABA, 0x4E11,
- 0x7893, 0x81FC, 0x6E26, 0x5618, 0x5504, 0x6B1D, 0x851A, 0x9C3B,
- 0x59E5, 0x53A9, 0x6D66, 0x74DC, 0x958F, 0x5642, 0x4E91, 0x904B,
- 0x96F2, 0x834F, 0x990C, 0x53E1, 0x55B6, 0x5B30, 0x5F71, 0x6620,
- 0x66F3, 0x6804, 0x6C38, 0x6CF3, 0x6D29, 0x745B, 0x76C8, 0x7A4E,
- 0x9834, 0x82F1, 0x885B, 0x8A60, 0x92ED, 0x6DB2, 0x75AB, 0x76CA,
- 0x99C5, 0x60A6, 0x8B01, 0x8D8A, 0x95B2, 0x698E, 0x53AD, 0x5186,
- 0x5712, 0x5830, 0x5944, 0x5BB4, 0x5EF6, 0x6028, 0x63A9, 0x63F4,
- 0x6CBF, 0x6F14, 0x708E, 0x7114, 0x7159, 0x71D5, 0x733F, 0x7E01,
- 0x8276, 0x82D1, 0x8597, 0x9060, 0x925B, 0x9D1B, 0x5869, 0x65BC,
- 0x6C5A, 0x7525, 0x51F9, 0x592E, 0x5965, 0x5F80, 0x5FDC,
-};
-const unsigned short euc_to_utf8_B2[] = {
- 0x62BC, 0x65FA, 0x6A2A, 0x6B27, 0x6BB4, 0x738B, 0x7FC1,
- 0x8956, 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104,
- 0x5C4B, 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378,
- 0x6069, 0x6E29, 0x7A4F, 0x97F3, 0x4E0B, 0x5316, 0x4EEE, 0x4F55,
- 0x4F3D, 0x4FA1, 0x4F73, 0x52A0, 0x53EF, 0x5609, 0x590F, 0x5AC1,
- 0x5BB6, 0x5BE1, 0x79D1, 0x6687, 0x679C, 0x67B6, 0x6B4C, 0x6CB3,
- 0x706B, 0x73C2, 0x798D, 0x79BE, 0x7A3C, 0x7B87, 0x82B1, 0x82DB,
- 0x8304, 0x8377, 0x83EF, 0x83D3, 0x8766, 0x8AB2, 0x5629, 0x8CA8,
- 0x8FE6, 0x904E, 0x971E, 0x868A, 0x4FC4, 0x5CE8, 0x6211, 0x7259,
- 0x753B, 0x81E5, 0x82BD, 0x86FE, 0x8CC0, 0x96C5, 0x9913, 0x99D5,
- 0x4ECB, 0x4F1A, 0x89E3, 0x56DE, 0x584A, 0x58CA, 0x5EFB, 0x5FEB,
- 0x602A, 0x6094, 0x6062, 0x61D0, 0x6212, 0x62D0, 0x6539,
-};
-const unsigned short euc_to_utf8_B3[] = {
- 0x9B41, 0x6666, 0x68B0, 0x6D77, 0x7070, 0x754C, 0x7686,
- 0x7D75, 0x82A5, 0x87F9, 0x958B, 0x968E, 0x8C9D, 0x51F1, 0x52BE,
- 0x5916, 0x54B3, 0x5BB3, 0x5D16, 0x6168, 0x6982, 0x6DAF, 0x788D,
- 0x84CB, 0x8857, 0x8A72, 0x93A7, 0x9AB8, 0x6D6C, 0x99A8, 0x86D9,
- 0x57A3, 0x67FF, 0x86CE, 0x920E, 0x5283, 0x5687, 0x5404, 0x5ED3,
- 0x62E1, 0x64B9, 0x683C, 0x6838, 0x6BBB, 0x7372, 0x78BA, 0x7A6B,
- 0x899A, 0x89D2, 0x8D6B, 0x8F03, 0x90ED, 0x95A3, 0x9694, 0x9769,
- 0x5B66, 0x5CB3, 0x697D, 0x984D, 0x984E, 0x639B, 0x7B20, 0x6A2B,
- 0x6A7F, 0x68B6, 0x9C0D, 0x6F5F, 0x5272, 0x559D, 0x6070, 0x62EC,
- 0x6D3B, 0x6E07, 0x6ED1, 0x845B, 0x8910, 0x8F44, 0x4E14, 0x9C39,
- 0x53F6, 0x691B, 0x6A3A, 0x9784, 0x682A, 0x515C, 0x7AC3, 0x84B2,
- 0x91DC, 0x938C, 0x565B, 0x9D28, 0x6822, 0x8305, 0x8431,
-};
-const unsigned short euc_to_utf8_B4[] = {
- 0x7CA5, 0x5208, 0x82C5, 0x74E6, 0x4E7E, 0x4F83, 0x51A0,
- 0x5BD2, 0x520A, 0x52D8, 0x52E7, 0x5DFB, 0x559A, 0x582A, 0x59E6,
- 0x5B8C, 0x5B98, 0x5BDB, 0x5E72, 0x5E79, 0x60A3, 0x611F, 0x6163,
- 0x61BE, 0x63DB, 0x6562, 0x67D1, 0x6853, 0x68FA, 0x6B3E, 0x6B53,
- 0x6C57, 0x6F22, 0x6F97, 0x6F45, 0x74B0, 0x7518, 0x76E3, 0x770B,
- 0x7AFF, 0x7BA1, 0x7C21, 0x7DE9, 0x7F36, 0x7FF0, 0x809D, 0x8266,
- 0x839E, 0x89B3, 0x8ACC, 0x8CAB, 0x9084, 0x9451, 0x9593, 0x9591,
- 0x95A2, 0x9665, 0x97D3, 0x9928, 0x8218, 0x4E38, 0x542B, 0x5CB8,
- 0x5DCC, 0x73A9, 0x764C, 0x773C, 0x5CA9, 0x7FEB, 0x8D0B, 0x96C1,
- 0x9811, 0x9854, 0x9858, 0x4F01, 0x4F0E, 0x5371, 0x559C, 0x5668,
- 0x57FA, 0x5947, 0x5B09, 0x5BC4, 0x5C90, 0x5E0C, 0x5E7E, 0x5FCC,
- 0x63EE, 0x673A, 0x65D7, 0x65E2, 0x671F, 0x68CB, 0x68C4,
-};
-const unsigned short euc_to_utf8_B5[] = {
- 0x6A5F, 0x5E30, 0x6BC5, 0x6C17, 0x6C7D, 0x757F, 0x7948,
- 0x5B63, 0x7A00, 0x7D00, 0x5FBD, 0x898F, 0x8A18, 0x8CB4, 0x8D77,
- 0x8ECC, 0x8F1D, 0x98E2, 0x9A0E, 0x9B3C, 0x4E80, 0x507D, 0x5100,
- 0x5993, 0x5B9C, 0x622F, 0x6280, 0x64EC, 0x6B3A, 0x72A0, 0x7591,
- 0x7947, 0x7FA9, 0x87FB, 0x8ABC, 0x8B70, 0x63AC, 0x83CA, 0x97A0,
- 0x5409, 0x5403, 0x55AB, 0x6854, 0x6A58, 0x8A70, 0x7827, 0x6775,
- 0x9ECD, 0x5374, 0x5BA2, 0x811A, 0x8650, 0x9006, 0x4E18, 0x4E45,
- 0x4EC7, 0x4F11, 0x53CA, 0x5438, 0x5BAE, 0x5F13, 0x6025, 0x6551,
- 0x673D, 0x6C42, 0x6C72, 0x6CE3, 0x7078, 0x7403, 0x7A76, 0x7AAE,
- 0x7B08, 0x7D1A, 0x7CFE, 0x7D66, 0x65E7, 0x725B, 0x53BB, 0x5C45,
- 0x5DE8, 0x62D2, 0x62E0, 0x6319, 0x6E20, 0x865A, 0x8A31, 0x8DDD,
- 0x92F8, 0x6F01, 0x79A6, 0x9B5A, 0x4EA8, 0x4EAB, 0x4EAC,
-};
-const unsigned short euc_to_utf8_B6[] = {
- 0x4F9B, 0x4FA0, 0x50D1, 0x5147, 0x7AF6, 0x5171, 0x51F6,
- 0x5354, 0x5321, 0x537F, 0x53EB, 0x55AC, 0x5883, 0x5CE1, 0x5F37,
- 0x5F4A, 0x602F, 0x6050, 0x606D, 0x631F, 0x6559, 0x6A4B, 0x6CC1,
- 0x72C2, 0x72ED, 0x77EF, 0x80F8, 0x8105, 0x8208, 0x854E, 0x90F7,
- 0x93E1, 0x97FF, 0x9957, 0x9A5A, 0x4EF0, 0x51DD, 0x5C2D, 0x6681,
- 0x696D, 0x5C40, 0x66F2, 0x6975, 0x7389, 0x6850, 0x7C81, 0x50C5,
- 0x52E4, 0x5747, 0x5DFE, 0x9326, 0x65A4, 0x6B23, 0x6B3D, 0x7434,
- 0x7981, 0x79BD, 0x7B4B, 0x7DCA, 0x82B9, 0x83CC, 0x887F, 0x895F,
- 0x8B39, 0x8FD1, 0x91D1, 0x541F, 0x9280, 0x4E5D, 0x5036, 0x53E5,
- 0x533A, 0x72D7, 0x7396, 0x77E9, 0x82E6, 0x8EAF, 0x99C6, 0x99C8,
- 0x99D2, 0x5177, 0x611A, 0x865E, 0x55B0, 0x7A7A, 0x5076, 0x5BD3,
- 0x9047, 0x9685, 0x4E32, 0x6ADB, 0x91E7, 0x5C51, 0x5C48,
-};
-const unsigned short euc_to_utf8_B7[] = {
- 0x6398, 0x7A9F, 0x6C93, 0x9774, 0x8F61, 0x7AAA, 0x718A,
- 0x9688, 0x7C82, 0x6817, 0x7E70, 0x6851, 0x936C, 0x52F2, 0x541B,
- 0x85AB, 0x8A13, 0x7FA4, 0x8ECD, 0x90E1, 0x5366, 0x8888, 0x7941,
- 0x4FC2, 0x50BE, 0x5211, 0x5144, 0x5553, 0x572D, 0x73EA, 0x578B,
- 0x5951, 0x5F62, 0x5F84, 0x6075, 0x6176, 0x6167, 0x61A9, 0x63B2,
- 0x643A, 0x656C, 0x666F, 0x6842, 0x6E13, 0x7566, 0x7A3D, 0x7CFB,
- 0x7D4C, 0x7D99, 0x7E4B, 0x7F6B, 0x830E, 0x834A, 0x86CD, 0x8A08,
- 0x8A63, 0x8B66, 0x8EFD, 0x981A, 0x9D8F, 0x82B8, 0x8FCE, 0x9BE8,
- 0x5287, 0x621F, 0x6483, 0x6FC0, 0x9699, 0x6841, 0x5091, 0x6B20,
- 0x6C7A, 0x6F54, 0x7A74, 0x7D50, 0x8840, 0x8A23, 0x6708, 0x4EF6,
- 0x5039, 0x5026, 0x5065, 0x517C, 0x5238, 0x5263, 0x55A7, 0x570F,
- 0x5805, 0x5ACC, 0x5EFA, 0x61B2, 0x61F8, 0x62F3, 0x6372,
-};
-const unsigned short euc_to_utf8_B8[] = {
- 0x691C, 0x6A29, 0x727D, 0x72AC, 0x732E, 0x7814, 0x786F,
- 0x7D79, 0x770C, 0x80A9, 0x898B, 0x8B19, 0x8CE2, 0x8ED2, 0x9063,
- 0x9375, 0x967A, 0x9855, 0x9A13, 0x9E78, 0x5143, 0x539F, 0x53B3,
- 0x5E7B, 0x5F26, 0x6E1B, 0x6E90, 0x7384, 0x73FE, 0x7D43, 0x8237,
- 0x8A00, 0x8AFA, 0x9650, 0x4E4E, 0x500B, 0x53E4, 0x547C, 0x56FA,
- 0x59D1, 0x5B64, 0x5DF1, 0x5EAB, 0x5F27, 0x6238, 0x6545, 0x67AF,
- 0x6E56, 0x72D0, 0x7CCA, 0x88B4, 0x80A1, 0x80E1, 0x83F0, 0x864E,
- 0x8A87, 0x8DE8, 0x9237, 0x96C7, 0x9867, 0x9F13, 0x4E94, 0x4E92,
- 0x4F0D, 0x5348, 0x5449, 0x543E, 0x5A2F, 0x5F8C, 0x5FA1, 0x609F,
- 0x68A7, 0x6A8E, 0x745A, 0x7881, 0x8A9E, 0x8AA4, 0x8B77, 0x9190,
- 0x4E5E, 0x9BC9, 0x4EA4, 0x4F7C, 0x4FAF, 0x5019, 0x5016, 0x5149,
- 0x516C, 0x529F, 0x52B9, 0x52FE, 0x539A, 0x53E3, 0x5411,
-};
-const unsigned short euc_to_utf8_B9[] = {
- 0x540E, 0x5589, 0x5751, 0x57A2, 0x597D, 0x5B54, 0x5B5D,
- 0x5B8F, 0x5DE5, 0x5DE7, 0x5DF7, 0x5E78, 0x5E83, 0x5E9A, 0x5EB7,
- 0x5F18, 0x6052, 0x614C, 0x6297, 0x62D8, 0x63A7, 0x653B, 0x6602,
- 0x6643, 0x66F4, 0x676D, 0x6821, 0x6897, 0x69CB, 0x6C5F, 0x6D2A,
- 0x6D69, 0x6E2F, 0x6E9D, 0x7532, 0x7687, 0x786C, 0x7A3F, 0x7CE0,
- 0x7D05, 0x7D18, 0x7D5E, 0x7DB1, 0x8015, 0x8003, 0x80AF, 0x80B1,
- 0x8154, 0x818F, 0x822A, 0x8352, 0x884C, 0x8861, 0x8B1B, 0x8CA2,
- 0x8CFC, 0x90CA, 0x9175, 0x9271, 0x783F, 0x92FC, 0x95A4, 0x964D,
- 0x9805, 0x9999, 0x9AD8, 0x9D3B, 0x525B, 0x52AB, 0x53F7, 0x5408,
- 0x58D5, 0x62F7, 0x6FE0, 0x8C6A, 0x8F5F, 0x9EB9, 0x514B, 0x523B,
- 0x544A, 0x56FD, 0x7A40, 0x9177, 0x9D60, 0x9ED2, 0x7344, 0x6F09,
- 0x8170, 0x7511, 0x5FFD, 0x60DA, 0x9AA8, 0x72DB, 0x8FBC,
-};
-const unsigned short euc_to_utf8_BA[] = {
- 0x6B64, 0x9803, 0x4ECA, 0x56F0, 0x5764, 0x58BE, 0x5A5A,
- 0x6068, 0x61C7, 0x660F, 0x6606, 0x6839, 0x68B1, 0x6DF7, 0x75D5,
- 0x7D3A, 0x826E, 0x9B42, 0x4E9B, 0x4F50, 0x53C9, 0x5506, 0x5D6F,
- 0x5DE6, 0x5DEE, 0x67FB, 0x6C99, 0x7473, 0x7802, 0x8A50, 0x9396,
- 0x88DF, 0x5750, 0x5EA7, 0x632B, 0x50B5, 0x50AC, 0x518D, 0x6700,
- 0x54C9, 0x585E, 0x59BB, 0x5BB0, 0x5F69, 0x624D, 0x63A1, 0x683D,
- 0x6B73, 0x6E08, 0x707D, 0x91C7, 0x7280, 0x7815, 0x7826, 0x796D,
- 0x658E, 0x7D30, 0x83DC, 0x88C1, 0x8F09, 0x969B, 0x5264, 0x5728,
- 0x6750, 0x7F6A, 0x8CA1, 0x51B4, 0x5742, 0x962A, 0x583A, 0x698A,
- 0x80B4, 0x54B2, 0x5D0E, 0x57FC, 0x7895, 0x9DFA, 0x4F5C, 0x524A,
- 0x548B, 0x643E, 0x6628, 0x6714, 0x67F5, 0x7A84, 0x7B56, 0x7D22,
- 0x932F, 0x685C, 0x9BAD, 0x7B39, 0x5319, 0x518A, 0x5237,
-};
-const unsigned short euc_to_utf8_BB[] = {
- 0x5BDF, 0x62F6, 0x64AE, 0x64E6, 0x672D, 0x6BBA, 0x85A9,
- 0x96D1, 0x7690, 0x9BD6, 0x634C, 0x9306, 0x9BAB, 0x76BF, 0x6652,
- 0x4E09, 0x5098, 0x53C2, 0x5C71, 0x60E8, 0x6492, 0x6563, 0x685F,
- 0x71E6, 0x73CA, 0x7523, 0x7B97, 0x7E82, 0x8695, 0x8B83, 0x8CDB,
- 0x9178, 0x9910, 0x65AC, 0x66AB, 0x6B8B, 0x4ED5, 0x4ED4, 0x4F3A,
- 0x4F7F, 0x523A, 0x53F8, 0x53F2, 0x55E3, 0x56DB, 0x58EB, 0x59CB,
- 0x59C9, 0x59FF, 0x5B50, 0x5C4D, 0x5E02, 0x5E2B, 0x5FD7, 0x601D,
- 0x6307, 0x652F, 0x5B5C, 0x65AF, 0x65BD, 0x65E8, 0x679D, 0x6B62,
- 0x6B7B, 0x6C0F, 0x7345, 0x7949, 0x79C1, 0x7CF8, 0x7D19, 0x7D2B,
- 0x80A2, 0x8102, 0x81F3, 0x8996, 0x8A5E, 0x8A69, 0x8A66, 0x8A8C,
- 0x8AEE, 0x8CC7, 0x8CDC, 0x96CC, 0x98FC, 0x6B6F, 0x4E8B, 0x4F3C,
- 0x4F8D, 0x5150, 0x5B57, 0x5BFA, 0x6148, 0x6301, 0x6642,
-};
-const unsigned short euc_to_utf8_BC[] = {
- 0x6B21, 0x6ECB, 0x6CBB, 0x723E, 0x74BD, 0x75D4, 0x78C1,
- 0x793A, 0x800C, 0x8033, 0x81EA, 0x8494, 0x8F9E, 0x6C50, 0x9E7F,
- 0x5F0F, 0x8B58, 0x9D2B, 0x7AFA, 0x8EF8, 0x5B8D, 0x96EB, 0x4E03,
- 0x53F1, 0x57F7, 0x5931, 0x5AC9, 0x5BA4, 0x6089, 0x6E7F, 0x6F06,
- 0x75BE, 0x8CEA, 0x5B9F, 0x8500, 0x7BE0, 0x5072, 0x67F4, 0x829D,
- 0x5C61, 0x854A, 0x7E1E, 0x820E, 0x5199, 0x5C04, 0x6368, 0x8D66,
- 0x659C, 0x716E, 0x793E, 0x7D17, 0x8005, 0x8B1D, 0x8ECA, 0x906E,
- 0x86C7, 0x90AA, 0x501F, 0x52FA, 0x5C3A, 0x6753, 0x707C, 0x7235,
- 0x914C, 0x91C8, 0x932B, 0x82E5, 0x5BC2, 0x5F31, 0x60F9, 0x4E3B,
- 0x53D6, 0x5B88, 0x624B, 0x6731, 0x6B8A, 0x72E9, 0x73E0, 0x7A2E,
- 0x816B, 0x8DA3, 0x9152, 0x9996, 0x5112, 0x53D7, 0x546A, 0x5BFF,
- 0x6388, 0x6A39, 0x7DAC, 0x9700, 0x56DA, 0x53CE, 0x5468,
-};
-const unsigned short euc_to_utf8_BD[] = {
- 0x5B97, 0x5C31, 0x5DDE, 0x4FEE, 0x6101, 0x62FE, 0x6D32,
- 0x79C0, 0x79CB, 0x7D42, 0x7E4D, 0x7FD2, 0x81ED, 0x821F, 0x8490,
- 0x8846, 0x8972, 0x8B90, 0x8E74, 0x8F2F, 0x9031, 0x914B, 0x916C,
- 0x96C6, 0x919C, 0x4EC0, 0x4F4F, 0x5145, 0x5341, 0x5F93, 0x620E,
- 0x67D4, 0x6C41, 0x6E0B, 0x7363, 0x7E26, 0x91CD, 0x9283, 0x53D4,
- 0x5919, 0x5BBF, 0x6DD1, 0x795D, 0x7E2E, 0x7C9B, 0x587E, 0x719F,
- 0x51FA, 0x8853, 0x8FF0, 0x4FCA, 0x5CFB, 0x6625, 0x77AC, 0x7AE3,
- 0x821C, 0x99FF, 0x51C6, 0x5FAA, 0x65EC, 0x696F, 0x6B89, 0x6DF3,
- 0x6E96, 0x6F64, 0x76FE, 0x7D14, 0x5DE1, 0x9075, 0x9187, 0x9806,
- 0x51E6, 0x521D, 0x6240, 0x6691, 0x66D9, 0x6E1A, 0x5EB6, 0x7DD2,
- 0x7F72, 0x66F8, 0x85AF, 0x85F7, 0x8AF8, 0x52A9, 0x53D9, 0x5973,
- 0x5E8F, 0x5F90, 0x6055, 0x92E4, 0x9664, 0x50B7, 0x511F,
-};
-const unsigned short euc_to_utf8_BE[] = {
- 0x52DD, 0x5320, 0x5347, 0x53EC, 0x54E8, 0x5546, 0x5531,
- 0x5617, 0x5968, 0x59BE, 0x5A3C, 0x5BB5, 0x5C06, 0x5C0F, 0x5C11,
- 0x5C1A, 0x5E84, 0x5E8A, 0x5EE0, 0x5F70, 0x627F, 0x6284, 0x62DB,
- 0x638C, 0x6377, 0x6607, 0x660C, 0x662D, 0x6676, 0x677E, 0x68A2,
- 0x6A1F, 0x6A35, 0x6CBC, 0x6D88, 0x6E09, 0x6E58, 0x713C, 0x7126,
- 0x7167, 0x75C7, 0x7701, 0x785D, 0x7901, 0x7965, 0x79F0, 0x7AE0,
- 0x7B11, 0x7CA7, 0x7D39, 0x8096, 0x83D6, 0x848B, 0x8549, 0x885D,
- 0x88F3, 0x8A1F, 0x8A3C, 0x8A54, 0x8A73, 0x8C61, 0x8CDE, 0x91A4,
- 0x9266, 0x937E, 0x9418, 0x969C, 0x9798, 0x4E0A, 0x4E08, 0x4E1E,
- 0x4E57, 0x5197, 0x5270, 0x57CE, 0x5834, 0x58CC, 0x5B22, 0x5E38,
- 0x60C5, 0x64FE, 0x6761, 0x6756, 0x6D44, 0x72B6, 0x7573, 0x7A63,
- 0x84B8, 0x8B72, 0x91B8, 0x9320, 0x5631, 0x57F4, 0x98FE,
-};
-const unsigned short euc_to_utf8_BF[] = {
- 0x62ED, 0x690D, 0x6B96, 0x71ED, 0x7E54, 0x8077, 0x8272,
- 0x89E6, 0x98DF, 0x8755, 0x8FB1, 0x5C3B, 0x4F38, 0x4FE1, 0x4FB5,
- 0x5507, 0x5A20, 0x5BDD, 0x5BE9, 0x5FC3, 0x614E, 0x632F, 0x65B0,
- 0x664B, 0x68EE, 0x699B, 0x6D78, 0x6DF1, 0x7533, 0x75B9, 0x771F,
- 0x795E, 0x79E6, 0x7D33, 0x81E3, 0x82AF, 0x85AA, 0x89AA, 0x8A3A,
- 0x8EAB, 0x8F9B, 0x9032, 0x91DD, 0x9707, 0x4EBA, 0x4EC1, 0x5203,
- 0x5875, 0x58EC, 0x5C0B, 0x751A, 0x5C3D, 0x814E, 0x8A0A, 0x8FC5,
- 0x9663, 0x976D, 0x7B25, 0x8ACF, 0x9808, 0x9162, 0x56F3, 0x53A8,
- 0x9017, 0x5439, 0x5782, 0x5E25, 0x63A8, 0x6C34, 0x708A, 0x7761,
- 0x7C8B, 0x7FE0, 0x8870, 0x9042, 0x9154, 0x9310, 0x9318, 0x968F,
- 0x745E, 0x9AC4, 0x5D07, 0x5D69, 0x6570, 0x67A2, 0x8DA8, 0x96DB,
- 0x636E, 0x6749, 0x6919, 0x83C5, 0x9817, 0x96C0, 0x88FE,
-};
-const unsigned short euc_to_utf8_C0[] = {
- 0x6F84, 0x647A, 0x5BF8, 0x4E16, 0x702C, 0x755D, 0x662F,
- 0x51C4, 0x5236, 0x52E2, 0x59D3, 0x5F81, 0x6027, 0x6210, 0x653F,
- 0x6574, 0x661F, 0x6674, 0x68F2, 0x6816, 0x6B63, 0x6E05, 0x7272,
- 0x751F, 0x76DB, 0x7CBE, 0x8056, 0x58F0, 0x88FD, 0x897F, 0x8AA0,
- 0x8A93, 0x8ACB, 0x901D, 0x9192, 0x9752, 0x9759, 0x6589, 0x7A0E,
- 0x8106, 0x96BB, 0x5E2D, 0x60DC, 0x621A, 0x65A5, 0x6614, 0x6790,
- 0x77F3, 0x7A4D, 0x7C4D, 0x7E3E, 0x810A, 0x8CAC, 0x8D64, 0x8DE1,
- 0x8E5F, 0x78A9, 0x5207, 0x62D9, 0x63A5, 0x6442, 0x6298, 0x8A2D,
- 0x7A83, 0x7BC0, 0x8AAC, 0x96EA, 0x7D76, 0x820C, 0x8749, 0x4ED9,
- 0x5148, 0x5343, 0x5360, 0x5BA3, 0x5C02, 0x5C16, 0x5DDD, 0x6226,
- 0x6247, 0x64B0, 0x6813, 0x6834, 0x6CC9, 0x6D45, 0x6D17, 0x67D3,
- 0x6F5C, 0x714E, 0x717D, 0x65CB, 0x7A7F, 0x7BAD, 0x7DDA,
-};
-const unsigned short euc_to_utf8_C1[] = {
- 0x7E4A, 0x7FA8, 0x817A, 0x821B, 0x8239, 0x85A6, 0x8A6E,
- 0x8CCE, 0x8DF5, 0x9078, 0x9077, 0x92AD, 0x9291, 0x9583, 0x9BAE,
- 0x524D, 0x5584, 0x6F38, 0x7136, 0x5168, 0x7985, 0x7E55, 0x81B3,
- 0x7CCE, 0x564C, 0x5851, 0x5CA8, 0x63AA, 0x66FE, 0x66FD, 0x695A,
- 0x72D9, 0x758F, 0x758E, 0x790E, 0x7956, 0x79DF, 0x7C97, 0x7D20,
- 0x7D44, 0x8607, 0x8A34, 0x963B, 0x9061, 0x9F20, 0x50E7, 0x5275,
- 0x53CC, 0x53E2, 0x5009, 0x55AA, 0x58EE, 0x594F, 0x723D, 0x5B8B,
- 0x5C64, 0x531D, 0x60E3, 0x60F3, 0x635C, 0x6383, 0x633F, 0x63BB,
- 0x64CD, 0x65E9, 0x66F9, 0x5DE3, 0x69CD, 0x69FD, 0x6F15, 0x71E5,
- 0x4E89, 0x75E9, 0x76F8, 0x7A93, 0x7CDF, 0x7DCF, 0x7D9C, 0x8061,
- 0x8349, 0x8358, 0x846C, 0x84BC, 0x85FB, 0x88C5, 0x8D70, 0x9001,
- 0x906D, 0x9397, 0x971C, 0x9A12, 0x50CF, 0x5897, 0x618E,
-};
-const unsigned short euc_to_utf8_C2[] = {
- 0x81D3, 0x8535, 0x8D08, 0x9020, 0x4FC3, 0x5074, 0x5247,
- 0x5373, 0x606F, 0x6349, 0x675F, 0x6E2C, 0x8DB3, 0x901F, 0x4FD7,
- 0x5C5E, 0x8CCA, 0x65CF, 0x7D9A, 0x5352, 0x8896, 0x5176, 0x63C3,
- 0x5B58, 0x5B6B, 0x5C0A, 0x640D, 0x6751, 0x905C, 0x4ED6, 0x591A,
- 0x592A, 0x6C70, 0x8A51, 0x553E, 0x5815, 0x59A5, 0x60F0, 0x6253,
- 0x67C1, 0x8235, 0x6955, 0x9640, 0x99C4, 0x9A28, 0x4F53, 0x5806,
- 0x5BFE, 0x8010, 0x5CB1, 0x5E2F, 0x5F85, 0x6020, 0x614B, 0x6234,
- 0x66FF, 0x6CF0, 0x6EDE, 0x80CE, 0x817F, 0x82D4, 0x888B, 0x8CB8,
- 0x9000, 0x902E, 0x968A, 0x9EDB, 0x9BDB, 0x4EE3, 0x53F0, 0x5927,
- 0x7B2C, 0x918D, 0x984C, 0x9DF9, 0x6EDD, 0x7027, 0x5353, 0x5544,
- 0x5B85, 0x6258, 0x629E, 0x62D3, 0x6CA2, 0x6FEF, 0x7422, 0x8A17,
- 0x9438, 0x6FC1, 0x8AFE, 0x8338, 0x51E7, 0x86F8, 0x53EA,
-};
-const unsigned short euc_to_utf8_C3[] = {
- 0x53E9, 0x4F46, 0x9054, 0x8FB0, 0x596A, 0x8131, 0x5DFD,
- 0x7AEA, 0x8FBF, 0x68DA, 0x8C37, 0x72F8, 0x9C48, 0x6A3D, 0x8AB0,
- 0x4E39, 0x5358, 0x5606, 0x5766, 0x62C5, 0x63A2, 0x65E6, 0x6B4E,
- 0x6DE1, 0x6E5B, 0x70AD, 0x77ED, 0x7AEF, 0x7BAA, 0x7DBB, 0x803D,
- 0x80C6, 0x86CB, 0x8A95, 0x935B, 0x56E3, 0x58C7, 0x5F3E, 0x65AD,
- 0x6696, 0x6A80, 0x6BB5, 0x7537, 0x8AC7, 0x5024, 0x77E5, 0x5730,
- 0x5F1B, 0x6065, 0x667A, 0x6C60, 0x75F4, 0x7A1A, 0x7F6E, 0x81F4,
- 0x8718, 0x9045, 0x99B3, 0x7BC9, 0x755C, 0x7AF9, 0x7B51, 0x84C4,
- 0x9010, 0x79E9, 0x7A92, 0x8336, 0x5AE1, 0x7740, 0x4E2D, 0x4EF2,
- 0x5B99, 0x5FE0, 0x62BD, 0x663C, 0x67F1, 0x6CE8, 0x866B, 0x8877,
- 0x8A3B, 0x914E, 0x92F3, 0x99D0, 0x6A17, 0x7026, 0x732A, 0x82E7,
- 0x8457, 0x8CAF, 0x4E01, 0x5146, 0x51CB, 0x558B, 0x5BF5,
-};
-const unsigned short euc_to_utf8_C4[] = {
- 0x5E16, 0x5E33, 0x5E81, 0x5F14, 0x5F35, 0x5F6B, 0x5FB4,
- 0x61F2, 0x6311, 0x66A2, 0x671D, 0x6F6E, 0x7252, 0x753A, 0x773A,
- 0x8074, 0x8139, 0x8178, 0x8776, 0x8ABF, 0x8ADC, 0x8D85, 0x8DF3,
- 0x929A, 0x9577, 0x9802, 0x9CE5, 0x52C5, 0x6357, 0x76F4, 0x6715,
- 0x6C88, 0x73CD, 0x8CC3, 0x93AE, 0x9673, 0x6D25, 0x589C, 0x690E,
- 0x69CC, 0x8FFD, 0x939A, 0x75DB, 0x901A, 0x585A, 0x6802, 0x63B4,
- 0x69FB, 0x4F43, 0x6F2C, 0x67D8, 0x8FBB, 0x8526, 0x7DB4, 0x9354,
- 0x693F, 0x6F70, 0x576A, 0x58F7, 0x5B2C, 0x7D2C, 0x722A, 0x540A,
- 0x91E3, 0x9DB4, 0x4EAD, 0x4F4E, 0x505C, 0x5075, 0x5243, 0x8C9E,
- 0x5448, 0x5824, 0x5B9A, 0x5E1D, 0x5E95, 0x5EAD, 0x5EF7, 0x5F1F,
- 0x608C, 0x62B5, 0x633A, 0x63D0, 0x68AF, 0x6C40, 0x7887, 0x798E,
- 0x7A0B, 0x7DE0, 0x8247, 0x8A02, 0x8AE6, 0x8E44, 0x9013,
-};
-const unsigned short euc_to_utf8_C5[] = {
- 0x90B8, 0x912D, 0x91D8, 0x9F0E, 0x6CE5, 0x6458, 0x64E2,
- 0x6575, 0x6EF4, 0x7684, 0x7B1B, 0x9069, 0x93D1, 0x6EBA, 0x54F2,
- 0x5FB9, 0x64A4, 0x8F4D, 0x8FED, 0x9244, 0x5178, 0x586B, 0x5929,
- 0x5C55, 0x5E97, 0x6DFB, 0x7E8F, 0x751C, 0x8CBC, 0x8EE2, 0x985B,
- 0x70B9, 0x4F1D, 0x6BBF, 0x6FB1, 0x7530, 0x96FB, 0x514E, 0x5410,
- 0x5835, 0x5857, 0x59AC, 0x5C60, 0x5F92, 0x6597, 0x675C, 0x6E21,
- 0x767B, 0x83DF, 0x8CED, 0x9014, 0x90FD, 0x934D, 0x7825, 0x783A,
- 0x52AA, 0x5EA6, 0x571F, 0x5974, 0x6012, 0x5012, 0x515A, 0x51AC,
- 0x51CD, 0x5200, 0x5510, 0x5854, 0x5858, 0x5957, 0x5B95, 0x5CF6,
- 0x5D8B, 0x60BC, 0x6295, 0x642D, 0x6771, 0x6843, 0x68BC, 0x68DF,
- 0x76D7, 0x6DD8, 0x6E6F, 0x6D9B, 0x706F, 0x71C8, 0x5F53, 0x75D8,
- 0x7977, 0x7B49, 0x7B54, 0x7B52, 0x7CD6, 0x7D71, 0x5230,
-};
-const unsigned short euc_to_utf8_C6[] = {
- 0x8463, 0x8569, 0x85E4, 0x8A0E, 0x8B04, 0x8C46, 0x8E0F,
- 0x9003, 0x900F, 0x9419, 0x9676, 0x982D, 0x9A30, 0x95D8, 0x50CD,
- 0x52D5, 0x540C, 0x5802, 0x5C0E, 0x61A7, 0x649E, 0x6D1E, 0x77B3,
- 0x7AE5, 0x80F4, 0x8404, 0x9053, 0x9285, 0x5CE0, 0x9D07, 0x533F,
- 0x5F97, 0x5FB3, 0x6D9C, 0x7279, 0x7763, 0x79BF, 0x7BE4, 0x6BD2,
- 0x72EC, 0x8AAD, 0x6803, 0x6A61, 0x51F8, 0x7A81, 0x6934, 0x5C4A,
- 0x9CF6, 0x82EB, 0x5BC5, 0x9149, 0x701E, 0x5678, 0x5C6F, 0x60C7,
- 0x6566, 0x6C8C, 0x8C5A, 0x9041, 0x9813, 0x5451, 0x66C7, 0x920D,
- 0x5948, 0x90A3, 0x5185, 0x4E4D, 0x51EA, 0x8599, 0x8B0E, 0x7058,
- 0x637A, 0x934B, 0x6962, 0x99B4, 0x7E04, 0x7577, 0x5357, 0x6960,
- 0x8EDF, 0x96E3, 0x6C5D, 0x4E8C, 0x5C3C, 0x5F10, 0x8FE9, 0x5302,
- 0x8CD1, 0x8089, 0x8679, 0x5EFF, 0x65E5, 0x4E73, 0x5165,
-};
-const unsigned short euc_to_utf8_C7[] = {
- 0x5982, 0x5C3F, 0x97EE, 0x4EFB, 0x598A, 0x5FCD, 0x8A8D,
- 0x6FE1, 0x79B0, 0x7962, 0x5BE7, 0x8471, 0x732B, 0x71B1, 0x5E74,
- 0x5FF5, 0x637B, 0x649A, 0x71C3, 0x7C98, 0x4E43, 0x5EFC, 0x4E4B,
- 0x57DC, 0x56A2, 0x60A9, 0x6FC3, 0x7D0D, 0x80FD, 0x8133, 0x81BF,
- 0x8FB2, 0x8997, 0x86A4, 0x5DF4, 0x628A, 0x64AD, 0x8987, 0x6777,
- 0x6CE2, 0x6D3E, 0x7436, 0x7834, 0x5A46, 0x7F75, 0x82AD, 0x99AC,
- 0x4FF3, 0x5EC3, 0x62DD, 0x6392, 0x6557, 0x676F, 0x76C3, 0x724C,
- 0x80CC, 0x80BA, 0x8F29, 0x914D, 0x500D, 0x57F9, 0x5A92, 0x6885,
- 0x6973, 0x7164, 0x72FD, 0x8CB7, 0x58F2, 0x8CE0, 0x966A, 0x9019,
- 0x877F, 0x79E4, 0x77E7, 0x8429, 0x4F2F, 0x5265, 0x535A, 0x62CD,
- 0x67CF, 0x6CCA, 0x767D, 0x7B94, 0x7C95, 0x8236, 0x8584, 0x8FEB,
- 0x66DD, 0x6F20, 0x7206, 0x7E1B, 0x83AB, 0x99C1, 0x9EA6,
-};
-const unsigned short euc_to_utf8_C8[] = {
- 0x51FD, 0x7BB1, 0x7872, 0x7BB8, 0x8087, 0x7B48, 0x6AE8,
- 0x5E61, 0x808C, 0x7551, 0x7560, 0x516B, 0x9262, 0x6E8C, 0x767A,
- 0x9197, 0x9AEA, 0x4F10, 0x7F70, 0x629C, 0x7B4F, 0x95A5, 0x9CE9,
- 0x567A, 0x5859, 0x86E4, 0x96BC, 0x4F34, 0x5224, 0x534A, 0x53CD,
- 0x53DB, 0x5E06, 0x642C, 0x6591, 0x677F, 0x6C3E, 0x6C4E, 0x7248,
- 0x72AF, 0x73ED, 0x7554, 0x7E41, 0x822C, 0x85E9, 0x8CA9, 0x7BC4,
- 0x91C6, 0x7169, 0x9812, 0x98EF, 0x633D, 0x6669, 0x756A, 0x76E4,
- 0x78D0, 0x8543, 0x86EE, 0x532A, 0x5351, 0x5426, 0x5983, 0x5E87,
- 0x5F7C, 0x60B2, 0x6249, 0x6279, 0x62AB, 0x6590, 0x6BD4, 0x6CCC,
- 0x75B2, 0x76AE, 0x7891, 0x79D8, 0x7DCB, 0x7F77, 0x80A5, 0x88AB,
- 0x8AB9, 0x8CBB, 0x907F, 0x975E, 0x98DB, 0x6A0B, 0x7C38, 0x5099,
- 0x5C3E, 0x5FAE, 0x6787, 0x6BD8, 0x7435, 0x7709, 0x7F8E,
-};
-const unsigned short euc_to_utf8_C9[] = {
- 0x9F3B, 0x67CA, 0x7A17, 0x5339, 0x758B, 0x9AED, 0x5F66,
- 0x819D, 0x83F1, 0x8098, 0x5F3C, 0x5FC5, 0x7562, 0x7B46, 0x903C,
- 0x6867, 0x59EB, 0x5A9B, 0x7D10, 0x767E, 0x8B2C, 0x4FF5, 0x5F6A,
- 0x6A19, 0x6C37, 0x6F02, 0x74E2, 0x7968, 0x8868, 0x8A55, 0x8C79,
- 0x5EDF, 0x63CF, 0x75C5, 0x79D2, 0x82D7, 0x9328, 0x92F2, 0x849C,
- 0x86ED, 0x9C2D, 0x54C1, 0x5F6C, 0x658C, 0x6D5C, 0x7015, 0x8CA7,
- 0x8CD3, 0x983B, 0x654F, 0x74F6, 0x4E0D, 0x4ED8, 0x57E0, 0x592B,
- 0x5A66, 0x5BCC, 0x51A8, 0x5E03, 0x5E9C, 0x6016, 0x6276, 0x6577,
- 0x65A7, 0x666E, 0x6D6E, 0x7236, 0x7B26, 0x8150, 0x819A, 0x8299,
- 0x8B5C, 0x8CA0, 0x8CE6, 0x8D74, 0x961C, 0x9644, 0x4FAE, 0x64AB,
- 0x6B66, 0x821E, 0x8461, 0x856A, 0x90E8, 0x5C01, 0x6953, 0x98A8,
- 0x847A, 0x8557, 0x4F0F, 0x526F, 0x5FA9, 0x5E45, 0x670D,
-};
-const unsigned short euc_to_utf8_CA[] = {
- 0x798F, 0x8179, 0x8907, 0x8986, 0x6DF5, 0x5F17, 0x6255,
- 0x6CB8, 0x4ECF, 0x7269, 0x9B92, 0x5206, 0x543B, 0x5674, 0x58B3,
- 0x61A4, 0x626E, 0x711A, 0x596E, 0x7C89, 0x7CDE, 0x7D1B, 0x96F0,
- 0x6587, 0x805E, 0x4E19, 0x4F75, 0x5175, 0x5840, 0x5E63, 0x5E73,
- 0x5F0A, 0x67C4, 0x4E26, 0x853D, 0x9589, 0x965B, 0x7C73, 0x9801,
- 0x50FB, 0x58C1, 0x7656, 0x78A7, 0x5225, 0x77A5, 0x8511, 0x7B86,
- 0x504F, 0x5909, 0x7247, 0x7BC7, 0x7DE8, 0x8FBA, 0x8FD4, 0x904D,
- 0x4FBF, 0x52C9, 0x5A29, 0x5F01, 0x97AD, 0x4FDD, 0x8217, 0x92EA,
- 0x5703, 0x6355, 0x6B69, 0x752B, 0x88DC, 0x8F14, 0x7A42, 0x52DF,
- 0x5893, 0x6155, 0x620A, 0x66AE, 0x6BCD, 0x7C3F, 0x83E9, 0x5023,
- 0x4FF8, 0x5305, 0x5446, 0x5831, 0x5949, 0x5B9D, 0x5CF0, 0x5CEF,
- 0x5D29, 0x5E96, 0x62B1, 0x6367, 0x653E, 0x65B9, 0x670B,
-};
-const unsigned short euc_to_utf8_CB[] = {
- 0x6CD5, 0x6CE1, 0x70F9, 0x7832, 0x7E2B, 0x80DE, 0x82B3,
- 0x840C, 0x84EC, 0x8702, 0x8912, 0x8A2A, 0x8C4A, 0x90A6, 0x92D2,
- 0x98FD, 0x9CF3, 0x9D6C, 0x4E4F, 0x4EA1, 0x508D, 0x5256, 0x574A,
- 0x59A8, 0x5E3D, 0x5FD8, 0x5FD9, 0x623F, 0x66B4, 0x671B, 0x67D0,
- 0x68D2, 0x5192, 0x7D21, 0x80AA, 0x81A8, 0x8B00, 0x8C8C, 0x8CBF,
- 0x927E, 0x9632, 0x5420, 0x982C, 0x5317, 0x50D5, 0x535C, 0x58A8,
- 0x64B2, 0x6734, 0x7267, 0x7766, 0x7A46, 0x91E6, 0x52C3, 0x6CA1,
- 0x6B86, 0x5800, 0x5E4C, 0x5954, 0x672C, 0x7FFB, 0x51E1, 0x76C6,
- 0x6469, 0x78E8, 0x9B54, 0x9EBB, 0x57CB, 0x59B9, 0x6627, 0x679A,
- 0x6BCE, 0x54E9, 0x69D9, 0x5E55, 0x819C, 0x6795, 0x9BAA, 0x67FE,
- 0x9C52, 0x685D, 0x4EA6, 0x4FE3, 0x53C8, 0x62B9, 0x672B, 0x6CAB,
- 0x8FC4, 0x4FAD, 0x7E6D, 0x9EBF, 0x4E07, 0x6162, 0x6E80,
-};
-const unsigned short euc_to_utf8_CC[] = {
- 0x6F2B, 0x8513, 0x5473, 0x672A, 0x9B45, 0x5DF3, 0x7B95,
- 0x5CAC, 0x5BC6, 0x871C, 0x6E4A, 0x84D1, 0x7A14, 0x8108, 0x5999,
- 0x7C8D, 0x6C11, 0x7720, 0x52D9, 0x5922, 0x7121, 0x725F, 0x77DB,
- 0x9727, 0x9D61, 0x690B, 0x5A7F, 0x5A18, 0x51A5, 0x540D, 0x547D,
- 0x660E, 0x76DF, 0x8FF7, 0x9298, 0x9CF4, 0x59EA, 0x725D, 0x6EC5,
- 0x514D, 0x68C9, 0x7DBF, 0x7DEC, 0x9762, 0x9EBA, 0x6478, 0x6A21,
- 0x8302, 0x5984, 0x5B5F, 0x6BDB, 0x731B, 0x76F2, 0x7DB2, 0x8017,
- 0x8499, 0x5132, 0x6728, 0x9ED9, 0x76EE, 0x6762, 0x52FF, 0x9905,
- 0x5C24, 0x623B, 0x7C7E, 0x8CB0, 0x554F, 0x60B6, 0x7D0B, 0x9580,
- 0x5301, 0x4E5F, 0x51B6, 0x591C, 0x723A, 0x8036, 0x91CE, 0x5F25,
- 0x77E2, 0x5384, 0x5F79, 0x7D04, 0x85AC, 0x8A33, 0x8E8D, 0x9756,
- 0x67F3, 0x85AE, 0x9453, 0x6109, 0x6108, 0x6CB9, 0x7652,
-};
-const unsigned short euc_to_utf8_CD[] = {
- 0x8AED, 0x8F38, 0x552F, 0x4F51, 0x512A, 0x52C7, 0x53CB,
- 0x5BA5, 0x5E7D, 0x60A0, 0x6182, 0x63D6, 0x6709, 0x67DA, 0x6E67,
- 0x6D8C, 0x7336, 0x7337, 0x7531, 0x7950, 0x88D5, 0x8A98, 0x904A,
- 0x9091, 0x90F5, 0x96C4, 0x878D, 0x5915, 0x4E88, 0x4F59, 0x4E0E,
- 0x8A89, 0x8F3F, 0x9810, 0x50AD, 0x5E7C, 0x5996, 0x5BB9, 0x5EB8,
- 0x63DA, 0x63FA, 0x64C1, 0x66DC, 0x694A, 0x69D8, 0x6D0B, 0x6EB6,
- 0x7194, 0x7528, 0x7AAF, 0x7F8A, 0x8000, 0x8449, 0x84C9, 0x8981,
- 0x8B21, 0x8E0A, 0x9065, 0x967D, 0x990A, 0x617E, 0x6291, 0x6B32,
- 0x6C83, 0x6D74, 0x7FCC, 0x7FFC, 0x6DC0, 0x7F85, 0x87BA, 0x88F8,
- 0x6765, 0x83B1, 0x983C, 0x96F7, 0x6D1B, 0x7D61, 0x843D, 0x916A,
- 0x4E71, 0x5375, 0x5D50, 0x6B04, 0x6FEB, 0x85CD, 0x862D, 0x89A7,
- 0x5229, 0x540F, 0x5C65, 0x674E, 0x68A8, 0x7406, 0x7483,
-};
-const unsigned short euc_to_utf8_CE[] = {
- 0x75E2, 0x88CF, 0x88E1, 0x91CC, 0x96E2, 0x9678, 0x5F8B,
- 0x7387, 0x7ACB, 0x844E, 0x63A0, 0x7565, 0x5289, 0x6D41, 0x6E9C,
- 0x7409, 0x7559, 0x786B, 0x7C92, 0x9686, 0x7ADC, 0x9F8D, 0x4FB6,
- 0x616E, 0x65C5, 0x865C, 0x4E86, 0x4EAE, 0x50DA, 0x4E21, 0x51CC,
- 0x5BEE, 0x6599, 0x6881, 0x6DBC, 0x731F, 0x7642, 0x77AD, 0x7A1C,
- 0x7CE7, 0x826F, 0x8AD2, 0x907C, 0x91CF, 0x9675, 0x9818, 0x529B,
- 0x7DD1, 0x502B, 0x5398, 0x6797, 0x6DCB, 0x71D0, 0x7433, 0x81E8,
- 0x8F2A, 0x96A3, 0x9C57, 0x9E9F, 0x7460, 0x5841, 0x6D99, 0x7D2F,
- 0x985E, 0x4EE4, 0x4F36, 0x4F8B, 0x51B7, 0x52B1, 0x5DBA, 0x601C,
- 0x73B2, 0x793C, 0x82D3, 0x9234, 0x96B7, 0x96F6, 0x970A, 0x9E97,
- 0x9F62, 0x66A6, 0x6B74, 0x5217, 0x52A3, 0x70C8, 0x88C2, 0x5EC9,
- 0x604B, 0x6190, 0x6F23, 0x7149, 0x7C3E, 0x7DF4, 0x806F,
-};
-const unsigned short euc_to_utf8_CF[] = {
- 0x84EE, 0x9023, 0x932C, 0x5442, 0x9B6F, 0x6AD3, 0x7089,
- 0x8CC2, 0x8DEF, 0x9732, 0x52B4, 0x5A41, 0x5ECA, 0x5F04, 0x6717,
- 0x697C, 0x6994, 0x6D6A, 0x6F0F, 0x7262, 0x72FC, 0x7BED, 0x8001,
- 0x807E, 0x874B, 0x90CE, 0x516D, 0x9E93, 0x7984, 0x808B, 0x9332,
- 0x8AD6, 0x502D, 0x548C, 0x8A71, 0x6B6A, 0x8CC4, 0x8107, 0x60D1,
- 0x67A0, 0x9DF2, 0x4E99, 0x4E98, 0x9C10, 0x8A6B, 0x85C1, 0x8568,
- 0x6900, 0x6E7E, 0x7897, 0x8155, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_D0[] = {
- 0x5F0C, 0x4E10, 0x4E15, 0x4E2A, 0x4E31, 0x4E36, 0x4E3C,
- 0x4E3F, 0x4E42, 0x4E56, 0x4E58, 0x4E82, 0x4E85, 0x8C6B, 0x4E8A,
- 0x8212, 0x5F0D, 0x4E8E, 0x4E9E, 0x4E9F, 0x4EA0, 0x4EA2, 0x4EB0,
- 0x4EB3, 0x4EB6, 0x4ECE, 0x4ECD, 0x4EC4, 0x4EC6, 0x4EC2, 0x4ED7,
- 0x4EDE, 0x4EED, 0x4EDF, 0x4EF7, 0x4F09, 0x4F5A, 0x4F30, 0x4F5B,
- 0x4F5D, 0x4F57, 0x4F47, 0x4F76, 0x4F88, 0x4F8F, 0x4F98, 0x4F7B,
- 0x4F69, 0x4F70, 0x4F91, 0x4F6F, 0x4F86, 0x4F96, 0x5118, 0x4FD4,
- 0x4FDF, 0x4FCE, 0x4FD8, 0x4FDB, 0x4FD1, 0x4FDA, 0x4FD0, 0x4FE4,
- 0x4FE5, 0x501A, 0x5028, 0x5014, 0x502A, 0x5025, 0x5005, 0x4F1C,
- 0x4FF6, 0x5021, 0x5029, 0x502C, 0x4FFE, 0x4FEF, 0x5011, 0x5006,
- 0x5043, 0x5047, 0x6703, 0x5055, 0x5050, 0x5048, 0x505A, 0x5056,
- 0x506C, 0x5078, 0x5080, 0x509A, 0x5085, 0x50B4, 0x50B2,
-};
-const unsigned short euc_to_utf8_D1[] = {
- 0x50C9, 0x50CA, 0x50B3, 0x50C2, 0x50D6, 0x50DE, 0x50E5,
- 0x50ED, 0x50E3, 0x50EE, 0x50F9, 0x50F5, 0x5109, 0x5101, 0x5102,
- 0x5116, 0x5115, 0x5114, 0x511A, 0x5121, 0x513A, 0x5137, 0x513C,
- 0x513B, 0x513F, 0x5140, 0x5152, 0x514C, 0x5154, 0x5162, 0x7AF8,
- 0x5169, 0x516A, 0x516E, 0x5180, 0x5182, 0x56D8, 0x518C, 0x5189,
- 0x518F, 0x5191, 0x5193, 0x5195, 0x5196, 0x51A4, 0x51A6, 0x51A2,
- 0x51A9, 0x51AA, 0x51AB, 0x51B3, 0x51B1, 0x51B2, 0x51B0, 0x51B5,
- 0x51BD, 0x51C5, 0x51C9, 0x51DB, 0x51E0, 0x8655, 0x51E9, 0x51ED,
- 0x51F0, 0x51F5, 0x51FE, 0x5204, 0x520B, 0x5214, 0x520E, 0x5227,
- 0x522A, 0x522E, 0x5233, 0x5239, 0x524F, 0x5244, 0x524B, 0x524C,
- 0x525E, 0x5254, 0x526A, 0x5274, 0x5269, 0x5273, 0x527F, 0x527D,
- 0x528D, 0x5294, 0x5292, 0x5271, 0x5288, 0x5291, 0x8FA8,
-};
-const unsigned short euc_to_utf8_D2[] = {
- 0x8FA7, 0x52AC, 0x52AD, 0x52BC, 0x52B5, 0x52C1, 0x52CD,
- 0x52D7, 0x52DE, 0x52E3, 0x52E6, 0x98ED, 0x52E0, 0x52F3, 0x52F5,
- 0x52F8, 0x52F9, 0x5306, 0x5308, 0x7538, 0x530D, 0x5310, 0x530F,
- 0x5315, 0x531A, 0x5323, 0x532F, 0x5331, 0x5333, 0x5338, 0x5340,
- 0x5346, 0x5345, 0x4E17, 0x5349, 0x534D, 0x51D6, 0x535E, 0x5369,
- 0x536E, 0x5918, 0x537B, 0x5377, 0x5382, 0x5396, 0x53A0, 0x53A6,
- 0x53A5, 0x53AE, 0x53B0, 0x53B6, 0x53C3, 0x7C12, 0x96D9, 0x53DF,
- 0x66FC, 0x71EE, 0x53EE, 0x53E8, 0x53ED, 0x53FA, 0x5401, 0x543D,
- 0x5440, 0x542C, 0x542D, 0x543C, 0x542E, 0x5436, 0x5429, 0x541D,
- 0x544E, 0x548F, 0x5475, 0x548E, 0x545F, 0x5471, 0x5477, 0x5470,
- 0x5492, 0x547B, 0x5480, 0x5476, 0x5484, 0x5490, 0x5486, 0x54C7,
- 0x54A2, 0x54B8, 0x54A5, 0x54AC, 0x54C4, 0x54C8, 0x54A8,
-};
-const unsigned short euc_to_utf8_D3[] = {
- 0x54AB, 0x54C2, 0x54A4, 0x54BE, 0x54BC, 0x54D8, 0x54E5,
- 0x54E6, 0x550F, 0x5514, 0x54FD, 0x54EE, 0x54ED, 0x54FA, 0x54E2,
- 0x5539, 0x5540, 0x5563, 0x554C, 0x552E, 0x555C, 0x5545, 0x5556,
- 0x5557, 0x5538, 0x5533, 0x555D, 0x5599, 0x5580, 0x54AF, 0x558A,
- 0x559F, 0x557B, 0x557E, 0x5598, 0x559E, 0x55AE, 0x557C, 0x5583,
- 0x55A9, 0x5587, 0x55A8, 0x55DA, 0x55C5, 0x55DF, 0x55C4, 0x55DC,
- 0x55E4, 0x55D4, 0x5614, 0x55F7, 0x5616, 0x55FE, 0x55FD, 0x561B,
- 0x55F9, 0x564E, 0x5650, 0x71DF, 0x5634, 0x5636, 0x5632, 0x5638,
- 0x566B, 0x5664, 0x562F, 0x566C, 0x566A, 0x5686, 0x5680, 0x568A,
- 0x56A0, 0x5694, 0x568F, 0x56A5, 0x56AE, 0x56B6, 0x56B4, 0x56C2,
- 0x56BC, 0x56C1, 0x56C3, 0x56C0, 0x56C8, 0x56CE, 0x56D1, 0x56D3,
- 0x56D7, 0x56EE, 0x56F9, 0x5700, 0x56FF, 0x5704, 0x5709,
-};
-const unsigned short euc_to_utf8_D4[] = {
- 0x5708, 0x570B, 0x570D, 0x5713, 0x5718, 0x5716, 0x55C7,
- 0x571C, 0x5726, 0x5737, 0x5738, 0x574E, 0x573B, 0x5740, 0x574F,
- 0x5769, 0x57C0, 0x5788, 0x5761, 0x577F, 0x5789, 0x5793, 0x57A0,
- 0x57B3, 0x57A4, 0x57AA, 0x57B0, 0x57C3, 0x57C6, 0x57D4, 0x57D2,
- 0x57D3, 0x580A, 0x57D6, 0x57E3, 0x580B, 0x5819, 0x581D, 0x5872,
- 0x5821, 0x5862, 0x584B, 0x5870, 0x6BC0, 0x5852, 0x583D, 0x5879,
- 0x5885, 0x58B9, 0x589F, 0x58AB, 0x58BA, 0x58DE, 0x58BB, 0x58B8,
- 0x58AE, 0x58C5, 0x58D3, 0x58D1, 0x58D7, 0x58D9, 0x58D8, 0x58E5,
- 0x58DC, 0x58E4, 0x58DF, 0x58EF, 0x58FA, 0x58F9, 0x58FB, 0x58FC,
- 0x58FD, 0x5902, 0x590A, 0x5910, 0x591B, 0x68A6, 0x5925, 0x592C,
- 0x592D, 0x5932, 0x5938, 0x593E, 0x7AD2, 0x5955, 0x5950, 0x594E,
- 0x595A, 0x5958, 0x5962, 0x5960, 0x5967, 0x596C, 0x5969,
-};
-const unsigned short euc_to_utf8_D5[] = {
- 0x5978, 0x5981, 0x599D, 0x4F5E, 0x4FAB, 0x59A3, 0x59B2,
- 0x59C6, 0x59E8, 0x59DC, 0x598D, 0x59D9, 0x59DA, 0x5A25, 0x5A1F,
- 0x5A11, 0x5A1C, 0x5A09, 0x5A1A, 0x5A40, 0x5A6C, 0x5A49, 0x5A35,
- 0x5A36, 0x5A62, 0x5A6A, 0x5A9A, 0x5ABC, 0x5ABE, 0x5ACB, 0x5AC2,
- 0x5ABD, 0x5AE3, 0x5AD7, 0x5AE6, 0x5AE9, 0x5AD6, 0x5AFA, 0x5AFB,
- 0x5B0C, 0x5B0B, 0x5B16, 0x5B32, 0x5AD0, 0x5B2A, 0x5B36, 0x5B3E,
- 0x5B43, 0x5B45, 0x5B40, 0x5B51, 0x5B55, 0x5B5A, 0x5B5B, 0x5B65,
- 0x5B69, 0x5B70, 0x5B73, 0x5B75, 0x5B78, 0x6588, 0x5B7A, 0x5B80,
- 0x5B83, 0x5BA6, 0x5BB8, 0x5BC3, 0x5BC7, 0x5BC9, 0x5BD4, 0x5BD0,
- 0x5BE4, 0x5BE6, 0x5BE2, 0x5BDE, 0x5BE5, 0x5BEB, 0x5BF0, 0x5BF6,
- 0x5BF3, 0x5C05, 0x5C07, 0x5C08, 0x5C0D, 0x5C13, 0x5C20, 0x5C22,
- 0x5C28, 0x5C38, 0x5C39, 0x5C41, 0x5C46, 0x5C4E, 0x5C53,
-};
-const unsigned short euc_to_utf8_D6[] = {
- 0x5C50, 0x5C4F, 0x5B71, 0x5C6C, 0x5C6E, 0x4E62, 0x5C76,
- 0x5C79, 0x5C8C, 0x5C91, 0x5C94, 0x599B, 0x5CAB, 0x5CBB, 0x5CB6,
- 0x5CBC, 0x5CB7, 0x5CC5, 0x5CBE, 0x5CC7, 0x5CD9, 0x5CE9, 0x5CFD,
- 0x5CFA, 0x5CED, 0x5D8C, 0x5CEA, 0x5D0B, 0x5D15, 0x5D17, 0x5D5C,
- 0x5D1F, 0x5D1B, 0x5D11, 0x5D14, 0x5D22, 0x5D1A, 0x5D19, 0x5D18,
- 0x5D4C, 0x5D52, 0x5D4E, 0x5D4B, 0x5D6C, 0x5D73, 0x5D76, 0x5D87,
- 0x5D84, 0x5D82, 0x5DA2, 0x5D9D, 0x5DAC, 0x5DAE, 0x5DBD, 0x5D90,
- 0x5DB7, 0x5DBC, 0x5DC9, 0x5DCD, 0x5DD3, 0x5DD2, 0x5DD6, 0x5DDB,
- 0x5DEB, 0x5DF2, 0x5DF5, 0x5E0B, 0x5E1A, 0x5E19, 0x5E11, 0x5E1B,
- 0x5E36, 0x5E37, 0x5E44, 0x5E43, 0x5E40, 0x5E4E, 0x5E57, 0x5E54,
- 0x5E5F, 0x5E62, 0x5E64, 0x5E47, 0x5E75, 0x5E76, 0x5E7A, 0x9EBC,
- 0x5E7F, 0x5EA0, 0x5EC1, 0x5EC2, 0x5EC8, 0x5ED0, 0x5ECF,
-};
-const unsigned short euc_to_utf8_D7[] = {
- 0x5ED6, 0x5EE3, 0x5EDD, 0x5EDA, 0x5EDB, 0x5EE2, 0x5EE1,
- 0x5EE8, 0x5EE9, 0x5EEC, 0x5EF1, 0x5EF3, 0x5EF0, 0x5EF4, 0x5EF8,
- 0x5EFE, 0x5F03, 0x5F09, 0x5F5D, 0x5F5C, 0x5F0B, 0x5F11, 0x5F16,
- 0x5F29, 0x5F2D, 0x5F38, 0x5F41, 0x5F48, 0x5F4C, 0x5F4E, 0x5F2F,
- 0x5F51, 0x5F56, 0x5F57, 0x5F59, 0x5F61, 0x5F6D, 0x5F73, 0x5F77,
- 0x5F83, 0x5F82, 0x5F7F, 0x5F8A, 0x5F88, 0x5F91, 0x5F87, 0x5F9E,
- 0x5F99, 0x5F98, 0x5FA0, 0x5FA8, 0x5FAD, 0x5FBC, 0x5FD6, 0x5FFB,
- 0x5FE4, 0x5FF8, 0x5FF1, 0x5FDD, 0x60B3, 0x5FFF, 0x6021, 0x6060,
- 0x6019, 0x6010, 0x6029, 0x600E, 0x6031, 0x601B, 0x6015, 0x602B,
- 0x6026, 0x600F, 0x603A, 0x605A, 0x6041, 0x606A, 0x6077, 0x605F,
- 0x604A, 0x6046, 0x604D, 0x6063, 0x6043, 0x6064, 0x6042, 0x606C,
- 0x606B, 0x6059, 0x6081, 0x608D, 0x60E7, 0x6083, 0x609A,
-};
-const unsigned short euc_to_utf8_D8[] = {
- 0x6084, 0x609B, 0x6096, 0x6097, 0x6092, 0x60A7, 0x608B,
- 0x60E1, 0x60B8, 0x60E0, 0x60D3, 0x60B4, 0x5FF0, 0x60BD, 0x60C6,
- 0x60B5, 0x60D8, 0x614D, 0x6115, 0x6106, 0x60F6, 0x60F7, 0x6100,
- 0x60F4, 0x60FA, 0x6103, 0x6121, 0x60FB, 0x60F1, 0x610D, 0x610E,
- 0x6147, 0x613E, 0x6128, 0x6127, 0x614A, 0x613F, 0x613C, 0x612C,
- 0x6134, 0x613D, 0x6142, 0x6144, 0x6173, 0x6177, 0x6158, 0x6159,
- 0x615A, 0x616B, 0x6174, 0x616F, 0x6165, 0x6171, 0x615F, 0x615D,
- 0x6153, 0x6175, 0x6199, 0x6196, 0x6187, 0x61AC, 0x6194, 0x619A,
- 0x618A, 0x6191, 0x61AB, 0x61AE, 0x61CC, 0x61CA, 0x61C9, 0x61F7,
- 0x61C8, 0x61C3, 0x61C6, 0x61BA, 0x61CB, 0x7F79, 0x61CD, 0x61E6,
- 0x61E3, 0x61F6, 0x61FA, 0x61F4, 0x61FF, 0x61FD, 0x61FC, 0x61FE,
- 0x6200, 0x6208, 0x6209, 0x620D, 0x620C, 0x6214, 0x621B,
-};
-const unsigned short euc_to_utf8_D9[] = {
- 0x621E, 0x6221, 0x622A, 0x622E, 0x6230, 0x6232, 0x6233,
- 0x6241, 0x624E, 0x625E, 0x6263, 0x625B, 0x6260, 0x6268, 0x627C,
- 0x6282, 0x6289, 0x627E, 0x6292, 0x6293, 0x6296, 0x62D4, 0x6283,
- 0x6294, 0x62D7, 0x62D1, 0x62BB, 0x62CF, 0x62FF, 0x62C6, 0x64D4,
- 0x62C8, 0x62DC, 0x62CC, 0x62CA, 0x62C2, 0x62C7, 0x629B, 0x62C9,
- 0x630C, 0x62EE, 0x62F1, 0x6327, 0x6302, 0x6308, 0x62EF, 0x62F5,
- 0x6350, 0x633E, 0x634D, 0x641C, 0x634F, 0x6396, 0x638E, 0x6380,
- 0x63AB, 0x6376, 0x63A3, 0x638F, 0x6389, 0x639F, 0x63B5, 0x636B,
- 0x6369, 0x63BE, 0x63E9, 0x63C0, 0x63C6, 0x63E3, 0x63C9, 0x63D2,
- 0x63F6, 0x63C4, 0x6416, 0x6434, 0x6406, 0x6413, 0x6426, 0x6436,
- 0x651D, 0x6417, 0x6428, 0x640F, 0x6467, 0x646F, 0x6476, 0x644E,
- 0x652A, 0x6495, 0x6493, 0x64A5, 0x64A9, 0x6488, 0x64BC,
-};
-const unsigned short euc_to_utf8_DA[] = {
- 0x64DA, 0x64D2, 0x64C5, 0x64C7, 0x64BB, 0x64D8, 0x64C2,
- 0x64F1, 0x64E7, 0x8209, 0x64E0, 0x64E1, 0x62AC, 0x64E3, 0x64EF,
- 0x652C, 0x64F6, 0x64F4, 0x64F2, 0x64FA, 0x6500, 0x64FD, 0x6518,
- 0x651C, 0x6505, 0x6524, 0x6523, 0x652B, 0x6534, 0x6535, 0x6537,
- 0x6536, 0x6538, 0x754B, 0x6548, 0x6556, 0x6555, 0x654D, 0x6558,
- 0x655E, 0x655D, 0x6572, 0x6578, 0x6582, 0x6583, 0x8B8A, 0x659B,
- 0x659F, 0x65AB, 0x65B7, 0x65C3, 0x65C6, 0x65C1, 0x65C4, 0x65CC,
- 0x65D2, 0x65DB, 0x65D9, 0x65E0, 0x65E1, 0x65F1, 0x6772, 0x660A,
- 0x6603, 0x65FB, 0x6773, 0x6635, 0x6636, 0x6634, 0x661C, 0x664F,
- 0x6644, 0x6649, 0x6641, 0x665E, 0x665D, 0x6664, 0x6667, 0x6668,
- 0x665F, 0x6662, 0x6670, 0x6683, 0x6688, 0x668E, 0x6689, 0x6684,
- 0x6698, 0x669D, 0x66C1, 0x66B9, 0x66C9, 0x66BE, 0x66BC,
-};
-const unsigned short euc_to_utf8_DB[] = {
- 0x66C4, 0x66B8, 0x66D6, 0x66DA, 0x66E0, 0x663F, 0x66E6,
- 0x66E9, 0x66F0, 0x66F5, 0x66F7, 0x670F, 0x6716, 0x671E, 0x6726,
- 0x6727, 0x9738, 0x672E, 0x673F, 0x6736, 0x6741, 0x6738, 0x6737,
- 0x6746, 0x675E, 0x6760, 0x6759, 0x6763, 0x6764, 0x6789, 0x6770,
- 0x67A9, 0x677C, 0x676A, 0x678C, 0x678B, 0x67A6, 0x67A1, 0x6785,
- 0x67B7, 0x67EF, 0x67B4, 0x67EC, 0x67B3, 0x67E9, 0x67B8, 0x67E4,
- 0x67DE, 0x67DD, 0x67E2, 0x67EE, 0x67B9, 0x67CE, 0x67C6, 0x67E7,
- 0x6A9C, 0x681E, 0x6846, 0x6829, 0x6840, 0x684D, 0x6832, 0x684E,
- 0x68B3, 0x682B, 0x6859, 0x6863, 0x6877, 0x687F, 0x689F, 0x688F,
- 0x68AD, 0x6894, 0x689D, 0x689B, 0x6883, 0x6AAE, 0x68B9, 0x6874,
- 0x68B5, 0x68A0, 0x68BA, 0x690F, 0x688D, 0x687E, 0x6901, 0x68CA,
- 0x6908, 0x68D8, 0x6922, 0x6926, 0x68E1, 0x690C, 0x68CD,
-};
-const unsigned short euc_to_utf8_DC[] = {
- 0x68D4, 0x68E7, 0x68D5, 0x6936, 0x6912, 0x6904, 0x68D7,
- 0x68E3, 0x6925, 0x68F9, 0x68E0, 0x68EF, 0x6928, 0x692A, 0x691A,
- 0x6923, 0x6921, 0x68C6, 0x6979, 0x6977, 0x695C, 0x6978, 0x696B,
- 0x6954, 0x697E, 0x696E, 0x6939, 0x6974, 0x693D, 0x6959, 0x6930,
- 0x6961, 0x695E, 0x695D, 0x6981, 0x696A, 0x69B2, 0x69AE, 0x69D0,
- 0x69BF, 0x69C1, 0x69D3, 0x69BE, 0x69CE, 0x5BE8, 0x69CA, 0x69DD,
- 0x69BB, 0x69C3, 0x69A7, 0x6A2E, 0x6991, 0x69A0, 0x699C, 0x6995,
- 0x69B4, 0x69DE, 0x69E8, 0x6A02, 0x6A1B, 0x69FF, 0x6B0A, 0x69F9,
- 0x69F2, 0x69E7, 0x6A05, 0x69B1, 0x6A1E, 0x69ED, 0x6A14, 0x69EB,
- 0x6A0A, 0x6A12, 0x6AC1, 0x6A23, 0x6A13, 0x6A44, 0x6A0C, 0x6A72,
- 0x6A36, 0x6A78, 0x6A47, 0x6A62, 0x6A59, 0x6A66, 0x6A48, 0x6A38,
- 0x6A22, 0x6A90, 0x6A8D, 0x6AA0, 0x6A84, 0x6AA2, 0x6AA3,
-};
-const unsigned short euc_to_utf8_DD[] = {
- 0x6A97, 0x8617, 0x6ABB, 0x6AC3, 0x6AC2, 0x6AB8, 0x6AB3,
- 0x6AAC, 0x6ADE, 0x6AD1, 0x6ADF, 0x6AAA, 0x6ADA, 0x6AEA, 0x6AFB,
- 0x6B05, 0x8616, 0x6AFA, 0x6B12, 0x6B16, 0x9B31, 0x6B1F, 0x6B38,
- 0x6B37, 0x76DC, 0x6B39, 0x98EE, 0x6B47, 0x6B43, 0x6B49, 0x6B50,
- 0x6B59, 0x6B54, 0x6B5B, 0x6B5F, 0x6B61, 0x6B78, 0x6B79, 0x6B7F,
- 0x6B80, 0x6B84, 0x6B83, 0x6B8D, 0x6B98, 0x6B95, 0x6B9E, 0x6BA4,
- 0x6BAA, 0x6BAB, 0x6BAF, 0x6BB2, 0x6BB1, 0x6BB3, 0x6BB7, 0x6BBC,
- 0x6BC6, 0x6BCB, 0x6BD3, 0x6BDF, 0x6BEC, 0x6BEB, 0x6BF3, 0x6BEF,
- 0x9EBE, 0x6C08, 0x6C13, 0x6C14, 0x6C1B, 0x6C24, 0x6C23, 0x6C5E,
- 0x6C55, 0x6C62, 0x6C6A, 0x6C82, 0x6C8D, 0x6C9A, 0x6C81, 0x6C9B,
- 0x6C7E, 0x6C68, 0x6C73, 0x6C92, 0x6C90, 0x6CC4, 0x6CF1, 0x6CD3,
- 0x6CBD, 0x6CD7, 0x6CC5, 0x6CDD, 0x6CAE, 0x6CB1, 0x6CBE,
-};
-const unsigned short euc_to_utf8_DE[] = {
- 0x6CBA, 0x6CDB, 0x6CEF, 0x6CD9, 0x6CEA, 0x6D1F, 0x884D,
- 0x6D36, 0x6D2B, 0x6D3D, 0x6D38, 0x6D19, 0x6D35, 0x6D33, 0x6D12,
- 0x6D0C, 0x6D63, 0x6D93, 0x6D64, 0x6D5A, 0x6D79, 0x6D59, 0x6D8E,
- 0x6D95, 0x6FE4, 0x6D85, 0x6DF9, 0x6E15, 0x6E0A, 0x6DB5, 0x6DC7,
- 0x6DE6, 0x6DB8, 0x6DC6, 0x6DEC, 0x6DDE, 0x6DCC, 0x6DE8, 0x6DD2,
- 0x6DC5, 0x6DFA, 0x6DD9, 0x6DE4, 0x6DD5, 0x6DEA, 0x6DEE, 0x6E2D,
- 0x6E6E, 0x6E2E, 0x6E19, 0x6E72, 0x6E5F, 0x6E3E, 0x6E23, 0x6E6B,
- 0x6E2B, 0x6E76, 0x6E4D, 0x6E1F, 0x6E43, 0x6E3A, 0x6E4E, 0x6E24,
- 0x6EFF, 0x6E1D, 0x6E38, 0x6E82, 0x6EAA, 0x6E98, 0x6EC9, 0x6EB7,
- 0x6ED3, 0x6EBD, 0x6EAF, 0x6EC4, 0x6EB2, 0x6ED4, 0x6ED5, 0x6E8F,
- 0x6EA5, 0x6EC2, 0x6E9F, 0x6F41, 0x6F11, 0x704C, 0x6EEC, 0x6EF8,
- 0x6EFE, 0x6F3F, 0x6EF2, 0x6F31, 0x6EEF, 0x6F32, 0x6ECC,
-};
-const unsigned short euc_to_utf8_DF[] = {
- 0x6F3E, 0x6F13, 0x6EF7, 0x6F86, 0x6F7A, 0x6F78, 0x6F81,
- 0x6F80, 0x6F6F, 0x6F5B, 0x6FF3, 0x6F6D, 0x6F82, 0x6F7C, 0x6F58,
- 0x6F8E, 0x6F91, 0x6FC2, 0x6F66, 0x6FB3, 0x6FA3, 0x6FA1, 0x6FA4,
- 0x6FB9, 0x6FC6, 0x6FAA, 0x6FDF, 0x6FD5, 0x6FEC, 0x6FD4, 0x6FD8,
- 0x6FF1, 0x6FEE, 0x6FDB, 0x7009, 0x700B, 0x6FFA, 0x7011, 0x7001,
- 0x700F, 0x6FFE, 0x701B, 0x701A, 0x6F74, 0x701D, 0x7018, 0x701F,
- 0x7030, 0x703E, 0x7032, 0x7051, 0x7063, 0x7099, 0x7092, 0x70AF,
- 0x70F1, 0x70AC, 0x70B8, 0x70B3, 0x70AE, 0x70DF, 0x70CB, 0x70DD,
- 0x70D9, 0x7109, 0x70FD, 0x711C, 0x7119, 0x7165, 0x7155, 0x7188,
- 0x7166, 0x7162, 0x714C, 0x7156, 0x716C, 0x718F, 0x71FB, 0x7184,
- 0x7195, 0x71A8, 0x71AC, 0x71D7, 0x71B9, 0x71BE, 0x71D2, 0x71C9,
- 0x71D4, 0x71CE, 0x71E0, 0x71EC, 0x71E7, 0x71F5, 0x71FC,
-};
-const unsigned short euc_to_utf8_E0[] = {
- 0x71F9, 0x71FF, 0x720D, 0x7210, 0x721B, 0x7228, 0x722D,
- 0x722C, 0x7230, 0x7232, 0x723B, 0x723C, 0x723F, 0x7240, 0x7246,
- 0x724B, 0x7258, 0x7274, 0x727E, 0x7282, 0x7281, 0x7287, 0x7292,
- 0x7296, 0x72A2, 0x72A7, 0x72B9, 0x72B2, 0x72C3, 0x72C6, 0x72C4,
- 0x72CE, 0x72D2, 0x72E2, 0x72E0, 0x72E1, 0x72F9, 0x72F7, 0x500F,
- 0x7317, 0x730A, 0x731C, 0x7316, 0x731D, 0x7334, 0x732F, 0x7329,
- 0x7325, 0x733E, 0x734E, 0x734F, 0x9ED8, 0x7357, 0x736A, 0x7368,
- 0x7370, 0x7378, 0x7375, 0x737B, 0x737A, 0x73C8, 0x73B3, 0x73CE,
- 0x73BB, 0x73C0, 0x73E5, 0x73EE, 0x73DE, 0x74A2, 0x7405, 0x746F,
- 0x7425, 0x73F8, 0x7432, 0x743A, 0x7455, 0x743F, 0x745F, 0x7459,
- 0x7441, 0x745C, 0x7469, 0x7470, 0x7463, 0x746A, 0x7476, 0x747E,
- 0x748B, 0x749E, 0x74A7, 0x74CA, 0x74CF, 0x74D4, 0x73F1,
-};
-const unsigned short euc_to_utf8_E1[] = {
- 0x74E0, 0x74E3, 0x74E7, 0x74E9, 0x74EE, 0x74F2, 0x74F0,
- 0x74F1, 0x74F8, 0x74F7, 0x7504, 0x7503, 0x7505, 0x750C, 0x750E,
- 0x750D, 0x7515, 0x7513, 0x751E, 0x7526, 0x752C, 0x753C, 0x7544,
- 0x754D, 0x754A, 0x7549, 0x755B, 0x7546, 0x755A, 0x7569, 0x7564,
- 0x7567, 0x756B, 0x756D, 0x7578, 0x7576, 0x7586, 0x7587, 0x7574,
- 0x758A, 0x7589, 0x7582, 0x7594, 0x759A, 0x759D, 0x75A5, 0x75A3,
- 0x75C2, 0x75B3, 0x75C3, 0x75B5, 0x75BD, 0x75B8, 0x75BC, 0x75B1,
- 0x75CD, 0x75CA, 0x75D2, 0x75D9, 0x75E3, 0x75DE, 0x75FE, 0x75FF,
- 0x75FC, 0x7601, 0x75F0, 0x75FA, 0x75F2, 0x75F3, 0x760B, 0x760D,
- 0x7609, 0x761F, 0x7627, 0x7620, 0x7621, 0x7622, 0x7624, 0x7634,
- 0x7630, 0x763B, 0x7647, 0x7648, 0x7646, 0x765C, 0x7658, 0x7661,
- 0x7662, 0x7668, 0x7669, 0x766A, 0x7667, 0x766C, 0x7670,
-};
-const unsigned short euc_to_utf8_E2[] = {
- 0x7672, 0x7676, 0x7678, 0x767C, 0x7680, 0x7683, 0x7688,
- 0x768B, 0x768E, 0x7696, 0x7693, 0x7699, 0x769A, 0x76B0, 0x76B4,
- 0x76B8, 0x76B9, 0x76BA, 0x76C2, 0x76CD, 0x76D6, 0x76D2, 0x76DE,
- 0x76E1, 0x76E5, 0x76E7, 0x76EA, 0x862F, 0x76FB, 0x7708, 0x7707,
- 0x7704, 0x7729, 0x7724, 0x771E, 0x7725, 0x7726, 0x771B, 0x7737,
- 0x7738, 0x7747, 0x775A, 0x7768, 0x776B, 0x775B, 0x7765, 0x777F,
- 0x777E, 0x7779, 0x778E, 0x778B, 0x7791, 0x77A0, 0x779E, 0x77B0,
- 0x77B6, 0x77B9, 0x77BF, 0x77BC, 0x77BD, 0x77BB, 0x77C7, 0x77CD,
- 0x77D7, 0x77DA, 0x77DC, 0x77E3, 0x77EE, 0x77FC, 0x780C, 0x7812,
- 0x7926, 0x7820, 0x792A, 0x7845, 0x788E, 0x7874, 0x7886, 0x787C,
- 0x789A, 0x788C, 0x78A3, 0x78B5, 0x78AA, 0x78AF, 0x78D1, 0x78C6,
- 0x78CB, 0x78D4, 0x78BE, 0x78BC, 0x78C5, 0x78CA, 0x78EC,
-};
-const unsigned short euc_to_utf8_E3[] = {
- 0x78E7, 0x78DA, 0x78FD, 0x78F4, 0x7907, 0x7912, 0x7911,
- 0x7919, 0x792C, 0x792B, 0x7940, 0x7960, 0x7957, 0x795F, 0x795A,
- 0x7955, 0x7953, 0x797A, 0x797F, 0x798A, 0x799D, 0x79A7, 0x9F4B,
- 0x79AA, 0x79AE, 0x79B3, 0x79B9, 0x79BA, 0x79C9, 0x79D5, 0x79E7,
- 0x79EC, 0x79E1, 0x79E3, 0x7A08, 0x7A0D, 0x7A18, 0x7A19, 0x7A20,
- 0x7A1F, 0x7980, 0x7A31, 0x7A3B, 0x7A3E, 0x7A37, 0x7A43, 0x7A57,
- 0x7A49, 0x7A61, 0x7A62, 0x7A69, 0x9F9D, 0x7A70, 0x7A79, 0x7A7D,
- 0x7A88, 0x7A97, 0x7A95, 0x7A98, 0x7A96, 0x7AA9, 0x7AC8, 0x7AB0,
- 0x7AB6, 0x7AC5, 0x7AC4, 0x7ABF, 0x9083, 0x7AC7, 0x7ACA, 0x7ACD,
- 0x7ACF, 0x7AD5, 0x7AD3, 0x7AD9, 0x7ADA, 0x7ADD, 0x7AE1, 0x7AE2,
- 0x7AE6, 0x7AED, 0x7AF0, 0x7B02, 0x7B0F, 0x7B0A, 0x7B06, 0x7B33,
- 0x7B18, 0x7B19, 0x7B1E, 0x7B35, 0x7B28, 0x7B36, 0x7B50,
-};
-const unsigned short euc_to_utf8_E4[] = {
- 0x7B7A, 0x7B04, 0x7B4D, 0x7B0B, 0x7B4C, 0x7B45, 0x7B75,
- 0x7B65, 0x7B74, 0x7B67, 0x7B70, 0x7B71, 0x7B6C, 0x7B6E, 0x7B9D,
- 0x7B98, 0x7B9F, 0x7B8D, 0x7B9C, 0x7B9A, 0x7B8B, 0x7B92, 0x7B8F,
- 0x7B5D, 0x7B99, 0x7BCB, 0x7BC1, 0x7BCC, 0x7BCF, 0x7BB4, 0x7BC6,
- 0x7BDD, 0x7BE9, 0x7C11, 0x7C14, 0x7BE6, 0x7BE5, 0x7C60, 0x7C00,
- 0x7C07, 0x7C13, 0x7BF3, 0x7BF7, 0x7C17, 0x7C0D, 0x7BF6, 0x7C23,
- 0x7C27, 0x7C2A, 0x7C1F, 0x7C37, 0x7C2B, 0x7C3D, 0x7C4C, 0x7C43,
- 0x7C54, 0x7C4F, 0x7C40, 0x7C50, 0x7C58, 0x7C5F, 0x7C64, 0x7C56,
- 0x7C65, 0x7C6C, 0x7C75, 0x7C83, 0x7C90, 0x7CA4, 0x7CAD, 0x7CA2,
- 0x7CAB, 0x7CA1, 0x7CA8, 0x7CB3, 0x7CB2, 0x7CB1, 0x7CAE, 0x7CB9,
- 0x7CBD, 0x7CC0, 0x7CC5, 0x7CC2, 0x7CD8, 0x7CD2, 0x7CDC, 0x7CE2,
- 0x9B3B, 0x7CEF, 0x7CF2, 0x7CF4, 0x7CF6, 0x7CFA, 0x7D06,
-};
-const unsigned short euc_to_utf8_E5[] = {
- 0x7D02, 0x7D1C, 0x7D15, 0x7D0A, 0x7D45, 0x7D4B, 0x7D2E,
- 0x7D32, 0x7D3F, 0x7D35, 0x7D46, 0x7D73, 0x7D56, 0x7D4E, 0x7D72,
- 0x7D68, 0x7D6E, 0x7D4F, 0x7D63, 0x7D93, 0x7D89, 0x7D5B, 0x7D8F,
- 0x7D7D, 0x7D9B, 0x7DBA, 0x7DAE, 0x7DA3, 0x7DB5, 0x7DC7, 0x7DBD,
- 0x7DAB, 0x7E3D, 0x7DA2, 0x7DAF, 0x7DDC, 0x7DB8, 0x7D9F, 0x7DB0,
- 0x7DD8, 0x7DDD, 0x7DE4, 0x7DDE, 0x7DFB, 0x7DF2, 0x7DE1, 0x7E05,
- 0x7E0A, 0x7E23, 0x7E21, 0x7E12, 0x7E31, 0x7E1F, 0x7E09, 0x7E0B,
- 0x7E22, 0x7E46, 0x7E66, 0x7E3B, 0x7E35, 0x7E39, 0x7E43, 0x7E37,
- 0x7E32, 0x7E3A, 0x7E67, 0x7E5D, 0x7E56, 0x7E5E, 0x7E59, 0x7E5A,
- 0x7E79, 0x7E6A, 0x7E69, 0x7E7C, 0x7E7B, 0x7E83, 0x7DD5, 0x7E7D,
- 0x8FAE, 0x7E7F, 0x7E88, 0x7E89, 0x7E8C, 0x7E92, 0x7E90, 0x7E93,
- 0x7E94, 0x7E96, 0x7E8E, 0x7E9B, 0x7E9C, 0x7F38, 0x7F3A,
-};
-const unsigned short euc_to_utf8_E6[] = {
- 0x7F45, 0x7F4C, 0x7F4D, 0x7F4E, 0x7F50, 0x7F51, 0x7F55,
- 0x7F54, 0x7F58, 0x7F5F, 0x7F60, 0x7F68, 0x7F69, 0x7F67, 0x7F78,
- 0x7F82, 0x7F86, 0x7F83, 0x7F88, 0x7F87, 0x7F8C, 0x7F94, 0x7F9E,
- 0x7F9D, 0x7F9A, 0x7FA3, 0x7FAF, 0x7FB2, 0x7FB9, 0x7FAE, 0x7FB6,
- 0x7FB8, 0x8B71, 0x7FC5, 0x7FC6, 0x7FCA, 0x7FD5, 0x7FD4, 0x7FE1,
- 0x7FE6, 0x7FE9, 0x7FF3, 0x7FF9, 0x98DC, 0x8006, 0x8004, 0x800B,
- 0x8012, 0x8018, 0x8019, 0x801C, 0x8021, 0x8028, 0x803F, 0x803B,
- 0x804A, 0x8046, 0x8052, 0x8058, 0x805A, 0x805F, 0x8062, 0x8068,
- 0x8073, 0x8072, 0x8070, 0x8076, 0x8079, 0x807D, 0x807F, 0x8084,
- 0x8086, 0x8085, 0x809B, 0x8093, 0x809A, 0x80AD, 0x5190, 0x80AC,
- 0x80DB, 0x80E5, 0x80D9, 0x80DD, 0x80C4, 0x80DA, 0x80D6, 0x8109,
- 0x80EF, 0x80F1, 0x811B, 0x8129, 0x8123, 0x812F, 0x814B,
-};
-const unsigned short euc_to_utf8_E7[] = {
- 0x968B, 0x8146, 0x813E, 0x8153, 0x8151, 0x80FC, 0x8171,
- 0x816E, 0x8165, 0x8166, 0x8174, 0x8183, 0x8188, 0x818A, 0x8180,
- 0x8182, 0x81A0, 0x8195, 0x81A4, 0x81A3, 0x815F, 0x8193, 0x81A9,
- 0x81B0, 0x81B5, 0x81BE, 0x81B8, 0x81BD, 0x81C0, 0x81C2, 0x81BA,
- 0x81C9, 0x81CD, 0x81D1, 0x81D9, 0x81D8, 0x81C8, 0x81DA, 0x81DF,
- 0x81E0, 0x81E7, 0x81FA, 0x81FB, 0x81FE, 0x8201, 0x8202, 0x8205,
- 0x8207, 0x820A, 0x820D, 0x8210, 0x8216, 0x8229, 0x822B, 0x8238,
- 0x8233, 0x8240, 0x8259, 0x8258, 0x825D, 0x825A, 0x825F, 0x8264,
- 0x8262, 0x8268, 0x826A, 0x826B, 0x822E, 0x8271, 0x8277, 0x8278,
- 0x827E, 0x828D, 0x8292, 0x82AB, 0x829F, 0x82BB, 0x82AC, 0x82E1,
- 0x82E3, 0x82DF, 0x82D2, 0x82F4, 0x82F3, 0x82FA, 0x8393, 0x8303,
- 0x82FB, 0x82F9, 0x82DE, 0x8306, 0x82DC, 0x8309, 0x82D9,
-};
-const unsigned short euc_to_utf8_E8[] = {
- 0x8335, 0x8334, 0x8316, 0x8332, 0x8331, 0x8340, 0x8339,
- 0x8350, 0x8345, 0x832F, 0x832B, 0x8317, 0x8318, 0x8385, 0x839A,
- 0x83AA, 0x839F, 0x83A2, 0x8396, 0x8323, 0x838E, 0x8387, 0x838A,
- 0x837C, 0x83B5, 0x8373, 0x8375, 0x83A0, 0x8389, 0x83A8, 0x83F4,
- 0x8413, 0x83EB, 0x83CE, 0x83FD, 0x8403, 0x83D8, 0x840B, 0x83C1,
- 0x83F7, 0x8407, 0x83E0, 0x83F2, 0x840D, 0x8422, 0x8420, 0x83BD,
- 0x8438, 0x8506, 0x83FB, 0x846D, 0x842A, 0x843C, 0x855A, 0x8484,
- 0x8477, 0x846B, 0x84AD, 0x846E, 0x8482, 0x8469, 0x8446, 0x842C,
- 0x846F, 0x8479, 0x8435, 0x84CA, 0x8462, 0x84B9, 0x84BF, 0x849F,
- 0x84D9, 0x84CD, 0x84BB, 0x84DA, 0x84D0, 0x84C1, 0x84C6, 0x84D6,
- 0x84A1, 0x8521, 0x84FF, 0x84F4, 0x8517, 0x8518, 0x852C, 0x851F,
- 0x8515, 0x8514, 0x84FC, 0x8540, 0x8563, 0x8558, 0x8548,
-};
-const unsigned short euc_to_utf8_E9[] = {
- 0x8541, 0x8602, 0x854B, 0x8555, 0x8580, 0x85A4, 0x8588,
- 0x8591, 0x858A, 0x85A8, 0x856D, 0x8594, 0x859B, 0x85EA, 0x8587,
- 0x859C, 0x8577, 0x857E, 0x8590, 0x85C9, 0x85BA, 0x85CF, 0x85B9,
- 0x85D0, 0x85D5, 0x85DD, 0x85E5, 0x85DC, 0x85F9, 0x860A, 0x8613,
- 0x860B, 0x85FE, 0x85FA, 0x8606, 0x8622, 0x861A, 0x8630, 0x863F,
- 0x864D, 0x4E55, 0x8654, 0x865F, 0x8667, 0x8671, 0x8693, 0x86A3,
- 0x86A9, 0x86AA, 0x868B, 0x868C, 0x86B6, 0x86AF, 0x86C4, 0x86C6,
- 0x86B0, 0x86C9, 0x8823, 0x86AB, 0x86D4, 0x86DE, 0x86E9, 0x86EC,
- 0x86DF, 0x86DB, 0x86EF, 0x8712, 0x8706, 0x8708, 0x8700, 0x8703,
- 0x86FB, 0x8711, 0x8709, 0x870D, 0x86F9, 0x870A, 0x8734, 0x873F,
- 0x8737, 0x873B, 0x8725, 0x8729, 0x871A, 0x8760, 0x875F, 0x8778,
- 0x874C, 0x874E, 0x8774, 0x8757, 0x8768, 0x876E, 0x8759,
-};
-const unsigned short euc_to_utf8_EA[] = {
- 0x8753, 0x8763, 0x876A, 0x8805, 0x87A2, 0x879F, 0x8782,
- 0x87AF, 0x87CB, 0x87BD, 0x87C0, 0x87D0, 0x96D6, 0x87AB, 0x87C4,
- 0x87B3, 0x87C7, 0x87C6, 0x87BB, 0x87EF, 0x87F2, 0x87E0, 0x880F,
- 0x880D, 0x87FE, 0x87F6, 0x87F7, 0x880E, 0x87D2, 0x8811, 0x8816,
- 0x8815, 0x8822, 0x8821, 0x8831, 0x8836, 0x8839, 0x8827, 0x883B,
- 0x8844, 0x8842, 0x8852, 0x8859, 0x885E, 0x8862, 0x886B, 0x8881,
- 0x887E, 0x889E, 0x8875, 0x887D, 0x88B5, 0x8872, 0x8882, 0x8897,
- 0x8892, 0x88AE, 0x8899, 0x88A2, 0x888D, 0x88A4, 0x88B0, 0x88BF,
- 0x88B1, 0x88C3, 0x88C4, 0x88D4, 0x88D8, 0x88D9, 0x88DD, 0x88F9,
- 0x8902, 0x88FC, 0x88F4, 0x88E8, 0x88F2, 0x8904, 0x890C, 0x890A,
- 0x8913, 0x8943, 0x891E, 0x8925, 0x892A, 0x892B, 0x8941, 0x8944,
- 0x893B, 0x8936, 0x8938, 0x894C, 0x891D, 0x8960, 0x895E,
-};
-const unsigned short euc_to_utf8_EB[] = {
- 0x8966, 0x8964, 0x896D, 0x896A, 0x896F, 0x8974, 0x8977,
- 0x897E, 0x8983, 0x8988, 0x898A, 0x8993, 0x8998, 0x89A1, 0x89A9,
- 0x89A6, 0x89AC, 0x89AF, 0x89B2, 0x89BA, 0x89BD, 0x89BF, 0x89C0,
- 0x89DA, 0x89DC, 0x89DD, 0x89E7, 0x89F4, 0x89F8, 0x8A03, 0x8A16,
- 0x8A10, 0x8A0C, 0x8A1B, 0x8A1D, 0x8A25, 0x8A36, 0x8A41, 0x8A5B,
- 0x8A52, 0x8A46, 0x8A48, 0x8A7C, 0x8A6D, 0x8A6C, 0x8A62, 0x8A85,
- 0x8A82, 0x8A84, 0x8AA8, 0x8AA1, 0x8A91, 0x8AA5, 0x8AA6, 0x8A9A,
- 0x8AA3, 0x8AC4, 0x8ACD, 0x8AC2, 0x8ADA, 0x8AEB, 0x8AF3, 0x8AE7,
- 0x8AE4, 0x8AF1, 0x8B14, 0x8AE0, 0x8AE2, 0x8AF7, 0x8ADE, 0x8ADB,
- 0x8B0C, 0x8B07, 0x8B1A, 0x8AE1, 0x8B16, 0x8B10, 0x8B17, 0x8B20,
- 0x8B33, 0x97AB, 0x8B26, 0x8B2B, 0x8B3E, 0x8B28, 0x8B41, 0x8B4C,
- 0x8B4F, 0x8B4E, 0x8B49, 0x8B56, 0x8B5B, 0x8B5A, 0x8B6B,
-};
-const unsigned short euc_to_utf8_EC[] = {
- 0x8B5F, 0x8B6C, 0x8B6F, 0x8B74, 0x8B7D, 0x8B80, 0x8B8C,
- 0x8B8E, 0x8B92, 0x8B93, 0x8B96, 0x8B99, 0x8B9A, 0x8C3A, 0x8C41,
- 0x8C3F, 0x8C48, 0x8C4C, 0x8C4E, 0x8C50, 0x8C55, 0x8C62, 0x8C6C,
- 0x8C78, 0x8C7A, 0x8C82, 0x8C89, 0x8C85, 0x8C8A, 0x8C8D, 0x8C8E,
- 0x8C94, 0x8C7C, 0x8C98, 0x621D, 0x8CAD, 0x8CAA, 0x8CBD, 0x8CB2,
- 0x8CB3, 0x8CAE, 0x8CB6, 0x8CC8, 0x8CC1, 0x8CE4, 0x8CE3, 0x8CDA,
- 0x8CFD, 0x8CFA, 0x8CFB, 0x8D04, 0x8D05, 0x8D0A, 0x8D07, 0x8D0F,
- 0x8D0D, 0x8D10, 0x9F4E, 0x8D13, 0x8CCD, 0x8D14, 0x8D16, 0x8D67,
- 0x8D6D, 0x8D71, 0x8D73, 0x8D81, 0x8D99, 0x8DC2, 0x8DBE, 0x8DBA,
- 0x8DCF, 0x8DDA, 0x8DD6, 0x8DCC, 0x8DDB, 0x8DCB, 0x8DEA, 0x8DEB,
- 0x8DDF, 0x8DE3, 0x8DFC, 0x8E08, 0x8E09, 0x8DFF, 0x8E1D, 0x8E1E,
- 0x8E10, 0x8E1F, 0x8E42, 0x8E35, 0x8E30, 0x8E34, 0x8E4A,
-};
-const unsigned short euc_to_utf8_ED[] = {
- 0x8E47, 0x8E49, 0x8E4C, 0x8E50, 0x8E48, 0x8E59, 0x8E64,
- 0x8E60, 0x8E2A, 0x8E63, 0x8E55, 0x8E76, 0x8E72, 0x8E7C, 0x8E81,
- 0x8E87, 0x8E85, 0x8E84, 0x8E8B, 0x8E8A, 0x8E93, 0x8E91, 0x8E94,
- 0x8E99, 0x8EAA, 0x8EA1, 0x8EAC, 0x8EB0, 0x8EC6, 0x8EB1, 0x8EBE,
- 0x8EC5, 0x8EC8, 0x8ECB, 0x8EDB, 0x8EE3, 0x8EFC, 0x8EFB, 0x8EEB,
- 0x8EFE, 0x8F0A, 0x8F05, 0x8F15, 0x8F12, 0x8F19, 0x8F13, 0x8F1C,
- 0x8F1F, 0x8F1B, 0x8F0C, 0x8F26, 0x8F33, 0x8F3B, 0x8F39, 0x8F45,
- 0x8F42, 0x8F3E, 0x8F4C, 0x8F49, 0x8F46, 0x8F4E, 0x8F57, 0x8F5C,
- 0x8F62, 0x8F63, 0x8F64, 0x8F9C, 0x8F9F, 0x8FA3, 0x8FAD, 0x8FAF,
- 0x8FB7, 0x8FDA, 0x8FE5, 0x8FE2, 0x8FEA, 0x8FEF, 0x9087, 0x8FF4,
- 0x9005, 0x8FF9, 0x8FFA, 0x9011, 0x9015, 0x9021, 0x900D, 0x901E,
- 0x9016, 0x900B, 0x9027, 0x9036, 0x9035, 0x9039, 0x8FF8,
-};
-const unsigned short euc_to_utf8_EE[] = {
- 0x904F, 0x9050, 0x9051, 0x9052, 0x900E, 0x9049, 0x903E,
- 0x9056, 0x9058, 0x905E, 0x9068, 0x906F, 0x9076, 0x96A8, 0x9072,
- 0x9082, 0x907D, 0x9081, 0x9080, 0x908A, 0x9089, 0x908F, 0x90A8,
- 0x90AF, 0x90B1, 0x90B5, 0x90E2, 0x90E4, 0x6248, 0x90DB, 0x9102,
- 0x9112, 0x9119, 0x9132, 0x9130, 0x914A, 0x9156, 0x9158, 0x9163,
- 0x9165, 0x9169, 0x9173, 0x9172, 0x918B, 0x9189, 0x9182, 0x91A2,
- 0x91AB, 0x91AF, 0x91AA, 0x91B5, 0x91B4, 0x91BA, 0x91C0, 0x91C1,
- 0x91C9, 0x91CB, 0x91D0, 0x91D6, 0x91DF, 0x91E1, 0x91DB, 0x91FC,
- 0x91F5, 0x91F6, 0x921E, 0x91FF, 0x9214, 0x922C, 0x9215, 0x9211,
- 0x925E, 0x9257, 0x9245, 0x9249, 0x9264, 0x9248, 0x9295, 0x923F,
- 0x924B, 0x9250, 0x929C, 0x9296, 0x9293, 0x929B, 0x925A, 0x92CF,
- 0x92B9, 0x92B7, 0x92E9, 0x930F, 0x92FA, 0x9344, 0x932E,
-};
-const unsigned short euc_to_utf8_EF[] = {
- 0x9319, 0x9322, 0x931A, 0x9323, 0x933A, 0x9335, 0x933B,
- 0x935C, 0x9360, 0x937C, 0x936E, 0x9356, 0x93B0, 0x93AC, 0x93AD,
- 0x9394, 0x93B9, 0x93D6, 0x93D7, 0x93E8, 0x93E5, 0x93D8, 0x93C3,
- 0x93DD, 0x93D0, 0x93C8, 0x93E4, 0x941A, 0x9414, 0x9413, 0x9403,
- 0x9407, 0x9410, 0x9436, 0x942B, 0x9435, 0x9421, 0x943A, 0x9441,
- 0x9452, 0x9444, 0x945B, 0x9460, 0x9462, 0x945E, 0x946A, 0x9229,
- 0x9470, 0x9475, 0x9477, 0x947D, 0x945A, 0x947C, 0x947E, 0x9481,
- 0x947F, 0x9582, 0x9587, 0x958A, 0x9594, 0x9596, 0x9598, 0x9599,
- 0x95A0, 0x95A8, 0x95A7, 0x95AD, 0x95BC, 0x95BB, 0x95B9, 0x95BE,
- 0x95CA, 0x6FF6, 0x95C3, 0x95CD, 0x95CC, 0x95D5, 0x95D4, 0x95D6,
- 0x95DC, 0x95E1, 0x95E5, 0x95E2, 0x9621, 0x9628, 0x962E, 0x962F,
- 0x9642, 0x964C, 0x964F, 0x964B, 0x9677, 0x965C, 0x965E,
-};
-const unsigned short euc_to_utf8_F0[] = {
- 0x965D, 0x965F, 0x9666, 0x9672, 0x966C, 0x968D, 0x9698,
- 0x9695, 0x9697, 0x96AA, 0x96A7, 0x96B1, 0x96B2, 0x96B0, 0x96B4,
- 0x96B6, 0x96B8, 0x96B9, 0x96CE, 0x96CB, 0x96C9, 0x96CD, 0x894D,
- 0x96DC, 0x970D, 0x96D5, 0x96F9, 0x9704, 0x9706, 0x9708, 0x9713,
- 0x970E, 0x9711, 0x970F, 0x9716, 0x9719, 0x9724, 0x972A, 0x9730,
- 0x9739, 0x973D, 0x973E, 0x9744, 0x9746, 0x9748, 0x9742, 0x9749,
- 0x975C, 0x9760, 0x9764, 0x9766, 0x9768, 0x52D2, 0x976B, 0x9771,
- 0x9779, 0x9785, 0x977C, 0x9781, 0x977A, 0x9786, 0x978B, 0x978F,
- 0x9790, 0x979C, 0x97A8, 0x97A6, 0x97A3, 0x97B3, 0x97B4, 0x97C3,
- 0x97C6, 0x97C8, 0x97CB, 0x97DC, 0x97ED, 0x9F4F, 0x97F2, 0x7ADF,
- 0x97F6, 0x97F5, 0x980F, 0x980C, 0x9838, 0x9824, 0x9821, 0x9837,
- 0x983D, 0x9846, 0x984F, 0x984B, 0x986B, 0x986F, 0x9870,
-};
-const unsigned short euc_to_utf8_F1[] = {
- 0x9871, 0x9874, 0x9873, 0x98AA, 0x98AF, 0x98B1, 0x98B6,
- 0x98C4, 0x98C3, 0x98C6, 0x98E9, 0x98EB, 0x9903, 0x9909, 0x9912,
- 0x9914, 0x9918, 0x9921, 0x991D, 0x991E, 0x9924, 0x9920, 0x992C,
- 0x992E, 0x993D, 0x993E, 0x9942, 0x9949, 0x9945, 0x9950, 0x994B,
- 0x9951, 0x9952, 0x994C, 0x9955, 0x9997, 0x9998, 0x99A5, 0x99AD,
- 0x99AE, 0x99BC, 0x99DF, 0x99DB, 0x99DD, 0x99D8, 0x99D1, 0x99ED,
- 0x99EE, 0x99F1, 0x99F2, 0x99FB, 0x99F8, 0x9A01, 0x9A0F, 0x9A05,
- 0x99E2, 0x9A19, 0x9A2B, 0x9A37, 0x9A45, 0x9A42, 0x9A40, 0x9A43,
- 0x9A3E, 0x9A55, 0x9A4D, 0x9A5B, 0x9A57, 0x9A5F, 0x9A62, 0x9A65,
- 0x9A64, 0x9A69, 0x9A6B, 0x9A6A, 0x9AAD, 0x9AB0, 0x9ABC, 0x9AC0,
- 0x9ACF, 0x9AD1, 0x9AD3, 0x9AD4, 0x9ADE, 0x9ADF, 0x9AE2, 0x9AE3,
- 0x9AE6, 0x9AEF, 0x9AEB, 0x9AEE, 0x9AF4, 0x9AF1, 0x9AF7,
-};
-const unsigned short euc_to_utf8_F2[] = {
- 0x9AFB, 0x9B06, 0x9B18, 0x9B1A, 0x9B1F, 0x9B22, 0x9B23,
- 0x9B25, 0x9B27, 0x9B28, 0x9B29, 0x9B2A, 0x9B2E, 0x9B2F, 0x9B32,
- 0x9B44, 0x9B43, 0x9B4F, 0x9B4D, 0x9B4E, 0x9B51, 0x9B58, 0x9B74,
- 0x9B93, 0x9B83, 0x9B91, 0x9B96, 0x9B97, 0x9B9F, 0x9BA0, 0x9BA8,
- 0x9BB4, 0x9BC0, 0x9BCA, 0x9BB9, 0x9BC6, 0x9BCF, 0x9BD1, 0x9BD2,
- 0x9BE3, 0x9BE2, 0x9BE4, 0x9BD4, 0x9BE1, 0x9C3A, 0x9BF2, 0x9BF1,
- 0x9BF0, 0x9C15, 0x9C14, 0x9C09, 0x9C13, 0x9C0C, 0x9C06, 0x9C08,
- 0x9C12, 0x9C0A, 0x9C04, 0x9C2E, 0x9C1B, 0x9C25, 0x9C24, 0x9C21,
- 0x9C30, 0x9C47, 0x9C32, 0x9C46, 0x9C3E, 0x9C5A, 0x9C60, 0x9C67,
- 0x9C76, 0x9C78, 0x9CE7, 0x9CEC, 0x9CF0, 0x9D09, 0x9D08, 0x9CEB,
- 0x9D03, 0x9D06, 0x9D2A, 0x9D26, 0x9DAF, 0x9D23, 0x9D1F, 0x9D44,
- 0x9D15, 0x9D12, 0x9D41, 0x9D3F, 0x9D3E, 0x9D46, 0x9D48,
-};
-const unsigned short euc_to_utf8_F3[] = {
- 0x9D5D, 0x9D5E, 0x9D64, 0x9D51, 0x9D50, 0x9D59, 0x9D72,
- 0x9D89, 0x9D87, 0x9DAB, 0x9D6F, 0x9D7A, 0x9D9A, 0x9DA4, 0x9DA9,
- 0x9DB2, 0x9DC4, 0x9DC1, 0x9DBB, 0x9DB8, 0x9DBA, 0x9DC6, 0x9DCF,
- 0x9DC2, 0x9DD9, 0x9DD3, 0x9DF8, 0x9DE6, 0x9DED, 0x9DEF, 0x9DFD,
- 0x9E1A, 0x9E1B, 0x9E1E, 0x9E75, 0x9E79, 0x9E7D, 0x9E81, 0x9E88,
- 0x9E8B, 0x9E8C, 0x9E92, 0x9E95, 0x9E91, 0x9E9D, 0x9EA5, 0x9EA9,
- 0x9EB8, 0x9EAA, 0x9EAD, 0x9761, 0x9ECC, 0x9ECE, 0x9ECF, 0x9ED0,
- 0x9ED4, 0x9EDC, 0x9EDE, 0x9EDD, 0x9EE0, 0x9EE5, 0x9EE8, 0x9EEF,
- 0x9EF4, 0x9EF6, 0x9EF7, 0x9EF9, 0x9EFB, 0x9EFC, 0x9EFD, 0x9F07,
- 0x9F08, 0x76B7, 0x9F15, 0x9F21, 0x9F2C, 0x9F3E, 0x9F4A, 0x9F52,
- 0x9F54, 0x9F63, 0x9F5F, 0x9F60, 0x9F61, 0x9F66, 0x9F67, 0x9F6C,
- 0x9F6A, 0x9F77, 0x9F72, 0x9F76, 0x9F95, 0x9F9C, 0x9FA0,
-};
-const unsigned short euc_to_utf8_F4[] = {
- 0x582F, 0x69C7, 0x9059, 0x7464, 0x51DC, 0x7199, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_F5[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFE33, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFE31, 0, 0,
- 0, 0, 0, 0, 0, 0xFE30, 0, 0,
- 0, 0, 0xFE35, 0xFE36, 0xFE39, 0xFE3A, 0, 0,
- 0xFE37, 0xFE38, 0xFE3F, 0xFE40, 0xFE3D, 0xFE3E, 0xFE41, 0xFE42,
- 0xFE43, 0xFE44, 0xFE3B, 0xFE3C, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_F9[] = {
- 0x7E8A, 0x891C, 0x9348, 0x9288, 0x84DC, 0x4FC9, 0x70BB,
- 0x6631, 0x68C8, 0x92F9, 0x66FB, 0x5F45, 0x4E28, 0x4EE1, 0x4EFC,
- 0x4F00, 0x4F03, 0x4F39, 0x4F56, 0x4F92, 0x4F8A, 0x4F9A, 0x4F94,
- 0x4FCD, 0x5040, 0x5022, 0x4FFF, 0x501E, 0x5046, 0x5070, 0x5042,
- 0x5094, 0x50F4, 0x50D8, 0x514A, 0x5164, 0x519D, 0x51BE, 0x51EC,
- 0x5215, 0x529C, 0x52A6, 0x52C0, 0x52DB, 0x5300, 0x5307, 0x5324,
- 0x5372, 0x5393, 0x53B2, 0x53DD, 0xFA0E, 0x549C, 0x548A, 0x54A9,
- 0x54FF, 0x5586, 0x5759, 0x5765, 0x57AC, 0x57C8, 0x57C7, 0xFA0F,
- 0xFA10, 0x589E, 0x58B2, 0x590B, 0x5953, 0x595B, 0x595D, 0x5963,
- 0x59A4, 0x59BA, 0x5B56, 0x5BC0, 0x752F, 0x5BD8, 0x5BEC, 0x5C1E,
- 0x5CA6, 0x5CBA, 0x5CF5, 0x5D27, 0x5D53, 0xFA11, 0x5D42, 0x5D6D,
- 0x5DB8, 0x5DB9, 0x5DD0, 0x5F21, 0x5F34, 0x5F67, 0x5FB7,
-};
-const unsigned short euc_to_utf8_FA[] = {
- 0x5FDE, 0x605D, 0x6085, 0x608A, 0x60DE, 0x60D5, 0x6120,
- 0x60F2, 0x6111, 0x6137, 0x6130, 0x6198, 0x6213, 0x62A6, 0x63F5,
- 0x6460, 0x649D, 0x64CE, 0x654E, 0x6600, 0x6615, 0x663B, 0x6609,
- 0x662E, 0x661E, 0x6624, 0x6665, 0x6657, 0x6659, 0xFA12, 0x6673,
- 0x6699, 0x66A0, 0x66B2, 0x66BF, 0x66FA, 0x670E, 0xF929, 0x6766,
- 0x67BB, 0x6852, 0x67C0, 0x6801, 0x6844, 0x68CF, 0xFA13, 0x6968,
- 0xFA14, 0x6998, 0x69E2, 0x6A30, 0x6A6B, 0x6A46, 0x6A73, 0x6A7E,
- 0x6AE2, 0x6AE4, 0x6BD6, 0x6C3F, 0x6C5C, 0x6C86, 0x6C6F, 0x6CDA,
- 0x6D04, 0x6D87, 0x6D6F, 0x6D96, 0x6DAC, 0x6DCF, 0x6DF8, 0x6DF2,
- 0x6DFC, 0x6E39, 0x6E5C, 0x6E27, 0x6E3C, 0x6EBF, 0x6F88, 0x6FB5,
- 0x6FF5, 0x7005, 0x7007, 0x7028, 0x7085, 0x70AB, 0x710F, 0x7104,
- 0x715C, 0x7146, 0x7147, 0xFA15, 0x71C1, 0x71FE, 0x72B1,
-};
-const unsigned short euc_to_utf8_FB[] = {
- 0x72BE, 0x7324, 0xFA16, 0x7377, 0x73BD, 0x73C9, 0x73D6,
- 0x73E3, 0x73D2, 0x7407, 0x73F5, 0x7426, 0x742A, 0x7429, 0x742E,
- 0x7462, 0x7489, 0x749F, 0x7501, 0x756F, 0x7682, 0x769C, 0x769E,
- 0x769B, 0x76A6, 0xFA17, 0x7746, 0x52AF, 0x7821, 0x784E, 0x7864,
- 0x787A, 0x7930, 0xFA18, 0xFA19, 0xFA1A, 0x7994, 0xFA1B, 0x799B,
- 0x7AD1, 0x7AE7, 0xFA1C, 0x7AEB, 0x7B9E, 0xFA1D, 0x7D48, 0x7D5C,
- 0x7DB7, 0x7DA0, 0x7DD6, 0x7E52, 0x7F47, 0x7FA1, 0xFA1E, 0x8301,
- 0x8362, 0x837F, 0x83C7, 0x83F6, 0x8448, 0x84B4, 0x8553, 0x8559,
- 0x856B, 0xFA1F, 0x85B0, 0xFA20, 0xFA21, 0x8807, 0x88F5, 0x8A12,
- 0x8A37, 0x8A79, 0x8AA7, 0x8ABE, 0x8ADF, 0xFA22, 0x8AF6, 0x8B53,
- 0x8B7F, 0x8CF0, 0x8CF4, 0x8D12, 0x8D76, 0xFA23, 0x8ECF, 0xFA24,
- 0xFA25, 0x9067, 0x90DE, 0xFA26, 0x9115, 0x9127, 0x91DA,
-};
-const unsigned short euc_to_utf8_FC[] = {
- 0x91D7, 0x91DE, 0x91ED, 0x91EE, 0x91E4, 0x91E5, 0x9206,
- 0x9210, 0x920A, 0x923A, 0x9240, 0x923C, 0x924E, 0x9259, 0x9251,
- 0x9239, 0x9267, 0x92A7, 0x9277, 0x9278, 0x92E7, 0x92D7, 0x92D9,
- 0x92D0, 0xFA27, 0x92D5, 0x92E0, 0x92D3, 0x9325, 0x9321, 0x92FB,
- 0xFA28, 0x931E, 0x92FF, 0x931D, 0x9302, 0x9370, 0x9357, 0x93A4,
- 0x93C6, 0x93DE, 0x93F8, 0x9431, 0x9445, 0x9448, 0x9592, 0xF9DC,
- 0xFA29, 0x969D, 0x96AF, 0x9733, 0x973B, 0x9743, 0x974D, 0x974F,
- 0x9751, 0x9755, 0x9857, 0x9865, 0xFA2A, 0xFA2B, 0x9927, 0xFA2C,
- 0x999E, 0x9A4E, 0x9AD9, 0x9ADC, 0x9B75, 0x9B72, 0x9B8F, 0x9BB1,
- 0x9BBB, 0x9C00, 0x9D70, 0x9D6B, 0xFA2D, 0x9E19, 0x9ED1, 0,
- 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176,
- 0x2177, 0x2178, 0x2179, 0xFFE2, 0x00A6, 0xFF07, 0xFF02,
-};
-
-/* Microsoft UCS Mapping Compatible */
-const unsigned short euc_to_utf8_FC_ms[] = {
- 0x91D7, 0x91DE, 0x91ED, 0x91EE, 0x91E4, 0x91E5, 0x9206,
- 0x9210, 0x920A, 0x923A, 0x9240, 0x923C, 0x924E, 0x9259, 0x9251,
- 0x9239, 0x9267, 0x92A7, 0x9277, 0x9278, 0x92E7, 0x92D7, 0x92D9,
- 0x92D0, 0xFA27, 0x92D5, 0x92E0, 0x92D3, 0x9325, 0x9321, 0x92FB,
- 0xFA28, 0x931E, 0x92FF, 0x931D, 0x9302, 0x9370, 0x9357, 0x93A4,
- 0x93C6, 0x93DE, 0x93F8, 0x9431, 0x9445, 0x9448, 0x9592, 0xF9DC,
- 0xFA29, 0x969D, 0x96AF, 0x9733, 0x973B, 0x9743, 0x974D, 0x974F,
- 0x9751, 0x9755, 0x9857, 0x9865, 0xFA2A, 0xFA2B, 0x9927, 0xFA2C,
- 0x999E, 0x9A4E, 0x9AD9, 0x9ADC, 0x9B75, 0x9B72, 0x9B8F, 0x9BB1,
- 0x9BBB, 0x9C00, 0x9D70, 0x9D6B, 0xFA2D, 0x9E19, 0x9ED1, 0,
- 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176,
- 0x2177, 0x2178, 0x2179, 0xFFE2, 0xFFE4, 0xFF07, 0xFF02,
-};
-
-#ifdef X0212_ENABLE
-const unsigned short euc_to_utf8_8FA2[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x02D8,
- 0x02C7, 0x00B8, 0x02D9, 0x02DD, 0x00AF, 0x02DB, 0x02DA, 0xFF5E,
- 0x0384, 0x0385, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x00A1, 0xFFE4, 0x00BF, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x00BA, 0x00AA, 0x00A9, 0x00AE, 0x2122,
- 0x00A4, 0x2116, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_8FA6[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x0386, 0x0388, 0x0389, 0x038A, 0x03AA, 0, 0x038C,
- 0, 0x038E, 0x03AB, 0, 0x038F, 0, 0, 0,
- 0, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03CA, 0x0390, 0x03CC,
- 0x03C2, 0x03CD, 0x03CB, 0x03B0, 0x03CE, 0, 0,
-};
-const unsigned short euc_to_utf8_8FA7[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
- 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
- 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045E, 0x045F,
-};
-const unsigned short euc_to_utf8_8FA9[] = {
- 0x00C6, 0x0110, 0, 0x0126, 0, 0x0132, 0,
- 0x0141, 0x013F, 0, 0x014A, 0x00D8, 0x0152, 0, 0x0166,
- 0x00DE, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x00E6, 0x0111, 0x00F0, 0x0127, 0x0131, 0x0133, 0x0138,
- 0x0142, 0x0140, 0x0149, 0x014B, 0x00F8, 0x0153, 0x00DF, 0x0167,
- 0x00FE, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_8FAA[] = {
- 0x00C1, 0x00C0, 0x00C4, 0x00C2, 0x0102, 0x01CD, 0x0100,
- 0x0104, 0x00C5, 0x00C3, 0x0106, 0x0108, 0x010C, 0x00C7, 0x010A,
- 0x010E, 0x00C9, 0x00C8, 0x00CB, 0x00CA, 0x011A, 0x0116, 0x0112,
- 0x0118, 0, 0x011C, 0x011E, 0x0122, 0x0120, 0x0124, 0x00CD,
- 0x00CC, 0x00CF, 0x00CE, 0x01CF, 0x0130, 0x012A, 0x012E, 0x0128,
- 0x0134, 0x0136, 0x0139, 0x013D, 0x013B, 0x0143, 0x0147, 0x0145,
- 0x00D1, 0x00D3, 0x00D2, 0x00D6, 0x00D4, 0x01D1, 0x0150, 0x014C,
- 0x00D5, 0x0154, 0x0158, 0x0156, 0x015A, 0x015C, 0x0160, 0x015E,
- 0x0164, 0x0162, 0x00DA, 0x00D9, 0x00DC, 0x00DB, 0x016C, 0x01D3,
- 0x0170, 0x016A, 0x0172, 0x016E, 0x0168, 0x01D7, 0x01DB, 0x01D9,
- 0x01D5, 0x0174, 0x00DD, 0x0178, 0x0176, 0x0179, 0x017D, 0x017B,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_8FAB[] = {
- 0x00E1, 0x00E0, 0x00E4, 0x00E2, 0x0103, 0x01CE, 0x0101,
- 0x0105, 0x00E5, 0x00E3, 0x0107, 0x0109, 0x010D, 0x00E7, 0x010B,
- 0x010F, 0x00E9, 0x00E8, 0x00EB, 0x00EA, 0x011B, 0x0117, 0x0113,
- 0x0119, 0x01F5, 0x011D, 0x011F, 0, 0x0121, 0x0125, 0x00ED,
- 0x00EC, 0x00EF, 0x00EE, 0x01D0, 0, 0x012B, 0x012F, 0x0129,
- 0x0135, 0x0137, 0x013A, 0x013E, 0x013C, 0x0144, 0x0148, 0x0146,
- 0x00F1, 0x00F3, 0x00F2, 0x00F6, 0x00F4, 0x01D2, 0x0151, 0x014D,
- 0x00F5, 0x0155, 0x0159, 0x0157, 0x015B, 0x015D, 0x0161, 0x015F,
- 0x0165, 0x0163, 0x00FA, 0x00F9, 0x00FC, 0x00FB, 0x016D, 0x01D4,
- 0x0171, 0x016B, 0x0173, 0x016F, 0x0169, 0x01D8, 0x01DC, 0x01DA,
- 0x01D6, 0x0175, 0x00FD, 0x00FF, 0x0177, 0x017A, 0x017E, 0x017C,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_8FB0[] = {
- 0x4E02, 0x4E04, 0x4E05, 0x4E0C, 0x4E12, 0x4E1F, 0x4E23,
- 0x4E24, 0x4E28, 0x4E2B, 0x4E2E, 0x4E2F, 0x4E30, 0x4E35, 0x4E40,
- 0x4E41, 0x4E44, 0x4E47, 0x4E51, 0x4E5A, 0x4E5C, 0x4E63, 0x4E68,
- 0x4E69, 0x4E74, 0x4E75, 0x4E79, 0x4E7F, 0x4E8D, 0x4E96, 0x4E97,
- 0x4E9D, 0x4EAF, 0x4EB9, 0x4EC3, 0x4ED0, 0x4EDA, 0x4EDB, 0x4EE0,
- 0x4EE1, 0x4EE2, 0x4EE8, 0x4EEF, 0x4EF1, 0x4EF3, 0x4EF5, 0x4EFD,
- 0x4EFE, 0x4EFF, 0x4F00, 0x4F02, 0x4F03, 0x4F08, 0x4F0B, 0x4F0C,
- 0x4F12, 0x4F15, 0x4F16, 0x4F17, 0x4F19, 0x4F2E, 0x4F31, 0x4F60,
- 0x4F33, 0x4F35, 0x4F37, 0x4F39, 0x4F3B, 0x4F3E, 0x4F40, 0x4F42,
- 0x4F48, 0x4F49, 0x4F4B, 0x4F4C, 0x4F52, 0x4F54, 0x4F56, 0x4F58,
- 0x4F5F, 0x4F63, 0x4F6A, 0x4F6C, 0x4F6E, 0x4F71, 0x4F77, 0x4F78,
- 0x4F79, 0x4F7A, 0x4F7D, 0x4F7E, 0x4F81, 0x4F82, 0x4F84,
-};
-const unsigned short euc_to_utf8_8FB1[] = {
- 0x4F85, 0x4F89, 0x4F8A, 0x4F8C, 0x4F8E, 0x4F90, 0x4F92,
- 0x4F93, 0x4F94, 0x4F97, 0x4F99, 0x4F9A, 0x4F9E, 0x4F9F, 0x4FB2,
- 0x4FB7, 0x4FB9, 0x4FBB, 0x4FBC, 0x4FBD, 0x4FBE, 0x4FC0, 0x4FC1,
- 0x4FC5, 0x4FC6, 0x4FC8, 0x4FC9, 0x4FCB, 0x4FCC, 0x4FCD, 0x4FCF,
- 0x4FD2, 0x4FDC, 0x4FE0, 0x4FE2, 0x4FF0, 0x4FF2, 0x4FFC, 0x4FFD,
- 0x4FFF, 0x5000, 0x5001, 0x5004, 0x5007, 0x500A, 0x500C, 0x500E,
- 0x5010, 0x5013, 0x5017, 0x5018, 0x501B, 0x501C, 0x501D, 0x501E,
- 0x5022, 0x5027, 0x502E, 0x5030, 0x5032, 0x5033, 0x5035, 0x5040,
- 0x5041, 0x5042, 0x5045, 0x5046, 0x504A, 0x504C, 0x504E, 0x5051,
- 0x5052, 0x5053, 0x5057, 0x5059, 0x505F, 0x5060, 0x5062, 0x5063,
- 0x5066, 0x5067, 0x506A, 0x506D, 0x5070, 0x5071, 0x503B, 0x5081,
- 0x5083, 0x5084, 0x5086, 0x508A, 0x508E, 0x508F, 0x5090,
-};
-const unsigned short euc_to_utf8_8FB2[] = {
- 0x5092, 0x5093, 0x5094, 0x5096, 0x509B, 0x509C, 0x509E,
- 0x509F, 0x50A0, 0x50A1, 0x50A2, 0x50AA, 0x50AF, 0x50B0, 0x50B9,
- 0x50BA, 0x50BD, 0x50C0, 0x50C3, 0x50C4, 0x50C7, 0x50CC, 0x50CE,
- 0x50D0, 0x50D3, 0x50D4, 0x50D8, 0x50DC, 0x50DD, 0x50DF, 0x50E2,
- 0x50E4, 0x50E6, 0x50E8, 0x50E9, 0x50EF, 0x50F1, 0x50F6, 0x50FA,
- 0x50FE, 0x5103, 0x5106, 0x5107, 0x5108, 0x510B, 0x510C, 0x510D,
- 0x510E, 0x50F2, 0x5110, 0x5117, 0x5119, 0x511B, 0x511C, 0x511D,
- 0x511E, 0x5123, 0x5127, 0x5128, 0x512C, 0x512D, 0x512F, 0x5131,
- 0x5133, 0x5134, 0x5135, 0x5138, 0x5139, 0x5142, 0x514A, 0x514F,
- 0x5153, 0x5155, 0x5157, 0x5158, 0x515F, 0x5164, 0x5166, 0x517E,
- 0x5183, 0x5184, 0x518B, 0x518E, 0x5198, 0x519D, 0x51A1, 0x51A3,
- 0x51AD, 0x51B8, 0x51BA, 0x51BC, 0x51BE, 0x51BF, 0x51C2,
-};
-const unsigned short euc_to_utf8_8FB3[] = {
- 0x51C8, 0x51CF, 0x51D1, 0x51D2, 0x51D3, 0x51D5, 0x51D8,
- 0x51DE, 0x51E2, 0x51E5, 0x51EE, 0x51F2, 0x51F3, 0x51F4, 0x51F7,
- 0x5201, 0x5202, 0x5205, 0x5212, 0x5213, 0x5215, 0x5216, 0x5218,
- 0x5222, 0x5228, 0x5231, 0x5232, 0x5235, 0x523C, 0x5245, 0x5249,
- 0x5255, 0x5257, 0x5258, 0x525A, 0x525C, 0x525F, 0x5260, 0x5261,
- 0x5266, 0x526E, 0x5277, 0x5278, 0x5279, 0x5280, 0x5282, 0x5285,
- 0x528A, 0x528C, 0x5293, 0x5295, 0x5296, 0x5297, 0x5298, 0x529A,
- 0x529C, 0x52A4, 0x52A5, 0x52A6, 0x52A7, 0x52AF, 0x52B0, 0x52B6,
- 0x52B7, 0x52B8, 0x52BA, 0x52BB, 0x52BD, 0x52C0, 0x52C4, 0x52C6,
- 0x52C8, 0x52CC, 0x52CF, 0x52D1, 0x52D4, 0x52D6, 0x52DB, 0x52DC,
- 0x52E1, 0x52E5, 0x52E8, 0x52E9, 0x52EA, 0x52EC, 0x52F0, 0x52F1,
- 0x52F4, 0x52F6, 0x52F7, 0x5300, 0x5303, 0x530A, 0x530B,
-};
-const unsigned short euc_to_utf8_8FB4[] = {
- 0x530C, 0x5311, 0x5313, 0x5318, 0x531B, 0x531C, 0x531E,
- 0x531F, 0x5325, 0x5327, 0x5328, 0x5329, 0x532B, 0x532C, 0x532D,
- 0x5330, 0x5332, 0x5335, 0x533C, 0x533D, 0x533E, 0x5342, 0x534C,
- 0x534B, 0x5359, 0x535B, 0x5361, 0x5363, 0x5365, 0x536C, 0x536D,
- 0x5372, 0x5379, 0x537E, 0x5383, 0x5387, 0x5388, 0x538E, 0x5393,
- 0x5394, 0x5399, 0x539D, 0x53A1, 0x53A4, 0x53AA, 0x53AB, 0x53AF,
- 0x53B2, 0x53B4, 0x53B5, 0x53B7, 0x53B8, 0x53BA, 0x53BD, 0x53C0,
- 0x53C5, 0x53CF, 0x53D2, 0x53D3, 0x53D5, 0x53DA, 0x53DD, 0x53DE,
- 0x53E0, 0x53E6, 0x53E7, 0x53F5, 0x5402, 0x5413, 0x541A, 0x5421,
- 0x5427, 0x5428, 0x542A, 0x542F, 0x5431, 0x5434, 0x5435, 0x5443,
- 0x5444, 0x5447, 0x544D, 0x544F, 0x545E, 0x5462, 0x5464, 0x5466,
- 0x5467, 0x5469, 0x546B, 0x546D, 0x546E, 0x5474, 0x547F,
-};
-const unsigned short euc_to_utf8_8FB5[] = {
- 0x5481, 0x5483, 0x5485, 0x5488, 0x5489, 0x548D, 0x5491,
- 0x5495, 0x5496, 0x549C, 0x549F, 0x54A1, 0x54A6, 0x54A7, 0x54A9,
- 0x54AA, 0x54AD, 0x54AE, 0x54B1, 0x54B7, 0x54B9, 0x54BA, 0x54BB,
- 0x54BF, 0x54C6, 0x54CA, 0x54CD, 0x54CE, 0x54E0, 0x54EA, 0x54EC,
- 0x54EF, 0x54F6, 0x54FC, 0x54FE, 0x54FF, 0x5500, 0x5501, 0x5505,
- 0x5508, 0x5509, 0x550C, 0x550D, 0x550E, 0x5515, 0x552A, 0x552B,
- 0x5532, 0x5535, 0x5536, 0x553B, 0x553C, 0x553D, 0x5541, 0x5547,
- 0x5549, 0x554A, 0x554D, 0x5550, 0x5551, 0x5558, 0x555A, 0x555B,
- 0x555E, 0x5560, 0x5561, 0x5564, 0x5566, 0x557F, 0x5581, 0x5582,
- 0x5586, 0x5588, 0x558E, 0x558F, 0x5591, 0x5592, 0x5593, 0x5594,
- 0x5597, 0x55A3, 0x55A4, 0x55AD, 0x55B2, 0x55BF, 0x55C1, 0x55C3,
- 0x55C6, 0x55C9, 0x55CB, 0x55CC, 0x55CE, 0x55D1, 0x55D2,
-};
-const unsigned short euc_to_utf8_8FB6[] = {
- 0x55D3, 0x55D7, 0x55D8, 0x55DB, 0x55DE, 0x55E2, 0x55E9,
- 0x55F6, 0x55FF, 0x5605, 0x5608, 0x560A, 0x560D, 0x560E, 0x560F,
- 0x5610, 0x5611, 0x5612, 0x5619, 0x562C, 0x5630, 0x5633, 0x5635,
- 0x5637, 0x5639, 0x563B, 0x563C, 0x563D, 0x563F, 0x5640, 0x5641,
- 0x5643, 0x5644, 0x5646, 0x5649, 0x564B, 0x564D, 0x564F, 0x5654,
- 0x565E, 0x5660, 0x5661, 0x5662, 0x5663, 0x5666, 0x5669, 0x566D,
- 0x566F, 0x5671, 0x5672, 0x5675, 0x5684, 0x5685, 0x5688, 0x568B,
- 0x568C, 0x5695, 0x5699, 0x569A, 0x569D, 0x569E, 0x569F, 0x56A6,
- 0x56A7, 0x56A8, 0x56A9, 0x56AB, 0x56AC, 0x56AD, 0x56B1, 0x56B3,
- 0x56B7, 0x56BE, 0x56C5, 0x56C9, 0x56CA, 0x56CB, 0x56CF, 0x56D0,
- 0x56CC, 0x56CD, 0x56D9, 0x56DC, 0x56DD, 0x56DF, 0x56E1, 0x56E4,
- 0x56E5, 0x56E6, 0x56E7, 0x56E8, 0x56F1, 0x56EB, 0x56ED,
-};
-const unsigned short euc_to_utf8_8FB7[] = {
- 0x56F6, 0x56F7, 0x5701, 0x5702, 0x5707, 0x570A, 0x570C,
- 0x5711, 0x5715, 0x571A, 0x571B, 0x571D, 0x5720, 0x5722, 0x5723,
- 0x5724, 0x5725, 0x5729, 0x572A, 0x572C, 0x572E, 0x572F, 0x5733,
- 0x5734, 0x573D, 0x573E, 0x573F, 0x5745, 0x5746, 0x574C, 0x574D,
- 0x5752, 0x5762, 0x5765, 0x5767, 0x5768, 0x576B, 0x576D, 0x576E,
- 0x576F, 0x5770, 0x5771, 0x5773, 0x5774, 0x5775, 0x5777, 0x5779,
- 0x577A, 0x577B, 0x577C, 0x577E, 0x5781, 0x5783, 0x578C, 0x5794,
- 0x5797, 0x5799, 0x579A, 0x579C, 0x579D, 0x579E, 0x579F, 0x57A1,
- 0x5795, 0x57A7, 0x57A8, 0x57A9, 0x57AC, 0x57B8, 0x57BD, 0x57C7,
- 0x57C8, 0x57CC, 0x57CF, 0x57D5, 0x57DD, 0x57DE, 0x57E4, 0x57E6,
- 0x57E7, 0x57E9, 0x57ED, 0x57F0, 0x57F5, 0x57F6, 0x57F8, 0x57FD,
- 0x57FE, 0x57FF, 0x5803, 0x5804, 0x5808, 0x5809, 0x57E1,
-};
-const unsigned short euc_to_utf8_8FB8[] = {
- 0x580C, 0x580D, 0x581B, 0x581E, 0x581F, 0x5820, 0x5826,
- 0x5827, 0x582D, 0x5832, 0x5839, 0x583F, 0x5849, 0x584C, 0x584D,
- 0x584F, 0x5850, 0x5855, 0x585F, 0x5861, 0x5864, 0x5867, 0x5868,
- 0x5878, 0x587C, 0x587F, 0x5880, 0x5881, 0x5887, 0x5888, 0x5889,
- 0x588A, 0x588C, 0x588D, 0x588F, 0x5890, 0x5894, 0x5896, 0x589D,
- 0x58A0, 0x58A1, 0x58A2, 0x58A6, 0x58A9, 0x58B1, 0x58B2, 0x58C4,
- 0x58BC, 0x58C2, 0x58C8, 0x58CD, 0x58CE, 0x58D0, 0x58D2, 0x58D4,
- 0x58D6, 0x58DA, 0x58DD, 0x58E1, 0x58E2, 0x58E9, 0x58F3, 0x5905,
- 0x5906, 0x590B, 0x590C, 0x5912, 0x5913, 0x5914, 0x8641, 0x591D,
- 0x5921, 0x5923, 0x5924, 0x5928, 0x592F, 0x5930, 0x5933, 0x5935,
- 0x5936, 0x593F, 0x5943, 0x5946, 0x5952, 0x5953, 0x5959, 0x595B,
- 0x595D, 0x595E, 0x595F, 0x5961, 0x5963, 0x596B, 0x596D,
-};
-const unsigned short euc_to_utf8_8FB9[] = {
- 0x596F, 0x5972, 0x5975, 0x5976, 0x5979, 0x597B, 0x597C,
- 0x598B, 0x598C, 0x598E, 0x5992, 0x5995, 0x5997, 0x599F, 0x59A4,
- 0x59A7, 0x59AD, 0x59AE, 0x59AF, 0x59B0, 0x59B3, 0x59B7, 0x59BA,
- 0x59BC, 0x59C1, 0x59C3, 0x59C4, 0x59C8, 0x59CA, 0x59CD, 0x59D2,
- 0x59DD, 0x59DE, 0x59DF, 0x59E3, 0x59E4, 0x59E7, 0x59EE, 0x59EF,
- 0x59F1, 0x59F2, 0x59F4, 0x59F7, 0x5A00, 0x5A04, 0x5A0C, 0x5A0D,
- 0x5A0E, 0x5A12, 0x5A13, 0x5A1E, 0x5A23, 0x5A24, 0x5A27, 0x5A28,
- 0x5A2A, 0x5A2D, 0x5A30, 0x5A44, 0x5A45, 0x5A47, 0x5A48, 0x5A4C,
- 0x5A50, 0x5A55, 0x5A5E, 0x5A63, 0x5A65, 0x5A67, 0x5A6D, 0x5A77,
- 0x5A7A, 0x5A7B, 0x5A7E, 0x5A8B, 0x5A90, 0x5A93, 0x5A96, 0x5A99,
- 0x5A9C, 0x5A9E, 0x5A9F, 0x5AA0, 0x5AA2, 0x5AA7, 0x5AAC, 0x5AB1,
- 0x5AB2, 0x5AB3, 0x5AB5, 0x5AB8, 0x5ABA, 0x5ABB, 0x5ABF,
-};
-const unsigned short euc_to_utf8_8FBA[] = {
- 0x5AC4, 0x5AC6, 0x5AC8, 0x5ACF, 0x5ADA, 0x5ADC, 0x5AE0,
- 0x5AE5, 0x5AEA, 0x5AEE, 0x5AF5, 0x5AF6, 0x5AFD, 0x5B00, 0x5B01,
- 0x5B08, 0x5B17, 0x5B34, 0x5B19, 0x5B1B, 0x5B1D, 0x5B21, 0x5B25,
- 0x5B2D, 0x5B38, 0x5B41, 0x5B4B, 0x5B4C, 0x5B52, 0x5B56, 0x5B5E,
- 0x5B68, 0x5B6E, 0x5B6F, 0x5B7C, 0x5B7D, 0x5B7E, 0x5B7F, 0x5B81,
- 0x5B84, 0x5B86, 0x5B8A, 0x5B8E, 0x5B90, 0x5B91, 0x5B93, 0x5B94,
- 0x5B96, 0x5BA8, 0x5BA9, 0x5BAC, 0x5BAD, 0x5BAF, 0x5BB1, 0x5BB2,
- 0x5BB7, 0x5BBA, 0x5BBC, 0x5BC0, 0x5BC1, 0x5BCD, 0x5BCF, 0x5BD6,
- 0x5BD7, 0x5BD8, 0x5BD9, 0x5BDA, 0x5BE0, 0x5BEF, 0x5BF1, 0x5BF4,
- 0x5BFD, 0x5C0C, 0x5C17, 0x5C1E, 0x5C1F, 0x5C23, 0x5C26, 0x5C29,
- 0x5C2B, 0x5C2C, 0x5C2E, 0x5C30, 0x5C32, 0x5C35, 0x5C36, 0x5C59,
- 0x5C5A, 0x5C5C, 0x5C62, 0x5C63, 0x5C67, 0x5C68, 0x5C69,
-};
-const unsigned short euc_to_utf8_8FBB[] = {
- 0x5C6D, 0x5C70, 0x5C74, 0x5C75, 0x5C7A, 0x5C7B, 0x5C7C,
- 0x5C7D, 0x5C87, 0x5C88, 0x5C8A, 0x5C8F, 0x5C92, 0x5C9D, 0x5C9F,
- 0x5CA0, 0x5CA2, 0x5CA3, 0x5CA6, 0x5CAA, 0x5CB2, 0x5CB4, 0x5CB5,
- 0x5CBA, 0x5CC9, 0x5CCB, 0x5CD2, 0x5CDD, 0x5CD7, 0x5CEE, 0x5CF1,
- 0x5CF2, 0x5CF4, 0x5D01, 0x5D06, 0x5D0D, 0x5D12, 0x5D2B, 0x5D23,
- 0x5D24, 0x5D26, 0x5D27, 0x5D31, 0x5D34, 0x5D39, 0x5D3D, 0x5D3F,
- 0x5D42, 0x5D43, 0x5D46, 0x5D48, 0x5D55, 0x5D51, 0x5D59, 0x5D4A,
- 0x5D5F, 0x5D60, 0x5D61, 0x5D62, 0x5D64, 0x5D6A, 0x5D6D, 0x5D70,
- 0x5D79, 0x5D7A, 0x5D7E, 0x5D7F, 0x5D81, 0x5D83, 0x5D88, 0x5D8A,
- 0x5D92, 0x5D93, 0x5D94, 0x5D95, 0x5D99, 0x5D9B, 0x5D9F, 0x5DA0,
- 0x5DA7, 0x5DAB, 0x5DB0, 0x5DB4, 0x5DB8, 0x5DB9, 0x5DC3, 0x5DC7,
- 0x5DCB, 0x5DD0, 0x5DCE, 0x5DD8, 0x5DD9, 0x5DE0, 0x5DE4,
-};
-const unsigned short euc_to_utf8_8FBC[] = {
- 0x5DE9, 0x5DF8, 0x5DF9, 0x5E00, 0x5E07, 0x5E0D, 0x5E12,
- 0x5E14, 0x5E15, 0x5E18, 0x5E1F, 0x5E20, 0x5E2E, 0x5E28, 0x5E32,
- 0x5E35, 0x5E3E, 0x5E4B, 0x5E50, 0x5E49, 0x5E51, 0x5E56, 0x5E58,
- 0x5E5B, 0x5E5C, 0x5E5E, 0x5E68, 0x5E6A, 0x5E6B, 0x5E6C, 0x5E6D,
- 0x5E6E, 0x5E70, 0x5E80, 0x5E8B, 0x5E8E, 0x5EA2, 0x5EA4, 0x5EA5,
- 0x5EA8, 0x5EAA, 0x5EAC, 0x5EB1, 0x5EB3, 0x5EBD, 0x5EBE, 0x5EBF,
- 0x5EC6, 0x5ECC, 0x5ECB, 0x5ECE, 0x5ED1, 0x5ED2, 0x5ED4, 0x5ED5,
- 0x5EDC, 0x5EDE, 0x5EE5, 0x5EEB, 0x5F02, 0x5F06, 0x5F07, 0x5F08,
- 0x5F0E, 0x5F19, 0x5F1C, 0x5F1D, 0x5F21, 0x5F22, 0x5F23, 0x5F24,
- 0x5F28, 0x5F2B, 0x5F2C, 0x5F2E, 0x5F30, 0x5F34, 0x5F36, 0x5F3B,
- 0x5F3D, 0x5F3F, 0x5F40, 0x5F44, 0x5F45, 0x5F47, 0x5F4D, 0x5F50,
- 0x5F54, 0x5F58, 0x5F5B, 0x5F60, 0x5F63, 0x5F64, 0x5F67,
-};
-const unsigned short euc_to_utf8_8FBD[] = {
- 0x5F6F, 0x5F72, 0x5F74, 0x5F75, 0x5F78, 0x5F7A, 0x5F7D,
- 0x5F7E, 0x5F89, 0x5F8D, 0x5F8F, 0x5F96, 0x5F9C, 0x5F9D, 0x5FA2,
- 0x5FA7, 0x5FAB, 0x5FA4, 0x5FAC, 0x5FAF, 0x5FB0, 0x5FB1, 0x5FB8,
- 0x5FC4, 0x5FC7, 0x5FC8, 0x5FC9, 0x5FCB, 0x5FD0, 0x5FD1, 0x5FD2,
- 0x5FD3, 0x5FD4, 0x5FDE, 0x5FE1, 0x5FE2, 0x5FE8, 0x5FE9, 0x5FEA,
- 0x5FEC, 0x5FED, 0x5FEE, 0x5FEF, 0x5FF2, 0x5FF3, 0x5FF6, 0x5FFA,
- 0x5FFC, 0x6007, 0x600A, 0x600D, 0x6013, 0x6014, 0x6017, 0x6018,
- 0x601A, 0x601F, 0x6024, 0x602D, 0x6033, 0x6035, 0x6040, 0x6047,
- 0x6048, 0x6049, 0x604C, 0x6051, 0x6054, 0x6056, 0x6057, 0x605D,
- 0x6061, 0x6067, 0x6071, 0x607E, 0x607F, 0x6082, 0x6086, 0x6088,
- 0x608A, 0x608E, 0x6091, 0x6093, 0x6095, 0x6098, 0x609D, 0x609E,
- 0x60A2, 0x60A4, 0x60A5, 0x60A8, 0x60B0, 0x60B1, 0x60B7,
-};
-const unsigned short euc_to_utf8_8FBE[] = {
- 0x60BB, 0x60BE, 0x60C2, 0x60C4, 0x60C8, 0x60C9, 0x60CA,
- 0x60CB, 0x60CE, 0x60CF, 0x60D4, 0x60D5, 0x60D9, 0x60DB, 0x60DD,
- 0x60DE, 0x60E2, 0x60E5, 0x60F2, 0x60F5, 0x60F8, 0x60FC, 0x60FD,
- 0x6102, 0x6107, 0x610A, 0x610C, 0x6110, 0x6111, 0x6112, 0x6113,
- 0x6114, 0x6116, 0x6117, 0x6119, 0x611C, 0x611E, 0x6122, 0x612A,
- 0x612B, 0x6130, 0x6131, 0x6135, 0x6136, 0x6137, 0x6139, 0x6141,
- 0x6145, 0x6146, 0x6149, 0x615E, 0x6160, 0x616C, 0x6172, 0x6178,
- 0x617B, 0x617C, 0x617F, 0x6180, 0x6181, 0x6183, 0x6184, 0x618B,
- 0x618D, 0x6192, 0x6193, 0x6197, 0x6198, 0x619C, 0x619D, 0x619F,
- 0x61A0, 0x61A5, 0x61A8, 0x61AA, 0x61AD, 0x61B8, 0x61B9, 0x61BC,
- 0x61C0, 0x61C1, 0x61C2, 0x61CE, 0x61CF, 0x61D5, 0x61DC, 0x61DD,
- 0x61DE, 0x61DF, 0x61E1, 0x61E2, 0x61E7, 0x61E9, 0x61E5,
-};
-const unsigned short euc_to_utf8_8FBF[] = {
- 0x61EC, 0x61ED, 0x61EF, 0x6201, 0x6203, 0x6204, 0x6207,
- 0x6213, 0x6215, 0x621C, 0x6220, 0x6222, 0x6223, 0x6227, 0x6229,
- 0x622B, 0x6239, 0x623D, 0x6242, 0x6243, 0x6244, 0x6246, 0x624C,
- 0x6250, 0x6251, 0x6252, 0x6254, 0x6256, 0x625A, 0x625C, 0x6264,
- 0x626D, 0x626F, 0x6273, 0x627A, 0x627D, 0x628D, 0x628E, 0x628F,
- 0x6290, 0x62A6, 0x62A8, 0x62B3, 0x62B6, 0x62B7, 0x62BA, 0x62BE,
- 0x62BF, 0x62C4, 0x62CE, 0x62D5, 0x62D6, 0x62DA, 0x62EA, 0x62F2,
- 0x62F4, 0x62FC, 0x62FD, 0x6303, 0x6304, 0x630A, 0x630B, 0x630D,
- 0x6310, 0x6313, 0x6316, 0x6318, 0x6329, 0x632A, 0x632D, 0x6335,
- 0x6336, 0x6339, 0x633C, 0x6341, 0x6342, 0x6343, 0x6344, 0x6346,
- 0x634A, 0x634B, 0x634E, 0x6352, 0x6353, 0x6354, 0x6358, 0x635B,
- 0x6365, 0x6366, 0x636C, 0x636D, 0x6371, 0x6374, 0x6375,
-};
-const unsigned short euc_to_utf8_8FC0[] = {
- 0x6378, 0x637C, 0x637D, 0x637F, 0x6382, 0x6384, 0x6387,
- 0x638A, 0x6390, 0x6394, 0x6395, 0x6399, 0x639A, 0x639E, 0x63A4,
- 0x63A6, 0x63AD, 0x63AE, 0x63AF, 0x63BD, 0x63C1, 0x63C5, 0x63C8,
- 0x63CE, 0x63D1, 0x63D3, 0x63D4, 0x63D5, 0x63DC, 0x63E0, 0x63E5,
- 0x63EA, 0x63EC, 0x63F2, 0x63F3, 0x63F5, 0x63F8, 0x63F9, 0x6409,
- 0x640A, 0x6410, 0x6412, 0x6414, 0x6418, 0x641E, 0x6420, 0x6422,
- 0x6424, 0x6425, 0x6429, 0x642A, 0x642F, 0x6430, 0x6435, 0x643D,
- 0x643F, 0x644B, 0x644F, 0x6451, 0x6452, 0x6453, 0x6454, 0x645A,
- 0x645B, 0x645C, 0x645D, 0x645F, 0x6460, 0x6461, 0x6463, 0x646D,
- 0x6473, 0x6474, 0x647B, 0x647D, 0x6485, 0x6487, 0x648F, 0x6490,
- 0x6491, 0x6498, 0x6499, 0x649B, 0x649D, 0x649F, 0x64A1, 0x64A3,
- 0x64A6, 0x64A8, 0x64AC, 0x64B3, 0x64BD, 0x64BE, 0x64BF,
-};
-const unsigned short euc_to_utf8_8FC1[] = {
- 0x64C4, 0x64C9, 0x64CA, 0x64CB, 0x64CC, 0x64CE, 0x64D0,
- 0x64D1, 0x64D5, 0x64D7, 0x64E4, 0x64E5, 0x64E9, 0x64EA, 0x64ED,
- 0x64F0, 0x64F5, 0x64F7, 0x64FB, 0x64FF, 0x6501, 0x6504, 0x6508,
- 0x6509, 0x650A, 0x650F, 0x6513, 0x6514, 0x6516, 0x6519, 0x651B,
- 0x651E, 0x651F, 0x6522, 0x6526, 0x6529, 0x652E, 0x6531, 0x653A,
- 0x653C, 0x653D, 0x6543, 0x6547, 0x6549, 0x6550, 0x6552, 0x6554,
- 0x655F, 0x6560, 0x6567, 0x656B, 0x657A, 0x657D, 0x6581, 0x6585,
- 0x658A, 0x6592, 0x6595, 0x6598, 0x659D, 0x65A0, 0x65A3, 0x65A6,
- 0x65AE, 0x65B2, 0x65B3, 0x65B4, 0x65BF, 0x65C2, 0x65C8, 0x65C9,
- 0x65CE, 0x65D0, 0x65D4, 0x65D6, 0x65D8, 0x65DF, 0x65F0, 0x65F2,
- 0x65F4, 0x65F5, 0x65F9, 0x65FE, 0x65FF, 0x6600, 0x6604, 0x6608,
- 0x6609, 0x660D, 0x6611, 0x6612, 0x6615, 0x6616, 0x661D,
-};
-const unsigned short euc_to_utf8_8FC2[] = {
- 0x661E, 0x6621, 0x6622, 0x6623, 0x6624, 0x6626, 0x6629,
- 0x662A, 0x662B, 0x662C, 0x662E, 0x6630, 0x6631, 0x6633, 0x6639,
- 0x6637, 0x6640, 0x6645, 0x6646, 0x664A, 0x664C, 0x6651, 0x664E,
- 0x6657, 0x6658, 0x6659, 0x665B, 0x665C, 0x6660, 0x6661, 0x66FB,
- 0x666A, 0x666B, 0x666C, 0x667E, 0x6673, 0x6675, 0x667F, 0x6677,
- 0x6678, 0x6679, 0x667B, 0x6680, 0x667C, 0x668B, 0x668C, 0x668D,
- 0x6690, 0x6692, 0x6699, 0x669A, 0x669B, 0x669C, 0x669F, 0x66A0,
- 0x66A4, 0x66AD, 0x66B1, 0x66B2, 0x66B5, 0x66BB, 0x66BF, 0x66C0,
- 0x66C2, 0x66C3, 0x66C8, 0x66CC, 0x66CE, 0x66CF, 0x66D4, 0x66DB,
- 0x66DF, 0x66E8, 0x66EB, 0x66EC, 0x66EE, 0x66FA, 0x6705, 0x6707,
- 0x670E, 0x6713, 0x6719, 0x671C, 0x6720, 0x6722, 0x6733, 0x673E,
- 0x6745, 0x6747, 0x6748, 0x674C, 0x6754, 0x6755, 0x675D,
-};
-const unsigned short euc_to_utf8_8FC3[] = {
- 0x6766, 0x676C, 0x676E, 0x6774, 0x6776, 0x677B, 0x6781,
- 0x6784, 0x678E, 0x678F, 0x6791, 0x6793, 0x6796, 0x6798, 0x6799,
- 0x679B, 0x67B0, 0x67B1, 0x67B2, 0x67B5, 0x67BB, 0x67BC, 0x67BD,
- 0x67F9, 0x67C0, 0x67C2, 0x67C3, 0x67C5, 0x67C8, 0x67C9, 0x67D2,
- 0x67D7, 0x67D9, 0x67DC, 0x67E1, 0x67E6, 0x67F0, 0x67F2, 0x67F6,
- 0x67F7, 0x6852, 0x6814, 0x6819, 0x681D, 0x681F, 0x6828, 0x6827,
- 0x682C, 0x682D, 0x682F, 0x6830, 0x6831, 0x6833, 0x683B, 0x683F,
- 0x6844, 0x6845, 0x684A, 0x684C, 0x6855, 0x6857, 0x6858, 0x685B,
- 0x686B, 0x686E, 0x686F, 0x6870, 0x6871, 0x6872, 0x6875, 0x6879,
- 0x687A, 0x687B, 0x687C, 0x6882, 0x6884, 0x6886, 0x6888, 0x6896,
- 0x6898, 0x689A, 0x689C, 0x68A1, 0x68A3, 0x68A5, 0x68A9, 0x68AA,
- 0x68AE, 0x68B2, 0x68BB, 0x68C5, 0x68C8, 0x68CC, 0x68CF,
-};
-const unsigned short euc_to_utf8_8FC4[] = {
- 0x68D0, 0x68D1, 0x68D3, 0x68D6, 0x68D9, 0x68DC, 0x68DD,
- 0x68E5, 0x68E8, 0x68EA, 0x68EB, 0x68EC, 0x68ED, 0x68F0, 0x68F1,
- 0x68F5, 0x68F6, 0x68FB, 0x68FC, 0x68FD, 0x6906, 0x6909, 0x690A,
- 0x6910, 0x6911, 0x6913, 0x6916, 0x6917, 0x6931, 0x6933, 0x6935,
- 0x6938, 0x693B, 0x6942, 0x6945, 0x6949, 0x694E, 0x6957, 0x695B,
- 0x6963, 0x6964, 0x6965, 0x6966, 0x6968, 0x6969, 0x696C, 0x6970,
- 0x6971, 0x6972, 0x697A, 0x697B, 0x697F, 0x6980, 0x698D, 0x6992,
- 0x6996, 0x6998, 0x69A1, 0x69A5, 0x69A6, 0x69A8, 0x69AB, 0x69AD,
- 0x69AF, 0x69B7, 0x69B8, 0x69BA, 0x69BC, 0x69C5, 0x69C8, 0x69D1,
- 0x69D6, 0x69D7, 0x69E2, 0x69E5, 0x69EE, 0x69EF, 0x69F1, 0x69F3,
- 0x69F5, 0x69FE, 0x6A00, 0x6A01, 0x6A03, 0x6A0F, 0x6A11, 0x6A15,
- 0x6A1A, 0x6A1D, 0x6A20, 0x6A24, 0x6A28, 0x6A30, 0x6A32,
-};
-const unsigned short euc_to_utf8_8FC5[] = {
- 0x6A34, 0x6A37, 0x6A3B, 0x6A3E, 0x6A3F, 0x6A45, 0x6A46,
- 0x6A49, 0x6A4A, 0x6A4E, 0x6A50, 0x6A51, 0x6A52, 0x6A55, 0x6A56,
- 0x6A5B, 0x6A64, 0x6A67, 0x6A6A, 0x6A71, 0x6A73, 0x6A7E, 0x6A81,
- 0x6A83, 0x6A86, 0x6A87, 0x6A89, 0x6A8B, 0x6A91, 0x6A9B, 0x6A9D,
- 0x6A9E, 0x6A9F, 0x6AA5, 0x6AAB, 0x6AAF, 0x6AB0, 0x6AB1, 0x6AB4,
- 0x6ABD, 0x6ABE, 0x6ABF, 0x6AC6, 0x6AC9, 0x6AC8, 0x6ACC, 0x6AD0,
- 0x6AD4, 0x6AD5, 0x6AD6, 0x6ADC, 0x6ADD, 0x6AE4, 0x6AE7, 0x6AEC,
- 0x6AF0, 0x6AF1, 0x6AF2, 0x6AFC, 0x6AFD, 0x6B02, 0x6B03, 0x6B06,
- 0x6B07, 0x6B09, 0x6B0F, 0x6B10, 0x6B11, 0x6B17, 0x6B1B, 0x6B1E,
- 0x6B24, 0x6B28, 0x6B2B, 0x6B2C, 0x6B2F, 0x6B35, 0x6B36, 0x6B3B,
- 0x6B3F, 0x6B46, 0x6B4A, 0x6B4D, 0x6B52, 0x6B56, 0x6B58, 0x6B5D,
- 0x6B60, 0x6B67, 0x6B6B, 0x6B6E, 0x6B70, 0x6B75, 0x6B7D,
-};
-const unsigned short euc_to_utf8_8FC6[] = {
- 0x6B7E, 0x6B82, 0x6B85, 0x6B97, 0x6B9B, 0x6B9F, 0x6BA0,
- 0x6BA2, 0x6BA3, 0x6BA8, 0x6BA9, 0x6BAC, 0x6BAD, 0x6BAE, 0x6BB0,
- 0x6BB8, 0x6BB9, 0x6BBD, 0x6BBE, 0x6BC3, 0x6BC4, 0x6BC9, 0x6BCC,
- 0x6BD6, 0x6BDA, 0x6BE1, 0x6BE3, 0x6BE6, 0x6BE7, 0x6BEE, 0x6BF1,
- 0x6BF7, 0x6BF9, 0x6BFF, 0x6C02, 0x6C04, 0x6C05, 0x6C09, 0x6C0D,
- 0x6C0E, 0x6C10, 0x6C12, 0x6C19, 0x6C1F, 0x6C26, 0x6C27, 0x6C28,
- 0x6C2C, 0x6C2E, 0x6C33, 0x6C35, 0x6C36, 0x6C3A, 0x6C3B, 0x6C3F,
- 0x6C4A, 0x6C4B, 0x6C4D, 0x6C4F, 0x6C52, 0x6C54, 0x6C59, 0x6C5B,
- 0x6C5C, 0x6C6B, 0x6C6D, 0x6C6F, 0x6C74, 0x6C76, 0x6C78, 0x6C79,
- 0x6C7B, 0x6C85, 0x6C86, 0x6C87, 0x6C89, 0x6C94, 0x6C95, 0x6C97,
- 0x6C98, 0x6C9C, 0x6C9F, 0x6CB0, 0x6CB2, 0x6CB4, 0x6CC2, 0x6CC6,
- 0x6CCD, 0x6CCF, 0x6CD0, 0x6CD1, 0x6CD2, 0x6CD4, 0x6CD6,
-};
-const unsigned short euc_to_utf8_8FC7[] = {
- 0x6CDA, 0x6CDC, 0x6CE0, 0x6CE7, 0x6CE9, 0x6CEB, 0x6CEC,
- 0x6CEE, 0x6CF2, 0x6CF4, 0x6D04, 0x6D07, 0x6D0A, 0x6D0E, 0x6D0F,
- 0x6D11, 0x6D13, 0x6D1A, 0x6D26, 0x6D27, 0x6D28, 0x6C67, 0x6D2E,
- 0x6D2F, 0x6D31, 0x6D39, 0x6D3C, 0x6D3F, 0x6D57, 0x6D5E, 0x6D5F,
- 0x6D61, 0x6D65, 0x6D67, 0x6D6F, 0x6D70, 0x6D7C, 0x6D82, 0x6D87,
- 0x6D91, 0x6D92, 0x6D94, 0x6D96, 0x6D97, 0x6D98, 0x6DAA, 0x6DAC,
- 0x6DB4, 0x6DB7, 0x6DB9, 0x6DBD, 0x6DBF, 0x6DC4, 0x6DC8, 0x6DCA,
- 0x6DCE, 0x6DCF, 0x6DD6, 0x6DDB, 0x6DDD, 0x6DDF, 0x6DE0, 0x6DE2,
- 0x6DE5, 0x6DE9, 0x6DEF, 0x6DF0, 0x6DF4, 0x6DF6, 0x6DFC, 0x6E00,
- 0x6E04, 0x6E1E, 0x6E22, 0x6E27, 0x6E32, 0x6E36, 0x6E39, 0x6E3B,
- 0x6E3C, 0x6E44, 0x6E45, 0x6E48, 0x6E49, 0x6E4B, 0x6E4F, 0x6E51,
- 0x6E52, 0x6E53, 0x6E54, 0x6E57, 0x6E5C, 0x6E5D, 0x6E5E,
-};
-const unsigned short euc_to_utf8_8FC8[] = {
- 0x6E62, 0x6E63, 0x6E68, 0x6E73, 0x6E7B, 0x6E7D, 0x6E8D,
- 0x6E93, 0x6E99, 0x6EA0, 0x6EA7, 0x6EAD, 0x6EAE, 0x6EB1, 0x6EB3,
- 0x6EBB, 0x6EBF, 0x6EC0, 0x6EC1, 0x6EC3, 0x6EC7, 0x6EC8, 0x6ECA,
- 0x6ECD, 0x6ECE, 0x6ECF, 0x6EEB, 0x6EED, 0x6EEE, 0x6EF9, 0x6EFB,
- 0x6EFD, 0x6F04, 0x6F08, 0x6F0A, 0x6F0C, 0x6F0D, 0x6F16, 0x6F18,
- 0x6F1A, 0x6F1B, 0x6F26, 0x6F29, 0x6F2A, 0x6F2F, 0x6F30, 0x6F33,
- 0x6F36, 0x6F3B, 0x6F3C, 0x6F2D, 0x6F4F, 0x6F51, 0x6F52, 0x6F53,
- 0x6F57, 0x6F59, 0x6F5A, 0x6F5D, 0x6F5E, 0x6F61, 0x6F62, 0x6F68,
- 0x6F6C, 0x6F7D, 0x6F7E, 0x6F83, 0x6F87, 0x6F88, 0x6F8B, 0x6F8C,
- 0x6F8D, 0x6F90, 0x6F92, 0x6F93, 0x6F94, 0x6F96, 0x6F9A, 0x6F9F,
- 0x6FA0, 0x6FA5, 0x6FA6, 0x6FA7, 0x6FA8, 0x6FAE, 0x6FAF, 0x6FB0,
- 0x6FB5, 0x6FB6, 0x6FBC, 0x6FC5, 0x6FC7, 0x6FC8, 0x6FCA,
-};
-const unsigned short euc_to_utf8_8FC9[] = {
- 0x6FDA, 0x6FDE, 0x6FE8, 0x6FE9, 0x6FF0, 0x6FF5, 0x6FF9,
- 0x6FFC, 0x6FFD, 0x7000, 0x7005, 0x7006, 0x7007, 0x700D, 0x7017,
- 0x7020, 0x7023, 0x702F, 0x7034, 0x7037, 0x7039, 0x703C, 0x7043,
- 0x7044, 0x7048, 0x7049, 0x704A, 0x704B, 0x7054, 0x7055, 0x705D,
- 0x705E, 0x704E, 0x7064, 0x7065, 0x706C, 0x706E, 0x7075, 0x7076,
- 0x707E, 0x7081, 0x7085, 0x7086, 0x7094, 0x7095, 0x7096, 0x7097,
- 0x7098, 0x709B, 0x70A4, 0x70AB, 0x70B0, 0x70B1, 0x70B4, 0x70B7,
- 0x70CA, 0x70D1, 0x70D3, 0x70D4, 0x70D5, 0x70D6, 0x70D8, 0x70DC,
- 0x70E4, 0x70FA, 0x7103, 0x7104, 0x7105, 0x7106, 0x7107, 0x710B,
- 0x710C, 0x710F, 0x711E, 0x7120, 0x712B, 0x712D, 0x712F, 0x7130,
- 0x7131, 0x7138, 0x7141, 0x7145, 0x7146, 0x7147, 0x714A, 0x714B,
- 0x7150, 0x7152, 0x7157, 0x715A, 0x715C, 0x715E, 0x7160,
-};
-const unsigned short euc_to_utf8_8FCA[] = {
- 0x7168, 0x7179, 0x7180, 0x7185, 0x7187, 0x718C, 0x7192,
- 0x719A, 0x719B, 0x71A0, 0x71A2, 0x71AF, 0x71B0, 0x71B2, 0x71B3,
- 0x71BA, 0x71BF, 0x71C0, 0x71C1, 0x71C4, 0x71CB, 0x71CC, 0x71D3,
- 0x71D6, 0x71D9, 0x71DA, 0x71DC, 0x71F8, 0x71FE, 0x7200, 0x7207,
- 0x7208, 0x7209, 0x7213, 0x7217, 0x721A, 0x721D, 0x721F, 0x7224,
- 0x722B, 0x722F, 0x7234, 0x7238, 0x7239, 0x7241, 0x7242, 0x7243,
- 0x7245, 0x724E, 0x724F, 0x7250, 0x7253, 0x7255, 0x7256, 0x725A,
- 0x725C, 0x725E, 0x7260, 0x7263, 0x7268, 0x726B, 0x726E, 0x726F,
- 0x7271, 0x7277, 0x7278, 0x727B, 0x727C, 0x727F, 0x7284, 0x7289,
- 0x728D, 0x728E, 0x7293, 0x729B, 0x72A8, 0x72AD, 0x72AE, 0x72B1,
- 0x72B4, 0x72BE, 0x72C1, 0x72C7, 0x72C9, 0x72CC, 0x72D5, 0x72D6,
- 0x72D8, 0x72DF, 0x72E5, 0x72F3, 0x72F4, 0x72FA, 0x72FB,
-};
-const unsigned short euc_to_utf8_8FCB[] = {
- 0x72FE, 0x7302, 0x7304, 0x7305, 0x7307, 0x730B, 0x730D,
- 0x7312, 0x7313, 0x7318, 0x7319, 0x731E, 0x7322, 0x7324, 0x7327,
- 0x7328, 0x732C, 0x7331, 0x7332, 0x7335, 0x733A, 0x733B, 0x733D,
- 0x7343, 0x734D, 0x7350, 0x7352, 0x7356, 0x7358, 0x735D, 0x735E,
- 0x735F, 0x7360, 0x7366, 0x7367, 0x7369, 0x736B, 0x736C, 0x736E,
- 0x736F, 0x7371, 0x7377, 0x7379, 0x737C, 0x7380, 0x7381, 0x7383,
- 0x7385, 0x7386, 0x738E, 0x7390, 0x7393, 0x7395, 0x7397, 0x7398,
- 0x739C, 0x739E, 0x739F, 0x73A0, 0x73A2, 0x73A5, 0x73A6, 0x73AA,
- 0x73AB, 0x73AD, 0x73B5, 0x73B7, 0x73B9, 0x73BC, 0x73BD, 0x73BF,
- 0x73C5, 0x73C6, 0x73C9, 0x73CB, 0x73CC, 0x73CF, 0x73D2, 0x73D3,
- 0x73D6, 0x73D9, 0x73DD, 0x73E1, 0x73E3, 0x73E6, 0x73E7, 0x73E9,
- 0x73F4, 0x73F5, 0x73F7, 0x73F9, 0x73FA, 0x73FB, 0x73FD,
-};
-const unsigned short euc_to_utf8_8FCC[] = {
- 0x73FF, 0x7400, 0x7401, 0x7404, 0x7407, 0x740A, 0x7411,
- 0x741A, 0x741B, 0x7424, 0x7426, 0x7428, 0x7429, 0x742A, 0x742B,
- 0x742C, 0x742D, 0x742E, 0x742F, 0x7430, 0x7431, 0x7439, 0x7440,
- 0x7443, 0x7444, 0x7446, 0x7447, 0x744B, 0x744D, 0x7451, 0x7452,
- 0x7457, 0x745D, 0x7462, 0x7466, 0x7467, 0x7468, 0x746B, 0x746D,
- 0x746E, 0x7471, 0x7472, 0x7480, 0x7481, 0x7485, 0x7486, 0x7487,
- 0x7489, 0x748F, 0x7490, 0x7491, 0x7492, 0x7498, 0x7499, 0x749A,
- 0x749C, 0x749F, 0x74A0, 0x74A1, 0x74A3, 0x74A6, 0x74A8, 0x74A9,
- 0x74AA, 0x74AB, 0x74AE, 0x74AF, 0x74B1, 0x74B2, 0x74B5, 0x74B9,
- 0x74BB, 0x74BF, 0x74C8, 0x74C9, 0x74CC, 0x74D0, 0x74D3, 0x74D8,
- 0x74DA, 0x74DB, 0x74DE, 0x74DF, 0x74E4, 0x74E8, 0x74EA, 0x74EB,
- 0x74EF, 0x74F4, 0x74FA, 0x74FB, 0x74FC, 0x74FF, 0x7506,
-};
-const unsigned short euc_to_utf8_8FCD[] = {
- 0x7512, 0x7516, 0x7517, 0x7520, 0x7521, 0x7524, 0x7527,
- 0x7529, 0x752A, 0x752F, 0x7536, 0x7539, 0x753D, 0x753E, 0x753F,
- 0x7540, 0x7543, 0x7547, 0x7548, 0x754E, 0x7550, 0x7552, 0x7557,
- 0x755E, 0x755F, 0x7561, 0x756F, 0x7571, 0x7579, 0x757A, 0x757B,
- 0x757C, 0x757D, 0x757E, 0x7581, 0x7585, 0x7590, 0x7592, 0x7593,
- 0x7595, 0x7599, 0x759C, 0x75A2, 0x75A4, 0x75B4, 0x75BA, 0x75BF,
- 0x75C0, 0x75C1, 0x75C4, 0x75C6, 0x75CC, 0x75CE, 0x75CF, 0x75D7,
- 0x75DC, 0x75DF, 0x75E0, 0x75E1, 0x75E4, 0x75E7, 0x75EC, 0x75EE,
- 0x75EF, 0x75F1, 0x75F9, 0x7600, 0x7602, 0x7603, 0x7604, 0x7607,
- 0x7608, 0x760A, 0x760C, 0x760F, 0x7612, 0x7613, 0x7615, 0x7616,
- 0x7619, 0x761B, 0x761C, 0x761D, 0x761E, 0x7623, 0x7625, 0x7626,
- 0x7629, 0x762D, 0x7632, 0x7633, 0x7635, 0x7638, 0x7639,
-};
-const unsigned short euc_to_utf8_8FCE[] = {
- 0x763A, 0x763C, 0x764A, 0x7640, 0x7641, 0x7643, 0x7644,
- 0x7645, 0x7649, 0x764B, 0x7655, 0x7659, 0x765F, 0x7664, 0x7665,
- 0x766D, 0x766E, 0x766F, 0x7671, 0x7674, 0x7681, 0x7685, 0x768C,
- 0x768D, 0x7695, 0x769B, 0x769C, 0x769D, 0x769F, 0x76A0, 0x76A2,
- 0x76A3, 0x76A4, 0x76A5, 0x76A6, 0x76A7, 0x76A8, 0x76AA, 0x76AD,
- 0x76BD, 0x76C1, 0x76C5, 0x76C9, 0x76CB, 0x76CC, 0x76CE, 0x76D4,
- 0x76D9, 0x76E0, 0x76E6, 0x76E8, 0x76EC, 0x76F0, 0x76F1, 0x76F6,
- 0x76F9, 0x76FC, 0x7700, 0x7706, 0x770A, 0x770E, 0x7712, 0x7714,
- 0x7715, 0x7717, 0x7719, 0x771A, 0x771C, 0x7722, 0x7728, 0x772D,
- 0x772E, 0x772F, 0x7734, 0x7735, 0x7736, 0x7739, 0x773D, 0x773E,
- 0x7742, 0x7745, 0x7746, 0x774A, 0x774D, 0x774E, 0x774F, 0x7752,
- 0x7756, 0x7757, 0x775C, 0x775E, 0x775F, 0x7760, 0x7762,
-};
-const unsigned short euc_to_utf8_8FCF[] = {
- 0x7764, 0x7767, 0x776A, 0x776C, 0x7770, 0x7772, 0x7773,
- 0x7774, 0x777A, 0x777D, 0x7780, 0x7784, 0x778C, 0x778D, 0x7794,
- 0x7795, 0x7796, 0x779A, 0x779F, 0x77A2, 0x77A7, 0x77AA, 0x77AE,
- 0x77AF, 0x77B1, 0x77B5, 0x77BE, 0x77C3, 0x77C9, 0x77D1, 0x77D2,
- 0x77D5, 0x77D9, 0x77DE, 0x77DF, 0x77E0, 0x77E4, 0x77E6, 0x77EA,
- 0x77EC, 0x77F0, 0x77F1, 0x77F4, 0x77F8, 0x77FB, 0x7805, 0x7806,
- 0x7809, 0x780D, 0x780E, 0x7811, 0x781D, 0x7821, 0x7822, 0x7823,
- 0x782D, 0x782E, 0x7830, 0x7835, 0x7837, 0x7843, 0x7844, 0x7847,
- 0x7848, 0x784C, 0x784E, 0x7852, 0x785C, 0x785E, 0x7860, 0x7861,
- 0x7863, 0x7864, 0x7868, 0x786A, 0x786E, 0x787A, 0x787E, 0x788A,
- 0x788F, 0x7894, 0x7898, 0x78A1, 0x789D, 0x789E, 0x789F, 0x78A4,
- 0x78A8, 0x78AC, 0x78AD, 0x78B0, 0x78B1, 0x78B2, 0x78B3,
-};
-const unsigned short euc_to_utf8_8FD0[] = {
- 0x78BB, 0x78BD, 0x78BF, 0x78C7, 0x78C8, 0x78C9, 0x78CC,
- 0x78CE, 0x78D2, 0x78D3, 0x78D5, 0x78D6, 0x78E4, 0x78DB, 0x78DF,
- 0x78E0, 0x78E1, 0x78E6, 0x78EA, 0x78F2, 0x78F3, 0x7900, 0x78F6,
- 0x78F7, 0x78FA, 0x78FB, 0x78FF, 0x7906, 0x790C, 0x7910, 0x791A,
- 0x791C, 0x791E, 0x791F, 0x7920, 0x7925, 0x7927, 0x7929, 0x792D,
- 0x7931, 0x7934, 0x7935, 0x793B, 0x793D, 0x793F, 0x7944, 0x7945,
- 0x7946, 0x794A, 0x794B, 0x794F, 0x7951, 0x7954, 0x7958, 0x795B,
- 0x795C, 0x7967, 0x7969, 0x796B, 0x7972, 0x7979, 0x797B, 0x797C,
- 0x797E, 0x798B, 0x798C, 0x7991, 0x7993, 0x7994, 0x7995, 0x7996,
- 0x7998, 0x799B, 0x799C, 0x79A1, 0x79A8, 0x79A9, 0x79AB, 0x79AF,
- 0x79B1, 0x79B4, 0x79B8, 0x79BB, 0x79C2, 0x79C4, 0x79C7, 0x79C8,
- 0x79CA, 0x79CF, 0x79D4, 0x79D6, 0x79DA, 0x79DD, 0x79DE,
-};
-const unsigned short euc_to_utf8_8FD1[] = {
- 0x79E0, 0x79E2, 0x79E5, 0x79EA, 0x79EB, 0x79ED, 0x79F1,
- 0x79F8, 0x79FC, 0x7A02, 0x7A03, 0x7A07, 0x7A09, 0x7A0A, 0x7A0C,
- 0x7A11, 0x7A15, 0x7A1B, 0x7A1E, 0x7A21, 0x7A27, 0x7A2B, 0x7A2D,
- 0x7A2F, 0x7A30, 0x7A34, 0x7A35, 0x7A38, 0x7A39, 0x7A3A, 0x7A44,
- 0x7A45, 0x7A47, 0x7A48, 0x7A4C, 0x7A55, 0x7A56, 0x7A59, 0x7A5C,
- 0x7A5D, 0x7A5F, 0x7A60, 0x7A65, 0x7A67, 0x7A6A, 0x7A6D, 0x7A75,
- 0x7A78, 0x7A7E, 0x7A80, 0x7A82, 0x7A85, 0x7A86, 0x7A8A, 0x7A8B,
- 0x7A90, 0x7A91, 0x7A94, 0x7A9E, 0x7AA0, 0x7AA3, 0x7AAC, 0x7AB3,
- 0x7AB5, 0x7AB9, 0x7ABB, 0x7ABC, 0x7AC6, 0x7AC9, 0x7ACC, 0x7ACE,
- 0x7AD1, 0x7ADB, 0x7AE8, 0x7AE9, 0x7AEB, 0x7AEC, 0x7AF1, 0x7AF4,
- 0x7AFB, 0x7AFD, 0x7AFE, 0x7B07, 0x7B14, 0x7B1F, 0x7B23, 0x7B27,
- 0x7B29, 0x7B2A, 0x7B2B, 0x7B2D, 0x7B2E, 0x7B2F, 0x7B30,
-};
-const unsigned short euc_to_utf8_8FD2[] = {
- 0x7B31, 0x7B34, 0x7B3D, 0x7B3F, 0x7B40, 0x7B41, 0x7B47,
- 0x7B4E, 0x7B55, 0x7B60, 0x7B64, 0x7B66, 0x7B69, 0x7B6A, 0x7B6D,
- 0x7B6F, 0x7B72, 0x7B73, 0x7B77, 0x7B84, 0x7B89, 0x7B8E, 0x7B90,
- 0x7B91, 0x7B96, 0x7B9B, 0x7B9E, 0x7BA0, 0x7BA5, 0x7BAC, 0x7BAF,
- 0x7BB0, 0x7BB2, 0x7BB5, 0x7BB6, 0x7BBA, 0x7BBB, 0x7BBC, 0x7BBD,
- 0x7BC2, 0x7BC5, 0x7BC8, 0x7BCA, 0x7BD4, 0x7BD6, 0x7BD7, 0x7BD9,
- 0x7BDA, 0x7BDB, 0x7BE8, 0x7BEA, 0x7BF2, 0x7BF4, 0x7BF5, 0x7BF8,
- 0x7BF9, 0x7BFA, 0x7BFC, 0x7BFE, 0x7C01, 0x7C02, 0x7C03, 0x7C04,
- 0x7C06, 0x7C09, 0x7C0B, 0x7C0C, 0x7C0E, 0x7C0F, 0x7C19, 0x7C1B,
- 0x7C20, 0x7C25, 0x7C26, 0x7C28, 0x7C2C, 0x7C31, 0x7C33, 0x7C34,
- 0x7C36, 0x7C39, 0x7C3A, 0x7C46, 0x7C4A, 0x7C55, 0x7C51, 0x7C52,
- 0x7C53, 0x7C59, 0x7C5A, 0x7C5B, 0x7C5C, 0x7C5D, 0x7C5E,
-};
-const unsigned short euc_to_utf8_8FD3[] = {
- 0x7C61, 0x7C63, 0x7C67, 0x7C69, 0x7C6D, 0x7C6E, 0x7C70,
- 0x7C72, 0x7C79, 0x7C7C, 0x7C7D, 0x7C86, 0x7C87, 0x7C8F, 0x7C94,
- 0x7C9E, 0x7CA0, 0x7CA6, 0x7CB0, 0x7CB6, 0x7CB7, 0x7CBA, 0x7CBB,
- 0x7CBC, 0x7CBF, 0x7CC4, 0x7CC7, 0x7CC8, 0x7CC9, 0x7CCD, 0x7CCF,
- 0x7CD3, 0x7CD4, 0x7CD5, 0x7CD7, 0x7CD9, 0x7CDA, 0x7CDD, 0x7CE6,
- 0x7CE9, 0x7CEB, 0x7CF5, 0x7D03, 0x7D07, 0x7D08, 0x7D09, 0x7D0F,
- 0x7D11, 0x7D12, 0x7D13, 0x7D16, 0x7D1D, 0x7D1E, 0x7D23, 0x7D26,
- 0x7D2A, 0x7D2D, 0x7D31, 0x7D3C, 0x7D3D, 0x7D3E, 0x7D40, 0x7D41,
- 0x7D47, 0x7D48, 0x7D4D, 0x7D51, 0x7D53, 0x7D57, 0x7D59, 0x7D5A,
- 0x7D5C, 0x7D5D, 0x7D65, 0x7D67, 0x7D6A, 0x7D70, 0x7D78, 0x7D7A,
- 0x7D7B, 0x7D7F, 0x7D81, 0x7D82, 0x7D83, 0x7D85, 0x7D86, 0x7D88,
- 0x7D8B, 0x7D8C, 0x7D8D, 0x7D91, 0x7D96, 0x7D97, 0x7D9D,
-};
-const unsigned short euc_to_utf8_8FD4[] = {
- 0x7D9E, 0x7DA6, 0x7DA7, 0x7DAA, 0x7DB3, 0x7DB6, 0x7DB7,
- 0x7DB9, 0x7DC2, 0x7DC3, 0x7DC4, 0x7DC5, 0x7DC6, 0x7DCC, 0x7DCD,
- 0x7DCE, 0x7DD7, 0x7DD9, 0x7E00, 0x7DE2, 0x7DE5, 0x7DE6, 0x7DEA,
- 0x7DEB, 0x7DED, 0x7DF1, 0x7DF5, 0x7DF6, 0x7DF9, 0x7DFA, 0x7E08,
- 0x7E10, 0x7E11, 0x7E15, 0x7E17, 0x7E1C, 0x7E1D, 0x7E20, 0x7E27,
- 0x7E28, 0x7E2C, 0x7E2D, 0x7E2F, 0x7E33, 0x7E36, 0x7E3F, 0x7E44,
- 0x7E45, 0x7E47, 0x7E4E, 0x7E50, 0x7E52, 0x7E58, 0x7E5F, 0x7E61,
- 0x7E62, 0x7E65, 0x7E6B, 0x7E6E, 0x7E6F, 0x7E73, 0x7E78, 0x7E7E,
- 0x7E81, 0x7E86, 0x7E87, 0x7E8A, 0x7E8D, 0x7E91, 0x7E95, 0x7E98,
- 0x7E9A, 0x7E9D, 0x7E9E, 0x7F3C, 0x7F3B, 0x7F3D, 0x7F3E, 0x7F3F,
- 0x7F43, 0x7F44, 0x7F47, 0x7F4F, 0x7F52, 0x7F53, 0x7F5B, 0x7F5C,
- 0x7F5D, 0x7F61, 0x7F63, 0x7F64, 0x7F65, 0x7F66, 0x7F6D,
-};
-const unsigned short euc_to_utf8_8FD5[] = {
- 0x7F71, 0x7F7D, 0x7F7E, 0x7F7F, 0x7F80, 0x7F8B, 0x7F8D,
- 0x7F8F, 0x7F90, 0x7F91, 0x7F96, 0x7F97, 0x7F9C, 0x7FA1, 0x7FA2,
- 0x7FA6, 0x7FAA, 0x7FAD, 0x7FB4, 0x7FBC, 0x7FBF, 0x7FC0, 0x7FC3,
- 0x7FC8, 0x7FCE, 0x7FCF, 0x7FDB, 0x7FDF, 0x7FE3, 0x7FE5, 0x7FE8,
- 0x7FEC, 0x7FEE, 0x7FEF, 0x7FF2, 0x7FFA, 0x7FFD, 0x7FFE, 0x7FFF,
- 0x8007, 0x8008, 0x800A, 0x800D, 0x800E, 0x800F, 0x8011, 0x8013,
- 0x8014, 0x8016, 0x801D, 0x801E, 0x801F, 0x8020, 0x8024, 0x8026,
- 0x802C, 0x802E, 0x8030, 0x8034, 0x8035, 0x8037, 0x8039, 0x803A,
- 0x803C, 0x803E, 0x8040, 0x8044, 0x8060, 0x8064, 0x8066, 0x806D,
- 0x8071, 0x8075, 0x8081, 0x8088, 0x808E, 0x809C, 0x809E, 0x80A6,
- 0x80A7, 0x80AB, 0x80B8, 0x80B9, 0x80C8, 0x80CD, 0x80CF, 0x80D2,
- 0x80D4, 0x80D5, 0x80D7, 0x80D8, 0x80E0, 0x80ED, 0x80EE,
-};
-const unsigned short euc_to_utf8_8FD6[] = {
- 0x80F0, 0x80F2, 0x80F3, 0x80F6, 0x80F9, 0x80FA, 0x80FE,
- 0x8103, 0x810B, 0x8116, 0x8117, 0x8118, 0x811C, 0x811E, 0x8120,
- 0x8124, 0x8127, 0x812C, 0x8130, 0x8135, 0x813A, 0x813C, 0x8145,
- 0x8147, 0x814A, 0x814C, 0x8152, 0x8157, 0x8160, 0x8161, 0x8167,
- 0x8168, 0x8169, 0x816D, 0x816F, 0x8177, 0x8181, 0x8190, 0x8184,
- 0x8185, 0x8186, 0x818B, 0x818E, 0x8196, 0x8198, 0x819B, 0x819E,
- 0x81A2, 0x81AE, 0x81B2, 0x81B4, 0x81BB, 0x81CB, 0x81C3, 0x81C5,
- 0x81CA, 0x81CE, 0x81CF, 0x81D5, 0x81D7, 0x81DB, 0x81DD, 0x81DE,
- 0x81E1, 0x81E4, 0x81EB, 0x81EC, 0x81F0, 0x81F1, 0x81F2, 0x81F5,
- 0x81F6, 0x81F8, 0x81F9, 0x81FD, 0x81FF, 0x8200, 0x8203, 0x820F,
- 0x8213, 0x8214, 0x8219, 0x821A, 0x821D, 0x8221, 0x8222, 0x8228,
- 0x8232, 0x8234, 0x823A, 0x8243, 0x8244, 0x8245, 0x8246,
-};
-const unsigned short euc_to_utf8_8FD7[] = {
- 0x824B, 0x824E, 0x824F, 0x8251, 0x8256, 0x825C, 0x8260,
- 0x8263, 0x8267, 0x826D, 0x8274, 0x827B, 0x827D, 0x827F, 0x8280,
- 0x8281, 0x8283, 0x8284, 0x8287, 0x8289, 0x828A, 0x828E, 0x8291,
- 0x8294, 0x8296, 0x8298, 0x829A, 0x829B, 0x82A0, 0x82A1, 0x82A3,
- 0x82A4, 0x82A7, 0x82A8, 0x82A9, 0x82AA, 0x82AE, 0x82B0, 0x82B2,
- 0x82B4, 0x82B7, 0x82BA, 0x82BC, 0x82BE, 0x82BF, 0x82C6, 0x82D0,
- 0x82D5, 0x82DA, 0x82E0, 0x82E2, 0x82E4, 0x82E8, 0x82EA, 0x82ED,
- 0x82EF, 0x82F6, 0x82F7, 0x82FD, 0x82FE, 0x8300, 0x8301, 0x8307,
- 0x8308, 0x830A, 0x830B, 0x8354, 0x831B, 0x831D, 0x831E, 0x831F,
- 0x8321, 0x8322, 0x832C, 0x832D, 0x832E, 0x8330, 0x8333, 0x8337,
- 0x833A, 0x833C, 0x833D, 0x8342, 0x8343, 0x8344, 0x8347, 0x834D,
- 0x834E, 0x8351, 0x8355, 0x8356, 0x8357, 0x8370, 0x8378,
-};
-const unsigned short euc_to_utf8_8FD8[] = {
- 0x837D, 0x837F, 0x8380, 0x8382, 0x8384, 0x8386, 0x838D,
- 0x8392, 0x8394, 0x8395, 0x8398, 0x8399, 0x839B, 0x839C, 0x839D,
- 0x83A6, 0x83A7, 0x83A9, 0x83AC, 0x83BE, 0x83BF, 0x83C0, 0x83C7,
- 0x83C9, 0x83CF, 0x83D0, 0x83D1, 0x83D4, 0x83DD, 0x8353, 0x83E8,
- 0x83EA, 0x83F6, 0x83F8, 0x83F9, 0x83FC, 0x8401, 0x8406, 0x840A,
- 0x840F, 0x8411, 0x8415, 0x8419, 0x83AD, 0x842F, 0x8439, 0x8445,
- 0x8447, 0x8448, 0x844A, 0x844D, 0x844F, 0x8451, 0x8452, 0x8456,
- 0x8458, 0x8459, 0x845A, 0x845C, 0x8460, 0x8464, 0x8465, 0x8467,
- 0x846A, 0x8470, 0x8473, 0x8474, 0x8476, 0x8478, 0x847C, 0x847D,
- 0x8481, 0x8485, 0x8492, 0x8493, 0x8495, 0x849E, 0x84A6, 0x84A8,
- 0x84A9, 0x84AA, 0x84AF, 0x84B1, 0x84B4, 0x84BA, 0x84BD, 0x84BE,
- 0x84C0, 0x84C2, 0x84C7, 0x84C8, 0x84CC, 0x84CF, 0x84D3,
-};
-const unsigned short euc_to_utf8_8FD9[] = {
- 0x84DC, 0x84E7, 0x84EA, 0x84EF, 0x84F0, 0x84F1, 0x84F2,
- 0x84F7, 0x8532, 0x84FA, 0x84FB, 0x84FD, 0x8502, 0x8503, 0x8507,
- 0x850C, 0x850E, 0x8510, 0x851C, 0x851E, 0x8522, 0x8523, 0x8524,
- 0x8525, 0x8527, 0x852A, 0x852B, 0x852F, 0x8533, 0x8534, 0x8536,
- 0x853F, 0x8546, 0x854F, 0x8550, 0x8551, 0x8552, 0x8553, 0x8556,
- 0x8559, 0x855C, 0x855D, 0x855E, 0x855F, 0x8560, 0x8561, 0x8562,
- 0x8564, 0x856B, 0x856F, 0x8579, 0x857A, 0x857B, 0x857D, 0x857F,
- 0x8581, 0x8585, 0x8586, 0x8589, 0x858B, 0x858C, 0x858F, 0x8593,
- 0x8598, 0x859D, 0x859F, 0x85A0, 0x85A2, 0x85A5, 0x85A7, 0x85B4,
- 0x85B6, 0x85B7, 0x85B8, 0x85BC, 0x85BD, 0x85BE, 0x85BF, 0x85C2,
- 0x85C7, 0x85CA, 0x85CB, 0x85CE, 0x85AD, 0x85D8, 0x85DA, 0x85DF,
- 0x85E0, 0x85E6, 0x85E8, 0x85ED, 0x85F3, 0x85F6, 0x85FC,
-};
-const unsigned short euc_to_utf8_8FDA[] = {
- 0x85FF, 0x8600, 0x8604, 0x8605, 0x860D, 0x860E, 0x8610,
- 0x8611, 0x8612, 0x8618, 0x8619, 0x861B, 0x861E, 0x8621, 0x8627,
- 0x8629, 0x8636, 0x8638, 0x863A, 0x863C, 0x863D, 0x8640, 0x8642,
- 0x8646, 0x8652, 0x8653, 0x8656, 0x8657, 0x8658, 0x8659, 0x865D,
- 0x8660, 0x8661, 0x8662, 0x8663, 0x8664, 0x8669, 0x866C, 0x866F,
- 0x8675, 0x8676, 0x8677, 0x867A, 0x868D, 0x8691, 0x8696, 0x8698,
- 0x869A, 0x869C, 0x86A1, 0x86A6, 0x86A7, 0x86A8, 0x86AD, 0x86B1,
- 0x86B3, 0x86B4, 0x86B5, 0x86B7, 0x86B8, 0x86B9, 0x86BF, 0x86C0,
- 0x86C1, 0x86C3, 0x86C5, 0x86D1, 0x86D2, 0x86D5, 0x86D7, 0x86DA,
- 0x86DC, 0x86E0, 0x86E3, 0x86E5, 0x86E7, 0x8688, 0x86FA, 0x86FC,
- 0x86FD, 0x8704, 0x8705, 0x8707, 0x870B, 0x870E, 0x870F, 0x8710,
- 0x8713, 0x8714, 0x8719, 0x871E, 0x871F, 0x8721, 0x8723,
-};
-const unsigned short euc_to_utf8_8FDB[] = {
- 0x8728, 0x872E, 0x872F, 0x8731, 0x8732, 0x8739, 0x873A,
- 0x873C, 0x873D, 0x873E, 0x8740, 0x8743, 0x8745, 0x874D, 0x8758,
- 0x875D, 0x8761, 0x8764, 0x8765, 0x876F, 0x8771, 0x8772, 0x877B,
- 0x8783, 0x8784, 0x8785, 0x8786, 0x8787, 0x8788, 0x8789, 0x878B,
- 0x878C, 0x8790, 0x8793, 0x8795, 0x8797, 0x8798, 0x8799, 0x879E,
- 0x87A0, 0x87A3, 0x87A7, 0x87AC, 0x87AD, 0x87AE, 0x87B1, 0x87B5,
- 0x87BE, 0x87BF, 0x87C1, 0x87C8, 0x87C9, 0x87CA, 0x87CE, 0x87D5,
- 0x87D6, 0x87D9, 0x87DA, 0x87DC, 0x87DF, 0x87E2, 0x87E3, 0x87E4,
- 0x87EA, 0x87EB, 0x87ED, 0x87F1, 0x87F3, 0x87F8, 0x87FA, 0x87FF,
- 0x8801, 0x8803, 0x8806, 0x8809, 0x880A, 0x880B, 0x8810, 0x8819,
- 0x8812, 0x8813, 0x8814, 0x8818, 0x881A, 0x881B, 0x881C, 0x881E,
- 0x881F, 0x8828, 0x882D, 0x882E, 0x8830, 0x8832, 0x8835,
-};
-const unsigned short euc_to_utf8_8FDC[] = {
- 0x883A, 0x883C, 0x8841, 0x8843, 0x8845, 0x8848, 0x8849,
- 0x884A, 0x884B, 0x884E, 0x8851, 0x8855, 0x8856, 0x8858, 0x885A,
- 0x885C, 0x885F, 0x8860, 0x8864, 0x8869, 0x8871, 0x8879, 0x887B,
- 0x8880, 0x8898, 0x889A, 0x889B, 0x889C, 0x889F, 0x88A0, 0x88A8,
- 0x88AA, 0x88BA, 0x88BD, 0x88BE, 0x88C0, 0x88CA, 0x88CB, 0x88CC,
- 0x88CD, 0x88CE, 0x88D1, 0x88D2, 0x88D3, 0x88DB, 0x88DE, 0x88E7,
- 0x88EF, 0x88F0, 0x88F1, 0x88F5, 0x88F7, 0x8901, 0x8906, 0x890D,
- 0x890E, 0x890F, 0x8915, 0x8916, 0x8918, 0x8919, 0x891A, 0x891C,
- 0x8920, 0x8926, 0x8927, 0x8928, 0x8930, 0x8931, 0x8932, 0x8935,
- 0x8939, 0x893A, 0x893E, 0x8940, 0x8942, 0x8945, 0x8946, 0x8949,
- 0x894F, 0x8952, 0x8957, 0x895A, 0x895B, 0x895C, 0x8961, 0x8962,
- 0x8963, 0x896B, 0x896E, 0x8970, 0x8973, 0x8975, 0x897A,
-};
-const unsigned short euc_to_utf8_8FDD[] = {
- 0x897B, 0x897C, 0x897D, 0x8989, 0x898D, 0x8990, 0x8994,
- 0x8995, 0x899B, 0x899C, 0x899F, 0x89A0, 0x89A5, 0x89B0, 0x89B4,
- 0x89B5, 0x89B6, 0x89B7, 0x89BC, 0x89D4, 0x89D5, 0x89D6, 0x89D7,
- 0x89D8, 0x89E5, 0x89E9, 0x89EB, 0x89ED, 0x89F1, 0x89F3, 0x89F6,
- 0x89F9, 0x89FD, 0x89FF, 0x8A04, 0x8A05, 0x8A07, 0x8A0F, 0x8A11,
- 0x8A12, 0x8A14, 0x8A15, 0x8A1E, 0x8A20, 0x8A22, 0x8A24, 0x8A26,
- 0x8A2B, 0x8A2C, 0x8A2F, 0x8A35, 0x8A37, 0x8A3D, 0x8A3E, 0x8A40,
- 0x8A43, 0x8A45, 0x8A47, 0x8A49, 0x8A4D, 0x8A4E, 0x8A53, 0x8A56,
- 0x8A57, 0x8A58, 0x8A5C, 0x8A5D, 0x8A61, 0x8A65, 0x8A67, 0x8A75,
- 0x8A76, 0x8A77, 0x8A79, 0x8A7A, 0x8A7B, 0x8A7E, 0x8A7F, 0x8A80,
- 0x8A83, 0x8A86, 0x8A8B, 0x8A8F, 0x8A90, 0x8A92, 0x8A96, 0x8A97,
- 0x8A99, 0x8A9F, 0x8AA7, 0x8AA9, 0x8AAE, 0x8AAF, 0x8AB3,
-};
-const unsigned short euc_to_utf8_8FDE[] = {
- 0x8AB6, 0x8AB7, 0x8ABB, 0x8ABE, 0x8AC3, 0x8AC6, 0x8AC8,
- 0x8AC9, 0x8ACA, 0x8AD1, 0x8AD3, 0x8AD4, 0x8AD5, 0x8AD7, 0x8ADD,
- 0x8ADF, 0x8AEC, 0x8AF0, 0x8AF4, 0x8AF5, 0x8AF6, 0x8AFC, 0x8AFF,
- 0x8B05, 0x8B06, 0x8B0B, 0x8B11, 0x8B1C, 0x8B1E, 0x8B1F, 0x8B0A,
- 0x8B2D, 0x8B30, 0x8B37, 0x8B3C, 0x8B42, 0x8B43, 0x8B44, 0x8B45,
- 0x8B46, 0x8B48, 0x8B52, 0x8B53, 0x8B54, 0x8B59, 0x8B4D, 0x8B5E,
- 0x8B63, 0x8B6D, 0x8B76, 0x8B78, 0x8B79, 0x8B7C, 0x8B7E, 0x8B81,
- 0x8B84, 0x8B85, 0x8B8B, 0x8B8D, 0x8B8F, 0x8B94, 0x8B95, 0x8B9C,
- 0x8B9E, 0x8B9F, 0x8C38, 0x8C39, 0x8C3D, 0x8C3E, 0x8C45, 0x8C47,
- 0x8C49, 0x8C4B, 0x8C4F, 0x8C51, 0x8C53, 0x8C54, 0x8C57, 0x8C58,
- 0x8C5B, 0x8C5D, 0x8C59, 0x8C63, 0x8C64, 0x8C66, 0x8C68, 0x8C69,
- 0x8C6D, 0x8C73, 0x8C75, 0x8C76, 0x8C7B, 0x8C7E, 0x8C86,
-};
-const unsigned short euc_to_utf8_8FDF[] = {
- 0x8C87, 0x8C8B, 0x8C90, 0x8C92, 0x8C93, 0x8C99, 0x8C9B,
- 0x8C9C, 0x8CA4, 0x8CB9, 0x8CBA, 0x8CC5, 0x8CC6, 0x8CC9, 0x8CCB,
- 0x8CCF, 0x8CD6, 0x8CD5, 0x8CD9, 0x8CDD, 0x8CE1, 0x8CE8, 0x8CEC,
- 0x8CEF, 0x8CF0, 0x8CF2, 0x8CF5, 0x8CF7, 0x8CF8, 0x8CFE, 0x8CFF,
- 0x8D01, 0x8D03, 0x8D09, 0x8D12, 0x8D17, 0x8D1B, 0x8D65, 0x8D69,
- 0x8D6C, 0x8D6E, 0x8D7F, 0x8D82, 0x8D84, 0x8D88, 0x8D8D, 0x8D90,
- 0x8D91, 0x8D95, 0x8D9E, 0x8D9F, 0x8DA0, 0x8DA6, 0x8DAB, 0x8DAC,
- 0x8DAF, 0x8DB2, 0x8DB5, 0x8DB7, 0x8DB9, 0x8DBB, 0x8DC0, 0x8DC5,
- 0x8DC6, 0x8DC7, 0x8DC8, 0x8DCA, 0x8DCE, 0x8DD1, 0x8DD4, 0x8DD5,
- 0x8DD7, 0x8DD9, 0x8DE4, 0x8DE5, 0x8DE7, 0x8DEC, 0x8DF0, 0x8DBC,
- 0x8DF1, 0x8DF2, 0x8DF4, 0x8DFD, 0x8E01, 0x8E04, 0x8E05, 0x8E06,
- 0x8E0B, 0x8E11, 0x8E14, 0x8E16, 0x8E20, 0x8E21, 0x8E22,
-};
-const unsigned short euc_to_utf8_8FE0[] = {
- 0x8E23, 0x8E26, 0x8E27, 0x8E31, 0x8E33, 0x8E36, 0x8E37,
- 0x8E38, 0x8E39, 0x8E3D, 0x8E40, 0x8E41, 0x8E4B, 0x8E4D, 0x8E4E,
- 0x8E4F, 0x8E54, 0x8E5B, 0x8E5C, 0x8E5D, 0x8E5E, 0x8E61, 0x8E62,
- 0x8E69, 0x8E6C, 0x8E6D, 0x8E6F, 0x8E70, 0x8E71, 0x8E79, 0x8E7A,
- 0x8E7B, 0x8E82, 0x8E83, 0x8E89, 0x8E90, 0x8E92, 0x8E95, 0x8E9A,
- 0x8E9B, 0x8E9D, 0x8E9E, 0x8EA2, 0x8EA7, 0x8EA9, 0x8EAD, 0x8EAE,
- 0x8EB3, 0x8EB5, 0x8EBA, 0x8EBB, 0x8EC0, 0x8EC1, 0x8EC3, 0x8EC4,
- 0x8EC7, 0x8ECF, 0x8ED1, 0x8ED4, 0x8EDC, 0x8EE8, 0x8EEE, 0x8EF0,
- 0x8EF1, 0x8EF7, 0x8EF9, 0x8EFA, 0x8EED, 0x8F00, 0x8F02, 0x8F07,
- 0x8F08, 0x8F0F, 0x8F10, 0x8F16, 0x8F17, 0x8F18, 0x8F1E, 0x8F20,
- 0x8F21, 0x8F23, 0x8F25, 0x8F27, 0x8F28, 0x8F2C, 0x8F2D, 0x8F2E,
- 0x8F34, 0x8F35, 0x8F36, 0x8F37, 0x8F3A, 0x8F40, 0x8F41,
-};
-const unsigned short euc_to_utf8_8FE1[] = {
- 0x8F43, 0x8F47, 0x8F4F, 0x8F51, 0x8F52, 0x8F53, 0x8F54,
- 0x8F55, 0x8F58, 0x8F5D, 0x8F5E, 0x8F65, 0x8F9D, 0x8FA0, 0x8FA1,
- 0x8FA4, 0x8FA5, 0x8FA6, 0x8FB5, 0x8FB6, 0x8FB8, 0x8FBE, 0x8FC0,
- 0x8FC1, 0x8FC6, 0x8FCA, 0x8FCB, 0x8FCD, 0x8FD0, 0x8FD2, 0x8FD3,
- 0x8FD5, 0x8FE0, 0x8FE3, 0x8FE4, 0x8FE8, 0x8FEE, 0x8FF1, 0x8FF5,
- 0x8FF6, 0x8FFB, 0x8FFE, 0x9002, 0x9004, 0x9008, 0x900C, 0x9018,
- 0x901B, 0x9028, 0x9029, 0x902F, 0x902A, 0x902C, 0x902D, 0x9033,
- 0x9034, 0x9037, 0x903F, 0x9043, 0x9044, 0x904C, 0x905B, 0x905D,
- 0x9062, 0x9066, 0x9067, 0x906C, 0x9070, 0x9074, 0x9079, 0x9085,
- 0x9088, 0x908B, 0x908C, 0x908E, 0x9090, 0x9095, 0x9097, 0x9098,
- 0x9099, 0x909B, 0x90A0, 0x90A1, 0x90A2, 0x90A5, 0x90B0, 0x90B2,
- 0x90B3, 0x90B4, 0x90B6, 0x90BD, 0x90CC, 0x90BE, 0x90C3,
-};
-const unsigned short euc_to_utf8_8FE2[] = {
- 0x90C4, 0x90C5, 0x90C7, 0x90C8, 0x90D5, 0x90D7, 0x90D8,
- 0x90D9, 0x90DC, 0x90DD, 0x90DF, 0x90E5, 0x90D2, 0x90F6, 0x90EB,
- 0x90EF, 0x90F0, 0x90F4, 0x90FE, 0x90FF, 0x9100, 0x9104, 0x9105,
- 0x9106, 0x9108, 0x910D, 0x9110, 0x9114, 0x9116, 0x9117, 0x9118,
- 0x911A, 0x911C, 0x911E, 0x9120, 0x9125, 0x9122, 0x9123, 0x9127,
- 0x9129, 0x912E, 0x912F, 0x9131, 0x9134, 0x9136, 0x9137, 0x9139,
- 0x913A, 0x913C, 0x913D, 0x9143, 0x9147, 0x9148, 0x914F, 0x9153,
- 0x9157, 0x9159, 0x915A, 0x915B, 0x9161, 0x9164, 0x9167, 0x916D,
- 0x9174, 0x9179, 0x917A, 0x917B, 0x9181, 0x9183, 0x9185, 0x9186,
- 0x918A, 0x918E, 0x9191, 0x9193, 0x9194, 0x9195, 0x9198, 0x919E,
- 0x91A1, 0x91A6, 0x91A8, 0x91AC, 0x91AD, 0x91AE, 0x91B0, 0x91B1,
- 0x91B2, 0x91B3, 0x91B6, 0x91BB, 0x91BC, 0x91BD, 0x91BF,
-};
-const unsigned short euc_to_utf8_8FE3[] = {
- 0x91C2, 0x91C3, 0x91C5, 0x91D3, 0x91D4, 0x91D7, 0x91D9,
- 0x91DA, 0x91DE, 0x91E4, 0x91E5, 0x91E9, 0x91EA, 0x91EC, 0x91ED,
- 0x91EE, 0x91EF, 0x91F0, 0x91F1, 0x91F7, 0x91F9, 0x91FB, 0x91FD,
- 0x9200, 0x9201, 0x9204, 0x9205, 0x9206, 0x9207, 0x9209, 0x920A,
- 0x920C, 0x9210, 0x9212, 0x9213, 0x9216, 0x9218, 0x921C, 0x921D,
- 0x9223, 0x9224, 0x9225, 0x9226, 0x9228, 0x922E, 0x922F, 0x9230,
- 0x9233, 0x9235, 0x9236, 0x9238, 0x9239, 0x923A, 0x923C, 0x923E,
- 0x9240, 0x9242, 0x9243, 0x9246, 0x9247, 0x924A, 0x924D, 0x924E,
- 0x924F, 0x9251, 0x9258, 0x9259, 0x925C, 0x925D, 0x9260, 0x9261,
- 0x9265, 0x9267, 0x9268, 0x9269, 0x926E, 0x926F, 0x9270, 0x9275,
- 0x9276, 0x9277, 0x9278, 0x9279, 0x927B, 0x927C, 0x927D, 0x927F,
- 0x9288, 0x9289, 0x928A, 0x928D, 0x928E, 0x9292, 0x9297,
-};
-const unsigned short euc_to_utf8_8FE4[] = {
- 0x9299, 0x929F, 0x92A0, 0x92A4, 0x92A5, 0x92A7, 0x92A8,
- 0x92AB, 0x92AF, 0x92B2, 0x92B6, 0x92B8, 0x92BA, 0x92BB, 0x92BC,
- 0x92BD, 0x92BF, 0x92C0, 0x92C1, 0x92C2, 0x92C3, 0x92C5, 0x92C6,
- 0x92C7, 0x92C8, 0x92CB, 0x92CC, 0x92CD, 0x92CE, 0x92D0, 0x92D3,
- 0x92D5, 0x92D7, 0x92D8, 0x92D9, 0x92DC, 0x92DD, 0x92DF, 0x92E0,
- 0x92E1, 0x92E3, 0x92E5, 0x92E7, 0x92E8, 0x92EC, 0x92EE, 0x92F0,
- 0x92F9, 0x92FB, 0x92FF, 0x9300, 0x9302, 0x9308, 0x930D, 0x9311,
- 0x9314, 0x9315, 0x931C, 0x931D, 0x931E, 0x931F, 0x9321, 0x9324,
- 0x9325, 0x9327, 0x9329, 0x932A, 0x9333, 0x9334, 0x9336, 0x9337,
- 0x9347, 0x9348, 0x9349, 0x9350, 0x9351, 0x9352, 0x9355, 0x9357,
- 0x9358, 0x935A, 0x935E, 0x9364, 0x9365, 0x9367, 0x9369, 0x936A,
- 0x936D, 0x936F, 0x9370, 0x9371, 0x9373, 0x9374, 0x9376,
-};
-const unsigned short euc_to_utf8_8FE5[] = {
- 0x937A, 0x937D, 0x937F, 0x9380, 0x9381, 0x9382, 0x9388,
- 0x938A, 0x938B, 0x938D, 0x938F, 0x9392, 0x9395, 0x9398, 0x939B,
- 0x939E, 0x93A1, 0x93A3, 0x93A4, 0x93A6, 0x93A8, 0x93AB, 0x93B4,
- 0x93B5, 0x93B6, 0x93BA, 0x93A9, 0x93C1, 0x93C4, 0x93C5, 0x93C6,
- 0x93C7, 0x93C9, 0x93CA, 0x93CB, 0x93CC, 0x93CD, 0x93D3, 0x93D9,
- 0x93DC, 0x93DE, 0x93DF, 0x93E2, 0x93E6, 0x93E7, 0x93F9, 0x93F7,
- 0x93F8, 0x93FA, 0x93FB, 0x93FD, 0x9401, 0x9402, 0x9404, 0x9408,
- 0x9409, 0x940D, 0x940E, 0x940F, 0x9415, 0x9416, 0x9417, 0x941F,
- 0x942E, 0x942F, 0x9431, 0x9432, 0x9433, 0x9434, 0x943B, 0x943F,
- 0x943D, 0x9443, 0x9445, 0x9448, 0x944A, 0x944C, 0x9455, 0x9459,
- 0x945C, 0x945F, 0x9461, 0x9463, 0x9468, 0x946B, 0x946D, 0x946E,
- 0x946F, 0x9471, 0x9472, 0x9484, 0x9483, 0x9578, 0x9579,
-};
-const unsigned short euc_to_utf8_8FE6[] = {
- 0x957E, 0x9584, 0x9588, 0x958C, 0x958D, 0x958E, 0x959D,
- 0x959E, 0x959F, 0x95A1, 0x95A6, 0x95A9, 0x95AB, 0x95AC, 0x95B4,
- 0x95B6, 0x95BA, 0x95BD, 0x95BF, 0x95C6, 0x95C8, 0x95C9, 0x95CB,
- 0x95D0, 0x95D1, 0x95D2, 0x95D3, 0x95D9, 0x95DA, 0x95DD, 0x95DE,
- 0x95DF, 0x95E0, 0x95E4, 0x95E6, 0x961D, 0x961E, 0x9622, 0x9624,
- 0x9625, 0x9626, 0x962C, 0x9631, 0x9633, 0x9637, 0x9638, 0x9639,
- 0x963A, 0x963C, 0x963D, 0x9641, 0x9652, 0x9654, 0x9656, 0x9657,
- 0x9658, 0x9661, 0x966E, 0x9674, 0x967B, 0x967C, 0x967E, 0x967F,
- 0x9681, 0x9682, 0x9683, 0x9684, 0x9689, 0x9691, 0x9696, 0x969A,
- 0x969D, 0x969F, 0x96A4, 0x96A5, 0x96A6, 0x96A9, 0x96AE, 0x96AF,
- 0x96B3, 0x96BA, 0x96CA, 0x96D2, 0x5DB2, 0x96D8, 0x96DA, 0x96DD,
- 0x96DE, 0x96DF, 0x96E9, 0x96EF, 0x96F1, 0x96FA, 0x9702,
-};
-const unsigned short euc_to_utf8_8FE7[] = {
- 0x9703, 0x9705, 0x9709, 0x971A, 0x971B, 0x971D, 0x9721,
- 0x9722, 0x9723, 0x9728, 0x9731, 0x9733, 0x9741, 0x9743, 0x974A,
- 0x974E, 0x974F, 0x9755, 0x9757, 0x9758, 0x975A, 0x975B, 0x9763,
- 0x9767, 0x976A, 0x976E, 0x9773, 0x9776, 0x9777, 0x9778, 0x977B,
- 0x977D, 0x977F, 0x9780, 0x9789, 0x9795, 0x9796, 0x9797, 0x9799,
- 0x979A, 0x979E, 0x979F, 0x97A2, 0x97AC, 0x97AE, 0x97B1, 0x97B2,
- 0x97B5, 0x97B6, 0x97B8, 0x97B9, 0x97BA, 0x97BC, 0x97BE, 0x97BF,
- 0x97C1, 0x97C4, 0x97C5, 0x97C7, 0x97C9, 0x97CA, 0x97CC, 0x97CD,
- 0x97CE, 0x97D0, 0x97D1, 0x97D4, 0x97D7, 0x97D8, 0x97D9, 0x97DD,
- 0x97DE, 0x97E0, 0x97DB, 0x97E1, 0x97E4, 0x97EF, 0x97F1, 0x97F4,
- 0x97F7, 0x97F8, 0x97FA, 0x9807, 0x980A, 0x9819, 0x980D, 0x980E,
- 0x9814, 0x9816, 0x981C, 0x981E, 0x9820, 0x9823, 0x9826,
-};
-const unsigned short euc_to_utf8_8FE8[] = {
- 0x982B, 0x982E, 0x982F, 0x9830, 0x9832, 0x9833, 0x9835,
- 0x9825, 0x983E, 0x9844, 0x9847, 0x984A, 0x9851, 0x9852, 0x9853,
- 0x9856, 0x9857, 0x9859, 0x985A, 0x9862, 0x9863, 0x9865, 0x9866,
- 0x986A, 0x986C, 0x98AB, 0x98AD, 0x98AE, 0x98B0, 0x98B4, 0x98B7,
- 0x98B8, 0x98BA, 0x98BB, 0x98BF, 0x98C2, 0x98C5, 0x98C8, 0x98CC,
- 0x98E1, 0x98E3, 0x98E5, 0x98E6, 0x98E7, 0x98EA, 0x98F3, 0x98F6,
- 0x9902, 0x9907, 0x9908, 0x9911, 0x9915, 0x9916, 0x9917, 0x991A,
- 0x991B, 0x991C, 0x991F, 0x9922, 0x9926, 0x9927, 0x992B, 0x9931,
- 0x9932, 0x9933, 0x9934, 0x9935, 0x9939, 0x993A, 0x993B, 0x993C,
- 0x9940, 0x9941, 0x9946, 0x9947, 0x9948, 0x994D, 0x994E, 0x9954,
- 0x9958, 0x9959, 0x995B, 0x995C, 0x995E, 0x995F, 0x9960, 0x999B,
- 0x999D, 0x999F, 0x99A6, 0x99B0, 0x99B1, 0x99B2, 0x99B5,
-};
-const unsigned short euc_to_utf8_8FE9[] = {
- 0x99B9, 0x99BA, 0x99BD, 0x99BF, 0x99C3, 0x99C9, 0x99D3,
- 0x99D4, 0x99D9, 0x99DA, 0x99DC, 0x99DE, 0x99E7, 0x99EA, 0x99EB,
- 0x99EC, 0x99F0, 0x99F4, 0x99F5, 0x99F9, 0x99FD, 0x99FE, 0x9A02,
- 0x9A03, 0x9A04, 0x9A0B, 0x9A0C, 0x9A10, 0x9A11, 0x9A16, 0x9A1E,
- 0x9A20, 0x9A22, 0x9A23, 0x9A24, 0x9A27, 0x9A2D, 0x9A2E, 0x9A33,
- 0x9A35, 0x9A36, 0x9A38, 0x9A47, 0x9A41, 0x9A44, 0x9A4A, 0x9A4B,
- 0x9A4C, 0x9A4E, 0x9A51, 0x9A54, 0x9A56, 0x9A5D, 0x9AAA, 0x9AAC,
- 0x9AAE, 0x9AAF, 0x9AB2, 0x9AB4, 0x9AB5, 0x9AB6, 0x9AB9, 0x9ABB,
- 0x9ABE, 0x9ABF, 0x9AC1, 0x9AC3, 0x9AC6, 0x9AC8, 0x9ACE, 0x9AD0,
- 0x9AD2, 0x9AD5, 0x9AD6, 0x9AD7, 0x9ADB, 0x9ADC, 0x9AE0, 0x9AE4,
- 0x9AE5, 0x9AE7, 0x9AE9, 0x9AEC, 0x9AF2, 0x9AF3, 0x9AF5, 0x9AF9,
- 0x9AFA, 0x9AFD, 0x9AFF, 0x9B00, 0x9B01, 0x9B02, 0x9B03,
-};
-const unsigned short euc_to_utf8_8FEA[] = {
- 0x9B04, 0x9B05, 0x9B08, 0x9B09, 0x9B0B, 0x9B0C, 0x9B0D,
- 0x9B0E, 0x9B10, 0x9B12, 0x9B16, 0x9B19, 0x9B1B, 0x9B1C, 0x9B20,
- 0x9B26, 0x9B2B, 0x9B2D, 0x9B33, 0x9B34, 0x9B35, 0x9B37, 0x9B39,
- 0x9B3A, 0x9B3D, 0x9B48, 0x9B4B, 0x9B4C, 0x9B55, 0x9B56, 0x9B57,
- 0x9B5B, 0x9B5E, 0x9B61, 0x9B63, 0x9B65, 0x9B66, 0x9B68, 0x9B6A,
- 0x9B6B, 0x9B6C, 0x9B6D, 0x9B6E, 0x9B73, 0x9B75, 0x9B77, 0x9B78,
- 0x9B79, 0x9B7F, 0x9B80, 0x9B84, 0x9B85, 0x9B86, 0x9B87, 0x9B89,
- 0x9B8A, 0x9B8B, 0x9B8D, 0x9B8F, 0x9B90, 0x9B94, 0x9B9A, 0x9B9D,
- 0x9B9E, 0x9BA6, 0x9BA7, 0x9BA9, 0x9BAC, 0x9BB0, 0x9BB1, 0x9BB2,
- 0x9BB7, 0x9BB8, 0x9BBB, 0x9BBC, 0x9BBE, 0x9BBF, 0x9BC1, 0x9BC7,
- 0x9BC8, 0x9BCE, 0x9BD0, 0x9BD7, 0x9BD8, 0x9BDD, 0x9BDF, 0x9BE5,
- 0x9BE7, 0x9BEA, 0x9BEB, 0x9BEF, 0x9BF3, 0x9BF7, 0x9BF8,
-};
-const unsigned short euc_to_utf8_8FEB[] = {
- 0x9BF9, 0x9BFA, 0x9BFD, 0x9BFF, 0x9C00, 0x9C02, 0x9C0B,
- 0x9C0F, 0x9C11, 0x9C16, 0x9C18, 0x9C19, 0x9C1A, 0x9C1C, 0x9C1E,
- 0x9C22, 0x9C23, 0x9C26, 0x9C27, 0x9C28, 0x9C29, 0x9C2A, 0x9C31,
- 0x9C35, 0x9C36, 0x9C37, 0x9C3D, 0x9C41, 0x9C43, 0x9C44, 0x9C45,
- 0x9C49, 0x9C4A, 0x9C4E, 0x9C4F, 0x9C50, 0x9C53, 0x9C54, 0x9C56,
- 0x9C58, 0x9C5B, 0x9C5D, 0x9C5E, 0x9C5F, 0x9C63, 0x9C69, 0x9C6A,
- 0x9C5C, 0x9C6B, 0x9C68, 0x9C6E, 0x9C70, 0x9C72, 0x9C75, 0x9C77,
- 0x9C7B, 0x9CE6, 0x9CF2, 0x9CF7, 0x9CF9, 0x9D0B, 0x9D02, 0x9D11,
- 0x9D17, 0x9D18, 0x9D1C, 0x9D1D, 0x9D1E, 0x9D2F, 0x9D30, 0x9D32,
- 0x9D33, 0x9D34, 0x9D3A, 0x9D3C, 0x9D45, 0x9D3D, 0x9D42, 0x9D43,
- 0x9D47, 0x9D4A, 0x9D53, 0x9D54, 0x9D5F, 0x9D63, 0x9D62, 0x9D65,
- 0x9D69, 0x9D6A, 0x9D6B, 0x9D70, 0x9D76, 0x9D77, 0x9D7B,
-};
-const unsigned short euc_to_utf8_8FEC[] = {
- 0x9D7C, 0x9D7E, 0x9D83, 0x9D84, 0x9D86, 0x9D8A, 0x9D8D,
- 0x9D8E, 0x9D92, 0x9D93, 0x9D95, 0x9D96, 0x9D97, 0x9D98, 0x9DA1,
- 0x9DAA, 0x9DAC, 0x9DAE, 0x9DB1, 0x9DB5, 0x9DB9, 0x9DBC, 0x9DBF,
- 0x9DC3, 0x9DC7, 0x9DC9, 0x9DCA, 0x9DD4, 0x9DD5, 0x9DD6, 0x9DD7,
- 0x9DDA, 0x9DDE, 0x9DDF, 0x9DE0, 0x9DE5, 0x9DE7, 0x9DE9, 0x9DEB,
- 0x9DEE, 0x9DF0, 0x9DF3, 0x9DF4, 0x9DFE, 0x9E0A, 0x9E02, 0x9E07,
- 0x9E0E, 0x9E10, 0x9E11, 0x9E12, 0x9E15, 0x9E16, 0x9E19, 0x9E1C,
- 0x9E1D, 0x9E7A, 0x9E7B, 0x9E7C, 0x9E80, 0x9E82, 0x9E83, 0x9E84,
- 0x9E85, 0x9E87, 0x9E8E, 0x9E8F, 0x9E96, 0x9E98, 0x9E9B, 0x9E9E,
- 0x9EA4, 0x9EA8, 0x9EAC, 0x9EAE, 0x9EAF, 0x9EB0, 0x9EB3, 0x9EB4,
- 0x9EB5, 0x9EC6, 0x9EC8, 0x9ECB, 0x9ED5, 0x9EDF, 0x9EE4, 0x9EE7,
- 0x9EEC, 0x9EED, 0x9EEE, 0x9EF0, 0x9EF1, 0x9EF2, 0x9EF5,
-};
-const unsigned short euc_to_utf8_8FED[] = {
- 0x9EF8, 0x9EFF, 0x9F02, 0x9F03, 0x9F09, 0x9F0F, 0x9F10,
- 0x9F11, 0x9F12, 0x9F14, 0x9F16, 0x9F17, 0x9F19, 0x9F1A, 0x9F1B,
- 0x9F1F, 0x9F22, 0x9F26, 0x9F2A, 0x9F2B, 0x9F2F, 0x9F31, 0x9F32,
- 0x9F34, 0x9F37, 0x9F39, 0x9F3A, 0x9F3C, 0x9F3D, 0x9F3F, 0x9F41,
- 0x9F43, 0x9F44, 0x9F45, 0x9F46, 0x9F47, 0x9F53, 0x9F55, 0x9F56,
- 0x9F57, 0x9F58, 0x9F5A, 0x9F5D, 0x9F5E, 0x9F68, 0x9F69, 0x9F6D,
- 0x9F6E, 0x9F6F, 0x9F70, 0x9F71, 0x9F73, 0x9F75, 0x9F7A, 0x9F7D,
- 0x9F8F, 0x9F90, 0x9F91, 0x9F92, 0x9F94, 0x9F96, 0x9F97, 0x9F9E,
- 0x9FA1, 0x9FA2, 0x9FA3, 0x9FA5, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short euc_to_utf8_8FF3[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174,
- 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x2160, 0x2161,
-};
-const unsigned short euc_to_utf8_8FF4[] = {
- 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168,
- 0x2169, 0xff07, 0xff02, 0x3231, 0x2116, 0x2121, 0x70bb, 0x4efc,
- 0x50f4, 0x51ec, 0x5307, 0x5324, 0xfa0e, 0x548a, 0x5759, 0xfa0f,
- 0xfa10, 0x589e, 0x5bec, 0x5cf5, 0x5d53, 0xfa11, 0x5fb7, 0x6085,
- 0x6120, 0x654e, 0x663b, 0x6665, 0xfa12, 0xf929, 0x6801, 0xfa13,
- 0xfa14, 0x6a6b, 0x6ae2, 0x6df8, 0x6df2, 0x7028, 0xfa15, 0xfa16,
- 0x7501, 0x7682, 0x769e, 0xfa17, 0x7930, 0xfa18, 0xfa19, 0xfa1a,
- 0xfa1b, 0x7ae7, 0xfa1c, 0xfa1d, 0x7da0, 0x7dd6, 0xfa1e, 0x8362,
- 0xfa1f, 0x85b0, 0xfa20, 0xfa21, 0x8807, 0xfa22, 0x8b7f, 0x8cf4,
- 0x8d76, 0xfa23, 0xfa24, 0xfa25, 0x90de, 0xfa26, 0x9115, 0xfa27,
- 0xfa28, 0x9592, 0xf9dc, 0xfa29, 0x973b, 0x974d, 0x9751, 0xfa2a,
- 0xfa2b, 0xfa2c, 0x999e, 0x9ad9, 0x9b72, 0xfa2d, 0x9ed1,
-};
-#endif /* X0212_ENABLE */
-
-const unsigned short euc_to_utf8_1byte[] = {
- 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
- 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
- 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
- 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
- 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87,
- 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
- 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97,
- 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x00A9, 0x2122,
-};
-const unsigned short *const euc_to_utf8_2bytes[] = {
- euc_to_utf8_A1, euc_to_utf8_A2, euc_to_utf8_A3,
- euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7,
- euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB,
- euc_to_utf8_AC, euc_to_utf8_AD, euc_to_utf8_AE, euc_to_utf8_AF,
- euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3,
- euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7,
- euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB,
- euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF,
- euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3,
- euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7,
- euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB,
- euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF,
- euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3,
- euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7,
- euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB,
- euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF,
- euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3,
- euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7,
- euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB,
- euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF,
- euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3,
- euc_to_utf8_F4, euc_to_utf8_F5, 0, 0,
- 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB,
- euc_to_utf8_FC, 0, 0,
-};
-/* Microsoft UCS Mapping Compatible */
-const unsigned short *const euc_to_utf8_2bytes_ms[] = {
- euc_to_utf8_A1_ms, euc_to_utf8_A2_ms, euc_to_utf8_A3,
- euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7,
- euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB,
- euc_to_utf8_AC, euc_to_utf8_AD, euc_to_utf8_AE, euc_to_utf8_AF,
- euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3,
- euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7,
- euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB,
- euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF,
- euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3,
- euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7,
- euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB,
- euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF,
- euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3,
- euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7,
- euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB,
- euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF,
- euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3,
- euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7,
- euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB,
- euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF,
- euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3,
- euc_to_utf8_F4, euc_to_utf8_F5, 0, 0,
- 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB,
- euc_to_utf8_FC_ms, 0, 0,
-};
-
-#ifdef X0212_ENABLE
-const unsigned short *const x0212_to_utf8_2bytes[] = {
- 0, euc_to_utf8_8FA2, 0,
- 0, 0, euc_to_utf8_8FA6, euc_to_utf8_8FA7,
- 0, euc_to_utf8_8FA9, euc_to_utf8_8FAA, euc_to_utf8_8FAB,
- 0, 0, 0, 0,
- euc_to_utf8_8FB0, euc_to_utf8_8FB1, euc_to_utf8_8FB2, euc_to_utf8_8FB3,
- euc_to_utf8_8FB4, euc_to_utf8_8FB5, euc_to_utf8_8FB6, euc_to_utf8_8FB7,
- euc_to_utf8_8FB8, euc_to_utf8_8FB9, euc_to_utf8_8FBA, euc_to_utf8_8FBB,
- euc_to_utf8_8FBC, euc_to_utf8_8FBD, euc_to_utf8_8FBE, euc_to_utf8_8FBF,
- euc_to_utf8_8FC0, euc_to_utf8_8FC1, euc_to_utf8_8FC2, euc_to_utf8_8FC3,
- euc_to_utf8_8FC4, euc_to_utf8_8FC5, euc_to_utf8_8FC6, euc_to_utf8_8FC7,
- euc_to_utf8_8FC8, euc_to_utf8_8FC9, euc_to_utf8_8FCA, euc_to_utf8_8FCB,
- euc_to_utf8_8FCC, euc_to_utf8_8FCD, euc_to_utf8_8FCE, euc_to_utf8_8FCF,
- euc_to_utf8_8FD0, euc_to_utf8_8FD1, euc_to_utf8_8FD2, euc_to_utf8_8FD3,
- euc_to_utf8_8FD4, euc_to_utf8_8FD5, euc_to_utf8_8FD6, euc_to_utf8_8FD7,
- euc_to_utf8_8FD8, euc_to_utf8_8FD9, euc_to_utf8_8FDA, euc_to_utf8_8FDB,
- euc_to_utf8_8FDC, euc_to_utf8_8FDD, euc_to_utf8_8FDE, euc_to_utf8_8FDF,
- euc_to_utf8_8FE0, euc_to_utf8_8FE1, euc_to_utf8_8FE2, euc_to_utf8_8FE3,
- euc_to_utf8_8FE4, euc_to_utf8_8FE5, euc_to_utf8_8FE6, euc_to_utf8_8FE7,
- euc_to_utf8_8FE8, euc_to_utf8_8FE9, euc_to_utf8_8FEA, euc_to_utf8_8FEB,
- euc_to_utf8_8FEC, euc_to_utf8_8FED, 0, 0,
- 0, 0, 0, euc_to_utf8_8FF3,
- euc_to_utf8_8FF4, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0,};
-#endif /* X0212_ENABLE */
-#endif /* UTF8_OUTPUT_ENABLE */
-
-#ifdef UTF8_INPUT_ENABLE
-const unsigned short utf8_to_euc_C2[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xA242, 0x2171, 0x2172, 0xA270, 0x216F, 0xA243, 0x2178,
- 0x212F, 0xA26D, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234,
- 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0,
- 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244,
-};
-const unsigned short utf8_to_euc_C2_ms[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xA242, 0x2171, 0x2172, 0xA270, 0x5C, 0xA243, 0x2178,
- 0x212F, 0xA26D, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234,
- 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0,
- 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244,
-};
-const unsigned short utf8_to_euc_C2_932[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x21, 0x2171, 0x2172, 0, 0x5C, 0x7C, 0x2178,
- 0x212F, 0x63, 0x61, 0x2263, 0x224C, 0x2D, 0x52, 0x2131,
- 0x216B, 0x215E, 0x32, 0x33, 0x212D, 0x264C, 0x2279, 0x2126,
- 0x2124, 0x31, 0x6F, 0x2264, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_C3[] = {
- 0xAA22, 0xAA21, 0xAA24, 0xAA2A, 0xAA23, 0xAA29, 0xA921, 0xAA2E,
- 0xAA32, 0xAA31, 0xAA34, 0xAA33, 0xAA40, 0xAA3F, 0xAA42, 0xAA41,
- 0, 0xAA50, 0xAA52, 0xAA51, 0xAA54, 0xAA58, 0xAA53, 0x215F,
- 0xA92C, 0xAA63, 0xAA62, 0xAA65, 0xAA64, 0xAA72, 0xA930, 0xA94E,
- 0xAB22, 0xAB21, 0xAB24, 0xAB2A, 0xAB23, 0xAB29, 0xA941, 0xAB2E,
- 0xAB32, 0xAB31, 0xAB34, 0xAB33, 0xAB40, 0xAB3F, 0xAB42, 0xAB41,
- 0xA943, 0xAB50, 0xAB52, 0xAB51, 0xAB54, 0xAB58, 0xAB53, 0x2160,
- 0xA94C, 0xAB63, 0xAB62, 0xAB65, 0xAB64, 0xAB72, 0xA950, 0xAB73,
-};
-const unsigned short utf8_to_euc_C3_932[] = {
- 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43,
- 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
- 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x215F,
- 0x4F, 0x55, 0x55, 0x55, 0x55, 0x59, 0x54, 0x73,
- 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x63,
- 0x65, 0x65, 0x65, 0x65, 0x69, 0x69, 0x69, 0x69,
- 0x64, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x2160,
- 0x6F, 0x75, 0x75, 0x75, 0x75, 0x79, 0x74, 0x79,
-};
-const unsigned short utf8_to_euc_C4[] = {
- 0xAA27, 0xAB27, 0xAA25, 0xAB25, 0xAA28, 0xAB28, 0xAA2B, 0xAB2B,
- 0xAA2C, 0xAB2C, 0xAA2F, 0xAB2F, 0xAA2D, 0xAB2D, 0xAA30, 0xAB30,
- 0xA922, 0xA942, 0xAA37, 0xAB37, 0, 0, 0xAA36, 0xAB36,
- 0xAA38, 0xAB38, 0xAA35, 0xAB35, 0xAA3A, 0xAB3A, 0xAA3B, 0xAB3B,
- 0xAA3D, 0xAB3D, 0xAA3C, 0, 0xAA3E, 0xAB3E, 0xA924, 0xA944,
- 0xAA47, 0xAB47, 0xAA45, 0xAB45, 0, 0, 0xAA46, 0xAB46,
- 0xAA44, 0xA945, 0xA926, 0xA946, 0xAA48, 0xAB48, 0xAA49, 0xAB49,
- 0xA947, 0xAA4A, 0xAB4A, 0xAA4C, 0xAB4C, 0xAA4B, 0xAB4B, 0xA929,
-};
-const unsigned short utf8_to_euc_C5[] = {
- 0xA949, 0xA928, 0xA948, 0xAA4D, 0xAB4D, 0xAA4F, 0xAB4F, 0xAA4E,
- 0xAB4E, 0xA94A, 0xA92B, 0xA94B, 0xAA57, 0xAB57, 0, 0,
- 0xAA56, 0xAB56, 0xA92D, 0xA94D, 0xAA59, 0xAB59, 0xAA5B, 0xAB5B,
- 0xAA5A, 0xAB5A, 0xAA5C, 0xAB5C, 0xAA5D, 0xAB5D, 0xAA5F, 0xAB5F,
- 0xAA5E, 0xAB5E, 0xAA61, 0xAB61, 0xAA60, 0xAB60, 0xA92F, 0xA94F,
- 0xAA6C, 0xAB6C, 0xAA69, 0xAB69, 0xAA66, 0xAB66, 0xAA6B, 0xAB6B,
- 0xAA68, 0xAB68, 0xAA6A, 0xAB6A, 0xAA71, 0xAB71, 0xAA74, 0xAB74,
- 0xAA73, 0xAA75, 0xAB75, 0xAA77, 0xAB77, 0xAA76, 0xAB76, 0,
-};
-const unsigned short utf8_to_euc_C7[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xAA26, 0xAB26, 0xAA43,
- 0xAB43, 0xAA55, 0xAB55, 0xAA67, 0xAB67, 0xAA70, 0xAB70, 0xAA6D,
- 0xAB6D, 0xAA6F, 0xAB6F, 0xAA6E, 0xAB6E, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xAB39, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_CB[] = {
- 0, 0, 0, 0, 0, 0, 0, 0xA230,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xA22F, 0xA232, 0xA236, 0xA235, 0, 0xA233, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_CE[] = {
- 0, 0, 0, 0, 0xA238, 0xA239, 0xA661, 0,
- 0xA662, 0xA663, 0xA664, 0, 0xA667, 0, 0xA669, 0xA66C,
- 0xA676, 0x2621, 0x2622, 0x2623, 0x2624, 0x2625, 0x2626, 0x2627,
- 0x2628, 0x2629, 0x262A, 0x262B, 0x262C, 0x262D, 0x262E, 0x262F,
- 0x2630, 0x2631, 0, 0x2632, 0x2633, 0x2634, 0x2635, 0x2636,
- 0x2637, 0x2638, 0xA665, 0xA66A, 0xA671, 0xA672, 0xA673, 0xA674,
- 0xA67B, 0x2641, 0x2642, 0x2643, 0x2644, 0x2645, 0x2646, 0x2647,
- 0x2648, 0x2649, 0x264A, 0x264B, 0x264C, 0x264D, 0x264E, 0x264F,
-};
-const unsigned short utf8_to_euc_CF[] = {
- 0x2650, 0x2651, 0xA678, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656,
- 0x2657, 0x2658, 0xA675, 0xA67A, 0xA677, 0xA679, 0xA67C, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_D0[] = {
- 0, 0x2727, 0xA742, 0xA743, 0xA744, 0xA745, 0xA746, 0xA747,
- 0xA748, 0xA749, 0xA74A, 0xA74B, 0xA74C, 0, 0xA74D, 0xA74E,
- 0x2721, 0x2722, 0x2723, 0x2724, 0x2725, 0x2726, 0x2728, 0x2729,
- 0x272A, 0x272B, 0x272C, 0x272D, 0x272E, 0x272F, 0x2730, 0x2731,
- 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737, 0x2738, 0x2739,
- 0x273A, 0x273B, 0x273C, 0x273D, 0x273E, 0x273F, 0x2740, 0x2741,
- 0x2751, 0x2752, 0x2753, 0x2754, 0x2755, 0x2756, 0x2758, 0x2759,
- 0x275A, 0x275B, 0x275C, 0x275D, 0x275E, 0x275F, 0x2760, 0x2761,
-};
-const unsigned short utf8_to_euc_D1[] = {
- 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767, 0x2768, 0x2769,
- 0x276A, 0x276B, 0x276C, 0x276D, 0x276E, 0x276F, 0x2770, 0x2771,
- 0, 0x2757, 0xA772, 0xA773, 0xA774, 0xA775, 0xA776, 0xA777,
- 0xA778, 0xA779, 0xA77A, 0xA77B, 0xA77C, 0, 0xA77D, 0xA77E,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E280[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x213E, 0, 0, 0, 0x213D, 0x213D, 0x2142, 0,
- 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0,
- 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0,
- 0, 0, 0, 0x2228, 0, 0, 0x2131, 0,
-};
-const unsigned short utf8_to_euc_E280_ms[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x213E, 0, 0, 0, 0x213D, 0x213D, 0x2142, 0,
- 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0,
- 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0,
- 0, 0, 0, 0x2228, 0, 0, 0x7E, 0,
-};
-const unsigned short utf8_to_euc_E280_932[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x213E, 0, 0, 0, 0, 0x213D, 0, 0,
- 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0,
- 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0,
- 0, 0, 0, 0x2228, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E284[] = {
- 0, 0, 0, 0x216E, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2D62, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2D64, 0xA26F, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2272, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E285[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2D35, 0x2D36, 0x2D37, 0x2D38, 0x2D39, 0x2D3A, 0x2D3B, 0x2D3C,
- 0x2D3D, 0x2D3E, 0, 0, 0, 0, 0, 0,
- 0xF373, 0xF374, 0xF375, 0xF376, 0xF377, 0xF378, 0xF379, 0xF37A,
- 0xF37B, 0xF37C, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E286[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x222B, 0x222C, 0x222A, 0x222D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E287[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x224D, 0, 0x224E, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E288[] = {
- 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260,
- 0x223A, 0, 0, 0x223B, 0, 0, 0, 0,
- 0, 0x2D74, 0x215D, 0, 0, 0, 0, 0,
- 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78,
- 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A,
- 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0,
- 0, 0, 0, 0, 0x2168, 0x2268, 0, 0,
- 0, 0, 0, 0, 0, 0x2266, 0, 0,
-};
-const unsigned short utf8_to_euc_E288_932[] = {
- 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260,
- 0x223A, 0, 0, 0x223B, 0, 0, 0, 0,
- 0, 0x2D74, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78,
- 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A,
- 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0,
- 0, 0, 0, 0, 0x2168, 0x2268, 0, 0,
- 0, 0, 0, 0, 0, 0x2266, 0, 0,
-};
-const unsigned short utf8_to_euc_E289[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2262, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2162, 0x2261, 0, 0, 0, 0, 0x2165, 0x2166,
- 0, 0, 0x2263, 0x2264, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E28A[] = {
- 0, 0, 0x223E, 0x223F, 0, 0, 0x223C, 0x223D,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x225D, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x2D79,
-};
-const unsigned short utf8_to_euc_E28C[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x225E, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E291[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2D21, 0x2D22, 0x2D23, 0x2D24, 0x2D25, 0x2D26, 0x2D27, 0x2D28,
- 0x2D29, 0x2D2A, 0x2D2B, 0x2D2C, 0x2D2D, 0x2D2E, 0x2D2F, 0x2D30,
- 0x2D31, 0x2D32, 0x2D33, 0x2D34, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E294[] = {
- 0x2821, 0x282C, 0x2822, 0x282D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2823, 0, 0, 0x282E,
- 0x2824, 0, 0, 0x282F, 0x2826, 0, 0, 0x2831,
- 0x2825, 0, 0, 0x2830, 0x2827, 0x283C, 0, 0,
- 0x2837, 0, 0, 0x2832, 0x2829, 0x283E, 0, 0,
- 0x2839, 0, 0, 0x2834, 0x2828, 0, 0, 0x2838,
- 0x283D, 0, 0, 0x2833, 0x282A, 0, 0, 0x283A,
- 0x283F, 0, 0, 0x2835, 0x282B, 0, 0, 0x283B,
-};
-const unsigned short utf8_to_euc_E295[] = {
- 0, 0, 0x2840, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2836, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E296[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2223, 0x2222, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2225, 0x2224, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2227, 0x2226, 0, 0,
-};
-const unsigned short utf8_to_euc_E297[] = {
- 0, 0, 0, 0, 0, 0, 0x2221, 0x217E,
- 0, 0, 0, 0x217B, 0, 0, 0x217D, 0x217C,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x227E,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E298[] = {
- 0, 0, 0, 0, 0, 0x217A, 0x2179, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E299[] = {
- 0x216A, 0, 0x2169, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2276, 0, 0, 0x2275, 0, 0x2274,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E380[] = {
- 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B,
- 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159,
- 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0, 0,
- 0, 0, 0, 0, 0x2141, 0x2D60, 0, 0x2D61,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E380_932[] = {
- 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B,
- 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159,
- 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0, 0,
- 0, 0, 0, 0, 0, 0x2D60, 0, 0x2D61,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E381[] = {
- 0, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427,
- 0x2428, 0x2429, 0x242A, 0x242B, 0x242C, 0x242D, 0x242E, 0x242F,
- 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437,
- 0x2438, 0x2439, 0x243A, 0x243B, 0x243C, 0x243D, 0x243E, 0x243F,
- 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447,
- 0x2448, 0x2449, 0x244A, 0x244B, 0x244C, 0x244D, 0x244E, 0x244F,
- 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457,
- 0x2458, 0x2459, 0x245A, 0x245B, 0x245C, 0x245D, 0x245E, 0x245F,
-};
-const unsigned short utf8_to_euc_E382[] = {
- 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
- 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F,
- 0x2470, 0x2471, 0x2472, 0x2473, 0, 0, 0, 0,
- 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0,
- 0, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527,
- 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F,
- 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537,
- 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F,
-};
-const unsigned short utf8_to_euc_E382_932[] = {
- 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
- 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F,
- 0x2470, 0x2471, 0x2472, 0x2473, 0x2574, 0, 0, 0,
- 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0,
- 0, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527,
- 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F,
- 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537,
- 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F,
-};
-const unsigned short utf8_to_euc_E383[] = {
- 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547,
- 0x2548, 0x2549, 0x254A, 0x254B, 0x254C, 0x254D, 0x254E, 0x254F,
- 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557,
- 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, 0x255F,
- 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567,
- 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x256D, 0x256E, 0x256F,
- 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0,
- 0, 0, 0, 0x2126, 0x213C, 0x2133, 0x2134, 0,
-};
-const unsigned short utf8_to_euc_E388[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2D6A, 0x2D6B, 0, 0, 0, 0, 0,
- 0, 0x2D6C, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E38A[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2D65, 0x2D66, 0x2D67, 0x2D68,
- 0x2D69, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E38C[] = {
- 0, 0, 0, 0x2D46, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2D4A, 0, 0,
- 0, 0, 0, 0, 0x2D41, 0, 0, 0,
- 0x2D44, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2D42, 0x2D4C, 0, 0, 0x2D4B, 0x2D45,
- 0, 0, 0, 0x2D4D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2D47, 0,
- 0, 0, 0, 0x2D4F, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E38D[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2D40, 0x2D4E, 0, 0, 0x2D43, 0, 0,
- 0, 0x2D48, 0, 0, 0, 0, 0, 0x2D49,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2D5F, 0x2D6F, 0x2D6E, 0x2D6D, 0,
-};
-const unsigned short utf8_to_euc_E38E[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2D53, 0x2D54,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2D50, 0x2D51, 0x2D52, 0,
- 0, 0x2D56, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E38F[] = {
- 0, 0, 0, 0, 0x2D55, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2D63, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E4B8[] = {
- 0x306C, 0x437A, 0xB021, 0x3C37, 0xB022, 0xB023, 0, 0x4B7C,
- 0x3E66, 0x3B30, 0x3E65, 0x323C, 0xB024, 0x4954, 0x4D3F, 0,
- 0x5022, 0x312F, 0xB025, 0, 0x336E, 0x5023, 0x4024, 0x5242,
- 0x3556, 0x4A3A, 0, 0, 0, 0, 0x3E67, 0xB026,
- 0, 0x4E3E, 0, 0xB027, 0xB028, 0, 0x4A42, 0,
- 0xB029, 0, 0x5024, 0xB02A, 0, 0x4366, 0xB02B, 0xB02C,
- 0xB02D, 0x5025, 0x367A, 0, 0, 0xB02E, 0x5026, 0,
- 0x345D, 0x4330, 0, 0x3C67, 0x5027, 0, 0, 0x5028,
-};
-const unsigned short utf8_to_euc_E4B9[] = {
- 0xB02F, 0xB030, 0x5029, 0x4735, 0xB031, 0x3557, 0, 0xB032,
- 0, 0, 0, 0x4737, 0, 0x4663, 0x3843, 0x4B33,
- 0, 0xB033, 0, 0, 0, 0x6949, 0x502A, 0x3E68,
- 0x502B, 0x3235, 0xB034, 0, 0xB035, 0x3665, 0x3870, 0x4C69,
- 0, 0, 0x5626, 0xB036, 0, 0, 0, 0,
- 0xB037, 0xB038, 0, 0, 0, 0, 0, 0,
- 0, 0x4D70, 0, 0x467D, 0xB039, 0xB03A, 0, 0,
- 0, 0xB03B, 0, 0, 0, 0, 0x3425, 0xB03C,
-};
-const unsigned short utf8_to_euc_E4BA[] = {
- 0x3535, 0, 0x502C, 0, 0, 0x502D, 0x4E3B, 0,
- 0x4D3D, 0x4168, 0x502F, 0x3B76, 0x4673, 0xB03D, 0x5032, 0,
- 0, 0x313E, 0x385F, 0, 0x385E, 0x3066, 0xB03E, 0xB03F,
- 0x4F4B, 0x4F4A, 0, 0x3A33, 0x3021, 0xB040, 0x5033, 0x5034,
- 0x5035, 0x4B34, 0x5036, 0, 0x3872, 0x3067, 0x4B72, 0,
- 0x357C, 0, 0, 0x357D, 0x357E, 0x4462, 0x4E3C, 0xB041,
- 0x5037, 0, 0, 0x5038, 0, 0, 0x5039, 0,
- 0, 0xB042, 0x3F4D, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E4BB[] = {
- 0x3D3A, 0x3F4E, 0x503E, 0xB043, 0x503C, 0, 0x503D, 0x3558,
- 0, 0, 0x3A23, 0x3270, 0, 0x503B, 0x503A, 0x4A29,
- 0xB044, 0, 0, 0, 0x3B46, 0x3B45, 0x423E, 0x503F,
- 0x4955, 0x4067, 0xB045, 0xB046, 0, 0x2138, 0x5040, 0x5042,
- 0xB047, 0xB048, 0xB049, 0x4265, 0x4E61, 0x304A, 0, 0,
- 0xB04A, 0, 0, 0, 0, 0x5041, 0x323E, 0xB04B,
- 0x3644, 0xB04C, 0x4367, 0xB04D, 0, 0xB04E, 0x376F, 0x5043,
- 0, 0, 0, 0x4724, 0xF42F, 0xB04F, 0xB050, 0xB051,
-};
-const unsigned short utf8_to_euc_E4BC[] = {
- 0xB052, 0x346B, 0xB053, 0xB054, 0, 0, 0, 0,
- 0xB055, 0x5044, 0x304B, 0xB056, 0xB057, 0x3860, 0x346C, 0x497A,
- 0x4832, 0x3559, 0xB058, 0, 0, 0xB059, 0xB05A, 0xB05B,
- 0, 0xB05C, 0x3271, 0, 0x5067, 0x4541, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xB05D, 0x476C,
- 0x5046, 0xB05E, 0, 0xB060, 0x483C, 0xB061, 0x4E62, 0xB062,
- 0x3F2D, 0xB063, 0x3B47, 0xB064, 0x3B77, 0x3240, 0xB065, 0,
-};
-const unsigned short utf8_to_euc_E4BD[] = {
- 0xB066, 0, 0xB067, 0x4451, 0, 0, 0x4322, 0x504A,
- 0xB068, 0xB069, 0, 0xB06A, 0xB06B, 0x304C, 0x4463, 0x3D3B,
- 0x3A34, 0x4D24, 0xB06C, 0x424E, 0xB06D, 0x323F, 0xB06E, 0x5049,
- 0xB06F, 0x4D3E, 0x5045, 0x5047, 0x3A6E, 0x5048, 0x5524, 0xB070,
- 0xB05F, 0, 0, 0xB071, 0, 0, 0, 0,
- 0, 0x5050, 0xB072, 0, 0xB073, 0, 0xB074, 0x5053,
- 0x5051, 0xB075, 0, 0x3242, 0, 0x4A3B, 0x504B, 0xB076,
- 0xB077, 0xB078, 0xB079, 0x504F, 0x3873, 0xB07A, 0xB07B, 0x3B48,
-};
-const unsigned short utf8_to_euc_E4BE[] = {
- 0, 0xB07C, 0xB07D, 0x3426, 0xB07E, 0xB121, 0x5054, 0,
- 0x504C, 0xB122, 0xB123, 0x4E63, 0xB124, 0x3B78, 0xB125, 0x504D,
- 0xB126, 0x5052, 0xB127, 0xB128, 0xB129, 0, 0x5055, 0xB12A,
- 0x504E, 0xB12B, 0xB12C, 0x3621, 0, 0x304D, 0xB12D, 0xB12E,
- 0x3622, 0x3241, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x5525, 0, 0x4B79, 0x496E, 0x3874,
- 0, 0, 0xB12F, 0, 0, 0x3F2F, 0x4E37, 0xB130,
- 0, 0xB131, 0, 0xB132, 0xB133, 0xB134, 0xB135, 0x4A58,
-};
-const unsigned short utf8_to_euc_E4BF[] = {
- 0xB136, 0xB137, 0x3738, 0x4225, 0x3264, 0xB138, 0xB139, 0,
- 0xB13A, 0xB13B, 0x3D53, 0xB13C, 0xB13D, 0xB13E, 0x5059, 0xB13F,
- 0x505E, 0x505C, 0xB140, 0, 0x5057, 0, 0, 0x422F,
- 0x505A, 0, 0x505D, 0x505B, 0xB141, 0x4A5D, 0, 0x5058,
- 0xB142, 0x3F2E, 0xB143, 0x4B73, 0x505F, 0x5060, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x3D24, 0x506D,
- 0xB144, 0, 0xB145, 0x4750, 0, 0x4936, 0x5068, 0,
- 0x4A70, 0, 0x3236, 0, 0xB146, 0xB147, 0x506C, 0xB148,
-};
-const unsigned short utf8_to_euc_E580[] = {
- 0xB149, 0xB14A, 0, 0, 0xB14B, 0x5066, 0x506F, 0xB14C,
- 0, 0x4152, 0xB14D, 0x3844, 0xB14E, 0x475C, 0xB14F, 0x6047,
- 0xB150, 0x506E, 0x455D, 0xB151, 0x5063, 0, 0x3876, 0xB152,
- 0xB153, 0x3875, 0x5061, 0xB154, 0xB155, 0xB156, 0xB157, 0x3C5A,
- 0, 0x5069, 0xB158, 0x4A6F, 0x434D, 0x5065, 0x3771, 0xB159,
- 0x5062, 0x506A, 0x5064, 0x4E51, 0x506B, 0x4F41, 0xB15A, 0,
- 0xB15B, 0, 0xB15C, 0xB15D, 0, 0xB15E, 0x3666, 0,
- 0, 0x3770, 0, 0xB176, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E581[] = {
- 0xB15F, 0xB160, 0xB161, 0x5070, 0, 0xB162, 0xB163, 0x5071,
- 0x5075, 0x304E, 0xB164, 0, 0xB165, 0, 0xB166, 0x4A50,
- 0x5074, 0xB167, 0xB168, 0xB169, 0, 0x5073, 0x5077, 0xB16A,
- 0, 0xB16B, 0x5076, 0, 0x4464, 0, 0, 0xB16C,
- 0xB16D, 0, 0xB16E, 0xB16F, 0, 0x3772, 0xB170, 0xB171,
- 0, 0, 0xB172, 0, 0x5078, 0xB173, 0, 0,
- 0xB174, 0xB175, 0x3C45, 0, 0x4226, 0x4465, 0x3676, 0,
- 0x5079, 0, 0, 0, 0, 0x3536, 0, 0,
-};
-const unsigned short utf8_to_euc_E582[] = {
- 0x507A, 0xB177, 0, 0xB178, 0xB179, 0x507C, 0xB17A, 0,
- 0, 0, 0xB17B, 0, 0, 0x4B35, 0xB17C, 0xB17D,
- 0xB17E, 0x3766, 0xB221, 0xB222, 0xB223, 0, 0xB224, 0,
- 0x3B31, 0x4877, 0x507B, 0xB225, 0xB226, 0, 0xB227, 0xB228,
- 0xB229, 0xB22A, 0xB22B, 0, 0, 0, 0, 0,
- 0, 0, 0xB22C, 0, 0x3A45, 0x4D43, 0, 0xB22D,
- 0xB22E, 0, 0x507E, 0x5123, 0x507D, 0x3A44, 0, 0x3D7D,
- 0, 0xB22F, 0xB230, 0, 0, 0xB231, 0x3739, 0,
-};
-const unsigned short utf8_to_euc_E583[] = {
- 0xB232, 0, 0x5124, 0xB233, 0xB234, 0x364F, 0, 0xB235,
- 0, 0x5121, 0x5122, 0, 0xB236, 0x462F, 0xB237, 0x417C,
- 0xB238, 0x3623, 0, 0xB239, 0xB23A, 0x4B4D, 0x5125, 0,
- 0xB23B, 0, 0x4E3D, 0, 0xB23C, 0xB23D, 0x5126, 0xB23E,
- 0, 0, 0xB23F, 0x5129, 0xB240, 0x5127, 0xB241, 0x414E,
- 0xB242, 0xB243, 0, 0, 0, 0x5128, 0x512A, 0xB244,
- 0, 0xB245, 0xB251, 0, 0xF430, 0x512C, 0xB246, 0,
- 0, 0x512B, 0xB247, 0x4A48, 0, 0, 0xB248, 0,
-};
-const unsigned short utf8_to_euc_E584[] = {
- 0x3537, 0x512E, 0x512F, 0xB249, 0x322F, 0, 0xB24A, 0xB24B,
- 0xB24C, 0x512D, 0, 0xB24D, 0xB24E, 0xB24F, 0xB250, 0,
- 0xB252, 0, 0x3C74, 0, 0x5132, 0x5131, 0x5130, 0xB253,
- 0x5056, 0xB254, 0x5133, 0xB255, 0xB256, 0xB257, 0xB258, 0x3D7E,
- 0, 0x5134, 0, 0xB259, 0, 0, 0, 0xB25A,
- 0xB25B, 0, 0x4D25, 0, 0xB25C, 0xB25D, 0, 0xB25E,
- 0, 0xB25F, 0x4C59, 0xB260, 0xB261, 0xB262, 0, 0x5136,
- 0xB263, 0xB264, 0x5135, 0x5138, 0x5137, 0, 0, 0x5139,
-};
-const unsigned short utf8_to_euc_E585[] = {
- 0x513A, 0x3074, 0xB265, 0x3835, 0x373B, 0x3D3C, 0x437B, 0x3624,
- 0x4068, 0x3877, 0xB266, 0x396E, 0x513C, 0x4C48, 0x4546, 0xB267,
- 0x3B79, 0, 0x513B, 0xB268, 0x513D, 0xB269, 0, 0xB26A,
- 0xB26B, 0, 0x455E, 0, 0x3375, 0, 0, 0xB26C,
- 0, 0, 0x513E, 0, 0xB26D, 0x467E, 0xB26E, 0,
- 0x4134, 0x5140, 0x5141, 0x482C, 0x3878, 0x4F3B, 0x5142, 0,
- 0, 0x3626, 0, 0, 0, 0x4A3C, 0x4236, 0x3671,
- 0x4535, 0, 0, 0, 0x3773, 0, 0xB26F, 0,
-};
-const unsigned short utf8_to_euc_E586[] = {
- 0x5143, 0, 0x5144, 0xB270, 0xB271, 0x4662, 0x315F, 0,
- 0, 0x5147, 0x3A7D, 0xB272, 0x5146, 0x3A46, 0xB273, 0x5148,
- 0x666E, 0x5149, 0x4B41, 0x514A, 0, 0x514B, 0x514C, 0x3E69,
- 0xB274, 0x3C4C, 0, 0, 0, 0xB275, 0, 0,
- 0x3427, 0xB276, 0x514F, 0xB277, 0x514D, 0x4C3D, 0x514E, 0,
- 0x495A, 0x5150, 0x5151, 0x5152, 0x455F, 0xB278, 0, 0,
- 0x5156, 0x5154, 0x5155, 0x5153, 0x3A63, 0x5157, 0x4C6A, 0x4E64,
- 0xB279, 0, 0xB27A, 0, 0xB27B, 0x5158, 0xB27C, 0xB27D,
-};
-const unsigned short utf8_to_euc_E587[] = {
- 0, 0, 0xB27E, 0, 0x4028, 0x5159, 0x3D5A, 0,
- 0xB321, 0x515A, 0, 0x437C, 0x4E3F, 0x4560, 0, 0xB322,
- 0, 0xB323, 0xB324, 0xB325, 0, 0xB326, 0x5245, 0,
- 0xB327, 0, 0, 0x515B, 0x7425, 0x3645, 0xB328, 0,
- 0x515C, 0x4B5E, 0xB329, 0, 0, 0xB32A, 0x3D68, 0x427C,
- 0, 0x515E, 0x4664, 0, 0xF431, 0x515F, 0xB32B, 0,
- 0x5160, 0x332E, 0xB32C, 0xB32D, 0xB32E, 0x5161, 0x3627, 0xB32F,
- 0x464C, 0x317A, 0x3D50, 0, 0, 0x4821, 0x5162, 0,
-};
-const unsigned short utf8_to_euc_E588[] = {
- 0x4561, 0xB330, 0xB331, 0x3F4F, 0x5163, 0xB332, 0x4A2C, 0x405A,
- 0x3422, 0, 0x3429, 0x5164, 0, 0, 0x5166, 0,
- 0, 0x373A, 0xB333, 0xB334, 0x5165, 0xB335, 0xB336, 0x4E73,
- 0xB337, 0, 0, 0, 0, 0x3D69, 0, 0,
- 0, 0, 0xB338, 0, 0x483D, 0x4A4C, 0, 0x5167,
- 0xB339, 0x4D78, 0x5168, 0, 0, 0, 0x5169, 0,
- 0x457E, 0xB33A, 0xB33B, 0x516A, 0, 0xB33C, 0x4029, 0x3A7E,
- 0x3774, 0x516B, 0x3B49, 0x396F, 0xB33D, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E589[] = {
- 0, 0, 0, 0x4466, 0x516D, 0xB33E, 0, 0x4227,
- 0, 0xB33F, 0x3A6F, 0x516E, 0x516F, 0x4130, 0, 0x516C,
- 0, 0, 0, 0, 0x5171, 0xB340, 0x4B36, 0xB341,
- 0xB342, 0, 0xB343, 0x3964, 0xB344, 0, 0x5170, 0xB345,
- 0xB346, 0xB347, 0, 0x3775, 0x3A5E, 0x476D, 0xB348, 0,
- 0, 0x5174, 0x5172, 0, 0, 0, 0xB349, 0x497B,
- 0x3E6A, 0x517B, 0x3364, 0x5175, 0x5173, 0x414F, 0, 0xB34A,
- 0xB34B, 0xB34C, 0, 0, 0, 0x5177, 0, 0x5176,
-};
-const unsigned short utf8_to_euc_E58A[] = {
- 0xB34D, 0, 0xB34E, 0x3344, 0, 0xB34F, 0, 0x3760,
- 0x517C, 0x4E2D, 0xB350, 0, 0xB351, 0x5178, 0, 0,
- 0, 0x517D, 0x517A, 0xB352, 0x5179, 0xB353, 0xB354, 0xB355,
- 0xB356, 0, 0xB357, 0x4E4F, 0xB358, 0, 0, 0x3879,
- 0x3243, 0, 0, 0x4E74, 0xB359, 0xB35A, 0xB35B, 0xB35C,
- 0, 0x3D75, 0x4558, 0x3965, 0x5222, 0x5223, 0, 0xB35D,
- 0xB35E, 0x4E65, 0, 0, 0x4F2B, 0x5225, 0xB35F, 0xB360,
- 0xB361, 0x387A, 0xB362, 0xB363, 0x5224, 0xB364, 0x332F, 0,
-};
-const unsigned short utf8_to_euc_E58B[] = {
- 0xB365, 0x5226, 0, 0x4B56, 0xB366, 0x443C, 0xB367, 0x4D26,
- 0xB368, 0x4A59, 0, 0, 0xB369, 0x5227, 0, 0xB36A,
- 0, 0xB36B, 0x7055, 0, 0xB36C, 0x4630, 0xB36D, 0x5228,
- 0x342A, 0x4C33, 0, 0xB36E, 0xB36F, 0x3E21, 0x5229, 0x4A67,
- 0x522D, 0xB370, 0x402A, 0x522A, 0x3650, 0xB371, 0x522B, 0x342B,
- 0xB372, 0xB373, 0xB374, 0, 0xB375, 0, 0, 0,
- 0xB376, 0xB377, 0x372E, 0x522E, 0xB378, 0x522F, 0xB379, 0xB37A,
- 0x5230, 0x5231, 0x3C5B, 0, 0, 0, 0x387B, 0x4C5E,
-};
-const unsigned short utf8_to_euc_E58C[] = {
- 0xB37B, 0x4C68, 0x4677, 0xB37C, 0, 0x4A71, 0x5232, 0xF432,
- 0x5233, 0, 0xB37D, 0xB37E, 0xB421, 0x5235, 0, 0x5237,
- 0x5236, 0xB422, 0, 0xB423, 0, 0x5238, 0x323D, 0x4B4C,
- 0xB424, 0x3A7C, 0x5239, 0xB425, 0xB426, 0x4159, 0xB427, 0xB428,
- 0x3E22, 0x3629, 0, 0x523A, 0xF433, 0xB429, 0, 0xB42A,
- 0xB42B, 0xB42C, 0x485B, 0xB42D, 0xB42E, 0xB42F, 0, 0x523B,
- 0xB430, 0x523C, 0xB431, 0x523D, 0, 0xB432, 0, 0,
- 0x523E, 0x4924, 0x3668, 0x3065, 0xB433, 0xB434, 0xB435, 0x463F,
-};
-const unsigned short utf8_to_euc_E58D[] = {
- 0x523F, 0x3D3D, 0xB436, 0x4069, 0, 0x5241, 0x5240, 0x3E23,
- 0x3861, 0x5243, 0x483E, 0xB438, 0xB437, 0x5244, 0, 0,
- 0, 0x485C, 0x4234, 0x426E, 0x3628, 0, 0, 0x466E,
- 0x4331, 0xB439, 0x476E, 0xB43A, 0x4B4E, 0, 0x5246, 0,
- 0x406A, 0xB43B, 0, 0xB43C, 0, 0xB43D, 0x3735, 0,
- 0, 0x5247, 0, 0, 0xB43E, 0xB43F, 0x5248, 0x312C,
- 0x3075, 0x346D, 0xB440, 0x4228, 0x3551, 0x4D71, 0, 0x524B,
- 0x3237, 0xB441, 0, 0x524A, 0, 0, 0xB442, 0x362A,
-};
-const unsigned short utf8_to_euc_E58E[] = {
- 0, 0, 0x524C, 0xB443, 0x4C71, 0, 0, 0xB444,
- 0xB445, 0, 0, 0, 0, 0, 0xB446, 0,
- 0, 0, 0, 0xB447, 0xB448, 0, 0x524D, 0,
- 0x4E52, 0xB449, 0x387C, 0, 0, 0xB44A, 0, 0x3836,
- 0x524E, 0xB44B, 0, 0, 0xB44C, 0x5250, 0x524F, 0,
- 0x3F5F, 0x3139, 0xB44D, 0xB44E, 0, 0x315E, 0x5251, 0xB44F,
- 0x5252, 0, 0xB450, 0x3837, 0xB451, 0xB452, 0x5253, 0xB453,
- 0xB454, 0, 0xB455, 0x356E, 0, 0xB456, 0, 0,
-};
-const unsigned short utf8_to_euc_E58F[] = {
- 0xB457, 0, 0x3B32, 0x5254, 0, 0xB458, 0, 0,
- 0x4B74, 0x3A35, 0x355A, 0x4D27, 0x4150, 0x483F, 0x3C7D, 0xB459,
- 0, 0, 0xB45A, 0xB45B, 0x3D47, 0xB45C, 0x3C68, 0x3C75,
- 0, 0x3D76, 0xB45D, 0x4840, 0, 0xB45E, 0xB45F, 0x5257,
- 0xB460, 0x3143, 0x4151, 0x387D, 0x3845, 0x3667, 0xB461, 0xB462,
- 0x525B, 0x4321, 0x427E, 0x362B, 0x3E24, 0x525C, 0x525A, 0x3244,
- 0x4266, 0x3C38, 0x3B4B, 0x3126, 0, 0xB463, 0x3370, 0x3966,
- 0x3B4A, 0, 0x525D, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E590[] = {
- 0, 0x525E, 0xB464, 0x3549, 0x3346, 0, 0, 0,
- 0x3967, 0x3548, 0x445F, 0x3125, 0x4631, 0x4C3E, 0x3921, 0x4D79,
- 0x4547, 0x387E, 0, 0xB465, 0, 0, 0, 0,
- 0, 0, 0xB466, 0x372F, 0, 0x5267, 0, 0x3663,
- 0x4B4A, 0xB467, 0, 0, 0, 0, 0x485D, 0xB468,
- 0xB469, 0x5266, 0xB46A, 0x345E, 0x5261, 0x5262, 0x5264, 0xB46B,
- 0, 0xB46C, 0, 0, 0xB46D, 0xB46E, 0x5265, 0,
- 0x355B, 0x3F61, 0, 0x4A2D, 0x5263, 0x525F, 0x3863, 0,
-};
-const unsigned short utf8_to_euc_E591[] = {
- 0x5260, 0, 0x4F24, 0xB46F, 0xB470, 0, 0x4A72, 0xB471,
- 0x4468, 0x3862, 0x3970, 0, 0, 0xB472, 0x5268, 0xB473,
- 0, 0x465D, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xB474, 0x526C,
- 0, 0, 0xB475, 0, 0xB476, 0, 0xB477, 0xB478,
- 0x3C7E, 0xB479, 0x3C76, 0xB47A, 0, 0xB47B, 0xB47C, 0,
- 0x526F, 0x526D, 0, 0x4C23, 0xB47D, 0x526A, 0x5273, 0x526E,
- 0, 0, 0, 0x5271, 0x3846, 0x4C3F, 0, 0xB47E,
-};
-const unsigned short utf8_to_euc_E592[] = {
- 0x5272, 0xB521, 0, 0xB522, 0x5274, 0xB523, 0x5276, 0,
- 0xB524, 0xB525, 0xF435, 0x3A70, 0x4F42, 0xB526, 0x526B, 0x5269,
- 0x5275, 0xB527, 0x5270, 0, 0, 0xB528, 0xB529, 0,
- 0, 0, 0, 0, 0xB52A, 0, 0, 0xB52B,
- 0, 0xB52C, 0x5278, 0, 0x5323, 0x527A, 0xB52D, 0xB52E,
- 0x527E, 0xB52F, 0xB530, 0x5321, 0x527B, 0xB531, 0xB532, 0x533E,
- 0, 0xB533, 0x3A69, 0x3331, 0, 0, 0, 0xB534,
- 0x5279, 0xB535, 0xB536, 0xB537, 0x5325, 0x3076, 0x5324, 0xB538,
-};
-const unsigned short utf8_to_euc_E593[] = {
- 0x3025, 0x494A, 0x5322, 0, 0x527C, 0, 0xB539, 0x5277,
- 0x527D, 0x3A48, 0xB53A, 0, 0, 0xB53B, 0xB53C, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x5326, 0, 0, 0, 0, 0, 0, 0,
- 0xB53D, 0x3077, 0x532F, 0, 0, 0x5327, 0x5328, 0,
- 0x3E25, 0x4B69, 0xB53E, 0, 0xB53F, 0x532D, 0x532C, 0xB540,
- 0, 0, 0x452F, 0, 0, 0, 0xB541, 0,
- 0, 0, 0x532E, 0, 0xB542, 0x532B, 0xB543, 0xB544,
-};
-const unsigned short utf8_to_euc_E594[] = {
- 0xB545, 0xB546, 0, 0, 0x3134, 0xB547, 0x3A36, 0x3F30,
- 0xB548, 0xB549, 0, 0, 0xB54A, 0xB54B, 0xB54C, 0x5329,
- 0x4562, 0, 0, 0, 0x532A, 0xB54D, 0x3022, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xB54E, 0xB54F, 0, 0, 0x5334, 0x4D23,
- 0, 0x3E27, 0xB550, 0x533A, 0, 0xB551, 0xB552, 0,
- 0x5339, 0x5330, 0, 0xB553, 0xB554, 0xB555, 0x4243, 0,
-};
-const unsigned short utf8_to_euc_E595[] = {
- 0x5331, 0xB556, 0, 0, 0x426F, 0x5336, 0x3E26, 0xB557,
- 0, 0xB558, 0xB559, 0, 0x5333, 0xB55A, 0, 0x4C64,
- 0xB55B, 0xB55C, 0, 0x373C, 0, 0, 0x5337, 0x5338,
- 0xB55D, 0, 0xB55E, 0xB55F, 0x5335, 0x533B, 0xB560, 0,
- 0xB561, 0xB562, 0, 0x5332, 0xB563, 0, 0xB564, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x5341, 0x5346, 0, 0x5342, 0xB565,
-};
-const unsigned short utf8_to_euc_E596[] = {
- 0x533D, 0xB566, 0xB567, 0x5347, 0x4131, 0, 0xB568, 0x5349,
- 0xB569, 0x3922, 0x533F, 0x437D, 0, 0, 0xB56A, 0xB56B,
- 0, 0xB56C, 0xB56D, 0xB56E, 0xB56F, 0, 0, 0xB570,
- 0x5343, 0x533C, 0x342D, 0, 0x346E, 0x3365, 0x5344, 0x5340,
- 0, 0, 0, 0xB571, 0xB572, 0, 0, 0x3776,
- 0x534A, 0x5348, 0x4153, 0x354A, 0x362C, 0xB573, 0x5345, 0,
- 0x3674, 0, 0xB574, 0, 0, 0, 0x3144, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xB575,
-};
-const unsigned short utf8_to_euc_E597[] = {
- 0, 0xB576, 0, 0xB577, 0x534E, 0x534C, 0xB578, 0x5427,
- 0, 0xB579, 0, 0xB57A, 0xB57B, 0, 0xB57C, 0,
- 0, 0xB57D, 0xB57E, 0xB621, 0x5351, 0, 0, 0xB622,
- 0xB623, 0, 0x534B, 0xB624, 0x534F, 0, 0xB625, 0x534D,
- 0, 0, 0xB626, 0x3B4C, 0x5350, 0, 0, 0,
- 0, 0xB627, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xB628, 0x5353,
- 0, 0x5358, 0, 0, 0, 0x5356, 0x5355, 0xB629,
-};
-const unsigned short utf8_to_euc_E598[] = {
- 0, 0, 0, 0, 0, 0xB62A, 0x4332, 0,
- 0xB62B, 0x3245, 0xB62C, 0, 0, 0xB62D, 0xB62E, 0xB62F,
- 0xB630, 0xB631, 0xB632, 0, 0x5352, 0, 0x5354, 0x3E28,
- 0x3133, 0xB633, 0, 0x5357, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x325E, 0, 0, 0xB634, 0, 0, 0x5362,
- 0xB635, 0x3E7C, 0x535E, 0xB636, 0x535C, 0xB637, 0x535D, 0xB638,
- 0x535F, 0xB639, 0, 0xB63A, 0xB63B, 0xB63C, 0, 0xB63D,
-};
-const unsigned short utf8_to_euc_E599[] = {
- 0xB63E, 0xB63F, 0x313D, 0xB640, 0xB641, 0, 0xB642, 0,
- 0, 0xB643, 0, 0xB644, 0x4139, 0xB645, 0x5359, 0xB646,
- 0x535A, 0, 0, 0, 0xB647, 0, 0, 0,
- 0, 0, 0, 0x337A, 0, 0, 0xB648, 0,
- 0xB649, 0xB64A, 0xB64B, 0xB64C, 0x5361, 0, 0xB64D, 0,
- 0x346F, 0xB64E, 0x5364, 0x5360, 0x5363, 0xB64F, 0, 0xB650,
- 0, 0xB651, 0xB652, 0, 0x4A2E, 0xB653, 0, 0,
- 0x4655, 0, 0x4838, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E59A[] = {
- 0x5366, 0, 0, 0, 0xB654, 0xB655, 0x5365, 0x3345,
- 0xB656, 0, 0x5367, 0xB657, 0xB658, 0, 0, 0x536A,
- 0, 0, 0, 0, 0x5369, 0xB659, 0, 0,
- 0, 0xB65A, 0xB65B, 0, 0, 0xB65C, 0xB65D, 0xB65E,
- 0x5368, 0, 0x4739, 0, 0, 0x536B, 0xB65F, 0xB660,
- 0xB661, 0xB662, 0, 0xB663, 0xB664, 0xB665, 0x536C, 0,
- 0, 0xB666, 0, 0xB667, 0x536E, 0, 0x536D, 0xB668,
- 0, 0, 0, 0, 0x5370, 0, 0xB669, 0,
-};
-const unsigned short utf8_to_euc_E59B[] = {
- 0x5373, 0x5371, 0x536F, 0x5372, 0, 0xB66A, 0, 0,
- 0x5374, 0xB66B, 0xB66C, 0xB66D, 0xB670, 0xB671, 0x5375, 0xB66E,
- 0xB66F, 0x5376, 0, 0x5377, 0, 0, 0, 0x5378,
- 0x5145, 0xB672, 0x3C7C, 0x3B4D, 0xB673, 0xB674, 0x3273, 0xB675,
- 0x3078, 0xB676, 0, 0x4344, 0xB677, 0xB678, 0xB679, 0xB67A,
- 0xB67B, 0, 0, 0xB67D, 0, 0xB67E, 0x5379, 0,
- 0x3A24, 0xB67C, 0x304F, 0x3F5E, 0, 0, 0xB721, 0xB722,
- 0, 0x537A, 0x3847, 0, 0, 0x3971, 0, 0x537C,
-};
-const unsigned short utf8_to_euc_E59C[] = {
- 0x537B, 0xB723, 0xB724, 0x4A60, 0x537D, 0, 0, 0xB725,
- 0x5421, 0x537E, 0xB726, 0x5422, 0xB727, 0x5423, 0, 0x3777,
- 0, 0xB728, 0x3160, 0x5424, 0, 0xB729, 0x5426, 0,
- 0x5425, 0, 0xB72A, 0xB72B, 0x5428, 0xB72C, 0, 0x455A,
- 0xB72D, 0, 0xB72E, 0xB72F, 0xB730, 0xB731, 0x5429, 0x3035,
- 0x3A5F, 0xB732, 0xB733, 0, 0xB734, 0x373D, 0xB735, 0xB736,
- 0x434F, 0, 0, 0xB737, 0xB738, 0, 0, 0x542A,
- 0x542B, 0, 0, 0x542D, 0, 0xB739, 0xB73A, 0xB73B,
-};
-const unsigned short utf8_to_euc_E59D[] = {
- 0x542E, 0, 0x3A64, 0, 0, 0xB73C, 0xB73D, 0x3651,
- 0, 0, 0x4B37, 0, 0xB73E, 0xB73F, 0x542C, 0x542F,
- 0x3A41, 0x3923, 0xB740, 0, 0, 0, 0, 0,
- 0, 0xF436, 0, 0, 0, 0, 0, 0,
- 0, 0x5433, 0xB741, 0, 0x3A25, 0xB742, 0x4333, 0xB743,
- 0xB744, 0x5430, 0x445A, 0xB745, 0, 0xB746, 0xB747, 0xB748,
- 0xB749, 0xB74A, 0, 0xB74B, 0xB74C, 0xB74D, 0, 0xB74E,
- 0, 0xB74F, 0xB750, 0xB751, 0xB752, 0, 0xB753, 0x5434,
-};
-const unsigned short utf8_to_euc_E59E[] = {
- 0, 0xB754, 0x3F62, 0xB755, 0, 0, 0, 0,
- 0x5432, 0x5435, 0, 0x373F, 0xB756, 0, 0, 0,
- 0, 0, 0, 0x5436, 0xB757, 0xB760, 0, 0xB758,
- 0, 0xB759, 0xB75A, 0, 0xB75B, 0xB75C, 0xB75D, 0xB75E,
- 0x5437, 0xB75F, 0x3924, 0x3340, 0x5439, 0, 0, 0xB761,
- 0xB762, 0xB763, 0x543A, 0, 0xB764, 0, 0, 0,
- 0x543B, 0, 0, 0x5438, 0, 0, 0, 0,
- 0xB765, 0, 0, 0, 0, 0xB766, 0, 0,
-};
-const unsigned short utf8_to_euc_E59F[] = {
- 0x5431, 0, 0, 0x543C, 0, 0, 0x543D, 0xB767,
- 0xB768, 0, 0, 0x4B64, 0xB769, 0, 0x3E6B, 0xB76A,
- 0, 0, 0x543F, 0x5440, 0x543E, 0xB76B, 0x5442, 0,
- 0, 0, 0, 0, 0x4738, 0xB76C, 0xB76D, 0x3068,
- 0x4956, 0xB77E, 0, 0x5443, 0xB76E, 0, 0xB76F, 0xB770,
- 0, 0xB771, 0, 0, 0, 0xB772, 0, 0,
- 0xB773, 0, 0, 0, 0x3E7D, 0xB774, 0xB775, 0x3C39,
- 0xB776, 0x475D, 0x3470, 0, 0x3A6B, 0xB777, 0xB778, 0xB779,
-};
-const unsigned short utf8_to_euc_E5A0[] = {
- 0x4B59, 0, 0x4632, 0xB77A, 0xB77B, 0x3778, 0x424F, 0,
- 0xB77C, 0xB77D, 0x5441, 0x5444, 0xB821, 0xB822, 0, 0,
- 0, 0, 0, 0, 0, 0x4244, 0, 0,
- 0, 0x5445, 0, 0xB823, 0, 0x5446, 0xB824, 0xB825,
- 0xB826, 0x5448, 0, 0, 0x4469, 0, 0xB827, 0xB828,
- 0, 0, 0x342E, 0, 0, 0xB829, 0, 0x7421,
- 0x3161, 0x4A73, 0xB82A, 0, 0x3E6C, 0x4548, 0, 0,
- 0, 0xB82B, 0x3A66, 0, 0, 0x544E, 0, 0xB82C,
-};
-const unsigned short utf8_to_euc_E5A1[] = {
- 0x4A3D, 0x4E5D, 0, 0, 0, 0, 0, 0,
- 0, 0xB82D, 0x3274, 0x544A, 0xB82E, 0xB82F, 0, 0xB830,
- 0xB831, 0x413A, 0x544D, 0, 0x4563, 0xB832, 0, 0x4549,
- 0x4564, 0x4839, 0x444D, 0, 0, 0, 0x3A49, 0xB833,
- 0, 0xB834, 0x5449, 0, 0xB835, 0, 0, 0xB836,
- 0xB837, 0x3176, 0, 0x4536, 0, 0, 0, 0,
- 0x544B, 0, 0x5447, 0, 0, 0x3F50, 0, 0,
- 0xB838, 0x544F, 0, 0, 0xB839, 0, 0x3D4E, 0xB83A,
-};
-const unsigned short utf8_to_euc_E5A2[] = {
- 0xB83B, 0xB83C, 0, 0x362D, 0, 0x5450, 0, 0xB83D,
- 0xB83E, 0xB83F, 0xB840, 0, 0xB841, 0xB842, 0, 0xB843,
- 0xB844, 0, 0, 0x4A68, 0xB845, 0, 0xB846, 0x417D,
- 0, 0, 0, 0, 0x4446, 0xB847, 0xF439, 0x5452,
- 0xB848, 0xB849, 0xB84A, 0, 0, 0, 0xB84B, 0,
- 0x4B4F, 0xB84C, 0, 0x5453, 0, 0, 0x5458, 0,
- 0, 0xB84D, 0xB84E, 0x4A2F, 0, 0, 0, 0,
- 0x5457, 0x5451, 0x5454, 0x5456, 0xB850, 0, 0x3A26, 0,
-};
-const unsigned short utf8_to_euc_E5A3[] = {
- 0, 0x4A49, 0xB851, 0, 0xB84F, 0x5459, 0, 0x4345,
- 0xB852, 0, 0x3275, 0, 0x3E6D, 0xB853, 0xB854, 0,
- 0xB855, 0x545B, 0xB856, 0x545A, 0xB857, 0x3968, 0xB858, 0x545C,
- 0x545E, 0x545D, 0xB859, 0, 0x5460, 0xB85A, 0x5455, 0x5462,
- 0, 0xB85B, 0xB85C, 0, 0x5461, 0x545F, 0, 0,
- 0, 0xB85D, 0, 0x3B4E, 0x3F51, 0, 0x4154, 0x5463,
- 0x403C, 0x306D, 0x4764, 0xB85E, 0, 0, 0, 0x445B,
- 0, 0x5465, 0x5464, 0x5466, 0x5467, 0x5468, 0, 0,
-};
-const unsigned short utf8_to_euc_E5A4[] = {
- 0, 0, 0x5469, 0, 0, 0xB85F, 0xB860, 0,
- 0, 0x4A51, 0x546A, 0xB861, 0xB862, 0, 0, 0x3246,
- 0x546B, 0, 0xB863, 0xB864, 0xB865, 0x4D3C, 0x3330, 0,
- 0x5249, 0x3D48, 0x423F, 0x546C, 0x4C6B, 0xB867, 0, 0,
- 0, 0xB868, 0x4C34, 0xB869, 0xB86A, 0x546E, 0, 0x4267,
- 0xB86B, 0x4537, 0x4240, 0x4957, 0x546F, 0x5470, 0x317B, 0xB86C,
- 0xB86D, 0x3C3A, 0x5471, 0xB86E, 0, 0xB86F, 0xB870, 0x3050,
- 0x5472, 0, 0, 0, 0, 0, 0x5473, 0xB871,
-};
-const unsigned short utf8_to_euc_E5A5[] = {
- 0, 0, 0, 0xB872, 0x3162, 0, 0xB873, 0x3471,
- 0x4660, 0x4A74, 0, 0, 0, 0, 0x5477, 0x4155,
- 0x5476, 0x3740, 0xB874, 0xB875, 0x4B5B, 0x5475, 0, 0x4565,
- 0x5479, 0xB876, 0x5478, 0xB877, 0, 0xB878, 0xB879, 0xB87A,
- 0x547B, 0xB87B, 0x547A, 0xB87C, 0, 0x317C, 0, 0x547C,
- 0x3E29, 0x547E, 0x4325, 0xB87D, 0x547D, 0xB87E, 0x4A33, 0xB921,
- 0, 0, 0xB922, 0x3D77, 0x455B, 0xB923, 0xB924, 0,
- 0x5521, 0xB925, 0, 0xB926, 0xB927, 0x3925, 0, 0,
-};
-const unsigned short utf8_to_euc_E5A6[] = {
- 0, 0x5522, 0x4721, 0x485E, 0x4C51, 0, 0, 0,
- 0, 0, 0x4725, 0xB928, 0xB929, 0x552B, 0xB92A, 0,
- 0, 0, 0xB92B, 0x3538, 0, 0xB92C, 0x4D45, 0xB92D,
- 0, 0x4C2F, 0, 0x562C, 0, 0x5523, 0, 0xB92E,
- 0, 0, 0, 0x5526, 0xB92F, 0x4245, 0, 0xB930,
- 0x4B38, 0, 0, 0, 0x454A, 0xB931, 0xB932, 0xB933,
- 0xB934, 0, 0x5527, 0xB935, 0, 0, 0, 0xB936,
- 0, 0x4B65, 0xB937, 0x3A4A, 0xB938, 0, 0x3E2A, 0,
-};
-const unsigned short utf8_to_euc_E5A7[] = {
- 0, 0xB939, 0, 0xB93A, 0xB93B, 0, 0x5528, 0,
- 0xB93C, 0x3B50, 0xB93D, 0x3B4F, 0, 0xB93E, 0, 0,
- 0x3039, 0x3848, 0xB93F, 0x402B, 0x3051, 0, 0, 0,
- 0, 0x552C, 0x552D, 0, 0x552A, 0xB940, 0xB941, 0xB942,
- 0, 0, 0, 0xB943, 0xB944, 0x3138, 0x342F, 0xB945,
- 0x5529, 0, 0x4C45, 0x4931, 0, 0, 0xB946, 0xB947,
- 0, 0xB948, 0xB949, 0, 0xB94A, 0, 0x3028, 0xB94B,
- 0, 0, 0, 0x3079, 0, 0, 0, 0x3B51,
-};
-const unsigned short utf8_to_euc_E5A8[] = {
- 0xB94C, 0x3052, 0, 0x3023, 0xB94D, 0, 0, 0,
- 0, 0x5532, 0, 0, 0xB94E, 0xB94F, 0xB950, 0,
- 0, 0x5530, 0xB951, 0xB952, 0, 0, 0, 0,
- 0x4C3C, 0, 0x5533, 0, 0x5531, 0, 0xB953, 0x552F,
- 0x3F31, 0, 0, 0xB954, 0xB955, 0x552E, 0, 0xB956,
- 0xB957, 0x4A5A, 0xB958, 0, 0, 0xB959, 0, 0x3864,
- 0xB95A, 0, 0, 0, 0, 0x5537, 0x5538, 0,
- 0, 0, 0, 0, 0x3E2B, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E5A9[] = {
- 0x5534, 0x4F2C, 0, 0, 0xB95B, 0xB95C, 0x474C, 0xB95D,
- 0xB95E, 0x5536, 0, 0, 0xB95F, 0, 0, 0,
- 0xB960, 0, 0, 0, 0, 0xB961, 0, 0,
- 0, 0, 0x3A27, 0, 0, 0, 0xB962, 0,
- 0, 0, 0x5539, 0xB963, 0, 0xB964, 0x4958, 0xB965,
- 0, 0, 0x553A, 0, 0x5535, 0xB966, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xB967,
- 0, 0, 0xB968, 0xB969, 0, 0, 0xB96A, 0x4C3B,
-};
-const unsigned short utf8_to_euc_E5AA[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xB96B, 0, 0, 0, 0,
- 0xB96C, 0, 0x475E, 0xB96D, 0, 0, 0xB96E, 0,
- 0, 0xB96F, 0x553B, 0x4932, 0xB970, 0, 0xB971, 0xB972,
- 0xB973, 0, 0xB974, 0, 0, 0, 0, 0xB975,
- 0, 0, 0, 0, 0xB976, 0, 0, 0,
- 0, 0xB977, 0xB978, 0xB979, 0, 0xB97A, 0, 0,
- 0xB97B, 0, 0xB97C, 0xB97D, 0x553C, 0x5540, 0x553D, 0xB97E,
-};
-const unsigned short utf8_to_euc_E5AB[] = {
- 0, 0x3247, 0x553F, 0, 0xBA21, 0, 0xBA22, 0,
- 0xBA23, 0x3C3B, 0, 0x553E, 0x3779, 0, 0, 0xBA24,
- 0x554C, 0, 0, 0, 0, 0, 0x5545, 0x5542,
- 0, 0, 0xBA25, 0, 0xBA26, 0, 0, 0,
- 0xBA27, 0x4364, 0, 0x5541, 0, 0xBA28, 0x5543, 0,
- 0, 0x5544, 0xBA29, 0, 0, 0, 0xBA2A, 0,
- 0, 0, 0, 0, 0, 0xBA2B, 0xBA2C, 0,
- 0, 0, 0x5546, 0x5547, 0, 0xBA2D, 0, 0,
-};
-const unsigned short utf8_to_euc_E5AC[] = {
- 0xBA2E, 0xBA2F, 0, 0, 0, 0, 0, 0,
- 0xBA30, 0x3472, 0, 0x5549, 0x5548, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x554A, 0xBA31,
- 0, 0xBA33, 0, 0xBA34, 0, 0xBA35, 0, 0,
- 0, 0xBA36, 0x3E6E, 0, 0, 0xBA37, 0, 0,
- 0, 0, 0x554D, 0, 0x445C, 0xBA38, 0, 0,
- 0x3145, 0, 0x554B, 0, 0xBA32, 0, 0x554E, 0,
- 0xBA39, 0, 0, 0, 0, 0, 0x554F, 0,
-};
-const unsigned short utf8_to_euc_E5AD[] = {
- 0x5552, 0xBA3A, 0, 0x5550, 0, 0x5551, 0, 0,
- 0, 0, 0, 0xBA3B, 0xBA3C, 0, 0, 0,
- 0x3B52, 0x5553, 0xBA3D, 0, 0x3926, 0x5554, 0xBA3E, 0x3B7A,
- 0x4238, 0, 0x5555, 0x5556, 0x3B5A, 0x3927, 0xBA3F, 0x4C52,
- 0, 0, 0, 0x3528, 0x3849, 0x5557, 0x3358, 0,
- 0xBA40, 0x5558, 0, 0x4239, 0, 0, 0xBA41, 0xBA42,
- 0x5559, 0x5623, 0, 0x555A, 0, 0x555B, 0, 0,
- 0x555C, 0, 0x555E, 0, 0xBA43, 0xBA44, 0xBA45, 0xBA46,
-};
-const unsigned short utf8_to_euc_E5AE[] = {
- 0x555F, 0xBA47, 0, 0x5560, 0xBA48, 0x4270, 0xBA49, 0x3127,
- 0x3C69, 0x3042, 0xBA4A, 0x4157, 0x3430, 0x3C35, 0xBA4B, 0x3928,
- 0xBA4C, 0xBA4D, 0, 0xBA4E, 0xBA4F, 0x4566, 0xBA50, 0x3D21,
- 0x3431, 0x4368, 0x446A, 0x3038, 0x3539, 0x4A75, 0, 0x3C42,
- 0, 0, 0x3552, 0x406B, 0x3C3C, 0x4D28, 0x5561, 0,
- 0xBA51, 0xBA52, 0, 0, 0xBA53, 0xBA54, 0x355C, 0xBA55,
- 0x3A4B, 0xBA56, 0xBA57, 0x3332, 0x3163, 0x3E2C, 0x3248, 0xBA58,
- 0x5562, 0x4D46, 0xBA59, 0, 0xBA5A, 0, 0, 0x3D49,
-};
-const unsigned short utf8_to_euc_E5AF[] = {
- 0xBA5B, 0xBA5C, 0x3C64, 0x5563, 0x3473, 0x4652, 0x4C29, 0x5564,
- 0, 0x5565, 0, 0, 0x4959, 0xBA5D, 0, 0xBA5E,
- 0x5567, 0, 0x3428, 0x3677, 0x5566, 0, 0xBA5F, 0xBA60,
- 0xBA61, 0xBA62, 0xBA63, 0x3432, 0, 0x3F32, 0x556B, 0x3B21,
- 0xBA64, 0x3249, 0x556A, 0, 0x5568, 0x556C, 0x5569, 0x472B,
- 0x5C4D, 0x3F33, 0, 0x556D, 0xF43A, 0, 0x4E40, 0xBA65,
- 0x556E, 0xBA66, 0, 0x5570, 0xBA67, 0x437E, 0x556F, 0,
- 0x4023, 0, 0x3B7B, 0, 0, 0xBA68, 0x4250, 0x3C77,
-};
-const unsigned short utf8_to_euc_E5B0[] = {
- 0, 0x4975, 0x406C, 0, 0x3C4D, 0x5571, 0x3E2D, 0x5572,
- 0x5573, 0x3053, 0x423A, 0x3F52, 0xBA69, 0x5574, 0x4633, 0x3E2E,
- 0, 0x3E2F, 0, 0x5575, 0, 0, 0x406D, 0xBA6A,
- 0, 0, 0x3E30, 0, 0, 0, 0xBA6B, 0xBA6C,
- 0x5576, 0, 0x5577, 0xBA6D, 0x4C60, 0, 0xBA6E, 0,
- 0x5578, 0xBA6F, 0, 0xBA70, 0xBA71, 0x3646, 0xBA72, 0,
- 0xBA73, 0x3D22, 0xBA74, 0, 0, 0xBA75, 0xBA76, 0,
- 0x5579, 0x557A, 0x3C5C, 0x3F2C, 0x4674, 0x3F54, 0x4878, 0x4722,
-};
-const unsigned short utf8_to_euc_E5B1[] = {
- 0x3649, 0x557B, 0, 0, 0, 0x356F, 0x557C, 0,
- 0x367E, 0, 0x464F, 0x3230, 0, 0x3B53, 0x557D, 0x5622,
- 0x5621, 0x367D, 0, 0x557E, 0, 0x4538, 0, 0,
- 0, 0xBA77, 0xBA78, 0, 0xBA79, 0, 0x4230, 0,
- 0x454B, 0x3C48, 0xBA7A, 0xBA7B, 0x4158, 0x4D7A, 0, 0xBA7C,
- 0xBA7D, 0xBA7E, 0, 0, 0x5624, 0xBB21, 0x5625, 0x4656,
- 0xBB22, 0x3B33, 0, 0, 0xBB23, 0xBB24, 0x5627, 0,
- 0, 0x5628, 0xBB25, 0xBB26, 0xBB27, 0xBB28, 0, 0,
-};
-const unsigned short utf8_to_euc_E5B2[] = {
- 0, 0, 0, 0, 0, 0, 0, 0xBB29,
- 0xBB2A, 0, 0xBB2B, 0, 0x5629, 0, 0, 0xBB2C,
- 0x3474, 0x562A, 0xBB2D, 0, 0x562B, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xBB2E, 0, 0xBB2F,
- 0xBB30, 0x322C, 0xBB31, 0xBB32, 0, 0, 0xBB33, 0,
- 0x413B, 0x3464, 0xBB34, 0x562D, 0x4C28, 0, 0, 0,
- 0, 0x4252, 0xBB35, 0x3359, 0xBB36, 0xBB37, 0x562F, 0x5631,
- 0x345F, 0, 0xBB38, 0x562E, 0x5630, 0, 0x5633, 0,
-};
-const unsigned short utf8_to_euc_E5B3[] = {
- 0, 0, 0, 0, 0, 0x5632, 0, 0x5634,
- 0, 0xBB39, 0, 0xBB3A, 0, 0, 0, 0,
- 0, 0, 0xBB3B, 0, 0, 0, 0, 0xBB3D,
- 0, 0x5635, 0, 0, 0, 0xBB3C, 0, 0,
- 0x463D, 0x362E, 0, 0, 0, 0, 0, 0,
- 0x3265, 0x5636, 0x563B, 0, 0, 0x5639, 0xBB3E, 0x4A77,
- 0x4A76, 0xBB3F, 0xBB40, 0, 0xBB41, 0xF43B, 0x4567, 0,
- 0, 0, 0x5638, 0x3D54, 0, 0x5637, 0, 0,
-};
-const unsigned short utf8_to_euc_E5B4[] = {
- 0, 0xBB42, 0, 0, 0, 0, 0xBB43, 0x3F72,
- 0, 0, 0, 0x563C, 0, 0xBB44, 0x3A6A, 0,
- 0, 0x5642, 0xBB45, 0, 0x5643, 0x563D, 0x3333, 0x563E,
- 0x5647, 0x5646, 0x5645, 0x5641, 0, 0, 0, 0x5640,
- 0, 0, 0x5644, 0xBB47, 0xBB48, 0, 0xBB49, 0xBB4A,
- 0, 0x4A78, 0, 0xBB46, 0, 0, 0, 0,
- 0, 0xBB4B, 0, 0, 0xBB4C, 0, 0, 0,
- 0, 0xBB4D, 0, 0, 0, 0xBB4E, 0, 0xBB4F,
-};
-const unsigned short utf8_to_euc_E5B5[] = {
- 0, 0, 0xBB50, 0xBB51, 0, 0, 0xBB52, 0,
- 0xBB53, 0, 0xBB57, 0x564B, 0x5648, 0, 0x564A, 0,
- 0x4D72, 0xBB55, 0x5649, 0xF43C, 0, 0xBB54, 0, 0,
- 0, 0xBB56, 0, 0, 0x563F, 0, 0, 0xBB58,
- 0xBB59, 0xBB5A, 0xBB5B, 0, 0xBB5C, 0, 0, 0,
- 0, 0x3F73, 0xBB5D, 0, 0x564C, 0xBB5E, 0, 0x3A37,
- 0xBB5F, 0, 0, 0x564D, 0, 0, 0x564E, 0,
- 0, 0xBB60, 0xBB61, 0, 0, 0, 0xBB62, 0xBB63,
-};
-const unsigned short utf8_to_euc_E5B6[] = {
- 0, 0xBB64, 0x5651, 0xBB65, 0x5650, 0, 0, 0x564F,
- 0xBB66, 0, 0xBB67, 0x4568, 0x563A, 0, 0, 0,
- 0x5657, 0, 0xBB68, 0xBB69, 0xBB6A, 0xBB6B, 0, 0,
- 0, 0xBB6C, 0, 0xBB6D, 0, 0x5653, 0, 0xBB6E,
- 0xBB6F, 0, 0x5652, 0, 0, 0, 0, 0xBB70,
- 0, 0, 0, 0xBB71, 0x5654, 0, 0x5655, 0,
- 0xBB72, 0, 0xE674, 0, 0xBB73, 0, 0, 0x5658,
- 0xBB74, 0xBB75, 0x4E66, 0, 0x5659, 0x5656, 0, 0,
-};
-const unsigned short utf8_to_euc_E5B7[] = {
- 0, 0, 0, 0xBB76, 0, 0, 0, 0xBB77,
- 0, 0x565A, 0, 0xBB78, 0x3460, 0x565B, 0xBB7A, 0,
- 0xBB79, 0, 0x565D, 0x565C, 0, 0, 0x565E, 0,
- 0xBB7B, 0xBB7C, 0, 0x565F, 0, 0x406E, 0x3D23, 0,
- 0xBB7D, 0x3D64, 0, 0x4163, 0xBB7E, 0x3929, 0x3A38, 0x392A,
- 0x3570, 0xBC21, 0, 0x5660, 0, 0, 0x3A39, 0,
- 0, 0x384A, 0x5661, 0x4C26, 0x4743, 0x5662, 0, 0x392B,
- 0xBC22, 0xBC23, 0, 0x342C, 0, 0x4327, 0x3652, 0,
-};
-const unsigned short utf8_to_euc_E5B8[] = {
- 0xBC24, 0, 0x3B54, 0x495B, 0, 0, 0x4841, 0xBC25,
- 0, 0, 0, 0x5663, 0x3475, 0xBC26, 0, 0,
- 0, 0x5666, 0xBC27, 0, 0xBC28, 0xBC29, 0x4421, 0,
- 0xBC2A, 0x5665, 0x5664, 0x5667, 0, 0x446B, 0, 0xBC2B,
- 0xBC2C, 0, 0, 0, 0, 0x3F63, 0, 0,
- 0xBC2E, 0, 0, 0x3B55, 0, 0x404A, 0xBC2D, 0x4253,
- 0x3522, 0, 0xBC2F, 0x4422, 0, 0xBC30, 0x5668, 0x5669,
- 0x3E6F, 0, 0, 0, 0, 0x4B39, 0xBC31, 0,
-};
-const unsigned short utf8_to_euc_E5B9[] = {
- 0x566C, 0, 0, 0x566B, 0x566A, 0x497D, 0, 0x5673,
- 0, 0xBC34, 0, 0xBC32, 0x4B5A, 0, 0x566D, 0,
- 0xBC33, 0xBC35, 0, 0, 0x566F, 0x4B6B, 0xBC36, 0x566E,
- 0xBC37, 0, 0, 0xBC38, 0xBC39, 0, 0xBC3A, 0x5670,
- 0, 0x4828, 0x5671, 0x4A3E, 0x5672, 0, 0, 0,
- 0xBC3B, 0, 0xBC3C, 0xBC3D, 0xBC3E, 0xBC3F, 0xBC40, 0,
- 0xBC41, 0, 0x3433, 0x4A3F, 0x472F, 0x5674, 0x5675, 0,
- 0x392C, 0x3434, 0x5676, 0x3838, 0x4D44, 0x4D29, 0x3476, 0x5678,
-};
-const unsigned short utf8_to_euc_E5BA[] = {
- 0xBC42, 0x4423, 0, 0x392D, 0x3E31, 0, 0, 0x485F,
- 0, 0, 0x3E32, 0xBC43, 0, 0, 0xBC44, 0x3D78,
- 0, 0, 0, 0, 0, 0x446C, 0x4A79, 0x4539,
- 0, 0, 0x392E, 0, 0x495C, 0, 0, 0,
- 0x5679, 0, 0xBC45, 0, 0xBC46, 0xBC47, 0x4559, 0x3A42,
- 0xBC48, 0, 0xBC49, 0x384B, 0xBC4A, 0x446D, 0, 0,
- 0, 0xBC4B, 0, 0xBC4C, 0, 0x3043, 0x3D6E, 0x392F,
- 0x4D47, 0, 0, 0, 0, 0xBC4D, 0xBC4E, 0xBC4F,
-};
-const unsigned short utf8_to_euc_E5BB[] = {
- 0, 0x567A, 0x567B, 0x4751, 0, 0, 0xBC50, 0,
- 0x567C, 0x4E77, 0x4F2D, 0xBC52, 0xBC51, 0, 0xBC53, 0x567E,
- 0x567D, 0xBC54, 0xBC55, 0x3347, 0xBC56, 0xBC57, 0x5721, 0,
- 0, 0, 0x5724, 0x5725, 0xBC58, 0x5723, 0xBC59, 0x4940,
- 0x3E33, 0x5727, 0x5726, 0x5722, 0, 0xBC5A, 0, 0,
- 0x5728, 0x5729, 0, 0xBC5B, 0x572A, 0, 0, 0,
- 0x572D, 0x572B, 0, 0x572C, 0x572E, 0, 0x3164, 0x446E,
- 0x572F, 0, 0x377A, 0x3276, 0x4736, 0, 0x5730, 0x467B,
-};
-const unsigned short utf8_to_euc_E5BC[] = {
- 0, 0x4A5B, 0xBC5C, 0x5731, 0x4F2E, 0, 0xBC5D, 0xBC5E,
- 0xBC5F, 0x5732, 0x4A40, 0x5735, 0x5021, 0x5031, 0xBC60, 0x3C30,
- 0x4675, 0x5736, 0, 0x355D, 0x4424, 0x307A, 0x5737, 0x4A26,
- 0x3930, 0xBC61, 0, 0x4350, 0xBC62, 0xBC63, 0, 0x446F,
- 0, 0xBC64, 0xBC65, 0xBC66, 0xBC67, 0x4C6F, 0x3839, 0x384C,
- 0xBC68, 0x5738, 0, 0xBC69, 0xBC6A, 0x5739, 0xBC6B, 0x573F,
- 0xBC6C, 0x3C65, 0, 0, 0xBC6D, 0x4425, 0xBC6E, 0x362F,
- 0x573A, 0, 0, 0xBC6F, 0x492B, 0xBC70, 0x4346, 0xBC71,
-};
-const unsigned short utf8_to_euc_E5BD[] = {
- 0xBC72, 0x573B, 0, 0, 0xBC73, 0xBC74, 0, 0xBC75,
- 0x573C, 0, 0x3630, 0, 0x573D, 0xBC76, 0x573E, 0,
- 0xBC77, 0x5740, 0, 0x4576, 0xBC78, 0, 0x5741, 0x5742,
- 0xBC79, 0x5743, 0, 0xBC7A, 0x5734, 0x5733, 0, 0,
- 0xBC7B, 0x5744, 0x3741, 0xBC7C, 0xBC7D, 0, 0x4927, 0xBC7E,
- 0, 0x3A4C, 0x4937, 0x4426, 0x494B, 0x5745, 0, 0xBD21,
- 0x3E34, 0x3146, 0xBD22, 0x5746, 0xBD23, 0xBD24, 0, 0x5747,
- 0xBD25, 0x4C72, 0xBD26, 0, 0x4860, 0xBD27, 0xBD28, 0x574A,
-};
-const unsigned short utf8_to_euc_E5BE[] = {
- 0x317D, 0x402C, 0x5749, 0x5748, 0x3742, 0x4254, 0, 0x574E,
- 0x574C, 0xBD29, 0x574B, 0x4E27, 0x3865, 0xBD2A, 0, 0xBD2B,
- 0x3D79, 0x574D, 0x454C, 0x3D3E, 0, 0, 0xBD2C, 0x4640,
- 0x5751, 0x5750, 0, 0, 0xBD2D, 0xBD2E, 0x574F, 0,
- 0x5752, 0x3866, 0xBD2F, 0, 0xBD32, 0, 0, 0xBD30,
- 0x5753, 0x497C, 0x3D5B, 0xBD31, 0xBD33, 0x5754, 0x4879, 0xBD34,
- 0xBD35, 0xBD36, 0, 0x4641, 0x4427, 0, 0, 0xF43E,
- 0xBD37, 0x4530, 0, 0, 0x5755, 0x352B, 0, 0,
-};
-const unsigned short utf8_to_euc_E5BF[] = {
- 0, 0, 0, 0x3F34, 0xBD38, 0x492C, 0, 0xBD39,
- 0xBD3A, 0xBD3B, 0, 0xBD3C, 0x3477, 0x4726, 0, 0,
- 0xBD3D, 0xBD3E, 0xBD3F, 0xBD40, 0xBD41, 0, 0x5756, 0x3B56,
- 0x4B3A, 0x4B3B, 0, 0, 0x317E, 0x575B, 0xBD42, 0,
- 0x4369, 0xBD43, 0xBD44, 0, 0x5758, 0, 0, 0,
- 0xBD45, 0xBD46, 0xBD47, 0x3277, 0xBD48, 0xBD49, 0xBD4A, 0xBD4B,
- 0x582D, 0x575A, 0xBD4C, 0xBD4D, 0, 0x4730, 0xBD4E, 0,
- 0x5759, 0, 0xBD4F, 0x5757, 0xBD50, 0x397A, 0, 0x575D,
-};
-const unsigned short utf8_to_euc_E680[] = {
- 0, 0, 0, 0, 0, 0, 0, 0xBD51,
- 0, 0, 0xBD52, 0, 0, 0xBD53, 0x5763, 0x5769,
- 0x5761, 0, 0x455C, 0xBD54, 0xBD55, 0x5766, 0x495D, 0xBD56,
- 0xBD57, 0x5760, 0xBD58, 0x5765, 0x4E67, 0x3B57, 0, 0xBD59,
- 0x4255, 0x575E, 0, 0, 0xBD5A, 0x355E, 0x5768, 0x402D,
- 0x3165, 0x5762, 0x3278, 0x5767, 0, 0xBD5B, 0, 0x3631,
- 0, 0x5764, 0, 0xBD5C, 0, 0xBD5D, 0, 0,
- 0, 0, 0x576A, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E681[] = {
- 0xBD5E, 0x576C, 0x5776, 0x5774, 0, 0, 0x5771, 0xBD5F,
- 0xBD60, 0xBD61, 0x5770, 0x4E78, 0xBD62, 0x5772, 0, 0,
- 0x3632, 0xBD63, 0x3931, 0, 0xBD64, 0x3D7A, 0xBD65, 0xBD66,
- 0, 0x5779, 0x576B, 0, 0, 0xBD67, 0, 0x576F,
- 0x575F, 0xBD68, 0x327A, 0x5773, 0x5775, 0x4351, 0, 0xBD69,
- 0x3A28, 0x3238, 0x576D, 0x5778, 0x5777, 0x3633, 0, 0x4229,
- 0x3366, 0xBD6A, 0, 0, 0, 0x3743, 0, 0x576E,
- 0, 0, 0, 0, 0, 0, 0xBD6B, 0xBD6C,
-};
-const unsigned short utf8_to_euc_E682[] = {
- 0, 0x577A, 0xBD6D, 0x577D, 0x5821, 0xF43F, 0xBD6E, 0,
- 0xBD6F, 0x3C3D, 0xBD70, 0x5827, 0x4470, 0x577B, 0xBD71, 0,
- 0, 0xBD72, 0x5825, 0xBD73, 0x3279, 0xBD74, 0x5823, 0x5824,
- 0xBD75, 0, 0x577E, 0x5822, 0, 0xBD76, 0xBD77, 0x3867,
- 0x4D2A, 0, 0xBD78, 0x3435, 0xBD79, 0xBD7A, 0x3159, 0x5826,
- 0xBD7B, 0x473A, 0x302D, 0, 0, 0, 0, 0,
- 0xBD7C, 0xBD7D, 0x4861, 0x575C, 0x582C, 0x5830, 0x4C65, 0xBD7E,
- 0x5829, 0, 0, 0xBE21, 0x4569, 0x582E, 0xBE22, 0,
-};
-const unsigned short utf8_to_euc_E683[] = {
- 0, 0, 0xBE23, 0, 0xBE24, 0x3E70, 0x582F, 0x4657,
- 0xBE25, 0xBE26, 0xBE27, 0xBE28, 0, 0, 0xBE29, 0xBE2A,
- 0, 0x4F47, 0, 0x582B, 0xBE2B, 0xBE2C, 0, 0,
- 0x5831, 0xBE2D, 0x397B, 0xBE2E, 0x404B, 0xBE2F, 0xBE30, 0x3054,
- 0x582A, 0x5828, 0xBE31, 0x415A, 0, 0xBE32, 0, 0x577C,
- 0x3B34, 0, 0, 0, 0, 0, 0, 0,
- 0x4246, 0x583D, 0xBE33, 0x415B, 0x5838, 0xBE34, 0x5835, 0x5836,
- 0xBE35, 0x3C66, 0x5839, 0x583C, 0xBE36, 0xBE37, 0, 0,
-};
-const unsigned short utf8_to_euc_E684[] = {
- 0x5837, 0x3D25, 0xBE38, 0x583A, 0, 0, 0x5834, 0xBE39,
- 0x4C7C, 0x4C7B, 0xBE3A, 0, 0xBE3B, 0x583E, 0x583F, 0x3055,
- 0xBE3C, 0xBE3D, 0xBE3E, 0xBE3F, 0xBE40, 0x5833, 0xBE41, 0xBE42,
- 0, 0xBE43, 0x3672, 0x3026, 0xBE44, 0, 0xBE45, 0x3436,
- 0xF440, 0x583B, 0xBE46, 0, 0, 0, 0, 0x5843,
- 0x5842, 0, 0xBE47, 0xBE48, 0x5847, 0, 0, 0,
- 0xBE49, 0xBE4A, 0, 0, 0x5848, 0xBE4B, 0xBE4C, 0xBE4D,
- 0, 0xBE4E, 0, 0, 0x5846, 0x5849, 0x5841, 0x5845,
-};
-const unsigned short utf8_to_euc_E685[] = {
- 0, 0xBE4F, 0x584A, 0, 0x584B, 0xBE50, 0xBE51, 0x5840,
- 0x3B7C, 0xBE52, 0x5844, 0x4256, 0x3932, 0x5832, 0x3F35, 0,
- 0, 0, 0, 0x5858, 0, 0x4A69, 0, 0,
- 0x584E, 0x584F, 0x5850, 0, 0, 0x5857, 0xBE53, 0x5856,
- 0xBE54, 0, 0x4B7D, 0x3437, 0, 0x5854, 0, 0x3745,
- 0x3334, 0, 0, 0x5851, 0xBE55, 0, 0x4E38, 0x5853,
- 0x3056, 0x5855, 0xBE56, 0x584C, 0x5852, 0x5859, 0x3744, 0x584D,
- 0xBE57, 0, 0, 0xBE58, 0xBE59, 0, 0x4D5D, 0xBE5A,
-};
-const unsigned short utf8_to_euc_E686[] = {
- 0xBE5B, 0xBE5C, 0x4D2B, 0xBE5D, 0xBE5E, 0, 0, 0x585C,
- 0, 0, 0x5860, 0xBE5F, 0, 0xBE60, 0x417E, 0,
- 0x4E79, 0x5861, 0xBE61, 0xBE62, 0x585E, 0, 0x585B, 0xBE63,
- 0xBE64, 0x585A, 0x585F, 0, 0xBE65, 0xBE66, 0, 0xBE67,
- 0xBE68, 0, 0, 0, 0x4A30, 0xBE69, 0, 0x4634,
- 0xBE6A, 0x3746, 0xBE6B, 0x5862, 0x585D, 0xBE6C, 0x5863, 0,
- 0, 0, 0x377B, 0, 0, 0, 0x3231, 0,
- 0xBE6D, 0xBE6E, 0x586B, 0, 0xBE6F, 0, 0x3438, 0,
-};
-const unsigned short utf8_to_euc_E687[] = {
- 0xBE70, 0xBE71, 0xBE72, 0x5869, 0, 0, 0x586A, 0x3A29,
- 0x5868, 0x5866, 0x5865, 0x586C, 0x5864, 0x586E, 0xBE73, 0xBE74,
- 0x327B, 0, 0, 0, 0, 0xBE75, 0, 0,
- 0, 0, 0, 0, 0xBE76, 0xBE77, 0xBE78, 0xBE79,
- 0, 0xBE7A, 0xBE7B, 0x5870, 0, 0xBE7E, 0x586F, 0xBE7C,
- 0, 0xBE7D, 0, 0, 0xBF21, 0xBF22, 0, 0xBF23,
- 0, 0, 0x4428, 0, 0x5873, 0, 0x5871, 0x5867,
- 0x377C, 0, 0x5872, 0, 0x5876, 0x5875, 0x5877, 0x5874,
-};
-const unsigned short utf8_to_euc_E688[] = {
- 0x5878, 0xBF24, 0, 0xBF25, 0xBF26, 0, 0, 0xBF27,
- 0x5879, 0x587A, 0x4A6A, 0, 0x587C, 0x587B, 0x3D3F, 0,
- 0x402E, 0x3266, 0x327C, 0xBF28, 0x587D, 0xBF29, 0x303F, 0,
- 0, 0, 0x404C, 0x587E, 0xBF2A, 0x6C43, 0x5921, 0x3761,
- 0xBF2B, 0x5922, 0xBF2C, 0xBF2D, 0, 0, 0x406F, 0xBF2E,
- 0, 0xBF2F, 0x5923, 0xBF30, 0, 0, 0x5924, 0x353A,
- 0x5925, 0, 0x5926, 0x5927, 0x4257, 0, 0, 0,
- 0x384D, 0xBF31, 0, 0x4C61, 0, 0xBF32, 0, 0x4B3C,
-};
-const unsigned short utf8_to_euc_E689[] = {
- 0x3D6A, 0x5928, 0xBF33, 0xBF34, 0xBF35, 0, 0xBF36, 0x4070,
- 0x6E3D, 0x4862, 0, 0x3C6A, 0xBF37, 0x3A4D, 0x5929, 0,
- 0xBF38, 0xBF39, 0xBF3A, 0x4247, 0xBF3B, 0x4A27, 0xBF3C, 0,
- 0x4271, 0, 0xBF3D, 0x592C, 0xBF3E, 0, 0x592A, 0,
- 0x592D, 0, 0, 0x592B, 0xBF3F, 0, 0, 0,
- 0x592E, 0, 0, 0, 0, 0xBF40, 0x4A31, 0xBF41,
- 0, 0x3037, 0, 0xBF42, 0, 0, 0x495E, 0,
- 0, 0x4863, 0xBF43, 0, 0x592F, 0xBF44, 0x5932, 0x3E35,
-};
-const unsigned short utf8_to_euc_E68A[] = {
- 0x353B, 0, 0x5930, 0x5937, 0x3E36, 0, 0, 0,
- 0, 0x5931, 0x4744, 0, 0, 0xBF45, 0xBF46, 0xBF47,
- 0xBF48, 0x4D5E, 0x5933, 0x5934, 0x5938, 0x456A, 0x5935, 0x3933,
- 0x405E, 0, 0, 0x5946, 0x4834, 0, 0x4272, 0,
- 0, 0, 0, 0, 0, 0, 0xBF49, 0,
- 0xBF4A, 0, 0, 0x4864, 0x5A2D, 0, 0, 0,
- 0, 0x4A7A, 0, 0xBF4B, 0, 0x4471, 0xBF4C, 0xBF4D,
- 0, 0x4B75, 0xBF4E, 0x593B, 0x3221, 0x436A, 0xBF4F, 0xBF50,
-};
-const unsigned short utf8_to_euc_E68B[] = {
- 0, 0, 0x5944, 0, 0xBF51, 0x4334, 0x593E, 0x5945,
- 0x5940, 0x5947, 0x5943, 0, 0x5942, 0x476F, 0xBF52, 0x593C,
- 0x327D, 0x593A, 0x3571, 0x4273, 0x5936, 0xBF53, 0xBF54, 0x5939,
- 0x3934, 0x405B, 0xBF55, 0x3E37, 0x5941, 0x4752, 0, 0,
- 0x3572, 0x3348, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xBF56, 0, 0x3367, 0x3F21, 0x5949, 0x594E,
- 0, 0x594A, 0xBF57, 0x377D, 0xBF58, 0x594F, 0x3B22, 0x3969,
- 0, 0, 0, 0, 0xBF59, 0xBF5A, 0x3D26, 0x593D,
-};
-const unsigned short utf8_to_euc_E68C[] = {
- 0, 0x3B7D, 0x594C, 0xBF5B, 0xBF5C, 0, 0, 0x3B58,
- 0x594D, 0x3044, 0xBF5D, 0xBF5E, 0x5948, 0xBF5F, 0, 0,
- 0xBF60, 0x4429, 0, 0xBF61, 0, 0, 0xBF62, 0,
- 0xBF63, 0x3573, 0, 0, 0, 0, 0, 0x3634,
- 0, 0, 0, 0, 0, 0, 0, 0x594B,
- 0x3027, 0xBF64, 0xBF65, 0x3A43, 0, 0xBF66, 0, 0x3F36,
- 0, 0, 0, 0, 0, 0xBF67, 0xBF68, 0,
- 0, 0xBF69, 0x4472, 0, 0xBF6A, 0x4854, 0x5951, 0x415E,
-};
-const unsigned short utf8_to_euc_E68D[] = {
- 0, 0xBF6B, 0xBF6C, 0xBF6D, 0xBF6E, 0, 0xBF6F, 0,
- 0, 0x422A, 0xBF70, 0xBF71, 0x3B2B, 0x5952, 0xBF72, 0x5954,
- 0x5950, 0, 0xBF73, 0xBF74, 0xBF75, 0x4A61, 0, 0x443D,
- 0xBF76, 0, 0, 0xBF77, 0x415C, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xBF78, 0xBF79, 0x4A7B,
- 0x3C4E, 0x5960, 0, 0x595F, 0xBF7A, 0xBF7B, 0x3F78, 0,
- 0, 0xBF7C, 0x377E, 0, 0xBF7D, 0xBF7E, 0x5959, 0x3E39,
- 0xC021, 0, 0x4668, 0x4731, 0xC022, 0xC023, 0, 0xC024,
-};
-const unsigned short utf8_to_euc_E68E[] = {
- 0x5957, 0, 0xC025, 0x415D, 0xC026, 0, 0, 0xC027,
- 0x3C78, 0x595C, 0xC028, 0, 0x3E38, 0, 0x5956, 0x595B,
- 0xC029, 0, 0x4753, 0, 0xC02A, 0xC02B, 0x5955, 0,
- 0x3721, 0xC02C, 0xC02D, 0x335D, 0, 0, 0xC02E, 0x595D,
- 0x4E2B, 0x3A4E, 0x4335, 0x595A, 0xC02F, 0x405C, 0xC030, 0x3935,
- 0x3F64, 0x3166, 0x413C, 0x5958, 0x3545, 0xC031, 0xC032, 0xC033,
- 0, 0, 0x3747, 0, 0x444F, 0x595E, 0, 0,
- 0, 0, 0, 0x415F, 0, 0xC034, 0x5961, 0,
-};
-const unsigned short utf8_to_euc_E68F[] = {
- 0x5963, 0xC035, 0, 0x4237, 0x5969, 0xC036, 0x5964, 0,
- 0xC037, 0x5966, 0, 0, 0, 0, 0xC038, 0x4941,
- 0x4473, 0xC039, 0x5967, 0xC03A, 0xC03B, 0xC03C, 0x4D2C, 0,
- 0, 0, 0x4D48, 0x3439, 0xC03D, 0, 0, 0,
- 0xC03E, 0x302E, 0, 0x5965, 0, 0xC03F, 0, 0,
- 0, 0x5962, 0xC040, 0, 0xC041, 0, 0x3478, 0,
- 0, 0, 0xC042, 0xC043, 0x3167, 0xC044, 0x5968, 0,
- 0xC045, 0xC046, 0x4D49, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E690[] = {
- 0, 0, 0, 0, 0, 0, 0x596C, 0,
- 0, 0xC047, 0xC048, 0, 0, 0x423B, 0, 0x5973,
- 0xC049, 0, 0xC04A, 0x596D, 0xC04B, 0, 0x596A, 0x5971,
- 0xC04C, 0, 0, 0, 0x5953, 0, 0xC04D, 0,
- 0xC04E, 0, 0xC04F, 0, 0xC050, 0xC051, 0x596E, 0,
- 0x5972, 0xC052, 0xC053, 0, 0x4842, 0x456B, 0, 0xC054,
- 0xC055, 0, 0, 0, 0x596B, 0xC056, 0x596F, 0,
- 0, 0, 0x3748, 0, 0, 0xC057, 0x3A71, 0xC058,
-};
-const unsigned short utf8_to_euc_E691[] = {
- 0, 0, 0x405D, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xC059, 0, 0, 0x5977, 0xC05A,
- 0, 0xC05B, 0xC05C, 0xC05D, 0xC05E, 0, 0, 0,
- 0x4526, 0, 0xC05F, 0xC060, 0xC061, 0xC062, 0, 0xC063,
- 0xC064, 0xC065, 0, 0xC066, 0, 0, 0, 0x5974,
- 0, 0x4B60, 0, 0, 0, 0xC067, 0, 0x5975,
- 0, 0, 0, 0xC068, 0xC069, 0, 0x5976, 0,
- 0x4C4E, 0, 0x4022, 0xC06A, 0, 0xC06B, 0, 0,
-};
-const unsigned short utf8_to_euc_E692[] = {
- 0, 0, 0, 0x3762, 0, 0xC06C, 0, 0xC06D,
- 0x597D, 0, 0, 0, 0, 0, 0, 0xC06E,
- 0xC06F, 0xC070, 0x3B35, 0x597A, 0, 0x5979, 0, 0,
- 0xC071, 0xC072, 0x4732, 0xC073, 0, 0xC074, 0x4635, 0xC075,
- 0, 0xC076, 0, 0xC077, 0x4531, 0x597B, 0xC078, 0,
- 0xC079, 0x597C, 0, 0x496F, 0xC07A, 0x4745, 0x3B23, 0,
- 0x4071, 0, 0x4B50, 0xC07B, 0, 0, 0, 0,
- 0, 0x3349, 0, 0x5A25, 0x597E, 0xC07C, 0xC07D, 0xC07E,
-};
-const unsigned short utf8_to_euc_E693[] = {
- 0, 0x4D4A, 0x5A27, 0, 0xC121, 0x5A23, 0, 0x5A24,
- 0, 0xC122, 0xC123, 0xC124, 0xC125, 0x4160, 0xC126, 0,
- 0xC127, 0xC128, 0x5A22, 0, 0x593F, 0xC129, 0, 0xC12A,
- 0x5A26, 0, 0x5A21, 0, 0, 0, 0, 0,
- 0x5A2B, 0x5A2C, 0x4527, 0x5A2E, 0xC12B, 0xC12C, 0x3B24, 0x5A29,
- 0, 0xC12D, 0xC12E, 0, 0x353C, 0xC12F, 0, 0x5A2F,
- 0xC130, 0x5A28, 0x5A33, 0, 0x5A32, 0xC131, 0x5A31, 0xC132,
- 0, 0, 0x5A34, 0xC133, 0, 0x5A36, 0x3E71, 0xC134,
-};
-const unsigned short utf8_to_euc_E694[] = {
- 0x5A35, 0xC135, 0, 0, 0xC136, 0x5A39, 0, 0,
- 0xC137, 0xC138, 0xC139, 0, 0, 0, 0, 0xC13A,
- 0, 0, 0, 0xC13B, 0xC13C, 0, 0xC13D, 0,
- 0x5A37, 0xC13E, 0, 0xC13F, 0x5A38, 0x5970, 0xC140, 0xC141,
- 0, 0, 0xC142, 0x5A3B, 0x5A3A, 0, 0xC143, 0,
- 0, 0xC144, 0x5978, 0x5A3C, 0x5A30, 0, 0xC145, 0x3B59,
- 0, 0xC146, 0, 0, 0x5A3D, 0x5A3E, 0x5A40, 0x5A3F,
- 0x5A41, 0x327E, 0xC147, 0x3936, 0xC148, 0xC149, 0x4A7C, 0x402F,
-};
-const unsigned short utf8_to_euc_E695[] = {
- 0, 0, 0, 0xC14A, 0, 0x384E, 0, 0xC14B,
- 0x5A43, 0xC14C, 0, 0, 0, 0x5A46, 0xF441, 0x4952,
- 0xC14D, 0x355F, 0xC14E, 0, 0xC14F, 0x5A45, 0x5A44, 0x4754,
- 0x5A47, 0x3635, 0, 0, 0, 0x5A49, 0x5A48, 0xC150,
- 0xC151, 0, 0x343A, 0x3B36, 0, 0, 0x4658, 0xC152,
- 0, 0, 0, 0xC153, 0x3749, 0, 0, 0,
- 0x3F74, 0, 0x5A4A, 0, 0x4030, 0x4528, 0, 0x495F,
- 0x5A4B, 0, 0xC154, 0, 0, 0xC155, 0, 0,
-};
-const unsigned short utf8_to_euc_E696[] = {
- 0, 0xC156, 0x5A4C, 0x5A4D, 0, 0xC157, 0, 0x4A38,
- 0x555D, 0x4046, 0xC158, 0, 0x494C, 0, 0x3A58, 0,
- 0x4865, 0x4843, 0xC159, 0, 0, 0xC15A, 0, 0x454D,
- 0xC15B, 0x4E41, 0, 0x5A4F, 0x3C50, 0xC15C, 0, 0x5A50,
- 0xC15D, 0x3036, 0, 0xC15E, 0x3654, 0x404D, 0xC15F, 0x4960,
- 0, 0, 0, 0x5A51, 0x3B42, 0x4347, 0xC160, 0x3B5B,
- 0x3F37, 0, 0xC161, 0xC162, 0xC163, 0, 0, 0x5A52,
- 0, 0x4A7D, 0, 0, 0x3177, 0x3B5C, 0, 0xC164,
-};
-const unsigned short utf8_to_euc_E697[] = {
- 0, 0x5A55, 0xC165, 0x5A53, 0x5A56, 0x4E39, 0x5A54, 0,
- 0xC166, 0xC167, 0, 0x407B, 0x5A57, 0, 0xC168, 0x4232,
- 0xC169, 0, 0x5A58, 0, 0xC16A, 0, 0xC16B, 0x347A,
- 0xC16C, 0x5A5A, 0, 0x5A59, 0, 0, 0, 0xC16D,
- 0x5A5B, 0x5A5C, 0x347B, 0, 0, 0x467C, 0x4336, 0x356C,
- 0x3B5D, 0x4161, 0, 0, 0x3D5C, 0x3030, 0, 0,
- 0xC16E, 0x5A5D, 0xC16F, 0, 0xC170, 0xC171, 0, 0,
- 0, 0xC172, 0x3222, 0x5A61, 0, 0, 0xC173, 0xC174,
-};
-const unsigned short utf8_to_euc_E698[] = {
- 0xC175, 0, 0x3937, 0x5A60, 0xC176, 0, 0x3A2B, 0x3E3A,
- 0xC177, 0xC178, 0x5A5F, 0, 0x3E3B, 0xC179, 0x4C40, 0x3A2A,
- 0, 0xC17A, 0xC17B, 0x3057, 0x404E, 0xC17C, 0xC17D, 0,
- 0, 0, 0, 0, 0x5A66, 0xC17E, 0xC221, 0x4031,
- 0x3147, 0xC222, 0xC223, 0xC224, 0xC225, 0x3D55, 0xC226, 0x4B66,
- 0x3A72, 0xC227, 0xC228, 0xC229, 0xC22A, 0x3E3C, 0xC22B, 0x4027,
- 0xC22C, 0xC22D, 0, 0xC22E, 0x5A65, 0x5A63, 0x5A64, 0xC230,
- 0, 0xC22F, 0, 0xF442, 0x436B, 0, 0, 0x5B26,
-};
-const unsigned short utf8_to_euc_E699[] = {
- 0xC231, 0x5A6A, 0x3B7E, 0x3938, 0x5A68, 0xC232, 0xC233, 0,
- 0, 0x5A69, 0xC234, 0x3F38, 0xC235, 0, 0xC237, 0x5A67,
- 0, 0xC236, 0x3B2F, 0, 0, 0, 0, 0xC238,
- 0xC239, 0xC23A, 0, 0xC23B, 0xC23C, 0x5A6C, 0x5A6B, 0x5A70,
- 0xC23D, 0xC23E, 0x5A71, 0, 0x5A6D, 0xF443, 0x3322, 0x5A6E,
- 0x5A6F, 0x4855, 0xC240, 0xC241, 0xC242, 0, 0x4961, 0x374A,
- 0x5A72, 0, 0, 0xC244, 0x4032, 0xC245, 0x3E3D, 0xC247,
- 0xC248, 0xC249, 0x4352, 0xC24A, 0xC24C, 0, 0xC243, 0xC246,
-};
-const unsigned short utf8_to_euc_E69A[] = {
- 0xC24B, 0x3647, 0, 0x5A73, 0x5A77, 0, 0, 0x324B,
- 0x5A74, 0x5A76, 0, 0xC24D, 0xC24E, 0xC24F, 0x5A75, 0,
- 0xC250, 0x3D6B, 0xC251, 0, 0, 0, 0x4348, 0x3045,
- 0x5A78, 0xC252, 0xC253, 0xC254, 0xC255, 0x5A79, 0, 0xC256,
- 0xC257, 0, 0x442A, 0, 0xC258, 0, 0x4E71, 0,
- 0, 0, 0, 0x3B43, 0, 0xC259, 0x4A6B, 0,
- 0, 0xC25A, 0xC25B, 0, 0x4B3D, 0xC25C, 0, 0,
- 0x5B22, 0x5A7B, 0, 0xC25D, 0x5A7E, 0, 0x5A7D, 0xC25E,
-};
-const unsigned short utf8_to_euc_E69B[] = {
- 0xC25F, 0x5A7A, 0xC260, 0xC261, 0x5B21, 0, 0, 0x465E,
- 0xC262, 0x5A7C, 0, 0, 0xC263, 0, 0xC264, 0xC265,
- 0, 0, 0, 0, 0xC266, 0, 0x5B23, 0,
- 0, 0x3D6C, 0x5B24, 0xC267, 0x4D4B, 0x4778, 0, 0xC268,
- 0x5B25, 0, 0, 0, 0, 0, 0x5B27, 0,
- 0xC269, 0x5B28, 0, 0xC26A, 0xC26B, 0, 0xC26C, 0,
- 0x5B29, 0, 0x364A, 0x3148, 0x3939, 0x5B2A, 0, 0x5B2B,
- 0x3D71, 0x4162, 0xC26D, 0xC23F, 0x5258, 0x413E, 0x413D, 0x4258,
-};
-const unsigned short utf8_to_euc_E69C[] = {
- 0x3A47, 0, 0, 0x5072, 0, 0xC26E, 0, 0xC26F,
- 0x376E, 0x4D2D, 0, 0x4A7E, 0, 0x497E, 0xC270, 0x5B2C,
- 0, 0, 0, 0xC271, 0x3A73, 0x443F, 0x5B2D, 0x4F2F,
- 0, 0xC272, 0, 0x4B3E, 0xC273, 0x442B, 0x5B2E, 0x347C,
- 0xC274, 0, 0xC275, 0, 0, 0, 0x5B2F, 0x5B30,
- 0x4C5A, 0, 0x4C24, 0x4B76, 0x4B5C, 0x3B25, 0x5B32, 0,
- 0, 0x3C6B, 0, 0xC276, 0x4B51, 0, 0x5B34, 0x5B37,
- 0x5B36, 0, 0x3479, 0, 0, 0x3560, 0xC277, 0x5B33,
-};
-const unsigned short utf8_to_euc_E69D[] = {
- 0, 0x5B35, 0, 0, 0, 0xC278, 0x5B38, 0xC279,
- 0xC27A, 0x3F79, 0, 0, 0xC27B, 0, 0x4D7B, 0x3049,
- 0x3A60, 0x423C, 0, 0x3C5D, 0xC27C, 0xC27D, 0x3E73, 0,
- 0, 0x5B3B, 0, 0, 0x454E, 0xC27E, 0x5B39, 0x422B,
- 0x5B3A, 0x3E72, 0x4C5D, 0x5B3C, 0x5B3D, 0x4D68, 0xC321, 0,
- 0, 0, 0x5B42, 0, 0xC322, 0x393A, 0xC323, 0x4755,
- 0x5B3F, 0x456C, 0x5A5E, 0x5A62, 0xC324, 0x354F, 0xC325, 0x4747,
- 0, 0, 0, 0xC326, 0x5B41, 0, 0x3E3E, 0x4844,
-};
-const unsigned short utf8_to_euc_E69E[] = {
- 0, 0xC327, 0, 0, 0xC328, 0x5B47, 0, 0x487A,
- 0, 0x5B3E, 0, 0x5B44, 0x5B43, 0, 0xC329, 0xC32A,
- 0x404F, 0xC32B, 0, 0xC32C, 0, 0x4B6D, 0xC32D, 0x4E53,
- 0xC32E, 0xC32F, 0x4B67, 0xC330, 0x324C, 0x3B5E, 0, 0,
- 0x4F48, 0x5B46, 0x3F75, 0, 0, 0, 0x5B45, 0,
- 0, 0x5B40, 0, 0, 0, 0, 0, 0x384F,
- 0xC331, 0xC332, 0xC333, 0x5B4C, 0x5B4A, 0xC334, 0x324D, 0x5B48,
- 0x5B4E, 0x5B54, 0, 0xC335, 0xC336, 0xC337, 0, 0,
-};
-const unsigned short utf8_to_euc_E69F[] = {
- 0xC339, 0x4248, 0xC33A, 0xC33B, 0x4A41, 0xC33C, 0x5B56, 0,
- 0xC33D, 0xC33E, 0x4922, 0, 0, 0, 0x5B55, 0x4770,
- 0x4B3F, 0x343B, 0xC33F, 0x4077, 0x3D40, 0, 0, 0xC340,
- 0x4453, 0xC341, 0x4D2E, 0, 0xC342, 0x5B51, 0x5B50, 0,
- 0, 0xC343, 0x5B52, 0, 0x5B4F, 0, 0xC344, 0x5B57,
- 0, 0x5B4D, 0, 0, 0x5B4B, 0, 0x5B53, 0x5B49,
- 0xC345, 0x436C, 0xC346, 0x4C78, 0x3C46, 0x3A74, 0xC347, 0xC348,
- 0, 0xC338, 0, 0x3A3A, 0, 0, 0x4B6F, 0x3341,
-};
-const unsigned short utf8_to_euc_E6A0[] = {
- 0, 0xF446, 0x444E, 0x464A, 0x3149, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x4072, 0xC34A, 0, 0x4034, 0x372A,
- 0, 0xC34B, 0, 0, 0, 0xC34C, 0x5B59, 0xC34D,
- 0, 0x393B, 0x337C, 0, 0, 0, 0, 0xC34F,
- 0xC34E, 0x5B5B, 0x3374, 0x5B61, 0xC350, 0xC351, 0, 0xC352,
- 0xC353, 0xC354, 0x5B5E, 0xC355, 0x4073, 0, 0, 0,
- 0x334B, 0x3A2C, 0, 0xC356, 0x334A, 0x3A4F, 0, 0xC357,
-};
-const unsigned short utf8_to_euc_E6A1[] = {
- 0x5B5C, 0x3765, 0x374B, 0x456D, 0xC358, 0xC359, 0x5B5A, 0,
- 0x3046, 0, 0xC35A, 0, 0xC35B, 0x5B5D, 0x5B5F, 0,
- 0x364D, 0x372C, 0xC349, 0x343C, 0x354B, 0xC35C, 0, 0xC35D,
- 0xC35E, 0x5B62, 0, 0xC35F, 0x3A79, 0x4B71, 0, 0x3B37,
- 0, 0, 0, 0x5B63, 0, 0, 0, 0x4930,
- 0, 0, 0, 0xC360, 0, 0, 0xC361, 0xC362,
- 0xC363, 0xC364, 0xC365, 0, 0x5B6F, 0xC366, 0x3233, 0x5B64,
- 0, 0xC367, 0xC368, 0xC369, 0xC36A, 0, 0x5B75, 0x5B65,
-};
-const unsigned short utf8_to_euc_E6A2[] = {
- 0, 0x4E42, 0xC36B, 0x5B6C, 0xC36C, 0x475F, 0xC36D, 0,
- 0xC36E, 0, 0, 0, 0, 0x5B74, 0, 0x5B67,
- 0, 0, 0, 0x3034, 0x5B69, 0, 0xC36F, 0x393C,
- 0xC370, 0, 0xC371, 0x5B6B, 0xC372, 0x5B6A, 0, 0x5B66,
- 0x5B71, 0xC373, 0x3E3F, 0xC374, 0, 0xC375, 0x546D, 0x3868,
- 0x4D7C, 0xC376, 0xC377, 0, 0, 0x5B68, 0xC378, 0x4474,
- 0x3323, 0x3A2D, 0xC379, 0x5B60, 0, 0x5B70, 0x3361, 0,
- 0, 0x5B6E, 0x5B72, 0xC37A, 0x456E, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E6A3[] = {
- 0, 0, 0, 0, 0x347E, 0xC37B, 0x5C32, 0,
- 0xC37C, 0x4C49, 0x5B77, 0x347D, 0xC37D, 0x5B7E, 0, 0xC37E,
- 0xC421, 0xC422, 0x4B40, 0xC423, 0x5C21, 0x5C23, 0xC424, 0x5C27,
- 0x5B79, 0xC425, 0x432A, 0, 0xC426, 0xC427, 0, 0x456F,
- 0x5C2B, 0x5B7C, 0, 0x5C28, 0, 0xC428, 0, 0x5C22,
- 0xC429, 0, 0xC42A, 0xC42B, 0xC42C, 0xC42D, 0x3F39, 0x5C2C,
- 0xC42E, 0xC42F, 0x4033, 0, 0, 0xC430, 0xC431, 0,
- 0, 0x5C2A, 0x343D, 0xC432, 0xC433, 0xC434, 0, 0,
-};
-const unsigned short utf8_to_euc_E6A4[] = {
- 0x4F50, 0x5B76, 0, 0, 0x5C26, 0x3058, 0xC435, 0,
- 0x5B78, 0xC436, 0xC437, 0x4C3A, 0x5B7D, 0x3F22, 0x4447, 0x5B73,
- 0xC438, 0xC439, 0x5C25, 0xC43A, 0, 0, 0xC43B, 0xC43C,
- 0, 0x3F7A, 0x5C2F, 0x3371, 0x3821, 0, 0, 0,
- 0, 0x5C31, 0x5B7A, 0x5C30, 0, 0x5C29, 0x5B7B, 0,
- 0x5C2D, 0, 0x5C2E, 0, 0, 0, 0, 0,
- 0x5C3F, 0xC43D, 0, 0xC43E, 0x464E, 0xC43F, 0x5C24, 0,
- 0xC440, 0x5C3B, 0, 0xC441, 0, 0x5C3D, 0, 0x4458,
-};
-const unsigned short utf8_to_euc_E6A5[] = {
- 0, 0, 0xC442, 0, 0, 0xC443, 0, 0,
- 0, 0xC444, 0x4D4C, 0, 0, 0, 0xC445, 0,
- 0, 0, 0, 0x4976, 0x5C38, 0x424A, 0, 0xC446,
- 0, 0x5C3E, 0x413F, 0xC447, 0x5C35, 0x5C42, 0x5C41, 0,
- 0x466F, 0x5C40, 0x466A, 0xC448, 0xC449, 0xC44A, 0xC44B, 0,
- 0xC44C, 0xC44D, 0x5C44, 0x5C37, 0xC44E, 0x3648, 0x5C3A, 0x3D5D,
- 0xC44F, 0xC450, 0xC451, 0x4760, 0x5C3C, 0x364B, 0, 0x5C34,
- 0x5C36, 0x5C33, 0xC452, 0xC453, 0x4F30, 0x335A, 0x5C39, 0xC454,
-};
-const unsigned short utf8_to_euc_E6A6[] = {
- 0xC455, 0x5C43, 0x3335, 0, 0, 0, 0, 0,
- 0, 0, 0x3A67, 0, 0, 0xC456, 0x315D, 0,
- 0, 0x5C54, 0xC457, 0, 0x4F31, 0x5C57, 0xC458, 0,
- 0xC459, 0, 0, 0x3F3A, 0x5C56, 0, 0, 0,
- 0x5C55, 0xC45A, 0, 0, 0, 0xC45B, 0xC45C, 0x5C52,
- 0xC45D, 0, 0, 0xC45E, 0, 0xC45F, 0x5C46, 0xC460,
- 0, 0x5C63, 0x5C45, 0, 0x5C58, 0, 0, 0xC461,
- 0xC462, 0, 0xC463, 0x5C50, 0xC464, 0, 0x5C4B, 0x5C48,
-};
-const unsigned short utf8_to_euc_E6A7[] = {
- 0, 0x5C49, 0, 0x5C51, 0, 0xC465, 0, 0x7422,
- 0xC466, 0, 0x5C4E, 0x393D, 0x4448, 0x4164, 0x5C4C, 0,
- 0x5C47, 0xC467, 0, 0x5C4A, 0, 0, 0xC468, 0xC469,
- 0x4D4D, 0x4B6A, 0, 0, 0, 0x5C4F, 0x5C59, 0,
- 0, 0, 0xC46A, 0, 0, 0xC46B, 0, 0x5C61,
- 0x5C5A, 0, 0, 0x5C67, 0, 0x5C65, 0xC46C, 0xC46D,
- 0, 0xC46E, 0x5C60, 0xC46F, 0, 0xC470, 0, 0,
- 0, 0x5C5F, 0, 0x4450, 0, 0x4165, 0xC471, 0x5C5D,
-};
-const unsigned short utf8_to_euc_E6A8[] = {
- 0xC472, 0xC473, 0x5C5B, 0xC474, 0, 0x5C62, 0, 0,
- 0, 0, 0x5C68, 0x4875, 0x5C6E, 0, 0, 0xC475,
- 0, 0xC476, 0x5C69, 0x5C6C, 0x5C66, 0xC477, 0, 0x4374,
- 0, 0x4938, 0xC478, 0x5C5C, 0, 0xC479, 0x5C64, 0x3E40,
- 0xC47A, 0x4C4F, 0x5C78, 0x5C6B, 0xC47B, 0, 0, 0,
- 0xC47C, 0x3822, 0x3223, 0x335F, 0, 0, 0x5C53, 0,
- 0xC47D, 0, 0xC47E, 0, 0xC521, 0x3E41, 0x5C70, 0xC522,
- 0x5C77, 0x3C79, 0x3372, 0xC523, 0, 0x432E, 0xC524, 0xC525,
-};
-const unsigned short utf8_to_euc_E6A9[] = {
- 0, 0, 0, 0, 0x5C6D, 0xC526, 0xC527, 0x5C72,
- 0x5C76, 0xC528, 0xC529, 0x3636, 0, 0, 0xC52A, 0,
- 0xC52B, 0xC52C, 0xC52D, 0, 0, 0xC52E, 0xC52F, 0,
- 0x354C, 0x5C74, 0, 0xC530, 0, 0, 0, 0x3521,
- 0, 0x464B, 0x5C73, 0, 0xC531, 0, 0x5C75, 0xC532,
- 0, 0, 0xC533, 0xF449, 0, 0, 0, 0,
- 0, 0xC534, 0x5C6F, 0xC535, 0, 0, 0, 0,
- 0x5C71, 0, 0, 0, 0, 0, 0xC536, 0x3360,
-};
-const unsigned short utf8_to_euc_E6AA[] = {
- 0x4349, 0xC537, 0, 0xC538, 0x5C7C, 0, 0xC539, 0xC53A,
- 0, 0xC53B, 0, 0xC53C, 0, 0x5C7A, 0x3869, 0,
- 0x5C79, 0xC53D, 0, 0, 0, 0, 0, 0x5D21,
- 0, 0, 0, 0xC53E, 0x5B58, 0xC53F, 0xC540, 0xC541,
- 0x5C7B, 0, 0x5C7D, 0x5C7E, 0, 0xC542, 0, 0,
- 0, 0, 0x5D2C, 0xC543, 0x5D28, 0, 0x5B6D, 0xC544,
- 0xC545, 0xC546, 0, 0x5D27, 0xC547, 0, 0, 0,
- 0x5D26, 0, 0, 0x5D23, 0, 0xC548, 0xC549, 0xC54A,
-};
-const unsigned short utf8_to_euc_E6AB[] = {
- 0, 0x5C6A, 0x5D25, 0x5D24, 0, 0, 0xC54B, 0,
- 0xC54D, 0xC54C, 0, 0, 0xC54E, 0, 0, 0,
- 0xC54F, 0x5D2A, 0, 0x4F26, 0xC550, 0xC551, 0xC552, 0,
- 0, 0, 0x5D2D, 0x367B, 0xC553, 0xC554, 0x5D29, 0x5D2B,
- 0, 0, 0xF44A, 0, 0xC555, 0, 0, 0xC556,
- 0x4827, 0, 0x5D2E, 0, 0xC557, 0, 0, 0,
- 0xC558, 0xC559, 0xC55A, 0, 0, 0, 0, 0,
- 0, 0, 0x5D32, 0x5D2F, 0xC55B, 0xC55C, 0, 0,
-};
-const unsigned short utf8_to_euc_E6AC[] = {
- 0, 0, 0xC55D, 0xC55E, 0x4D73, 0x5D30, 0xC55F, 0xC560,
- 0, 0xC561, 0x5C5E, 0, 0, 0, 0, 0xC562,
- 0xC563, 0xC564, 0x5D33, 0, 0, 0, 0x5D34, 0xC565,
- 0, 0, 0, 0xC566, 0, 0x3135, 0xC567, 0x5D36,
- 0x3767, 0x3C21, 0, 0x3655, 0xC568, 0, 0, 0x3224,
- 0xC569, 0, 0, 0xC56A, 0xC56B, 0, 0, 0xC56C,
- 0, 0, 0x4D5F, 0, 0, 0xC56D, 0xC56E, 0x5D38,
- 0x5D37, 0x5D3A, 0x353D, 0xC56F, 0, 0x3656, 0x343E, 0xC570,
-};
-const unsigned short utf8_to_euc_E6AD[] = {
- 0, 0, 0, 0x5D3D, 0, 0, 0xC571, 0x5D3C,
- 0, 0x5D3E, 0xC572, 0, 0x324E, 0xC573, 0x4337, 0,
- 0x5D3F, 0, 0xC574, 0x343F, 0x5D41, 0, 0xC575, 0,
- 0xC576, 0x5D40, 0, 0x5D42, 0, 0xC577, 0, 0x5D43,
- 0xC578, 0x5D44, 0x3B5F, 0x4035, 0x3A21, 0, 0x4970, 0xC579,
- 0, 0x4A62, 0x4F44, 0xC57A, 0, 0, 0xC57B, 0x3B75,
- 0xC57C, 0, 0, 0x3A50, 0x4E72, 0xC57D, 0, 0,
- 0x5D45, 0x5D46, 0, 0x3B60, 0, 0xC57E, 0xC621, 0x5D47,
-};
-const unsigned short utf8_to_euc_E6AE[] = {
- 0x5D48, 0, 0xC622, 0x5D4A, 0x5D49, 0xC623, 0x4B58, 0,
- 0, 0x3D5E, 0x3C6C, 0x3B44, 0, 0x5D4B, 0, 0,
- 0, 0, 0, 0, 0, 0x5D4D, 0x3F23, 0xC624,
- 0x5D4C, 0, 0, 0xC625, 0, 0, 0x5D4E, 0xC626,
- 0xC627, 0, 0xC628, 0xC629, 0x5D4F, 0, 0, 0,
- 0xC62A, 0xC62B, 0x5D50, 0x5D51, 0xC62C, 0xC62D, 0xC62E, 0x5D52,
- 0xC62F, 0x5D54, 0x5D53, 0x5D55, 0x3225, 0x434A, 0, 0x5D56,
- 0xC630, 0xC631, 0x3B26, 0x334C, 0x5D57, 0xC632, 0xC633, 0x4542,
-};
-const unsigned short utf8_to_euc_E6AF[] = {
- 0x544C, 0, 0, 0xC634, 0xC635, 0x3523, 0x5D58, 0,
- 0, 0xC636, 0, 0x5D59, 0xC637, 0x4A6C, 0x4B68, 0,
- 0, 0, 0x4647, 0x5D5A, 0x4866, 0, 0xC638, 0,
- 0x487B, 0, 0xC639, 0x4C53, 0, 0, 0, 0x5D5B,
- 0, 0xC63A, 0, 0xC63B, 0, 0, 0xC63C, 0xC63D,
- 0, 0, 0, 0x5D5D, 0x5D5C, 0, 0xC63E, 0x5D5F,
- 0, 0xC63F, 0, 0x5D5E, 0, 0, 0, 0xC640,
- 0, 0xC641, 0, 0, 0, 0, 0, 0xC642,
-};
-const unsigned short utf8_to_euc_E6B0[] = {
- 0, 0, 0xC643, 0, 0xC644, 0xC645, 0, 0,
- 0x5D61, 0xC646, 0, 0, 0, 0xC647, 0xC648, 0x3B61,
- 0xC649, 0x4C31, 0xC64A, 0x5D62, 0x5D63, 0, 0, 0x3524,
- 0, 0xC64B, 0, 0x5D64, 0, 0, 0, 0xC64C,
- 0, 0, 0, 0x5D66, 0x5D65, 0, 0xC64D, 0xC64E,
- 0xC64F, 0, 0, 0, 0xC650, 0, 0xC651, 0,
- 0, 0, 0, 0xC652, 0x3F65, 0xC653, 0xC654, 0x4939,
- 0x314A, 0, 0xC655, 0xC656, 0, 0, 0x4845, 0xC657,
-};
-const unsigned short utf8_to_euc_E6B1[] = {
- 0x4475, 0x3D41, 0x3561, 0, 0, 0, 0, 0,
- 0, 0, 0xC658, 0xC659, 0, 0xC65A, 0x4846, 0xC65B,
- 0x3C2E, 0, 0xC65C, 0, 0xC65D, 0x5D68, 0, 0x3440,
- 0, 0xC65E, 0x3178, 0xC65F, 0xC660, 0x4672, 0x5D67, 0x393E,
- 0x4353, 0, 0x5D69, 0, 0, 0, 0, 0xC736,
- 0x5D71, 0, 0x5D6A, 0xC661, 0, 0xC662, 0, 0xC663,
- 0x4241, 0, 0x3562, 0x5D72, 0xC664, 0, 0xC665, 0,
- 0xC666, 0xC667, 0x3768, 0xC668, 0, 0x3525, 0x5D70, 0,
-};
-const unsigned short utf8_to_euc_E6B2[] = {
- 0, 0x5D6E, 0x5D6B, 0x4D60, 0, 0xC669, 0xC66A, 0xC66B,
- 0x4440, 0xC66C, 0, 0, 0x4659, 0x5D6C, 0, 0,
- 0x5D74, 0, 0x5D73, 0x3723, 0xC66D, 0xC66E, 0x322D, 0xC66F,
- 0xC670, 0x3A3B, 0x5D6D, 0x5D6F, 0xC671, 0, 0, 0xC672,
- 0, 0x4B57, 0x4274, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x4B77, 0, 0, 0x5D7C, 0,
- 0xC673, 0x5D7D, 0xC674, 0x324F, 0xC675, 0, 0, 0,
- 0x4A28, 0x4C7D, 0x5E21, 0x3C23, 0x3E42, 0x5D78, 0x5D7E, 0x3168,
-};
-const unsigned short utf8_to_euc_E6B3[] = {
- 0, 0x3637, 0xC676, 0, 0x5D75, 0x5D7A, 0xC677, 0,
- 0, 0x4074, 0x4771, 0, 0x4867, 0xC678, 0, 0xC679,
- 0xC67A, 0xC67B, 0xC67C, 0x5D77, 0xC67D, 0x4B21, 0xC67E, 0x5D79,
- 0, 0x5E24, 0xC721, 0x5E22, 0xC722, 0x5D7B, 0, 0,
- 0xC723, 0x4B22, 0x4748, 0x3563, 0, 0x4525, 0, 0xC724,
- 0x436D, 0xC725, 0x5E25, 0xC726, 0xC727, 0, 0xC728, 0x5E23,
- 0x4259, 0x5D76, 0xC729, 0x314B, 0xC72A, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E6B4[] = {
- 0, 0, 0, 0, 0xC72B, 0, 0, 0xC72C,
- 0, 0, 0xC72D, 0x4D4E, 0x5E30, 0, 0xC72E, 0xC72F,
- 0, 0xC730, 0x5E2F, 0xC731, 0, 0, 0, 0x4076,
- 0, 0x5E2C, 0xC732, 0x4D6C, 0, 0, 0x4636, 0x5E26,
- 0, 0, 0, 0, 0, 0x4445, 0xC733, 0xC734,
- 0xC735, 0x314C, 0x393F, 0x5E29, 0, 0, 0xC737, 0xC738,
- 0, 0xC739, 0x3D27, 0x5E2E, 0, 0x5E2D, 0x5E28, 0,
- 0x5E2B, 0xC73A, 0, 0x3368, 0xC73B, 0x5E2A, 0x4749, 0xC73C,
-};
-const unsigned short utf8_to_euc_E6B5[] = {
- 0, 0x4E2E, 0, 0, 0x3E74, 0x4075, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xC73D,
- 0, 0x5E36, 0x5E34, 0, 0x494D, 0, 0xC73E, 0xC73F,
- 0, 0xC740, 0, 0x5E31, 0x5E33, 0xC741, 0x313A, 0xC742,
- 0, 0x3940, 0x4F32, 0, 0x333D, 0, 0x4962, 0xC743,
- 0xC744, 0, 0, 0, 0x4D61, 0, 0, 0x3324,
- 0x3F3B, 0x5E35, 0, 0, 0xC745, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E6B6[] = {
- 0, 0, 0xC746, 0, 0, 0x5E3A, 0, 0xC747,
- 0x3E43, 0, 0, 0, 0x4D30, 0, 0x5E37, 0,
- 0, 0xC748, 0xC749, 0x5E32, 0xC74A, 0x5E38, 0xC74B, 0xC74C,
- 0xC74D, 0x4E5E, 0, 0x4573, 0x4642, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xC74E, 0, 0xC74F, 0, 0, 0x3336,
- 0, 0, 0x3155, 0, 0xC750, 0x5E3E, 0, 0xC751,
- 0x5E41, 0xC752, 0, 0, 0x4E43, 0xC753, 0, 0xC754,
-};
-const unsigned short utf8_to_euc_E6B7[] = {
- 0x4D64, 0, 0, 0, 0xC755, 0x5E48, 0x5E42, 0x5E3F,
- 0xC756, 0, 0xC757, 0x4E54, 0x5E45, 0, 0xC758, 0xC759,
- 0, 0x3D4A, 0x5E47, 0, 0, 0x5E4C, 0xC75A, 0,
- 0x4571, 0x5E4A, 0, 0xC75B, 0, 0xC75C, 0x5E44, 0xC75D,
- 0xC75E, 0x4338, 0xC75F, 0, 0x5E4B, 0xC760, 0x5E40, 0,
- 0x5E46, 0xC761, 0x5E4D, 0x307C, 0x5E43, 0, 0x5E4E, 0xC762,
- 0xC763, 0x3F3C, 0xF44C, 0x3D5F, 0xC764, 0x4A25, 0xC765, 0x3A2E,
- 0xF44B, 0x5E3B, 0x5E49, 0x453A, 0xC766, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E6B8[] = {
- 0xC767, 0, 0, 0, 0xC768, 0x4036, 0, 0x3369,
- 0x3A51, 0x3E44, 0x5E3D, 0x3D42, 0, 0, 0, 0,
- 0, 0, 0, 0x374C, 0, 0x5E3C, 0, 0,
- 0, 0x5E52, 0x3D6D, 0x383A, 0, 0x5E61, 0xC769, 0x5E5B,
- 0x3574, 0x454F, 0xC76A, 0x5E56, 0x5E5F, 0x302F, 0x3132, 0xC76B,
- 0, 0x3239, 0, 0x5E58, 0x422C, 0x5E4F, 0x5E51, 0x3941,
- 0, 0, 0xC76C, 0, 0, 0, 0xC76D, 0,
- 0x5E62, 0xC76E, 0x5E5D, 0xC76F, 0xC770, 0, 0x5E55, 0,
-};
-const unsigned short utf8_to_euc_E6B9[] = {
- 0, 0, 0, 0x5E5C, 0xC771, 0xC772, 0, 0,
- 0xC773, 0xC774, 0x4C2B, 0xC775, 0, 0x5E5A, 0x5E5E, 0xC776,
- 0, 0xC777, 0xC778, 0xC779, 0xC77A, 0, 0x3850, 0xC77B,
- 0x3E45, 0, 0, 0x4339, 0xC77C, 0xC77D, 0xC77E, 0x5E54,
- 0, 0, 0xC821, 0xC822, 0, 0, 0, 0x4D2F,
- 0xC823, 0, 0, 0x5E57, 0, 0, 0x5E50, 0x4572,
- 0, 0, 0x5E53, 0xC824, 0, 0, 0x5E59, 0,
- 0, 0, 0, 0xC825, 0, 0xC826, 0x4F51, 0x3C3E,
-};
-const unsigned short utf8_to_euc_E6BA[] = {
- 0x4B7E, 0, 0x5E63, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x482E, 0xC827, 0, 0x5E6F,
- 0x383B, 0, 0, 0xC828, 0, 0, 0x3D60, 0,
- 0x5E65, 0xC829, 0, 0, 0x4E2F, 0x3942, 0, 0x5E72,
- 0xC82A, 0, 0x306E, 0, 0, 0x5E70, 0, 0xC82B,
- 0, 0, 0x5E64, 0, 0, 0xC82C, 0xC82D, 0x5E6A,
- 0, 0xC82E, 0x5E6C, 0xC82F, 0, 0, 0x4D4F, 0x5E67,
- 0, 0, 0x452E, 0xC830, 0, 0x5E69, 0, 0xC831,
-};
-const unsigned short utf8_to_euc_E6BB[] = {
- 0xC832, 0xC833, 0x5E71, 0xC834, 0x5E6B, 0x4C47, 0, 0xC835,
- 0xC836, 0x5E66, 0xC837, 0x3C22, 0x5E7E, 0xC838, 0xC839, 0xC83A,
- 0, 0x336A, 0, 0x5E68, 0x5E6D, 0x5E6E, 0, 0,
- 0, 0, 0, 0, 0, 0x426C, 0x425A, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xC83B, 0x5E76, 0xC83C, 0xC83D, 0x5E7C,
- 0, 0, 0x5E7A, 0, 0x4529, 0, 0, 0x5F23,
- 0x5E77, 0xC83E, 0, 0xC83F, 0, 0xC840, 0x5E78, 0x5E60,
-};
-const unsigned short utf8_to_euc_E6BC[] = {
- 0, 0x3579, 0x493A, 0, 0xC841, 0, 0x3C3F, 0,
- 0xC842, 0x3977, 0xC843, 0, 0xC844, 0xC845, 0, 0x4F33,
- 0, 0x5E74, 0, 0x5F22, 0x3169, 0x4166, 0xC846, 0,
- 0xC847, 0, 0xC848, 0xC849, 0, 0, 0, 0,
- 0x4779, 0, 0x3441, 0x4E7A, 0, 0, 0xC84A, 0,
- 0, 0xC84B, 0xC84C, 0x4C21, 0x4452, 0xC853, 0, 0xC84D,
- 0xC84E, 0x5E7B, 0x5E7D, 0xC84F, 0, 0, 0xC850, 0,
- 0x4132, 0, 0, 0xC851, 0xC852, 0, 0x5F21, 0x5E79,
-};
-const unsigned short utf8_to_euc_E6BD[] = {
- 0, 0x5E73, 0, 0, 0, 0x3443, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xC854,
- 0, 0xC855, 0xC856, 0xC857, 0x3769, 0, 0, 0xC858,
- 0x5F2F, 0xC859, 0xC85A, 0x5F2A, 0x4078, 0xC85B, 0xC85C, 0x3363,
- 0, 0xC85D, 0xC85E, 0, 0x3D61, 0, 0x5F33, 0,
- 0xC85F, 0, 0, 0, 0xC860, 0x5F2C, 0x442C, 0x5F29,
- 0x4459, 0, 0, 0, 0x5F4C, 0, 0, 0,
- 0x5F26, 0, 0x5F25, 0, 0x5F2E, 0xC861, 0xC862, 0,
-};
-const unsigned short utf8_to_euc_E6BE[] = {
- 0x5F28, 0x5F27, 0x5F2D, 0xC863, 0x4021, 0, 0x5F24, 0xC864,
- 0xC865, 0, 0, 0xC866, 0xC867, 0xC868, 0x5F30, 0,
- 0xC869, 0x5F31, 0xC86A, 0xC86B, 0xC86C, 0, 0xC86D, 0x3442,
- 0, 0, 0xC86E, 0, 0, 0, 0, 0xC86F,
- 0xC870, 0x5F36, 0, 0x5F35, 0x5F37, 0xC871, 0xC872, 0xC873,
- 0xC874, 0, 0x5F3A, 0, 0, 0, 0xC875, 0xC876,
- 0xC877, 0x4543, 0, 0x5F34, 0, 0xC878, 0xC879, 0,
- 0, 0x5F38, 0, 0, 0xC87A, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E6BF[] = {
- 0x3763, 0x4279, 0x5F32, 0x473B, 0, 0xC87B, 0x5F39, 0xC87C,
- 0xC87D, 0, 0xC87E, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x5F3E, 0x5F3C, 0, 0,
- 0x5F3F, 0, 0xC921, 0x5F42, 0, 0, 0xC922, 0x5F3B,
- 0x396A, 0x4728, 0, 0, 0x5E39, 0, 0, 0,
- 0xC923, 0xC924, 0, 0x4D74, 0x5F3D, 0, 0x5F41, 0x4275,
- 0xC925, 0x5F40, 0, 0x5F2B, 0, 0xC926, 0x6F69, 0,
- 0, 0xC927, 0x5F45, 0, 0xC928, 0xC929, 0x5F49, 0,
-};
-const unsigned short utf8_to_euc_E780[] = {
- 0xC92A, 0x5F47, 0, 0, 0, 0xC92B, 0xC92C, 0xC92D,
- 0, 0x5F43, 0, 0x5F44, 0, 0xC92E, 0, 0x5F48,
- 0, 0x5F46, 0, 0, 0, 0x494E, 0, 0xC92F,
- 0x5F4E, 0, 0x5F4B, 0x5F4A, 0, 0x5F4D, 0x4654, 0x5F4F,
- 0xC930, 0, 0, 0xC931, 0, 0, 0x4375, 0x426D,
- 0xF44D, 0, 0, 0, 0x4025, 0, 0, 0xC932,
- 0x5F50, 0, 0x5F52, 0, 0xC933, 0, 0, 0xC934,
- 0, 0xC935, 0, 0, 0xC936, 0, 0x5F51, 0,
-};
-const unsigned short utf8_to_euc_E781[] = {
- 0, 0, 0, 0xC937, 0xC938, 0, 0, 0,
- 0xC939, 0xC93A, 0xC93B, 0xC93C, 0x5E75, 0, 0xC941, 0,
- 0, 0x5F53, 0, 0, 0xC93D, 0xC93E, 0, 0,
- 0x4667, 0, 0, 0, 0, 0xC93F, 0xC940, 0,
- 0, 0, 0, 0x5F54, 0xC942, 0xC943, 0, 0,
- 0, 0, 0, 0x3250, 0xC944, 0, 0xC945, 0x4574,
- 0x3325, 0, 0, 0, 0, 0xC946, 0xC947, 0,
- 0x3564, 0, 0, 0, 0x3C5E, 0x3A52, 0xC948, 0,
-};
-const unsigned short utf8_to_euc_E782[] = {
- 0, 0xC949, 0, 0, 0, 0xC94A, 0xC94B, 0,
- 0, 0x4F27, 0x3F66, 0, 0, 0, 0x316A, 0,
- 0, 0, 0x5F56, 0, 0xC94C, 0xC94D, 0xC94E, 0xC94F,
- 0xC950, 0x5F55, 0, 0xC951, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xC952, 0, 0, 0,
- 0, 0, 0, 0xC953, 0x5F59, 0x433A, 0x5F5C, 0x5F57,
- 0xC954, 0xC955, 0, 0x5F5B, 0xC956, 0, 0, 0xC957,
- 0x5F5A, 0x4540, 0x3059, 0xF42E, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E783[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x4E75, 0, 0xC958, 0x5F5E, 0, 0, 0, 0x3128,
- 0, 0xC959, 0, 0xC95A, 0xC95B, 0xC95C, 0xC95D, 0,
- 0xC95E, 0x5F60, 0, 0, 0xC95F, 0x5F5F, 0, 0x5F5D,
- 0, 0, 0, 0, 0xC960, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x5F58, 0, 0, 0, 0, 0, 0,
- 0, 0x4B23, 0xC961, 0, 0, 0x5F62, 0, 0,
-};
-const unsigned short utf8_to_euc_E784[] = {
- 0, 0, 0, 0xC962, 0xC963, 0xC964, 0xC965, 0xC966,
- 0, 0x5F61, 0, 0xC967, 0xC968, 0, 0, 0xC969,
- 0, 0, 0, 0, 0x316B, 0, 0, 0,
- 0, 0x5F64, 0x4A32, 0, 0x5F63, 0, 0xC96A, 0,
- 0xC96B, 0x4C35, 0, 0, 0, 0, 0x3E47, 0,
- 0, 0, 0, 0xC96C, 0, 0xC96D, 0, 0xC96E,
- 0xC96F, 0xC970, 0, 0, 0, 0, 0x4133, 0,
- 0xC971, 0, 0, 0, 0x3E46, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E785[] = {
- 0, 0xC972, 0, 0, 0, 0xC973, 0xC974, 0xC975,
- 0, 0x4E7B, 0xC976, 0xC977, 0x5F6A, 0, 0x4079, 0,
- 0xC978, 0, 0xC979, 0, 0, 0x5F66, 0x5F6B, 0xC97A,
- 0, 0x316C, 0xC97B, 0, 0xC97C, 0, 0xC97D, 0,
- 0xC97E, 0, 0x5F69, 0, 0x4761, 0x5F65, 0x5F68, 0x3E48,
- 0xCA21, 0x4851, 0, 0, 0x5F6C, 0, 0x3C51, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xCA22, 0, 0, 0, 0x407A, 0, 0,
-};
-const unsigned short utf8_to_euc_E786[] = {
- 0xCA23, 0, 0, 0, 0x5F6F, 0xCA24, 0, 0xCA25,
- 0x5F67, 0, 0x3727, 0, 0xCA26, 0, 0, 0x5F6D,
- 0, 0, 0xCA27, 0, 0x4D50, 0x5F70, 0, 0,
- 0, 0x7426, 0xCA28, 0xCA29, 0, 0, 0, 0x3D4F,
- 0xCA2A, 0, 0xCA2B, 0, 0, 0, 0, 0,
- 0x5F71, 0, 0, 0, 0x5F72, 0, 0, 0xCA2C,
- 0xCA2D, 0x472E, 0xCA2E, 0xCA2F, 0, 0, 0, 0,
- 0, 0x5F74, 0xCA30, 0, 0, 0, 0x5F75, 0xCA31,
-};
-const unsigned short utf8_to_euc_E787[] = {
- 0xCA32, 0xCA33, 0, 0x4733, 0xCA34, 0, 0, 0,
- 0x4575, 0x5F77, 0, 0xCA35, 0xCA36, 0, 0x5F79, 0,
- 0x4E55, 0, 0x5F76, 0xCA37, 0x5F78, 0x316D, 0xCA38, 0x5F73,
- 0, 0xCA39, 0xCA3A, 0, 0xCA3B, 0, 0, 0x535B,
- 0x5F7A, 0, 0, 0, 0, 0x4167, 0x3B38, 0x5F7C,
- 0, 0, 0, 0, 0x5F7B, 0x3F24, 0x5259, 0,
- 0, 0, 0, 0, 0, 0x5F7D, 0, 0,
- 0xCA3C, 0x6021, 0, 0x5F6E, 0x5F7E, 0, 0xCA3D, 0x6022,
-};
-const unsigned short utf8_to_euc_E788[] = {
- 0xCA3E, 0, 0, 0, 0, 0, 0x477A, 0xCA3F,
- 0xCA40, 0xCA41, 0, 0, 0, 0x6023, 0, 0,
- 0x6024, 0, 0, 0xCA42, 0, 0, 0, 0xCA43,
- 0, 0, 0xCA44, 0x6025, 0, 0xCA45, 0, 0xCA46,
- 0, 0, 0, 0, 0xCA47, 0, 0, 0,
- 0x6026, 0, 0x445E, 0xCA48, 0x6028, 0x6027, 0, 0xCA49,
- 0x6029, 0, 0x602A, 0, 0xCA4A, 0x3C5F, 0x4963, 0,
- 0xCA4B, 0xCA4C, 0x4C6C, 0x602B, 0x602C, 0x4156, 0x3C24, 0x602D,
-};
-const unsigned short utf8_to_euc_E789[] = {
- 0x602E, 0xCA4D, 0xCA4E, 0xCA4F, 0, 0xCA50, 0x602F, 0x4A52,
- 0x4847, 0, 0, 0x6030, 0x4757, 0, 0xCA51, 0xCA52,
- 0xCA53, 0, 0x442D, 0xCA54, 0, 0xCA55, 0xCA56, 0,
- 0x6031, 0x3267, 0xCA57, 0x356D, 0xCA58, 0x4C46, 0xCA59, 0x4C36,
- 0xCA5A, 0x3234, 0x4F34, 0xCA5B, 0, 0, 0, 0x4B52,
- 0xCA5C, 0x4A2A, 0, 0xCA5D, 0, 0, 0xCA5E, 0xCA5F,
- 0, 0xCA60, 0x4037, 0, 0x6032, 0, 0, 0xCA61,
- 0xCA62, 0x4643, 0, 0xCA63, 0xCA64, 0x3823, 0x6033, 0xCA65,
-};
-const unsigned short utf8_to_euc_E78A[] = {
- 0x3A54, 0x6035, 0x6034, 0, 0xCA66, 0, 0, 0x6036,
- 0, 0xCA67, 0, 0, 0, 0xCA68, 0xCA69, 0,
- 0, 0, 0x6037, 0xCA6A, 0, 0, 0x6038, 0,
- 0, 0, 0, 0xCA6B, 0, 0, 0, 0,
- 0x353E, 0, 0x6039, 0, 0, 0, 0, 0x603A,
- 0xCA6C, 0, 0, 0, 0x3824, 0xCA6D, 0xCA6E, 0x4848,
- 0, 0xCA6F, 0x603C, 0, 0xCA70, 0, 0x3E75, 0,
- 0, 0x603B, 0, 0, 0, 0, 0xCA71, 0,
-};
-const unsigned short utf8_to_euc_E78B[] = {
- 0, 0xCA72, 0x3638, 0x603D, 0x603F, 0, 0x603E, 0xCA73,
- 0, 0xCA74, 0, 0, 0xCA75, 0, 0x6040, 0,
- 0x3851, 0, 0x6041, 0, 0, 0xCA76, 0xCA77, 0x3669,
- 0xCA78, 0x4140, 0, 0x397D, 0, 0, 0, 0xCA79,
- 0x6043, 0x6044, 0x6042, 0, 0, 0xCA7A, 0, 0,
- 0, 0x3C6D, 0, 0, 0x4648, 0x3639, 0, 0,
- 0, 0, 0, 0xCA7B, 0xCA7C, 0, 0, 0x6046,
- 0x432C, 0x6045, 0xCA7D, 0xCA7E, 0x4F35, 0x4762, 0xCB21, 0,
-};
-const unsigned short utf8_to_euc_E78C[] = {
- 0, 0, 0xCB22, 0, 0xCB23, 0xCB24, 0, 0xCB25,
- 0, 0, 0x6049, 0xCB26, 0, 0xCB27, 0, 0,
- 0, 0, 0xCB28, 0xCB29, 0, 0, 0x604B, 0x6048,
- 0xCB2A, 0xCB2B, 0, 0x4C54, 0x604A, 0x604C, 0xCB2C, 0x4E44,
- 0, 0, 0xCB2D, 0, 0xCB2E, 0x6050, 0, 0xCB2F,
- 0xCB30, 0x604F, 0x4376, 0x472D, 0xCB31, 0, 0x3825, 0x604E,
- 0, 0xCB32, 0xCB33, 0, 0x604D, 0xCB34, 0x4D31, 0x4D32,
- 0, 0, 0xCB35, 0xCB36, 0, 0xCB37, 0x6051, 0x316E,
-};
-const unsigned short utf8_to_euc_E78D[] = {
- 0, 0, 0, 0xCB38, 0x3976, 0x3B62, 0, 0,
- 0, 0, 0, 0, 0, 0xCB39, 0x6052, 0x6053,
- 0xCB3A, 0, 0xCB3B, 0, 0, 0, 0xCB3C, 0x6055,
- 0xCB3D, 0, 0, 0, 0, 0xCB3E, 0xCB3F, 0xCB40,
- 0xCB41, 0, 0, 0x3D43, 0, 0, 0xCB42, 0xCB43,
- 0x6057, 0xCB44, 0x6056, 0xCB45, 0xCB46, 0, 0xCB47, 0xCB48,
- 0x6058, 0xCB49, 0x334D, 0, 0, 0x605A, 0, 0xCB4A,
- 0x6059, 0xCB4B, 0x605C, 0x605B, 0xCB4C, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E78E[] = {
- 0xCB4D, 0xCB4E, 0, 0xCB4F, 0x383C, 0xCB50, 0xCB51, 0x4E28,
- 0, 0x364C, 0, 0x3226, 0, 0, 0xCB52, 0,
- 0xCB53, 0, 0, 0xCB54, 0, 0xCB55, 0x366A, 0xCB56,
- 0xCB57, 0, 0, 0, 0xCB58, 0, 0xCB59, 0xCB5A,
- 0xCB5B, 0, 0xCB5C, 0, 0, 0xCB5D, 0xCB5E, 0,
- 0, 0x3461, 0xCB5F, 0xCB60, 0, 0xCB61, 0, 0,
- 0, 0, 0x4E68, 0x605E, 0, 0xCB62, 0, 0xCB63,
- 0, 0xCB64, 0, 0x6060, 0xCB65, 0xCB66, 0, 0xCB67,
-};
-const unsigned short utf8_to_euc_E78F[] = {
- 0x6061, 0, 0x3251, 0, 0, 0xCB68, 0xCB69, 0,
- 0x605D, 0xCB6A, 0x3B39, 0xCB6B, 0xCB6C, 0x4441, 0x605F, 0xCB6D,
- 0, 0, 0xCB6E, 0xCB6F, 0, 0, 0xCB70, 0,
- 0, 0xCB71, 0, 0, 0, 0xCB72, 0x6064, 0,
- 0x3C6E, 0xCB73, 0, 0xCB74, 0, 0x6062, 0xCB75, 0xCB76,
- 0, 0xCB77, 0x373E, 0, 0, 0x4849, 0x6063, 0,
- 0, 0x607E, 0, 0, 0xCB78, 0xCB79, 0, 0xCB7A,
- 0x6069, 0xCB7B, 0xCB7C, 0xCB7D, 0, 0xCB7E, 0x383D, 0xCC21,
-};
-const unsigned short utf8_to_euc_E790[] = {
- 0xCC22, 0xCC23, 0, 0x3565, 0xCC24, 0x6066, 0x4D7D, 0xCC25,
- 0, 0x4E30, 0xCC26, 0, 0, 0, 0, 0,
- 0, 0xCC27, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xCC28, 0xCC29, 0, 0, 0, 0,
- 0, 0, 0x4276, 0, 0xCC2A, 0x6068, 0xCC2B, 0,
- 0xCC2C, 0xCC2D, 0xCC2E, 0xCC2F, 0xCC30, 0xCC31, 0xCC32, 0xCC33,
- 0xCC34, 0xCC35, 0x606A, 0x4E56, 0x3657, 0x487C, 0x474A, 0,
- 0, 0xCC36, 0x606B, 0, 0, 0, 0, 0x606D,
-};
-const unsigned short utf8_to_euc_E791[] = {
- 0xCC37, 0x6070, 0, 0xCC38, 0xCC39, 0, 0xCC3A, 0xCC3B,
- 0, 0, 0, 0xCC3C, 0, 0xCC3D, 0, 0,
- 0, 0xCC3E, 0xCC3F, 0, 0, 0x606C, 0, 0xCC40,
- 0, 0x606F, 0x386A, 0x314D, 0x6071, 0xCC41, 0x3F70, 0x606E,
- 0x4E5C, 0, 0xCC42, 0x6074, 0x7424, 0, 0xCC43, 0xCC44,
- 0xCC45, 0x6072, 0x6075, 0xCC46, 0, 0xCC47, 0xCC48, 0x6067,
- 0x6073, 0xCC49, 0xCC4A, 0x3A3C, 0, 0, 0x6076, 0,
- 0, 0, 0, 0, 0, 0, 0x6077, 0,
-};
-const unsigned short utf8_to_euc_E792[] = {
- 0xCC4B, 0xCC4C, 0, 0x4D7E, 0, 0xCC4D, 0xCC4E, 0xCC4F,
- 0, 0xCC50, 0, 0x6078, 0, 0, 0, 0xCC51,
- 0xCC52, 0xCC53, 0xCC54, 0, 0, 0, 0, 0,
- 0xCC55, 0xCC56, 0xCC57, 0, 0xCC58, 0, 0x6079, 0xCC59,
- 0xCC5A, 0xCC5B, 0x6065, 0xCC5C, 0, 0, 0xCC5D, 0x607A,
- 0xCC5E, 0xCC5F, 0xCC60, 0xCC61, 0, 0, 0xCC62, 0xCC63,
- 0x3444, 0xCC64, 0xCC65, 0, 0, 0xCC66, 0, 0,
- 0, 0xCC67, 0, 0xCC68, 0, 0x3C25, 0, 0xCC69,
-};
-const unsigned short utf8_to_euc_E793[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xCC6A, 0xCC6B, 0x607B, 0, 0xCC6C, 0, 0, 0x607C,
- 0xCC6D, 0, 0, 0xCC6E, 0x607D, 0, 0, 0,
- 0xCC6F, 0, 0xCC70, 0xCC71, 0x313B, 0, 0xCC72, 0xCC73,
- 0x6121, 0, 0x493B, 0x6122, 0xCC74, 0, 0x3424, 0x6123,
- 0xCC75, 0x6124, 0xCC76, 0xCC77, 0, 0, 0x6125, 0xCC78,
- 0x6127, 0x6128, 0x6126, 0, 0xCC79, 0, 0x4953, 0x612A,
- 0x6129, 0, 0xCC7A, 0xCC7B, 0xCC7C, 0, 0, 0xCC7D,
-};
-const unsigned short utf8_to_euc_E794[] = {
- 0, 0xF450, 0, 0x612C, 0x612B, 0x612D, 0xCC7E, 0,
- 0, 0, 0, 0, 0x612E, 0x6130, 0x612F, 0,
- 0, 0x3979, 0xCD21, 0x6132, 0, 0x6131, 0xCD22, 0xCD23,
- 0x3445, 0, 0x3F53, 0, 0x453C, 0, 0x6133, 0x4038,
- 0xCD24, 0xCD25, 0, 0x3B3A, 0xCD26, 0x3179, 0x6134, 0xCD27,
- 0x4D51, 0xCD28, 0xCD29, 0x4A63, 0x6135, 0, 0, 0xCD2A,
- 0x4544, 0x4D33, 0x3943, 0x3F3D, 0, 0, 0xCD2B, 0x434B,
- 0x5234, 0xCD2C, 0x442E, 0x3268, 0x6136, 0xCD2D, 0xCD2E, 0xCD2F,
-};
-const unsigned short utf8_to_euc_E795[] = {
- 0xCD30, 0, 0, 0xCD31, 0x6137, 0, 0x613C, 0xCD32,
- 0xCD33, 0x613A, 0x6139, 0x5A42, 0x3326, 0x6138, 0xCD34, 0x305A,
- 0xCD35, 0x482A, 0xCD36, 0, 0x484A, 0, 0, 0xCD37,
- 0, 0x4E31, 0x613D, 0x613B, 0x435C, 0x4026, 0xCD38, 0xCD39,
- 0x482B, 0xCD3A, 0x492D, 0, 0x613F, 0x4E2C, 0x374D, 0x6140,
- 0, 0x613E, 0x4856, 0x6141, 0, 0x6142, 0, 0xCD3B,
- 0x305B, 0xCD3C, 0, 0x3E76, 0x6147, 0, 0x6144, 0x466D,
- 0x6143, 0xCD3D, 0xCD3E, 0xCD3F, 0xCD40, 0xCD41, 0xCD42, 0x3526,
-};
-const unsigned short utf8_to_euc_E796[] = {
- 0, 0xCD43, 0x614A, 0, 0, 0xCD44, 0x6145, 0x6146,
- 0, 0x6149, 0x6148, 0x4925, 0, 0, 0x4142, 0x4141,
- 0xCD45, 0x353F, 0xCD46, 0xCD47, 0x614B, 0xCD48, 0, 0,
- 0, 0xCD49, 0x614C, 0, 0xCD4A, 0x614D, 0, 0,
- 0, 0, 0xCD4B, 0x614F, 0xCD4C, 0x614E, 0, 0,
- 0, 0, 0, 0x3156, 0, 0, 0, 0,
- 0, 0x6157, 0x4868, 0x6151, 0xCD4D, 0x6153, 0, 0,
- 0x6155, 0x3F3E, 0xCD4E, 0, 0x6156, 0x6154, 0x3C40, 0xCD4F,
-};
-const unsigned short utf8_to_euc_E797[] = {
- 0xCD50, 0xCD51, 0x6150, 0x6152, 0xCD52, 0x4942, 0xCD53, 0x3E49,
- 0, 0, 0x6159, 0, 0xCD54, 0x6158, 0xCD55, 0xCD56,
- 0, 0, 0x615A, 0, 0x3C26, 0x3A2F, 0, 0xCD57,
- 0x4577, 0x615B, 0, 0x444B, 0xCD58, 0, 0x615D, 0xCD59,
- 0xCD5A, 0xCD5B, 0x4E21, 0x615C, 0xCD5C, 0, 0, 0xCD5D,
- 0, 0x4169, 0, 0, 0xCD5E, 0, 0xCD5F, 0xCD60,
- 0x6162, 0xCD61, 0x6164, 0x6165, 0x4354, 0, 0, 0,
- 0, 0xCD62, 0x6163, 0, 0x6160, 0, 0x615E, 0x615F,
-};
-const unsigned short utf8_to_euc_E798[] = {
- 0xCD63, 0x6161, 0xCD64, 0xCD65, 0xCD66, 0, 0, 0xCD67,
- 0xCD68, 0x6168, 0xCD69, 0x6166, 0xCD6A, 0x6167, 0, 0xCD6B,
- 0, 0, 0xCD6C, 0xCD6D, 0, 0xCD6E, 0xCD6F, 0,
- 0, 0xCD70, 0, 0xCD71, 0xCD72, 0xCD73, 0xCD74, 0x6169,
- 0x616B, 0x616C, 0x616D, 0xCD75, 0x616E, 0xCD76, 0xCD77, 0x616A,
- 0, 0xCD78, 0, 0, 0, 0xCD79, 0, 0,
- 0x6170, 0, 0xCD7A, 0xCD7B, 0x616F, 0xCD7C, 0, 0,
- 0xCD7D, 0xCD7E, 0xCE21, 0x6171, 0xCE22, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E799[] = {
- 0xCE24, 0xCE25, 0x4E45, 0xCE26, 0xCE27, 0xCE28, 0x6174, 0x6172,
- 0x6173, 0xCE29, 0xCE23, 0xCE2A, 0x3462, 0, 0, 0,
- 0, 0, 0x4C7E, 0, 0, 0xCE2B, 0x4A4A, 0,
- 0x6176, 0xCE2C, 0, 0, 0x6175, 0, 0, 0xCE2D,
- 0, 0x6177, 0x6178, 0, 0xCE2E, 0xCE2F, 0, 0x617C,
- 0x6179, 0x617A, 0x617B, 0, 0x617D, 0xCE30, 0xCE31, 0xCE32,
- 0x617E, 0xCE33, 0x6221, 0, 0xCE34, 0, 0x6222, 0,
- 0x6223, 0, 0x482F, 0x4550, 0x6224, 0x4772, 0x4934, 0,
-};
-const unsigned short utf8_to_euc_E79A[] = {
- 0x6225, 0xCE35, 0xF451, 0x6226, 0x452A, 0xCE36, 0x3327, 0x3944,
- 0x6227, 0, 0, 0x6228, 0xCE37, 0xCE38, 0x6229, 0,
- 0x3B29, 0, 0, 0x622B, 0, 0xCE39, 0x622A, 0,
- 0, 0x622C, 0x622D, 0xCE3A, 0xCE3B, 0xCE3C, 0xF452, 0xCE3D,
- 0xCE3E, 0, 0xCE3F, 0xCE40, 0xCE41, 0xCE42, 0xCE43, 0xCE44,
- 0xCE45, 0, 0xCE46, 0, 0, 0xCE47, 0x4869, 0,
- 0x622E, 0, 0, 0, 0x622F, 0, 0, 0x7369,
- 0x6230, 0x6231, 0x6232, 0, 0, 0xCE48, 0, 0x3B2E,
-};
-const unsigned short utf8_to_euc_E79B[] = {
- 0, 0xCE49, 0x6233, 0x4756, 0, 0xCE4A, 0x4B5F, 0,
- 0x314E, 0xCE4B, 0x3157, 0xCE4C, 0xCE4D, 0x6234, 0xCE4E, 0,
- 0, 0, 0x6236, 0, 0xCE4F, 0, 0x6235, 0x4570,
- 0, 0xCE50, 0, 0x4039, 0x5D39, 0, 0x6237, 0x4C41,
- 0xCE51, 0x6238, 0, 0x3446, 0x4857, 0x6239, 0xCE52, 0x623A,
- 0xCE53, 0, 0x623B, 0, 0xCE54, 0, 0x4C5C, 0,
- 0xCE55, 0xCE56, 0x4C55, 0, 0x443E, 0, 0xCE57, 0,
- 0x416A, 0xCE58, 0, 0x623D, 0xCE59, 0, 0x3D62, 0,
-};
-const unsigned short utf8_to_euc_E79C[] = {
- 0xCE5A, 0x3E4A, 0, 0, 0x6240, 0, 0xCE5B, 0x623F,
- 0x623E, 0x487D, 0xCE5C, 0x3447, 0x3829, 0, 0xCE5D, 0,
- 0, 0, 0xCE5E, 0, 0xCE5F, 0xCE60, 0, 0xCE61,
- 0, 0xCE62, 0xCE63, 0x6246, 0xCE64, 0, 0x6243, 0x3F3F,
- 0x4C32, 0, 0xCE65, 0, 0x6242, 0x6244, 0x6245, 0,
- 0xCE66, 0x6241, 0, 0, 0, 0xCE67, 0xCE68, 0xCE69,
- 0, 0, 0, 0, 0xCE6A, 0xCE6B, 0xCE6C, 0x6247,
- 0x6248, 0xCE6D, 0x442F, 0, 0x3463, 0xCE6E, 0xCE6F, 0,
-};
-const unsigned short utf8_to_euc_E79D[] = {
- 0x4365, 0, 0xCE70, 0, 0, 0xCE71, 0xCE72, 0x6249,
- 0, 0, 0xCE73, 0, 0, 0xCE74, 0xCE75, 0xCE76,
- 0, 0, 0xCE77, 0, 0, 0, 0xCE78, 0xCE79,
- 0, 0, 0x624A, 0x624D, 0xCE7A, 0, 0xCE7B, 0xCE7C,
- 0xCE7D, 0x3F67, 0xCE7E, 0x4644, 0xCF21, 0x624E, 0x4B53, 0xCF22,
- 0x624B, 0, 0xCF23, 0x624C, 0xCF24, 0, 0, 0,
- 0xCF25, 0, 0xCF26, 0xCF27, 0xCF28, 0, 0, 0,
- 0, 0x6251, 0xCF29, 0, 0, 0xCF2A, 0x6250, 0x624F,
-};
-const unsigned short utf8_to_euc_E79E[] = {
- 0xCF2B, 0, 0, 0, 0xCF2C, 0, 0, 0,
- 0, 0, 0, 0x6253, 0xCF2D, 0xCF2E, 0x6252, 0,
- 0, 0x6254, 0, 0, 0xCF2F, 0xCF30, 0xCF31, 0,
- 0, 0, 0xCF32, 0, 0, 0, 0x6256, 0xCF33,
- 0x6255, 0, 0xCF34, 0, 0, 0x4A4D, 0, 0xCF35,
- 0, 0, 0xCF36, 0, 0x3D56, 0x4E46, 0xCF37, 0xCF38,
- 0x6257, 0xCF39, 0, 0x4637, 0, 0xCF3A, 0x6258, 0,
- 0, 0x6259, 0, 0x625D, 0x625B, 0x625C, 0xCF3B, 0x625A,
-};
-const unsigned short utf8_to_euc_E79F[] = {
- 0, 0, 0, 0xCF3C, 0, 0, 0, 0x625E,
- 0, 0xCF3D, 0, 0, 0, 0x625F, 0, 0,
- 0, 0xCF3E, 0xCF3F, 0, 0, 0xCF40, 0, 0x6260,
- 0, 0xCF41, 0x6261, 0x4C37, 0x6262, 0, 0xCF42, 0xCF43,
- 0xCF44, 0, 0x4C70, 0x6263, 0xCF45, 0x434E, 0xCF46, 0x476A,
- 0, 0x366B, 0xCF47, 0, 0xCF48, 0x433B, 0x6264, 0x363A,
- 0xCF49, 0xCF4A, 0, 0x4050, 0xCF4B, 0, 0, 0,
- 0xCF4C, 0, 0, 0xCF4D, 0x6265, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E7A0[] = {
- 0, 0, 0x3A3D, 0, 0, 0xCF4E, 0xCF4F, 0,
- 0, 0xCF50, 0, 0, 0x6266, 0xCF51, 0xCF52, 0,
- 0, 0xCF53, 0x6267, 0, 0x3826, 0x3A55, 0, 0,
- 0, 0, 0, 0, 0, 0xCF54, 0, 0,
- 0x6269, 0xCF55, 0xCF56, 0xCF57, 0, 0x4556, 0x3A56, 0x354E,
- 0, 0, 0, 0, 0, 0xCF58, 0xCF59, 0,
- 0xCF5A, 0, 0x4B24, 0, 0x474B, 0xCF5B, 0, 0xCF5C,
- 0, 0, 0x4557, 0, 0, 0, 0, 0x395C,
-};
-const unsigned short utf8_to_euc_E7A1[] = {
- 0, 0, 0, 0xCF5D, 0xCF5E, 0x626B, 0, 0xCF5F,
- 0xCF60, 0, 0, 0, 0xCF61, 0, 0xCF62, 0,
- 0, 0, 0xCF63, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xCF64, 0x3E4B, 0xCF65, 0,
- 0xCF66, 0xCF67, 0, 0xCF68, 0xCF69, 0, 0, 0,
- 0xCF6A, 0, 0xCF6B, 0x4E32, 0x3945, 0, 0xCF6C, 0x3827,
- 0, 0, 0x4823, 0, 0x626D, 0, 0, 0,
- 0, 0, 0xCF6D, 0, 0x626F, 0, 0xCF6E, 0,
-};
-const unsigned short utf8_to_euc_E7A2[] = {
- 0, 0x386B, 0, 0, 0, 0, 0x626E, 0x4476,
- 0, 0, 0xCF6F, 0, 0x6271, 0x3337, 0x626C, 0xCF70,
- 0, 0x486A, 0, 0x3130, 0xCF71, 0x3A6C, 0, 0x4F52,
- 0xCF72, 0, 0x6270, 0, 0, 0xCF74, 0xCF75, 0xCF76,
- 0, 0xCF73, 0, 0x6272, 0xCF77, 0, 0, 0x4A4B,
- 0xCF78, 0x4059, 0x6274, 0, 0xCF79, 0xCF7A, 0, 0x6275,
- 0xCF7B, 0xCF7C, 0xCF7D, 0xCF7E, 0, 0x6273, 0, 0,
- 0, 0, 0x334E, 0xD021, 0x627B, 0xD022, 0x627A, 0xD023,
-};
-const unsigned short utf8_to_euc_E7A3[] = {
- 0, 0x3C27, 0, 0, 0, 0x627C, 0x6277, 0xD024,
- 0xD025, 0xD026, 0x627D, 0x6278, 0xD027, 0, 0xD028, 0,
- 0x4858, 0x6276, 0xD029, 0xD02A, 0x6279, 0xD02B, 0xD02C, 0,
- 0, 0, 0x6322, 0xD02E, 0, 0, 0, 0xD02F,
- 0xD030, 0xD031, 0, 0, 0xD02D, 0, 0xD032, 0x6321,
- 0x4B61, 0, 0xD033, 0, 0x627E, 0, 0, 0x306B,
- 0, 0, 0xD034, 0xD035, 0x6324, 0, 0xD037, 0xD038,
- 0, 0, 0xD039, 0xD03A, 0, 0x6323, 0, 0xD03B,
-};
-const unsigned short utf8_to_euc_E7A4[] = {
- 0xD036, 0x3E4C, 0, 0, 0, 0, 0xD03C, 0x6325,
- 0, 0, 0, 0, 0xD03D, 0, 0x4143, 0,
- 0xD03E, 0x6327, 0x6326, 0, 0, 0, 0, 0,
- 0, 0x6328, 0xD03F, 0, 0xD040, 0, 0xD041, 0xD042,
- 0xD043, 0, 0, 0, 0, 0xD044, 0x6268, 0xD045,
- 0, 0xD046, 0x626A, 0x632A, 0x6329, 0xD047, 0, 0,
- 0xF454, 0xD048, 0, 0, 0xD049, 0xD04A, 0, 0,
- 0, 0, 0x3C28, 0xD04B, 0x4E69, 0xD04C, 0x3C52, 0xD04D,
-};
-const unsigned short utf8_to_euc_E7A5[] = {
- 0x632B, 0x3737, 0, 0, 0xD04E, 0xD04F, 0xD050, 0x3540,
- 0x3527, 0x3B63, 0xD051, 0xD052, 0, 0, 0, 0xD053,
- 0x4D34, 0xD054, 0, 0x6331, 0xD055, 0x6330, 0x4144, 0x632D,
- 0xD056, 0, 0x632F, 0xD057, 0xD058, 0x3D4B, 0x3F40, 0x632E,
- 0x632C, 0, 0x472A, 0, 0, 0x3E4D, 0, 0xD059,
- 0x493C, 0xD05A, 0, 0xD05B, 0, 0x3A57, 0, 0,
- 0, 0, 0xD05C, 0, 0, 0, 0, 0x4578,
- 0, 0xD05D, 0x6332, 0xD05E, 0xD05F, 0, 0xD060, 0x6333,
-};
-const unsigned short utf8_to_euc_E7A6[] = {
- 0x6349, 0x3658, 0, 0, 0x4F3D, 0x4135, 0, 0,
- 0, 0, 0x6334, 0xD061, 0xD062, 0x3252, 0x4477, 0x4A21,
- 0, 0xD063, 0, 0xD064, 0xD065, 0xD066, 0xD067, 0,
- 0xD068, 0, 0, 0xD069, 0xD06A, 0x6335, 0, 0,
- 0, 0xD06B, 0, 0, 0, 0, 0x357A, 0x6336,
- 0xD06C, 0xD06D, 0x6338, 0xD06E, 0, 0, 0x6339, 0xD06F,
- 0x4729, 0xD070, 0, 0x633A, 0xD071, 0, 0, 0,
- 0xD072, 0x633B, 0x633C, 0xD073, 0, 0x3659, 0x3253, 0x4645,
-};
-const unsigned short utf8_to_euc_E7A7[] = {
- 0x3D28, 0x3B64, 0xD074, 0, 0xD075, 0, 0, 0xD076,
- 0xD077, 0x633D, 0xD078, 0x3D29, 0, 0, 0, 0xD079,
- 0, 0x324A, 0x4943, 0, 0xD07A, 0x633E, 0xD07B, 0,
- 0x486B, 0, 0xD07C, 0, 0, 0xD07D, 0xD07E, 0x4145,
- 0xD121, 0x6341, 0xD122, 0x6342, 0x4769, 0xD123, 0x3F41, 0x633F,
- 0, 0x4361, 0xD124, 0xD125, 0x6340, 0xD126, 0, 0,
- 0x3E4E, 0xD127, 0, 0, 0, 0, 0, 0,
- 0xD128, 0, 0, 0x305C, 0xD129, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E7A8[] = {
- 0x3529, 0, 0xD12A, 0xD12B, 0, 0, 0, 0xD12C,
- 0x6343, 0xD12D, 0xD12E, 0x4478, 0xD12F, 0x6344, 0x4047, 0,
- 0, 0xD130, 0, 0, 0x4C2D, 0xD131, 0, 0x4923,
- 0x6345, 0x6346, 0x4355, 0xD132, 0x4E47, 0, 0xD133, 0x6348,
- 0x6347, 0xD134, 0, 0, 0, 0, 0, 0xD135,
- 0, 0, 0, 0xD136, 0, 0xD137, 0x3C6F, 0xD138,
- 0xD139, 0x634A, 0x3070, 0, 0xD13A, 0xD13B, 0, 0x634D,
- 0xD13C, 0xD13D, 0xD13E, 0x634B, 0x3254, 0x374E, 0x634C, 0x3946,
-};
-const unsigned short utf8_to_euc_E7A9[] = {
- 0x3972, 0, 0x4A66, 0x634E, 0xD13F, 0xD140, 0x4B54, 0xD141,
- 0xD142, 0x6350, 0, 0, 0xD143, 0x4051, 0x314F, 0x323A,
- 0x302C, 0, 0, 0, 0, 0xD144, 0xD145, 0x634F,
- 0, 0xD146, 0, 0, 0xD147, 0xD148, 0, 0xD149,
- 0xD14A, 0x6351, 0x6352, 0x3E77, 0, 0xD14B, 0, 0xD14C,
- 0, 0x6353, 0xD14D, 0x334F, 0, 0xD14E, 0, 0,
- 0x6355, 0, 0, 0, 0x376A, 0xD14F, 0x3566, 0,
- 0xD150, 0x6356, 0x3675, 0, 0, 0x6357, 0xD151, 0x407C,
-};
-const unsigned short utf8_to_euc_E7AA[] = {
- 0xD152, 0x464D, 0xD153, 0x4060, 0x3A75, 0xD154, 0xD155, 0,
- 0x6358, 0, 0xD156, 0xD157, 0, 0, 0, 0,
- 0xD158, 0xD159, 0x4362, 0x416B, 0xD15A, 0x635A, 0x635C, 0x6359,
- 0x635B, 0, 0, 0, 0, 0, 0xD15B, 0x3722,
- 0xD15C, 0, 0, 0xD15D, 0, 0, 0, 0,
- 0, 0x635D, 0x3726, 0, 0xD15E, 0, 0x3567, 0x4D52,
- 0x635F, 0, 0, 0xD15F, 0, 0xD160, 0x6360, 0,
- 0, 0xD161, 0x312E, 0xD162, 0xD163, 0, 0, 0x6363,
-};
-const unsigned short utf8_to_euc_E7AB[] = {
- 0, 0, 0, 0x3376, 0x6362, 0x6361, 0xD164, 0x6365,
- 0x635E, 0xD165, 0x6366, 0x4E29, 0xD166, 0x6367, 0xD167, 0x6368,
- 0, 0xD168, 0x5474, 0x636A, 0, 0x6369, 0, 0,
- 0, 0x636B, 0x636C, 0xD169, 0x4E35, 0x636D, 0, 0x706F,
- 0x3E4F, 0x636E, 0x636F, 0x3D57, 0, 0x4638, 0x6370, 0xF459,
- 0xD16A, 0xD16B, 0x4328, 0xD16C, 0xD16D, 0x6371, 0, 0x433C,
- 0x6372, 0xD16E, 0, 0, 0xD16F, 0, 0x3625, 0,
- 0x513F, 0x435D, 0x3C33, 0xD170, 0, 0xD171, 0xD172, 0x3448,
-};
-const unsigned short utf8_to_euc_E7AC[] = {
- 0, 0, 0x6373, 0, 0x6422, 0, 0x6376, 0xD173,
- 0x3568, 0, 0x6375, 0x6424, 0, 0, 0, 0x6374,
- 0, 0x3E50, 0, 0, 0xD174, 0, 0, 0,
- 0x6378, 0x6379, 0, 0x452B, 0, 0, 0x637A, 0xD175,
- 0x335E, 0, 0, 0xD176, 0, 0x3F5A, 0x4964, 0xD177,
- 0x637C, 0xD178, 0xD179, 0xD17A, 0x4268, 0xD17B, 0xD17C, 0xD17D,
- 0xD17E, 0xD221, 0, 0x6377, 0xD222, 0x637B, 0x637D, 0,
- 0, 0x3A7B, 0, 0, 0, 0xD223, 0, 0xD224,
-};
-const unsigned short utf8_to_euc_E7AD[] = {
- 0xD225, 0xD226, 0, 0, 0, 0x6426, 0x492E, 0xD227,
- 0x4826, 0x4579, 0, 0x365A, 0x6425, 0x6423, 0xD228, 0x4835,
- 0x637E, 0x435E, 0x457B, 0, 0x457A, 0xD229, 0x3A76, 0,
- 0, 0, 0, 0, 0, 0x6438, 0, 0,
- 0xD22A, 0, 0, 0, 0xD22B, 0x6428, 0xD22C, 0x642A,
- 0, 0xD22D, 0xD22E, 0, 0x642D, 0xD22F, 0x642E, 0xD230,
- 0x642B, 0x642C, 0xD231, 0xD232, 0x6429, 0x6427, 0, 0xD233,
- 0, 0, 0x6421, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E7AE[] = {
- 0, 0, 0, 0, 0xD234, 0, 0x4A4F, 0x3255,
- 0, 0xD235, 0, 0x6435, 0, 0x6432, 0xD236, 0x6437,
- 0xD237, 0xD238, 0x6436, 0, 0x4773, 0x4C27, 0xD239, 0x3B3B,
- 0x6430, 0x6439, 0x6434, 0xD23A, 0x6433, 0x642F, 0xD23B, 0x6431,
- 0xD23C, 0x3449, 0, 0, 0, 0xD23D, 0, 0,
- 0, 0, 0x433D, 0, 0xD23E, 0x407D, 0, 0xD23F,
- 0xD240, 0x4822, 0xD241, 0, 0x643E, 0xD242, 0xD243, 0,
- 0x4824, 0, 0xD244, 0xD245, 0xD246, 0xD247, 0, 0,
-};
-const unsigned short utf8_to_euc_E7AF[] = {
- 0x4061, 0x643B, 0xD248, 0, 0x484F, 0xD249, 0x643F, 0x4A53,
- 0xD24A, 0x435B, 0xD24B, 0x643A, 0x643C, 0, 0, 0x643D,
- 0, 0, 0, 0, 0xD24C, 0, 0xD24D, 0xD24E,
- 0, 0xD24F, 0xD250, 0xD251, 0, 0x6440, 0, 0,
- 0x3C44, 0, 0, 0, 0x4646, 0x6445, 0x6444, 0,
- 0xD252, 0x6441, 0xD253, 0, 0, 0x4F36, 0, 0,
- 0, 0, 0xD254, 0x644A, 0xD255, 0xD256, 0x644E, 0x644B,
- 0xD257, 0xD258, 0xD259, 0, 0xD25A, 0, 0xD25B, 0,
-};
-const unsigned short utf8_to_euc_E7B0[] = {
- 0x6447, 0xD25C, 0xD25D, 0xD25E, 0xD25F, 0, 0xD260, 0x6448,
- 0, 0xD261, 0, 0xD262, 0xD263, 0x644D, 0xD264, 0xD265,
- 0, 0x6442, 0x5255, 0x6449, 0x6443, 0, 0, 0x644C,
- 0, 0xD266, 0, 0xD267, 0, 0, 0, 0x6452,
- 0xD268, 0x344A, 0, 0x644F, 0, 0xD269, 0xD26A, 0x6450,
- 0xD26B, 0, 0x6451, 0x6454, 0xD26C, 0, 0, 0,
- 0, 0xD26D, 0, 0xD26E, 0xD26F, 0, 0xD270, 0x6453,
- 0x4876, 0xD271, 0xD272, 0, 0, 0x6455, 0x4E7C, 0x4A6D,
-};
-const unsigned short utf8_to_euc_E7B1[] = {
- 0x645A, 0, 0, 0x6457, 0, 0, 0xD273, 0,
- 0, 0, 0xD274, 0, 0x6456, 0x4052, 0, 0x6459,
- 0x645B, 0xD276, 0xD277, 0xD278, 0x6458, 0xD275, 0x645F, 0,
- 0x645C, 0xD279, 0xD27A, 0xD27B, 0xD27C, 0xD27D, 0xD27E, 0x645D,
- 0x6446, 0xD321, 0, 0xD322, 0x645E, 0x6460, 0, 0xD323,
- 0, 0xD324, 0, 0, 0x6461, 0xD325, 0xD326, 0,
- 0xD327, 0, 0xD328, 0x4A46, 0, 0x6462, 0, 0,
- 0, 0xD329, 0, 0, 0xD32A, 0xD32B, 0x4C62, 0,
-};
-const unsigned short utf8_to_euc_E7B2[] = {
- 0, 0x364E, 0x3729, 0x6463, 0, 0, 0xD32C, 0xD32D,
- 0, 0x4A34, 0, 0x3F68, 0, 0x4C30, 0, 0xD32E,
- 0x6464, 0, 0x4E33, 0, 0xD32F, 0x4774, 0, 0x4146,
- 0x4734, 0, 0, 0x3D4D, 0, 0, 0xD330, 0x3040,
- 0xD331, 0x6469, 0x6467, 0, 0x6465, 0x3421, 0xD332, 0x3E51,
- 0x646A, 0, 0, 0x6468, 0, 0x6466, 0x646E, 0,
- 0xD333, 0x646D, 0x646C, 0x646B, 0, 0, 0xD334, 0xD335,
- 0, 0x646F, 0xD336, 0xD337, 0xD338, 0x6470, 0x403A, 0xD339,
-};
-const unsigned short utf8_to_euc_E7B3[] = {
- 0x6471, 0, 0x6473, 0, 0xD33A, 0x6472, 0, 0xD33B,
- 0xD33C, 0xD33D, 0x3852, 0, 0, 0xD33E, 0x4138, 0xD33F,
- 0, 0, 0x6475, 0xD340, 0xD341, 0xD342, 0x457C, 0xD343,
- 0x6474, 0xD344, 0xD345, 0, 0x6476, 0xD346, 0x4A35, 0x416C,
- 0x3947, 0, 0x6477, 0, 0, 0, 0xD347, 0x4E48,
- 0, 0xD348, 0, 0xD349, 0, 0, 0, 0x6479,
- 0, 0, 0x647A, 0, 0x647B, 0xD34A, 0x647C, 0,
- 0x3B65, 0, 0x647D, 0x374F, 0, 0, 0x356A, 0,
-};
-const unsigned short utf8_to_euc_E7B4[] = {
- 0x352A, 0, 0x6521, 0xD34B, 0x4C73, 0x3948, 0x647E, 0xD34C,
- 0xD34D, 0xD34E, 0x6524, 0x4C66, 0, 0x473C, 0, 0xD34F,
- 0x4933, 0xD350, 0xD351, 0xD352, 0x3D63, 0x6523, 0xD353, 0x3C53,
- 0x3949, 0x3B66, 0x3569, 0x4A36, 0x6522, 0xD354, 0xD355, 0,
- 0x4147, 0x4B42, 0x3A77, 0xD356, 0, 0, 0xD357, 0,
- 0, 0, 0xD358, 0x3B67, 0x445D, 0xD359, 0x6527, 0x4E5F,
- 0x3A59, 0xD35A, 0x6528, 0x3F42, 0, 0x652A, 0, 0,
- 0, 0x3E52, 0x3A30, 0, 0xD35B, 0xD35C, 0xD35D, 0x6529,
-};
-const unsigned short utf8_to_euc_E7B5[] = {
- 0xD35E, 0xD35F, 0x3D2A, 0x383E, 0x4148, 0x6525, 0x652B, 0xD360,
- 0xD361, 0, 0, 0x6526, 0x3750, 0xD362, 0x652E, 0x6532,
- 0x376B, 0xD363, 0, 0xD364, 0, 0, 0x652D, 0xD365,
- 0, 0xD366, 0xD367, 0x6536, 0xD368, 0xD369, 0x394A, 0,
- 0, 0x4D6D, 0x303C, 0x6533, 0, 0xD36A, 0x356B, 0xD36B,
- 0x6530, 0, 0xD36C, 0, 0, 0, 0x6531, 0,
- 0xD36D, 0x457D, 0x652F, 0x652C, 0, 0x3328, 0x4064, 0,
- 0xD36E, 0x3828, 0xD36F, 0xD370, 0, 0x6538, 0, 0xD371,
-};
-const unsigned short utf8_to_euc_E7B6[] = {
- 0, 0xD372, 0xD373, 0xD374, 0, 0xD375, 0xD376, 0,
- 0xD377, 0x6535, 0, 0xD378, 0xD379, 0xD37A, 0, 0x6537,
- 0, 0xD37B, 0, 0x6534, 0, 0, 0xD37C, 0xD37D,
- 0, 0x3751, 0x4233, 0x6539, 0x416E, 0xD37E, 0xD421, 0x6546,
- 0xF45C, 0, 0x6542, 0x653C, 0, 0, 0xD422, 0xD423,
- 0, 0, 0xD424, 0x6540, 0x3C7A, 0x305D, 0x653B, 0x6543,
- 0x6547, 0x394B, 0x4C56, 0xD425, 0x4456, 0x653D, 0xD426, 0xD427,
- 0x6545, 0xD428, 0x653A, 0x433E, 0, 0x653F, 0x303D, 0x4C4A,
-};
-const unsigned short utf8_to_euc_E7B7[] = {
- 0, 0, 0xD429, 0xD42A, 0xD42B, 0xD42C, 0xD42D, 0x653E,
- 0, 0, 0x365B, 0x486C, 0xD42E, 0xD42F, 0xD430, 0x416D,
- 0, 0x4E50, 0x3D6F, 0, 0, 0x656E, 0xF45D, 0xD431,
- 0x6548, 0xD432, 0x407E, 0, 0x6544, 0x6549, 0x654B, 0,
- 0x4479, 0x654E, 0xD434, 0, 0x654A, 0xD435, 0xD436, 0,
- 0x4A54, 0x344B, 0xD437, 0xD438, 0x4C4B, 0xD439, 0, 0x305E,
- 0, 0xD43A, 0x654D, 0, 0x4E7D, 0xD43B, 0xD43C, 0,
- 0, 0xD43D, 0xD43E, 0x654C, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E7B8[] = {
- 0xD433, 0x316F, 0, 0, 0x466C, 0x654F, 0, 0,
- 0xD43F, 0x6556, 0x6550, 0x6557, 0, 0, 0, 0,
- 0xD440, 0xD441, 0x6553, 0, 0, 0xD442, 0, 0xD443,
- 0, 0, 0, 0x477B, 0xD444, 0xD445, 0x3C4A, 0x6555,
- 0xD446, 0x6552, 0x6558, 0x6551, 0, 0, 0x3D44, 0xD447,
- 0xD448, 0, 0, 0x4B25, 0xD449, 0xD44A, 0x3D4C, 0xD44B,
- 0, 0x6554, 0x6560, 0xD44C, 0, 0x655C, 0xD44D, 0x655F,
- 0, 0x655D, 0x6561, 0x655B, 0, 0x6541, 0x4053, 0xD44E,
-};
-const unsigned short utf8_to_euc_E7B9[] = {
- 0, 0x484B, 0, 0x655E, 0xD44F, 0xD450, 0x6559, 0xD451,
- 0, 0, 0x4121, 0x3752, 0, 0x3D2B, 0xD452, 0,
- 0xD453, 0, 0xD454, 0, 0x3F25, 0x4136, 0x6564, 0,
- 0xD455, 0x6566, 0x6567, 0, 0, 0x6563, 0x6565, 0xD456,
- 0, 0xD457, 0xD458, 0, 0, 0xD459, 0x655A, 0x6562,
- 0, 0x656A, 0x6569, 0xD45A, 0, 0x4B7A, 0xD45B, 0xD45C,
- 0x372B, 0, 0, 0xD45D, 0, 0, 0, 0,
- 0xD45E, 0x6568, 0, 0x656C, 0x656B, 0x656F, 0xD45F, 0x6571,
-};
-const unsigned short utf8_to_euc_E7BA[] = {
- 0, 0xD460, 0x3B3C, 0x656D, 0, 0, 0xD461, 0xD462,
- 0x6572, 0x6573, 0xD463, 0, 0x6574, 0xD464, 0x657A, 0x453B,
- 0x6576, 0xD465, 0x6575, 0x6577, 0x6578, 0xD466, 0x6579, 0,
- 0xD467, 0, 0xD468, 0x657B, 0x657C, 0xD469, 0xD46A, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E7BC[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x344C, 0,
- 0x657D, 0, 0x657E, 0xD46C, 0xD46B, 0xD46D, 0xD46E, 0xD46F,
-};
-const unsigned short utf8_to_euc_E7BD[] = {
- 0, 0, 0, 0xD470, 0xD471, 0x6621, 0, 0xD472,
- 0, 0, 0, 0, 0x6622, 0x6623, 0x6624, 0xD473,
- 0x6625, 0x6626, 0xD474, 0xD475, 0x6628, 0x6627, 0, 0,
- 0x6629, 0, 0, 0xD476, 0xD477, 0xD478, 0, 0x662A,
- 0x662B, 0xD479, 0, 0xD47A, 0xD47B, 0xD47C, 0xD47D, 0x662E,
- 0x662C, 0x662D, 0x3A61, 0x3753, 0, 0xD47E, 0x4356, 0,
- 0x4833, 0xD521, 0x3D70, 0, 0, 0x474D, 0, 0x486D,
- 0x662F, 0x586D, 0, 0, 0, 0xD522, 0xD523, 0xD524,
-};
-const unsigned short utf8_to_euc_E7BE[] = {
- 0xD525, 0, 0x6630, 0x6632, 0, 0x4D65, 0x6631, 0x6634,
- 0x6633, 0, 0x4D53, 0xD526, 0x6635, 0xD527, 0x487E, 0xD528,
- 0xD529, 0xD52A, 0, 0, 0x6636, 0, 0xD52B, 0xD52C,
- 0, 0, 0x6639, 0, 0xD52D, 0x6638, 0x6637, 0,
- 0, 0xD52E, 0xD52F, 0x663A, 0x3732, 0, 0xD530, 0,
- 0x4122, 0x3541, 0xD531, 0, 0, 0xD532, 0x663E, 0x663B,
- 0, 0, 0x663C, 0, 0xD533, 0, 0x663F, 0,
- 0x6640, 0x663D, 0, 0, 0xD534, 0x3129, 0, 0xD535,
-};
-const unsigned short utf8_to_euc_E7BF[] = {
- 0xD536, 0x3227, 0, 0xD537, 0, 0x6642, 0x6643, 0,
- 0xD538, 0, 0x6644, 0, 0x4D62, 0, 0xD539, 0xD53A,
- 0, 0, 0x3D2C, 0, 0x6646, 0x6645, 0, 0,
- 0, 0, 0, 0xD53B, 0, 0, 0, 0xD53C,
- 0x3F69, 0x6647, 0, 0xD53D, 0, 0xD53E, 0x6648, 0,
- 0xD53F, 0x6649, 0, 0x3465, 0xD540, 0, 0xD541, 0xD542,
- 0x344D, 0, 0xD543, 0x664A, 0, 0, 0, 0,
- 0, 0x664B, 0xD544, 0x4B5D, 0x4D63, 0xD545, 0xD546, 0xD547,
-};
-const unsigned short utf8_to_euc_E880[] = {
- 0x4D54, 0x4F37, 0, 0x394D, 0x664E, 0x3C54, 0x664D, 0xD548,
- 0xD549, 0, 0xD54A, 0x664F, 0x3C29, 0xD54B, 0xD54C, 0xD54D,
- 0x4251, 0xD54E, 0x6650, 0xD54F, 0xD550, 0x394C, 0xD551, 0x4C57,
- 0x6651, 0x6652, 0, 0, 0x6653, 0xD552, 0xD553, 0xD554,
- 0xD555, 0x6654, 0, 0, 0xD556, 0, 0xD557, 0,
- 0x6655, 0, 0, 0, 0xD558, 0, 0xD559, 0,
- 0xD55A, 0, 0, 0x3C2A, 0xD55B, 0xD55C, 0x4C6D, 0xD55D,
- 0, 0xD55E, 0xD55F, 0x6657, 0xD560, 0x433F, 0xD561, 0x6656,
-};
-const unsigned short utf8_to_euc_E881[] = {
- 0xD562, 0, 0, 0, 0xD563, 0, 0x6659, 0,
- 0, 0, 0x6658, 0, 0, 0, 0, 0,
- 0, 0, 0x665A, 0, 0, 0, 0x403B, 0,
- 0x665B, 0, 0x665C, 0, 0, 0, 0x4A39, 0x665D,
- 0xD564, 0x416F, 0x665E, 0, 0xD565, 0, 0xD566, 0,
- 0x665F, 0, 0, 0, 0, 0xD567, 0, 0x4E7E,
- 0x6662, 0xD568, 0x6661, 0x6660, 0x4430, 0xD569, 0x6663, 0x3F26,
- 0, 0x6664, 0, 0, 0, 0x6665, 0x4F38, 0x6666,
-};
-const unsigned short utf8_to_euc_E882[] = {
- 0, 0xD56A, 0, 0, 0x6667, 0x6669, 0x6668, 0x4825,
- 0xD56B, 0x4679, 0, 0x4F3E, 0x4829, 0, 0xD56C, 0,
- 0, 0, 0, 0x666B, 0, 0, 0x3E53, 0,
- 0x492A, 0, 0x666C, 0x666A, 0xD56D, 0x344E, 0xD56E, 0,
- 0, 0x3854, 0x3B68, 0, 0, 0x486E, 0xD56F, 0xD570,
- 0, 0x382A, 0x4B43, 0xD571, 0x666F, 0x666D, 0, 0x394E,
- 0, 0x394F, 0x3069, 0, 0x3A68, 0, 0, 0,
- 0xD572, 0xD573, 0x4759, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E883[] = {
- 0, 0, 0, 0x305F, 0x6674, 0, 0x4340, 0,
- 0xD574, 0, 0, 0, 0x4758, 0xD575, 0x425B, 0xD576,
- 0, 0, 0xD577, 0, 0xD578, 0xD579, 0x6676, 0xD57A,
- 0xD57B, 0x6672, 0x6675, 0x6670, 0, 0x6673, 0x4B26, 0,
- 0xD57C, 0x3855, 0, 0, 0x307D, 0x6671, 0, 0,
- 0, 0, 0, 0, 0, 0xD57D, 0xD57E, 0x6678,
- 0xD621, 0x6679, 0xD622, 0xD623, 0x4639, 0, 0xD624, 0,
- 0x363B, 0xD625, 0xD626, 0, 0x6726, 0x473D, 0xD627, 0,
-};
-const unsigned short utf8_to_euc_E884[] = {
- 0, 0, 0x3B69, 0xD628, 0, 0x363C, 0x4048, 0x4F46,
- 0x4C2E, 0x6677, 0x4054, 0xD629, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xD62A, 0xD62B,
- 0xD62C, 0, 0x3553, 0x667A, 0xD62D, 0, 0xD62E, 0,
- 0xD62F, 0, 0, 0x667C, 0xD630, 0, 0, 0xD631,
- 0, 0x667B, 0, 0, 0xD632, 0, 0, 0x667D,
- 0xD633, 0x4326, 0, 0x473E, 0, 0xD634, 0, 0,
- 0, 0x4431, 0xD635, 0, 0xD636, 0, 0x6723, 0,
-};
-const unsigned short utf8_to_euc_E885[] = {
- 0, 0, 0, 0, 0, 0xD637, 0x6722, 0xD638,
- 0, 0, 0xD639, 0x667E, 0xD63A, 0, 0x3F55, 0,
- 0x4965, 0x6725, 0xD63B, 0x6724, 0x3950, 0x4F53, 0, 0xD63C,
- 0, 0, 0, 0, 0, 0, 0, 0x6735,
- 0xD63D, 0xD63E, 0, 0, 0, 0x6729, 0x672A, 0xD63F,
- 0xD640, 0xD641, 0, 0x3C70, 0, 0xD642, 0x6728, 0xD643,
- 0x3978, 0x6727, 0, 0, 0x672B, 0, 0, 0xD644,
- 0x4432, 0x4A22, 0x4123, 0, 0, 0, 0, 0x425C,
-};
-const unsigned short utf8_to_euc_E886[] = {
- 0x672F, 0xD645, 0x6730, 0x672C, 0xD647, 0xD648, 0xD649, 0,
- 0x672D, 0, 0x672E, 0xD64A, 0, 0, 0xD64B, 0x3951,
- 0xD646, 0, 0, 0x6736, 0, 0x6732, 0xD64C, 0,
- 0xD64D, 0, 0x4966, 0xD64E, 0x4B6C, 0x4928, 0xD64F, 0,
- 0x6731, 0, 0xD650, 0x6734, 0x6733, 0, 0, 0,
- 0x4B44, 0x6737, 0, 0, 0, 0, 0xD651, 0,
- 0x6738, 0, 0xD652, 0x4137, 0xD653, 0x6739, 0, 0,
- 0x673B, 0, 0x673F, 0xD654, 0, 0x673C, 0x673A, 0x473F,
-};
-const unsigned short utf8_to_euc_E887[] = {
- 0x673D, 0, 0x673E, 0xD656, 0, 0xD657, 0x3232, 0,
- 0x6745, 0x6740, 0xD658, 0xD655, 0, 0x6741, 0xD659, 0xD65A,
- 0, 0x6742, 0, 0x4221, 0, 0xD65B, 0, 0xD65C,
- 0x6744, 0x6743, 0x6746, 0xD65D, 0, 0xD65E, 0xD65F, 0x6747,
- 0x6748, 0xD660, 0, 0x3F43, 0xD661, 0x3269, 0, 0x6749,
- 0x4E57, 0, 0x3C2B, 0xD662, 0xD663, 0x3D2D, 0, 0,
- 0xD664, 0xD665, 0xD666, 0x3B6A, 0x4357, 0xD667, 0xD668, 0,
- 0xD669, 0xD66A, 0x674A, 0x674B, 0x3131, 0xD66B, 0x674C, 0xD66C,
-};
-const unsigned short utf8_to_euc_E888[] = {
- 0xD66D, 0x674D, 0x674E, 0xD66E, 0, 0x674F, 0, 0x6750,
- 0x363D, 0x5A2A, 0x6751, 0, 0x4065, 0x6752, 0x3C4B, 0xD66F,
- 0x6753, 0, 0x5030, 0xD670, 0xD671, 0, 0x6754, 0x4A5E,
- 0x345C, 0xD672, 0xD673, 0x4124, 0x3D58, 0xD674, 0x4971, 0x3D2E,
- 0, 0xD675, 0xD676, 0, 0, 0, 0, 0,
- 0xD677, 0x6755, 0x3952, 0x6756, 0x484C, 0, 0x6764, 0,
- 0, 0, 0xD678, 0x6758, 0xD679, 0x4249, 0x4775, 0x383F,
- 0x6757, 0x4125, 0xD67A, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E889[] = {
- 0x6759, 0, 0, 0xD67B, 0xD67C, 0xD67D, 0xD67E, 0x447A,
- 0, 0, 0, 0xD721, 0, 0, 0xD722, 0xD723,
- 0, 0xD724, 0, 0, 0, 0, 0xD725, 0,
- 0x675B, 0x675A, 0x675D, 0, 0xD726, 0x675C, 0, 0x675E,
- 0xD727, 0, 0x6760, 0xD728, 0x675F, 0, 0x344F, 0xD729,
- 0x6761, 0, 0x6762, 0x6763, 0, 0xD72A, 0x3A31, 0x4E49,
- 0, 0x6765, 0x3F27, 0, 0xD72B, 0, 0x3170, 0x6766,
- 0x6767, 0, 0, 0xD72C, 0, 0xD72D, 0x6768, 0xD72E,
-};
-const unsigned short utf8_to_euc_E88A[] = {
- 0xD72F, 0xD730, 0, 0xD731, 0xD732, 0, 0, 0xD733,
- 0, 0xD734, 0xD735, 0x3072, 0, 0x6769, 0xD736, 0,
- 0, 0xD737, 0x676A, 0, 0xD738, 0, 0xD739, 0,
- 0xD73A, 0x4967, 0xD73B, 0xD73C, 0, 0x3C47, 0, 0x676C,
- 0xD73D, 0xD73E, 0, 0xD73F, 0xD740, 0x3329, 0x3032, 0xD741,
- 0xD742, 0xD743, 0xD744, 0x676B, 0x676E, 0x474E, 0xD745, 0x3F44,
- 0xD746, 0x3256, 0xD747, 0x4B27, 0xD748, 0, 0, 0xD749,
- 0x375D, 0x365C, 0xD74A, 0x676D, 0xD74B, 0x326A, 0xD74C, 0xD74D,
-};
-const unsigned short utf8_to_euc_E88B[] = {
- 0, 0, 0, 0, 0, 0x3423, 0xD74E, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xD74F, 0x3171, 0x6772, 0x4E6A, 0x425D, 0xD750, 0, 0x4944,
- 0, 0x677E, 0xD751, 0x3257, 0x677C, 0, 0x677A, 0x6771,
- 0xD752, 0x676F, 0xD753, 0x6770, 0xD754, 0x3C63, 0x366C, 0x4377,
- 0xD755, 0, 0xD756, 0x4651, 0, 0xD757, 0, 0xD758,
- 0, 0x3151, 0, 0x6774, 0x6773, 0, 0xD759, 0xD75A,
- 0, 0x6779, 0x6775, 0x6778, 0, 0xD75B, 0xD75C, 0,
-};
-const unsigned short utf8_to_euc_E88C[] = {
- 0xD75D, 0xD75E, 0x4C50, 0x6777, 0x3258, 0x337D, 0x677B, 0xD75F,
- 0xD760, 0x677D, 0xD761, 0xD762, 0, 0, 0x3754, 0,
- 0, 0, 0, 0, 0, 0, 0x6823, 0x682C,
- 0x682D, 0, 0, 0xD764, 0x302B, 0xD765, 0xD766, 0xD767,
- 0, 0xD768, 0xD769, 0x6834, 0, 0, 0, 0,
- 0x3071, 0, 0, 0x682B, 0xD76A, 0xD76B, 0xD76C, 0x682A,
- 0xD76D, 0x6825, 0x6824, 0xD76E, 0x6822, 0x6821, 0x4363, 0xD76F,
- 0x427B, 0x6827, 0xD770, 0, 0xD771, 0xD772, 0, 0,
-};
-const unsigned short utf8_to_euc_E88D[] = {
- 0x6826, 0, 0xD773, 0xD774, 0xD775, 0x6829, 0, 0xD776,
- 0, 0x4170, 0x3755, 0, 0, 0xD777, 0xD778, 0x3141,
- 0x6828, 0xD779, 0x3953, 0xD83E, 0xD763, 0xD77A, 0xD77B, 0xD77C,
- 0x4171, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xF45F, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xD77D, 0, 0, 0x683A, 0, 0x683B, 0, 0x3259,
- 0xD77E, 0, 0, 0x322E, 0x6838, 0xD821, 0, 0xD822,
-};
-const unsigned short utf8_to_euc_E88E[] = {
- 0xD823, 0, 0xD824, 0, 0xD825, 0x682E, 0xD826, 0x6836,
- 0, 0x683D, 0x6837, 0, 0, 0xD827, 0x6835, 0,
- 0, 0, 0xD828, 0x6776, 0xD829, 0xD82A, 0x6833, 0,
- 0xD82B, 0xD82C, 0x682F, 0xD82D, 0xD82E, 0xD82F, 0x3450, 0x6831,
- 0x683C, 0, 0x6832, 0, 0, 0, 0xD830, 0xD831,
- 0x683E, 0xD832, 0x6830, 0x477C, 0xD833, 0xD84C, 0, 0,
- 0, 0x4D69, 0, 0, 0, 0x6839, 0, 0,
- 0, 0, 0, 0, 0, 0x684F, 0xD834, 0xD835,
-};
-const unsigned short utf8_to_euc_E88F[] = {
- 0xD836, 0x6847, 0, 0, 0, 0x3F7B, 0, 0xD837,
- 0, 0xD838, 0x3546, 0, 0x365D, 0, 0x6842, 0xD839,
- 0xD83A, 0xD83B, 0, 0x325B, 0xD83C, 0, 0x3E54, 0,
- 0x6845, 0, 0, 0, 0x3A5A, 0xD83D, 0, 0x4551,
- 0x684A, 0, 0, 0, 0, 0, 0, 0,
- 0xD83F, 0x4A6E, 0xD840, 0x6841, 0, 0, 0, 0x325A,
- 0x3856, 0x4929, 0x684B, 0, 0x683F, 0, 0xD841, 0x6848,
- 0xD842, 0xD843, 0, 0x6852, 0xD844, 0x6843, 0, 0,
-};
-const unsigned short utf8_to_euc_E890[] = {
- 0, 0xD845, 0, 0x6844, 0x463A, 0, 0xD846, 0x6849,
- 0, 0, 0xD847, 0x6846, 0x4B28, 0x684C, 0x3060, 0xD848,
- 0, 0xD849, 0, 0x6840, 0, 0xD84A, 0, 0,
- 0, 0xD84B, 0, 0, 0, 0, 0, 0,
- 0x684E, 0, 0x684D, 0, 0, 0, 0, 0,
- 0, 0x476B, 0x6854, 0, 0x685F, 0, 0, 0xD84D,
- 0, 0x337E, 0, 0, 0, 0x6862, 0, 0,
- 0x6850, 0xD84E, 0, 0, 0x6855, 0x4D6E, 0, 0,
-};
-const unsigned short utf8_to_euc_E891[] = {
- 0, 0, 0, 0, 0, 0xD84F, 0x685E, 0xD850,
- 0xD851, 0x4D55, 0xD852, 0, 0, 0xD853, 0x4E2A, 0xD854,
- 0, 0xD855, 0xD856, 0, 0, 0, 0xD857, 0x4378,
- 0xD858, 0xD859, 0xD85A, 0x336B, 0xD85B, 0, 0, 0,
- 0xD85C, 0x4972, 0x6864, 0x4621, 0xD85D, 0xD85E, 0x3031, 0xD85F,
- 0, 0x685D, 0xD860, 0x6859, 0x4172, 0x6853, 0x685B, 0x6860,
- 0xD861, 0x472C, 0, 0xD862, 0xD863, 0x302A, 0xD864, 0x6858,
- 0xD865, 0x6861, 0x4978, 0, 0xD866, 0xD867, 0, 0,
-};
-const unsigned short utf8_to_euc_E892[] = {
- 0, 0xD868, 0x685C, 0, 0x6857, 0xD869, 0, 0,
- 0, 0, 0, 0x3E55, 0, 0, 0, 0,
- 0x3D2F, 0, 0xD86A, 0xD86B, 0x3C2C, 0xD86C, 0, 0,
- 0, 0x4C58, 0, 0, 0x4947, 0, 0xD86D, 0x6867,
- 0, 0x6870, 0, 0, 0, 0, 0xD86E, 0,
- 0xD86F, 0xD870, 0xD871, 0, 0, 0x685A, 0, 0xD872,
- 0, 0xD873, 0x3377, 0, 0xD874, 0, 0, 0,
- 0x3E78, 0x6865, 0xD875, 0x686A, 0x4173, 0xD876, 0xD877, 0x6866,
-};
-const unsigned short utf8_to_euc_E893[] = {
- 0xD878, 0x686D, 0xD879, 0, 0x435F, 0, 0x686E, 0xD87A,
- 0xD87B, 0x4D56, 0x6863, 0x3338, 0xD87C, 0x6869, 0, 0xD87D,
- 0x686C, 0x4C2C, 0, 0xD87E, 0, 0, 0x686F, 0,
- 0, 0x6868, 0x686B, 0, 0xD921, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xD922,
- 0, 0, 0xD923, 0, 0x4B29, 0, 0x4F21, 0xD924,
- 0xD925, 0xD926, 0xD927, 0, 0x6873, 0, 0, 0xD928,
- 0, 0, 0xD92A, 0xD92B, 0x687A, 0xD92C, 0, 0x6872,
-};
-const unsigned short utf8_to_euc_E894[] = {
- 0x3C43, 0, 0xD92D, 0xD92E, 0, 0, 0x6851, 0xD92F,
- 0, 0, 0, 0, 0xD930, 0, 0xD931, 0,
- 0xD932, 0x4A4E, 0, 0x4C22, 0x6879, 0x6878, 0, 0x6874,
- 0x6875, 0, 0x3136, 0, 0xD933, 0, 0xD934, 0x6877,
- 0, 0x6871, 0xD935, 0xD936, 0xD937, 0xD938, 0x4455, 0xD939,
- 0, 0, 0xD93A, 0xD93B, 0x6876, 0x307E, 0, 0xD93C,
- 0, 0, 0xD929, 0xD93D, 0xD93E, 0x4222, 0xD93F, 0,
- 0, 0, 0, 0, 0, 0x4A43, 0, 0xD940,
-};
-const unsigned short utf8_to_euc_E895[] = {
- 0x687B, 0x6921, 0, 0x4859, 0, 0, 0xD941, 0,
- 0x687E, 0x3E56, 0x3C49, 0x6923, 0, 0, 0x363E, 0xD942,
- 0xD943, 0xD944, 0xD945, 0xD946, 0, 0x6924, 0xD947, 0x4979,
- 0x687D, 0xD948, 0x6856, 0, 0xD949, 0xD94A, 0xD94B, 0xD94C,
- 0xD94D, 0xD94E, 0xD94F, 0x687C, 0xD950, 0, 0, 0,
- 0x4F4F, 0x4622, 0x4973, 0xD951, 0, 0x692B, 0, 0xD952,
- 0, 0, 0, 0, 0, 0, 0, 0x6931,
- 0, 0xD953, 0xD954, 0xD955, 0, 0xD956, 0x6932, 0xD957,
-};
-const unsigned short utf8_to_euc_E896[] = {
- 0x6925, 0xD958, 0, 0, 0x4776, 0xD959, 0xD95A, 0x692F,
- 0x6927, 0xD95B, 0x6929, 0xD95C, 0xD95D, 0, 0, 0xD95E,
- 0x6933, 0x6928, 0, 0xD95F, 0x692C, 0, 0, 0x3172,
- 0xD960, 0x4665, 0, 0x692D, 0x6930, 0xD961, 0, 0xD962,
- 0xD963, 0, 0xD964, 0, 0x6926, 0xD965, 0x4126, 0xD966,
- 0x692A, 0x3B27, 0x3F45, 0x3730, 0x4C74, 0xD974, 0x4C79, 0x3D72,
- 0xF461, 0, 0, 0, 0xD967, 0, 0xD968, 0xD969,
- 0xD96A, 0x6937, 0x6935, 0, 0xD96B, 0xD96C, 0xD96D, 0xD96E,
-};
-const unsigned short utf8_to_euc_E897[] = {
- 0, 0x4F4E, 0xD96F, 0, 0, 0, 0, 0xD970,
- 0, 0x6934, 0xD971, 0xD972, 0, 0x4D75, 0xD973, 0x6936,
- 0x6938, 0, 0, 0, 0, 0x6939, 0, 0,
- 0xD975, 0, 0xD976, 0, 0x693C, 0x693A, 0, 0xD977,
- 0xD978, 0, 0, 0, 0x4623, 0x693B, 0xD979, 0,
- 0xD97A, 0x484D, 0x692E, 0, 0, 0xD97B, 0, 0,
- 0, 0, 0, 0xD97C, 0, 0, 0xD97D, 0x3D73,
- 0, 0x693D, 0x6942, 0x4174, 0xD97E, 0, 0x6941, 0xDA21,
-};
-const unsigned short utf8_to_euc_E898[] = {
- 0xDA22, 0, 0x6922, 0, 0xDA23, 0xDA24, 0x6943, 0x4149,
- 0, 0, 0x693E, 0x6940, 0, 0xDA25, 0xDA26, 0,
- 0xDA27, 0xDA28, 0xDA29, 0x693F, 0, 0, 0x5D31, 0x5D22,
- 0xDA2A, 0xDA2B, 0x6945, 0xDA2C, 0, 0, 0xDA2D, 0,
- 0, 0xDA2E, 0x6944, 0, 0, 0, 0, 0xDA2F,
- 0, 0xDA30, 0, 0, 0, 0x4D76, 0, 0x623C,
- 0x6946, 0, 0, 0, 0, 0, 0xDA31, 0,
- 0xDA32, 0, 0xDA33, 0, 0xDA34, 0xDA35, 0, 0x6947,
-};
-const unsigned short utf8_to_euc_E899[] = {
- 0xDA36, 0xB866, 0xDA37, 0, 0, 0, 0xDA38, 0,
- 0, 0, 0, 0, 0, 0x6948, 0x3857, 0,
- 0x3554, 0, 0xDA39, 0xDA3A, 0x694A, 0x515D, 0xDA3B, 0xDA3C,
- 0xDA3D, 0xDA3E, 0x3575, 0, 0x4E3A, 0xDA3F, 0x3673, 0x694B,
- 0xDA40, 0xDA41, 0xDA42, 0xDA43, 0xDA44, 0, 0, 0x694C,
- 0, 0xDA45, 0, 0x436E, 0xDA46, 0, 0, 0xDA47,
- 0, 0x694D, 0, 0, 0, 0xDA48, 0xDA49, 0xDA4A,
- 0, 0x467A, 0xDA4B, 0x303A, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E89A[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xDA6D, 0, 0x3263, 0x6952, 0x6953, 0xDA4C, 0, 0,
- 0, 0xDA4D, 0, 0x694E, 0, 0x3B3D, 0xDA4E, 0,
- 0xDA4F, 0, 0xDA50, 0, 0xDA51, 0, 0, 0,
- 0, 0xDA52, 0, 0x694F, 0x4742, 0, 0xDA53, 0xDA54,
- 0xDA55, 0x6950, 0x6951, 0x695B, 0, 0xDA56, 0, 0x6955,
- 0x6958, 0xDA57, 0, 0xDA58, 0xDA59, 0xDA5A, 0x6954, 0xDA5B,
- 0xDA5C, 0xDA5D, 0, 0, 0, 0, 0, 0xDA5E,
-};
-const unsigned short utf8_to_euc_E89B[] = {
- 0xDA5F, 0xDA60, 0, 0xDA61, 0x6956, 0xDA62, 0x6957, 0x3C58,
- 0, 0x6959, 0, 0x4341, 0, 0x3756, 0x3342, 0,
- 0, 0xDA63, 0xDA64, 0, 0x695C, 0xDA65, 0, 0xDA66,
- 0, 0x333F, 0xDA67, 0x6961, 0xDA68, 0, 0x695D, 0x6960,
- 0xDA69, 0, 0, 0xDA6A, 0x483A, 0xDA6B, 0, 0xDA6C,
- 0, 0x695E, 0, 0, 0x695F, 0x4948, 0x485A, 0x6962,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x427D, 0x696C, 0xDA6E, 0x6968, 0xDA6F, 0xDA70, 0x326B, 0,
-};
-const unsigned short utf8_to_euc_E89C[] = {
- 0x6966, 0, 0x4B2A, 0x6967, 0xDA71, 0xDA72, 0x6964, 0xDA73,
- 0x6965, 0x696A, 0x696D, 0xDA74, 0, 0x696B, 0xDA75, 0xDA76,
- 0xDA77, 0x6969, 0x6963, 0xDA78, 0xDA79, 0, 0, 0,
- 0x4358, 0xDA7A, 0x6974, 0, 0x4C2A, 0, 0xDA7B, 0xDA7C,
- 0, 0xDA7D, 0, 0xDA7E, 0, 0x6972, 0, 0,
- 0xDB21, 0x6973, 0, 0, 0, 0, 0xDB22, 0xDB23,
- 0, 0xDB24, 0xDB25, 0, 0x696E, 0, 0, 0x6970,
- 0, 0xDB26, 0xDB27, 0x6971, 0xDB28, 0xDB29, 0xDB2A, 0x696F,
-};
-const unsigned short utf8_to_euc_E89D[] = {
- 0xDB2B, 0, 0, 0xDB2C, 0, 0xDB2D, 0, 0,
- 0, 0x4066, 0, 0x4F39, 0x6978, 0xDB2E, 0x6979, 0,
- 0, 0, 0, 0x6A21, 0, 0x3F2A, 0, 0x697B,
- 0xDB2F, 0x697E, 0, 0, 0, 0xDB30, 0, 0x6976,
- 0x6975, 0xDB31, 0, 0x6A22, 0xDB32, 0xDB33, 0x325C, 0,
- 0x697C, 0, 0x6A23, 0, 0, 0, 0x697D, 0xDB34,
- 0, 0xDB35, 0xDB36, 0, 0x697A, 0, 0x4433, 0,
- 0x6977, 0, 0, 0xDB37, 0, 0, 0, 0x4768,
-};
-const unsigned short utf8_to_euc_E89E[] = {
- 0, 0, 0x6A27, 0xDB38, 0xDB39, 0xDB3A, 0xDB3B, 0xDB3C,
- 0xDB3D, 0xDB3E, 0, 0xDB3F, 0xDB40, 0x4D3B, 0, 0,
- 0xDB41, 0, 0, 0xDB42, 0, 0xDB43, 0, 0xDB44,
- 0xDB45, 0xDB46, 0, 0, 0, 0, 0xDB47, 0x6A26,
- 0xDB48, 0, 0x6A25, 0xDB49, 0, 0, 0, 0xDB4A,
- 0, 0, 0, 0x6A2E, 0xDB4B, 0xDB4C, 0xDB4D, 0x6A28,
- 0, 0xDB4E, 0, 0x6A30, 0, 0xDB4F, 0, 0,
- 0, 0, 0x4D66, 0x6A33, 0, 0x6A2A, 0xDB50, 0xDB51,
-};
-const unsigned short utf8_to_euc_E89F[] = {
- 0x6A2B, 0xDB52, 0, 0, 0x6A2F, 0, 0x6A32, 0x6A31,
- 0xDB53, 0xDB54, 0xDB55, 0x6A29, 0, 0, 0xDB56, 0,
- 0x6A2C, 0, 0x6A3D, 0, 0, 0xDB57, 0xDB58, 0,
- 0, 0xDB59, 0xDB5A, 0, 0xDB5B, 0, 0, 0xDB5C,
- 0x6A36, 0, 0xDB5D, 0xDB5E, 0xDB5F, 0, 0, 0,
- 0, 0, 0xDB60, 0xDB61, 0, 0xDB62, 0, 0x6A34,
- 0, 0xDB63, 0x6A35, 0xDB64, 0, 0, 0x6A3A, 0x6A3B,
- 0xDB65, 0x332A, 0xDB66, 0x3542, 0, 0, 0x6A39, 0xDB67,
-};
-const unsigned short utf8_to_euc_E8A0[] = {
- 0, 0xDB68, 0, 0xDB69, 0, 0x6A24, 0xDB6A, 0xF464,
- 0, 0xDB6B, 0xDB6C, 0xDB6D, 0, 0x6A38, 0x6A3C, 0x6A37,
- 0xDB6E, 0x6A3E, 0xDB70, 0xDB71, 0xDB72, 0x6A40, 0x6A3F, 0,
- 0xDB73, 0xDB6F, 0xDB74, 0xDB75, 0xDB76, 0, 0xDB77, 0xDB78,
- 0, 0x6A42, 0x6A41, 0x695A, 0, 0, 0, 0x6A46,
- 0xDB79, 0, 0, 0, 0, 0xDB7A, 0xDB7B, 0,
- 0xDB7C, 0x6A43, 0xDB7D, 0, 0, 0xDB7E, 0x6A44, 0,
- 0, 0x6A45, 0xDC21, 0x6A47, 0xDC22, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E8A1[] = {
- 0x376C, 0xDC23, 0x6A49, 0xDC24, 0x6A48, 0xDC25, 0x3D30, 0,
- 0xDC26, 0xDC27, 0xDC28, 0xDC29, 0x3954, 0x5E27, 0xDC2A, 0,
- 0, 0xDC2B, 0x6A4A, 0x3D51, 0, 0xDC2C, 0xDC2D, 0x3339,
- 0xDC2E, 0x6A4B, 0xDC2F, 0x3152, 0xDC30, 0x3E57, 0x6A4C, 0xDC31,
- 0xDC32, 0x3955, 0x6A4D, 0x3061, 0xDC33, 0, 0, 0,
- 0x493D, 0xDC34, 0, 0x6A4E, 0, 0, 0, 0,
- 0x3F6A, 0xDC35, 0x6A55, 0, 0, 0x6A52, 0, 0x436F,
- 0, 0xDC36, 0, 0xDC37, 0, 0x6A53, 0x6A50, 0x365E,
-};
-const unsigned short utf8_to_euc_E8A2[] = {
- 0xDC38, 0x6A4F, 0x6A56, 0, 0, 0, 0, 0,
- 0x3736, 0, 0, 0x425E, 0, 0x6A5C, 0, 0,
- 0, 0, 0x6A58, 0, 0, 0, 0x4235, 0x6A57,
- 0xDC39, 0x6A5A, 0xDC3A, 0xDC3B, 0xDC3C, 0, 0x6A51, 0xDC3D,
- 0xDC3E, 0, 0x6A5B, 0, 0x6A5D, 0, 0, 0,
- 0xDC3F, 0, 0xDC40, 0x486F, 0, 0, 0x6A59, 0,
- 0x6A5E, 0x6A60, 0, 0, 0x3853, 0x6A54, 0, 0x3041,
- 0, 0, 0xDC41, 0, 0, 0xDC42, 0xDC43, 0x6A5F,
-};
-const unsigned short utf8_to_euc_E8A3[] = {
- 0xDC44, 0x3A5B, 0x4E76, 0x6A61, 0x6A62, 0x4175, 0, 0,
- 0, 0, 0xDC45, 0xDC46, 0xDC47, 0xDC48, 0xDC49, 0x4E22,
- 0, 0xDC4A, 0xDC4B, 0xDC4C, 0x6A63, 0x4D35, 0, 0,
- 0x6A64, 0x6A65, 0, 0xDC4D, 0x4A64, 0x6A66, 0xDC4E, 0x3A40,
- 0, 0x4E23, 0, 0, 0, 0, 0, 0xDC4F,
- 0x6A6B, 0, 0, 0, 0, 0, 0, 0xDC50,
- 0xDC51, 0xDC52, 0x6A6C, 0x3E58, 0x6A6A, 0xDC53, 0, 0xDC54,
- 0x4D67, 0x6A67, 0, 0, 0x6A69, 0x403D, 0x3F7E, 0,
-};
-const unsigned short utf8_to_euc_E8A4[] = {
- 0, 0xDC55, 0x6A68, 0, 0x6A6D, 0, 0xDC56, 0x4A23,
- 0, 0, 0x6A6F, 0, 0x6A6E, 0xDC57, 0xDC58, 0xDC59,
- 0x336C, 0, 0x4B2B, 0x6A70, 0, 0xDC5A, 0xDC5B, 0,
- 0xDC5C, 0xDC5D, 0xDC5E, 0, 0xDC5F, 0x6A7C, 0x6A72, 0,
- 0xDC60, 0, 0, 0, 0, 0x6A73, 0xDC61, 0xDC62,
- 0xDC63, 0, 0x6A74, 0x6A75, 0, 0, 0, 0,
- 0xDC64, 0xDC65, 0xDC66, 0, 0, 0xDC67, 0x6A79, 0,
- 0x6A7A, 0xDC68, 0xDC69, 0x6A78, 0, 0, 0xDC6A, 0,
-};
-const unsigned short utf8_to_euc_E8A5[] = {
- 0xDC6B, 0x6A76, 0xDC6C, 0x6A71, 0x6A77, 0xDC6D, 0xDC6E, 0,
- 0, 0xDC6F, 0, 0, 0x6A7B, 0x7037, 0, 0xDC70,
- 0, 0, 0xDC71, 0, 0, 0, 0x3228, 0xDC72,
- 0, 0, 0xDC73, 0xDC74, 0xDC75, 0, 0x6A7E, 0x365F,
- 0x6A7D, 0xDC76, 0xDC77, 0xDC78, 0x6B22, 0, 0x6B21, 0,
- 0, 0, 0x6B24, 0xDC79, 0, 0x6B23, 0xDC7A, 0x6B25,
- 0xDC7B, 0, 0x3D31, 0xDC7C, 0x6B26, 0xDC7D, 0, 0x6B27,
- 0, 0, 0xDC7E, 0xDD21, 0xDD22, 0xDD23, 0x6B28, 0x403E,
-};
-const unsigned short utf8_to_euc_E8A6[] = {
- 0, 0x4D57, 0, 0x6B29, 0, 0, 0x4A24, 0x4746,
- 0x6B2A, 0xDD24, 0x6B2B, 0x382B, 0, 0xDD25, 0, 0x352C,
- 0xDD26, 0, 0, 0x6B2C, 0xDD27, 0xDD28, 0x3B6B, 0x4741,
- 0x6B2D, 0, 0x3350, 0xDD29, 0xDD2A, 0, 0, 0xDD2B,
- 0xDD2C, 0x6B2E, 0, 0, 0, 0xDD2D, 0x6B30, 0x4D77,
- 0, 0x6B2F, 0x3F46, 0, 0x6B31, 0, 0, 0x6B32,
- 0xDD2E, 0, 0x6B33, 0x3451, 0xDD2F, 0xDD30, 0xDD31, 0xDD32,
- 0, 0, 0x6B34, 0, 0xDD33, 0x6B35, 0, 0x6B36,
-};
-const unsigned short utf8_to_euc_E8A7[] = {
- 0x6B37, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x3351, 0, 0xDD34, 0xDD35, 0xDD36, 0xDD37,
- 0xDD38, 0, 0x6B38, 0, 0x6B39, 0x6B3A, 0, 0,
- 0, 0, 0, 0x3272, 0, 0xDD39, 0x3F28, 0x6B3B,
- 0, 0xDD3A, 0, 0xDD3B, 0, 0xDD3C, 0, 0,
- 0, 0xDD3D, 0, 0xDD3E, 0x6B3C, 0, 0xDD3F, 0,
- 0x6B3D, 0xDD40, 0, 0, 0, 0xDD41, 0, 0xDD42,
-};
-const unsigned short utf8_to_euc_E8A8[] = {
- 0x3840, 0, 0x447B, 0x6B3E, 0xDD43, 0xDD44, 0, 0xDD45,
- 0x3757, 0, 0x3F56, 0, 0x6B41, 0, 0x4624, 0xDD46,
- 0x6B40, 0xDD47, 0xDD48, 0x3731, 0xDD49, 0xDD4A, 0x6B3F, 0x4277,
- 0x352D, 0, 0, 0x6B42, 0, 0x6B43, 0xDD4B, 0x3E59,
- 0xDD4C, 0, 0xDD4D, 0x376D, 0xDD4E, 0x6B44, 0xDD4F, 0,
- 0, 0, 0x4B2C, 0xDD50, 0xDD51, 0x405F, 0, 0xDD52,
- 0, 0x3576, 0, 0x4C75, 0x414A, 0xDD53, 0x6B45, 0xDD54,
- 0, 0, 0x3F47, 0x4370, 0x3E5A, 0xDD55, 0xDD56, 0,
-};
-const unsigned short utf8_to_euc_E8A9[] = {
- 0xDD57, 0x6B46, 0, 0xDD58, 0, 0xDD59, 0x6B49, 0xDD5A,
- 0x6B4A, 0xDD5B, 0, 0, 0, 0xDD5C, 0xDD5D, 0,
- 0x3A3E, 0x4242, 0x6B48, 0xDD5E, 0x3E5B, 0x493E, 0xDD5F, 0xDD60,
- 0xDD61, 0, 0, 0x6B47, 0xDD62, 0xDD63, 0x3B6C, 0,
- 0x3153, 0xDD64, 0x6B4E, 0x3758, 0, 0xDD65, 0x3B6E, 0xDD66,
- 0, 0x3B6D, 0, 0x4F4D, 0x6B4D, 0x6B4C, 0x4127, 0,
- 0x354D, 0x4F43, 0x333A, 0x3E5C, 0, 0xDD67, 0xDD68, 0xDD69,
- 0, 0xDD6A, 0xDD6B, 0xDD6C, 0x6B4B, 0, 0xDD6D, 0xDD6E,
-};
-const unsigned short utf8_to_euc_E8AA[] = {
- 0xDD6F, 0, 0x6B50, 0xDD70, 0x6B51, 0x6B4F, 0xDD71, 0x3858,
- 0, 0x4D40, 0, 0xDD72, 0x3B6F, 0x4727, 0, 0xDD73,
- 0xDD74, 0x6B54, 0xDD75, 0x4040, 0, 0x4342, 0xDD76, 0xDD77,
- 0x4D36, 0xDD78, 0x6B57, 0, 0, 0, 0x386C, 0xDD79,
- 0x403F, 0x6B53, 0, 0x6B58, 0x386D, 0x6B55, 0x6B56, 0xDD7A,
- 0x6B52, 0xDD7B, 0, 0, 0x4062, 0x4649, 0xDD7C, 0xDD7D,
- 0x432F, 0, 0x325D, 0xDD7E, 0, 0, 0xDE21, 0xDE22,
- 0, 0x4870, 0, 0xDE23, 0x3543, 0, 0xDE24, 0x4434,
-};
-const unsigned short utf8_to_euc_E8AB[] = {
- 0, 0, 0x6B5B, 0xDE25, 0x6B59, 0, 0xDE26, 0x434C,
- 0xDE27, 0xDE28, 0xDE29, 0x4041, 0x3452, 0x6B5A, 0, 0x3F5B,
- 0, 0xDE2A, 0x4E4A, 0xDE2B, 0xDE2C, 0xDE2D, 0x4F40, 0xDE2E,
- 0, 0, 0x6B5C, 0x6B67, 0x4435, 0xDE2F, 0x6B66, 0xDE30,
- 0x6B63, 0x6B6B, 0x6B64, 0, 0x6B60, 0, 0x447C, 0x6B5F,
- 0, 0, 0, 0x6B5D, 0xDE31, 0x4D21, 0x3B70, 0,
- 0xDE32, 0x6B61, 0, 0x6B5E, 0xDE33, 0xDE34, 0xDE35, 0x6B65,
- 0x3D74, 0, 0x3841, 0, 0xDE36, 0, 0x427A, 0xDE37,
-};
-const unsigned short utf8_to_euc_E8AC[] = {
- 0x4B45, 0x315A, 0x3062, 0, 0x4625, 0xDE38, 0xDE39, 0x6B69,
- 0, 0, 0xDE3F, 0xDE3A, 0x6B68, 0, 0x4666, 0,
- 0x6B6D, 0xDE3B, 0, 0, 0x6B62, 0, 0x6B6C, 0x6B6E,
- 0, 0x382C, 0x6B6A, 0x3956, 0xDE3C, 0x3C55, 0xDE3D, 0xDE3E,
- 0x6B6F, 0x4D58, 0, 0, 0, 0, 0x6B72, 0,
- 0x6B75, 0, 0, 0x6B73, 0x4935, 0xDE40, 0, 0,
- 0xDE41, 0, 0, 0x6B70, 0, 0, 0, 0xDE42,
- 0, 0x3660, 0, 0, 0xDE43, 0, 0x6B74, 0,
-};
-const unsigned short utf8_to_euc_E8AD[] = {
- 0, 0x6B76, 0xDE44, 0xDE45, 0xDE46, 0xDE47, 0xDE48, 0,
- 0xDE49, 0x6B7A, 0, 0, 0x6B77, 0xDE4E, 0x6B79, 0x6B78,
- 0, 0, 0xDE4A, 0xDE4B, 0xDE4C, 0, 0x6B7B, 0,
- 0x3C31, 0xDE4D, 0x6B7D, 0x6B7C, 0x4968, 0, 0xDE4F, 0x6C21,
- 0, 0, 0, 0xDE50, 0, 0, 0x3759, 0,
- 0, 0, 0, 0x6B7E, 0x6C22, 0xDE51, 0, 0x6C23,
- 0x3544, 0x6641, 0x3E79, 0, 0x6C24, 0, 0xDE52, 0x386E,
- 0xDE53, 0xDE54, 0, 0, 0xDE55, 0x6C25, 0xDE56, 0xF466,
-};
-const unsigned short utf8_to_euc_E8AE[] = {
- 0x6C26, 0xDE57, 0, 0x3B3E, 0xDE58, 0xDE59, 0, 0,
- 0, 0, 0x5A4E, 0xDE5A, 0x6C27, 0xDE5B, 0x6C28, 0xDE5C,
- 0x3D32, 0, 0x6C29, 0x6C2A, 0xDE5D, 0xDE5E, 0x6C2B, 0,
- 0, 0x6C2C, 0x6C2D, 0, 0xDE5F, 0, 0xDE60, 0xDE61,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E8B0[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x432B,
- 0xDE62, 0xDE63, 0x6C2E, 0, 0, 0xDE64, 0xDE65, 0x6C30,
-};
-const unsigned short utf8_to_euc_E8B1[] = {
- 0, 0x6C2F, 0, 0, 0, 0xDE66, 0x4626, 0xDE67,
- 0x6C31, 0xDE68, 0x4B2D, 0xDE69, 0x6C32, 0, 0x6C33, 0xDE6A,
- 0x6C34, 0xDE6B, 0, 0xDE6C, 0xDE6D, 0x6C35, 0, 0xDE6E,
- 0xDE6F, 0xDE72, 0x465A, 0xDE70, 0, 0xDE71, 0, 0,
- 0, 0x3E5D, 0x6C36, 0xDE73, 0xDE74, 0, 0xDE75, 0,
- 0xDE76, 0xDE77, 0x396B, 0x502E, 0x6C37, 0xDE78, 0, 0,
- 0, 0, 0, 0xDE79, 0, 0xDE7A, 0xDE7B, 0,
- 0x6C38, 0x493F, 0x6C39, 0xDE7C, 0x6C41, 0, 0xDE7D, 0,
-};
-const unsigned short utf8_to_euc_E8B2[] = {
- 0, 0, 0x6C3A, 0, 0, 0x6C3C, 0xDE7E, 0xDF21,
- 0, 0x6C3B, 0x6C3D, 0xDF22, 0x4B46, 0x6C3E, 0x6C3F, 0,
- 0xDF23, 0, 0xDF24, 0xDF25, 0x6C40, 0, 0, 0,
- 0x6C42, 0xDF26, 0, 0xDF27, 0xDF28, 0x332D, 0x4467, 0,
- 0x4969, 0x3A62, 0x3957, 0, 0xDF29, 0, 0, 0x494F,
- 0x325F, 0x484E, 0x6C45, 0x3453, 0x4055, 0x6C44, 0x6C49, 0x4379,
- 0x4C63, 0, 0x6C47, 0x6C48, 0x352E, 0, 0x6C4A, 0x4763,
- 0x425F, 0xDF2A, 0xDF2B, 0x4871, 0x453D, 0x6C46, 0, 0x4B47,
-};
-const unsigned short utf8_to_euc_E8B3[] = {
- 0x326C, 0x6C4C, 0x4F28, 0x4442, 0x4F45, 0xDF2C, 0xDF2D, 0x3B71,
- 0x6C4B, 0xDF2E, 0x4231, 0xDF2F, 0, 0x6C5C, 0x4128, 0xDF30,
- 0, 0x4678, 0, 0x4950, 0, 0xDF32, 0xDF31, 0,
- 0, 0xDF33, 0x6C4F, 0x3B3F, 0x3B72, 0xDF34, 0x3E5E, 0,
- 0x4765, 0xDF35, 0x382D, 0x6C4E, 0x6C4D, 0, 0x496A, 0,
- 0xDF36, 0, 0x3C41, 0, 0xDF37, 0x4552, 0, 0xDF38,
- 0xDF39, 0, 0xDF3A, 0, 0xF467, 0xDF3B, 0, 0xDF3C,
- 0xDF3D, 0, 0x6C51, 0x6C52, 0x3958, 0x6C50, 0xDF3E, 0xDF3F,
-};
-const unsigned short utf8_to_euc_E8B4[] = {
- 0, 0xDF40, 0, 0xDF41, 0x6C53, 0x6C54, 0, 0x6C56,
- 0x4223, 0xDF42, 0x6C55, 0x3466, 0, 0x6C58, 0, 0x6C57,
- 0x6C59, 0, 0xDF43, 0x6C5B, 0x6C5D, 0, 0x6C5E, 0xDF44,
- 0, 0, 0, 0xDF45, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E8B5[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x4056, 0xDF46, 0x3C4F, 0x6C5F,
- 0, 0xDF47, 0, 0x3352, 0xDF48, 0x6C60, 0xDF49, 0,
- 0x4176, 0x6C61, 0, 0x6C62, 0x496B, 0, 0xF468, 0x352F,
- 0, 0, 0, 0, 0, 0, 0, 0xDF4A,
-};
-const unsigned short utf8_to_euc_E8B6[] = {
- 0, 0x6C63, 0xDF4B, 0, 0xDF4C, 0x4436, 0, 0,
- 0xDF4D, 0, 0x315B, 0, 0, 0xDF4E, 0, 0,
- 0xDF4F, 0xDF50, 0, 0, 0, 0xDF51, 0, 0,
- 0, 0x6C64, 0, 0, 0, 0, 0xDF52, 0xDF53,
- 0xDF54, 0, 0, 0x3C71, 0, 0, 0xDF55, 0,
- 0x3F76, 0, 0, 0xDF56, 0xDF57, 0, 0, 0xDF58,
- 0, 0, 0xDF59, 0x422D, 0, 0xDF5A, 0, 0xDF5B,
- 0, 0xDF5C, 0x6C67, 0xDF5D, 0xDF6F, 0, 0x6C66, 0,
-};
-const unsigned short utf8_to_euc_E8B7[] = {
- 0xDF5E, 0, 0x6C65, 0, 0, 0xDF5F, 0xDF60, 0xDF61,
- 0xDF62, 0, 0xDF63, 0x6C6D, 0x6C6B, 0, 0xDF64, 0x6C68,
- 0, 0xDF65, 0, 0, 0xDF66, 0xDF67, 0x6C6A, 0xDF68,
- 0, 0xDF69, 0x6C69, 0x6C6C, 0, 0x3577, 0, 0x6C70,
- 0, 0x4057, 0, 0x6C71, 0xDF6A, 0xDF6B, 0, 0xDF6C,
- 0x3859, 0, 0x6C6E, 0x6C6F, 0xDF6D, 0, 0, 0x4F29,
- 0xDF6E, 0xDF70, 0xDF71, 0x4437, 0xDF72, 0x4129, 0, 0,
- 0, 0, 0, 0, 0x6C72, 0xDF73, 0, 0x6C75,
-};
-const unsigned short utf8_to_euc_E8B8[] = {
- 0, 0xDF74, 0, 0, 0xDF75, 0xDF76, 0xDF77, 0,
- 0x6C73, 0x6C74, 0x4D59, 0xDF78, 0, 0, 0, 0x4627,
- 0x6C78, 0xDF79, 0, 0, 0xDF7A, 0, 0xDF7B, 0,
- 0, 0, 0, 0, 0, 0x6C76, 0x6C77, 0x6C79,
- 0xDF7C, 0xDF7D, 0xDF7E, 0xE021, 0, 0, 0xE022, 0xE023,
- 0, 0, 0x6D29, 0, 0, 0, 0, 0,
- 0x6C7C, 0xE024, 0, 0xE025, 0x6C7D, 0x6C7B, 0xE026, 0xE027,
- 0xE028, 0xE029, 0, 0, 0, 0xE02A, 0, 0,
-};
-const unsigned short utf8_to_euc_E8B9[] = {
- 0xE02B, 0xE02C, 0x6C7A, 0, 0x447D, 0, 0, 0x6D21,
- 0x6D25, 0x6D22, 0x6C7E, 0xE02D, 0x6D23, 0xE02E, 0xE02F, 0xE030,
- 0x6D24, 0, 0, 0, 0xE031, 0x6D2B, 0, 0,
- 0, 0x6D26, 0, 0xE032, 0xE033, 0xE034, 0xE035, 0x4058,
- 0x6D28, 0xE036, 0xE037, 0x6D2A, 0x6D27, 0, 0, 0,
- 0, 0xE038, 0, 0, 0xE039, 0xE03A, 0, 0xE03B,
- 0xE03C, 0xE03D, 0x6D2D, 0, 0x3D33, 0, 0x6D2C, 0,
- 0, 0xE03E, 0xE03F, 0xE040, 0x6D2E, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E8BA[] = {
- 0, 0x6D2F, 0xE041, 0xE042, 0x6D32, 0x6D31, 0, 0x6D30,
- 0, 0xE043, 0x6D34, 0x6D33, 0, 0x4C76, 0, 0,
- 0xE044, 0x6D36, 0xE045, 0x6D35, 0x6D37, 0xE046, 0, 0,
- 0, 0x6D38, 0xE047, 0xE048, 0, 0xE049, 0xE04A, 0,
- 0, 0x6D3A, 0xE04B, 0, 0, 0, 0, 0xE04C,
- 0, 0xE04D, 0x6D39, 0x3F48, 0x6D3B, 0xE04E, 0xE04F, 0x366D,
- 0x6D3C, 0x6D3E, 0, 0xE050, 0, 0xE051, 0, 0,
- 0, 0, 0xE052, 0xE053, 0, 0, 0x6D3F, 0,
-};
-const unsigned short utf8_to_euc_E8BB[] = {
- 0xE054, 0xE055, 0, 0xE056, 0xE057, 0x6D40, 0x6D3D, 0xE058,
- 0x6D41, 0, 0x3C56, 0x6D42, 0x3530, 0x3733, 0, 0xE059,
- 0, 0xE05A, 0x382E, 0, 0xE05B, 0, 0, 0,
- 0, 0, 0, 0x6D43, 0xE05C, 0, 0, 0x4670,
- 0, 0, 0x453E, 0x6D44, 0, 0, 0, 0,
- 0xE05D, 0, 0, 0x6D47, 0, 0xE064, 0xE05E, 0,
- 0xE05F, 0xE060, 0, 0, 0, 0, 0, 0xE061,
- 0x3C34, 0xE062, 0xE063, 0x6D46, 0x6D45, 0x375A, 0x6D48, 0,
-};
-const unsigned short utf8_to_euc_E8BC[] = {
- 0xE065, 0, 0xE066, 0x3353, 0, 0x6D4A, 0, 0xE067,
- 0xE068, 0x3A5C, 0x6D49, 0, 0x6D52, 0, 0, 0xE069,
- 0xE06A, 0, 0x6D4C, 0x6D4E, 0x4A65, 0x6D4B, 0xE06B, 0xE06C,
- 0xE06D, 0x6D4D, 0, 0x6D51, 0x6D4F, 0x3531, 0xE06E, 0x6D50,
- 0xE06F, 0xE070, 0, 0xE071, 0, 0xE072, 0x6D53, 0xE073,
- 0xE074, 0x475A, 0x4E58, 0, 0xE075, 0xE076, 0xE077, 0x3D34,
- 0, 0, 0, 0x6D54, 0xE078, 0xE079, 0xE07A, 0xE07B,
- 0x4D22, 0x6D56, 0xE07C, 0x6D55, 0, 0, 0x6D59, 0x4D41,
-};
-const unsigned short utf8_to_euc_E8BD[] = {
- 0xE07D, 0xE07E, 0x6D58, 0xE121, 0x336D, 0x6D57, 0x6D5C, 0xE122,
- 0, 0x6D5B, 0, 0, 0x6D5A, 0x4532, 0x6D5D, 0xE123,
- 0, 0xE124, 0xE125, 0xE126, 0xE127, 0xE128, 0, 0x6D5E,
- 0xE129, 0, 0, 0, 0x6D5F, 0xE12A, 0xE12B, 0x396C,
- 0, 0x3725, 0x6D60, 0x6D61, 0x6D62, 0xE12C, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E8BE[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x3F49, 0x6D63, 0xE12D, 0x3C2D, 0x6D64,
- 0xE12E, 0xE12F, 0, 0x6D65, 0xE130, 0xE131, 0xE132, 0x5221,
- 0x517E, 0, 0, 0, 0, 0x6D66, 0x6570, 0x6D67,
- 0x4324, 0x3F2B, 0x4740, 0, 0, 0xE133, 0xE134, 0x6D68,
- 0xE135, 0, 0x4A55, 0x4454, 0x397E, 0, 0xE136, 0x4329,
-};
-const unsigned short utf8_to_euc_E8BF[] = {
- 0xE137, 0xE138, 0x312A, 0, 0x4B78, 0x3F57, 0xE139, 0,
- 0, 0, 0xE13A, 0xE13B, 0, 0xE13C, 0x375E, 0,
- 0xE13D, 0x3661, 0xE13E, 0xE13F, 0x4A56, 0xE140, 0, 0,
- 0, 0, 0x6D69, 0, 0, 0, 0, 0,
- 0xE141, 0, 0x6D6B, 0xE142, 0xE143, 0x6D6A, 0x3260, 0,
- 0xE144, 0x4676, 0x6D6C, 0x4777, 0, 0x4533, 0xE145, 0x6D6D,
- 0x3D52, 0xE146, 0, 0, 0x6D6F, 0xE147, 0xE148, 0x4C42,
- 0x6D7E, 0x6D71, 0x6D72, 0xE149, 0, 0x4449, 0xE14A, 0,
-};
-const unsigned short utf8_to_euc_E980[] = {
- 0x4260, 0x4177, 0xE14B, 0x4628, 0xE14C, 0x6D70, 0x3555, 0,
- 0xE14D, 0, 0, 0x6D79, 0xE14E, 0x6D76, 0x6E25, 0x4629,
- 0x4360, 0x6D73, 0, 0x447E, 0x4553, 0x6D74, 0x6D78, 0x3F60,
- 0xE14F, 0x4767, 0x444C, 0xE150, 0, 0x4042, 0x6D77, 0x422E,
- 0x4224, 0x6D75, 0x3029, 0x4F22, 0, 0, 0, 0x6D7A,
- 0xE151, 0xE152, 0xE154, 0, 0xE155, 0xE156, 0x4261, 0xE153,
- 0, 0x3D35, 0x3F4A, 0xE157, 0xE158, 0x6D7C, 0x6D7B, 0xE159,
- 0x306F, 0x6D7D, 0, 0, 0x492F, 0, 0x6E27, 0xE15A,
-};
-const unsigned short utf8_to_euc_E981[] = {
- 0, 0x465B, 0x3F6B, 0xE15B, 0xE15C, 0x4359, 0, 0x3678,
- 0, 0x6E26, 0x4D37, 0x313F, 0xE15D, 0x4A57, 0x3261, 0x6E21,
- 0x6E22, 0x6E23, 0x6E24, 0x463B, 0x4323, 0x3063, 0x6E28, 0,
- 0x6E29, 0x7423, 0, 0xE15E, 0x423D, 0xE15F, 0x6E2A, 0,
- 0x3173, 0x414C, 0xE160, 0x382F, 0, 0x4D5A, 0xE161, 0xE162,
- 0x6E2B, 0x452C, 0, 0, 0xE163, 0x4178, 0x3C57, 0x6E2C,
- 0xE164, 0, 0x6E2F, 0, 0xE165, 0x3D65, 0x6E2D, 0x412B,
- 0x412A, 0xE166, 0x3064, 0, 0x4E4B, 0x6E31, 0, 0x4872,
-};
-const unsigned short utf8_to_euc_E982[] = {
- 0x6E33, 0x6E32, 0x6E30, 0x6364, 0x3454, 0xE167, 0, 0x6D6E,
- 0xE168, 0x6E35, 0x6E34, 0xE169, 0xE16A, 0, 0xE16B, 0x6E36,
- 0xE16C, 0x4D38, 0, 0, 0, 0xE16D, 0, 0xE16E,
- 0xE16F, 0xE170, 0, 0xE171, 0, 0, 0, 0,
- 0xE172, 0xE173, 0xE174, 0x4661, 0, 0xE175, 0x4B2E, 0,
- 0x6E37, 0, 0x3C59, 0, 0, 0, 0, 0x6E38,
- 0xE176, 0x6E39, 0xE177, 0xE178, 0xE179, 0x6E3A, 0xE17A, 0,
- 0x4521, 0, 0, 0, 0, 0xE17B, 0xE17D, 0,
-};
-const unsigned short utf8_to_euc_E983[] = {
- 0, 0x306A, 0, 0xE17E, 0xE221, 0xE222, 0, 0xE223,
- 0xE224, 0, 0x3959, 0, 0xE17C, 0, 0x4F3A, 0,
- 0, 0, 0xE22D, 0, 0, 0xE225, 0, 0xE226,
- 0xE227, 0xE228, 0, 0x6E3E, 0xE229, 0xE22A, 0xF46C, 0xE22B,
- 0, 0x3734, 0x6E3B, 0, 0x6E3C, 0xE22C, 0, 0,
- 0x4974, 0, 0, 0xE22F, 0, 0x3354, 0, 0xE230,
- 0xE231, 0, 0, 0, 0xE232, 0x4D39, 0xE22E, 0x363F,
- 0, 0, 0, 0, 0, 0x4554, 0xE233, 0xE234,
-};
-const unsigned short utf8_to_euc_E984[] = {
- 0xE235, 0, 0x6E3F, 0, 0xE236, 0xE237, 0xE238, 0,
- 0xE239, 0, 0, 0, 0, 0xE23A, 0, 0,
- 0xE23B, 0, 0x6E40, 0, 0xE23C, 0xF46E, 0xE23D, 0xE23E,
- 0xE23F, 0x6E41, 0xE240, 0, 0xE241, 0, 0xE242, 0,
- 0xE243, 0, 0xE245, 0xE246, 0, 0xE244, 0, 0xE247,
- 0, 0xE248, 0, 0, 0, 0x4522, 0xE249, 0xE24A,
- 0x6E43, 0xE24B, 0x6E42, 0, 0xE24C, 0, 0xE24D, 0xE24E,
- 0, 0xE24F, 0xE250, 0, 0xE251, 0xE252, 0, 0,
-};
-const unsigned short utf8_to_euc_E985[] = {
- 0, 0, 0, 0xE253, 0, 0, 0, 0xE254,
- 0xE255, 0x4653, 0x6E44, 0x3D36, 0x3C60, 0x475B, 0x4371, 0xE256,
- 0, 0, 0x3C72, 0xE257, 0x3F6C, 0, 0x6E45, 0xE258,
- 0x6E46, 0xE259, 0xE25A, 0xE25B, 0, 0, 0, 0,
- 0, 0xE25C, 0x3F5D, 0x6E47, 0xE25D, 0x6E48, 0, 0xE25E,
- 0, 0x6E49, 0x4D6F, 0, 0x3D37, 0xE25F, 0, 0,
- 0, 0, 0x6E4B, 0x6E4A, 0xE260, 0x395A, 0, 0x3973,
- 0x3B40, 0xE261, 0xE262, 0xE263, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E986[] = {
- 0, 0xE264, 0x6E4E, 0xE265, 0, 0xE266, 0xE267, 0x3D66,
- 0, 0x6E4D, 0xE268, 0x6E4C, 0, 0x4269, 0xE269, 0,
- 0x386F, 0xE26A, 0x4043, 0xE26B, 0xE26C, 0xE26D, 0, 0x4830,
- 0xE26E, 0, 0, 0, 0x3D39, 0, 0xE26F, 0,
- 0, 0xE270, 0x6E4F, 0, 0x3E5F, 0, 0xE271, 0,
- 0xE272, 0, 0x6E52, 0x6E50, 0xE273, 0xE274, 0xE275, 0x6E51,
- 0xE276, 0xE277, 0xE278, 0xE279, 0x6E54, 0x6E53, 0xE27A, 0,
- 0x3E7A, 0, 0x6E55, 0xE27B, 0xE27C, 0xE27D, 0, 0xE27E,
-};
-const unsigned short utf8_to_euc_E987[] = {
- 0x6E56, 0x6E57, 0xE321, 0xE322, 0, 0xE323, 0x4850, 0x3A53,
- 0x3C61, 0x6E58, 0, 0x6E59, 0x4E24, 0x3D45, 0x4C6E, 0x4E4C,
- 0x6E5A, 0x3662, 0, 0xE324, 0xE325, 0, 0x6E5B, 0xE326,
- 0x4523, 0xE327, 0xE328, 0x6E5E, 0x3378, 0x3F4B, 0xE329, 0x6E5C,
- 0, 0x6E5D, 0, 0x4460, 0xE32A, 0xE32B, 0x4B55, 0x367C,
- 0, 0xE32C, 0xE32D, 0, 0xE32E, 0xE32F, 0xE330, 0xE331,
- 0xE332, 0xE333, 0, 0, 0, 0x6E60, 0x6E61, 0xE334,
- 0, 0xE335, 0, 0xE336, 0x6E5F, 0xE337, 0, 0x6E63,
-};
-const unsigned short utf8_to_euc_E988[] = {
- 0xE338, 0xE339, 0, 0, 0xE33A, 0xE33B, 0xE33C, 0xE33D,
- 0, 0xE33E, 0xE33F, 0, 0xE340, 0x465F, 0x3343, 0,
- 0xE341, 0x6E67, 0xE342, 0xE343, 0x6E64, 0x6E66, 0xE344, 0,
- 0xE345, 0, 0, 0, 0xE346, 0xE347, 0x6E62, 0,
- 0, 0, 0, 0xE348, 0xE349, 0xE34A, 0xE34B, 0,
- 0xE34C, 0x6F4F, 0, 0, 0x6E65, 0, 0xE34D, 0xE34E,
- 0xE34F, 0, 0, 0xE350, 0x4E6B, 0xE351, 0xE352, 0x385A,
- 0xE353, 0xE354, 0xE355, 0, 0xE356, 0, 0xE357, 0x6E6F,
-};
-const unsigned short utf8_to_euc_E989[] = {
- 0xE358, 0, 0xE359, 0xE35A, 0x4534, 0x6E6A, 0xE35B, 0xE35C,
- 0x6E6D, 0x6E6B, 0xE35D, 0x6E70, 0, 0xE35E, 0xE35F, 0xE360,
- 0x6E71, 0xE361, 0, 0, 0, 0, 0, 0x6E69,
- 0xE362, 0xE363, 0x6E76, 0x3174, 0xE364, 0xE365, 0x6E68, 0,
- 0xE366, 0xE367, 0x482D, 0, 0x6E6C, 0xE368, 0x3E60, 0xE369,
- 0xE36A, 0xE36B, 0, 0, 0, 0, 0xE36C, 0xE36D,
- 0xE36E, 0x395B, 0, 0, 0, 0xE36F, 0xE370, 0xE371,
- 0xE372, 0xE373, 0, 0xE374, 0xE375, 0xE376, 0x4B48, 0xE377,
-};
-const unsigned short utf8_to_euc_E98A[] = {
- 0x3664, 0, 0, 0x3D46, 0, 0x463C, 0, 0,
- 0xE378, 0xE379, 0xE37A, 0, 0, 0xE37B, 0xE37C, 0,
- 0, 0x412D, 0xE37D, 0x6E74, 0, 0x6E6E, 0x6E73, 0xE37E,
- 0x4C43, 0xE421, 0x4438, 0x6E75, 0x6E72, 0, 0, 0xE422,
- 0xE423, 0, 0, 0, 0xE424, 0xE425, 0, 0xE426,
- 0xE427, 0, 0, 0xE428, 0, 0x412C, 0, 0xE429,
- 0, 0, 0xE42A, 0, 0, 0, 0xE42B, 0x6E79,
- 0xE42C, 0x6E78, 0xE42D, 0xE42E, 0xE42F, 0xE430, 0, 0xE431,
-};
-const unsigned short utf8_to_euc_E98B[] = {
- 0xE432, 0xE433, 0xE434, 0xE435, 0, 0xE436, 0xE437, 0xE438,
- 0xE439, 0, 0, 0xE43A, 0xE43B, 0xE43C, 0xE43D, 0x6E77,
- 0xE43E, 0, 0x4B2F, 0xE43F, 0, 0xE440, 0, 0xE441,
- 0xE442, 0xE443, 0, 0, 0xE444, 0xE445, 0, 0xE446,
- 0xE447, 0xE448, 0, 0xE449, 0x3D7B, 0xE44A, 0, 0xE44B,
- 0xE44C, 0x6E7A, 0x4A5F, 0, 0xE44D, 0x3154, 0xE44E, 0,
- 0xE44F, 0, 0x4946, 0x4372, 0, 0, 0, 0,
- 0x3578, 0xE450, 0x6E7C, 0xE451, 0x395D, 0, 0, 0xE452,
-};
-const unsigned short utf8_to_euc_E98C[] = {
- 0xE453, 0, 0xE454, 0, 0, 0, 0x3B2C, 0,
- 0xE455, 0, 0, 0, 0, 0xE456, 0, 0x6E7B,
- 0x3F6D, 0xE457, 0, 0, 0xE458, 0xE459, 0, 0,
- 0x3F6E, 0x6F21, 0x6F23, 0, 0xE45A, 0xE45B, 0xE45C, 0xE45D,
- 0x3E7B, 0xE45E, 0x6F22, 0x6F24, 0xE45F, 0xE460, 0x3653, 0xE461,
- 0x4945, 0xE462, 0xE463, 0x3C62, 0x4F23, 0, 0x6E7E, 0x3A78,
- 0, 0, 0x4F3F, 0xE464, 0xE465, 0x6F26, 0xE466, 0xE467,
- 0, 0, 0x6F25, 0x6F27, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E98D[] = {
- 0, 0, 0, 0, 0x6E7D, 0, 0, 0xE468,
- 0xE469, 0xE46A, 0, 0x4669, 0, 0x4555, 0, 0,
- 0xE46B, 0xE46C, 0xE46D, 0, 0x4457, 0xE46E, 0x6F2C, 0xE46F,
- 0xE470, 0, 0xE471, 0x4343, 0x6F28, 0, 0xE472, 0,
- 0x6F29, 0, 0, 0, 0xE473, 0xE474, 0, 0xE475,
- 0, 0xE476, 0xE477, 0, 0x372D, 0xE478, 0x6F2B, 0xE479,
- 0xE47A, 0xE47B, 0, 0xE47C, 0xE47D, 0x3830, 0xE47E, 0,
- 0, 0, 0xE521, 0, 0x6F2A, 0xE522, 0x3E61, 0xE523,
-};
-const unsigned short utf8_to_euc_E98E[] = {
- 0xE524, 0xE525, 0xE526, 0, 0, 0, 0, 0,
- 0xE527, 0, 0xE528, 0xE529, 0x3379, 0xE52A, 0, 0xE52B,
- 0, 0, 0xE52C, 0, 0x6F30, 0xE52D, 0x3A3F, 0x4179,
- 0xE52E, 0, 0x444A, 0xE52F, 0, 0, 0xE530, 0,
- 0, 0xE531, 0, 0xE532, 0xE533, 0, 0xE534, 0x333B,
- 0xE535, 0xE53B, 0, 0xE536, 0x6F2E, 0x6F2F, 0x4443, 0,
- 0x6F2D, 0, 0, 0, 0xE537, 0xE538, 0xE539, 0,
- 0, 0x6F31, 0xE53A, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E98F[] = {
- 0, 0xE53C, 0, 0x6F37, 0xE53D, 0xE53E, 0xE53F, 0xE540,
- 0x6F3A, 0xE541, 0xE542, 0xE543, 0xE544, 0xE545, 0, 0,
- 0x6F39, 0x452D, 0, 0xE546, 0, 0, 0x6F32, 0x6F33,
- 0x6F36, 0xE547, 0, 0, 0xE548, 0x6F38, 0xE549, 0xE54A,
- 0, 0x3640, 0xE54B, 0, 0x6F3B, 0x6F35, 0xE54C, 0xE54D,
- 0x6F34, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xE54F,
- 0xE550, 0xE54E, 0xE551, 0xE552, 0, 0xE553, 0, 0,
-};
-const unsigned short utf8_to_euc_E990[] = {
- 0, 0xE554, 0xE555, 0x6F3F, 0xE556, 0, 0, 0x6F40,
- 0xE557, 0xE558, 0, 0, 0, 0xE559, 0xE55A, 0xE55B,
- 0x6F41, 0, 0, 0x6F3E, 0x6F3D, 0xE55C, 0xE55D, 0xE55E,
- 0x3E62, 0x462A, 0x6F3C, 0, 0, 0, 0, 0xE55F,
- 0, 0x6F45, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x6F43, 0, 0, 0xE560, 0xE561,
- 0, 0xE562, 0xE563, 0xE564, 0xE565, 0x6F44, 0x6F42, 0,
- 0x4278, 0, 0x6F46, 0xE566, 0, 0xE568, 0, 0xE567,
-};
-const unsigned short utf8_to_euc_E991[] = {
- 0, 0x6F47, 0, 0xE569, 0x6F49, 0xE56A, 0, 0,
- 0xE56B, 0, 0xE56C, 0, 0xE56D, 0, 0, 0,
- 0, 0x3455, 0x6F48, 0x4C7A, 0, 0xE56E, 0, 0,
- 0, 0xE56F, 0x6F54, 0x6F4A, 0xE570, 0, 0x6F4D, 0xE571,
- 0x6F4B, 0xE572, 0x6F4C, 0xE573, 0, 0, 0, 0,
- 0xE574, 0, 0x6F4E, 0xE575, 0, 0xE576, 0xE577, 0xE578,
- 0x6F50, 0xE579, 0xE57A, 0, 0, 0x6F51, 0, 0x6F52,
- 0, 0, 0, 0, 0x6F55, 0x6F53, 0x6F56, 0x6F58,
-};
-const unsigned short utf8_to_euc_E992[] = {
- 0, 0x6F57, 0, 0xE57C, 0xE57B, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E995[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x4439,
- 0xE57D, 0xE57E, 0, 0, 0, 0, 0xE621, 0,
-};
-const unsigned short utf8_to_euc_E996[] = {
- 0x4C67, 0, 0x6F59, 0x412E, 0xE622, 0, 0, 0x6F5A,
- 0xE623, 0x4A44, 0x6F5B, 0x332B, 0xE624, 0xE625, 0xE626, 0x313C,
- 0, 0x3457, 0xF471, 0x3456, 0x6F5C, 0, 0x6F5D, 0,
- 0x6F5E, 0x6F5F, 0, 0, 0, 0xE627, 0xE628, 0xE629,
- 0x6F60, 0xE62A, 0x3458, 0x3355, 0x395E, 0x4836, 0xE62B, 0x6F62,
- 0x6F61, 0xE62C, 0, 0xE62D, 0xE62E, 0x6F63, 0, 0,
- 0, 0, 0x315C, 0, 0xE62F, 0, 0xE630, 0,
- 0, 0x6F66, 0xE631, 0x6F65, 0x6F64, 0xE632, 0x6F67, 0xE633,
-};
-const unsigned short utf8_to_euc_E997[] = {
- 0, 0, 0, 0x6F6A, 0, 0, 0xE634, 0x3047,
- 0xE635, 0xE636, 0x6F68, 0xE637, 0x6F6C, 0x6F6B, 0, 0,
- 0xE638, 0xE639, 0xE63A, 0xE63B, 0x6F6E, 0x6F6D, 0x6F6F, 0,
- 0x462E, 0xE63C, 0xE63D, 0, 0x6F70, 0xE63E, 0xE63F, 0xE640,
- 0xE641, 0x6F71, 0x6F73, 0, 0xE642, 0x6F72, 0xE643, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E998[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x496C, 0xE644, 0xE645, 0,
- 0, 0x6F74, 0xE646, 0, 0xE647, 0xE648, 0xE649, 0,
- 0x6F75, 0, 0x3A65, 0, 0xE64A, 0, 0x6F76, 0x6F77,
- 0, 0xE64B, 0x4B49, 0xE64C, 0, 0, 0, 0xE64D,
- 0xE64E, 0xE64F, 0xE650, 0x414B, 0xE651, 0xE652, 0, 0x3024,
-};
-const unsigned short utf8_to_euc_E999[] = {
- 0x424B, 0xE653, 0x6F78, 0, 0x496D, 0, 0, 0,
- 0, 0, 0, 0x6F7B, 0x6F79, 0x395F, 0, 0x6F7A,
- 0x3842, 0, 0xE654, 0, 0xE655, 0, 0xE656, 0xE657,
- 0xE658, 0, 0, 0x4A45, 0x6F7D, 0x7021, 0x6F7E, 0x7022,
- 0, 0xE659, 0x3121, 0x3F58, 0x3D7C, 0x3459, 0x7023, 0,
- 0, 0, 0x4766, 0, 0x7025, 0, 0xE65A, 0,
- 0x3122, 0, 0x7024, 0x4444, 0xE65B, 0x4E4D, 0x462B, 0x6F7C,
- 0x4E26, 0, 0x3831, 0xE65C, 0xE65D, 0x4D5B, 0xE65E, 0xE65F,
-};
-const unsigned short utf8_to_euc_E99A[] = {
- 0, 0xE660, 0xE661, 0xE662, 0xE663, 0x3679, 0x4E34, 0,
- 0x3728, 0xE664, 0x4262, 0x6721, 0, 0x7026, 0x332C, 0x3F6F,
- 0, 0xE665, 0, 0, 0x3356, 0x7028, 0xE666, 0x7029,
- 0x7027, 0x3764, 0xE667, 0x3A5D, 0x3E63, 0xE668, 0, 0xE669,
- 0x3123, 0, 0, 0x4E59, 0xE66A, 0xE66B, 0xE66C, 0x702B,
- 0x6E2E, 0xE66D, 0x702A, 0, 0, 0, 0xE66E, 0xE66F,
- 0x702E, 0x702C, 0x702D, 0xE670, 0x702F, 0, 0x7030, 0x4E6C,
- 0x7031, 0x7032, 0xE671, 0x4049, 0x483B, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E99B[] = {
- 0x3F7D, 0x3467, 0, 0, 0x4D3A, 0x326D, 0x3D38, 0x385B,
- 0, 0x7035, 0xE672, 0x7034, 0x3B73, 0x7036, 0x7033, 0,
- 0, 0x3B28, 0xE673, 0, 0, 0x703A, 0x6A2D, 0,
- 0xE675, 0x5256, 0xE676, 0x3F77, 0x7038, 0xE677, 0xE678, 0xE679,
- 0, 0, 0x4E25, 0x4671, 0, 0, 0, 0,
- 0x312B, 0xE67A, 0x4063, 0x3C36, 0, 0, 0, 0xE67B,
- 0x4A37, 0xE67C, 0x3140, 0, 0, 0, 0x4E6D, 0x4D6B,
- 0, 0x703B, 0xE67D, 0x4545, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E99C[] = {
- 0x3C7B, 0, 0xE67E, 0xE721, 0x703C, 0xE722, 0x703D, 0x3F4C,
- 0x703E, 0xE723, 0x4E6E, 0, 0, 0x7039, 0x7040, 0x7042,
- 0, 0x7041, 0, 0x703F, 0, 0, 0x7043, 0,
- 0, 0x7044, 0xE724, 0xE725, 0x417A, 0xE726, 0x3262, 0,
- 0, 0xE727, 0xE728, 0xE729, 0x7045, 0, 0, 0x4C38,
- 0xE72A, 0, 0x7046, 0, 0, 0, 0, 0,
- 0x7047, 0xE72B, 0x4F2A, 0xE72C, 0, 0, 0, 0,
- 0x5B31, 0x7048, 0, 0xF474, 0, 0x7049, 0x704A, 0,
-};
-const unsigned short utf8_to_euc_E99D[] = {
- 0, 0xE72D, 0x704E, 0xE72E, 0x704B, 0, 0x704C, 0,
- 0x704D, 0x704F, 0xE72F, 0, 0, 0xF475, 0xE730, 0xE731,
- 0, 0xF476, 0x4044, 0, 0, 0xE732, 0x4C77, 0xE733,
- 0xE734, 0x4045, 0xE735, 0xE736, 0x7050, 0, 0x4873, 0,
- 0x7051, 0x7353, 0x4C4C, 0xE737, 0x7052, 0, 0x7053, 0xE738,
- 0x7054, 0x3357, 0xE739, 0x7056, 0, 0x3F59, 0xE73A, 0,
- 0, 0x7057, 0, 0xE73B, 0x3724, 0, 0xE73C, 0xE73D,
- 0xE73E, 0x7058, 0x705C, 0xE73F, 0x705A, 0xE740, 0, 0xE741,
-};
-const unsigned short utf8_to_euc_E99E[] = {
- 0xE742, 0x705B, 0, 0, 0x3373, 0x7059, 0x705D, 0,
- 0, 0xE743, 0, 0x705E, 0, 0x3048, 0, 0x705F,
- 0x7060, 0, 0, 0, 0, 0xE744, 0xE745, 0xE746,
- 0x3E64, 0xE747, 0xE748, 0, 0x7061, 0, 0xE749, 0xE74A,
- 0x3547, 0, 0xE74B, 0x7064, 0, 0, 0x7063, 0,
- 0x7062, 0, 0, 0x6B71, 0xE74C, 0x4A5C, 0xE74D, 0,
- 0, 0xE74E, 0xE74F, 0x7065, 0x7066, 0xE750, 0xE751, 0,
- 0xE752, 0xE753, 0xE754, 0, 0xE755, 0, 0xE756, 0xE757,
-};
-const unsigned short utf8_to_euc_E99F[] = {
- 0, 0xE758, 0, 0x7067, 0xE759, 0xE75A, 0x7068, 0xE75B,
- 0x7069, 0xE75C, 0xE75D, 0x706A, 0xE75E, 0xE75F, 0xE760, 0,
- 0xE761, 0xE762, 0, 0x345A, 0xE763, 0, 0, 0xE764,
- 0xE765, 0xE766, 0, 0xE76A, 0x706B, 0xE767, 0xE768, 0,
- 0xE769, 0xE76B, 0, 0, 0xE76C, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x706C, 0x4723, 0xE76D,
- 0, 0xE76E, 0x706E, 0x323B, 0xE76F, 0x7071, 0x7070, 0xE770,
- 0xE771, 0, 0xE772, 0x3124, 0, 0, 0, 0x3641,
-};
-const unsigned short utf8_to_euc_E9A0[] = {
- 0, 0x4A47, 0x443A, 0x3A22, 0, 0x3960, 0x3D67, 0xE773,
- 0x3F5C, 0, 0xE774, 0, 0x7073, 0xE776, 0xE777, 0x7072,
- 0x4D42, 0x3468, 0x4852, 0x465C, 0xE778, 0, 0xE779, 0x3F7C,
- 0x4E4E, 0xE775, 0x375B, 0, 0xE77A, 0, 0xE77B, 0,
- 0xE77C, 0x7076, 0, 0xE77D, 0x7075, 0xE828, 0xE77E, 0,
- 0, 0, 0, 0xE821, 0x4B4B, 0x462C, 0xE822, 0xE823,
- 0xE824, 0, 0xE825, 0xE826, 0x3150, 0xE827, 0, 0x7077,
- 0x7074, 0, 0, 0x4951, 0x4D6A, 0x7078, 0xE829, 0,
-};
-const unsigned short utf8_to_euc_E9A1[] = {
- 0, 0, 0, 0, 0xE82A, 0, 0x7079, 0xE82B,
- 0, 0, 0xE82C, 0x707B, 0x426A, 0x335B, 0x335C, 0x707A,
- 0, 0xE82D, 0xE82E, 0xE82F, 0x3469, 0x3832, 0xE830, 0xE831,
- 0x346A, 0xE832, 0xE833, 0x453F, 0, 0, 0x4E60, 0,
- 0, 0, 0xE834, 0xE835, 0, 0xE836, 0xE837, 0x385C,
- 0, 0, 0xE838, 0x707C, 0xE839, 0, 0, 0x707D,
- 0x707E, 0x7121, 0, 0x7123, 0x7122, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E9A2[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x4977, 0, 0x7124, 0xE83A, 0, 0xE83B, 0xE83C, 0x7125,
- 0xE83D, 0x7126, 0, 0, 0xE83E, 0, 0x7127, 0xE83F,
- 0xE840, 0, 0xE841, 0xE842, 0, 0, 0, 0xE843,
-};
-const unsigned short utf8_to_euc_E9A3[] = {
- 0, 0, 0xE844, 0x7129, 0x7128, 0xE845, 0x712A, 0,
- 0xE846, 0, 0, 0, 0xE847, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x4874, 0x664C, 0, 0, 0x3F29,
- 0, 0xE848, 0x3532, 0xE849, 0, 0xE84A, 0xE84B, 0xE84C,
- 0, 0x712B, 0xE84D, 0x712C, 0, 0x522C, 0x5D3B, 0x4853,
- 0, 0, 0x307B, 0xE84E, 0x303B, 0, 0xE84F, 0,
- 0, 0, 0, 0, 0x3B74, 0x4B30, 0x3E7E, 0,
-};
-const unsigned short utf8_to_euc_E9A4[] = {
- 0, 0, 0xE850, 0x712D, 0, 0x4C5F, 0, 0xE851,
- 0xE852, 0x712E, 0x4D5C, 0, 0x3142, 0, 0, 0,
- 0x3B41, 0xE853, 0x712F, 0x326E, 0x7130, 0xE854, 0xE855, 0xE856,
- 0x7131, 0, 0xE857, 0xE858, 0xE859, 0x7133, 0x7134, 0xE85A,
- 0x7136, 0x7132, 0xE85B, 0, 0x7135, 0, 0xE85C, 0xE85D,
- 0x345B, 0, 0, 0xE85E, 0x7137, 0, 0x7138, 0,
- 0, 0xE85F, 0xE860, 0xE861, 0xE862, 0xE863, 0, 0,
- 0, 0xE864, 0xE865, 0xE866, 0xE867, 0x7139, 0x713A, 0,
-};
-const unsigned short utf8_to_euc_E9A5[] = {
- 0xE868, 0xE869, 0x713B, 0, 0, 0x713D, 0xE86A, 0xE86B,
- 0xE86C, 0x713C, 0, 0x713F, 0x7142, 0xE86D, 0xE86E, 0,
- 0x713E, 0x7140, 0x7141, 0, 0xE86F, 0x7143, 0, 0x3642,
- 0xE870, 0xE871, 0, 0xE872, 0xE873, 0, 0xE874, 0xE875,
- 0xE876, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E9A6[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x3C73, 0x7144,
- 0x7145, 0x3961, 0, 0xE877, 0, 0xE878, 0xF47A, 0xE879,
- 0, 0, 0, 0, 0, 0x7146, 0xE87A, 0,
- 0x333E, 0, 0, 0, 0x474F, 0x7147, 0x7148, 0,
- 0xE87B, 0xE87C, 0xE87D, 0x435A, 0x466B, 0xE87E, 0, 0,
- 0, 0xE921, 0xE922, 0, 0x7149, 0xE923, 0, 0xE924,
-};
-const unsigned short utf8_to_euc_E9A7[] = {
- 0, 0x477D, 0, 0xE925, 0x424C, 0x3158, 0x366E, 0,
- 0x366F, 0xE926, 0, 0, 0, 0, 0, 0,
- 0x4373, 0x714E, 0x3670, 0xE927, 0xE928, 0x326F, 0, 0,
- 0x714D, 0xE929, 0xE92A, 0x714B, 0xE92B, 0x714C, 0xE92C, 0x714A,
- 0, 0, 0x7158, 0, 0, 0, 0, 0xE92D,
- 0, 0, 0xE92E, 0xE92F, 0xE930, 0x714F, 0x7150, 0,
- 0xE931, 0x7151, 0x7152, 0, 0xE932, 0xE933, 0, 0,
- 0x7154, 0xE934, 0, 0x7153, 0, 0xE935, 0xE936, 0x3D59,
-};
-const unsigned short utf8_to_euc_E9A8[] = {
- 0, 0x7155, 0xE937, 0xE938, 0xE939, 0x7157, 0, 0,
- 0, 0, 0, 0xE93A, 0xE93B, 0, 0x3533, 0x7156,
- 0xE93C, 0xE93D, 0x417B, 0x3833, 0, 0, 0xE93E, 0,
- 0, 0x7159, 0, 0, 0, 0, 0xE93F, 0,
- 0xE940, 0, 0xE941, 0xE942, 0xE943, 0, 0, 0xE944,
- 0x424D, 0, 0, 0x715A, 0, 0xE945, 0xE946, 0,
- 0x462D, 0, 0, 0xE947, 0, 0xE948, 0xE949, 0x715B,
- 0xE94A, 0, 0, 0, 0, 0, 0x7160, 0,
-};
-const unsigned short utf8_to_euc_E9A9[] = {
- 0x715E, 0xE94C, 0x715D, 0x715F, 0xE94D, 0x715C, 0, 0xE94B,
- 0, 0, 0xE94E, 0xE94F, 0xE950, 0x7162, 0xE951, 0,
- 0, 0xE952, 0, 0, 0xE953, 0x7161, 0xE954, 0x7164,
- 0, 0, 0x3643, 0x7163, 0, 0xE955, 0, 0x7165,
- 0, 0, 0x7166, 0, 0x7168, 0x7167, 0, 0,
- 0, 0x7169, 0x716B, 0x716A, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E9AA[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x397C, 0, 0xE956, 0, 0xE957, 0x716C, 0xE958, 0xE959,
- 0x716D, 0, 0xE95A, 0, 0xE95B, 0xE95C, 0xE95D, 0,
- 0x333C, 0xE95E, 0, 0xE95F, 0x716E, 0, 0xE960, 0xE961,
-};
-const unsigned short utf8_to_euc_E9AB[] = {
- 0x716F, 0xE962, 0, 0xE963, 0x3F71, 0, 0xE964, 0,
- 0xE965, 0, 0, 0, 0, 0, 0xE966, 0x7170,
- 0xE967, 0x7171, 0xE968, 0x7172, 0x7173, 0xE969, 0xE96A, 0xE96B,
- 0x3962, 0xF47B, 0, 0xE96C, 0xE96D, 0, 0x7174, 0x7175,
- 0xE96E, 0, 0x7176, 0x7177, 0xE96F, 0xE970, 0x7178, 0xE971,
- 0, 0xE972, 0x4831, 0x717A, 0xE973, 0x4926, 0x717B, 0x7179,
- 0, 0x717D, 0xE974, 0xE975, 0x717C, 0xE976, 0, 0x717E,
- 0, 0xE977, 0xE978, 0x7221, 0, 0xE979, 0, 0xE97A,
-};
-const unsigned short utf8_to_euc_E9AC[] = {
- 0xE97B, 0xE97C, 0xE97D, 0xE97E, 0xEA21, 0xEA22, 0x7222, 0,
- 0xEA23, 0xEA24, 0, 0xEA25, 0xEA26, 0xEA27, 0xEA28, 0,
- 0xEA29, 0, 0xEA2A, 0, 0, 0, 0xEA2B, 0,
- 0x7223, 0xEA2C, 0x7224, 0xEA2D, 0xEA2E, 0, 0, 0x7225,
- 0xEA2F, 0, 0x7226, 0x7227, 0, 0x7228, 0xEA30, 0x7229,
- 0x722A, 0x722B, 0x722C, 0xEA31, 0, 0xEA32, 0x722D, 0x722E,
- 0, 0x5D35, 0x722F, 0xEA33, 0xEA34, 0xEA35, 0, 0xEA36,
- 0, 0xEA37, 0xEA38, 0x6478, 0x3534, 0xEA39, 0, 0,
-};
-const unsigned short utf8_to_euc_E9AD[] = {
- 0, 0x3321, 0x3A32, 0x7231, 0x7230, 0x4C25, 0, 0,
- 0xEA3A, 0, 0, 0xEA3B, 0xEA3C, 0x7233, 0x7234, 0x7232,
- 0, 0x7235, 0, 0, 0x4B62, 0xEA3D, 0xEA3E, 0xEA3F,
- 0x7236, 0, 0x357B, 0xEA40, 0, 0, 0xEA41, 0,
- 0, 0xEA42, 0, 0xEA43, 0, 0xEA44, 0xEA45, 0,
- 0xEA46, 0, 0xEA47, 0xEA48, 0xEA49, 0xEA4A, 0xEA4B, 0x4F25,
- 0, 0, 0xF47C, 0xEA4C, 0x7237, 0xEA4D, 0, 0xEA4E,
- 0xEA4F, 0xEA50, 0, 0, 0, 0, 0, 0xEA51,
-};
-const unsigned short utf8_to_euc_E9AE[] = {
- 0xEA52, 0, 0, 0x7239, 0xEA53, 0xEA54, 0xEA55, 0xEA56,
- 0, 0xEA57, 0xEA58, 0xEA59, 0, 0xEA5A, 0x303E, 0xEA5B,
- 0xEA5C, 0x723A, 0x4A2B, 0x7238, 0xEA5D, 0, 0x723B, 0x723C,
- 0, 0, 0xEA5E, 0, 0, 0xEA5F, 0xEA60, 0x723D,
- 0x723E, 0, 0, 0, 0, 0, 0xEA61, 0xEA62,
- 0x723F, 0xEA63, 0x4B6E, 0x3B2D, 0xEA64, 0x3A7A, 0x412F, 0,
- 0xEA65, 0xEA66, 0xEA67, 0, 0x7240, 0, 0, 0xEA68,
- 0xEA69, 0x7243, 0, 0xEA6A, 0xEA6B, 0, 0xEA6C, 0xEA6D,
-};
-const unsigned short utf8_to_euc_E9AF[] = {
- 0x7241, 0xEA6E, 0, 0, 0, 0, 0x7244, 0xEA6F,
- 0xEA70, 0x3871, 0x7242, 0, 0, 0, 0xEA71, 0x7245,
- 0xEA72, 0x7246, 0x7247, 0, 0x724B, 0, 0x3B2A, 0xEA73,
- 0xEA74, 0, 0, 0x4264, 0, 0xEA75, 0, 0xEA76,
- 0, 0x724C, 0x7249, 0x7248, 0x724A, 0xEA77, 0, 0xEA78,
- 0x375F, 0, 0xEA79, 0xEA7A, 0, 0, 0, 0xEA7B,
- 0x7250, 0x724F, 0x724E, 0xEA7C, 0, 0x3033, 0, 0xEA7D,
- 0xEA7E, 0xEB21, 0xEB22, 0, 0, 0xEB23, 0, 0xEB24,
-};
-const unsigned short utf8_to_euc_E9B0[] = {
- 0xEB25, 0, 0xEB26, 0, 0x725A, 0, 0x7256, 0,
- 0x7257, 0x7253, 0x7259, 0xEB27, 0x7255, 0x3362, 0, 0xEB28,
- 0x4F4C, 0xEB29, 0x7258, 0x7254, 0x7252, 0x7251, 0xEB2A, 0,
- 0xEB2B, 0xEB2C, 0xEB2D, 0x725C, 0xEB2E, 0, 0xEB2F, 0,
- 0, 0x725F, 0xEB30, 0xEB31, 0x725E, 0x725D, 0xEB32, 0xEB33,
- 0xEB34, 0xEB35, 0xEB36, 0, 0, 0x4949, 0x725B, 0x3073,
- 0x7260, 0xEB37, 0x7262, 0, 0, 0xEB38, 0xEB39, 0xEB3A,
- 0, 0x336F, 0x724D, 0x3137, 0, 0xEB3B, 0x7264, 0,
-};
-const unsigned short utf8_to_euc_E9B1[] = {
- 0, 0xEB3C, 0, 0xEB3D, 0xEB3E, 0xEB3F, 0x7263, 0x7261,
- 0x432D, 0xEB40, 0xEB41, 0, 0, 0, 0xEB42, 0xEB43,
- 0xEB44, 0, 0x4B70, 0xEB45, 0xEB46, 0, 0xEB47, 0x4E5A,
- 0xEB48, 0, 0x7265, 0xEB49, 0xEB50, 0xEB4A, 0xEB4B, 0xEB4C,
- 0x7266, 0, 0, 0xEB4D, 0, 0, 0, 0x7267,
- 0xEB52, 0xEB4E, 0xEB4F, 0xEB51, 0, 0, 0xEB53, 0,
- 0xEB54, 0, 0xEB55, 0, 0, 0xEB56, 0x7268, 0xEB57,
- 0x7269, 0, 0, 0xEB58, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E9B3[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x443B, 0xEB59, 0x726A,
- 0, 0x4837, 0, 0x726F, 0x726B, 0, 0, 0,
- 0x726C, 0, 0xEB5A, 0x4B31, 0x4C44, 0, 0x4650, 0xEB5B,
- 0, 0xEB5C, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E9B4[] = {
- 0, 0, 0xEB5E, 0x7270, 0, 0, 0x7271, 0x463E,
- 0x726E, 0x726D, 0, 0xEB5D, 0, 0, 0x322A, 0,
- 0, 0xEB5F, 0x7279, 0, 0, 0x7278, 0, 0xEB60,
- 0xEB61, 0, 0, 0x3175, 0xEB62, 0xEB63, 0xEB64, 0x7276,
- 0, 0, 0, 0x7275, 0, 0, 0x7273, 0,
- 0x337B, 0, 0x7272, 0x3C32, 0x3229, 0, 0, 0xEB65,
- 0xEB66, 0, 0xEB67, 0xEB68, 0xEB69, 0, 0, 0,
- 0, 0, 0xEB6A, 0x3963, 0xEB6B, 0xEB6D, 0x727C, 0x727B,
-};
-const unsigned short utf8_to_euc_E9B5[] = {
- 0, 0x727A, 0xEB6E, 0xEB6F, 0x7277, 0xEB6C, 0x727D, 0xEB70,
- 0x727E, 0, 0xEB71, 0, 0, 0, 0, 0,
- 0x7325, 0x7324, 0, 0xEB72, 0xEB73, 0, 0, 0,
- 0, 0x7326, 0, 0, 0x312D, 0x7321, 0x7322, 0xEB74,
- 0x3974, 0x4C39, 0xEB76, 0xEB75, 0x7323, 0xEB77, 0, 0,
- 0, 0xEB78, 0xEB79, 0xEB7A, 0x4B32, 0, 0, 0x732B,
- 0xEB7B, 0, 0x7327, 0, 0, 0, 0xEB7C, 0xEB7D,
- 0, 0, 0x732C, 0xEB7E, 0xEC21, 0, 0xEC22, 0,
-};
-const unsigned short utf8_to_euc_E9B6[] = {
- 0, 0, 0, 0xEC23, 0xEC24, 0, 0xEC25, 0x7329,
- 0, 0x7328, 0xEC26, 0, 0, 0xEC27, 0xEC28, 0x375C,
- 0, 0, 0xEC29, 0xEC2A, 0, 0xEC2B, 0xEC2C, 0xEC2D,
- 0xEC2E, 0, 0x732D, 0, 0, 0, 0, 0,
- 0, 0xEC2F, 0, 0, 0x732E, 0, 0, 0,
- 0, 0x732F, 0xEC30, 0x732A, 0xEC31, 0, 0xEC32, 0x7274,
- 0, 0xEC33, 0x7330, 0, 0x4461, 0xEC34, 0, 0,
- 0x7334, 0xEC35, 0x7335, 0x7333, 0xEC36, 0, 0, 0xEC37,
-};
-const unsigned short utf8_to_euc_E9B7[] = {
- 0, 0x7332, 0x7338, 0xEC38, 0x7331, 0, 0x7336, 0xEC39,
- 0, 0xEC3A, 0xEC3B, 0, 0, 0, 0, 0x7337,
- 0, 0, 0, 0x733A, 0xEC3C, 0xEC3D, 0xEC3E, 0xEC3F,
- 0, 0x7339, 0xEC40, 0, 0, 0, 0xEC41, 0xEC42,
- 0xEC43, 0, 0, 0, 0, 0xEC44, 0x733C, 0xEC45,
- 0, 0xEC46, 0, 0xEC47, 0, 0x733D, 0xEC48, 0x733E,
- 0xEC49, 0, 0x4F49, 0xEC4A, 0xEC4B, 0, 0, 0,
- 0x733B, 0x426B, 0x3A6D, 0, 0, 0x733F, 0xEC4C, 0,
-};
-const unsigned short utf8_to_euc_E9B8[] = {
- 0, 0, 0xEC4E, 0, 0, 0, 0, 0xEC4F,
- 0, 0, 0xEC4D, 0, 0, 0, 0xEC50, 0,
- 0xEC51, 0xEC52, 0xEC53, 0, 0, 0xEC54, 0xEC55, 0,
- 0, 0xEC56, 0x7340, 0x7341, 0xEC57, 0xEC58, 0x7342, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_E9B9[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x7343, 0, 0,
- 0x3834, 0x7344, 0xEC59, 0xEC5A, 0xEC5B, 0x7345, 0, 0x3C2F,
-};
-const unsigned short utf8_to_euc_E9BA[] = {
- 0xEC5C, 0x7346, 0xEC5D, 0xEC5E, 0xEC5F, 0xEC60, 0, 0xEC61,
- 0x7347, 0, 0, 0x7348, 0x7349, 0, 0xEC62, 0xEC63,
- 0, 0x734C, 0x734A, 0x4F3C, 0, 0x734B, 0xEC64, 0x4E6F,
- 0xEC65, 0, 0, 0xEC66, 0, 0x734D, 0xEC67, 0x4E5B,
- 0, 0, 0, 0, 0xEC68, 0x734E, 0x477E, 0,
- 0xEC69, 0x734F, 0x7351, 0, 0xEC6A, 0x7352, 0xEC6B, 0xEC6C,
- 0xEC6D, 0, 0, 0xEC6E, 0xEC6F, 0xEC70, 0, 0,
- 0x7350, 0x396D, 0x4C4D, 0x4B63, 0x5677, 0, 0x5D60, 0x4B7B,
-};
-const unsigned short utf8_to_euc_E9BB[] = {
- 0, 0, 0, 0, 0x322B, 0, 0xEC71, 0,
- 0xEC72, 0, 0, 0xEC73, 0x7354, 0x3550, 0x7355, 0x7356,
- 0x7357, 0xF47E, 0x3975, 0, 0x7358, 0xEC74, 0, 0,
- 0x6054, 0x4C5B, 0, 0x4263, 0x7359, 0x735B, 0x735A, 0xEC75,
- 0x735C, 0, 0, 0, 0xEC76, 0x735D, 0, 0xEC77,
- 0x735E, 0, 0, 0, 0xEC78, 0xEC79, 0xEC7A, 0x735F,
- 0xEC7B, 0xEC7C, 0xEC7D, 0, 0x7360, 0xEC7E, 0x7361, 0x7362,
- 0xED21, 0x7363, 0, 0x7364, 0x7365, 0x7366, 0, 0xED22,
-};
-const unsigned short utf8_to_euc_E9BC[] = {
- 0, 0, 0xED23, 0xED24, 0, 0, 0, 0x7367,
- 0x7368, 0xED25, 0, 0, 0, 0, 0x4524, 0xED26,
- 0xED27, 0xED28, 0xED29, 0x385D, 0xED2A, 0x736A, 0xED2B, 0xED2C,
- 0, 0xED2D, 0xED2E, 0xED2F, 0, 0, 0, 0xED30,
- 0x414D, 0x736B, 0xED31, 0, 0, 0, 0xED32, 0,
- 0, 0, 0xED33, 0xED34, 0x736C, 0, 0, 0xED35,
- 0, 0xED36, 0xED37, 0, 0xED38, 0, 0, 0xED39,
- 0, 0xED3A, 0xED3B, 0x4921, 0xED3C, 0xED3D, 0x736D, 0xED3E,
-};
-const unsigned short utf8_to_euc_E9BD[] = {
- 0, 0xED3F, 0, 0xED40, 0xED41, 0xED42, 0xED43, 0xED44,
- 0, 0, 0x736E, 0x6337, 0, 0, 0x6C5A, 0x706D,
- 0, 0, 0x736F, 0xED45, 0x7370, 0xED46, 0xED47, 0xED48,
- 0xED49, 0, 0xED4A, 0, 0, 0xED4B, 0xED4C, 0x7372,
- 0x7373, 0x7374, 0x4E70, 0x7371, 0, 0, 0x7375, 0x7376,
- 0xED4D, 0xED4E, 0x7378, 0, 0x7377, 0xED4F, 0xED50, 0xED51,
- 0xED52, 0xED53, 0x737A, 0xED54, 0, 0xED55, 0x737B, 0x7379,
- 0, 0, 0xED56, 0, 0, 0xED57, 0, 0,
-};
-const unsigned short utf8_to_euc_E9BE[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x4E36, 0, 0xED58,
- 0xED59, 0xED5A, 0xED5B, 0, 0xED5C, 0x737C, 0xED5D, 0xED5E,
- 0, 0, 0, 0, 0x737D, 0x6354, 0xED5F, 0,
- 0x737E, 0xED60, 0xED61, 0xED62, 0, 0xED63, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_EFA4[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xF445, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_EFA7[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xF472, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_EFA8[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xF434, 0xF437,
- 0xF438, 0xF43D, 0xF444, 0xF447, 0xF448, 0xF44E, 0xF44F, 0xF453,
- 0xF455, 0xF456, 0xF457, 0xF458, 0xF45A, 0xF45B, 0xF45E, 0xF460,
- 0xF462, 0xF463, 0xF465, 0xF469, 0xF46A, 0xF46B, 0xF46D, 0xF46F,
- 0xF470, 0xF473, 0xF477, 0xF478, 0xF479, 0xF47D, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_EFBC[] = {
- 0, 0x212A, 0xF42A, 0x2174, 0x2170, 0x2173, 0x2175, 0xF429,
- 0x214A, 0x214B, 0x2176, 0x215C, 0x2124, 0x215D, 0x2125, 0x213F,
- 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337,
- 0x2338, 0x2339, 0x2127, 0x2128, 0x2163, 0x2161, 0x2164, 0x2129,
- 0x2177, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347,
- 0x2348, 0x2349, 0x234A, 0x234B, 0x234C, 0x234D, 0x234E, 0x234F,
- 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357,
- 0x2358, 0x2359, 0x235A, 0x214E, 0x2140, 0x214F, 0x2130, 0x2132,
-};
-const unsigned short utf8_to_euc_EFBD[] = {
- 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367,
- 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F,
- 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377,
- 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0xA237, 0,
- 0, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
- 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
- 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
- 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F,
-};
-const unsigned short utf8_to_euc_EFBD_ms[] = {
- 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367,
- 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F,
- 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377,
- 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0x2141, 0,
- 0, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
- 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
- 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
- 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F,
-};
-const unsigned short utf8_to_euc_EFBE[] = {
- 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
- 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
- 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
- 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0E5C, 0x0E5D, 0x0E5E, 0x0E5F,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short utf8_to_euc_EFBF[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2171, 0x2172, 0x224C, 0x2131, 0xA243, 0x216F, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short *const utf8_to_euc_E2[] = {
- utf8_to_euc_E280, 0, 0, 0,
- utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287,
- utf8_to_euc_E288, utf8_to_euc_E289, utf8_to_euc_E28A, 0,
- utf8_to_euc_E28C, 0, 0, 0,
- 0, utf8_to_euc_E291, 0, 0,
- utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297,
- utf8_to_euc_E298, utf8_to_euc_E299, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const utf8_to_euc_E2_ms[] = {
- utf8_to_euc_E280_ms, 0, 0, 0,
- utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287,
- utf8_to_euc_E288, utf8_to_euc_E289, utf8_to_euc_E28A, 0,
- utf8_to_euc_E28C, 0, 0, 0,
- 0, utf8_to_euc_E291, 0, 0,
- utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297,
- utf8_to_euc_E298, utf8_to_euc_E299, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const utf8_to_euc_E2_932[] = {
- utf8_to_euc_E280_932, 0, 0, 0,
- utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287,
- utf8_to_euc_E288_932, utf8_to_euc_E289, utf8_to_euc_E28A, 0,
- utf8_to_euc_E28C, 0, 0, 0,
- 0, utf8_to_euc_E291, 0, 0,
- utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297,
- utf8_to_euc_E298, utf8_to_euc_E299, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const utf8_to_euc_E3[] = {
- utf8_to_euc_E380, utf8_to_euc_E381, utf8_to_euc_E382, utf8_to_euc_E383,
- 0, 0, 0, 0,
- utf8_to_euc_E388, 0, utf8_to_euc_E38A, 0,
- utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const utf8_to_euc_E3_932[] = {
- utf8_to_euc_E380_932, utf8_to_euc_E381, utf8_to_euc_E382_932, utf8_to_euc_E383,
- 0, 0, 0, 0,
- utf8_to_euc_E388, 0, utf8_to_euc_E38A, 0,
- utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const utf8_to_euc_E4[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_E4B8, utf8_to_euc_E4B9, utf8_to_euc_E4BA, utf8_to_euc_E4BB,
- utf8_to_euc_E4BC, utf8_to_euc_E4BD, utf8_to_euc_E4BE, utf8_to_euc_E4BF,
-};
-const unsigned short *const utf8_to_euc_E5[] = {
- utf8_to_euc_E580, utf8_to_euc_E581, utf8_to_euc_E582, utf8_to_euc_E583,
- utf8_to_euc_E584, utf8_to_euc_E585, utf8_to_euc_E586, utf8_to_euc_E587,
- utf8_to_euc_E588, utf8_to_euc_E589, utf8_to_euc_E58A, utf8_to_euc_E58B,
- utf8_to_euc_E58C, utf8_to_euc_E58D, utf8_to_euc_E58E, utf8_to_euc_E58F,
- utf8_to_euc_E590, utf8_to_euc_E591, utf8_to_euc_E592, utf8_to_euc_E593,
- utf8_to_euc_E594, utf8_to_euc_E595, utf8_to_euc_E596, utf8_to_euc_E597,
- utf8_to_euc_E598, utf8_to_euc_E599, utf8_to_euc_E59A, utf8_to_euc_E59B,
- utf8_to_euc_E59C, utf8_to_euc_E59D, utf8_to_euc_E59E, utf8_to_euc_E59F,
- utf8_to_euc_E5A0, utf8_to_euc_E5A1, utf8_to_euc_E5A2, utf8_to_euc_E5A3,
- utf8_to_euc_E5A4, utf8_to_euc_E5A5, utf8_to_euc_E5A6, utf8_to_euc_E5A7,
- utf8_to_euc_E5A8, utf8_to_euc_E5A9, utf8_to_euc_E5AA, utf8_to_euc_E5AB,
- utf8_to_euc_E5AC, utf8_to_euc_E5AD, utf8_to_euc_E5AE, utf8_to_euc_E5AF,
- utf8_to_euc_E5B0, utf8_to_euc_E5B1, utf8_to_euc_E5B2, utf8_to_euc_E5B3,
- utf8_to_euc_E5B4, utf8_to_euc_E5B5, utf8_to_euc_E5B6, utf8_to_euc_E5B7,
- utf8_to_euc_E5B8, utf8_to_euc_E5B9, utf8_to_euc_E5BA, utf8_to_euc_E5BB,
- utf8_to_euc_E5BC, utf8_to_euc_E5BD, utf8_to_euc_E5BE, utf8_to_euc_E5BF,
-};
-const unsigned short *const utf8_to_euc_E6[] = {
- utf8_to_euc_E680, utf8_to_euc_E681, utf8_to_euc_E682, utf8_to_euc_E683,
- utf8_to_euc_E684, utf8_to_euc_E685, utf8_to_euc_E686, utf8_to_euc_E687,
- utf8_to_euc_E688, utf8_to_euc_E689, utf8_to_euc_E68A, utf8_to_euc_E68B,
- utf8_to_euc_E68C, utf8_to_euc_E68D, utf8_to_euc_E68E, utf8_to_euc_E68F,
- utf8_to_euc_E690, utf8_to_euc_E691, utf8_to_euc_E692, utf8_to_euc_E693,
- utf8_to_euc_E694, utf8_to_euc_E695, utf8_to_euc_E696, utf8_to_euc_E697,
- utf8_to_euc_E698, utf8_to_euc_E699, utf8_to_euc_E69A, utf8_to_euc_E69B,
- utf8_to_euc_E69C, utf8_to_euc_E69D, utf8_to_euc_E69E, utf8_to_euc_E69F,
- utf8_to_euc_E6A0, utf8_to_euc_E6A1, utf8_to_euc_E6A2, utf8_to_euc_E6A3,
- utf8_to_euc_E6A4, utf8_to_euc_E6A5, utf8_to_euc_E6A6, utf8_to_euc_E6A7,
- utf8_to_euc_E6A8, utf8_to_euc_E6A9, utf8_to_euc_E6AA, utf8_to_euc_E6AB,
- utf8_to_euc_E6AC, utf8_to_euc_E6AD, utf8_to_euc_E6AE, utf8_to_euc_E6AF,
- utf8_to_euc_E6B0, utf8_to_euc_E6B1, utf8_to_euc_E6B2, utf8_to_euc_E6B3,
- utf8_to_euc_E6B4, utf8_to_euc_E6B5, utf8_to_euc_E6B6, utf8_to_euc_E6B7,
- utf8_to_euc_E6B8, utf8_to_euc_E6B9, utf8_to_euc_E6BA, utf8_to_euc_E6BB,
- utf8_to_euc_E6BC, utf8_to_euc_E6BD, utf8_to_euc_E6BE, utf8_to_euc_E6BF,
-};
-const unsigned short *const utf8_to_euc_E7[] = {
- utf8_to_euc_E780, utf8_to_euc_E781, utf8_to_euc_E782, utf8_to_euc_E783,
- utf8_to_euc_E784, utf8_to_euc_E785, utf8_to_euc_E786, utf8_to_euc_E787,
- utf8_to_euc_E788, utf8_to_euc_E789, utf8_to_euc_E78A, utf8_to_euc_E78B,
- utf8_to_euc_E78C, utf8_to_euc_E78D, utf8_to_euc_E78E, utf8_to_euc_E78F,
- utf8_to_euc_E790, utf8_to_euc_E791, utf8_to_euc_E792, utf8_to_euc_E793,
- utf8_to_euc_E794, utf8_to_euc_E795, utf8_to_euc_E796, utf8_to_euc_E797,
- utf8_to_euc_E798, utf8_to_euc_E799, utf8_to_euc_E79A, utf8_to_euc_E79B,
- utf8_to_euc_E79C, utf8_to_euc_E79D, utf8_to_euc_E79E, utf8_to_euc_E79F,
- utf8_to_euc_E7A0, utf8_to_euc_E7A1, utf8_to_euc_E7A2, utf8_to_euc_E7A3,
- utf8_to_euc_E7A4, utf8_to_euc_E7A5, utf8_to_euc_E7A6, utf8_to_euc_E7A7,
- utf8_to_euc_E7A8, utf8_to_euc_E7A9, utf8_to_euc_E7AA, utf8_to_euc_E7AB,
- utf8_to_euc_E7AC, utf8_to_euc_E7AD, utf8_to_euc_E7AE, utf8_to_euc_E7AF,
- utf8_to_euc_E7B0, utf8_to_euc_E7B1, utf8_to_euc_E7B2, utf8_to_euc_E7B3,
- utf8_to_euc_E7B4, utf8_to_euc_E7B5, utf8_to_euc_E7B6, utf8_to_euc_E7B7,
- utf8_to_euc_E7B8, utf8_to_euc_E7B9, utf8_to_euc_E7BA, 0,
- utf8_to_euc_E7BC, utf8_to_euc_E7BD, utf8_to_euc_E7BE, utf8_to_euc_E7BF,
-};
-const unsigned short *const utf8_to_euc_E8[] = {
- utf8_to_euc_E880, utf8_to_euc_E881, utf8_to_euc_E882, utf8_to_euc_E883,
- utf8_to_euc_E884, utf8_to_euc_E885, utf8_to_euc_E886, utf8_to_euc_E887,
- utf8_to_euc_E888, utf8_to_euc_E889, utf8_to_euc_E88A, utf8_to_euc_E88B,
- utf8_to_euc_E88C, utf8_to_euc_E88D, utf8_to_euc_E88E, utf8_to_euc_E88F,
- utf8_to_euc_E890, utf8_to_euc_E891, utf8_to_euc_E892, utf8_to_euc_E893,
- utf8_to_euc_E894, utf8_to_euc_E895, utf8_to_euc_E896, utf8_to_euc_E897,
- utf8_to_euc_E898, utf8_to_euc_E899, utf8_to_euc_E89A, utf8_to_euc_E89B,
- utf8_to_euc_E89C, utf8_to_euc_E89D, utf8_to_euc_E89E, utf8_to_euc_E89F,
- utf8_to_euc_E8A0, utf8_to_euc_E8A1, utf8_to_euc_E8A2, utf8_to_euc_E8A3,
- utf8_to_euc_E8A4, utf8_to_euc_E8A5, utf8_to_euc_E8A6, utf8_to_euc_E8A7,
- utf8_to_euc_E8A8, utf8_to_euc_E8A9, utf8_to_euc_E8AA, utf8_to_euc_E8AB,
- utf8_to_euc_E8AC, utf8_to_euc_E8AD, utf8_to_euc_E8AE, 0,
- utf8_to_euc_E8B0, utf8_to_euc_E8B1, utf8_to_euc_E8B2, utf8_to_euc_E8B3,
- utf8_to_euc_E8B4, utf8_to_euc_E8B5, utf8_to_euc_E8B6, utf8_to_euc_E8B7,
- utf8_to_euc_E8B8, utf8_to_euc_E8B9, utf8_to_euc_E8BA, utf8_to_euc_E8BB,
- utf8_to_euc_E8BC, utf8_to_euc_E8BD, utf8_to_euc_E8BE, utf8_to_euc_E8BF,
-};
-const unsigned short *const utf8_to_euc_E9[] = {
- utf8_to_euc_E980, utf8_to_euc_E981, utf8_to_euc_E982, utf8_to_euc_E983,
- utf8_to_euc_E984, utf8_to_euc_E985, utf8_to_euc_E986, utf8_to_euc_E987,
- utf8_to_euc_E988, utf8_to_euc_E989, utf8_to_euc_E98A, utf8_to_euc_E98B,
- utf8_to_euc_E98C, utf8_to_euc_E98D, utf8_to_euc_E98E, utf8_to_euc_E98F,
- utf8_to_euc_E990, utf8_to_euc_E991, utf8_to_euc_E992, 0,
- 0, utf8_to_euc_E995, utf8_to_euc_E996, utf8_to_euc_E997,
- utf8_to_euc_E998, utf8_to_euc_E999, utf8_to_euc_E99A, utf8_to_euc_E99B,
- utf8_to_euc_E99C, utf8_to_euc_E99D, utf8_to_euc_E99E, utf8_to_euc_E99F,
- utf8_to_euc_E9A0, utf8_to_euc_E9A1, utf8_to_euc_E9A2, utf8_to_euc_E9A3,
- utf8_to_euc_E9A4, utf8_to_euc_E9A5, utf8_to_euc_E9A6, utf8_to_euc_E9A7,
- utf8_to_euc_E9A8, utf8_to_euc_E9A9, utf8_to_euc_E9AA, utf8_to_euc_E9AB,
- utf8_to_euc_E9AC, utf8_to_euc_E9AD, utf8_to_euc_E9AE, utf8_to_euc_E9AF,
- utf8_to_euc_E9B0, utf8_to_euc_E9B1, 0, utf8_to_euc_E9B3,
- utf8_to_euc_E9B4, utf8_to_euc_E9B5, utf8_to_euc_E9B6, utf8_to_euc_E9B7,
- utf8_to_euc_E9B8, utf8_to_euc_E9B9, utf8_to_euc_E9BA, utf8_to_euc_E9BB,
- utf8_to_euc_E9BC, utf8_to_euc_E9BD, utf8_to_euc_E9BE, 0,
-};
-const unsigned short *const utf8_to_euc_EF[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_EFA4, 0, 0, utf8_to_euc_EFA7,
- utf8_to_euc_EFA8, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_EFBC, utf8_to_euc_EFBD, utf8_to_euc_EFBE, utf8_to_euc_EFBF,
-};
-const unsigned short *const utf8_to_euc_EF_ms[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_EFA4, 0, 0, utf8_to_euc_EFA7,
- utf8_to_euc_EFA8, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_EFBC, utf8_to_euc_EFBD_ms, utf8_to_euc_EFBE, utf8_to_euc_EFBF,
-};
-const unsigned short *const utf8_to_euc_2bytes[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, utf8_to_euc_C2, utf8_to_euc_C3,
- utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7,
- 0, 0, 0, utf8_to_euc_CB,
- 0, 0, utf8_to_euc_CE, utf8_to_euc_CF,
- utf8_to_euc_D0, utf8_to_euc_D1, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const utf8_to_euc_2bytes_ms[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, utf8_to_euc_C2_ms, utf8_to_euc_C3,
- utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7,
- 0, 0, 0, utf8_to_euc_CB,
- 0, 0, utf8_to_euc_CE, utf8_to_euc_CF,
- utf8_to_euc_D0, utf8_to_euc_D1, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const utf8_to_euc_2bytes_932[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, utf8_to_euc_C2_932, utf8_to_euc_C3_932,
- utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7,
- 0, 0, 0, utf8_to_euc_CB,
- 0, 0, utf8_to_euc_CE, utf8_to_euc_CF,
- utf8_to_euc_D0, utf8_to_euc_D1, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const *const utf8_to_euc_3bytes[] = {
- 0, 0, utf8_to_euc_E2, utf8_to_euc_E3,
- utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7,
- utf8_to_euc_E8, utf8_to_euc_E9, 0, 0,
- 0, 0, 0, utf8_to_euc_EF,
-};
-const unsigned short *const *const utf8_to_euc_3bytes_ms[] = {
- 0, 0, utf8_to_euc_E2_ms, utf8_to_euc_E3,
- utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7,
- utf8_to_euc_E8, utf8_to_euc_E9, 0, 0,
- 0, 0, 0, utf8_to_euc_EF_ms,
-};
-const unsigned short *const *const utf8_to_euc_3bytes_932[] = {
- 0, 0, utf8_to_euc_E2_932, utf8_to_euc_E3_932,
- utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7,
- utf8_to_euc_E8, utf8_to_euc_E9, 0, 0,
- 0, 0, 0, utf8_to_euc_EF_ms,
-};
-
-#ifdef UNICODE_NORMALIZATION
-
-/* Normalization Table by Apple */
-/* http://developer.apple.com/technotes/tn/tn1150table.html */
-
-const struct normalization_pair normalization_table[] = {
- {{0xcd,0xbe}, {0x3b}},
- {{0xc3,0x80}, {0x41,0xcc,0x80,0x00}},
- {{0xc3,0x81}, {0x41,0xcc,0x81}},
- {{0xc3,0x82}, {0x41,0xcc,0x82}},
- {{0xe1,0xba,0xa6}, {0x41,0xcc,0x82,0xcc,0x80}},
- {{0xe1,0xba,0xa4}, {0x41,0xcc,0x82,0xcc,0x81}},
- {{0xe1,0xba,0xaa}, {0x41,0xcc,0x82,0xcc,0x83}},
- {{0xe1,0xba,0xa8}, {0x41,0xcc,0x82,0xcc,0x89}},
- {{0xc3,0x83}, {0x41,0xcc,0x83}},
- {{0xc4,0x80}, {0x41,0xcc,0x84}},
- {{0xc4,0x82}, {0x41,0xcc,0x86}},
- {{0xe1,0xba,0xb0}, {0x41,0xcc,0x86,0xcc,0x80}},
- {{0xe1,0xba,0xae}, {0x41,0xcc,0x86,0xcc,0x81}},
- {{0xe1,0xba,0xb4}, {0x41,0xcc,0x86,0xcc,0x83}},
- {{0xe1,0xba,0xb2}, {0x41,0xcc,0x86,0xcc,0x89}},
- {{0xc7,0xa0}, {0x41,0xcc,0x87,0xcc,0x84}},
- {{0xc3,0x84}, {0x41,0xcc,0x88}},
- {{0xc7,0x9e}, {0x41,0xcc,0x88,0xcc,0x84}},
- {{0xe1,0xba,0xa2}, {0x41,0xcc,0x89}},
- {{0xc3,0x85}, {0x41,0xcc,0x8a}},
- {{0xc7,0xba}, {0x41,0xcc,0x8a,0xcc,0x81}},
- {{0xc7,0x8d}, {0x41,0xcc,0x8c}},
- {{0xc8,0x80}, {0x41,0xcc,0x8f}},
- {{0xc8,0x82}, {0x41,0xcc,0x91}},
- {{0xe1,0xba,0xa0}, {0x41,0xcc,0xa3}},
- {{0xe1,0xba,0xac}, {0x41,0xcc,0xa3,0xcc,0x82}},
- {{0xe1,0xba,0xb6}, {0x41,0xcc,0xa3,0xcc,0x86}},
- {{0xe1,0xb8,0x80}, {0x41,0xcc,0xa5}},
- {{0xc4,0x84}, {0x41,0xcc,0xa8}},
- {{0xe1,0xb8,0x82}, {0x42,0xcc,0x87}},
- {{0xe1,0xb8,0x84}, {0x42,0xcc,0xa3}},
- {{0xe1,0xb8,0x86}, {0x42,0xcc,0xb1}},
- {{0xc4,0x86}, {0x43,0xcc,0x81}},
- {{0xc4,0x88}, {0x43,0xcc,0x82}},
- {{0xc4,0x8a}, {0x43,0xcc,0x87}},
- {{0xc4,0x8c}, {0x43,0xcc,0x8c}},
- {{0xc3,0x87}, {0x43,0xcc,0xa7}},
- {{0xe1,0xb8,0x88}, {0x43,0xcc,0xa7,0xcc,0x81}},
- {{0xe1,0xb8,0x8a}, {0x44,0xcc,0x87}},
- {{0xc4,0x8e}, {0x44,0xcc,0x8c}},
- {{0xe1,0xb8,0x8c}, {0x44,0xcc,0xa3}},
- {{0xe1,0xb8,0x90}, {0x44,0xcc,0xa7}},
- {{0xe1,0xb8,0x92}, {0x44,0xcc,0xad}},
- {{0xe1,0xb8,0x8e}, {0x44,0xcc,0xb1}},
- {{0xc3,0x88}, {0x45,0xcc,0x80}},
- {{0xc3,0x89}, {0x45,0xcc,0x81}},
- {{0xc3,0x8a}, {0x45,0xcc,0x82}},
- {{0xe1,0xbb,0x80}, {0x45,0xcc,0x82,0xcc,0x80}},
- {{0xe1,0xba,0xbe}, {0x45,0xcc,0x82,0xcc,0x81}},
- {{0xe1,0xbb,0x84}, {0x45,0xcc,0x82,0xcc,0x83}},
- {{0xe1,0xbb,0x82}, {0x45,0xcc,0x82,0xcc,0x89}},
- {{0xe1,0xba,0xbc}, {0x45,0xcc,0x83}},
- {{0xc4,0x92}, {0x45,0xcc,0x84}},
- {{0xe1,0xb8,0x94}, {0x45,0xcc,0x84,0xcc,0x80}},
- {{0xe1,0xb8,0x96}, {0x45,0xcc,0x84,0xcc,0x81}},
- {{0xc4,0x94}, {0x45,0xcc,0x86}},
- {{0xc4,0x96}, {0x45,0xcc,0x87}},
- {{0xc3,0x8b}, {0x45,0xcc,0x88}},
- {{0xe1,0xba,0xba}, {0x45,0xcc,0x89}},
- {{0xc4,0x9a}, {0x45,0xcc,0x8c}},
- {{0xc8,0x84}, {0x45,0xcc,0x8f}},
- {{0xc8,0x86}, {0x45,0xcc,0x91}},
- {{0xe1,0xba,0xb8}, {0x45,0xcc,0xa3}},
- {{0xe1,0xbb,0x86}, {0x45,0xcc,0xa3,0xcc,0x82}},
- {{0xe1,0xb8,0x9c}, {0x45,0xcc,0xa7,0xcc,0x86}},
- {{0xc4,0x98}, {0x45,0xcc,0xa8}},
- {{0xe1,0xb8,0x98}, {0x45,0xcc,0xad}},
- {{0xe1,0xb8,0x9a}, {0x45,0xcc,0xb0}},
- {{0xe1,0xb8,0x9e}, {0x46,0xcc,0x87}},
- {{0xc7,0xb4}, {0x47,0xcc,0x81}},
- {{0xc4,0x9c}, {0x47,0xcc,0x82}},
- {{0xe1,0xb8,0xa0}, {0x47,0xcc,0x84}},
- {{0xc4,0x9e}, {0x47,0xcc,0x86}},
- {{0xc4,0xa0}, {0x47,0xcc,0x87}},
- {{0xc7,0xa6}, {0x47,0xcc,0x8c}},
- {{0xc4,0xa2}, {0x47,0xcc,0xa7}},
- {{0xc4,0xa4}, {0x48,0xcc,0x82}},
- {{0xe1,0xb8,0xa2}, {0x48,0xcc,0x87}},
- {{0xe1,0xb8,0xa6}, {0x48,0xcc,0x88}},
- {{0xe1,0xb8,0xa4}, {0x48,0xcc,0xa3}},
- {{0xe1,0xb8,0xa8}, {0x48,0xcc,0xa7}},
- {{0xe1,0xb8,0xaa}, {0x48,0xcc,0xae}},
- {{0xc3,0x8c}, {0x49,0xcc,0x80}},
- {{0xc3,0x8d}, {0x49,0xcc,0x81}},
- {{0xc3,0x8e}, {0x49,0xcc,0x82}},
- {{0xc4,0xa8}, {0x49,0xcc,0x83}},
- {{0xc4,0xaa}, {0x49,0xcc,0x84}},
- {{0xc4,0xac}, {0x49,0xcc,0x86}},
- {{0xc4,0xb0}, {0x49,0xcc,0x87}},
- {{0xc3,0x8f}, {0x49,0xcc,0x88}},
- {{0xe1,0xb8,0xae}, {0x49,0xcc,0x88,0xcc,0x81}},
- {{0xe1,0xbb,0x88}, {0x49,0xcc,0x89}},
- {{0xc7,0x8f}, {0x49,0xcc,0x8c}},
- {{0xc8,0x88}, {0x49,0xcc,0x8f}},
- {{0xc8,0x8a}, {0x49,0xcc,0x91}},
- {{0xe1,0xbb,0x8a}, {0x49,0xcc,0xa3}},
- {{0xc4,0xae}, {0x49,0xcc,0xa8}},
- {{0xe1,0xb8,0xac}, {0x49,0xcc,0xb0}},
- {{0xc4,0xb4}, {0x4a,0xcc,0x82}},
- {{0xe1,0xb8,0xb0}, {0x4b,0xcc,0x81}},
- {{0xc7,0xa8}, {0x4b,0xcc,0x8c}},
- {{0xe1,0xb8,0xb2}, {0x4b,0xcc,0xa3}},
- {{0xc4,0xb6}, {0x4b,0xcc,0xa7}},
- {{0xe1,0xb8,0xb4}, {0x4b,0xcc,0xb1}},
- {{0xc4,0xb9}, {0x4c,0xcc,0x81}},
- {{0xc4,0xbd}, {0x4c,0xcc,0x8c}},
- {{0xe1,0xb8,0xb6}, {0x4c,0xcc,0xa3}},
- {{0xe1,0xb8,0xb8}, {0x4c,0xcc,0xa3,0xcc,0x84}},
- {{0xc4,0xbb}, {0x4c,0xcc,0xa7}},
- {{0xe1,0xb8,0xbc}, {0x4c,0xcc,0xad}},
- {{0xe1,0xb8,0xba}, {0x4c,0xcc,0xb1}},
- {{0xe1,0xb8,0xbe}, {0x4d,0xcc,0x81}},
- {{0xe1,0xb9,0x80}, {0x4d,0xcc,0x87}},
- {{0xe1,0xb9,0x82}, {0x4d,0xcc,0xa3}},
- {{0xc5,0x83}, {0x4e,0xcc,0x81}},
- {{0xc3,0x91}, {0x4e,0xcc,0x83}},
- {{0xe1,0xb9,0x84}, {0x4e,0xcc,0x87}},
- {{0xc5,0x87}, {0x4e,0xcc,0x8c}},
- {{0xe1,0xb9,0x86}, {0x4e,0xcc,0xa3}},
- {{0xc5,0x85}, {0x4e,0xcc,0xa7}},
- {{0xe1,0xb9,0x8a}, {0x4e,0xcc,0xad}},
- {{0xe1,0xb9,0x88}, {0x4e,0xcc,0xb1}},
- {{0xc3,0x92}, {0x4f,0xcc,0x80}},
- {{0xc3,0x93}, {0x4f,0xcc,0x81}},
- {{0xc3,0x94}, {0x4f,0xcc,0x82}},
- {{0xe1,0xbb,0x92}, {0x4f,0xcc,0x82,0xcc,0x80}},
- {{0xe1,0xbb,0x90}, {0x4f,0xcc,0x82,0xcc,0x81}},
- {{0xe1,0xbb,0x96}, {0x4f,0xcc,0x82,0xcc,0x83}},
- {{0xe1,0xbb,0x94}, {0x4f,0xcc,0x82,0xcc,0x89}},
- {{0xc3,0x95}, {0x4f,0xcc,0x83}},
- {{0xe1,0xb9,0x8c}, {0x4f,0xcc,0x83,0xcc,0x81}},
- {{0xe1,0xb9,0x8e}, {0x4f,0xcc,0x83,0xcc,0x88}},
- {{0xc5,0x8c}, {0x4f,0xcc,0x84}},
- {{0xe1,0xb9,0x90}, {0x4f,0xcc,0x84,0xcc,0x80}},
- {{0xe1,0xb9,0x92}, {0x4f,0xcc,0x84,0xcc,0x81}},
- {{0xc5,0x8e}, {0x4f,0xcc,0x86}},
- {{0xc3,0x96}, {0x4f,0xcc,0x88}},
- {{0xe1,0xbb,0x8e}, {0x4f,0xcc,0x89}},
- {{0xc5,0x90}, {0x4f,0xcc,0x8b}},
- {{0xc7,0x91}, {0x4f,0xcc,0x8c}},
- {{0xc8,0x8c}, {0x4f,0xcc,0x8f}},
- {{0xc8,0x8e}, {0x4f,0xcc,0x91}},
- {{0xc6,0xa0}, {0x4f,0xcc,0x9b}},
- {{0xe1,0xbb,0x9c}, {0x4f,0xcc,0x9b,0xcc,0x80}},
- {{0xe1,0xbb,0x9a}, {0x4f,0xcc,0x9b,0xcc,0x81}},
- {{0xe1,0xbb,0xa0}, {0x4f,0xcc,0x9b,0xcc,0x83}},
- {{0xe1,0xbb,0x9e}, {0x4f,0xcc,0x9b,0xcc,0x89}},
- {{0xe1,0xbb,0xa2}, {0x4f,0xcc,0x9b,0xcc,0xa3}},
- {{0xe1,0xbb,0x8c}, {0x4f,0xcc,0xa3}},
- {{0xe1,0xbb,0x98}, {0x4f,0xcc,0xa3,0xcc,0x82}},
- {{0xc7,0xaa}, {0x4f,0xcc,0xa8}},
- {{0xc7,0xac}, {0x4f,0xcc,0xa8,0xcc,0x84}},
- {{0xe1,0xb9,0x94}, {0x50,0xcc,0x81}},
- {{0xe1,0xb9,0x96}, {0x50,0xcc,0x87}},
- {{0xc5,0x94}, {0x52,0xcc,0x81}},
- {{0xe1,0xb9,0x98}, {0x52,0xcc,0x87}},
- {{0xc5,0x98}, {0x52,0xcc,0x8c}},
- {{0xc8,0x90}, {0x52,0xcc,0x8f}},
- {{0xc8,0x92}, {0x52,0xcc,0x91}},
- {{0xe1,0xb9,0x9a}, {0x52,0xcc,0xa3}},
- {{0xe1,0xb9,0x9c}, {0x52,0xcc,0xa3,0xcc,0x84}},
- {{0xc5,0x96}, {0x52,0xcc,0xa7}},
- {{0xe1,0xb9,0x9e}, {0x52,0xcc,0xb1}},
- {{0xc5,0x9a}, {0x53,0xcc,0x81}},
- {{0xe1,0xb9,0xa4}, {0x53,0xcc,0x81,0xcc,0x87}},
- {{0xc5,0x9c}, {0x53,0xcc,0x82}},
- {{0xe1,0xb9,0xa0}, {0x53,0xcc,0x87}},
- {{0xc5,0xa0}, {0x53,0xcc,0x8c}},
- {{0xe1,0xb9,0xa6}, {0x53,0xcc,0x8c,0xcc,0x87}},
- {{0xe1,0xb9,0xa2}, {0x53,0xcc,0xa3}},
- {{0xe1,0xb9,0xa8}, {0x53,0xcc,0xa3,0xcc,0x87}},
- {{0xc5,0x9e}, {0x53,0xcc,0xa7}},
- {{0xe1,0xb9,0xaa}, {0x54,0xcc,0x87}},
- {{0xc5,0xa4}, {0x54,0xcc,0x8c}},
- {{0xe1,0xb9,0xac}, {0x54,0xcc,0xa3}},
- {{0xc5,0xa2}, {0x54,0xcc,0xa7}},
- {{0xe1,0xb9,0xb0}, {0x54,0xcc,0xad}},
- {{0xe1,0xb9,0xae}, {0x54,0xcc,0xb1}},
- {{0xc3,0x99}, {0x55,0xcc,0x80}},
- {{0xc3,0x9a}, {0x55,0xcc,0x81}},
- {{0xc3,0x9b}, {0x55,0xcc,0x82}},
- {{0xc5,0xa8}, {0x55,0xcc,0x83}},
- {{0xe1,0xb9,0xb8}, {0x55,0xcc,0x83,0xcc,0x81}},
- {{0xc5,0xaa}, {0x55,0xcc,0x84}},
- {{0xe1,0xb9,0xba}, {0x55,0xcc,0x84,0xcc,0x88}},
- {{0xc5,0xac}, {0x55,0xcc,0x86}},
- {{0xc3,0x9c}, {0x55,0xcc,0x88}},
- {{0xc7,0x9b}, {0x55,0xcc,0x88,0xcc,0x80}},
- {{0xc7,0x97}, {0x55,0xcc,0x88,0xcc,0x81}},
- {{0xc7,0x95}, {0x55,0xcc,0x88,0xcc,0x84}},
- {{0xc7,0x99}, {0x55,0xcc,0x88,0xcc,0x8c}},
- {{0xe1,0xbb,0xa6}, {0x55,0xcc,0x89}},
- {{0xc5,0xae}, {0x55,0xcc,0x8a}},
- {{0xc5,0xb0}, {0x55,0xcc,0x8b}},
- {{0xc7,0x93}, {0x55,0xcc,0x8c}},
- {{0xc8,0x94}, {0x55,0xcc,0x8f}},
- {{0xc8,0x96}, {0x55,0xcc,0x91}},
- {{0xc6,0xaf}, {0x55,0xcc,0x9b}},
- {{0xe1,0xbb,0xaa}, {0x55,0xcc,0x9b,0xcc,0x80}},
- {{0xe1,0xbb,0xa8}, {0x55,0xcc,0x9b,0xcc,0x81}},
- {{0xe1,0xbb,0xae}, {0x55,0xcc,0x9b,0xcc,0x83}},
- {{0xe1,0xbb,0xac}, {0x55,0xcc,0x9b,0xcc,0x89}},
- {{0xe1,0xbb,0xb0}, {0x55,0xcc,0x9b,0xcc,0xa3}},
- {{0xe1,0xbb,0xa4}, {0x55,0xcc,0xa3}},
- {{0xe1,0xb9,0xb2}, {0x55,0xcc,0xa4}},
- {{0xc5,0xb2}, {0x55,0xcc,0xa8}},
- {{0xe1,0xb9,0xb6}, {0x55,0xcc,0xad}},
- {{0xe1,0xb9,0xb4}, {0x55,0xcc,0xb0}},
- {{0xe1,0xb9,0xbc}, {0x56,0xcc,0x83}},
- {{0xe1,0xb9,0xbe}, {0x56,0xcc,0xa3}},
- {{0xe1,0xba,0x80}, {0x57,0xcc,0x80}},
- {{0xe1,0xba,0x82}, {0x57,0xcc,0x81}},
- {{0xc5,0xb4}, {0x57,0xcc,0x82}},
- {{0xe1,0xba,0x86}, {0x57,0xcc,0x87}},
- {{0xe1,0xba,0x84}, {0x57,0xcc,0x88}},
- {{0xe1,0xba,0x88}, {0x57,0xcc,0xa3}},
- {{0xe1,0xba,0x8a}, {0x58,0xcc,0x87}},
- {{0xe1,0xba,0x8c}, {0x58,0xcc,0x88}},
- {{0xe1,0xbb,0xb2}, {0x59,0xcc,0x80}},
- {{0xc3,0x9d}, {0x59,0xcc,0x81}},
- {{0xc5,0xb6}, {0x59,0xcc,0x82}},
- {{0xe1,0xbb,0xb8}, {0x59,0xcc,0x83}},
- {{0xe1,0xba,0x8e}, {0x59,0xcc,0x87}},
- {{0xc5,0xb8}, {0x59,0xcc,0x88}},
- {{0xe1,0xbb,0xb6}, {0x59,0xcc,0x89}},
- {{0xe1,0xbb,0xb4}, {0x59,0xcc,0xa3}},
- {{0xc5,0xb9}, {0x5a,0xcc,0x81}},
- {{0xe1,0xba,0x90}, {0x5a,0xcc,0x82}},
- {{0xc5,0xbb}, {0x5a,0xcc,0x87}},
- {{0xc5,0xbd}, {0x5a,0xcc,0x8c}},
- {{0xe1,0xba,0x92}, {0x5a,0xcc,0xa3}},
- {{0xe1,0xba,0x94}, {0x5a,0xcc,0xb1}},
- {{0xe1,0xbf,0xaf}, {0x60}},
- {{0xc3,0xa0}, {0x61,0xcc,0x80}},
- {{0xc3,0xa1}, {0x61,0xcc,0x81}},
- {{0xc3,0xa2}, {0x61,0xcc,0x82}},
- {{0xe1,0xba,0xa7}, {0x61,0xcc,0x82,0xcc,0x80}},
- {{0xe1,0xba,0xa5}, {0x61,0xcc,0x82,0xcc,0x81}},
- {{0xe1,0xba,0xab}, {0x61,0xcc,0x82,0xcc,0x83}},
- {{0xe1,0xba,0xa9}, {0x61,0xcc,0x82,0xcc,0x89}},
- {{0xc3,0xa3}, {0x61,0xcc,0x83}},
- {{0xc4,0x81}, {0x61,0xcc,0x84}},
- {{0xc4,0x83}, {0x61,0xcc,0x86}},
- {{0xe1,0xba,0xb1}, {0x61,0xcc,0x86,0xcc,0x80}},
- {{0xe1,0xba,0xaf}, {0x61,0xcc,0x86,0xcc,0x81}},
- {{0xe1,0xba,0xb5}, {0x61,0xcc,0x86,0xcc,0x83}},
- {{0xe1,0xba,0xb3}, {0x61,0xcc,0x86,0xcc,0x89}},
- {{0xc7,0xa1}, {0x61,0xcc,0x87,0xcc,0x84}},
- {{0xc3,0xa4}, {0x61,0xcc,0x88}},
- {{0xc7,0x9f}, {0x61,0xcc,0x88,0xcc,0x84}},
- {{0xe1,0xba,0xa3}, {0x61,0xcc,0x89}},
- {{0xc3,0xa5}, {0x61,0xcc,0x8a}},
- {{0xc7,0xbb}, {0x61,0xcc,0x8a,0xcc,0x81}},
- {{0xc7,0x8e}, {0x61,0xcc,0x8c}},
- {{0xc8,0x81}, {0x61,0xcc,0x8f}},
- {{0xc8,0x83}, {0x61,0xcc,0x91}},
- {{0xe1,0xba,0xa1}, {0x61,0xcc,0xa3}},
- {{0xe1,0xba,0xad}, {0x61,0xcc,0xa3,0xcc,0x82}},
- {{0xe1,0xba,0xb7}, {0x61,0xcc,0xa3,0xcc,0x86}},
- {{0xe1,0xb8,0x81}, {0x61,0xcc,0xa5}},
- {{0xc4,0x85}, {0x61,0xcc,0xa8}},
- {{0xe1,0xb8,0x83}, {0x62,0xcc,0x87}},
- {{0xe1,0xb8,0x85}, {0x62,0xcc,0xa3}},
- {{0xe1,0xb8,0x87}, {0x62,0xcc,0xb1}},
- {{0xc4,0x87}, {0x63,0xcc,0x81}},
- {{0xc4,0x89}, {0x63,0xcc,0x82}},
- {{0xc4,0x8b}, {0x63,0xcc,0x87}},
- {{0xc4,0x8d}, {0x63,0xcc,0x8c}},
- {{0xc3,0xa7}, {0x63,0xcc,0xa7}},
- {{0xe1,0xb8,0x89}, {0x63,0xcc,0xa7,0xcc,0x81}},
- {{0xe1,0xb8,0x8b}, {0x64,0xcc,0x87}},
- {{0xc4,0x8f}, {0x64,0xcc,0x8c}},
- {{0xe1,0xb8,0x8d}, {0x64,0xcc,0xa3}},
- {{0xe1,0xb8,0x91}, {0x64,0xcc,0xa7}},
- {{0xe1,0xb8,0x93}, {0x64,0xcc,0xad}},
- {{0xe1,0xb8,0x8f}, {0x64,0xcc,0xb1}},
- {{0xc3,0xa8}, {0x65,0xcc,0x80}},
- {{0xc3,0xa9}, {0x65,0xcc,0x81}},
- {{0xc3,0xaa}, {0x65,0xcc,0x82}},
- {{0xe1,0xbb,0x81}, {0x65,0xcc,0x82,0xcc,0x80}},
- {{0xe1,0xba,0xbf}, {0x65,0xcc,0x82,0xcc,0x81}},
- {{0xe1,0xbb,0x85}, {0x65,0xcc,0x82,0xcc,0x83}},
- {{0xe1,0xbb,0x83}, {0x65,0xcc,0x82,0xcc,0x89}},
- {{0xe1,0xba,0xbd}, {0x65,0xcc,0x83}},
- {{0xc4,0x93}, {0x65,0xcc,0x84}},
- {{0xe1,0xb8,0x95}, {0x65,0xcc,0x84,0xcc,0x80}},
- {{0xe1,0xb8,0x97}, {0x65,0xcc,0x84,0xcc,0x81}},
- {{0xc4,0x95}, {0x65,0xcc,0x86}},
- {{0xc4,0x97}, {0x65,0xcc,0x87}},
- {{0xc3,0xab}, {0x65,0xcc,0x88}},
- {{0xe1,0xba,0xbb}, {0x65,0xcc,0x89}},
- {{0xc4,0x9b}, {0x65,0xcc,0x8c}},
- {{0xc8,0x85}, {0x65,0xcc,0x8f}},
- {{0xc8,0x87}, {0x65,0xcc,0x91}},
- {{0xe1,0xba,0xb9}, {0x65,0xcc,0xa3}},
- {{0xe1,0xbb,0x87}, {0x65,0xcc,0xa3,0xcc,0x82}},
- {{0xe1,0xb8,0x9d}, {0x65,0xcc,0xa7,0xcc,0x86}},
- {{0xc4,0x99}, {0x65,0xcc,0xa8}},
- {{0xe1,0xb8,0x99}, {0x65,0xcc,0xad}},
- {{0xe1,0xb8,0x9b}, {0x65,0xcc,0xb0}},
- {{0xe1,0xb8,0x9f}, {0x66,0xcc,0x87}},
- {{0xc7,0xb5}, {0x67,0xcc,0x81}},
- {{0xc4,0x9d}, {0x67,0xcc,0x82}},
- {{0xe1,0xb8,0xa1}, {0x67,0xcc,0x84}},
- {{0xc4,0x9f}, {0x67,0xcc,0x86}},
- {{0xc4,0xa1}, {0x67,0xcc,0x87}},
- {{0xc7,0xa7}, {0x67,0xcc,0x8c}},
- {{0xc4,0xa3}, {0x67,0xcc,0xa7}},
- {{0xc4,0xa5}, {0x68,0xcc,0x82}},
- {{0xe1,0xb8,0xa3}, {0x68,0xcc,0x87}},
- {{0xe1,0xb8,0xa7}, {0x68,0xcc,0x88}},
- {{0xe1,0xb8,0xa5}, {0x68,0xcc,0xa3}},
- {{0xe1,0xb8,0xa9}, {0x68,0xcc,0xa7}},
- {{0xe1,0xb8,0xab}, {0x68,0xcc,0xae}},
- {{0xe1,0xba,0x96}, {0x68,0xcc,0xb1}},
- {{0xc3,0xac}, {0x69,0xcc,0x80}},
- {{0xc3,0xad}, {0x69,0xcc,0x81}},
- {{0xc3,0xae}, {0x69,0xcc,0x82}},
- {{0xc4,0xa9}, {0x69,0xcc,0x83}},
- {{0xc4,0xab}, {0x69,0xcc,0x84}},
- {{0xc4,0xad}, {0x69,0xcc,0x86}},
- {{0xc3,0xaf}, {0x69,0xcc,0x88}},
- {{0xe1,0xb8,0xaf}, {0x69,0xcc,0x88,0xcc,0x81}},
- {{0xe1,0xbb,0x89}, {0x69,0xcc,0x89}},
- {{0xc7,0x90}, {0x69,0xcc,0x8c}},
- {{0xc8,0x89}, {0x69,0xcc,0x8f}},
- {{0xc8,0x8b}, {0x69,0xcc,0x91}},
- {{0xe1,0xbb,0x8b}, {0x69,0xcc,0xa3}},
- {{0xc4,0xaf}, {0x69,0xcc,0xa8}},
- {{0xe1,0xb8,0xad}, {0x69,0xcc,0xb0}},
- {{0xc4,0xb5}, {0x6a,0xcc,0x82}},
- {{0xc7,0xb0}, {0x6a,0xcc,0x8c}},
- {{0xe1,0xb8,0xb1}, {0x6b,0xcc,0x81}},
- {{0xc7,0xa9}, {0x6b,0xcc,0x8c}},
- {{0xe1,0xb8,0xb3}, {0x6b,0xcc,0xa3}},
- {{0xc4,0xb7}, {0x6b,0xcc,0xa7}},
- {{0xe1,0xb8,0xb5}, {0x6b,0xcc,0xb1}},
- {{0xc4,0xba}, {0x6c,0xcc,0x81}},
- {{0xc4,0xbe}, {0x6c,0xcc,0x8c}},
- {{0xe1,0xb8,0xb7}, {0x6c,0xcc,0xa3}},
- {{0xe1,0xb8,0xb9}, {0x6c,0xcc,0xa3,0xcc,0x84}},
- {{0xc4,0xbc}, {0x6c,0xcc,0xa7}},
- {{0xe1,0xb8,0xbd}, {0x6c,0xcc,0xad}},
- {{0xe1,0xb8,0xbb}, {0x6c,0xcc,0xb1}},
- {{0xe1,0xb8,0xbf}, {0x6d,0xcc,0x81}},
- {{0xe1,0xb9,0x81}, {0x6d,0xcc,0x87}},
- {{0xe1,0xb9,0x83}, {0x6d,0xcc,0xa3}},
- {{0xc5,0x84}, {0x6e,0xcc,0x81}},
- {{0xc3,0xb1}, {0x6e,0xcc,0x83}},
- {{0xe1,0xb9,0x85}, {0x6e,0xcc,0x87}},
- {{0xc5,0x88}, {0x6e,0xcc,0x8c}},
- {{0xe1,0xb9,0x87}, {0x6e,0xcc,0xa3}},
- {{0xc5,0x86}, {0x6e,0xcc,0xa7}},
- {{0xe1,0xb9,0x8b}, {0x6e,0xcc,0xad}},
- {{0xe1,0xb9,0x89}, {0x6e,0xcc,0xb1}},
- {{0xc3,0xb2}, {0x6f,0xcc,0x80}},
- {{0xc3,0xb3}, {0x6f,0xcc,0x81}},
- {{0xc3,0xb4}, {0x6f,0xcc,0x82}},
- {{0xe1,0xbb,0x93}, {0x6f,0xcc,0x82,0xcc,0x80}},
- {{0xe1,0xbb,0x91}, {0x6f,0xcc,0x82,0xcc,0x81}},
- {{0xe1,0xbb,0x97}, {0x6f,0xcc,0x82,0xcc,0x83}},
- {{0xe1,0xbb,0x95}, {0x6f,0xcc,0x82,0xcc,0x89}},
- {{0xc3,0xb5}, {0x6f,0xcc,0x83}},
- {{0xe1,0xb9,0x8d}, {0x6f,0xcc,0x83,0xcc,0x81}},
- {{0xe1,0xb9,0x8f}, {0x6f,0xcc,0x83,0xcc,0x88}},
- {{0xc5,0x8d}, {0x6f,0xcc,0x84}},
- {{0xe1,0xb9,0x91}, {0x6f,0xcc,0x84,0xcc,0x80}},
- {{0xe1,0xb9,0x93}, {0x6f,0xcc,0x84,0xcc,0x81}},
- {{0xc5,0x8f}, {0x6f,0xcc,0x86}},
- {{0xc3,0xb6}, {0x6f,0xcc,0x88}},
- {{0xe1,0xbb,0x8f}, {0x6f,0xcc,0x89}},
- {{0xc5,0x91}, {0x6f,0xcc,0x8b}},
- {{0xc7,0x92}, {0x6f,0xcc,0x8c}},
- {{0xc8,0x8d}, {0x6f,0xcc,0x8f}},
- {{0xc8,0x8f}, {0x6f,0xcc,0x91}},
- {{0xc6,0xa1}, {0x6f,0xcc,0x9b}},
- {{0xe1,0xbb,0x9d}, {0x6f,0xcc,0x9b,0xcc,0x80}},
- {{0xe1,0xbb,0x9b}, {0x6f,0xcc,0x9b,0xcc,0x81}},
- {{0xe1,0xbb,0xa1}, {0x6f,0xcc,0x9b,0xcc,0x83}},
- {{0xe1,0xbb,0x9f}, {0x6f,0xcc,0x9b,0xcc,0x89}},
- {{0xe1,0xbb,0xa3}, {0x6f,0xcc,0x9b,0xcc,0xa3}},
- {{0xe1,0xbb,0x8d}, {0x6f,0xcc,0xa3}},
- {{0xe1,0xbb,0x99}, {0x6f,0xcc,0xa3,0xcc,0x82}},
- {{0xc7,0xab}, {0x6f,0xcc,0xa8}},
- {{0xc7,0xad}, {0x6f,0xcc,0xa8,0xcc,0x84}},
- {{0xe1,0xb9,0x95}, {0x70,0xcc,0x81}},
- {{0xe1,0xb9,0x97}, {0x70,0xcc,0x87}},
- {{0xc5,0x95}, {0x72,0xcc,0x81}},
- {{0xe1,0xb9,0x99}, {0x72,0xcc,0x87}},
- {{0xc5,0x99}, {0x72,0xcc,0x8c}},
- {{0xc8,0x91}, {0x72,0xcc,0x8f}},
- {{0xc8,0x93}, {0x72,0xcc,0x91}},
- {{0xe1,0xb9,0x9b}, {0x72,0xcc,0xa3}},
- {{0xe1,0xb9,0x9d}, {0x72,0xcc,0xa3,0xcc,0x84}},
- {{0xc5,0x97}, {0x72,0xcc,0xa7}},
- {{0xe1,0xb9,0x9f}, {0x72,0xcc,0xb1}},
- {{0xc5,0x9b}, {0x73,0xcc,0x81}},
- {{0xe1,0xb9,0xa5}, {0x73,0xcc,0x81,0xcc,0x87}},
- {{0xc5,0x9d}, {0x73,0xcc,0x82}},
- {{0xe1,0xb9,0xa1}, {0x73,0xcc,0x87}},
- {{0xc5,0xa1}, {0x73,0xcc,0x8c}},
- {{0xe1,0xb9,0xa7}, {0x73,0xcc,0x8c,0xcc,0x87}},
- {{0xe1,0xb9,0xa3}, {0x73,0xcc,0xa3}},
- {{0xe1,0xb9,0xa9}, {0x73,0xcc,0xa3,0xcc,0x87}},
- {{0xc5,0x9f}, {0x73,0xcc,0xa7}},
- {{0xe1,0xb9,0xab}, {0x74,0xcc,0x87}},
- {{0xe1,0xba,0x97}, {0x74,0xcc,0x88}},
- {{0xc5,0xa5}, {0x74,0xcc,0x8c}},
- {{0xe1,0xb9,0xad}, {0x74,0xcc,0xa3}},
- {{0xc5,0xa3}, {0x74,0xcc,0xa7}},
- {{0xe1,0xb9,0xb1}, {0x74,0xcc,0xad}},
- {{0xe1,0xb9,0xaf}, {0x74,0xcc,0xb1}},
- {{0xc3,0xb9}, {0x75,0xcc,0x80}},
- {{0xc3,0xba}, {0x75,0xcc,0x81}},
- {{0xc3,0xbb}, {0x75,0xcc,0x82}},
- {{0xc5,0xa9}, {0x75,0xcc,0x83}},
- {{0xe1,0xb9,0xb9}, {0x75,0xcc,0x83,0xcc,0x81}},
- {{0xc5,0xab}, {0x75,0xcc,0x84}},
- {{0xe1,0xb9,0xbb}, {0x75,0xcc,0x84,0xcc,0x88}},
- {{0xc5,0xad}, {0x75,0xcc,0x86}},
- {{0xc3,0xbc}, {0x75,0xcc,0x88}},
- {{0xc7,0x9c}, {0x75,0xcc,0x88,0xcc,0x80}},
- {{0xc7,0x98}, {0x75,0xcc,0x88,0xcc,0x81}},
- {{0xc7,0x96}, {0x75,0xcc,0x88,0xcc,0x84}},
- {{0xc7,0x9a}, {0x75,0xcc,0x88,0xcc,0x8c}},
- {{0xe1,0xbb,0xa7}, {0x75,0xcc,0x89}},
- {{0xc5,0xaf}, {0x75,0xcc,0x8a}},
- {{0xc5,0xb1}, {0x75,0xcc,0x8b}},
- {{0xc7,0x94}, {0x75,0xcc,0x8c}},
- {{0xc8,0x95}, {0x75,0xcc,0x8f}},
- {{0xc8,0x97}, {0x75,0xcc,0x91}},
- {{0xc6,0xb0}, {0x75,0xcc,0x9b}},
- {{0xe1,0xbb,0xab}, {0x75,0xcc,0x9b,0xcc,0x80}},
- {{0xe1,0xbb,0xa9}, {0x75,0xcc,0x9b,0xcc,0x81}},
- {{0xe1,0xbb,0xaf}, {0x75,0xcc,0x9b,0xcc,0x83}},
- {{0xe1,0xbb,0xad}, {0x75,0xcc,0x9b,0xcc,0x89}},
- {{0xe1,0xbb,0xb1}, {0x75,0xcc,0x9b,0xcc,0xa3}},
- {{0xe1,0xbb,0xa5}, {0x75,0xcc,0xa3}},
- {{0xe1,0xb9,0xb3}, {0x75,0xcc,0xa4}},
- {{0xc5,0xb3}, {0x75,0xcc,0xa8}},
- {{0xe1,0xb9,0xb7}, {0x75,0xcc,0xad}},
- {{0xe1,0xb9,0xb5}, {0x75,0xcc,0xb0}},
- {{0xe1,0xb9,0xbd}, {0x76,0xcc,0x83}},
- {{0xe1,0xb9,0xbf}, {0x76,0xcc,0xa3}},
- {{0xe1,0xba,0x81}, {0x77,0xcc,0x80}},
- {{0xe1,0xba,0x83}, {0x77,0xcc,0x81}},
- {{0xc5,0xb5}, {0x77,0xcc,0x82}},
- {{0xe1,0xba,0x87}, {0x77,0xcc,0x87}},
- {{0xe1,0xba,0x85}, {0x77,0xcc,0x88}},
- {{0xe1,0xba,0x98}, {0x77,0xcc,0x8a}},
- {{0xe1,0xba,0x89}, {0x77,0xcc,0xa3}},
- {{0xe1,0xba,0x8b}, {0x78,0xcc,0x87}},
- {{0xe1,0xba,0x8d}, {0x78,0xcc,0x88}},
- {{0xe1,0xbb,0xb3}, {0x79,0xcc,0x80}},
- {{0xc3,0xbd}, {0x79,0xcc,0x81}},
- {{0xc5,0xb7}, {0x79,0xcc,0x82}},
- {{0xe1,0xbb,0xb9}, {0x79,0xcc,0x83}},
- {{0xe1,0xba,0x8f}, {0x79,0xcc,0x87}},
- {{0xc3,0xbf}, {0x79,0xcc,0x88}},
- {{0xe1,0xbb,0xb7}, {0x79,0xcc,0x89}},
- {{0xe1,0xba,0x99}, {0x79,0xcc,0x8a}},
- {{0xe1,0xbb,0xb5}, {0x79,0xcc,0xa3}},
- {{0xc5,0xba}, {0x7a,0xcc,0x81}},
- {{0xe1,0xba,0x91}, {0x7a,0xcc,0x82}},
- {{0xc5,0xbc}, {0x7a,0xcc,0x87}},
- {{0xc5,0xbe}, {0x7a,0xcc,0x8c}},
- {{0xe1,0xba,0x93}, {0x7a,0xcc,0xa3}},
- {{0xe1,0xba,0x95}, {0x7a,0xcc,0xb1}},
- {{0xe1,0xbf,0xad}, {0xc2,0xa8,0xcc,0x80}},
- {{0xe1,0xbf,0xae}, {0xc2,0xa8,0xcc,0x81}},
- {{0xce,0x85}, {0xc2,0xa8,0xcc,0x8d}},
- {{0xe1,0xbf,0x81}, {0xc2,0xa8,0xcd,0x82}},
- {{0xe1,0xbf,0xbd}, {0xc2,0xb4}},
- {{0xce,0x87}, {0xc2,0xb7}},
- {{0xd3,0x94}, {0xc3,0x86}},
- {{0xc7,0xbc}, {0xc3,0x86,0xcc,0x81}},
- {{0xc7,0xa2}, {0xc3,0x86,0xcc,0x84}},
- {{0xc7,0xbe}, {0xc3,0x98,0xcc,0x81}},
- {{0xd3,0x95}, {0xc3,0xa6}},
- {{0xc7,0xbd}, {0xc3,0xa6,0xcc,0x81}},
- {{0xc7,0xa3}, {0xc3,0xa6,0xcc,0x84}},
- {{0xc7,0xbf}, {0xc3,0xb8,0xcc,0x81}},
- {{0xe1,0xba,0x9b}, {0xc5,0xbf,0xcc,0x87}},
- {{0xd3,0x98}, {0xc6,0x8f}},
- {{0xd3,0x9a}, {0xc6,0x8f,0xcc,0x88}},
- {{0xd3,0xa8}, {0xc6,0x9f}},
- {{0xd3,0xaa}, {0xc6,0x9f,0xcc,0x88}},
- {{0xd3,0xa0}, {0xc6,0xb7}},
- {{0xc7,0xae}, {0xc6,0xb7,0xcc,0x8c}},
- {{0xd3,0x99}, {0xc9,0x99}},
- {{0xd3,0x9b}, {0xc9,0x99,0xcc,0x88}},
- {{0xd3,0xa9}, {0xc9,0xb5}},
- {{0xd3,0xab}, {0xc9,0xb5,0xcc,0x88}},
- {{0xd3,0xa1}, {0xca,0x92}},
- {{0xc7,0xaf}, {0xca,0x92,0xcc,0x8c}},
- {{0xcd,0xb4}, {0xca,0xb9}},
- {{0xcd,0x80}, {0xcc,0x80}},
- {{0xcd,0x81}, {0xcc,0x81}},
- {{0xcc,0x90}, {0xcc,0x86,0xcc,0x87}},
- {{0xcd,0x84}, {0xcc,0x88,0xcc,0x8d}},
- {{0xcd,0x83}, {0xcc,0x93}},
- {{0xe1,0xbe,0xba}, {0xce,0x91,0xcc,0x80}},
- {{0xe1,0xbe,0xbb}, {0xce,0x91,0xcc,0x81}},
- {{0xe1,0xbe,0xb9}, {0xce,0x91,0xcc,0x84}},
- {{0xe1,0xbe,0xb8}, {0xce,0x91,0xcc,0x86}},
- {{0xce,0x86}, {0xce,0x91,0xcc,0x8d}},
- {{0xe1,0xbc,0x88}, {0xce,0x91,0xcc,0x93}},
- {{0xe1,0xbc,0x8a}, {0xce,0x91,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0x8c}, {0xce,0x91,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0x8e}, {0xce,0x91,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbc,0x89}, {0xce,0x91,0xcc,0x94}},
- {{0xe1,0xbc,0x8b}, {0xce,0x91,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0x8d}, {0xce,0x91,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbc,0x8f}, {0xce,0x91,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbe,0xbc}, {0xce,0x91,0xcd,0x85}},
- {{0xe1,0xbe,0x88}, {0xce,0x91,0xcd,0x85,0xcc,0x93}},
- {{0xe1,0xbe,0x8a}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbe,0x8c}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbe,0x8e}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbe,0x89}, {0xce,0x91,0xcd,0x85,0xcc,0x94}},
- {{0xe1,0xbe,0x8b}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbe,0x8d}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbe,0x8f}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0x88}, {0xce,0x95,0xcc,0x80}},
- {{0xe1,0xbf,0x89}, {0xce,0x95,0xcc,0x81}},
- {{0xce,0x88}, {0xce,0x95,0xcc,0x8d}},
- {{0xe1,0xbc,0x98}, {0xce,0x95,0xcc,0x93}},
- {{0xe1,0xbc,0x9a}, {0xce,0x95,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0x9c}, {0xce,0x95,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0x99}, {0xce,0x95,0xcc,0x94}},
- {{0xe1,0xbc,0x9b}, {0xce,0x95,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0x9d}, {0xce,0x95,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbf,0x8a}, {0xce,0x97,0xcc,0x80}},
- {{0xe1,0xbf,0x8b}, {0xce,0x97,0xcc,0x81}},
- {{0xce,0x89}, {0xce,0x97,0xcc,0x8d}},
- {{0xe1,0xbc,0xa8}, {0xce,0x97,0xcc,0x93}},
- {{0xe1,0xbc,0xaa}, {0xce,0x97,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0xac}, {0xce,0x97,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0xae}, {0xce,0x97,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbc,0xa9}, {0xce,0x97,0xcc,0x94}},
- {{0xe1,0xbc,0xab}, {0xce,0x97,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0xad}, {0xce,0x97,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbc,0xaf}, {0xce,0x97,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0x8c}, {0xce,0x97,0xcd,0x85}},
- {{0xe1,0xbe,0x98}, {0xce,0x97,0xcd,0x85,0xcc,0x93}},
- {{0xe1,0xbe,0x9a}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbe,0x9c}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbe,0x9e}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbe,0x99}, {0xce,0x97,0xcd,0x85,0xcc,0x94}},
- {{0xe1,0xbe,0x9b}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbe,0x9d}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbe,0x9f}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0x9a}, {0xce,0x99,0xcc,0x80}},
- {{0xe1,0xbf,0x9b}, {0xce,0x99,0xcc,0x81}},
- {{0xe1,0xbf,0x99}, {0xce,0x99,0xcc,0x84}},
- {{0xe1,0xbf,0x98}, {0xce,0x99,0xcc,0x86}},
- {{0xce,0xaa}, {0xce,0x99,0xcc,0x88}},
- {{0xce,0x8a}, {0xce,0x99,0xcc,0x8d}},
- {{0xe1,0xbc,0xb8}, {0xce,0x99,0xcc,0x93}},
- {{0xe1,0xbc,0xba}, {0xce,0x99,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0xbc}, {0xce,0x99,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0xbe}, {0xce,0x99,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbc,0xb9}, {0xce,0x99,0xcc,0x94}},
- {{0xe1,0xbc,0xbb}, {0xce,0x99,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0xbd}, {0xce,0x99,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbc,0xbf}, {0xce,0x99,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0xb8}, {0xce,0x9f,0xcc,0x80}},
- {{0xe1,0xbf,0xb9}, {0xce,0x9f,0xcc,0x81}},
- {{0xce,0x8c}, {0xce,0x9f,0xcc,0x8d}},
- {{0xe1,0xbd,0x88}, {0xce,0x9f,0xcc,0x93}},
- {{0xe1,0xbd,0x8a}, {0xce,0x9f,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbd,0x8c}, {0xce,0x9f,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbd,0x89}, {0xce,0x9f,0xcc,0x94}},
- {{0xe1,0xbd,0x8b}, {0xce,0x9f,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbd,0x8d}, {0xce,0x9f,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbf,0xac}, {0xce,0xa1,0xcc,0x94}},
- {{0xe1,0xbf,0xaa}, {0xce,0xa5,0xcc,0x80}},
- {{0xe1,0xbf,0xab}, {0xce,0xa5,0xcc,0x81}},
- {{0xe1,0xbf,0xa9}, {0xce,0xa5,0xcc,0x84}},
- {{0xe1,0xbf,0xa8}, {0xce,0xa5,0xcc,0x86}},
- {{0xce,0xab}, {0xce,0xa5,0xcc,0x88}},
- {{0xce,0x8e}, {0xce,0xa5,0xcc,0x8d}},
- {{0xe1,0xbd,0x99}, {0xce,0xa5,0xcc,0x94}},
- {{0xe1,0xbd,0x9b}, {0xce,0xa5,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbd,0x9d}, {0xce,0xa5,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbd,0x9f}, {0xce,0xa5,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0xba}, {0xce,0xa9,0xcc,0x80}},
- {{0xe1,0xbf,0xbb}, {0xce,0xa9,0xcc,0x81}},
- {{0xce,0x8f}, {0xce,0xa9,0xcc,0x8d}},
- {{0xe1,0xbd,0xa8}, {0xce,0xa9,0xcc,0x93}},
- {{0xe1,0xbd,0xaa}, {0xce,0xa9,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbd,0xac}, {0xce,0xa9,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbd,0xae}, {0xce,0xa9,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbd,0xa9}, {0xce,0xa9,0xcc,0x94}},
- {{0xe1,0xbd,0xab}, {0xce,0xa9,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbd,0xad}, {0xce,0xa9,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbd,0xaf}, {0xce,0xa9,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0xbc}, {0xce,0xa9,0xcd,0x85}},
- {{0xe1,0xbe,0xa8}, {0xce,0xa9,0xcd,0x85,0xcc,0x93}},
- {{0xe1,0xbe,0xaa}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbe,0xac}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbe,0xae}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbe,0xa9}, {0xce,0xa9,0xcd,0x85,0xcc,0x94}},
- {{0xe1,0xbe,0xab}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbe,0xad}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbe,0xaf}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbd,0xb0}, {0xce,0xb1,0xcc,0x80}},
- {{0xe1,0xbd,0xb1}, {0xce,0xb1,0xcc,0x81}},
- {{0xe1,0xbe,0xb1}, {0xce,0xb1,0xcc,0x84}},
- {{0xe1,0xbe,0xb0}, {0xce,0xb1,0xcc,0x86}},
- {{0xce,0xac}, {0xce,0xb1,0xcc,0x8d}},
- {{0xe1,0xbc,0x80}, {0xce,0xb1,0xcc,0x93}},
- {{0xe1,0xbc,0x82}, {0xce,0xb1,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0x84}, {0xce,0xb1,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0x86}, {0xce,0xb1,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbc,0x81}, {0xce,0xb1,0xcc,0x94}},
- {{0xe1,0xbc,0x83}, {0xce,0xb1,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0x85}, {0xce,0xb1,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbc,0x87}, {0xce,0xb1,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbe,0xb6}, {0xce,0xb1,0xcd,0x82}},
- {{0xe1,0xbe,0xb3}, {0xce,0xb1,0xcd,0x85}},
- {{0xe1,0xbe,0xb2}, {0xce,0xb1,0xcd,0x85,0xcc,0x80}},
- {{0xe1,0xbe,0xb4}, {0xce,0xb1,0xcd,0x85,0xcc,0x81}},
- {{0xe1,0xbe,0x80}, {0xce,0xb1,0xcd,0x85,0xcc,0x93}},
- {{0xe1,0xbe,0x82}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbe,0x84}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbe,0x86}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbe,0x81}, {0xce,0xb1,0xcd,0x85,0xcc,0x94}},
- {{0xe1,0xbe,0x83}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbe,0x85}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbe,0x87}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbe,0xb7}, {0xce,0xb1,0xcd,0x85,0xcd,0x82}},
- {{0xe1,0xbd,0xb2}, {0xce,0xb5,0xcc,0x80}},
- {{0xe1,0xbd,0xb3}, {0xce,0xb5,0xcc,0x81}},
- {{0xce,0xad}, {0xce,0xb5,0xcc,0x8d}},
- {{0xe1,0xbc,0x90}, {0xce,0xb5,0xcc,0x93}},
- {{0xe1,0xbc,0x92}, {0xce,0xb5,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0x94}, {0xce,0xb5,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0x91}, {0xce,0xb5,0xcc,0x94}},
- {{0xe1,0xbc,0x93}, {0xce,0xb5,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0x95}, {0xce,0xb5,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbd,0xb4}, {0xce,0xb7,0xcc,0x80}},
- {{0xe1,0xbd,0xb5}, {0xce,0xb7,0xcc,0x81}},
- {{0xce,0xae}, {0xce,0xb7,0xcc,0x8d}},
- {{0xe1,0xbc,0xa0}, {0xce,0xb7,0xcc,0x93}},
- {{0xe1,0xbc,0xa2}, {0xce,0xb7,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0xa4}, {0xce,0xb7,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0xa6}, {0xce,0xb7,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbc,0xa1}, {0xce,0xb7,0xcc,0x94}},
- {{0xe1,0xbc,0xa3}, {0xce,0xb7,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0xa5}, {0xce,0xb7,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbc,0xa7}, {0xce,0xb7,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0x86}, {0xce,0xb7,0xcd,0x82}},
- {{0xe1,0xbf,0x83}, {0xce,0xb7,0xcd,0x85}},
- {{0xe1,0xbf,0x82}, {0xce,0xb7,0xcd,0x85,0xcc,0x80}},
- {{0xe1,0xbf,0x84}, {0xce,0xb7,0xcd,0x85,0xcc,0x81}},
- {{0xe1,0xbe,0x90}, {0xce,0xb7,0xcd,0x85,0xcc,0x93}},
- {{0xe1,0xbe,0x92}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbe,0x94}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbe,0x96}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbe,0x91}, {0xce,0xb7,0xcd,0x85,0xcc,0x94}},
- {{0xe1,0xbe,0x93}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbe,0x95}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbe,0x97}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0x87}, {0xce,0xb7,0xcd,0x85,0xcd,0x82}},
- {{0xe1,0xbe,0xbe}, {0xce,0xb9}},
- {{0xe1,0xbd,0xb6}, {0xce,0xb9,0xcc,0x80}},
- {{0xe1,0xbd,0xb7}, {0xce,0xb9,0xcc,0x81}},
- {{0xe1,0xbf,0x91}, {0xce,0xb9,0xcc,0x84}},
- {{0xe1,0xbf,0x90}, {0xce,0xb9,0xcc,0x86}},
- {{0xcf,0x8a}, {0xce,0xb9,0xcc,0x88}},
- {{0xe1,0xbf,0x92}, {0xce,0xb9,0xcc,0x88,0xcc,0x80}},
- {{0xe1,0xbf,0x93}, {0xce,0xb9,0xcc,0x88,0xcc,0x81}},
- {{0xce,0x90}, {0xce,0xb9,0xcc,0x88,0xcc,0x8d}},
- {{0xe1,0xbf,0x97}, {0xce,0xb9,0xcc,0x88,0xcd,0x82}},
- {{0xce,0xaf}, {0xce,0xb9,0xcc,0x8d}},
- {{0xe1,0xbc,0xb0}, {0xce,0xb9,0xcc,0x93}},
- {{0xe1,0xbc,0xb2}, {0xce,0xb9,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0xb4}, {0xce,0xb9,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0xb6}, {0xce,0xb9,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbc,0xb1}, {0xce,0xb9,0xcc,0x94}},
- {{0xe1,0xbc,0xb3}, {0xce,0xb9,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0xb5}, {0xce,0xb9,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbc,0xb7}, {0xce,0xb9,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0x96}, {0xce,0xb9,0xcd,0x82}},
- {{0xe1,0xbd,0xb8}, {0xce,0xbf,0xcc,0x80}},
- {{0xe1,0xbd,0xb9}, {0xce,0xbf,0xcc,0x81}},
- {{0xcf,0x8c}, {0xce,0xbf,0xcc,0x8d}},
- {{0xe1,0xbd,0x80}, {0xce,0xbf,0xcc,0x93}},
- {{0xe1,0xbd,0x82}, {0xce,0xbf,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbd,0x84}, {0xce,0xbf,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbd,0x81}, {0xce,0xbf,0xcc,0x94}},
- {{0xe1,0xbd,0x83}, {0xce,0xbf,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbd,0x85}, {0xce,0xbf,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbf,0xb4}, {0xce,0xbf,0xcd,0x85,0xcc,0x81}},
- {{0xe1,0xbf,0xa4}, {0xcf,0x81,0xcc,0x93}},
- {{0xe1,0xbf,0xa5}, {0xcf,0x81,0xcc,0x94}},
- {{0xe1,0xbd,0xba}, {0xcf,0x85,0xcc,0x80}},
- {{0xe1,0xbd,0xbb}, {0xcf,0x85,0xcc,0x81}},
- {{0xe1,0xbf,0xa1}, {0xcf,0x85,0xcc,0x84}},
- {{0xe1,0xbf,0xa0}, {0xcf,0x85,0xcc,0x86}},
- {{0xcf,0x8b}, {0xcf,0x85,0xcc,0x88}},
- {{0xe1,0xbf,0xa2}, {0xcf,0x85,0xcc,0x88,0xcc,0x80}},
- {{0xe1,0xbf,0xa3}, {0xcf,0x85,0xcc,0x88,0xcc,0x81}},
- {{0xce,0xb0}, {0xcf,0x85,0xcc,0x88,0xcc,0x8d}},
- {{0xe1,0xbf,0xa7}, {0xcf,0x85,0xcc,0x88,0xcd,0x82}},
- {{0xcf,0x8d}, {0xcf,0x85,0xcc,0x8d}},
- {{0xe1,0xbd,0x90}, {0xcf,0x85,0xcc,0x93}},
- {{0xe1,0xbd,0x92}, {0xcf,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbd,0x94}, {0xcf,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbd,0x96}, {0xcf,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbd,0x91}, {0xcf,0x85,0xcc,0x94}},
- {{0xe1,0xbd,0x93}, {0xcf,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbd,0x95}, {0xcf,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbd,0x97}, {0xcf,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0xa6}, {0xcf,0x85,0xcd,0x82}},
- {{0xe1,0xbd,0xbc}, {0xcf,0x89,0xcc,0x80}},
- {{0xe1,0xbd,0xbd}, {0xcf,0x89,0xcc,0x81}},
- {{0xcf,0x8e}, {0xcf,0x89,0xcc,0x8d}},
- {{0xe1,0xbd,0xa0}, {0xcf,0x89,0xcc,0x93}},
- {{0xe1,0xbd,0xa2}, {0xcf,0x89,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbd,0xa4}, {0xcf,0x89,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbd,0xa6}, {0xcf,0x89,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbd,0xa1}, {0xcf,0x89,0xcc,0x94}},
- {{0xe1,0xbd,0xa3}, {0xcf,0x89,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbd,0xa5}, {0xcf,0x89,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbd,0xa7}, {0xcf,0x89,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0xb6}, {0xcf,0x89,0xcd,0x82}},
- {{0xe1,0xbf,0xb3}, {0xcf,0x89,0xcd,0x85}},
- {{0xe1,0xbf,0xb2}, {0xcf,0x89,0xcd,0x85,0xcc,0x80}},
- {{0xe1,0xbe,0xa0}, {0xcf,0x89,0xcd,0x85,0xcc,0x93}},
- {{0xe1,0xbe,0xa2}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbe,0xa4}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbe,0xa6}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbe,0xa1}, {0xcf,0x89,0xcd,0x85,0xcc,0x94}},
- {{0xe1,0xbe,0xa3}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbe,0xa5}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbe,0xa7}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0xb7}, {0xcf,0x89,0xcd,0x85,0xcd,0x82}},
- {{0xcf,0x94}, {0xcf,0x92,0xcc,0x88}},
- {{0xcf,0x93}, {0xcf,0x92,0xcc,0x8d}},
- {{0xd0,0x87}, {0xd0,0x86,0xcc,0x88}},
- {{0xd3,0x90}, {0xd0,0x90,0xcc,0x86}},
- {{0xd3,0x92}, {0xd0,0x90,0xcc,0x88}},
- {{0xd0,0x83}, {0xd0,0x93,0xcc,0x81}},
- {{0xd3,0x96}, {0xd0,0x95,0xcc,0x86}},
- {{0xd0,0x81}, {0xd0,0x95,0xcc,0x88}},
- {{0xd3,0x81}, {0xd0,0x96,0xcc,0x86}},
- {{0xd3,0x9c}, {0xd0,0x96,0xcc,0x88}},
- {{0xd3,0x9e}, {0xd0,0x97,0xcc,0x88}},
- {{0xd3,0xa2}, {0xd0,0x98,0xcc,0x84}},
- {{0xd0,0x99}, {0xd0,0x98,0xcc,0x86}},
- {{0xd3,0xa4}, {0xd0,0x98,0xcc,0x88}},
- {{0xd0,0x8c}, {0xd0,0x9a,0xcc,0x81}},
- {{0xd3,0xa6}, {0xd0,0x9e,0xcc,0x88}},
- {{0xd3,0xae}, {0xd0,0xa3,0xcc,0x84}},
- {{0xd0,0x8e}, {0xd0,0xa3,0xcc,0x86}},
- {{0xd3,0xb0}, {0xd0,0xa3,0xcc,0x88}},
- {{0xd3,0xb2}, {0xd0,0xa3,0xcc,0x8b}},
- {{0xd3,0xb4}, {0xd0,0xa7,0xcc,0x88}},
- {{0xd3,0xb8}, {0xd0,0xab,0xcc,0x88}},
- {{0xd3,0x91}, {0xd0,0xb0,0xcc,0x86}},
- {{0xd3,0x93}, {0xd0,0xb0,0xcc,0x88}},
- {{0xd1,0x93}, {0xd0,0xb3,0xcc,0x81}},
- {{0xd3,0x97}, {0xd0,0xb5,0xcc,0x86}},
- {{0xd1,0x91}, {0xd0,0xb5,0xcc,0x88}},
- {{0xd3,0x82}, {0xd0,0xb6,0xcc,0x86}},
- {{0xd3,0x9d}, {0xd0,0xb6,0xcc,0x88}},
- {{0xd3,0x9f}, {0xd0,0xb7,0xcc,0x88}},
- {{0xd3,0xa3}, {0xd0,0xb8,0xcc,0x84}},
- {{0xd0,0xb9}, {0xd0,0xb8,0xcc,0x86}},
- {{0xd3,0xa5}, {0xd0,0xb8,0xcc,0x88}},
- {{0xd1,0x9c}, {0xd0,0xba,0xcc,0x81}},
- {{0xd3,0xa7}, {0xd0,0xbe,0xcc,0x88}},
- {{0xd3,0xaf}, {0xd1,0x83,0xcc,0x84}},
- {{0xd1,0x9e}, {0xd1,0x83,0xcc,0x86}},
- {{0xd3,0xb1}, {0xd1,0x83,0xcc,0x88}},
- {{0xd3,0xb3}, {0xd1,0x83,0xcc,0x8b}},
- {{0xd3,0xb5}, {0xd1,0x87,0xcc,0x88}},
- {{0xd3,0xb9}, {0xd1,0x8b,0xcc,0x88}},
- {{0xd1,0x97}, {0xd1,0x96,0xcc,0x88}},
- {{0xd1,0xb6}, {0xd1,0xb4,0xcc,0x8f}},
- {{0xd1,0xb7}, {0xd1,0xb5,0xcc,0x8f}},
- {{0xef,0xac,0xae}, {0xd7,0x90,0xd6,0xb7}},
- {{0xef,0xac,0xaf}, {0xd7,0x90,0xd6,0xb8}},
- {{0xef,0xac,0xb0}, {0xd7,0x90,0xd6,0xbc}},
- {{0xef,0xac,0xb1}, {0xd7,0x91,0xd6,0xbc}},
- {{0xef,0xad,0x8c}, {0xd7,0x91,0xd6,0xbf}},
- {{0xef,0xac,0xb2}, {0xd7,0x92,0xd6,0xbc}},
- {{0xef,0xac,0xb3}, {0xd7,0x93,0xd6,0xbc}},
- {{0xef,0xac,0xb4}, {0xd7,0x94,0xd6,0xbc}},
- {{0xef,0xad,0x8b}, {0xd7,0x95,0xd6,0xb9}},
- {{0xef,0xac,0xb5}, {0xd7,0x95,0xd6,0xbc}},
- {{0xef,0xac,0xb6}, {0xd7,0x96,0xd6,0xbc}},
- {{0xef,0xac,0xb8}, {0xd7,0x98,0xd6,0xbc}},
- {{0xef,0xac,0xb9}, {0xd7,0x99,0xd6,0xbc}},
- {{0xef,0xac,0xba}, {0xd7,0x9a,0xd6,0xbc}},
- {{0xef,0xac,0xbb}, {0xd7,0x9b,0xd6,0xbc}},
- {{0xef,0xad,0x8d}, {0xd7,0x9b,0xd6,0xbf}},
- {{0xef,0xac,0xbc}, {0xd7,0x9c,0xd6,0xbc}},
- {{0xef,0xac,0xbe}, {0xd7,0x9e,0xd6,0xbc}},
- {{0xef,0xad,0x80}, {0xd7,0xa0,0xd6,0xbc}},
- {{0xef,0xad,0x81}, {0xd7,0xa1,0xd6,0xbc}},
- {{0xef,0xad,0x83}, {0xd7,0xa3,0xd6,0xbc}},
- {{0xef,0xad,0x84}, {0xd7,0xa4,0xd6,0xbc}},
- {{0xef,0xad,0x8e}, {0xd7,0xa4,0xd6,0xbf}},
- {{0xef,0xad,0x86}, {0xd7,0xa6,0xd6,0xbc}},
- {{0xef,0xad,0x87}, {0xd7,0xa7,0xd6,0xbc}},
- {{0xef,0xad,0x88}, {0xd7,0xa8,0xd6,0xbc}},
- {{0xef,0xad,0x89}, {0xd7,0xa9,0xd6,0xbc}},
- {{0xef,0xac,0xac}, {0xd7,0xa9,0xd6,0xbc,0xd7,0x81}},
- {{0xef,0xac,0xad}, {0xd7,0xa9,0xd6,0xbc,0xd7,0x82}},
- {{0xef,0xac,0xaa}, {0xd7,0xa9,0xd7,0x81}},
- {{0xef,0xac,0xab}, {0xd7,0xa9,0xd7,0x82}},
- {{0xef,0xad,0x8a}, {0xd7,0xaa,0xd6,0xbc}},
- {{0xef,0xac,0x9f}, {0xd7,0xb2,0xd6,0xb7}},
- {{0xe0,0xa5,0x98}, {0xe0,0xa4,0x95,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x99}, {0xe0,0xa4,0x96,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x9a}, {0xe0,0xa4,0x97,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x9b}, {0xe0,0xa4,0x9c,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x9c}, {0xe0,0xa4,0xa1,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x9d}, {0xe0,0xa4,0xa2,0xe0,0xa4,0xbc}},
- {{0xe0,0xa4,0xa9}, {0xe0,0xa4,0xa8,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x9e}, {0xe0,0xa4,0xab,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x9f}, {0xe0,0xa4,0xaf,0xe0,0xa4,0xbc}},
- {{0xe0,0xa4,0xb1}, {0xe0,0xa4,0xb0,0xe0,0xa4,0xbc}},
- {{0xe0,0xa4,0xb4}, {0xe0,0xa4,0xb3,0xe0,0xa4,0xbc}},
- {{0xe0,0xa7,0x9c}, {0xe0,0xa6,0xa1,0xe0,0xa6,0xbc}},
- {{0xe0,0xa7,0x9d}, {0xe0,0xa6,0xa2,0xe0,0xa6,0xbc}},
- {{0xe0,0xa6,0xb0}, {0xe0,0xa6,0xac,0xe0,0xa6,0xbc}},
- {{0xe0,0xa7,0x9f}, {0xe0,0xa6,0xaf,0xe0,0xa6,0xbc}},
- {{0xe0,0xa7,0x8b}, {0xe0,0xa7,0x87,0xe0,0xa6,0xbe}},
- {{0xe0,0xa7,0x8c}, {0xe0,0xa7,0x87,0xe0,0xa7,0x97}},
- {{0xe0,0xa9,0x99}, {0xe0,0xa8,0x96,0xe0,0xa8,0xbc}},
- {{0xe0,0xa9,0x9a}, {0xe0,0xa8,0x97,0xe0,0xa8,0xbc}},
- {{0xe0,0xa9,0x9b}, {0xe0,0xa8,0x9c,0xe0,0xa8,0xbc}},
- {{0xe0,0xa9,0x9c}, {0xe0,0xa8,0xa1,0xe0,0xa8,0xbc}},
- {{0xe0,0xa9,0x9e}, {0xe0,0xa8,0xab,0xe0,0xa8,0xbc}},
- {{0xe0,0xad,0x9c}, {0xe0,0xac,0xa1,0xe0,0xac,0xbc}},
- {{0xe0,0xad,0x9d}, {0xe0,0xac,0xa2,0xe0,0xac,0xbc}},
- {{0xe0,0xad,0x9f}, {0xe0,0xac,0xaf,0xe0,0xac,0xbc}},
- {{0xe0,0xad,0x8b}, {0xe0,0xad,0x87,0xe0,0xac,0xbe}},
- {{0xe0,0xad,0x88}, {0xe0,0xad,0x87,0xe0,0xad,0x96}},
- {{0xe0,0xad,0x8c}, {0xe0,0xad,0x87,0xe0,0xad,0x97}},
- {{0xe0,0xae,0x94}, {0xe0,0xae,0x92,0xe0,0xaf,0x97}},
- {{0xe0,0xaf,0x8a}, {0xe0,0xaf,0x86,0xe0,0xae,0xbe}},
- {{0xe0,0xaf,0x8c}, {0xe0,0xaf,0x86,0xe0,0xaf,0x97}},
- {{0xe0,0xaf,0x8b}, {0xe0,0xaf,0x87,0xe0,0xae,0xbe}},
- {{0xe0,0xb1,0x88}, {0xe0,0xb1,0x86,0xe0,0xb1,0x96}},
- {{0xe0,0xb3,0x80}, {0xe0,0xb2,0xbf,0xe0,0xb3,0x95}},
- {{0xe0,0xb3,0x8a}, {0xe0,0xb3,0x86,0xe0,0xb3,0x82}},
- {{0xe0,0xb3,0x8b}, {0xe0,0xb3,0x86,0xe0,0xb3,0x82,0xe0,0xb3,0x95}},
- {{0xe0,0xb3,0x87}, {0xe0,0xb3,0x86,0xe0,0xb3,0x95}},
- {{0xe0,0xb3,0x88}, {0xe0,0xb3,0x86,0xe0,0xb3,0x96}},
- {{0xe0,0xb5,0x8a}, {0xe0,0xb5,0x86,0xe0,0xb4,0xbe}},
- {{0xe0,0xb5,0x8c}, {0xe0,0xb5,0x86,0xe0,0xb5,0x97}},
- {{0xe0,0xb5,0x8b}, {0xe0,0xb5,0x87,0xe0,0xb4,0xbe}},
- {{0xe0,0xb8,0xb3}, {0xe0,0xb9,0x8d,0xe0,0xb8,0xb2}},
- {{0xe0,0xba,0xb3}, {0xe0,0xbb,0x8d,0xe0,0xba,0xb2}},
- {{0xe0,0xbd,0xa9}, {0xe0,0xbd,0x80,0xe0,0xbe,0xb5}},
- {{0xe0,0xbd,0x83}, {0xe0,0xbd,0x82,0xe0,0xbe,0xb7}},
- {{0xe0,0xbd,0x8d}, {0xe0,0xbd,0x8c,0xe0,0xbe,0xb7}},
- {{0xe0,0xbd,0x92}, {0xe0,0xbd,0x91,0xe0,0xbe,0xb7}},
- {{0xe0,0xbd,0x97}, {0xe0,0xbd,0x96,0xe0,0xbe,0xb7}},
- {{0xe0,0xbd,0x9c}, {0xe0,0xbd,0x9b,0xe0,0xbe,0xb7}},
- {{0xe0,0xbd,0xb3}, {0xe0,0xbd,0xb2,0xe0,0xbd,0xb1}},
- {{0xe0,0xbd,0xb5}, {0xe0,0xbd,0xb4,0xe0,0xbd,0xb1}},
- {{0xe0,0xbe,0x81}, {0xe0,0xbe,0x80,0xe0,0xbd,0xb1}},
- {{0xe0,0xbe,0xb9}, {0xe0,0xbe,0x90,0xe0,0xbe,0xb5}},
- {{0xe0,0xbe,0x93}, {0xe0,0xbe,0x92,0xe0,0xbe,0xb7}},
- {{0xe0,0xbe,0x9d}, {0xe0,0xbe,0x9c,0xe0,0xbe,0xb7}},
- {{0xe0,0xbe,0xa2}, {0xe0,0xbe,0xa1,0xe0,0xbe,0xb7}},
- {{0xe0,0xbe,0xa7}, {0xe0,0xbe,0xa6,0xe0,0xbe,0xb7}},
- {{0xe0,0xbe,0xac}, {0xe0,0xbe,0xab,0xe0,0xbe,0xb7}},
- {{0xe0,0xbd,0xb6}, {0xe0,0xbe,0xb2,0xe0,0xbe,0x80}},
- {{0xe0,0xbd,0xb7}, {0xe0,0xbe,0xb2,0xe0,0xbe,0x80,0xe0,0xbd,0xb1}},
- {{0xe0,0xbd,0xb8}, {0xe0,0xbe,0xb3,0xe0,0xbe,0x80}},
- {{0xe0,0xbd,0xb9}, {0xe0,0xbe,0xb3,0xe0,0xbe,0x80,0xe0,0xbd,0xb1}},
- {{0xe1,0xbf,0x8d}, {0xe1,0xbe,0xbf,0xcc,0x80}},
- {{0xe1,0xbf,0x8e}, {0xe1,0xbe,0xbf,0xcc,0x81}},
- {{0xe1,0xbf,0x8f}, {0xe1,0xbe,0xbf,0xcd,0x82}},
- {{0xe1,0xbf,0x9d}, {0xe1,0xbf,0xbe,0xcc,0x80}},
- {{0xe1,0xbf,0x9e}, {0xe1,0xbf,0xbe,0xcc,0x81}},
- {{0xe1,0xbf,0x9f}, {0xe1,0xbf,0xbe,0xcd,0x82}},
- {{0xe3,0x82,0x94}, {0xe3,0x81,0x86,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x8c}, {0xe3,0x81,0x8b,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x8e}, {0xe3,0x81,0x8d,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x90}, {0xe3,0x81,0x8f,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x92}, {0xe3,0x81,0x91,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x94}, {0xe3,0x81,0x93,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x96}, {0xe3,0x81,0x95,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x98}, {0xe3,0x81,0x97,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x9a}, {0xe3,0x81,0x99,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x9c}, {0xe3,0x81,0x9b,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x9e}, {0xe3,0x81,0x9d,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xa0}, {0xe3,0x81,0x9f,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xa2}, {0xe3,0x81,0xa1,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xa5}, {0xe3,0x81,0xa4,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xa7}, {0xe3,0x81,0xa6,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xa9}, {0xe3,0x81,0xa8,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xb0}, {0xe3,0x81,0xaf,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xb1}, {0xe3,0x81,0xaf,0xe3,0x82,0x9a}},
- {{0xe3,0x81,0xb3}, {0xe3,0x81,0xb2,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xb4}, {0xe3,0x81,0xb2,0xe3,0x82,0x9a}},
- {{0xe3,0x81,0xb6}, {0xe3,0x81,0xb5,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xb7}, {0xe3,0x81,0xb5,0xe3,0x82,0x9a}},
- {{0xe3,0x81,0xb9}, {0xe3,0x81,0xb8,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xba}, {0xe3,0x81,0xb8,0xe3,0x82,0x9a}},
- {{0xe3,0x81,0xbc}, {0xe3,0x81,0xbb,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xbd}, {0xe3,0x81,0xbb,0xe3,0x82,0x9a}},
- {{0xe3,0x82,0x9e}, {0xe3,0x82,0x9d,0xe3,0x82,0x99}},
- {{0xe3,0x83,0xb4}, {0xe3,0x82,0xa6,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xac}, {0xe3,0x82,0xab,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xae}, {0xe3,0x82,0xad,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xb0}, {0xe3,0x82,0xaf,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xb2}, {0xe3,0x82,0xb1,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xb4}, {0xe3,0x82,0xb3,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xb6}, {0xe3,0x82,0xb5,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xb8}, {0xe3,0x82,0xb7,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xba}, {0xe3,0x82,0xb9,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xbc}, {0xe3,0x82,0xbb,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xbe}, {0xe3,0x82,0xbd,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x80}, {0xe3,0x82,0xbf,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x82}, {0xe3,0x83,0x81,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x85}, {0xe3,0x83,0x84,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x87}, {0xe3,0x83,0x86,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x89}, {0xe3,0x83,0x88,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x90}, {0xe3,0x83,0x8f,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x91}, {0xe3,0x83,0x8f,0xe3,0x82,0x9a}},
- {{0xe3,0x83,0x93}, {0xe3,0x83,0x92,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x94}, {0xe3,0x83,0x92,0xe3,0x82,0x9a}},
- {{0xe3,0x83,0x96}, {0xe3,0x83,0x95,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x97}, {0xe3,0x83,0x95,0xe3,0x82,0x9a}},
- {{0xe3,0x83,0x99}, {0xe3,0x83,0x98,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x9a}, {0xe3,0x83,0x98,0xe3,0x82,0x9a}},
- {{0xe3,0x83,0x9c}, {0xe3,0x83,0x9b,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x9d}, {0xe3,0x83,0x9b,0xe3,0x82,0x9a}},
- {{0xe3,0x83,0xb7}, {0xe3,0x83,0xaf,0xe3,0x82,0x99}},
- {{0xe3,0x83,0xb8}, {0xe3,0x83,0xb0,0xe3,0x82,0x99}},
- {{0xe3,0x83,0xb9}, {0xe3,0x83,0xb1,0xe3,0x82,0x99}},
- {{0xe3,0x83,0xba}, {0xe3,0x83,0xb2,0xe3,0x82,0x99}},
- {{0xe3,0x83,0xbe}, {0xe3,0x83,0xbd,0xe3,0x82,0x99}},
-};
-#endif /* UNICODE_NORMALIZATION */
-#endif /* UTF8_INPUT_ENABLE */
-
-#ifdef SHIFTJIS_CP932
-const unsigned short shiftjis_cp932[3][189] = {
- {
- 0xEEEF, 0xEEF0, 0xEEF1, 0xEEF2, 0xEEF3, 0xEEF4, 0xEEF5, 0xEEF6,
- 0xEEF7, 0xEEF8, 0x8754, 0x8755, 0x8756, 0x8757, 0x8758, 0x8759,
- 0x875A, 0x875B, 0x875C, 0x875D, 0x81CA, 0xEEFA, 0xEEFB, 0xEEFC,
- 0x878A, 0x8782, 0x8784, 0x81E6, 0xED40, 0xED41, 0xED42, 0xED43,
- 0xED44, 0xED45, 0xED46, 0xED47, 0xED48, 0xED49, 0xED4A, 0xED4B,
- 0xED4C, 0xED4D, 0xED4E, 0xED4F, 0xED50, 0xED51, 0xED52, 0xED53,
- 0xED54, 0xED55, 0xED56, 0xED57, 0xED58, 0xED59, 0xED5A, 0xED5B,
- 0xED5C, 0xED5D, 0xED5E, 0xED5F, 0xED60, 0xED61, 0xED62, 0,
- 0xED63, 0xED64, 0xED65, 0xED66, 0xED67, 0xED68, 0xED69, 0xED6A,
- 0xED6B, 0xED6C, 0xED6D, 0xED6E, 0xED6F, 0xED70, 0xED71, 0xED72,
- 0xED73, 0xED74, 0xED75, 0xED76, 0xED77, 0xED78, 0xED79, 0xED7A,
- 0xED7B, 0xED7C, 0xED7D, 0xED7E, 0xED80, 0xED81, 0xED82, 0xED83,
- 0xED84, 0xED85, 0xED86, 0xED87, 0xED88, 0xED89, 0xED8A, 0xED8B,
- 0xED8C, 0xED8D, 0xED8E, 0xED8F, 0xED90, 0xED91, 0xED92, 0xED93,
- 0xED94, 0xED95, 0xED96, 0xED97, 0xED98, 0xED99, 0xED9A, 0xED9B,
- 0xED9C, 0xED9D, 0xED9E, 0xED9F, 0xEDA0, 0xEDA1, 0xEDA2, 0xEDA3,
- 0xEDA4, 0xEDA5, 0xEDA6, 0xEDA7, 0xEDA8, 0xEDA9, 0xEDAA, 0xEDAB,
- 0xEDAC, 0xEDAD, 0xEDAE, 0xEDAF, 0xEDB0, 0xEDB1, 0xEDB2, 0xEDB3,
- 0xEDB4, 0xEDB5, 0xEDB6, 0xEDB7, 0xEDB8, 0xEDB9, 0xEDBA, 0xEDBB,
- 0xEDBC, 0xEDBD, 0xEDBE, 0xEDBF, 0xEDC0, 0xEDC1, 0xEDC2, 0xEDC3,
- 0xEDC4, 0xEDC5, 0xEDC6, 0xEDC7, 0xEDC8, 0xEDC9, 0xEDCA, 0xEDCB,
- 0xEDCC, 0xEDCD, 0xEDCE, 0xEDCF, 0xEDD0, 0xEDD1, 0xEDD2, 0xEDD3,
- 0xEDD4, 0xEDD5, 0xEDD6, 0xEDD7, 0xEDD8, 0xEDD9, 0xEDDA, 0xEDDB,
- 0xEDDC, 0xEDDD, 0xEDDE, 0xEDDF, 0xEDE0,
- },
- {
- 0xEDE1, 0xEDE2, 0xEDE3, 0xEDE4, 0xEDE5, 0xEDE6, 0xEDE7, 0xEDE8,
- 0xEDE9, 0xEDEA, 0xEDEB, 0xEDEC, 0xEDED, 0xEDEE, 0xEDEF, 0xEDF0,
- 0xEDF1, 0xEDF2, 0xEDF3, 0xEDF4, 0xEDF5, 0xEDF6, 0xEDF7, 0xEDF8,
- 0xEDF9, 0xEDFA, 0xEDFB, 0xEDFC, 0xEE40, 0xEE41, 0xEE42, 0xEE43,
- 0xEE44, 0xEE45, 0xEE46, 0xEE47, 0xEE48, 0xEE49, 0xEE4A, 0xEE4B,
- 0xEE4C, 0xEE4D, 0xEE4E, 0xEE4F, 0xEE50, 0xEE51, 0xEE52, 0xEE53,
- 0xEE54, 0xEE55, 0xEE56, 0xEE57, 0xEE58, 0xEE59, 0xEE5A, 0xEE5B,
- 0xEE5C, 0xEE5D, 0xEE5E, 0xEE5F, 0xEE60, 0xEE61, 0xEE62, 0,
- 0xEE63, 0xEE64, 0xEE65, 0xEE66, 0xEE67, 0xEE68, 0xEE69, 0xEE6A,
- 0xEE6B, 0xEE6C, 0xEE6D, 0xEE6E, 0xEE6F, 0xEE70, 0xEE71, 0xEE72,
- 0xEE73, 0xEE74, 0xEE75, 0xEE76, 0xEE77, 0xEE78, 0xEE79, 0xEE7A,
- 0xEE7B, 0xEE7C, 0xEE7D, 0xEE7E, 0xEE80, 0xEE81, 0xEE82, 0xEE83,
- 0xEE84, 0xEE85, 0xEE86, 0xEE87, 0xEE88, 0xEE89, 0xEE8A, 0xEE8B,
- 0xEE8C, 0xEE8D, 0xEE8E, 0xEE8F, 0xEE90, 0xEE91, 0xEE92, 0xEE93,
- 0xEE94, 0xEE95, 0xEE96, 0xEE97, 0xEE98, 0xEE99, 0xEE9A, 0xEE9B,
- 0xEE9C, 0xEE9D, 0xEE9E, 0xEE9F, 0xEEA0, 0xEEA1, 0xEEA2, 0xEEA3,
- 0xEEA4, 0xEEA5, 0xEEA6, 0xEEA7, 0xEEA8, 0xEEA9, 0xEEAA, 0xEEAB,
- 0xEEAC, 0xEEAD, 0xEEAE, 0xEEAF, 0xEEB0, 0xEEB1, 0xEEB2, 0xEEB3,
- 0xEEB4, 0xEEB5, 0xEEB6, 0xEEB7, 0xEEB8, 0xEEB9, 0xEEBA, 0xEEBB,
- 0xEEBC, 0xEEBD, 0xEEBE, 0xEEBF, 0xEEC0, 0xEEC1, 0xEEC2, 0xEEC3,
- 0xEEC4, 0xEEC5, 0xEEC6, 0xEEC7, 0xEEC8, 0xEEC9, 0xEECA, 0xEECB,
- 0xEECC, 0xEECD, 0xEECE, 0xEECF, 0xEED0, 0xEED1, 0xEED2, 0xEED3,
- 0xEED4, 0xEED5, 0xEED6, 0xEED7, 0xEED8, 0xEED9, 0xEEDA, 0xEEDB,
- 0xEEDC, 0xEEDD, 0xEEDE, 0xEEDF, 0xEEE0,
- },
- {
- 0xEEE1, 0xEEE2, 0xEEE3, 0xEEE4, 0xEEE5, 0xEEE6, 0xEEE7, 0xEEE8,
- 0xEEE9, 0xEEEA, 0xEEEB, 0xEEEC, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- },
-};
-const unsigned short cp932inv[2][189] = {
- {
- 0xFA5C, 0xFA5D, 0xFA5E, 0xFA5F, 0xFA60, 0xFA61, 0xFA62, 0xFA63,
- 0xFA64, 0xFA65, 0xFA66, 0xFA67, 0xFA68, 0xFA69, 0xFA6A, 0xFA6B,
- 0xFA6C, 0xFA6D, 0xFA6E, 0xFA6F, 0xFA70, 0xFA71, 0xFA72, 0xFA73,
- 0xFA74, 0xFA75, 0xFA76, 0xFA77, 0xFA78, 0xFA79, 0xFA7A, 0xFA7B,
- 0xFA7C, 0xFA7D, 0xFA7E, 0xFA80, 0xFA81, 0xFA82, 0xFA83, 0xFA84,
- 0xFA85, 0xFA86, 0xFA87, 0xFA88, 0xFA89, 0xFA8A, 0xFA8B, 0xFA8C,
- 0xFA8D, 0xFA8E, 0xFA8F, 0xFA90, 0xFA91, 0xFA92, 0xFA93, 0xFA94,
- 0xFA95, 0xFA96, 0xFA97, 0xFA98, 0xFA99, 0xFA9A, 0xFA9B, 0,
- 0xFA9C, 0xFA9D, 0xFA9E, 0xFA9F, 0xFAA0, 0xFAA1, 0xFAA2, 0xFAA3,
- 0xFAA4, 0xFAA5, 0xFAA6, 0xFAA7, 0xFAA8, 0xFAA9, 0xFAAA, 0xFAAB,
- 0xFAAC, 0xFAAD, 0xFAAE, 0xFAAF, 0xFAB0, 0xFAB1, 0xFAB2, 0xFAB3,
- 0xFAB4, 0xFAB5, 0xFAB6, 0xFAB7, 0xFAB8, 0xFAB9, 0xFABA, 0xFABB,
- 0xFABC, 0xFABD, 0xFABE, 0xFABF, 0xFAC0, 0xFAC1, 0xFAC2, 0xFAC3,
- 0xFAC4, 0xFAC5, 0xFAC6, 0xFAC7, 0xFAC8, 0xFAC9, 0xFACA, 0xFACB,
- 0xFACC, 0xFACD, 0xFACE, 0xFACF, 0xFAD0, 0xFAD1, 0xFAD2, 0xFAD3,
- 0xFAD4, 0xFAD5, 0xFAD6, 0xFAD7, 0xFAD8, 0xFAD9, 0xFADA, 0xFADB,
- 0xFADC, 0xFADD, 0xFADE, 0xFADF, 0xFAE0, 0xFAE1, 0xFAE2, 0xFAE3,
- 0xFAE4, 0xFAE5, 0xFAE6, 0xFAE7, 0xFAE8, 0xFAE9, 0xFAEA, 0xFAEB,
- 0xFAEC, 0xFAED, 0xFAEE, 0xFAEF, 0xFAF0, 0xFAF1, 0xFAF2, 0xFAF3,
- 0xFAF4, 0xFAF5, 0xFAF6, 0xFAF7, 0xFAF8, 0xFAF9, 0xFAFA, 0xFAFB,
- 0xFAFC, 0xFB40, 0xFB41, 0xFB42, 0xFB43, 0xFB44, 0xFB45, 0xFB46,
- 0xFB47, 0xFB48, 0xFB49, 0xFB4A, 0xFB4B, 0xFB4C, 0xFB4D, 0xFB4E,
- 0xFB4F, 0xFB50, 0xFB51, 0xFB52, 0xFB53, 0xFB54, 0xFB55, 0xFB56,
- 0xFB57, 0xFB58, 0xFB59, 0xFB5A, 0xFB5B,
- },
- {
- 0xFB5C, 0xFB5D, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61, 0xFB62, 0xFB63,
- 0xFB64, 0xFB65, 0xFB66, 0xFB67, 0xFB68, 0xFB69, 0xFB6A, 0xFB6B,
- 0xFB6C, 0xFB6D, 0xFB6E, 0xFB6F, 0xFB70, 0xFB71, 0xFB72, 0xFB73,
- 0xFB74, 0xFB75, 0xFB76, 0xFB77, 0xFB78, 0xFB79, 0xFB7A, 0xFB7B,
- 0xFB7C, 0xFB7D, 0xFB7E, 0xFB80, 0xFB81, 0xFB82, 0xFB83, 0xFB84,
- 0xFB85, 0xFB86, 0xFB87, 0xFB88, 0xFB89, 0xFB8A, 0xFB8B, 0xFB8C,
- 0xFB8D, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, 0xFB92, 0xFB93, 0xFB94,
- 0xFB95, 0xFB96, 0xFB97, 0xFB98, 0xFB99, 0xFB9A, 0xFB9B, 0,
- 0xFB9C, 0xFB9D, 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3,
- 0xFBA4, 0xFBA5, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9, 0xFBAA, 0xFBAB,
- 0xFBAC, 0xFBAD, 0xFBAE, 0xFBAF, 0xFBB0, 0xFBB1, 0xFBB2, 0xFBB3,
- 0xFBB4, 0xFBB5, 0xFBB6, 0xFBB7, 0xFBB8, 0xFBB9, 0xFBBA, 0xFBBB,
- 0xFBBC, 0xFBBD, 0xFBBE, 0xFBBF, 0xFBC0, 0xFBC1, 0xFBC2, 0xFBC3,
- 0xFBC4, 0xFBC5, 0xFBC6, 0xFBC7, 0xFBC8, 0xFBC9, 0xFBCA, 0xFBCB,
- 0xFBCC, 0xFBCD, 0xFBCE, 0xFBCF, 0xFBD0, 0xFBD1, 0xFBD2, 0xFBD3,
- 0xFBD4, 0xFBD5, 0xFBD6, 0xFBD7, 0xFBD8, 0xFBD9, 0xFBDA, 0xFBDB,
- 0xFBDC, 0xFBDD, 0xFBDE, 0xFBDF, 0xFBE0, 0xFBE1, 0xFBE2, 0xFBE3,
- 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEB,
- 0xFBEC, 0xFBED, 0xFBEE, 0xFBEF, 0xFBF0, 0xFBF1, 0xFBF2, 0xFBF3,
- 0xFBF4, 0xFBF5, 0xFBF6, 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB,
- 0xFBFC, 0xFC40, 0xFC41, 0xFC42, 0xFC43, 0xFC44, 0xFC45, 0xFC46,
- 0xFC47, 0xFC48, 0xFC49, 0xFC4A, 0xFC4B, 0, 0, 0xFA40,
- 0xFA41, 0xFA42, 0xFA43, 0xFA44, 0xFA45, 0xFA46, 0xFA47, 0xFA48,
- 0xFA49, 0, 0xFA55, 0xFA56, 0xFA57,
- },
-};
-#endif /* SHIFTJIS_CP932 */
-
-#ifdef X0212_ENABLE
-const unsigned short shiftjis_x0212[3][189] = {
- {
- 0xF373, 0xF374, 0xF375, 0xF376, 0xF377, 0xF378, 0xF379, 0xF37A,
- 0xF37B, 0xF37C, 0xF37D, 0xF37E, 0xF421, 0xF422, 0xF423, 0xF424,
- 0xF425, 0xF426, 0xF427, 0xF428, 0x224C, 0xA243, 0xF429, 0xF42A,
- 0xF42B, 0xF42C, 0xF42D, 0x2268, 0xD463, 0xDC5F, 0xE469, 0xE378,
- 0xD921, 0xB13B, 0xF42E, 0xC22D, 0xC37C, 0xE450, 0xC23F, 0xBC74,
- 0xB029, 0xB048, 0xF42F, 0xB052, 0xB054, 0xB063, 0xB06E, 0xB127,
- 0xB123, 0xB12C, 0xB129, 0xB13E, 0xB15F, 0xB158, 0xB148, 0xB157,
- 0xB163, 0xB174, 0xB161, 0xB223, 0xF430, 0xB23B, 0xB266, 0,
- 0xB26D, 0xB275, 0xB27C, 0xF431, 0xB335, 0xB358, 0xB35B, 0xB365,
- 0xB36E, 0xB37B, 0xF432, 0xF433, 0xB440, 0xB447, 0xB450, 0xB45E,
- 0xF434, 0xB52A, 0xF435, 0xB52F, 0xB544, 0xB568, 0xF436, 0xB742,
- 0xB764, 0xB768, 0xB767, 0xF437, 0xF438, 0xF439, 0xB84E, 0xB861,
- 0xB875, 0xB877, 0xB878, 0xB87C, 0xB92F, 0xB937, 0xBA3E, 0xBA5B,
- 0xCD2A, 0xBA61, 0xF43A, 0xBA6B, 0xBB33, 0xBB38, 0xF43B, 0xBB4A,
- 0xF43C, 0xF43D, 0xBB50, 0xBB5E, 0xBB74, 0xBB75, 0xBB79, 0xBC64,
- 0xBC6D, 0xBC7E, 0xF43E, 0xBD42, 0xBD67, 0xF43F, 0xBD70, 0xBE30,
- 0xBE2C, 0xF440, 0xBE33, 0xBE3D, 0xBE4D, 0xBE49, 0xBE64, 0xBF28,
- 0xBF49, 0xC044, 0xC064, 0xC074, 0xC126, 0xF441, 0xC175, 0xC17C,
- 0xF442, 0xC178, 0xC22B, 0xC221, 0xC225, 0xF443, 0xC238, 0xC23A,
- 0xF444, 0xC244, 0xC252, 0xC257, 0xC25B, 0xC25E, 0xC26D, 0xC270,
- 0xF445, 0xC321, 0xC335, 0xC349, 0xC339, 0xF446, 0xC358, 0xC37E,
- 0xF447, 0xC44C, 0xF448, 0xC459, 0xC46A, 0xC47D, 0xF449, 0xC527,
- 0xC535, 0xC536, 0xF44A, 0xC555, 0xC638, 0xC657, 0xC660, 0xC66A,
- 0xC663, 0xC721, 0xC72B, 0xC747, 0xC743,
- },
- {
- 0xC74B, 0xC74F, 0xC759, 0xF44B, 0xF44C, 0xC766, 0xC76E, 0xC77C,
- 0xC76B, 0xC770, 0xC831, 0xC865, 0xC878, 0xC926, 0xC92B, 0xC92D,
- 0xF44D, 0xC94A, 0xC953, 0xC969, 0xC963, 0xC97C, 0xC974, 0xC975,
- 0xF44E, 0xCA33, 0xCA3D, 0xCA6F, 0xCA71, 0xCB2E, 0xF44F, 0xCB4A,
- 0xCB66, 0xCB6A, 0xCB70, 0xCB74, 0xCB6E, 0xCC25, 0xCB79, 0xCC2B,
- 0xCC2E, 0xCC2D, 0xCC32, 0xCC42, 0xCC50, 0xCC59, 0xF450, 0xCD3B,
- 0xF451, 0xCE3B, 0xF452, 0xCE3A, 0xCE43, 0xF453, 0xCE72, 0xB35D,
- 0xCF55, 0xCF62, 0xCF69, 0xCF6D, 0xF454, 0xF455, 0xF456, 0,
- 0xF457, 0xD065, 0xF458, 0xD069, 0xD168, 0xF459, 0xF45A, 0xD16C,
- 0xD23B, 0xF45B, 0xD361, 0xD368, 0xD427, 0xF45C, 0xF45D, 0xD454,
- 0xD472, 0xD52E, 0xF45E, 0xD75E, 0xF45F, 0xD822, 0xD837, 0xD841,
- 0xD851, 0xD874, 0xD946, 0xD948, 0xD951, 0xF460, 0xF461, 0xF462,
- 0xF463, 0xF464, 0xDC53, 0xDD48, 0xDD54, 0xDD6A, 0xDD7A, 0xDE24,
- 0xDE30, 0xF465, 0xDE35, 0xDE4B, 0xF466, 0xDF39, 0xF467, 0xDF43,
- 0xF468, 0xF469, 0xE059, 0xF46A, 0xF46B, 0xE162, 0xF46C, 0xF46D,
- 0xF46E, 0xE247, 0xE328, 0xE326, 0xE329, 0xE32F, 0xE330, 0xE32A,
- 0xE32B, 0xE33C, 0xE341, 0xE33F, 0xE355, 0xE358, 0xE356, 0xE35F,
- 0xE363, 0xE361, 0xE354, 0xE369, 0xE426, 0xE371, 0xE372, 0xE44B,
- 0xE441, 0xE443, 0xE43E, 0xF46F, 0xE440, 0xE447, 0xE43F, 0xE460,
- 0xE45E, 0xE451, 0xF470, 0xE45C, 0xE452, 0xE45B, 0xE454, 0xE47A,
- 0xE46F, 0xE533, 0xE53F, 0xE549, 0xE550, 0xE562, 0xE56A, 0xE56B,
- 0xF471, 0xF472, 0xF473, 0xE668, 0xE66F, 0xE72C, 0xF474, 0xE72E,
- 0xF475, 0xE731, 0xF476, 0xE732, 0xE831, 0xE836, 0xF477, 0xF478,
- 0xE85D, 0xF479, 0xF47A, 0xE951, 0xF47B,
- },
- {
- 0xE96D, 0xEA4D, 0xF47C, 0xEA5B, 0xEA66, 0xEA6A, 0xEB25, 0xEB7B,
- 0xEB7A, 0xF47D, 0xEC56, 0xF47E, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- },
-};
-
-const unsigned short x0212_shiftjis_A2[] = {
- 0x819F, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x8143, 0, 0, 0x8150, 0, 0, 0x8160,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA55, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_B0[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFA68, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFA69, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFA6B, 0, 0xFA6C, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA6D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFA6E, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_B1[] = {
- 0, 0, 0xFA70, 0, 0, 0, 0xFA6F,
- 0, 0xFA72, 0, 0, 0xFA71, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA61, 0, 0, 0xFA73, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFA76, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFA77,
- 0xFA75, 0, 0, 0, 0, 0, 0, 0xFA74,
- 0, 0xFA7A, 0, 0xFA78, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFA79, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_B2[] = {
- 0, 0, 0xFA7B, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA7D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFA7E, 0,
- 0, 0, 0, 0, 0, 0xFA80, 0, 0,
- 0, 0, 0, 0, 0, 0xFA81, 0, 0,
- 0, 0, 0, 0, 0xFA82, 0, 0,
-};
-const unsigned short x0212_shiftjis_B3[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFA84, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFA85, 0, 0, 0xFA86, 0, 0xFB77, 0, 0,
- 0, 0, 0, 0, 0, 0xFA87, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFA88, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA89, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_B4[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFA8C, 0, 0, 0, 0, 0, 0, 0xFA8D,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFA8E, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFA8F, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_B5[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFA91, 0, 0, 0, 0, 0xFA93,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFA94, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFA95, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_B7[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFA97, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFA98, 0, 0, 0xFA9A,
- 0xFA99, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_B8[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFA9E, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFA9F, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAA0, 0, 0xFAA1,
- 0xFAA2, 0, 0, 0, 0xFAA3, 0, 0,
-};
-const unsigned short x0212_shiftjis_B9[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFAA4,
- 0, 0, 0, 0, 0, 0, 0, 0xFAA5,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_BA[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFAA6, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFAA7, 0, 0, 0, 0,
- 0, 0xFAA9, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFAAB, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_BB[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFAAC, 0, 0, 0, 0,
- 0xFAAD, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFAAF, 0, 0, 0, 0, 0,
- 0xFAB2, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFAB3, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFAB4, 0xFAB5, 0, 0,
- 0, 0xFAB6, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_BC[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFAB7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAB8, 0, 0,
- 0, 0, 0, 0, 0xFA67, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFAB9,
-};
-const unsigned short x0212_shiftjis_BD[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFABB, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFABC,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFABE, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_BE[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFAC0, 0, 0, 0,
- 0xFABF, 0, 0, 0xFAC2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAC3, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFAC5, 0, 0, 0, 0xFAC4, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFAC6, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_BF[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0xFAC7, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFAC8, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_C0[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFAC9, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFACA, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFACB, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_C1[] = {
- 0, 0, 0, 0, 0, 0xFACC, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFACE, 0, 0,
- 0xFAD1, 0, 0, 0, 0xFACF, 0, 0,
-};
-const unsigned short x0212_shiftjis_C2[] = {
- 0xFAD3, 0, 0, 0, 0xFAD4, 0, 0,
- 0, 0, 0, 0xFAD2, 0, 0xFA63, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFAD6, 0, 0xFAD7, 0, 0, 0, 0, 0xFA66,
- 0, 0, 0, 0, 0xFAD9, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFADA, 0, 0, 0, 0, 0xFADB,
- 0, 0, 0, 0xFADC, 0, 0, 0xFADD, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFADE, 0, 0,
- 0xFADF, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_C3[] = {
- 0xFAE1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAE2, 0, 0,
- 0, 0xFAE4, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFAE3, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFAE6, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFA64, 0, 0xFAE7,
-};
-const unsigned short x0212_shiftjis_C4[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFAE9, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFAEB, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFAEC, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAED, 0,
-};
-const unsigned short x0212_shiftjis_C5[] = {
- 0, 0, 0, 0, 0, 0, 0xFAEF,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAF0, 0xFAF1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAF3, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_C6[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFAF4, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFAF5,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFAF6, 0, 0, 0xFAF8, 0, 0, 0, 0,
- 0, 0, 0xFAF7, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_C7[] = {
- 0xFAF9, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFAFA, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFAFC, 0, 0, 0, 0xFAFB,
- 0, 0, 0, 0xFB40, 0, 0, 0, 0xFB41,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB42, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFB45, 0,
- 0, 0, 0, 0xFB48, 0, 0, 0xFB46, 0,
- 0xFB49, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFB47, 0, 0,
-};
-const unsigned short x0212_shiftjis_C8[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB4A, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFB4B, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFB4C, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_C9[] = {
- 0, 0, 0, 0, 0, 0xFB4D, 0,
- 0, 0, 0, 0xFB4E, 0, 0xFB4F, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB51, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFB52, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFB54, 0, 0, 0, 0,
- 0, 0xFB53, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFB56, 0xFB57, 0, 0,
- 0, 0, 0, 0, 0xFB55, 0, 0,
-};
-const unsigned short x0212_shiftjis_CA[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFB59, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFB5A, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFB5B,
- 0, 0xFB5C, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_CB[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFB5D, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB5F, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFB60, 0,
- 0, 0, 0xFB61, 0, 0, 0, 0xFB64, 0,
- 0xFB62, 0, 0, 0, 0xFB63, 0, 0, 0,
- 0, 0xFB66, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_CC[] = {
- 0, 0, 0, 0, 0xFB65, 0, 0,
- 0, 0, 0, 0xFB67, 0, 0xFB69, 0xFB68, 0,
- 0, 0, 0xFB6A, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB6B, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFB6C, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB6D, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_CD[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFAA8, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFB6F, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_CE[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB73, 0xFB71, 0, 0, 0, 0,
- 0, 0, 0, 0xFB74, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB76, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_CF[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFB78, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB79, 0, 0, 0, 0, 0,
- 0, 0xFB7A, 0, 0, 0, 0xFB7B, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_D0[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFB81, 0, 0,
- 0, 0xFB83, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_D1[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFB84, 0, 0, 0, 0xFB87, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_D2[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFB88, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_D3[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB8A, 0, 0, 0, 0, 0, 0,
- 0xFB8B, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_D4[] = {
- 0, 0, 0, 0, 0, 0, 0xFB8C,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFB8F, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA5C, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB90, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_D5[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFB91, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_D7[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFB93, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_D8[] = {
- 0, 0xFB95, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFB96,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB97, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB98, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFB99, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_D9[] = {
- 0xFA60, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFB9A, 0,
- 0xFB9B, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB9C, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_DC[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFBA2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFA5D,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_DD[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFBA3, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFBA4, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFBA5, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFBA6, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_DE[] = {
- 0, 0, 0, 0xFBA7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFBA8, 0, 0, 0, 0, 0xFBAA, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFBAB, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_DF[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFBAD, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFBAF, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_E0[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFBB2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_E1[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFBB5, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_E2[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFBB9,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_E3[] = {
- 0, 0, 0, 0, 0, 0xFBBB, 0,
- 0xFBBA, 0xFBBC, 0xFBBF, 0xFBC0, 0, 0, 0, 0xFBBD,
- 0xFBBE, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFBC1, 0, 0, 0xFBC3,
- 0, 0xFBC2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFBCA, 0xFBC4, 0xFBC6, 0,
- 0xFBC5, 0, 0, 0, 0, 0, 0, 0xFBC7,
- 0, 0xFBC9, 0, 0xFBC8, 0, 0, 0, 0,
- 0, 0xFBCB, 0, 0, 0, 0, 0, 0,
- 0, 0xFBCD, 0xFBCE, 0, 0, 0, 0, 0,
- 0xFA5F, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_E4[] = {
- 0, 0, 0, 0, 0, 0xFBCC, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFBD2, 0xFBD6,
- 0xFBD4, 0xFBD0, 0, 0xFBD1, 0, 0, 0, 0xFBD5,
- 0, 0, 0, 0xFBCF, 0, 0, 0, 0,
- 0xFA65, 0xFBD9, 0xFBDC, 0, 0xFBDE, 0, 0, 0,
- 0, 0, 0, 0xFBDD, 0xFBDB, 0, 0xFBD8, 0,
- 0xFBD7, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFA5E, 0, 0, 0, 0, 0, 0xFBE0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFBDF, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_E5[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFBE1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFBE2,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFBE3, 0, 0, 0, 0, 0, 0,
- 0xFBE4, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFBE5, 0, 0, 0, 0, 0,
- 0, 0, 0xFBE6, 0xFBE7, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_E6[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFBEB, 0, 0, 0, 0, 0, 0, 0xFBEC,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_E7[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFBED, 0, 0xFBEF, 0,
- 0, 0xFBF1, 0xFBF3, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_E8[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFBF4, 0, 0, 0, 0, 0xFBF5, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFBF8, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_E9[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFBFB, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFC40, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_EA[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFC41, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFC43, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFC44, 0,
- 0, 0, 0xFC45, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_EB[] = {
- 0, 0, 0, 0, 0xFC46, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFC48, 0xFC47, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_EC[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFC4A, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-const unsigned short x0212_shiftjis_F3[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA40, 0xFA41, 0xFA42, 0xFA43, 0xFA44,
- 0xFA45, 0xFA46, 0xFA47, 0xFA48, 0xFA49, 0xFA4A, 0xFA4B,
-};
-const unsigned short x0212_shiftjis_F4[] = {
- 0xFA4C, 0xFA4D, 0xFA4E, 0xFA4F, 0xFA50, 0xFA51, 0xFA52,
- 0xFA53, 0xFA56, 0xFA57, 0xFA58, 0xFA59, 0xFA5A, 0xFA62, 0xFA6A,
- 0xFA7C, 0xFA83, 0xFA8A, 0xFA8B, 0xFA90, 0xFA92, 0xFA96, 0xFA9B,
- 0xFA9C, 0xFA9D, 0xFAAA, 0xFAAE, 0xFAB0, 0xFAB1, 0xFABA, 0xFABD,
- 0xFAC1, 0xFACD, 0xFAD0, 0xFAD5, 0xFAD8, 0xFAE0, 0xFAE5, 0xFAE8,
- 0xFAEA, 0xFAEE, 0xFAF2, 0xFB43, 0xFB44, 0xFB50, 0xFB58, 0xFB5E,
- 0xFB6E, 0xFB70, 0xFB72, 0xFB75, 0xFB7C, 0xFB7D, 0xFB7E, 0xFB80,
- 0xFB82, 0xFB85, 0xFB86, 0xFB89, 0xFB8D, 0xFB8E, 0xFB92, 0xFB94,
- 0xFB9D, 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA9, 0xFBAC, 0xFBAE,
- 0xFBB0, 0xFBB1, 0xFBB3, 0xFBB4, 0xFBB6, 0xFBB7, 0xFBB8, 0xFBD3,
- 0xFBDA, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEE, 0xFBF0, 0xFBF2, 0xFBF6,
- 0xFBF7, 0xFBF9, 0xFBFA, 0xFBFC, 0xFC42, 0xFC49, 0xFC4B,
-};
-const unsigned short *const x0212_shiftjis[] = {
- 0, x0212_shiftjis_A2, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- x0212_shiftjis_B0, x0212_shiftjis_B1, x0212_shiftjis_B2, x0212_shiftjis_B3,
- x0212_shiftjis_B4, x0212_shiftjis_B5, 0, x0212_shiftjis_B7,
- x0212_shiftjis_B8, x0212_shiftjis_B9, x0212_shiftjis_BA, x0212_shiftjis_BB,
- x0212_shiftjis_BC, x0212_shiftjis_BD, x0212_shiftjis_BE, x0212_shiftjis_BF,
- x0212_shiftjis_C0, x0212_shiftjis_C1, x0212_shiftjis_C2, x0212_shiftjis_C3,
- x0212_shiftjis_C4, x0212_shiftjis_C5, x0212_shiftjis_C6, x0212_shiftjis_C7,
- x0212_shiftjis_C8, x0212_shiftjis_C9, x0212_shiftjis_CA, x0212_shiftjis_CB,
- x0212_shiftjis_CC, x0212_shiftjis_CD, x0212_shiftjis_CE, x0212_shiftjis_CF,
- x0212_shiftjis_D0, x0212_shiftjis_D1, x0212_shiftjis_D2, x0212_shiftjis_D3,
- x0212_shiftjis_D4, x0212_shiftjis_D5, 0, x0212_shiftjis_D7,
- x0212_shiftjis_D8, x0212_shiftjis_D9, 0, 0,
- x0212_shiftjis_DC, x0212_shiftjis_DD, x0212_shiftjis_DE, x0212_shiftjis_DF,
- x0212_shiftjis_E0, x0212_shiftjis_E1, x0212_shiftjis_E2, x0212_shiftjis_E3,
- x0212_shiftjis_E4, x0212_shiftjis_E5, x0212_shiftjis_E6, x0212_shiftjis_E7,
- x0212_shiftjis_E8, x0212_shiftjis_E9, x0212_shiftjis_EA, x0212_shiftjis_EB,
- x0212_shiftjis_EC, 0, 0, 0,
- 0, 0, 0, x0212_shiftjis_F3,
- x0212_shiftjis_F4, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0,
-};
-#endif /* X0212_ENABLE */
diff --git a/ext/nkf/nkf-utf8/utf8tbl.h b/ext/nkf/nkf-utf8/utf8tbl.h
deleted file mode 100644
index 1f40f0b363..0000000000
--- a/ext/nkf/nkf-utf8/utf8tbl.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef _UTF8TBL_H_
-#define _UTF8TBL_H_
-
-#ifdef UTF8_OUTPUT_ENABLE
-extern const unsigned short euc_to_utf8_1byte[];
-extern const unsigned short *const euc_to_utf8_2bytes[];
-extern const unsigned short *const euc_to_utf8_2bytes_ms[];
-extern const unsigned short *const x0212_to_utf8_2bytes[];
-#endif /* UTF8_OUTPUT_ENABLE */
-
-#ifdef UTF8_INPUT_ENABLE
-extern const unsigned short *const utf8_to_euc_2bytes[];
-extern const unsigned short *const utf8_to_euc_2bytes_ms[];
-extern const unsigned short *const utf8_to_euc_2bytes_932[];
-extern const unsigned short *const *const utf8_to_euc_3bytes[];
-extern const unsigned short *const *const utf8_to_euc_3bytes_ms[];
-extern const unsigned short *const *const utf8_to_euc_3bytes_932[];
-#endif /* UTF8_INPUT_ENABLE */
-
-#ifdef UNICODE_NORMALIZATION
-extern const struct normalization_pair normalization_table[];
-#endif
-
-#ifdef SHIFTJIS_CP932
-extern const unsigned short shiftjis_cp932[3][189];
-extern const unsigned short cp932inv[2][189];
-#endif /* SHIFTJIS_CP932 */
-
-#ifdef X0212_ENABLE
-extern const unsigned short shiftjis_x0212[3][189];
-extern const unsigned short *const x0212_shiftjis[];
-#endif /* X0212_ENABLE */
-
-#endif
diff --git a/ext/nkf/nkf.c b/ext/nkf/nkf.c
deleted file mode 100644
index 8eb92b6cd6..0000000000
--- a/ext/nkf/nkf.c
+++ /dev/null
@@ -1,654 +0,0 @@
-/*
- * NKF - Ruby extension for Network Kanji Filter
- *
- * original nkf2.x is maintained at http://sourceforge.jp/projects/nkf/
- *
- * $Id$
- *
- */
-
-#define RUBY_NKF_REVISION "$Revision$"
-#define RUBY_NKF_VERSION NKF_VERSION " (" NKF_RELEASE_DATE ")"
-
-#include "ruby.h"
-
-/* Encoding Constants */
-#define _AUTO 0
-#define _JIS 1
-#define _EUC 2
-#define _SJIS 3
-#define _BINARY 4
-#define _NOCONV 4
-#define _ASCII 5
-/* 0b011x is reserved for UTF-8 Family */
-#define _UTF8 6
-/* 0b10xx is reserved for UTF-16 Family */
-#define _UTF16 8
-/* 0b11xx is reserved for UTF-32 Family */
-#define _UTF32 12
-#define _OTHER 16
-#define _UNKNOWN _AUTO
-
-/* Replace nkf's getchar/putchar for variable modification */
-/* we never use getc, ungetc */
-
-#undef getc
-#undef ungetc
-#define getc(f) (input_ctr>=i_len?-1:input[input_ctr++])
-#define ungetc(c,f) input_ctr--
-
-#define INCSIZE 32
-#undef putchar
-#undef TRUE
-#undef FALSE
-#define putchar(c) rb_nkf_putchar(c)
-
-/* Input/Output pointers */
-
-static unsigned char *output;
-static unsigned char *input;
-static int input_ctr;
-static int i_len;
-static int output_ctr;
-static int o_len;
-static int incsize;
-
-static VALUE result;
-
-static int
-rb_nkf_putchar(c)
- unsigned int c;
-{
- if (output_ctr >= o_len) {
- o_len += incsize;
- rb_str_resize(result, o_len);
- incsize *= 2;
- output = RSTRING(result)->ptr;
- }
- output[output_ctr++] = c;
-
- return c;
-}
-
-/* Include kanji filter main part */
-/* getchar and putchar will be replaced during inclusion */
-
-#define PERL_XS 1
-#include "nkf-utf8/config.h"
-#include "nkf-utf8/utf8tbl.c"
-#include "nkf-utf8/nkf.c"
-
-int nkf_split_options(arg)
- const char* arg;
-{
- int count = 0;
- char option[256];
- int i = 0, j = 0;
- int is_escaped = FALSE;
- int is_single_quoted = FALSE;
- int is_double_quoted = FALSE;
- for(i = 0; arg[i]; i++){
- if(j == 255){
- return -1;
- }else if(is_single_quoted){
- if(arg[i] == '\''){
- is_single_quoted = FALSE;
- }else{
- option[j++] = arg[i];
- }
- }else if(is_escaped){
- is_escaped = FALSE;
- option[j++] = arg[i];
- }else if(arg[i] == '\\'){
- is_escaped = TRUE;
- }else if(is_double_quoted){
- if(arg[i] == '"'){
- is_double_quoted = FALSE;
- }else{
- option[j++] = arg[i];
- }
- }else if(arg[i] == '\''){
- is_single_quoted = TRUE;
- }else if(arg[i] == '"'){
- is_double_quoted = TRUE;
- }else if(arg[i] == ' '){
- option[j] = '\0';
- options(option);
- j = 0;
- }else{
- option[j++] = arg[i];
- }
- }
- if(j){
- option[j] = '\0';
- options(option);
- }
- return count;
-}
-
-/*
- * call-seq:
- * NKF.nkf(opt, str) -> string
- *
- * Convert _str_ and return converted result.
- * Conversion details are specified by _opt_ as String.
- *
- * require 'nkf'
- * output = NKF.nkf("-s", input)
- *
- * *Note*
- * By default, nkf decodes MIME encoded string.
- * If you want not to decode input, use NKF.nkf with <b>-m0</b> flag.
- */
-
-static VALUE
-rb_nkf_kconv(obj, opt, src)
- VALUE obj, opt, src;
-{
- char *opt_ptr, *opt_end;
- volatile VALUE v;
-
- reinit();
- StringValue(opt);
- opt_ptr = RSTRING(opt)->ptr;
- opt_end = opt_ptr + RSTRING(opt)->len;
- nkf_split_options(opt_ptr);
-
- incsize = INCSIZE;
-
- input_ctr = 0;
- StringValue(src);
- input = RSTRING(src)->ptr;
- i_len = RSTRING(src)->len;
- result = rb_str_new(0, i_len*3 + 10);
- v = result;
-
- output_ctr = 0;
- output = RSTRING(result)->ptr;
- o_len = RSTRING(result)->len;
- *output = '\0';
-
- if(x0201_f == WISH_TRUE)
- x0201_f = ((!iso2022jp_f)? TRUE : NO_X0201);
-
- kanji_convert(NULL);
- RSTRING(result)->ptr[output_ctr] = '\0';
- RSTRING(result)->len = output_ctr;
- OBJ_INFECT(result, src);
-
- return result;
-}
-
-
-/*
- * call-seq:
- * NKF.guess1(str) -> integer
- *
- * Returns guessed encoding of _str_ as integer.
- *
- * Algorithm described in:
- * Ken Lunde. `Understanding Japanese Information Processing'
- * Sebastopol, CA: O'Reilly & Associates.
- *
- * case NKF.guess1(input)
- * when NKF::JIS
- * "ISO-2022-JP"
- * when NKF::SJIS
- * "Shift_JIS"
- * when NKF::EUC
- * "EUC-JP"
- * when NKF::UNKNOWN
- * "UNKNOWN(ASCII)"
- * when NKF::BINARY
- * "BINARY"
- * end
- */
-
-static VALUE
-rb_nkf_guess1(obj, src)
- VALUE obj, src;
-{
- unsigned char *p;
- unsigned char *pend;
- int sequence_counter = 0;
-
- StringValue(src);
- p = RSTRING(src)->ptr;
- pend = p + RSTRING(src)->len;
- if (p == pend) return INT2FIX(_UNKNOWN);
-
-#define INCR do {\
- p++;\
- if (p==pend) return INT2FIX(_UNKNOWN);\
- sequence_counter++;\
- if (sequence_counter % 2 == 1 && *p != 0xa4)\
- sequence_counter = 0;\
- if (6 <= sequence_counter) {\
- sequence_counter = 0;\
- return INT2FIX(_EUC);\
- }\
- } while (0)
-
- if (*p == 0xa4)
- sequence_counter = 1;
-
- while (p<pend) {
- if (*p == '\033') {
- return INT2FIX(_JIS);
- }
- if (*p < '\006' || *p == 0x7f || *p == 0xff) {
- return INT2FIX(_BINARY);
- }
- if (0x81 <= *p && *p <= 0x8d) {
- return INT2FIX(_SJIS);
- }
- if (0x8f <= *p && *p <= 0x9f) {
- return INT2FIX(_SJIS);
- }
- if (*p == 0x8e) { /* SS2 */
- INCR;
- if ((0x40 <= *p && *p <= 0x7e) ||
- (0x80 <= *p && *p <= 0xa0) ||
- (0xe0 <= *p && *p <= 0xfc))
- return INT2FIX(_SJIS);
- }
- else if (0xa1 <= *p && *p <= 0xdf) {
- INCR;
- if (0xf0 <= *p && *p <= 0xfe)
- return INT2FIX(_EUC);
- if (0xe0 <= *p && *p <= 0xef) {
- while (p < pend && *p >= 0x40) {
- if (*p >= 0x81) {
- if (*p <= 0x8d || (0x8f <= *p && *p <= 0x9f)) {
- return INT2FIX(_SJIS);
- }
- else if (0xfd <= *p && *p <= 0xfe) {
- return INT2FIX(_EUC);
- }
- }
- INCR;
- }
- }
- else if (*p <= 0x9f) {
- return INT2FIX(_SJIS);
- }
- }
- else if (0xf0 <= *p && *p <= 0xfe) {
- return INT2FIX(_EUC);
- }
- else if (0xe0 <= *p && *p <= 0xef) {
- INCR;
- if ((0x40 <= *p && *p <= 0x7e) ||
- (0x80 <= *p && *p <= 0xa0)) {
- return INT2FIX(_SJIS);
- }
- if (0xfd <= *p && *p <= 0xfe) {
- return INT2FIX(_EUC);
- }
- }
- INCR;
- }
- return INT2FIX(_UNKNOWN);
-}
-
-
-/*
- * call-seq:
- * NKF.guess2(str) -> integer
- *
- * Returns guessed encoding of _str_ as integer by nkf routine.
- *
- * case NKF.guess(input)
- * when NKF::ASCII
- * "ASCII"
- * when NKF::JIS
- * "ISO-2022-JP"
- * when NKF::SJIS
- * "Shift_JIS"
- * when NKF::EUC
- * "EUC-JP"
- * when NKF::UTF8
- * "UTF-8"
- * when NKF::UTF16
- * "UTF-16"
- * when NKF::UNKNOWN
- * "UNKNOWN"
- * when NKF::BINARY
- * "BINARY"
- * end
- */
-
-static VALUE
-rb_nkf_guess2(obj, src)
- VALUE obj, src;
-{
- int code = _BINARY;
-
- reinit();
-
- input_ctr = 0;
- StringValue(src);
- input = RSTRING(src)->ptr;
- i_len = RSTRING(src)->len;
-
- if(x0201_f == WISH_TRUE)
- x0201_f = ((!iso2022jp_f)? TRUE : NO_X0201);
-
- guess_f = TRUE;
- kanji_convert( NULL );
- guess_f = FALSE;
-
- if (!is_inputcode_mixed) {
- if (strcmp(input_codename, "") == 0) {
- code = _ASCII;
- } else if (strcmp(input_codename, "ISO-2022-JP") == 0) {
- code = _JIS;
- } else if (strcmp(input_codename, "EUC-JP") == 0) {
- code = _EUC;
- } else if (strcmp(input_codename, "Shift_JIS") == 0) {
- code = _SJIS;
- } else if (strcmp(input_codename, "UTF-8") == 0) {
- code = _UTF8;
- } else if (strcmp(input_codename, "UTF-16") == 0) {
- code = _UTF16;
- } else if (strlen(input_codename) > 0) {
- code = _UNKNOWN;
- }
- }
-
- return INT2FIX( code );
-}
-
-
-/*
- * NKF - Ruby extension for Network Kanji Filter
- *
- * == Description
- *
- * This is a Ruby Extension version of nkf (Netowrk Kanji Filter).
- * It converts the first argument and return converted result. Conversion
- * details are specified by flags as the first argument.
- *
- * *Nkf* is a yet another kanji code converter among networks, hosts and terminals.
- * It converts input kanji code to designated kanji code
- * such as ISO-2022-JP, Shift_JIS, EUC-JP, UTF-8 or UTF-16.
- *
- * One of the most unique faculty of *nkf* is the guess of the input kanji encodings.
- * It currently recognizes ISO-2022-JP, Shift_JIS, EUC-JP, UTF-8 and UTF-16.
- * So users needn't set the input kanji code explicitly.
- *
- * By default, X0201 kana is converted into X0208 kana.
- * For X0201 kana, SO/SI, SSO and ESC-(-I methods are supported.
- * For automatic code detection, nkf assumes no X0201 kana in Shift_JIS.
- * To accept X0201 in Shift_JIS, use <b>-X</b>, <b>-x</b> or <b>-S</b>.
- *
- * == Flags
- *
- * === -b -u
- *
- * Output is buffered (DEFAULT), Output is unbuffered.
- *
- * === -j -s -e -w -w16
- *
- * Output code is ISO-2022-JP (7bit JIS), Shift_JIS, EUC-JP,
- * UTF-8N, UTF-16BE.
- * Without this option and compile option, ISO-2022-JP is assumed.
- *
- * === -J -S -E -W -W16
- *
- * Input assumption is JIS 7 bit, Shift_JIS, EUC-JP,
- * UTF-8, UTF-16LE.
- *
- * ==== -J
- *
- * Assume JIS input. It also accepts EUC-JP.
- * This is the default. This flag does not exclude Shift_JIS.
- *
- * ==== -S
- *
- * Assume Shift_JIS and X0201 kana input. It also accepts JIS.
- * EUC-JP is recognized as X0201 kana. Without <b>-x</b> flag,
- * X0201 kana (halfwidth kana) is converted into X0208.
- *
- * ==== -E
- *
- * Assume EUC-JP input. It also accepts JIS.
- * Same as -J.
- *
- * === -t
- *
- * No conversion.
- *
- * === -i_
- *
- * Output sequence to designate JIS-kanji. (DEFAULT B)
- *
- * === -o_
- *
- * Output sequence to designate ASCII. (DEFAULT B)
- *
- * === -r
- *
- * {de/en}crypt ROT13/47
- *
- * === -h[123] --hiragana --katakana --katakana-hiragana
- *
- * [-h1 --hiragana] Katakana to Hiragana conversion.
- *
- * [-h2 --katakana] Hiragana to Katakana conversion.
- *
- * [-h3 --katakana-hiragana] Katakana to Hiragana and Hiragana to Katakana conversion.
- *
- * === -T
- *
- * Text mode output (MS-DOS)
- *
- * === -l
- *
- * ISO8859-1 (Latin-1) support
- *
- * === -f[<code>m</code> [- <code>n</code>]]
- *
- * Folding on <code>m</code> length with <code>n</code> margin in a line.
- * Without this option, fold length is 60 and fold margin is 10.
- *
- * === -F
- *
- * New line preserving line folding.
- *
- * === -Z[0-3]
- *
- * Convert X0208 alphabet (Fullwidth Alphabets) to ASCII.
- *
- * [-Z -Z0] Convert X0208 alphabet to ASCII.
- *
- * [-Z1] Converts X0208 kankaku to single ASCII space.
- *
- * [-Z2] Converts X0208 kankaku to double ASCII spaces.
- *
- * [-Z3] Replacing Fullwidth >, <, ", & into '&gt;', '&lt;', '&quot;', '&amp;' as in HTML.
- *
- * === -X -x
- *
- * Assume X0201 kana in MS-Kanji.
- * With <b>-X</b> or without this option, X0201 is converted into X0208 Kana.
- * With <b>-x</b>, try to preserve X0208 kana and do not convert X0201 kana to X0208.
- * In JIS output, ESC-(-I is used. In EUC output, SSO is used.
- *
- * === -B[0-2]
- *
- * Assume broken JIS-Kanji input, which lost ESC.
- * Useful when your site is using old B-News Nihongo patch.
- *
- * [-B1] allows any char after ESC-( or ESC-$.
- *
- * [-B2] forces ASCII after NL.
- *
- * === -I
- *
- * Replacing non iso-2022-jp char into a geta character
- * (substitute character in Japanese).
- *
- * === -d -c
- *
- * Delete \r in line feed, Add \r in line feed.
- *
- * === -m[BQN0]
- *
- * MIME ISO-2022-JP/ISO8859-1 decode. (DEFAULT)
- * To see ISO8859-1 (Latin-1) -l is necessary.
- *
- * [-mB] Decode MIME base64 encoded stream. Remove header or other part before
- * conversion.
- *
- * [-mQ] Decode MIME quoted stream. '_' in quoted stream is converted to space.
- *
- * [-mN] Non-strict decoding.
- * It allows line break in the middle of the base64 encoding.
- *
- * [-m0] No MIME decode.
- *
- * === -M
- *
- * MIME encode. Header style. All ASCII code and control characters are intact.
- * Kanji conversion is performed before encoding, so this cannot be used as a picture encoder.
- *
- * [-MB] MIME encode Base64 stream.
- *
- * [-MQ] Perfome quoted encoding.
- *
- * === -l
- *
- * Input and output code is ISO8859-1 (Latin-1) and ISO-2022-JP.
- * <b>-s</b>, <b>-e</b> and <b>-x</b> are not compatible with this option.
- *
- * === -L[uwm]
- *
- * new line mode
- * Without this option, nkf doesn't convert line breaks.
- *
- * [-Lu] unix (LF)
- *
- * [-Lw] windows (CRLF)
- *
- * [-Lm] mac (CR)
- *
- * === --fj --unix --mac --msdos --windows
- *
- * convert for these system
- *
- * === --jis --euc --sjis --mime --base64
- *
- * convert for named code
- *
- * === --jis-input --euc-input --sjis-input --mime-input --base64-input
- *
- * assume input system
- *
- * === --ic=<code>input codeset</code> --oc=<code>output codeset</code>
- *
- * Set the input or output codeset.
- * NKF supports following codesets and those codeset name are case insensitive.
- *
- * [ISO-2022-JP] a.k.a. RFC1468, 7bit JIS, JUNET
- *
- * [EUC-JP (eucJP-nkf)] a.k.a. AT&T JIS, Japanese EUC, UJIS
- *
- * [eucJP-ascii] a.k.a. x-eucjp-open-19970715-ascii
- *
- * [eucJP-ms] a.k.a. x-eucjp-open-19970715-ms
- *
- * [CP51932] Microsoft Version of EUC-JP.
- *
- * [Shift_JIS] SJIS, MS-Kanji
- *
- * [CP932] a.k.a. Windows-31J
- *
- * [UTF-8] same as UTF-8N
- *
- * [UTF-8N] UTF-8 without BOM
- *
- * [UTF-8-BOM] UTF-8 with BOM
- *
- * [UTF-16] same as UTF-16BE
- *
- * [UTF-16BE] UTF-16 Big Endian without BOM
- *
- * [UTF-16BE-BOM] UTF-16 Big Endian with BOM
- *
- * [UTF-16LE] UTF-16 Little Endian without BOM
- *
- * [UTF-16LE-BOM] UTF-16 Little Endian with BOM
- *
- * [UTF8-MAC] NKDed UTF-8, a.k.a. UTF8-NFD (input only)
- *
- * === --fb-{skip, html, xml, perl, java, subchar}
- *
- * Specify the way that nkf handles unassigned characters.
- * Without this option, --fb-skip is assumed.
- *
- * === --prefix= <code>escape character</code> <code>target character</code> ..
- *
- * When nkf converts to Shift_JIS,
- * nkf adds a specified escape character to specified 2nd byte of Shift_JIS characters.
- * 1st byte of argument is the escape character and following bytes are target characters.
- *
- * === --disable-cp932ext
- *
- * Handle the characters extended in CP932 as unassigned characters.
- *
- * === --cap-input
- *
- * Decode hex encoded characters.
- *
- * === --url-input
- *
- * Unescape percent escaped characters.
- *
- * === --
- *
- * Ignore rest of -option.
- */
-
-void
-Init_nkf()
-{
- /* hoge */
- VALUE mKconv = rb_define_module("NKF");
- /* hoge */
-
- rb_define_module_function(mKconv, "nkf", rb_nkf_kconv, 2);
- rb_define_module_function(mKconv, "guess1", rb_nkf_guess1, 1);
- rb_define_module_function(mKconv, "guess2", rb_nkf_guess2, 1);
- rb_define_alias(mKconv, "guess", "guess2");
- rb_define_alias(rb_singleton_class(mKconv), "guess", "guess2");
-
- /* Auto-Detect */
- rb_define_const(mKconv, "AUTO", INT2FIX(_AUTO));
- /* ISO-2022-JP */
- rb_define_const(mKconv, "JIS", INT2FIX(_JIS));
- /* EUC-JP */
- rb_define_const(mKconv, "EUC", INT2FIX(_EUC));
- /* Shift_JIS */
- rb_define_const(mKconv, "SJIS", INT2FIX(_SJIS));
- /* BINARY */
- rb_define_const(mKconv, "BINARY", INT2FIX(_BINARY));
- /* No conversion */
- rb_define_const(mKconv, "NOCONV", INT2FIX(_NOCONV));
- /* ASCII */
- rb_define_const(mKconv, "ASCII", INT2FIX(_ASCII));
- /* UTF-8 */
- rb_define_const(mKconv, "UTF8", INT2FIX(_UTF8));
- /* UTF-16 */
- rb_define_const(mKconv, "UTF16", INT2FIX(_UTF16));
- /* UTF-32 */
- rb_define_const(mKconv, "UTF32", INT2FIX(_UTF32));
- /* UNKNOWN */
- rb_define_const(mKconv, "UNKNOWN", INT2FIX(_UNKNOWN));
- /* Full version string of nkf */
- rb_define_const(mKconv, "VERSION", rb_str_new2(RUBY_NKF_VERSION));
- /* Version of nkf */
- rb_define_const(mKconv, "NKF_VERSION", rb_str_new2(NKF_VERSION));
- /* Release date of nkf */
- rb_define_const(mKconv, "NKF_RELEASE_DATE", rb_str_new2(NKF_RELEASE_DATE));
-}
diff --git a/ext/objspace/depend b/ext/objspace/depend
new file mode 100644
index 0000000000..d9dfc0c42b
--- /dev/null
+++ b/ext/objspace/depend
@@ -0,0 +1,642 @@
+# AUTOGENERATED DEPENDENCIES START
+object_tracing.o: $(RUBY_EXTCONF_H)
+object_tracing.o: $(arch_hdrdir)/ruby/config.h
+object_tracing.o: $(hdrdir)/ruby/assert.h
+object_tracing.o: $(hdrdir)/ruby/atomic.h
+object_tracing.o: $(hdrdir)/ruby/backward.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/assume.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/attributes.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/bool.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/inttypes.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/limits.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/long_long.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/stdalign.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/stdarg.h
+object_tracing.o: $(hdrdir)/ruby/debug.h
+object_tracing.o: $(hdrdir)/ruby/defines.h
+object_tracing.o: $(hdrdir)/ruby/encoding.h
+object_tracing.o: $(hdrdir)/ruby/intern.h
+object_tracing.o: $(hdrdir)/ruby/internal/abi.h
+object_tracing.o: $(hdrdir)/ruby/internal/anyargs.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/assume.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/artificial.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/cold.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/const.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/error.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/format.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/noalias.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/noinline.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/pure.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/restrict.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/warning.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/weakref.h
+object_tracing.o: $(hdrdir)/ruby/internal/cast.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_since.h
+object_tracing.o: $(hdrdir)/ruby/internal/config.h
+object_tracing.o: $(hdrdir)/ruby/internal/constant_p.h
+object_tracing.o: $(hdrdir)/ruby/internal/core.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rarray.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rbasic.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rbignum.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rclass.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rdata.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rfile.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rhash.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/robject.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rregexp.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rstring.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rstruct.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+object_tracing.o: $(hdrdir)/ruby/internal/ctype.h
+object_tracing.o: $(hdrdir)/ruby/internal/dllexport.h
+object_tracing.o: $(hdrdir)/ruby/internal/dosish.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/re.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/string.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+object_tracing.o: $(hdrdir)/ruby/internal/error.h
+object_tracing.o: $(hdrdir)/ruby/internal/eval.h
+object_tracing.o: $(hdrdir)/ruby/internal/event.h
+object_tracing.o: $(hdrdir)/ruby/internal/fl_type.h
+object_tracing.o: $(hdrdir)/ruby/internal/gc.h
+object_tracing.o: $(hdrdir)/ruby/internal/glob.h
+object_tracing.o: $(hdrdir)/ruby/internal/globals.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/attribute.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/builtin.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/extension.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/feature.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/warning.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/array.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/bignum.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/class.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/compar.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/complex.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/cont.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/dir.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/enum.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/error.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/eval.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/file.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/hash.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/io.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/load.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/marshal.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/numeric.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/object.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/parse.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/proc.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/process.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/random.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/range.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/rational.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/re.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/ruby.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/select.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/set.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/signal.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/string.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/struct.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/thread.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/time.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/variable.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/vm.h
+object_tracing.o: $(hdrdir)/ruby/internal/interpreter.h
+object_tracing.o: $(hdrdir)/ruby/internal/iterator.h
+object_tracing.o: $(hdrdir)/ruby/internal/memory.h
+object_tracing.o: $(hdrdir)/ruby/internal/method.h
+object_tracing.o: $(hdrdir)/ruby/internal/module.h
+object_tracing.o: $(hdrdir)/ruby/internal/newobj.h
+object_tracing.o: $(hdrdir)/ruby/internal/scan_args.h
+object_tracing.o: $(hdrdir)/ruby/internal/special_consts.h
+object_tracing.o: $(hdrdir)/ruby/internal/static_assert.h
+object_tracing.o: $(hdrdir)/ruby/internal/stdalign.h
+object_tracing.o: $(hdrdir)/ruby/internal/stdbool.h
+object_tracing.o: $(hdrdir)/ruby/internal/stdckdint.h
+object_tracing.o: $(hdrdir)/ruby/internal/symbol.h
+object_tracing.o: $(hdrdir)/ruby/internal/value.h
+object_tracing.o: $(hdrdir)/ruby/internal/value_type.h
+object_tracing.o: $(hdrdir)/ruby/internal/variable.h
+object_tracing.o: $(hdrdir)/ruby/internal/warning_push.h
+object_tracing.o: $(hdrdir)/ruby/internal/xmalloc.h
+object_tracing.o: $(hdrdir)/ruby/missing.h
+object_tracing.o: $(hdrdir)/ruby/onigmo.h
+object_tracing.o: $(hdrdir)/ruby/oniguruma.h
+object_tracing.o: $(hdrdir)/ruby/ruby.h
+object_tracing.o: $(hdrdir)/ruby/st.h
+object_tracing.o: $(hdrdir)/ruby/subst.h
+object_tracing.o: $(hdrdir)/ruby/thread_native.h
+object_tracing.o: $(top_srcdir)/ccan/check_type/check_type.h
+object_tracing.o: $(top_srcdir)/ccan/container_of/container_of.h
+object_tracing.o: $(top_srcdir)/ccan/list/list.h
+object_tracing.o: $(top_srcdir)/ccan/str/str.h
+object_tracing.o: $(top_srcdir)/id_table.h
+object_tracing.o: $(top_srcdir)/internal.h
+object_tracing.o: $(top_srcdir)/internal/array.h
+object_tracing.o: $(top_srcdir)/internal/basic_operators.h
+object_tracing.o: $(top_srcdir)/internal/box.h
+object_tracing.o: $(top_srcdir)/internal/compilers.h
+object_tracing.o: $(top_srcdir)/internal/gc.h
+object_tracing.o: $(top_srcdir)/internal/imemo.h
+object_tracing.o: $(top_srcdir)/internal/sanitizers.h
+object_tracing.o: $(top_srcdir)/internal/serial.h
+object_tracing.o: $(top_srcdir)/internal/set_table.h
+object_tracing.o: $(top_srcdir)/internal/static_assert.h
+object_tracing.o: $(top_srcdir)/internal/vm.h
+object_tracing.o: $(top_srcdir)/internal/warnings.h
+object_tracing.o: $(top_srcdir)/method.h
+object_tracing.o: $(top_srcdir)/node.h
+object_tracing.o: $(top_srcdir)/ruby_assert.h
+object_tracing.o: $(top_srcdir)/ruby_atomic.h
+object_tracing.o: $(top_srcdir)/rubyparser.h
+object_tracing.o: $(top_srcdir)/thread_pthread.h
+object_tracing.o: $(top_srcdir)/vm_core.h
+object_tracing.o: $(top_srcdir)/vm_opts.h
+object_tracing.o: object_tracing.c
+object_tracing.o: objspace.h
+object_tracing.o: {$(VPATH)}id.h
+objspace.o: $(RUBY_EXTCONF_H)
+objspace.o: $(arch_hdrdir)/ruby/config.h
+objspace.o: $(hdrdir)/ruby/assert.h
+objspace.o: $(hdrdir)/ruby/atomic.h
+objspace.o: $(hdrdir)/ruby/backward.h
+objspace.o: $(hdrdir)/ruby/backward/2/assume.h
+objspace.o: $(hdrdir)/ruby/backward/2/attributes.h
+objspace.o: $(hdrdir)/ruby/backward/2/bool.h
+objspace.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+objspace.o: $(hdrdir)/ruby/backward/2/inttypes.h
+objspace.o: $(hdrdir)/ruby/backward/2/limits.h
+objspace.o: $(hdrdir)/ruby/backward/2/long_long.h
+objspace.o: $(hdrdir)/ruby/backward/2/stdalign.h
+objspace.o: $(hdrdir)/ruby/backward/2/stdarg.h
+objspace.o: $(hdrdir)/ruby/defines.h
+objspace.o: $(hdrdir)/ruby/encoding.h
+objspace.o: $(hdrdir)/ruby/intern.h
+objspace.o: $(hdrdir)/ruby/internal/abi.h
+objspace.o: $(hdrdir)/ruby/internal/anyargs.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+objspace.o: $(hdrdir)/ruby/internal/assume.h
+objspace.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+objspace.o: $(hdrdir)/ruby/internal/attr/artificial.h
+objspace.o: $(hdrdir)/ruby/internal/attr/cold.h
+objspace.o: $(hdrdir)/ruby/internal/attr/const.h
+objspace.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+objspace.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+objspace.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+objspace.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+objspace.o: $(hdrdir)/ruby/internal/attr/error.h
+objspace.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+objspace.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+objspace.o: $(hdrdir)/ruby/internal/attr/format.h
+objspace.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+objspace.o: $(hdrdir)/ruby/internal/attr/noalias.h
+objspace.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+objspace.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+objspace.o: $(hdrdir)/ruby/internal/attr/noinline.h
+objspace.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+objspace.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+objspace.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+objspace.o: $(hdrdir)/ruby/internal/attr/pure.h
+objspace.o: $(hdrdir)/ruby/internal/attr/restrict.h
+objspace.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+objspace.o: $(hdrdir)/ruby/internal/attr/warning.h
+objspace.o: $(hdrdir)/ruby/internal/attr/weakref.h
+objspace.o: $(hdrdir)/ruby/internal/cast.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_since.h
+objspace.o: $(hdrdir)/ruby/internal/config.h
+objspace.o: $(hdrdir)/ruby/internal/constant_p.h
+objspace.o: $(hdrdir)/ruby/internal/core.h
+objspace.o: $(hdrdir)/ruby/internal/core/rarray.h
+objspace.o: $(hdrdir)/ruby/internal/core/rbasic.h
+objspace.o: $(hdrdir)/ruby/internal/core/rbignum.h
+objspace.o: $(hdrdir)/ruby/internal/core/rclass.h
+objspace.o: $(hdrdir)/ruby/internal/core/rdata.h
+objspace.o: $(hdrdir)/ruby/internal/core/rfile.h
+objspace.o: $(hdrdir)/ruby/internal/core/rhash.h
+objspace.o: $(hdrdir)/ruby/internal/core/rmatch.h
+objspace.o: $(hdrdir)/ruby/internal/core/robject.h
+objspace.o: $(hdrdir)/ruby/internal/core/rregexp.h
+objspace.o: $(hdrdir)/ruby/internal/core/rstring.h
+objspace.o: $(hdrdir)/ruby/internal/core/rstruct.h
+objspace.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+objspace.o: $(hdrdir)/ruby/internal/ctype.h
+objspace.o: $(hdrdir)/ruby/internal/dllexport.h
+objspace.o: $(hdrdir)/ruby/internal/dosish.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/re.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/string.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+objspace.o: $(hdrdir)/ruby/internal/error.h
+objspace.o: $(hdrdir)/ruby/internal/eval.h
+objspace.o: $(hdrdir)/ruby/internal/event.h
+objspace.o: $(hdrdir)/ruby/internal/fl_type.h
+objspace.o: $(hdrdir)/ruby/internal/gc.h
+objspace.o: $(hdrdir)/ruby/internal/glob.h
+objspace.o: $(hdrdir)/ruby/internal/globals.h
+objspace.o: $(hdrdir)/ruby/internal/has/attribute.h
+objspace.o: $(hdrdir)/ruby/internal/has/builtin.h
+objspace.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+objspace.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+objspace.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+objspace.o: $(hdrdir)/ruby/internal/has/extension.h
+objspace.o: $(hdrdir)/ruby/internal/has/feature.h
+objspace.o: $(hdrdir)/ruby/internal/has/warning.h
+objspace.o: $(hdrdir)/ruby/internal/intern/array.h
+objspace.o: $(hdrdir)/ruby/internal/intern/bignum.h
+objspace.o: $(hdrdir)/ruby/internal/intern/class.h
+objspace.o: $(hdrdir)/ruby/internal/intern/compar.h
+objspace.o: $(hdrdir)/ruby/internal/intern/complex.h
+objspace.o: $(hdrdir)/ruby/internal/intern/cont.h
+objspace.o: $(hdrdir)/ruby/internal/intern/dir.h
+objspace.o: $(hdrdir)/ruby/internal/intern/enum.h
+objspace.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+objspace.o: $(hdrdir)/ruby/internal/intern/error.h
+objspace.o: $(hdrdir)/ruby/internal/intern/eval.h
+objspace.o: $(hdrdir)/ruby/internal/intern/file.h
+objspace.o: $(hdrdir)/ruby/internal/intern/hash.h
+objspace.o: $(hdrdir)/ruby/internal/intern/io.h
+objspace.o: $(hdrdir)/ruby/internal/intern/load.h
+objspace.o: $(hdrdir)/ruby/internal/intern/marshal.h
+objspace.o: $(hdrdir)/ruby/internal/intern/numeric.h
+objspace.o: $(hdrdir)/ruby/internal/intern/object.h
+objspace.o: $(hdrdir)/ruby/internal/intern/parse.h
+objspace.o: $(hdrdir)/ruby/internal/intern/proc.h
+objspace.o: $(hdrdir)/ruby/internal/intern/process.h
+objspace.o: $(hdrdir)/ruby/internal/intern/random.h
+objspace.o: $(hdrdir)/ruby/internal/intern/range.h
+objspace.o: $(hdrdir)/ruby/internal/intern/rational.h
+objspace.o: $(hdrdir)/ruby/internal/intern/re.h
+objspace.o: $(hdrdir)/ruby/internal/intern/ruby.h
+objspace.o: $(hdrdir)/ruby/internal/intern/select.h
+objspace.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+objspace.o: $(hdrdir)/ruby/internal/intern/set.h
+objspace.o: $(hdrdir)/ruby/internal/intern/signal.h
+objspace.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+objspace.o: $(hdrdir)/ruby/internal/intern/string.h
+objspace.o: $(hdrdir)/ruby/internal/intern/struct.h
+objspace.o: $(hdrdir)/ruby/internal/intern/thread.h
+objspace.o: $(hdrdir)/ruby/internal/intern/time.h
+objspace.o: $(hdrdir)/ruby/internal/intern/variable.h
+objspace.o: $(hdrdir)/ruby/internal/intern/vm.h
+objspace.o: $(hdrdir)/ruby/internal/interpreter.h
+objspace.o: $(hdrdir)/ruby/internal/iterator.h
+objspace.o: $(hdrdir)/ruby/internal/memory.h
+objspace.o: $(hdrdir)/ruby/internal/method.h
+objspace.o: $(hdrdir)/ruby/internal/module.h
+objspace.o: $(hdrdir)/ruby/internal/newobj.h
+objspace.o: $(hdrdir)/ruby/internal/scan_args.h
+objspace.o: $(hdrdir)/ruby/internal/special_consts.h
+objspace.o: $(hdrdir)/ruby/internal/static_assert.h
+objspace.o: $(hdrdir)/ruby/internal/stdalign.h
+objspace.o: $(hdrdir)/ruby/internal/stdbool.h
+objspace.o: $(hdrdir)/ruby/internal/stdckdint.h
+objspace.o: $(hdrdir)/ruby/internal/symbol.h
+objspace.o: $(hdrdir)/ruby/internal/value.h
+objspace.o: $(hdrdir)/ruby/internal/value_type.h
+objspace.o: $(hdrdir)/ruby/internal/variable.h
+objspace.o: $(hdrdir)/ruby/internal/warning_push.h
+objspace.o: $(hdrdir)/ruby/internal/xmalloc.h
+objspace.o: $(hdrdir)/ruby/io.h
+objspace.o: $(hdrdir)/ruby/missing.h
+objspace.o: $(hdrdir)/ruby/onigmo.h
+objspace.o: $(hdrdir)/ruby/oniguruma.h
+objspace.o: $(hdrdir)/ruby/re.h
+objspace.o: $(hdrdir)/ruby/regex.h
+objspace.o: $(hdrdir)/ruby/ruby.h
+objspace.o: $(hdrdir)/ruby/st.h
+objspace.o: $(hdrdir)/ruby/subst.h
+objspace.o: $(hdrdir)/ruby/thread_native.h
+objspace.o: $(top_srcdir)/ccan/check_type/check_type.h
+objspace.o: $(top_srcdir)/ccan/container_of/container_of.h
+objspace.o: $(top_srcdir)/ccan/list/list.h
+objspace.o: $(top_srcdir)/ccan/str/str.h
+objspace.o: $(top_srcdir)/constant.h
+objspace.o: $(top_srcdir)/debug_counter.h
+objspace.o: $(top_srcdir)/id_table.h
+objspace.o: $(top_srcdir)/internal.h
+objspace.o: $(top_srcdir)/internal/array.h
+objspace.o: $(top_srcdir)/internal/basic_operators.h
+objspace.o: $(top_srcdir)/internal/box.h
+objspace.o: $(top_srcdir)/internal/class.h
+objspace.o: $(top_srcdir)/internal/compilers.h
+objspace.o: $(top_srcdir)/internal/gc.h
+objspace.o: $(top_srcdir)/internal/hash.h
+objspace.o: $(top_srcdir)/internal/imemo.h
+objspace.o: $(top_srcdir)/internal/sanitizers.h
+objspace.o: $(top_srcdir)/internal/serial.h
+objspace.o: $(top_srcdir)/internal/set_table.h
+objspace.o: $(top_srcdir)/internal/static_assert.h
+objspace.o: $(top_srcdir)/internal/struct.h
+objspace.o: $(top_srcdir)/internal/variable.h
+objspace.o: $(top_srcdir)/internal/vm.h
+objspace.o: $(top_srcdir)/internal/warnings.h
+objspace.o: $(top_srcdir)/method.h
+objspace.o: $(top_srcdir)/node.h
+objspace.o: $(top_srcdir)/ruby_assert.h
+objspace.o: $(top_srcdir)/ruby_atomic.h
+objspace.o: $(top_srcdir)/rubyparser.h
+objspace.o: $(top_srcdir)/shape.h
+objspace.o: $(top_srcdir)/symbol.h
+objspace.o: $(top_srcdir)/thread_pthread.h
+objspace.o: $(top_srcdir)/vm_core.h
+objspace.o: $(top_srcdir)/vm_debug.h
+objspace.o: $(top_srcdir)/vm_opts.h
+objspace.o: $(top_srcdir)/vm_sync.h
+objspace.o: objspace.c
+objspace.o: {$(VPATH)}id.h
+objspace_dump.o: $(RUBY_EXTCONF_H)
+objspace_dump.o: $(arch_hdrdir)/ruby/config.h
+objspace_dump.o: $(hdrdir)/ruby/assert.h
+objspace_dump.o: $(hdrdir)/ruby/atomic.h
+objspace_dump.o: $(hdrdir)/ruby/backward.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/assume.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/attributes.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/bool.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/inttypes.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/limits.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/long_long.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/stdalign.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/stdarg.h
+objspace_dump.o: $(hdrdir)/ruby/debug.h
+objspace_dump.o: $(hdrdir)/ruby/defines.h
+objspace_dump.o: $(hdrdir)/ruby/encoding.h
+objspace_dump.o: $(hdrdir)/ruby/intern.h
+objspace_dump.o: $(hdrdir)/ruby/internal/abi.h
+objspace_dump.o: $(hdrdir)/ruby/internal/anyargs.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/assume.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/artificial.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/cold.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/const.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/error.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/format.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/noalias.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/noinline.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/pure.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/restrict.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/warning.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/weakref.h
+objspace_dump.o: $(hdrdir)/ruby/internal/cast.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_since.h
+objspace_dump.o: $(hdrdir)/ruby/internal/config.h
+objspace_dump.o: $(hdrdir)/ruby/internal/constant_p.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rarray.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rbasic.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rbignum.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rclass.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rdata.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rfile.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rhash.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/robject.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rregexp.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rstring.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rstruct.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+objspace_dump.o: $(hdrdir)/ruby/internal/ctype.h
+objspace_dump.o: $(hdrdir)/ruby/internal/dllexport.h
+objspace_dump.o: $(hdrdir)/ruby/internal/dosish.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/re.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/string.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+objspace_dump.o: $(hdrdir)/ruby/internal/error.h
+objspace_dump.o: $(hdrdir)/ruby/internal/eval.h
+objspace_dump.o: $(hdrdir)/ruby/internal/event.h
+objspace_dump.o: $(hdrdir)/ruby/internal/fl_type.h
+objspace_dump.o: $(hdrdir)/ruby/internal/gc.h
+objspace_dump.o: $(hdrdir)/ruby/internal/glob.h
+objspace_dump.o: $(hdrdir)/ruby/internal/globals.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/attribute.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/builtin.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/extension.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/feature.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/warning.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/array.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/bignum.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/class.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/compar.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/complex.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/cont.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/dir.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/enum.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/error.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/eval.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/file.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/hash.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/io.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/load.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/marshal.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/numeric.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/object.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/parse.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/proc.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/process.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/random.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/range.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/rational.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/re.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/ruby.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/select.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/set.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/signal.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/string.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/struct.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/thread.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/time.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/variable.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/vm.h
+objspace_dump.o: $(hdrdir)/ruby/internal/interpreter.h
+objspace_dump.o: $(hdrdir)/ruby/internal/iterator.h
+objspace_dump.o: $(hdrdir)/ruby/internal/memory.h
+objspace_dump.o: $(hdrdir)/ruby/internal/method.h
+objspace_dump.o: $(hdrdir)/ruby/internal/module.h
+objspace_dump.o: $(hdrdir)/ruby/internal/newobj.h
+objspace_dump.o: $(hdrdir)/ruby/internal/scan_args.h
+objspace_dump.o: $(hdrdir)/ruby/internal/special_consts.h
+objspace_dump.o: $(hdrdir)/ruby/internal/static_assert.h
+objspace_dump.o: $(hdrdir)/ruby/internal/stdalign.h
+objspace_dump.o: $(hdrdir)/ruby/internal/stdbool.h
+objspace_dump.o: $(hdrdir)/ruby/internal/stdckdint.h
+objspace_dump.o: $(hdrdir)/ruby/internal/symbol.h
+objspace_dump.o: $(hdrdir)/ruby/internal/value.h
+objspace_dump.o: $(hdrdir)/ruby/internal/value_type.h
+objspace_dump.o: $(hdrdir)/ruby/internal/variable.h
+objspace_dump.o: $(hdrdir)/ruby/internal/warning_push.h
+objspace_dump.o: $(hdrdir)/ruby/internal/xmalloc.h
+objspace_dump.o: $(hdrdir)/ruby/io.h
+objspace_dump.o: $(hdrdir)/ruby/missing.h
+objspace_dump.o: $(hdrdir)/ruby/onigmo.h
+objspace_dump.o: $(hdrdir)/ruby/oniguruma.h
+objspace_dump.o: $(hdrdir)/ruby/ruby.h
+objspace_dump.o: $(hdrdir)/ruby/st.h
+objspace_dump.o: $(hdrdir)/ruby/subst.h
+objspace_dump.o: $(hdrdir)/ruby/thread_native.h
+objspace_dump.o: $(hdrdir)/ruby/util.h
+objspace_dump.o: $(top_srcdir)/ccan/check_type/check_type.h
+objspace_dump.o: $(top_srcdir)/ccan/container_of/container_of.h
+objspace_dump.o: $(top_srcdir)/ccan/list/list.h
+objspace_dump.o: $(top_srcdir)/ccan/str/str.h
+objspace_dump.o: $(top_srcdir)/constant.h
+objspace_dump.o: $(top_srcdir)/debug_counter.h
+objspace_dump.o: $(top_srcdir)/encindex.h
+objspace_dump.o: $(top_srcdir)/id_table.h
+objspace_dump.o: $(top_srcdir)/internal.h
+objspace_dump.o: $(top_srcdir)/internal/array.h
+objspace_dump.o: $(top_srcdir)/internal/basic_operators.h
+objspace_dump.o: $(top_srcdir)/internal/box.h
+objspace_dump.o: $(top_srcdir)/internal/class.h
+objspace_dump.o: $(top_srcdir)/internal/compilers.h
+objspace_dump.o: $(top_srcdir)/internal/gc.h
+objspace_dump.o: $(top_srcdir)/internal/hash.h
+objspace_dump.o: $(top_srcdir)/internal/imemo.h
+objspace_dump.o: $(top_srcdir)/internal/io.h
+objspace_dump.o: $(top_srcdir)/internal/sanitizers.h
+objspace_dump.o: $(top_srcdir)/internal/serial.h
+objspace_dump.o: $(top_srcdir)/internal/set_table.h
+objspace_dump.o: $(top_srcdir)/internal/static_assert.h
+objspace_dump.o: $(top_srcdir)/internal/string.h
+objspace_dump.o: $(top_srcdir)/internal/struct.h
+objspace_dump.o: $(top_srcdir)/internal/variable.h
+objspace_dump.o: $(top_srcdir)/internal/vm.h
+objspace_dump.o: $(top_srcdir)/internal/warnings.h
+objspace_dump.o: $(top_srcdir)/method.h
+objspace_dump.o: $(top_srcdir)/node.h
+objspace_dump.o: $(top_srcdir)/ruby_assert.h
+objspace_dump.o: $(top_srcdir)/ruby_atomic.h
+objspace_dump.o: $(top_srcdir)/rubyparser.h
+objspace_dump.o: $(top_srcdir)/shape.h
+objspace_dump.o: $(top_srcdir)/symbol.h
+objspace_dump.o: $(top_srcdir)/thread_pthread.h
+objspace_dump.o: $(top_srcdir)/vm_callinfo.h
+objspace_dump.o: $(top_srcdir)/vm_core.h
+objspace_dump.o: $(top_srcdir)/vm_debug.h
+objspace_dump.o: $(top_srcdir)/vm_opts.h
+objspace_dump.o: $(top_srcdir)/vm_sync.h
+objspace_dump.o: objspace.h
+objspace_dump.o: objspace_dump.c
+objspace_dump.o: {$(VPATH)}id.h
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/objspace/extconf.rb b/ext/objspace/extconf.rb
new file mode 100644
index 0000000000..d0c2dbd02b
--- /dev/null
+++ b/ext/objspace/extconf.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+$INCFLAGS << " -I$(topdir) -I$(top_srcdir)"
+$VPATH << '$(topdir)' << '$(top_srcdir)' # for id.h.
+create_makefile('objspace')
diff --git a/ext/objspace/lib/objspace.rb b/ext/objspace/lib/objspace.rb
new file mode 100644
index 0000000000..47873f5112
--- /dev/null
+++ b/ext/objspace/lib/objspace.rb
@@ -0,0 +1,135 @@
+# frozen_string_literal: true
+
+require 'objspace.so'
+
+module ObjectSpace
+ class << self
+ private :_dump
+ private :_dump_all
+ private :_dump_shapes
+ end
+
+ module_function
+
+ # Dump the contents of a ruby object as JSON.
+ #
+ # _output_ can be one of: +:stdout+, +:file+, +:string+, or IO object.
+ #
+ # * +:file+ means dumping to a tempfile and returning corresponding File object;
+ # * +:stdout+ means printing the dump and returning +nil+;
+ # * +:string+ means returning a string with the dump;
+ # * if an instance of IO object is provided, the output goes there, and the object
+ # is returned.
+ #
+ # This method is only expected to work with C Ruby.
+ # This is an experimental method and is subject to change.
+ # In particular, the function signature and output format are
+ # not guaranteed to be compatible in future versions of ruby.
+ def dump(obj, output: :string)
+ out = case output
+ when :file, nil
+ require 'tempfile'
+ Tempfile.create(%w(rubyobj .json))
+ when :stdout
+ STDOUT
+ when :string
+ +''
+ when IO
+ output
+ else
+ raise ArgumentError, "wrong output option: #{output.inspect}"
+ end
+
+ ret = _dump(obj, out)
+ return nil if output == :stdout
+ ret
+ end
+
+
+ # Dump the contents of the ruby heap as JSON.
+ #
+ # _output_ argument is the same as for #dump.
+ #
+ # _full_ must be a boolean. If true, all heap slots are dumped including the empty ones (+T_NONE+).
+ #
+ # _since_ must be a non-negative integer or +nil+.
+ #
+ # If _since_ is a positive integer, only objects of that generation and
+ # newer generations are dumped. The current generation can be accessed using
+ # GC::count. Objects that were allocated without object allocation tracing enabled
+ # are ignored. See ::trace_object_allocations for more information and
+ # examples.
+ #
+ # If _since_ is omitted or is +nil+, all objects are dumped.
+ #
+ # _shapes_ must be a boolean or a non-negative integer.
+ #
+ # If _shapes_ is a positive integer, only shapes newer than the provided
+ # shape id are dumped. The current shape_id can be accessed using <tt>RubyVM.stat(:next_shape_id)</tt>.
+ #
+ # If _shapes_ is +false+, no shapes are dumped.
+ #
+ # To only dump objects allocated past a certain point you can combine _since_ and _shapes_:
+ # ObjectSpace.trace_object_allocations
+ # GC.start
+ # gc_generation = GC.count
+ # shape_generation = RubyVM.stat(:next_shape_id)
+ # call_method_to_instrument
+ # ObjectSpace.dump_all(since: gc_generation, shapes: shape_generation)
+ #
+ # This method is only expected to work with C Ruby.
+ # This is an experimental method and is subject to change.
+ # In particular, the function signature and output format are
+ # not guaranteed to be compatible in future versions of ruby.
+ def dump_all(output: :file, full: false, since: nil, shapes: true)
+ out = case output
+ when :file, nil
+ require 'tempfile'
+ Tempfile.create(%w(rubyheap .json))
+ when :stdout
+ STDOUT
+ when :string
+ +''
+ when IO
+ output
+ else
+ raise ArgumentError, "wrong output option: #{output.inspect}"
+ end
+
+ shapes = 0 if shapes == true
+ ret = _dump_all(out, full, since, shapes)
+ return nil if output == :stdout
+ ret
+ end
+
+ # Dump the contents of the ruby shape tree as JSON.
+ #
+ # _output_ argument is the same as for #dump.
+ #
+ # If _since_ is a positive integer, only shapes newer than the provided
+ # shape id are dumped. The current shape_id can be accessed using <tt>RubyVM.stat(:next_shape_id)</tt>.
+ #
+ # This method is only expected to work with C Ruby.
+ # This is an experimental method and is subject to change.
+ # In particular, the function signature and output format are
+ # not guaranteed to be compatible in future versions of ruby.
+ def dump_shapes(output: :file, since: 0)
+ out = case output
+ when :file, nil
+ require 'tempfile'
+ Tempfile.create(%w(rubyshapes .json))
+ when :stdout
+ STDOUT
+ when :string
+ +''
+ when IO
+ output
+ else
+ raise ArgumentError, "wrong output option: #{output.inspect}"
+ end
+
+ ret = _dump_shapes(out, since)
+ return nil if output == :stdout
+ ret
+ end
+end
diff --git a/ext/objspace/lib/objspace/trace.rb b/ext/objspace/lib/objspace/trace.rb
new file mode 100644
index 0000000000..c23f5a9d52
--- /dev/null
+++ b/ext/objspace/lib/objspace/trace.rb
@@ -0,0 +1,45 @@
+# This is a simple tool to enable the object allocation tracer.
+# When you have an object of unknown provenance, you can use this
+# to investigate where the object in question is created.
+#
+# = Important notice
+#
+# This is only for debugging purpose. Do not use this in production.
+# Require'ing this file immediately starts tracing the object allocation,
+# which brings a large performance overhead.
+#
+# = Usage
+#
+# 1. Add `require "objspace/trace"` into your code (or add `-robjspace/trace` into the command line)
+# 2. `p obj` will show the allocation site of `obj`
+#
+# Note: This redefines `Kernel#p` method, but not `Object#inspect`.
+#
+# = Examples
+#
+# 1: require "objspace/trace"
+# 2:
+# 3: obj = "str"
+# 4:
+# 5: p obj #=> "str" @ test.rb:3
+
+require 'objspace.so'
+
+module Kernel
+ remove_method :p
+ define_method(:p) do |*objs|
+ objs.each do |obj|
+ file = ObjectSpace.allocation_sourcefile(obj)
+ line = ObjectSpace.allocation_sourceline(obj)
+ if file
+ puts "#{ obj.inspect } @ #{ file }:#{ line }"
+ else
+ puts obj.inspect
+ end
+ end
+ end
+end
+
+ObjectSpace.trace_object_allocations_start
+
+warn "objspace/trace is enabled"
diff --git a/ext/objspace/object_tracing.c b/ext/objspace/object_tracing.c
new file mode 100644
index 0000000000..1c18bf02ee
--- /dev/null
+++ b/ext/objspace/object_tracing.c
@@ -0,0 +1,607 @@
+/**********************************************************************
+
+ object_tracing.c - Object Tracing mechanism/ObjectSpace extender for MRI.
+
+ $Author$
+ created at: Mon May 27 16:27:44 2013
+
+ NOTE: This extension library is not expected to exist except C Ruby.
+ NOTE: This feature is an example usage of internal event tracing APIs.
+
+ All the files in this distribution are covered under the Ruby's
+ license (see the file COPYING).
+
+**********************************************************************/
+
+#include "internal.h"
+#include "internal/gc.h"
+#include "ruby/debug.h"
+#include "objspace.h"
+
+struct traceobj_arg {
+ int running;
+ int keep_remains;
+ VALUE newobj_trace;
+ VALUE freeobj_trace;
+ st_table *object_table; /* obj (VALUE) -> allocation_info */
+ st_table *str_table; /* cstr -> refcount */
+ struct traceobj_arg *prev_traceobj_arg;
+};
+
+static const char *
+make_unique_str(st_table *tbl, const char *str, long len)
+{
+ if (!str) {
+ return NULL;
+ }
+ else {
+ st_data_t n;
+ char *result;
+
+ if (st_lookup(tbl, (st_data_t)str, &n)) {
+ st_insert(tbl, (st_data_t)str, n+1);
+ st_get_key(tbl, (st_data_t)str, &n);
+ result = (char *)n;
+ }
+ else {
+ result = (char *)ruby_xmalloc(len+1);
+ strncpy(result, str, len);
+ result[len] = 0;
+ st_add_direct(tbl, (st_data_t)result, 1);
+ }
+ return result;
+ }
+}
+
+static int
+delete_unique_str_dec(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
+{
+ assert(existing);
+ *value = arg;
+ return ST_CONTINUE;
+}
+
+static void
+delete_unique_str(st_table *tbl, const char *str)
+{
+ if (str) {
+ st_data_t n;
+
+ st_lookup(tbl, (st_data_t)str, &n);
+ if (n == 1) {
+ n = (st_data_t)str;
+ st_delete(tbl, &n, 0);
+ ruby_xfree((char *)n);
+ }
+ else {
+ st_update(tbl, (st_data_t)str, delete_unique_str_dec, (st_data_t)(n-1));
+ }
+ }
+}
+
+static void
+newobj_i(VALUE tpval, void *data)
+{
+ struct traceobj_arg *arg = (struct traceobj_arg *)data;
+ rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval);
+ VALUE obj = rb_tracearg_object(tparg);
+ VALUE path = rb_tracearg_path(tparg);
+ VALUE line = rb_tracearg_lineno(tparg);
+ VALUE mid = rb_tracearg_method_id(tparg);
+ VALUE klass = rb_tracearg_defined_class(tparg);
+ struct allocation_info *info;
+ const char *path_cstr = RTEST(path) ? make_unique_str(arg->str_table, RSTRING_PTR(path), RSTRING_LEN(path)) : 0;
+ VALUE class_path = (RTEST(klass) && !OBJ_FROZEN(klass)) ? rb_mod_name(klass) : Qnil;
+ const char *class_path_cstr = RTEST(class_path) ? make_unique_str(arg->str_table, RSTRING_PTR(class_path), RSTRING_LEN(class_path)) : 0;
+ st_data_t v;
+
+ if (st_lookup(arg->object_table, (st_data_t)obj, &v)) {
+ info = (struct allocation_info *)v;
+ if (arg->keep_remains) {
+ if (info->living) {
+ /* do nothing. there is possibility to keep living if FREEOBJ events while suppressing tracing */
+ }
+ }
+ /* reuse info */
+ delete_unique_str(arg->str_table, info->path);
+ delete_unique_str(arg->str_table, info->class_path);
+ }
+ else {
+ info = (struct allocation_info *)ruby_xmalloc(sizeof(struct allocation_info));
+ }
+ info->living = 1;
+ info->flags = RBASIC(obj)->flags;
+ info->klass = RBASIC_CLASS(obj);
+
+ info->path = path_cstr;
+ info->line = NUM2INT(line);
+ info->mid = mid;
+ info->class_path = class_path_cstr;
+ info->generation = rb_gc_count();
+ st_insert(arg->object_table, (st_data_t)obj, (st_data_t)info);
+}
+
+static void
+freeobj_i(VALUE tpval, void *data)
+{
+ struct traceobj_arg *arg = (struct traceobj_arg *)data;
+ rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval);
+ st_data_t obj = (st_data_t)rb_tracearg_object(tparg);
+ st_data_t v;
+ struct allocation_info *info;
+
+ /* Modifying the st table can cause allocations, which can trigger GC.
+ * Since freeobj_i is called during GC, it must not trigger another GC. */
+ VALUE gc_disabled = rb_gc_disable_no_rest();
+
+ if (arg->keep_remains) {
+ if (st_lookup(arg->object_table, obj, &v)) {
+ info = (struct allocation_info *)v;
+ info->living = 0;
+ }
+ }
+ else {
+ if (st_delete(arg->object_table, &obj, &v)) {
+ info = (struct allocation_info *)v;
+ delete_unique_str(arg->str_table, info->path);
+ delete_unique_str(arg->str_table, info->class_path);
+ ruby_xfree(info);
+ }
+ }
+
+ if (gc_disabled == Qfalse) rb_gc_enable();
+}
+
+static int
+free_keys_i(st_data_t key, st_data_t value, st_data_t data)
+{
+ ruby_xfree((void *)key);
+ return ST_CONTINUE;
+}
+
+static int
+free_values_i(st_data_t key, st_data_t value, st_data_t data)
+{
+ ruby_xfree((void *)value);
+ return ST_CONTINUE;
+}
+
+static void
+allocation_info_tracer_mark(void *ptr)
+{
+ struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
+ rb_gc_mark(trace_arg->newobj_trace);
+ rb_gc_mark(trace_arg->freeobj_trace);
+}
+
+static void
+allocation_info_tracer_free(void *ptr)
+{
+ struct traceobj_arg *arg = (struct traceobj_arg *)ptr;
+ /* clear tables */
+ st_foreach(arg->object_table, free_values_i, 0);
+ st_free_table(arg->object_table);
+ st_foreach(arg->str_table, free_keys_i, 0);
+ st_free_table(arg->str_table);
+ xfree(arg);
+}
+
+static size_t
+allocation_info_tracer_memsize(const void *ptr)
+{
+ size_t size;
+ struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
+ size = sizeof(*trace_arg);
+ size += st_memsize(trace_arg->object_table);
+ size += st_memsize(trace_arg->str_table);
+ return size;
+}
+
+static int
+allocation_info_tracer_compact_update_object_table_i(st_data_t key, st_data_t value, st_data_t data)
+{
+ st_table *table = (st_table *)data;
+
+ if (!rb_gc_pointer_to_heap_p(key)) {
+ struct allocation_info *info = (struct allocation_info *)value;
+ xfree(info);
+ return ST_DELETE;
+ }
+
+ if (key != rb_gc_location(key)) {
+ DURING_GC_COULD_MALLOC_REGION_START();
+ {
+ st_insert(table, rb_gc_location(key), value);
+ }
+ DURING_GC_COULD_MALLOC_REGION_END();
+
+ return ST_DELETE;
+ }
+
+ return ST_CONTINUE;
+}
+
+static void
+allocation_info_tracer_compact(void *ptr)
+{
+ struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
+
+ if (trace_arg->object_table &&
+ st_foreach(
+ trace_arg->object_table,
+ allocation_info_tracer_compact_update_object_table_i,
+ (st_data_t)trace_arg->object_table)) {
+ rb_raise(rb_eRuntimeError, "hash modified during iteration");
+ }
+}
+
+static const rb_data_type_t allocation_info_tracer_type = {
+ "ObjectTracing/allocation_info_tracer",
+ {
+ allocation_info_tracer_mark,
+ allocation_info_tracer_free, /* Never called because global */
+ allocation_info_tracer_memsize,
+ allocation_info_tracer_compact,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static VALUE traceobj_arg;
+static struct traceobj_arg *tmp_trace_arg; /* TODO: Do not use global variables */
+static int tmp_keep_remains; /* TODO: Do not use global variables */
+
+static struct traceobj_arg *
+get_traceobj_arg(void)
+{
+ if (tmp_trace_arg == 0) {
+ VALUE obj = TypedData_Make_Struct(rb_cObject, struct traceobj_arg, &allocation_info_tracer_type, tmp_trace_arg);
+ traceobj_arg = obj;
+ rb_gc_register_mark_object(traceobj_arg);
+ tmp_trace_arg->running = 0;
+ tmp_trace_arg->keep_remains = tmp_keep_remains;
+ tmp_trace_arg->newobj_trace = 0;
+ tmp_trace_arg->freeobj_trace = 0;
+ tmp_trace_arg->object_table = st_init_numtable();
+ tmp_trace_arg->str_table = st_init_strtable();
+ }
+ return tmp_trace_arg;
+}
+
+/*
+ * call-seq: trace_object_allocations_start
+ *
+ * Starts tracing object allocations.
+ *
+ */
+static VALUE
+trace_object_allocations_start(VALUE self)
+{
+ struct traceobj_arg *arg = get_traceobj_arg();
+
+ if (arg->running++ > 0) {
+ /* do nothing */
+ }
+ else {
+ if (arg->newobj_trace == 0) {
+ arg->newobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, arg);
+ arg->freeobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_FREEOBJ, freeobj_i, arg);
+ }
+ rb_tracepoint_enable(arg->newobj_trace);
+ rb_tracepoint_enable(arg->freeobj_trace);
+ }
+
+ return Qnil;
+}
+
+/*
+ * call-seq: trace_object_allocations_stop
+ *
+ * Stop tracing object allocations.
+ *
+ * Note that if ::trace_object_allocations_start is called n-times, then
+ * tracing will stop after calling ::trace_object_allocations_stop n-times.
+ *
+ */
+static VALUE
+trace_object_allocations_stop(VALUE self)
+{
+ struct traceobj_arg *arg = get_traceobj_arg();
+
+ if (arg->running > 0) {
+ arg->running--;
+ }
+
+ if (arg->running == 0) {
+ if (arg->newobj_trace != 0) {
+ rb_tracepoint_disable(arg->newobj_trace);
+ }
+ if (arg->freeobj_trace != 0) {
+ rb_tracepoint_disable(arg->freeobj_trace);
+ }
+ }
+
+ return Qnil;
+}
+
+/*
+ * call-seq: trace_object_allocations_clear
+ *
+ * Clear recorded tracing information.
+ *
+ */
+static VALUE
+trace_object_allocations_clear(VALUE self)
+{
+ struct traceobj_arg *arg = get_traceobj_arg();
+
+ /* clear tables */
+ st_foreach(arg->object_table, free_values_i, 0);
+ st_clear(arg->object_table);
+ st_foreach(arg->str_table, free_keys_i, 0);
+ st_clear(arg->str_table);
+
+ /* do not touch TracePoints */
+
+ return Qnil;
+}
+
+/*
+ * call-seq: trace_object_allocations { block }
+ *
+ * Starts tracing object allocations from the ObjectSpace extension module.
+ *
+ * For example:
+ *
+ * require 'objspace'
+ *
+ * class C
+ * include ObjectSpace
+ *
+ * def foo
+ * trace_object_allocations do
+ * obj = Object.new
+ * p "#{allocation_sourcefile(obj)}:#{allocation_sourceline(obj)}"
+ * end
+ * end
+ * end
+ *
+ * C.new.foo #=> "objtrace.rb:8"
+ *
+ * This example has included the ObjectSpace module to make it easier to read,
+ * but you can also use the ::trace_object_allocations notation (recommended).
+ *
+ * Note that this feature introduces a huge performance decrease and huge
+ * memory consumption.
+ */
+static VALUE
+trace_object_allocations(VALUE self)
+{
+ trace_object_allocations_start(self);
+ return rb_ensure(rb_yield, Qnil, trace_object_allocations_stop, self);
+}
+
+int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);
+static int object_allocations_reporter_registered = 0;
+
+static int
+object_allocations_reporter_i(st_data_t key, st_data_t val, st_data_t ptr)
+{
+ FILE *out = (FILE *)ptr;
+ VALUE obj = (VALUE)key;
+ struct allocation_info *info = (struct allocation_info *)val;
+
+ fprintf(out, "-- %p (%s F: %p, ", (void *)obj, info->living ? "live" : "dead", (void *)info->flags);
+ if (info->class_path) fprintf(out, "C: %s", info->class_path);
+ else fprintf(out, "C: %p", (void *)info->klass);
+ fprintf(out, "@%s:%lu", info->path ? info->path : "", info->line);
+ if (!NIL_P(info->mid)) {
+ VALUE m = rb_sym2str(info->mid);
+ fprintf(out, " (%s)", RSTRING_PTR(m));
+ }
+ fprintf(out, ")\n");
+
+ return ST_CONTINUE;
+}
+
+static void
+object_allocations_reporter(FILE *out, void *ptr)
+{
+ fprintf(out, "== object_allocations_reporter: START\n");
+ if (tmp_trace_arg) {
+ st_foreach(tmp_trace_arg->object_table, object_allocations_reporter_i, (st_data_t)out);
+ }
+ fprintf(out, "== object_allocations_reporter: END\n");
+}
+
+/*
+ * call-seq: trace_object_allocations_debug_start
+ *
+ * Starts tracing object allocations for GC debugging.
+ * If you encounter the BUG "... is T_NONE" (and so on) on your
+ * application, please try this method at the beginning of your app.
+ */
+static VALUE
+trace_object_allocations_debug_start(VALUE self)
+{
+ tmp_keep_remains = 1;
+ if (object_allocations_reporter_registered == 0) {
+ object_allocations_reporter_registered = 1;
+ rb_bug_reporter_add(object_allocations_reporter, 0);
+ }
+
+ return trace_object_allocations_start(self);
+}
+
+static struct allocation_info *
+lookup_allocation_info(VALUE obj)
+{
+ if (tmp_trace_arg) {
+ st_data_t info;
+ if (st_lookup(tmp_trace_arg->object_table, obj, &info)) {
+ return (struct allocation_info *)info;
+ }
+ }
+ return NULL;
+}
+
+struct allocation_info *
+objspace_lookup_allocation_info(VALUE obj)
+{
+ return lookup_allocation_info(obj);
+}
+
+/*
+ * call-seq: allocation_sourcefile(object) -> string
+ *
+ * Returns the source file origin from the given +object+.
+ *
+ * See ::trace_object_allocations for more information and examples.
+ */
+static VALUE
+allocation_sourcefile(VALUE self, VALUE obj)
+{
+ struct allocation_info *info = lookup_allocation_info(obj);
+
+ if (info && info->path) {
+ return rb_str_new2(info->path);
+ }
+ else {
+ return Qnil;
+ }
+}
+
+/*
+ * call-seq: allocation_sourceline(object) -> integer
+ *
+ * Returns the original line from source for from the given +object+.
+ *
+ * See ::trace_object_allocations for more information and examples.
+ */
+static VALUE
+allocation_sourceline(VALUE self, VALUE obj)
+{
+ struct allocation_info *info = lookup_allocation_info(obj);
+
+ if (info) {
+ return INT2FIX(info->line);
+ }
+ else {
+ return Qnil;
+ }
+}
+
+/*
+ * call-seq: allocation_class_path(object) -> string
+ *
+ * Returns the class for the given +object+.
+ *
+ * class A
+ * def foo
+ * ObjectSpace::trace_object_allocations do
+ * obj = Object.new
+ * p "#{ObjectSpace::allocation_class_path(obj)}"
+ * end
+ * end
+ * end
+ *
+ * A.new.foo #=> "Class"
+ *
+ * See ::trace_object_allocations for more information and examples.
+ */
+static VALUE
+allocation_class_path(VALUE self, VALUE obj)
+{
+ struct allocation_info *info = lookup_allocation_info(obj);
+
+ if (info && info->class_path) {
+ return rb_str_new2(info->class_path);
+ }
+ else {
+ return Qnil;
+ }
+}
+
+/*
+ * call-seq: allocation_method_id(object) -> string
+ *
+ * Returns the method identifier for the given +object+.
+ *
+ * class A
+ * include ObjectSpace
+ *
+ * def foo
+ * trace_object_allocations do
+ * obj = Object.new
+ * p "#{allocation_class_path(obj)}##{allocation_method_id(obj)}"
+ * end
+ * end
+ * end
+ *
+ * A.new.foo #=> "Class#new"
+ *
+ * See ::trace_object_allocations for more information and examples.
+ */
+static VALUE
+allocation_method_id(VALUE self, VALUE obj)
+{
+ struct allocation_info *info = lookup_allocation_info(obj);
+ if (info) {
+ return info->mid;
+ }
+ else {
+ return Qnil;
+ }
+}
+
+/*
+ * call-seq: allocation_generation(object) -> integer or nil
+ *
+ * Returns garbage collector generation for the given +object+.
+ *
+ * class B
+ * include ObjectSpace
+ *
+ * def foo
+ * trace_object_allocations do
+ * obj = Object.new
+ * p "Generation is #{allocation_generation(obj)}"
+ * end
+ * end
+ * end
+ *
+ * B.new.foo #=> "Generation is 3"
+ *
+ * See ::trace_object_allocations for more information and examples.
+ */
+static VALUE
+allocation_generation(VALUE self, VALUE obj)
+{
+ struct allocation_info *info = lookup_allocation_info(obj);
+ if (info) {
+ return SIZET2NUM(info->generation);
+ }
+ else {
+ return Qnil;
+ }
+}
+
+void
+Init_object_tracing(VALUE rb_mObjSpace)
+{
+#if 0
+ rb_mObjSpace = rb_define_module("ObjectSpace"); /* let rdoc know */
+#endif
+
+ rb_define_module_function(rb_mObjSpace, "trace_object_allocations", trace_object_allocations, 0);
+ rb_define_module_function(rb_mObjSpace, "trace_object_allocations_start", trace_object_allocations_start, 0);
+ rb_define_module_function(rb_mObjSpace, "trace_object_allocations_stop", trace_object_allocations_stop, 0);
+ rb_define_module_function(rb_mObjSpace, "trace_object_allocations_clear", trace_object_allocations_clear, 0);
+
+ rb_define_module_function(rb_mObjSpace, "trace_object_allocations_debug_start", trace_object_allocations_debug_start, 0);
+
+ rb_define_module_function(rb_mObjSpace, "allocation_sourcefile", allocation_sourcefile, 1);
+ rb_define_module_function(rb_mObjSpace, "allocation_sourceline", allocation_sourceline, 1);
+ rb_define_module_function(rb_mObjSpace, "allocation_class_path", allocation_class_path, 1);
+ rb_define_module_function(rb_mObjSpace, "allocation_method_id", allocation_method_id, 1);
+ rb_define_module_function(rb_mObjSpace, "allocation_generation", allocation_generation, 1);
+}
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c
new file mode 100644
index 0000000000..20eab820a1
--- /dev/null
+++ b/ext/objspace/objspace.c
@@ -0,0 +1,868 @@
+/**********************************************************************
+
+ objspace.c - ObjectSpace extender for MRI.
+
+ $Author$
+ created at: Wed Jun 17 07:39:17 2009
+
+ NOTE: This extension library is only expected to exist with C Ruby.
+
+ All the files in this distribution are covered under the Ruby's
+ license (see the file COPYING).
+
+**********************************************************************/
+
+#include "internal.h"
+#include "internal/class.h"
+#include "internal/compilers.h"
+#include "internal/gc.h"
+#include "internal/hash.h"
+#include "internal/imemo.h"
+#include "internal/sanitizers.h"
+#include "ruby/io.h"
+#include "ruby/re.h"
+#include "ruby/st.h"
+#include "symbol.h"
+
+#undef rb_funcall
+
+#include "ruby/ruby.h"
+
+/*
+ * call-seq:
+ * ObjectSpace.memsize_of(obj) -> integer
+ *
+ * Returns the amount of memory in bytes consumed by +obj+.
+ *
+ * The returned size includes the slot that +obj+ occupies plus any memory
+ * that +obj+ allocates outside of that slot, such as the storage backing a
+ * large String, Array, or Hash:
+ *
+ * require 'objspace'
+ *
+ * ObjectSpace.memsize_of("small") # => 40
+ * ObjectSpace.memsize_of("a" * 1000) # => 1041
+ * ObjectSpace.memsize_of([1, 2, 3]) # => 40
+ * ObjectSpace.memsize_of(Array.new(100)) # => 840
+ *
+ * Special constants such as +true+, +false+, +nil+, small integers, and some
+ * symbols do not occupy a slot, so their size is reported as +0+:
+ *
+ * ObjectSpace.memsize_of(true) # => 0
+ * ObjectSpace.memsize_of(42) # => 0
+ *
+ * The returned size is only a hint and may be an underestimate, since it does
+ * not account for all of the memory that +obj+ references. In particular, the
+ * size of a +T_DATA+ object (an object implemented in C, such as one defined
+ * by a C extension) may not be reported correctly.
+ *
+ * This method is only expected to work with CRuby.
+ */
+
+static VALUE
+memsize_of_m(VALUE self, VALUE obj)
+{
+ return SIZET2NUM(rb_obj_memsize_of(obj));
+}
+
+struct total_data {
+ size_t total;
+ VALUE klass;
+};
+
+static void
+total_i(VALUE v, void *ptr)
+{
+ struct total_data *data = (struct total_data *)ptr;
+
+ if (!rb_objspace_internal_object_p(v)) {
+ if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
+ data->total += rb_obj_memsize_of(v);
+ }
+ }
+}
+
+typedef void (*each_obj_with_flags)(VALUE, void*);
+
+struct obj_itr {
+ each_obj_with_flags cb;
+ void *data;
+};
+
+static int
+heap_iter(void *vstart, void *vend, size_t stride, void *ptr)
+{
+ struct obj_itr * ctx = (struct obj_itr *)ptr;
+ VALUE v;
+
+ for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
+ void *poisoned = rb_asan_poisoned_object_p(v);
+ rb_asan_unpoison_object(v, false);
+
+ if (RBASIC(v)->flags) {
+ (*ctx->cb)(v, ctx->data);
+ }
+
+ if (poisoned) {
+ rb_asan_poison_object(v);
+ }
+ }
+
+ return 0;
+}
+
+static void
+each_object_with_flags(each_obj_with_flags cb, void *ctx)
+{
+ struct obj_itr data;
+ data.cb = cb;
+ data.data = ctx;
+ rb_objspace_each_objects(heap_iter, &data);
+}
+
+/*
+ * call-seq:
+ * ObjectSpace.memsize_of_all(klass = nil) -> integer
+ *
+ * Returns the total memory size of all living objects in bytes.
+ *
+ * ObjectSpace.memsize_of_all # => 12502001
+ *
+ * If +klass+ is given (which must be a Class or Module), returns the total
+ * memory size of objects whose class is, or is a subclass, of +klass+.
+ *
+ * class MyClass; end
+ * ObjectSpace.memsize_of_all(MyClass) # => 0
+ * o = MyClass.new
+ * ObjectSpace.memsize_of_all(MyClass) # => 40
+ *
+ * Note that the value returned may be an underestimate of the actual amount
+ * of memory used. Therefore, the value returned should only be used as a hint,
+ * rather than a source of truth. In particular, the size of +T_DATA+ objects may
+ * not be correct.
+ *
+ * This method is only expected to work with C Ruby.
+ */
+
+static VALUE
+memsize_of_all_m(int argc, VALUE *argv, VALUE self)
+{
+ struct total_data data = {0, 0};
+
+ if (argc > 0) {
+ rb_scan_args(argc, argv, "01", &data.klass);
+ if (!NIL_P(data.klass)) rb_obj_is_kind_of(Qnil, data.klass);
+ }
+
+ each_object_with_flags(total_i, &data);
+ return SIZET2NUM(data.total);
+}
+
+static int
+set_zero_i(st_data_t key, st_data_t val, st_data_t arg)
+{
+ VALUE k = (VALUE)key;
+ VALUE hash = (VALUE)arg;
+ rb_hash_aset(hash, k, INT2FIX(0));
+ return ST_CONTINUE;
+}
+
+static VALUE
+setup_hash(int argc, VALUE *argv)
+{
+ VALUE hash;
+
+ if (rb_scan_args(argc, argv, "01", &hash) == 1) {
+ if (!RB_TYPE_P(hash, T_HASH))
+ rb_raise(rb_eTypeError, "non-hash given");
+ }
+
+ if (hash == Qnil) {
+ hash = rb_hash_new();
+ }
+ else if (!RHASH_EMPTY_P(hash)) {
+ rb_hash_foreach(hash, set_zero_i, (st_data_t)hash);
+ }
+
+ return hash;
+}
+
+static void
+cos_i(VALUE v, void *data)
+{
+ size_t *counts = (size_t *)data;
+ counts[BUILTIN_TYPE(v)] += rb_obj_memsize_of(v);
+}
+
+static VALUE
+type2sym(enum ruby_value_type i)
+{
+ VALUE type;
+ switch (i) {
+#define CASE_TYPE(t) case t: type = ID2SYM(rb_intern(#t)); break;
+ CASE_TYPE(T_NONE);
+ CASE_TYPE(T_OBJECT);
+ CASE_TYPE(T_CLASS);
+ CASE_TYPE(T_MODULE);
+ CASE_TYPE(T_FLOAT);
+ CASE_TYPE(T_STRING);
+ CASE_TYPE(T_REGEXP);
+ CASE_TYPE(T_ARRAY);
+ CASE_TYPE(T_HASH);
+ CASE_TYPE(T_STRUCT);
+ CASE_TYPE(T_BIGNUM);
+ CASE_TYPE(T_FILE);
+ CASE_TYPE(T_DATA);
+ CASE_TYPE(T_MATCH);
+ CASE_TYPE(T_COMPLEX);
+ CASE_TYPE(T_RATIONAL);
+ CASE_TYPE(T_NIL);
+ CASE_TYPE(T_TRUE);
+ CASE_TYPE(T_FALSE);
+ CASE_TYPE(T_SYMBOL);
+ CASE_TYPE(T_FIXNUM);
+ CASE_TYPE(T_UNDEF);
+ CASE_TYPE(T_IMEMO);
+ CASE_TYPE(T_NODE);
+ CASE_TYPE(T_ICLASS);
+ CASE_TYPE(T_MOVED);
+ CASE_TYPE(T_ZOMBIE);
+#undef CASE_TYPE
+ default: rb_bug("type2sym: unknown type (%d)", i);
+ }
+ return type;
+}
+
+/*
+ * call-seq:
+ * ObjectSpace.count_objects_size(result_hash = {}) -> result_hash
+ *
+ * Counts objects size (in bytes) for each type.
+ *
+ * Note that the returned size may not be accurate, so it should only
+ * be used as a hint. Specifically, the size for +T_DATA+ may be
+ * inaccurate because these are custom objects defined in Ruby and
+ * native extensions and so they may not accurately report their
+ * memory size.
+ *
+ * It returns a hash that looks like:
+ *
+ * {TOTAL: 1461154, T_CLASS: 158280, T_MODULE: 20672, T_STRING: 527249, ...}
+ *
+ * The contents of the returned hash are implementation specific and
+ * may be changed in future versions without notice.
+ *
+ * If the optional argument, +result_hash+, is given,
+ * it is overwritten and returned.
+ * This is intended to avoid the probe effect.
+ *
+ * This method is only expected to work with C Ruby.
+ */
+
+static VALUE
+count_objects_size(int argc, VALUE *argv, VALUE os)
+{
+ size_t counts[T_MASK+1];
+ size_t total = 0;
+ enum ruby_value_type i;
+ VALUE hash = setup_hash(argc, argv);
+
+ for (i = 0; i <= T_MASK; i++) {
+ counts[i] = 0;
+ }
+
+ each_object_with_flags(cos_i, &counts[0]);
+
+ for (i = 0; i <= T_MASK; i++) {
+ if (counts[i]) {
+ VALUE type = type2sym(i);
+ total += counts[i];
+ rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
+ }
+ }
+ rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
+ return hash;
+}
+
+struct dynamic_symbol_counts {
+ size_t mortal;
+ size_t immortal;
+};
+
+static void
+cs_i(VALUE v, void *n)
+{
+ struct dynamic_symbol_counts *counts = (struct dynamic_symbol_counts *)n;
+
+ if (BUILTIN_TYPE(v) == T_SYMBOL) {
+ ID id = RSYMBOL(v)->id;
+ if ((id & ~ID_SCOPE_MASK) == 0) {
+ counts->mortal++;
+ }
+ else {
+ counts->immortal++;
+ }
+ }
+}
+
+size_t rb_sym_immortal_count(void);
+
+/*
+ * call-seq:
+ * ObjectSpace.count_symbols(result_hash = nil) -> hash
+ *
+ * Returns a hash containing the number of objects for each Symbol type.
+ *
+ * The types of Symbols are the following:
+ *
+ * - +mortal_dynamic_symbol+: Symbols that are garbage collectable.
+ * - +immortal_dynamic_symbol+: Symbols that are objects allocated from the
+ * garbage collector, but are not garbage collectable.
+ * - +immortal_static_symbol+: Symbols that are not allocated from the
+ * garbage collector, and are thus not garbage collectable.
+ * - +immortal_symbol+: the sum of +immortal_dynamic_symbol+ and +immortal_static_symbol+.
+ *
+ * If the optional argument +result_hash+ is given, it is overwritten and
+ * returned. This is intended to avoid the probe effect.
+ *
+ * This method is intended for developers interested in performance and memory
+ * usage of Ruby programs. The contents of the returned hash is implementation
+ * specific and may change in the future.
+ *
+ * This method is only expected to work with C Ruby.
+ */
+
+static VALUE
+count_symbols(int argc, VALUE *argv, VALUE os)
+{
+ struct dynamic_symbol_counts dynamic_counts = {0, 0};
+ VALUE hash = setup_hash(argc, argv);
+
+ size_t immortal_symbols = rb_sym_immortal_count();
+ each_object_with_flags(cs_i, &dynamic_counts);
+
+ rb_hash_aset(hash, ID2SYM(rb_intern("mortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.mortal));
+ rb_hash_aset(hash, ID2SYM(rb_intern("immortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.immortal));
+ rb_hash_aset(hash, ID2SYM(rb_intern("immortal_static_symbol")), SIZET2NUM(immortal_symbols - dynamic_counts.immortal));
+ rb_hash_aset(hash, ID2SYM(rb_intern("immortal_symbol")), SIZET2NUM(immortal_symbols));
+
+ return hash;
+}
+
+static void
+cto_i(VALUE v, void *data)
+{
+ VALUE hash = (VALUE)data;
+
+ if (BUILTIN_TYPE(v) == T_DATA) {
+ VALUE counter;
+ VALUE key = RBASIC(v)->klass;
+
+ if (key == 0) {
+ const char *name = rb_objspace_data_type_name(v);
+ if (name == 0) name = "unknown";
+ key = ID2SYM(rb_intern(name));
+ }
+
+ counter = rb_hash_aref(hash, key);
+ if (NIL_P(counter)) {
+ counter = INT2FIX(1);
+ }
+ else {
+ counter = INT2FIX(FIX2INT(counter) + 1);
+ }
+
+ rb_hash_aset(hash, key, counter);
+ }
+}
+
+/*
+ * call-seq:
+ * ObjectSpace.count_tdata_objects(result_hash = nil) -> hash
+ *
+ * Returns a hash containing the number of objects for each +T_DATA+ type.
+ * The keys are Class objects when the +T_DATA+ object has an associated class,
+ * or Symbol objects of the name defined in the +rb_data_type_struct+ for internal
+ * +T_DATA+ objects.
+ *
+ * ObjectSpace.count_tdata_objects
+ * # => {RBS::Location => 39255, marshal_compat_table: 1, Encoding => 103, mutex: 1, ... }
+ *
+ * If the optional argument +result_hash+ is given, it is overwritten and
+ * returned. This is intended to avoid the probe effect.
+ *
+ * This method is intended for developers interested in performance and memory
+ * usage of Ruby programs. The contents of the returned hash is implementation
+ * specific and may change in the future.
+ *
+ * This method is only expected to work with C Ruby.
+ */
+
+static VALUE
+count_tdata_objects(int argc, VALUE *argv, VALUE self)
+{
+ VALUE hash = setup_hash(argc, argv);
+ each_object_with_flags(cto_i, (void *)hash);
+ return hash;
+}
+
+static ID imemo_type_ids[IMEMO_MASK+1];
+
+static void
+count_imemo_objects_i(VALUE v, void *data)
+{
+ VALUE hash = (VALUE)data;
+
+ if (BUILTIN_TYPE(v) == T_IMEMO) {
+ VALUE counter;
+ VALUE key = ID2SYM(imemo_type_ids[imemo_type(v)]);
+
+ counter = rb_hash_aref(hash, key);
+
+ if (NIL_P(counter)) {
+ counter = INT2FIX(1);
+ }
+ else {
+ counter = INT2FIX(FIX2INT(counter) + 1);
+ }
+
+ rb_hash_aset(hash, key, counter);
+ }
+}
+
+/*
+ * call-seq:
+ * ObjectSpace.count_imemo_objects(result_hash = nil) -> hash
+ *
+ * Returns a hash containing the number of objects for each +T_IMEMO+ type.
+ * The keys are Symbol objects of the +T_IMEMO+ type name.
+ * +T_IMEMO+ objects are Ruby internal objects that are not visible to Ruby
+ * programs.
+ *
+ * ObjectSpace.count_imemo_objects
+ * # => {imemo_callcache: 5482, imemo_constcache: 1258, imemo_ment: 13906, ... }
+ *
+ * If the optional argument +result_hash+ is given, it is overwritten and
+ * returned. This is intended to avoid the probe effect.
+ *
+ * This method is intended for developers interested in performance and memory
+ * usage of Ruby programs. The contents of the returned hash is implementation
+ * specific and may change in the future.
+ *
+ * This method is only expected to work with C Ruby.
+ */
+
+static VALUE
+count_imemo_objects(int argc, VALUE *argv, VALUE self)
+{
+ VALUE hash = setup_hash(argc, argv);
+
+ if (imemo_type_ids[0] == 0) {
+#define INIT_IMEMO_TYPE_ID(n) (imemo_type_ids[n] = rb_intern_const(#n))
+ INIT_IMEMO_TYPE_ID(imemo_env);
+ INIT_IMEMO_TYPE_ID(imemo_cref);
+ INIT_IMEMO_TYPE_ID(imemo_svar);
+ INIT_IMEMO_TYPE_ID(imemo_throw_data);
+ INIT_IMEMO_TYPE_ID(imemo_ifunc);
+ INIT_IMEMO_TYPE_ID(imemo_memo);
+ INIT_IMEMO_TYPE_ID(imemo_ment);
+ INIT_IMEMO_TYPE_ID(imemo_iseq);
+ INIT_IMEMO_TYPE_ID(imemo_tmpbuf);
+ INIT_IMEMO_TYPE_ID(imemo_cvar_entry);
+ INIT_IMEMO_TYPE_ID(imemo_callinfo);
+ INIT_IMEMO_TYPE_ID(imemo_callcache);
+ INIT_IMEMO_TYPE_ID(imemo_constcache);
+ INIT_IMEMO_TYPE_ID(imemo_fields);
+ INIT_IMEMO_TYPE_ID(imemo_subclasses);
+ INIT_IMEMO_TYPE_ID(imemo_cdhash);
+#undef INIT_IMEMO_TYPE_ID
+ }
+
+ each_object_with_flags(count_imemo_objects_i, (void *)hash);
+
+ return hash;
+}
+
+static void
+iow_mark(void *ptr)
+{
+ rb_gc_mark((VALUE)ptr);
+}
+
+static size_t
+iow_size(const void *ptr)
+{
+ VALUE obj = (VALUE)ptr;
+ return rb_obj_memsize_of(obj);
+}
+
+static const rb_data_type_t iow_data_type = {
+ "ObjectSpace::InternalObjectWrapper",
+ {iow_mark, 0, iow_size,},
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static VALUE rb_cInternalObjectWrapper;
+
+static VALUE
+iow_newobj(VALUE obj)
+{
+ return TypedData_Wrap_Struct(rb_cInternalObjectWrapper, &iow_data_type, (void *)obj);
+}
+
+/* Returns the type of the internal object. */
+static VALUE
+iow_type(VALUE self)
+{
+ VALUE obj = (VALUE)DATA_PTR(self);
+ return type2sym(BUILTIN_TYPE(obj));
+}
+
+/* See Object#inspect. */
+static VALUE
+iow_inspect(VALUE self)
+{
+ VALUE obj = (VALUE)DATA_PTR(self);
+ VALUE type = type2sym(BUILTIN_TYPE(obj));
+
+ return rb_sprintf("#<InternalObject:%p %"PRIsVALUE">", (void *)obj, rb_sym2str(type));
+}
+
+/* Returns the Object#object_id of the internal object. */
+static VALUE
+iow_internal_object_id(VALUE self)
+{
+ VALUE obj = (VALUE)DATA_PTR(self);
+ return rb_obj_id(obj);
+}
+
+struct rof_data {
+ VALUE refs;
+ VALUE values;
+};
+
+static void
+reachable_object_from_i(VALUE obj, void *data_ptr)
+{
+ struct rof_data *data = (struct rof_data *)data_ptr;
+ VALUE key = obj;
+ VALUE val = obj;
+
+ if (!rb_objspace_garbage_object_p(obj)) {
+ if (NIL_P(rb_hash_lookup(data->refs, key))) {
+ rb_hash_aset(data->refs, key, Qtrue);
+
+ if (rb_objspace_internal_object_p(obj)) {
+ val = iow_newobj(obj);
+ }
+
+ rb_ary_push(data->values, val);
+ }
+ }
+}
+
+static int
+collect_values(st_data_t key, st_data_t value, st_data_t data)
+{
+ VALUE ary = (VALUE)data;
+ rb_ary_push(ary, (VALUE)value);
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * ObjectSpace.reachable_objects_from(obj) -> array or nil
+ *
+ * Returns all reachable objects from +obj+ as an array:
+ *
+ * ObjectSpace.reachable_objects_from(['a', 'b', 'c'])
+ * #=> [Array, 'a', 'b', 'c']
+ *
+ * The returned array is deduplicated, meaning that if +obj+ refers
+ * to another object more than once, it will only be added to the array
+ * once:
+ *
+ * ObjectSpace.reachable_objects_from([v = 'a', v, v])
+ * #=> [Array, 'a']
+ *
+ * Returns +nil+ if +obj+ is not a markable object (i.e. non-heap
+ * managed) object. Non-markable objects include +true+, +false+,
+ * +nil+, certain symbols, small integers, and floats:
+ *
+ * ObjectSpace.reachable_objects_from(1)
+ * #=> nil
+ *
+ * All references to internal objects in the returned array are wrapped
+ * using ObjectSpace::InternalObjectWrapper objects. This object contains
+ * a reference to the internal object and the type of the object can
+ * be accessed using the ObjectSpace::InternalObjectWrapper#type method.
+ *
+ * If +obj+ is instance of ObjectSpace::InternalObjectWrapper, then this
+ * method returns all reachable object from the internal object.
+ *
+ * This method is useful for debugging purposes, such as finding
+ * memory leaks.
+ *
+ * This method is only expected to work with C Ruby.
+ */
+
+static VALUE
+reachable_objects_from(VALUE self, VALUE obj)
+{
+ if (!RB_SPECIAL_CONST_P(obj)) {
+ struct rof_data data;
+
+ if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
+ obj = (VALUE)DATA_PTR(obj);
+ }
+
+ data.refs = rb_obj_hide(rb_ident_hash_new());
+ data.values = rb_ary_new();
+
+ rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data);
+
+ return data.values;
+ }
+ else {
+ return Qnil;
+ }
+}
+
+struct rofr_data {
+ VALUE categories;
+ const char *last_category;
+ VALUE last_category_str;
+ VALUE last_category_objects;
+};
+
+static void
+reachable_object_from_root_i(const char *category, VALUE obj, void *ptr)
+{
+ struct rofr_data *data = (struct rofr_data *)ptr;
+ VALUE category_str;
+ VALUE category_objects;
+
+ if (category == data->last_category) {
+ category_str = data->last_category_str;
+ category_objects = data->last_category_objects;
+ }
+ else {
+ data->last_category = category;
+ category_str = data->last_category_str = rb_str_new2(category);
+ category_objects = data->last_category_objects = rb_ident_hash_new();
+ if (!NIL_P(rb_hash_lookup(data->categories, category_str))) {
+ rb_bug("reachable_object_from_root_i: category should insert at once");
+ }
+ rb_hash_aset(data->categories, category_str, category_objects);
+ }
+
+ if (!rb_objspace_garbage_object_p(obj) &&
+ obj != data->categories &&
+ obj != data->last_category_objects) {
+ if (rb_objspace_internal_object_p(obj)) {
+ obj = iow_newobj(obj);
+ }
+ rb_hash_aset(category_objects, obj, obj);
+ }
+}
+
+static int
+collect_values_of_values(VALUE category, VALUE category_objects, VALUE categories)
+{
+ VALUE ary = rb_ary_new();
+ rb_hash_foreach(category_objects, collect_values, ary);
+ rb_hash_aset(categories, category, ary);
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * ObjectSpace.reachable_objects_from_root -> hash
+ *
+ * Returns a hash of objects directly reachable from the VM roots,
+ * grouped by the root that reaches them.
+ *
+ * The roots are the entry points the garbage collector starts from when it
+ * marks live objects, such as the virtual machine and the global variable
+ * table. The keys of the returned hash are strings naming each root, and each
+ * value is an array of the objects reachable from that root:
+ *
+ * require 'objspace'
+ *
+ * reachable = ObjectSpace.reachable_objects_from_root
+ * reachable.keys # => ["vm", "global_tbl", "machine_context", "global_symbols"]
+ * reachable.values.first # => [#<Ractor:#1 running>, ...]
+ *
+ * The returned hash compares its keys by identity, so it cannot be indexed
+ * with a string literal; iterate over it (or over its #values) instead.
+ *
+ * Any reference to an internal object is wrapped in an
+ * ObjectSpace::InternalObjectWrapper object.
+ *
+ * This method is useful for debugging the object graph, for example when
+ * tracking down the cause of a memory leak.
+ *
+ * This method is only expected to work with C Ruby.
+ */
+static VALUE
+reachable_objects_from_root(VALUE self)
+{
+ struct rofr_data data;
+ VALUE hash = data.categories = rb_ident_hash_new();
+ data.last_category = 0;
+
+ rb_objspace_reachable_objects_from_root(reachable_object_from_root_i, &data);
+ rb_hash_foreach(hash, collect_values_of_values, hash);
+
+ return hash;
+}
+
+static VALUE
+wrap_klass_iow(VALUE klass)
+{
+ if (!RTEST(klass)) {
+ return Qnil;
+ }
+ else if (RB_TYPE_P(klass, T_ICLASS) ||
+ CLASS_OF(klass) == Qfalse /* hidden object */) {
+ return iow_newobj(klass);
+ }
+ else {
+ return klass;
+ }
+}
+
+/*
+ * call-seq:
+ * ObjectSpace.internal_class_of(obj) -> class or module
+ *
+ * Returns the real class of +obj+, which may differ from the class returned
+ * by Object#class.
+ *
+ * Ruby inserts hidden classes into an object's ancestry, such as a singleton
+ * class or an included module's iclass. Object#class skips over these, but
+ * this method returns the first one, including any hidden class:
+ *
+ * require 'objspace'
+ *
+ * s = "x"
+ * def s.foo; end # gives +s+ a singleton class
+ * s.class # => String
+ * ObjectSpace.internal_class_of(s) # => #<Class:#<String:0x000000012574c1f8>>
+ *
+ * +obj+ may be an ObjectSpace::InternalObjectWrapper, in which case the class
+ * of the wrapped internal object is returned.
+ *
+ * Note that you should not use this method in your application.
+ *
+ * This method is only expected to work with C Ruby.
+ */
+static VALUE
+objspace_internal_class_of(VALUE self, VALUE obj)
+{
+ VALUE klass;
+
+ if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
+ obj = (VALUE)DATA_PTR(obj);
+ }
+
+ if (RB_TYPE_P(obj, T_IMEMO)) {
+ return Qnil;
+ }
+ else {
+ klass = CLASS_OF(obj);
+ return wrap_klass_iow(klass);
+ }
+}
+
+/*
+ * call-seq:
+ * ObjectSpace.internal_super_of(cls) -> Class or Module
+ *
+ * [MRI specific feature] Return internal super class of cls (Class or Module).
+ * obj can be an instance of InternalObjectWrapper.
+ *
+ * Note that you should not use this method in your application.
+ */
+static VALUE
+objspace_internal_super_of(VALUE self, VALUE obj)
+{
+ VALUE super;
+
+ if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
+ obj = (VALUE)DATA_PTR(obj);
+ }
+
+ switch (OBJ_BUILTIN_TYPE(obj)) {
+ case T_MODULE:
+ case T_CLASS:
+ case T_ICLASS:
+ super = rb_class_super_of(obj);
+ break;
+ default:
+ rb_raise(rb_eArgError, "class or module is expected");
+ }
+
+ return wrap_klass_iow(super);
+}
+
+void Init_object_tracing(VALUE rb_mObjSpace);
+void Init_objspace_dump(VALUE rb_mObjSpace);
+
+/*
+ * Document-module: ObjectSpace
+ *
+ * The objspace library extends the ObjectSpace module and adds several
+ * methods to get internal statistic information about
+ * object/memory management.
+ *
+ * You need to <code>require 'objspace'</code> to use this extension module.
+ *
+ * Generally, you *SHOULD* *NOT* use this library if you do not know
+ * about the MRI implementation. Mainly, this library is for (memory)
+ * profiler developers and MRI developers who need to know about MRI
+ * memory usage.
+ */
+
+void
+Init_objspace(void)
+{
+#undef rb_intern
+ VALUE rb_mObjSpace;
+#if 0
+ rb_mObjSpace = rb_define_module("ObjectSpace"); /* let rdoc know */
+#endif
+ rb_mObjSpace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
+
+ rb_define_module_function(rb_mObjSpace, "memsize_of", memsize_of_m, 1);
+ rb_define_module_function(rb_mObjSpace, "memsize_of_all", memsize_of_all_m, -1);
+
+ rb_define_module_function(rb_mObjSpace, "count_objects_size", count_objects_size, -1);
+ rb_define_module_function(rb_mObjSpace, "count_symbols", count_symbols, -1);
+ rb_define_module_function(rb_mObjSpace, "count_tdata_objects", count_tdata_objects, -1);
+ rb_define_module_function(rb_mObjSpace, "count_imemo_objects", count_imemo_objects, -1);
+
+ rb_define_module_function(rb_mObjSpace, "reachable_objects_from", reachable_objects_from, 1);
+ rb_define_module_function(rb_mObjSpace, "reachable_objects_from_root", reachable_objects_from_root, 0);
+
+ rb_define_module_function(rb_mObjSpace, "internal_class_of", objspace_internal_class_of, 1);
+ rb_define_module_function(rb_mObjSpace, "internal_super_of", objspace_internal_super_of, 1);
+
+ /*
+ * This class is used as a return value from
+ * ObjectSpace::reachable_objects_from.
+ *
+ * When ObjectSpace::reachable_objects_from returns an object with
+ * references to an internal object, an instance of this class is returned.
+ *
+ * You can use the #type method to check the type of the internal object.
+ */
+ rb_cInternalObjectWrapper = rb_define_class_under(rb_mObjSpace, "InternalObjectWrapper", rb_cObject);
+ rb_undef_alloc_func(rb_cInternalObjectWrapper);
+ rb_define_method(rb_cInternalObjectWrapper, "type", iow_type, 0);
+ rb_define_method(rb_cInternalObjectWrapper, "inspect", iow_inspect, 0);
+ rb_define_method(rb_cInternalObjectWrapper, "internal_object_id", iow_internal_object_id, 0);
+
+ Init_object_tracing(rb_mObjSpace);
+ Init_objspace_dump(rb_mObjSpace);
+}
diff --git a/ext/objspace/objspace.h b/ext/objspace/objspace.h
new file mode 100644
index 0000000000..95b84d6c1e
--- /dev/null
+++ b/ext/objspace/objspace.h
@@ -0,0 +1,20 @@
+#ifndef OBJSPACE_H
+#define OBJSPACE_H 1
+
+/* object_tracing.c */
+struct allocation_info {
+ /* all of information don't need marking. */
+ int living;
+ VALUE flags;
+ VALUE klass;
+
+ /* allocation info */
+ const char *path;
+ unsigned long line;
+ const char *class_path;
+ VALUE mid;
+ size_t generation;
+};
+struct allocation_info *objspace_lookup_allocation_info(VALUE obj);
+
+#endif
diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c
new file mode 100644
index 0000000000..68ada01af3
--- /dev/null
+++ b/ext/objspace/objspace_dump.c
@@ -0,0 +1,932 @@
+/**********************************************************************
+
+ objspace_dump.c - Heap dumping ObjectSpace extender for MRI.
+
+ $Author$
+ created at: Sat Oct 11 10:11:00 2013
+
+ NOTE: This extension library is not expected to exist except C Ruby.
+
+ All the files in this distribution are covered under the Ruby's
+ license (see the file COPYING).
+
+**********************************************************************/
+
+#include "id_table.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/class.h"
+#include "internal/gc.h"
+#include "internal/hash.h"
+#include "internal/io.h"
+#include "internal/string.h"
+#include "internal/sanitizers.h"
+#include "symbol.h"
+#include "shape.h"
+#include "node.h"
+#include "objspace.h"
+#include "ruby/debug.h"
+#include "ruby/util.h"
+#include "ruby/io.h"
+#include "vm_callinfo.h"
+#include "vm_sync.h"
+
+RUBY_EXTERN const char ruby_hexdigits[];
+
+#define BUFFER_CAPACITY 4096
+
+struct dump_config {
+ VALUE given_output;
+ VALUE output_io;
+ VALUE string;
+ FILE *stream;
+ const char *root_category;
+ VALUE cur_obj;
+ VALUE cur_obj_klass;
+ size_t cur_page_slot_size;
+ size_t cur_obj_references;
+ unsigned int roots: 1;
+ unsigned int full_heap: 1;
+ unsigned int partial_dump;
+ size_t since;
+ size_t shapes_since;
+ unsigned long buffer_len;
+ char buffer[BUFFER_CAPACITY];
+};
+
+static void
+dump_flush(struct dump_config *dc)
+{
+ if (dc->buffer_len) {
+ if (dc->stream) {
+ size_t written = fwrite(dc->buffer, sizeof(dc->buffer[0]), dc->buffer_len, dc->stream);
+ if (written < dc->buffer_len) {
+ MEMMOVE(dc->buffer, dc->buffer + written, char, dc->buffer_len - written);
+ dc->buffer_len -= written;
+ return;
+ }
+ }
+ else if (dc->string) {
+ rb_str_cat(dc->string, dc->buffer, dc->buffer_len);
+ }
+ dc->buffer_len = 0;
+ }
+}
+
+static inline void
+buffer_ensure_capa(struct dump_config *dc, unsigned long requested)
+{
+ RUBY_ASSERT(requested <= BUFFER_CAPACITY);
+ if (requested + dc->buffer_len >= BUFFER_CAPACITY) {
+ dump_flush(dc);
+ if (requested + dc->buffer_len >= BUFFER_CAPACITY) {
+ rb_raise(rb_eIOError, "full buffer");
+ }
+ }
+}
+
+static void
+buffer_append(struct dump_config *dc, const char *cstr, unsigned long len)
+{
+ if (LIKELY(len > 0)) {
+ buffer_ensure_capa(dc, len);
+ MEMCPY(dc->buffer + dc->buffer_len, cstr, char, len);
+ dc->buffer_len += len;
+ }
+}
+
+# define dump_append(dc, str) buffer_append(dc, (str), (long)strlen(str))
+
+static void
+dump_append_ld(struct dump_config *dc, const long number)
+{
+ const unsigned int width = DECIMAL_SIZE_OF_BITS(sizeof(number) * CHAR_BIT - 1) + 2;
+ buffer_ensure_capa(dc, width);
+ unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "%ld", number);
+ RUBY_ASSERT(required <= width);
+ dc->buffer_len += required;
+}
+
+static void
+dump_append_lu(struct dump_config *dc, const unsigned long number)
+{
+ const unsigned int width = DECIMAL_SIZE_OF_BITS(sizeof(number) * CHAR_BIT) + 1;
+ buffer_ensure_capa(dc, width);
+ unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "%lu", number);
+ RUBY_ASSERT(required <= width);
+ dc->buffer_len += required;
+}
+
+static void
+dump_append_g(struct dump_config *dc, const double number)
+{
+ unsigned long capa_left = BUFFER_CAPACITY - dc->buffer_len;
+ unsigned long required = snprintf(dc->buffer + dc->buffer_len, capa_left, "%#g", number);
+
+ if (required >= capa_left) {
+ buffer_ensure_capa(dc, required);
+ capa_left = BUFFER_CAPACITY - dc->buffer_len;
+ snprintf(dc->buffer + dc->buffer_len, capa_left, "%#g", number);
+ }
+ dc->buffer_len += required;
+}
+
+static void
+dump_append_d(struct dump_config *dc, const int number)
+{
+ const unsigned int width = DECIMAL_SIZE_OF_BITS(sizeof(number) * CHAR_BIT - 1) + 2;
+ buffer_ensure_capa(dc, width);
+ unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "%d", number);
+ RUBY_ASSERT(required <= width);
+ dc->buffer_len += required;
+}
+
+static void
+dump_append_sizet(struct dump_config *dc, const size_t number)
+{
+ const unsigned int width = DECIMAL_SIZE_OF_BITS(sizeof(number) * CHAR_BIT) + 1;
+ buffer_ensure_capa(dc, width);
+ unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "%"PRIuSIZE, number);
+ RUBY_ASSERT(required <= width);
+ dc->buffer_len += required;
+}
+
+static void
+dump_append_c(struct dump_config *dc, unsigned char c)
+{
+ if (c <= 0x1f) {
+ const unsigned int width = rb_strlen_lit("\\u0000") + 1;
+ buffer_ensure_capa(dc, width);
+ unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "\\u00%02x", c);
+ RUBY_ASSERT(required <= width);
+ dc->buffer_len += required;
+ }
+ else {
+ buffer_ensure_capa(dc, 1);
+ dc->buffer[dc->buffer_len] = c;
+ dc->buffer_len++;
+ }
+}
+
+static void
+dump_append_ptr(struct dump_config *dc, VALUE ref)
+{
+ char buffer[roomof(sizeof(VALUE) * CHAR_BIT, 4) + rb_strlen_lit("\"0x\"")];
+ char *buffer_start, *buffer_end;
+
+ buffer_start = buffer_end = &buffer[sizeof(buffer)];
+ *--buffer_start = '"';
+ while (ref) {
+ *--buffer_start = ruby_hexdigits[ref & 0xF];
+ ref >>= 4;
+ }
+ *--buffer_start = 'x';
+ *--buffer_start = '0';
+ *--buffer_start = '"';
+ buffer_append(dc, buffer_start, buffer_end - buffer_start);
+}
+
+static void
+dump_append_ref(struct dump_config *dc, VALUE ref)
+{
+ RUBY_ASSERT(ref > 0);
+ dump_append_ptr(dc, ref);
+}
+
+
+static void
+dump_append_string_value(struct dump_config *dc, VALUE obj)
+{
+ long i;
+ char c;
+ const char *value;
+
+ dump_append(dc, "\"");
+ for (i = 0, value = RSTRING_PTR(obj); i < RSTRING_LEN(obj); i++) {
+ switch ((c = value[i])) {
+ case '\\':
+ dump_append(dc, "\\\\");
+ break;
+ case '"':
+ dump_append(dc, "\\\"");
+ break;
+ case '\0':
+ dump_append(dc, "\\u0000");
+ break;
+ case '\b':
+ dump_append(dc, "\\b");
+ break;
+ case '\t':
+ dump_append(dc, "\\t");
+ break;
+ case '\f':
+ dump_append(dc, "\\f");
+ break;
+ case '\n':
+ dump_append(dc, "\\n");
+ break;
+ case '\r':
+ dump_append(dc, "\\r");
+ break;
+ case '\177':
+ dump_append(dc, "\\u007f");
+ break;
+ default:
+ dump_append_c(dc, c);
+ }
+ }
+ dump_append(dc, "\"");
+}
+
+static void
+dump_append_symbol_value(struct dump_config *dc, VALUE obj)
+{
+ dump_append(dc, "{\"type\":\"SYMBOL\", \"value\":");
+ dump_append_string_value(dc, rb_sym2str(obj));
+ dump_append(dc, "}");
+}
+
+static inline const char *
+obj_type(VALUE obj)
+{
+ switch (BUILTIN_TYPE(obj)) {
+#define CASE_TYPE(type) case T_##type: return #type
+ CASE_TYPE(NONE);
+ CASE_TYPE(NIL);
+ CASE_TYPE(OBJECT);
+ CASE_TYPE(CLASS);
+ CASE_TYPE(ICLASS);
+ CASE_TYPE(MODULE);
+ CASE_TYPE(FLOAT);
+ CASE_TYPE(STRING);
+ CASE_TYPE(REGEXP);
+ CASE_TYPE(ARRAY);
+ CASE_TYPE(HASH);
+ CASE_TYPE(STRUCT);
+ CASE_TYPE(BIGNUM);
+ CASE_TYPE(FILE);
+ CASE_TYPE(FIXNUM);
+ CASE_TYPE(TRUE);
+ CASE_TYPE(FALSE);
+ CASE_TYPE(DATA);
+ CASE_TYPE(MATCH);
+ CASE_TYPE(SYMBOL);
+ CASE_TYPE(RATIONAL);
+ CASE_TYPE(COMPLEX);
+ CASE_TYPE(IMEMO);
+ CASE_TYPE(UNDEF);
+ CASE_TYPE(NODE);
+ CASE_TYPE(ZOMBIE);
+#undef CASE_TYPE
+ default: break;
+ }
+ return "UNKNOWN";
+}
+
+static void
+dump_append_special_const(struct dump_config *dc, VALUE value)
+{
+ if (value == Qtrue) {
+ dump_append(dc, "true");
+ }
+ else if (value == Qfalse) {
+ dump_append(dc, "false");
+ }
+ else if (value == Qnil) {
+ dump_append(dc, "null");
+ }
+ else if (FIXNUM_P(value)) {
+ dump_append_ld(dc, FIX2LONG(value));
+ }
+ else if (FLONUM_P(value)) {
+ dump_append_g(dc, RFLOAT_VALUE(value));
+ }
+ else if (SYMBOL_P(value)) {
+ dump_append_symbol_value(dc, value);
+ }
+ else {
+ dump_append(dc, "{}");
+ }
+}
+
+static void
+reachable_object_i(VALUE ref, void *data)
+{
+ struct dump_config *dc = (struct dump_config *)data;
+
+ if (dc->cur_obj_klass == ref)
+ return;
+
+ if (dc->cur_obj_references == 0) {
+ dump_append(dc, ", \"references\":[");
+ dump_append_ref(dc, ref);
+ }
+ else {
+ dump_append(dc, ", ");
+ dump_append_ref(dc, ref);
+ }
+
+ dc->cur_obj_references++;
+}
+
+static bool
+dump_string_ascii_only(const char *str, long size)
+{
+ for (long i = 0; i < size; i++) {
+ if (str[i] & 0x80) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void
+dump_append_string_content(struct dump_config *dc, VALUE obj)
+{
+ dump_append(dc, ", \"bytesize\":");
+ dump_append_ld(dc, RSTRING_LEN(obj));
+ if (!STR_EMBED_P(obj) && !STR_SHARED_P(obj) && (long)rb_str_capacity(obj) != RSTRING_LEN(obj)) {
+ dump_append(dc, ", \"capacity\":");
+ dump_append_sizet(dc, rb_str_capacity(obj));
+ }
+
+ if (RSTRING_LEN(obj) && rb_enc_asciicompat(rb_enc_from_index(ENCODING_GET(obj)))) {
+ int cr = ENC_CODERANGE(obj);
+ if (cr == RUBY_ENC_CODERANGE_UNKNOWN) {
+ if (dump_string_ascii_only(RSTRING_PTR(obj), RSTRING_LEN(obj))) {
+ cr = RUBY_ENC_CODERANGE_7BIT;
+ }
+ }
+ if (cr == RUBY_ENC_CODERANGE_7BIT) {
+ dump_append(dc, ", \"value\":");
+ dump_append_string_value(dc, obj);
+ }
+ }
+}
+
+static inline void
+dump_append_id(struct dump_config *dc, ID id)
+{
+ VALUE str = rb_sym2str(ID2SYM(id));
+ if (RTEST(str)) {
+ dump_append_string_value(dc, str);
+ }
+ else {
+ dump_append(dc, "\"ID_INTERNAL(");
+ dump_append_sizet(dc, rb_id_to_serial(id));
+ dump_append(dc, ")\"");
+ }
+}
+
+
+static void
+dump_object(VALUE obj, struct dump_config *dc)
+{
+ size_t memsize;
+ struct allocation_info *ainfo = objspace_lookup_allocation_info(obj);
+ rb_io_t *fptr;
+ ID mid;
+
+ if (SPECIAL_CONST_P(obj)) {
+ dump_append_special_const(dc, obj);
+ return;
+ }
+
+ dc->cur_obj = obj;
+ dc->cur_obj_references = 0;
+ if (BUILTIN_TYPE(obj) == T_NODE || (BUILTIN_TYPE(obj) == T_IMEMO && !IMEMO_TYPE_P(obj, imemo_fields))) {
+ dc->cur_obj_klass = 0;
+ }
+ else {
+ dc->cur_obj_klass = RBASIC_CLASS(obj);
+ }
+
+ if (dc->partial_dump && (!ainfo || ainfo->generation < dc->since)) {
+ return;
+ }
+
+ if (dc->cur_obj == dc->string)
+ return;
+
+ dump_append(dc, "{\"address\":");
+ dump_append_ref(dc, obj);
+
+ dump_append(dc, ", \"type\":\"");
+ dump_append(dc, obj_type(obj));
+ dump_append(dc, "\"");
+
+ if (BUILTIN_TYPE(obj) != T_IMEMO || IMEMO_TYPE_P(obj, imemo_fields)) {
+ size_t shape_id = rb_obj_shape_id(obj) & SHAPE_ID_OFFSET_MASK;
+ dump_append(dc, ", \"shape_id\":");
+ dump_append_sizet(dc, shape_id);
+ }
+
+ dump_append(dc, ", \"slot_size\":");
+ dump_append_sizet(dc, dc->cur_page_slot_size);
+
+ if (dc->cur_obj_klass) {
+ dump_append(dc, ", \"class\":");
+ dump_append_ref(dc, dc->cur_obj_klass);
+ }
+ if (rb_obj_frozen_p(obj))
+ dump_append(dc, ", \"frozen\":true");
+
+ switch (BUILTIN_TYPE(obj)) {
+ case T_NONE:
+ dump_append(dc, "}\n");
+ return;
+
+ case T_IMEMO:
+ dump_append(dc, ", \"imemo_type\":\"");
+ dump_append(dc, rb_imemo_name(imemo_type(obj)));
+ dump_append(dc, "\"");
+
+ switch (imemo_type(obj)) {
+ case imemo_callinfo:
+ mid = vm_ci_mid((const struct rb_callinfo *)obj);
+ if (mid != 0) {
+ dump_append(dc, ", \"mid\":");
+ dump_append_id(dc, mid);
+ }
+ break;
+
+ case imemo_callcache:
+ {
+ VALUE klass = ((const struct rb_callcache *)obj)->klass;
+ if (klass != Qundef) {
+ mid = vm_cc_cme((const struct rb_callcache *)obj)->called_id;
+ if (mid != 0) {
+ dump_append(dc, ", \"called_id\":");
+ dump_append_id(dc, mid);
+
+ }
+
+ dump_append(dc, ", \"receiver_class\":");
+ dump_append_ref(dc, klass);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case T_SYMBOL:
+ dump_append_string_content(dc, rb_sym2str(obj));
+ break;
+
+ case T_STRING:
+ if (STR_EMBED_P(obj))
+ dump_append(dc, ", \"embedded\":true");
+ if (FL_TEST(obj, RSTRING_FSTR))
+ dump_append(dc, ", \"fstring\":true");
+ if (CHILLED_STRING_P(obj))
+ dump_append(dc, ", \"chilled\":true");
+ if (STR_SHARED_P(obj))
+ dump_append(dc, ", \"shared\":true");
+ else
+ dump_append_string_content(dc, obj);
+
+ if (!ENCODING_IS_ASCII8BIT(obj)) {
+ dump_append(dc, ", \"encoding\":\"");
+ dump_append(dc, rb_enc_name(rb_enc_from_index(ENCODING_GET(obj))));
+ dump_append(dc, "\"");
+ }
+
+ dump_append(dc, ", \"coderange\":\"");
+ switch (RB_ENC_CODERANGE(obj)) {
+ case RUBY_ENC_CODERANGE_UNKNOWN:
+ dump_append(dc, "unknown");
+ break;
+ case RUBY_ENC_CODERANGE_7BIT:
+ dump_append(dc, "7bit");
+ break;
+ case RUBY_ENC_CODERANGE_VALID:
+ dump_append(dc, "valid");
+ break;
+ case RUBY_ENC_CODERANGE_BROKEN:
+ dump_append(dc, "broken");
+ break;
+ }
+ dump_append(dc, "\"");
+
+ if (RB_ENC_CODERANGE(obj) == RUBY_ENC_CODERANGE_BROKEN)
+ dump_append(dc, ", \"broken\":true");
+
+ break;
+
+ case T_HASH:
+ dump_append(dc, ", \"size\":");
+ dump_append_sizet(dc, (size_t)RHASH_SIZE(obj));
+ if (FL_TEST(obj, RHASH_PROC_DEFAULT)) {
+ dump_append(dc, ", \"default\":");
+ dump_append_ref(dc, RHASH_IFNONE(obj));
+ }
+ break;
+
+ case T_ARRAY:
+ dump_append(dc, ", \"length\":");
+ dump_append_ld(dc, RARRAY_LEN(obj));
+ if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, RARRAY_SHARED_FLAG))
+ dump_append(dc, ", \"shared\":true");
+ if (FL_TEST(obj, RARRAY_EMBED_FLAG))
+ dump_append(dc, ", \"embedded\":true");
+ break;
+
+ case T_ICLASS:
+ if (rb_class_get_superclass(obj)) {
+ dump_append(dc, ", \"superclass\":");
+ dump_append_ref(dc, rb_class_get_superclass(obj));
+ }
+ break;
+
+ case T_CLASS:
+ dump_append(dc, ", \"variation_count\":");
+ dump_append_d(dc, rb_class_variation_count(obj));
+
+ case T_MODULE:
+ if (rb_class_get_superclass(obj)) {
+ dump_append(dc, ", \"superclass\":");
+ dump_append_ref(dc, rb_class_get_superclass(obj));
+ }
+
+ if (dc->cur_obj_klass) {
+ VALUE mod_name = rb_mod_name(obj);
+ if (!NIL_P(mod_name)) {
+ dump_append(dc, ", \"name\":");
+ dump_append_string_value(dc, mod_name);
+ }
+ else {
+ VALUE real_mod_name = rb_mod_name(rb_class_real(obj));
+ if (RTEST(real_mod_name)) {
+ dump_append(dc, ", \"real_class_name\":\"");
+ dump_append(dc, RSTRING_PTR(real_mod_name));
+ dump_append(dc, "\"");
+ }
+ }
+
+ if (rb_class_singleton_p(obj)) {
+ dump_append(dc, ", \"singleton\":true");
+ }
+ }
+ break;
+
+ case T_DATA:
+ {
+ const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
+ dump_append(dc, ", \"struct\":\"");
+ dump_append(dc, type->wrap_struct_name);
+ dump_append(dc, "\"");
+ if (!(type->flags & RUBY_TYPED_FREE_IMMEDIATELY) &&
+ type->function.dfree != RUBY_DEFAULT_FREE) {
+ dump_append(dc, ", \"free_immediately\":false");
+ }
+ }
+ break;
+
+ case T_FLOAT:
+ dump_append(dc, ", \"value\":\"");
+ dump_append_g(dc, RFLOAT_VALUE(obj));
+ dump_append(dc, "\"");
+ break;
+
+ case T_OBJECT:
+ if (!FL_TEST_RAW(obj, ROBJECT_HEAP)) {
+ dump_append(dc, ", \"embedded\":true");
+ }
+
+ dump_append(dc, ", \"ivars\":");
+ dump_append_lu(dc, ROBJECT_FIELDS_COUNT(obj));
+ if (rb_obj_shape_complex_p(obj)) {
+ dump_append(dc, ", \"complex_shape\":true");
+ }
+ break;
+
+ case T_FILE:
+ fptr = RFILE(obj)->fptr;
+ if (fptr) {
+ dump_append(dc, ", \"fd\":");
+ dump_append_d(dc, fptr->fd);
+ }
+ break;
+
+ case T_ZOMBIE:
+ dump_append(dc, "}\n");
+ return;
+
+ default:
+ break;
+ }
+
+ rb_objspace_reachable_objects_from(obj, reachable_object_i, dc);
+ if (dc->cur_obj_references > 0)
+ dump_append(dc, "]");
+
+ if (ainfo) {
+ if (ainfo->path) {
+ dump_append(dc, ", \"file\":\"");
+ dump_append(dc, ainfo->path);
+ dump_append(dc, "\"");
+ }
+ if (ainfo->line) {
+ dump_append(dc, ", \"line\":");
+ dump_append_lu(dc, ainfo->line);
+ }
+ if (RTEST(ainfo->mid)) {
+ VALUE m = rb_sym2str(ainfo->mid);
+ dump_append(dc, ", \"method\":");
+ dump_append_string_value(dc, m);
+ }
+ dump_append(dc, ", \"generation\":");
+ dump_append_sizet(dc, ainfo->generation);
+ }
+
+ if ((memsize = rb_obj_memsize_of(obj)) > 0) {
+ dump_append(dc, ", \"memsize\":");
+ dump_append_sizet(dc, memsize);
+ }
+
+ struct rb_gc_object_metadata_entry *gc_metadata = rb_gc_object_metadata(obj);
+ for (int i = 0; gc_metadata[i].name != 0; i++) {
+ if (i == 0) {
+ dump_append(dc, ", \"flags\":{");
+ }
+ else {
+ dump_append(dc, ", ");
+ }
+
+ dump_append(dc, "\"");
+ dump_append(dc, rb_id2name(gc_metadata[i].name));
+ dump_append(dc, "\":");
+ dump_append_special_const(dc, gc_metadata[i].val);
+ }
+
+ /* If rb_gc_object_metadata had any entries, we need to close the opening
+ * `"flags":{`. */
+ if (gc_metadata[0].name != 0) {
+ dump_append(dc, "}");
+ }
+
+ dump_append(dc, "}\n");
+}
+
+static int
+heap_i(void *vstart, void *vend, size_t stride, void *data)
+{
+ struct dump_config *dc = (struct dump_config *)data;
+ VALUE v = (VALUE)vstart;
+ for (; v != (VALUE)vend; v += stride) {
+ void *ptr = rb_asan_poisoned_object_p(v);
+ rb_asan_unpoison_object(v, false);
+ dc->cur_page_slot_size = stride;
+
+ if (dc->full_heap || RBASIC(v)->flags)
+ dump_object(v, dc);
+
+ if (ptr) {
+ rb_asan_poison_object(v);
+ }
+ }
+ return 0;
+}
+
+static void
+root_obj_i(const char *category, VALUE obj, void *data)
+{
+ struct dump_config *dc = (struct dump_config *)data;
+
+ if (dc->root_category != NULL && category != dc->root_category)
+ dump_append(dc, "]}\n");
+ if (dc->root_category == NULL || category != dc->root_category) {
+ dump_append(dc, "{\"type\":\"ROOT\", \"root\":\"");
+ dump_append(dc, category);
+ dump_append(dc, "\", \"references\":[");
+ dump_append_ref(dc, obj);
+ }
+ else {
+ dump_append(dc, ", ");
+ dump_append_ref(dc, obj);
+ }
+
+ dc->root_category = category;
+ dc->roots = 1;
+}
+
+static void
+dump_output(struct dump_config *dc, VALUE output, VALUE full, VALUE since, VALUE shapes)
+{
+ dc->given_output = output;
+ dc->full_heap = 0;
+ dc->buffer_len = 0;
+
+ if (TYPE(output) == T_STRING) {
+ dc->stream = NULL;
+ dc->string = output;
+ }
+ else {
+ rb_io_t *fptr;
+ // Output should be an IO, typecheck and get a FILE* for writing.
+ // We cannot write with the usual IO code here because writes
+ // interleave with calls to rb_gc_mark(). The usual IO code can
+ // cause a thread switch, raise exceptions, and even run arbitrary
+ // ruby code through the fiber scheduler.
+ //
+ // Mark functions generally can't handle these possibilities so
+ // the usual IO code is unsafe in this context. (For example,
+ // there are many ways to crash when ruby code runs and mutates
+ // the execution context while rb_execution_context_mark() is in
+ // progress.)
+ //
+ // Using FILE* isn't perfect, but it avoids the most acute problems.
+ output = rb_io_get_io(output);
+ dc->output_io = rb_io_get_write_io(output);
+ rb_io_flush(dc->output_io);
+ GetOpenFile(dc->output_io, fptr);
+ dc->stream = rb_io_stdio_file(fptr);
+ dc->string = Qfalse;
+ }
+
+ if (full == Qtrue) {
+ dc->full_heap = 1;
+ }
+
+ if (RTEST(since)) {
+ dc->partial_dump = 1;
+ dc->since = NUM2SIZET(since);
+ }
+ else {
+ dc->partial_dump = 0;
+ }
+
+ dc->shapes_since = RTEST(shapes) ? NUM2SIZET(shapes) : 0;
+}
+
+static VALUE
+dump_result(struct dump_config *dc)
+{
+ dump_flush(dc);
+
+ if (dc->stream) {
+ fflush(dc->stream);
+ }
+ if (dc->string) {
+ return dc->string;
+ }
+ return dc->given_output;
+}
+
+static VALUE
+dump_locked(void *args_p)
+{
+ struct dump_config dc = {0,};
+ VALUE obj = ((VALUE*)args_p)[0];
+ VALUE output = ((VALUE*)args_p)[1];
+
+ if (!RB_SPECIAL_CONST_P(obj)) {
+ dc.cur_page_slot_size = rb_gc_obj_slot_size(obj);
+ }
+ dump_output(&dc, output, Qnil, Qnil, Qnil);
+
+ dump_object(obj, &dc);
+
+ return dump_result(&dc);
+}
+
+/* :nodoc: */
+static VALUE
+objspace_dump(VALUE os, VALUE obj, VALUE output)
+{
+ VALUE args[2];
+ args[0] = obj;
+ args[1] = output;
+ return rb_vm_lock_with_barrier(dump_locked, (void*)args);
+}
+
+static void
+shape_id_i(shape_id_t shape_id, void *data)
+{
+ struct dump_config *dc = (struct dump_config *)data;
+
+ if (shape_id < dc->shapes_since) {
+ return;
+ }
+
+ dump_append(dc, "{\"address\":");
+ dump_append_ref(dc, (VALUE)RSHAPE(shape_id));
+
+ dump_append(dc, ", \"type\":\"SHAPE\", \"id\":");
+ dump_append_sizet(dc, shape_id);
+
+ if (RSHAPE_TYPE(shape_id) != SHAPE_ROOT) {
+ dump_append(dc, ", \"parent_id\":");
+ dump_append_lu(dc, RSHAPE_PARENT_OFFSET(shape_id));
+ }
+
+ dump_append(dc, ", \"depth\":");
+ dump_append_sizet(dc, rb_shape_depth(shape_id));
+
+ switch (RSHAPE_TYPE(shape_id)) {
+ case SHAPE_ROOT:
+ dump_append(dc, ", \"shape_type\":\"ROOT\"");
+ break;
+ case SHAPE_IVAR:
+ dump_append(dc, ", \"shape_type\":\"IVAR\"");
+
+ dump_append(dc, ",\"edge_name\":");
+ dump_append_id(dc, RSHAPE_EDGE_NAME(shape_id));
+
+ break;
+ case SHAPE_OBJ_ID:
+ dump_append(dc, ", \"shape_type\":\"OBJ_ID\"");
+ break;
+ }
+
+ dump_append(dc, ", \"edges\":");
+ dump_append_sizet(dc, rb_shape_edges_count(shape_id));
+
+ dump_append(dc, ", \"memsize\":");
+ dump_append_sizet(dc, rb_shape_memsize(shape_id));
+
+ dump_append(dc, "}\n");
+}
+
+static VALUE
+dump_all_locked(void *args_p)
+{
+ struct dump_config dc = {0,};
+ VALUE output = ((VALUE*)args_p)[0];
+ VALUE full = ((VALUE*)args_p)[1];
+ VALUE since = ((VALUE*)args_p)[2];
+ VALUE shapes = ((VALUE*)args_p)[3];
+
+ dump_output(&dc, output, full, since, shapes);
+
+ if (!dc.partial_dump || dc.since == 0) {
+ /* dump roots */
+ rb_objspace_reachable_objects_from_root(root_obj_i, &dc);
+ if (dc.roots) dump_append(&dc, "]}\n");
+ }
+
+ if (RTEST(shapes)) {
+ rb_shape_each_shape_id(shape_id_i, &dc);
+ }
+
+ /* dump all objects */
+ rb_objspace_each_objects(heap_i, &dc);
+
+ return dump_result(&dc);
+}
+
+/* :nodoc: */
+static VALUE
+objspace_dump_all(VALUE os, VALUE output, VALUE full, VALUE since, VALUE shapes)
+{
+ VALUE args[4];
+ args[0] = output;
+ args[1] = full;
+ args[2] = since;
+ args[3] = shapes;
+ return rb_vm_lock_with_barrier(dump_all_locked, (void*)args);
+}
+
+static VALUE
+dump_shapes_locked(void *args_p)
+{
+ struct dump_config dc = {0,};
+ VALUE output = ((VALUE*)args_p)[0];
+ VALUE shapes = ((VALUE*)args_p)[1];
+
+ dump_output(&dc, output, Qfalse, Qnil, shapes);
+
+ if (RTEST(shapes)) {
+ rb_shape_each_shape_id(shape_id_i, &dc);
+ }
+ return dump_result(&dc);
+}
+
+/* :nodoc: */
+static VALUE
+objspace_dump_shapes(VALUE os, VALUE output, VALUE shapes)
+{
+ VALUE args[2];
+ args[0] = output;
+ args[1] = shapes;
+ return rb_vm_lock_with_barrier(dump_shapes_locked, (void*)args);
+}
+
+void
+Init_objspace_dump(VALUE rb_mObjSpace)
+{
+#undef rb_intern
+#if 0
+ rb_mObjSpace = rb_define_module("ObjectSpace"); /* let rdoc know */
+#endif
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ RB_EXT_RACTOR_SAFE(true);
+#endif
+
+ rb_define_module_function(rb_mObjSpace, "_dump", objspace_dump, 2);
+ rb_define_module_function(rb_mObjSpace, "_dump_all", objspace_dump_all, 4);
+ rb_define_module_function(rb_mObjSpace, "_dump_shapes", objspace_dump_shapes, 2);
+}
diff --git a/ext/openssl/.cvsignore b/ext/openssl/.cvsignore
deleted file mode 100644
index 3a9a9f341f..0000000000
--- a/ext/openssl/.cvsignore
+++ /dev/null
@@ -1,5 +0,0 @@
-GNUmakefile
-Makefile
-mkmf.log
-dep
-extconf.h
diff --git a/ext/openssl/History.md b/ext/openssl/History.md
new file mode 100644
index 0000000000..ce01b3e0f2
--- /dev/null
+++ b/ext/openssl/History.md
@@ -0,0 +1,1007 @@
+Version 4.0.2
+=============
+
+Merged changes in 3.2.4 and 3.3.3.
+
+
+Version 4.0.1
+=============
+
+Notable changes
+---------------
+
+* Add `sync_close` keyword argument to `OpenSSL::SSL::SSLSocket.new` as a
+ short-hand for setting `sync_close` attribute on the created `SSLSocket`
+ instance.
+ [[GitHub #955]](https://github.com/ruby/openssl/issues/955)
+ [[GitHub #996]](https://github.com/ruby/openssl/pull/996)
+
+
+Bug fixes
+---------
+
+* Fix uninitialized variables in `OpenSSL::OCSP::BasicResponse#status`.
+ [[GitHub #1004]](https://github.com/ruby/openssl/pull/1004)
+
+
+Version 4.0.0
+=============
+
+Compatibility
+-------------
+
+* Ruby >= 2.7
+* OpenSSL >= 1.1.1, LibreSSL >= 3.9, and AWS-LC 1.66.0
+ - Removed support for OpenSSL 1.0.2-1.1.0 and LibreSSL 3.1-3.8.
+ [[GitHub #835]](https://github.com/ruby/openssl/issues/835)
+ - Added support for AWS-LC.
+ [[GitHub #833]](https://github.com/ruby/openssl/issues/833)
+
+
+Notable changes
+---------------
+
+* `OpenSSL::SSL`
+ - Reduce overhead when writing to `OpenSSL::SSL::SSLSocket`. `#syswrite` no
+ longer creates a temporary String object.
+ [[GitHub #831]](https://github.com/ruby/openssl/pull/831)
+ - Make `OpenSSL::SSL::SSLContext#min_version=` and `#max_version=` wrap the
+ corresponding OpenSSL APIs directly, and remove the fallback to SSL options.
+ [[GitHub #849]](https://github.com/ruby/openssl/pull/849)
+ - Add `OpenSSL::SSL::SSLContext#sigalgs=` and `#client_sigalgs=` for
+ specifying signature algorithms to use for connections.
+ [[GitHub #895]](https://github.com/ruby/openssl/pull/895)
+ - Rename `OpenSSL::SSL::SSLContext#ecdh_curves=` to `#groups=` following
+ the underlying OpenSSL API rename. This method is no longer specific to
+ ECDHE. The old method remains as an alias.
+ [[GitHub #900]](https://github.com/ruby/openssl/pull/900)
+ - Add `OpenSSL::SSL::SSLSocket#sigalg`, `#peer_sigalg`, and `#group` for
+ getting the signature algorithm and the key agreement group used in the
+ current connection.
+ [[GitHub #908]](https://github.com/ruby/openssl/pull/908)
+ - Enable `SSL_CTX_set_dh_auto()` for servers by default.
+ [[GitHub #924]](https://github.com/ruby/openssl/pull/924)
+ - Improve Ractor compatibility. Note that the internal-use constant
+ `OpenSSL::SSL::SSLContext::DEFAULT_PARAMS` is now frozen.
+ [[GitHub #925]](https://github.com/ruby/openssl/pull/925)
+* `OpenSSL::PKey`
+ - Remove `OpenSSL::PKey::EC::Point#mul` support with array arguments. The
+ underlying OpenSSL API has been removed, and the method has been deprecated
+ since ruby/openssl v3.0.0.
+ [[GitHub #843]](https://github.com/ruby/openssl/pull/843)
+ - `OpenSSL::PKey::{RSA,DSA,DH}#params` uses `nil` to indicate missing fields
+ instead of the number `0`.
+ [[GitHub #774]](https://github.com/ruby/openssl/pull/774)
+ - Unify `OpenSSL::PKey::PKeyError` classes. The former subclasses
+ `OpenSSL::PKey::DHError`, `OpenSSL::PKey::DSAError`,
+ `OpenSSL::PKey::ECError`, and `OpenSSL::PKey::RSAError` have been merged
+ into a single class.
+ [[GitHub #929]](https://github.com/ruby/openssl/pull/929)
+* `OpenSSL::Cipher`
+ - `OpenSSL::Cipher#encrypt` and `#decrypt` no longer accept arguments.
+ Passing passwords has been deprecated since Ruby 1.8.2 (released in 2004).
+ [[GitHub #887]](https://github.com/ruby/openssl/pull/887)
+ - `OpenSSL::Cipher#final` raises `OpenSSL::Cipher::AuthTagError` when the
+ integrity check fails for AEAD ciphers. `OpenSSL::Cipher::AuthTagError` is a
+ new subclass of `OpenSSL::Cipher::CipherError`, which was previously raised.
+ [[GitHub #939]](https://github.com/ruby/openssl/pull/939)
+ - `OpenSSL::Cipher.new` now raises `OpenSSL::Cipher::CipherError` instead of
+ `RuntimeError` when OpenSSL does not recognize the algorithm.
+ [[GitHub #958]](https://github.com/ruby/openssl/pull/958)
+ - Add support for "fetched" cipher algorithms with OpenSSL 3.0 or later.
+ [[GitHub #958]](https://github.com/ruby/openssl/pull/958)
+* `OpenSSL::Digest`
+ - `OpenSSL::Digest.new` now raises `OpenSSL::Digest::DigestError` instead of
+ `RuntimeError` when OpenSSL does not recognize the algorithm.
+ [[GitHub #958]](https://github.com/ruby/openssl/pull/958)
+ - Add support for "fetched" digest algorithms with OpenSSL 3.0 or later.
+ [[GitHub #958]](https://github.com/ruby/openssl/pull/958)
+* `OpenSSL::ASN1.decode` now assumes a 1950-2049 year range for `UTCTime`
+ according to RFC 5280. It previously used a 1969-2068 range. The encoder
+ has always used the 1950-2049 range.
+ [[GitHub #909]](https://github.com/ruby/openssl/pull/909)
+* `OpenSSL::OpenSSLError`, the base class for all ruby/openssl errors, carry
+ an additional attribute `#errors` to keep the content of OpenSSL's error
+ queue. Also, add `#detailed_message` for Ruby 3.2 or later.
+ [[GitHub #976]](https://github.com/ruby/openssl/pull/976)
+* `OpenSSL::PKCS7.new` raises `OpenSSL::PKCS7::PKCS7Error` instead of
+ `ArgumentError` on error to be consistent with other constructors.
+ [[GitHub #983]](https://github.com/ruby/openssl/pull/983)
+
+
+Version 3.3.3
+=============
+
+Merged changes in 3.2.4.
+
+
+Version 3.3.2
+=============
+
+Merged changes in 3.1.3 and 3.2.3.
+
+
+Version 3.3.1
+=============
+
+Merged changes in 3.1.2 and 3.2.2.
+
+
+Version 3.3.0
+=============
+
+Compatibility
+-------------
+
+* Ruby version: 2.7 or later
+* OpenSSL version: OpenSSL 1.0.2 or later, and LibreSSL 3.1 or later
+
+Notable changes
+---------------
+
+* `OpenSSL::SSL`
+ - `OpenSSL::SSL::SSLSocket#set_params` no longer sets `#min_version=` to TLS
+ 1.0 except when OpenSSL 1.0.2 is used. This has been done to disable
+ SSL 3.0, which is not supported by default in OpenSSL 1.1.0 or later, or in
+ LibreSSL. This lets it respect the system default if the system-wide
+ configuration file specifies a higher minimum protocol version.
+ [[GitHub #710]](https://github.com/ruby/openssl/pull/710)
+ - `OpenSSL::SSL::SSLSocket.new` no longer enables the `OpenSSL::SSL::OP_ALL`
+ SSL options by default and follows the system default.
+ [[GitHub #767]](https://github.com/ruby/openssl/pull/767)
+ - Add the following IO methods to `OpenSSL::SSL::SSLSocket`, which will pass
+ along to the underlying socket: `#local_address`, `#remote_address`,
+ `#close_on_exec=`, `#close_on_exec?`, `#wait`, `#wait_readable`, and
+ `#wait_writable`.
+ [[GitHub #708]](https://github.com/ruby/openssl/pull/708)
+ - Update `OpenSSL::SSL::SSLSocket#gets` to take the `chomp` keyword argument.
+ [[GitHub #708]](https://github.com/ruby/openssl/pull/708)
+ - Make `OpenSSL::SSL::SSLSocket` respect the `IO#timeout` value of the
+ underlying socket on Ruby 3.2 or later. `#timeout` and `#timeout=` methods
+ are also added.
+ [[GitHub #714]](https://github.com/ruby/openssl/pull/714)
+ - Add `OpenSSL::SSL::SSLSocket#close_read` and `#close_write`.
+ [[GitHub #743]](https://github.com/ruby/openssl/pull/743)
+ - Add `OpenSSL::Digest.digests` to get a list of all available digest
+ algorithms.
+ [[GitHub #726]](https://github.com/ruby/openssl/pull/726)
+ - Fix `OpenSSL::SSL::SSLSocket#read_nonblock` clearing the passed String
+ buffer when nothing can be read from the connection.
+ [[GitHub #739]](https://github.com/ruby/openssl/pull/739)
+* Add `#to_text` methods to `OpenSSL::Timestamp::Response`,
+ `OpenSSL::Timestamp::Request`, `OpenSSL::Timestamp::TokenInfo`, and
+ `OpenSSL::PKCS7` to get a human-readable representation of the object.
+ [[GitHub #756]](https://github.com/ruby/openssl/pull/756)
+* Add `OpenSSL::X509::Certificate#tbs_bytes` to get the DER encoding of the
+ TBSCertificate.
+ [[GitHub #753]](https://github.com/ruby/openssl/pull/753)
+* Allow passing `nil` as the digest algorithm to `#sign` methods on
+ `OpenSSL::X509::Certificate`, `OpenSSL::X509::Request`, and
+ `OpenSSL::X509::CRL`. This adds supports for signing with EdDSA keys.
+ [[GitHub #761]](https://github.com/ruby/openssl/pull/761)
+ [[GitHub #804]](https://github.com/ruby/openssl/pull/804)
+* Add `OpenSSL::SSL::SSLSocket#readbyte`.
+ [[GitHub #771]](https://github.com/ruby/openssl/pull/771)
+* Change `OpenSSL::X509::Store#time=` to set the time to the `X509_VERIFY_PARAM`
+ in the `X509_STORE`. This allows `OpenSSL::Timestamp::Response#verify` to
+ verify a signature with the specified timestamp.
+ [[GitHub #770]](https://github.com/ruby/openssl/pull/770)
+* Make `OpenSSL::PKCS7.encrypt`'s third parameter `cipher` mandatory. It had
+ an undocumented default value "RC2-40-CBC", which is not only insecure, but
+ also not supported in OpenSSL 3.0 or later.
+ [[GitHub #796]](https://github.com/ruby/openssl/pull/796)
+* Make `OpenSSL::BN` shareable between ractors when frozen.
+ [[GitHub #808]](https://github.com/ruby/openssl/pull/808)
+* Make `OpenSSL::Config` instances frozen by default, and make it shareable
+ between ractors. `OpenSSL::Config::DEFAULT_CONFIG_FILE` is also frozen.
+ [[GitHub #809]](https://github.com/ruby/openssl/pull/809)
+* Add `OpenSSL::PKCS12#set_mac` to configure the MAC parameters and recalculate
+ a MAC for the content.
+ [[GitHub #788]](https://github.com/ruby/openssl/pull/788)
+
+And various non-user-visible changes and bug fixes. Please see the commit
+history for more details.
+
+
+Version 3.2.4
+=============
+
+Notable changes
+---------------
+
+* Add support for OpenSSL 4.0.
+ [[GitHub #1051]](https://github.com/ruby/openssl/pull/1051)
+
+
+Version 3.2.3
+=============
+
+Merged changes in 3.1.3.
+
+
+Version 3.2.2
+=============
+
+Merged changes in 3.1.2.
+
+
+Version 3.2.1
+=============
+
+Merged changes in 3.0.3.
+
+
+Version 3.2.0
+=============
+
+Compatibility
+-------------
+
+* Ruby >= 2.7
+ - Support for Ruby 2.6 has been removed. Note that Ruby 2.6 reached the
+ end-of-life in 2022-04.
+ [[GitHub #639]](https://github.com/ruby/openssl/pull/639)
+* OpenSSL >= 1.0.2 or LibreSSL >= 3.1
+
+Notable changes
+---------------
+
+* Add a stub gemspec for JRuby, which depends on the `jruby-openssl` gem.
+ [[GitHub #598]](https://github.com/ruby/openssl/pull/598)
+* Add support for the FIPS module in OpenSSL 3.0/3.1.
+ [[GitHub #608]](https://github.com/ruby/openssl/pull/608)
+* Rework `OpenSSL::PKey` routines for loading DER or PEM encoded keys for better
+ compatibility with OpenSSL 3.0/3.1 with the FIPS module.
+ [[GitHub #615]](https://github.com/ruby/openssl/pull/615)
+ [[GitHub #669]](https://github.com/ruby/openssl/pull/669)
+* Add `OpenSSL::Provider` module for loading and unloading OpenSSL 3 providers.
+ [[GitHub #635]](https://github.com/ruby/openssl/pull/635)
+* Add `OpenSSL::PKey.new_raw_private_key`, `.new_raw_public_key`,
+ `OpenSSL::PKey::PKey#raw_private_key`, and `#raw_public_key` for public key
+ algorithms that use "raw private/public key", such as X25519 and Ed25519.
+ [[GitHub #646]](https://github.com/ruby/openssl/pull/646)
+* Improve OpenSSL error messages to include additional information when
+ it is available in OpenSSL's error queue.
+ [[GitHub #648]](https://github.com/ruby/openssl/pull/648)
+* Change `OpenSSL::SSL::SSLContext#ca_file=` and `#ca_path=` to raise
+ `OpenSSL::SSL::SSLError` instead of printing a warning message.
+ [[GitHub #659]](https://github.com/ruby/openssl/pull/659)
+* Allow `OpenSSL::X509::ExtensionFactory#create_extension` to take OIDs in the
+ dotted-decimal notation.
+ [[GitHub #141]](https://github.com/ruby/openssl/pull/141)
+
+
+Version 3.1.3
+=============
+
+Bug fixes
+---------
+
+* Fix missing NULL check for `EVP_PKEY_get0()` functions with OpenSSL 3.x.
+ [[GitHub #957]](https://github.com/ruby/openssl/pull/957)
+
+
+Version 3.1.2
+=============
+
+Bug fixes
+---------
+
+* Fix crash when attempting to export an incomplete `OpenSSL::PKey::DSA` key.
+ [[GitHub #845]](https://github.com/ruby/openssl/issues/845)
+ [[GitHub #847]](https://github.com/ruby/openssl/pull/847)
+* Remove the `OpenSSL::X509::V_FLAG_CRL_CHECK_ALL` flag from the default store
+ used by `OpenSSL::SSL::SSLContext#set_params`. It causes certificate
+ verification to fail with OpenSSL 3.6.0. It has no effect with any other
+ OpenSSL versions.
+ [[GitHub #949]](https://github.com/ruby/openssl/issues/949)
+ [[GitHub #950]](https://github.com/ruby/openssl/pull/950)
+
+
+Version 3.1.1
+=============
+
+Merged changes in 3.0.3.
+
+
+Version 3.1.0
+=============
+
+Ruby/OpenSSL 3.1 will be maintained for the lifetime of Ruby 3.2.
+
+Merged bug fixes in 2.2.3 and 3.0.2. Among the new features and changes are:
+
+Notable changes
+---------------
+
+* Add `OpenSSL::SSL::SSLContext#ciphersuites=` to allow setting TLS 1.3 cipher
+ suites.
+ [[GitHub #493]](https://github.com/ruby/openssl/pull/493)
+* Add `OpenSSL::SSL::SSLSocket#export_keying_material` for exporting keying
+ material of the session, as defined in RFC 5705.
+ [[GitHub #530]](https://github.com/ruby/openssl/pull/530)
+* Add `OpenSSL::SSL::SSLContext#keylog_cb=` for setting the TLS key logging
+ callback, which is useful for supporting NSS's SSLKEYLOGFILE debugging output.
+ [[GitHub #536]](https://github.com/ruby/openssl/pull/536)
+* Remove the default digest algorithm from `OpenSSL::OCSP::BasicResponse#sign`
+ and `OpenSSL::OCSP::Request#sign`. Omitting the 5th parameter of these
+ methods used to be equivalent of specifying SHA-1. This default value is now
+ removed and we will let the underlying OpenSSL library decide instead.
+ [[GitHub #507]](https://github.com/ruby/openssl/pull/507)
+* Add `OpenSSL::BN#mod_sqrt`.
+ [[GitHub #553]](https://github.com/ruby/openssl/pull/553)
+* Allow calling `OpenSSL::Cipher#update` with an empty string. This was
+ prohibited to workaround an ancient bug in OpenSSL.
+ [[GitHub #568]](https://github.com/ruby/openssl/pull/568)
+* Fix build on platforms without socket support, such as WASI. `OpenSSL::SSL`
+ will not be defined if OpenSSL is compiled with `OPENSSL_NO_SOCK`.
+ [[GitHub #558]](https://github.com/ruby/openssl/pull/558)
+* Improve support for recent LibreSSL versions. This includes HKDF support in
+ LibreSSL 3.6 and Ed25519 support in LibreSSL 3.7.
+
+
+Version 3.0.3
+=============
+
+Bug fixes
+---------
+
+* Fix a performance regression introduced in v2.1.3 on a buffered write to
+ `SSLSocket`.
+ [[GitHub #706]](https://github.com/ruby/openssl/pull/706)
+* Fix `OpenSSL::PKCS7` to handle PKCS#7 structures without content.
+ [[GitHub #690]](https://github.com/ruby/openssl/pull/690)
+ [[GitHub #752]](https://github.com/ruby/openssl/pull/752)
+* Fix `OpenSSL::ASN1::ObjectId#==` with OIDs without a known name.
+ [[GitHub #791]](https://github.com/ruby/openssl/issues/791)
+ [[GitHub #792]](https://github.com/ruby/openssl/pull/792)
+* Fix `OpenSSL::X509::Certificate#crl_uris` to handle CDP with multiple CRL
+ URIs.
+ [[GitHub #775]](https://github.com/ruby/openssl/issues/775)
+ [[GitHub #776]](https://github.com/ruby/openssl/pull/776)
+* Fix `OpenSSL::Cipher#update` to always make the output buffer `String`
+ independent.
+ [[Bug #20937]](https://bugs.ruby-lang.org/issues/20937)
+ [[GitHub #824]](https://github.com/ruby/openssl/pull/824)
+
+
+Version 3.0.2
+=============
+
+Merged changes in 2.2.3. Additionally, the following issues are fixed by this
+release.
+
+Bug fixes
+---------
+
+* Fix OpenSSL::PKey::EC#check_key not working correctly on OpenSSL 3.0.
+ [[GitHub #563]](https://github.com/ruby/openssl/issues/563)
+ [[GitHub #580]](https://github.com/ruby/openssl/pull/580)
+
+
+Version 3.0.1
+=============
+
+Merged changes in 2.1.4 and 2.2.2. Additionally, the following issues are fixed
+by this release.
+
+Bug fixes
+---------
+
+* Add missing type check in OpenSSL::PKey::PKey#sign's optional parameters.
+ [[GitHub #531]](https://github.com/ruby/openssl/pull/531)
+* Work around OpenSSL 3.0's HMAC issues with a zero-length key.
+ [[GitHub #538]](https://github.com/ruby/openssl/pull/538)
+* Fix a regression in OpenSSL::PKey::DSA.generate's default of 'q' size.
+ [[GitHub #483]](https://github.com/ruby/openssl/issues/483)
+ [[GitHub #539]](https://github.com/ruby/openssl/pull/539)
+* Restore OpenSSL::PKey.read's ability to decode "openssl ecparam -genkey"
+ output when linked against OpenSSL 3.0.
+ [[GitHub #535]](https://github.com/ruby/openssl/pull/535)
+ [[GitHub #540]](https://github.com/ruby/openssl/pull/540)
+* Restore error checks in OpenSSL::PKey::EC#{to_der,to_pem}.
+ [[GitHub #541]](https://github.com/ruby/openssl/pull/541)
+
+
+Version 3.0.0
+=============
+
+Compatibility notes
+-------------------
+
+* OpenSSL 1.0.1 and Ruby 2.3-2.5 are no longer supported.
+ [[GitHub #396]](https://github.com/ruby/openssl/pull/396)
+ [[GitHub #466]](https://github.com/ruby/openssl/pull/466)
+
+* OpenSSL 3.0 support is added. It is the first major version bump from OpenSSL
+ 1.1 and contains incompatible changes that affect Ruby/OpenSSL.
+ Note that OpenSSL 3.0 support is preliminary and not all features are
+ currently available:
+ [[GitHub #369]](https://github.com/ruby/openssl/issues/369)
+
+ - Deprecate the ability to modify `OpenSSL::PKey::PKey` instances. OpenSSL 3.0
+ made EVP_PKEY structure immutable, and hence the following methods are not
+ available when Ruby/OpenSSL is linked against OpenSSL 3.0.
+ [[GitHub #480]](https://github.com/ruby/openssl/pull/480)
+
+ - `OpenSSL::PKey::RSA#set_key`, `#set_factors`, `#set_crt_params`
+ - `OpenSSL::PKey::DSA#set_pqg`, `#set_key`
+ - `OpenSSL::PKey::DH#set_pqg`, `#set_key`, `#generate_key!`
+ - `OpenSSL::PKey::EC#private_key=`, `#public_key=`, `#group=`, `#generate_key!`
+
+ - Deprecate `OpenSSL::Engine`. The ENGINE API has been deprecated in OpenSSL 3.0
+ in favor of the new "provider" concept and will be removed in a future
+ version.
+ [[GitHub #481]](https://github.com/ruby/openssl/pull/481)
+
+* `OpenSSL::SSL::SSLContext#tmp_ecdh_callback` has been removed. It has been
+ deprecated since v2.0.0 because it is incompatible with modern OpenSSL
+ versions.
+ [[GitHub #394]](https://github.com/ruby/openssl/pull/394)
+
+* `OpenSSL::SSL::SSLSocket#read` and `#write` now raise `OpenSSL::SSL::SSLError`
+ if called before a TLS connection is established. Historically, they
+ read/wrote unencrypted data to the underlying socket directly in that case.
+ [[GitHub #9]](https://github.com/ruby/openssl/issues/9)
+ [[GitHub #469]](https://github.com/ruby/openssl/pull/469)
+
+
+Notable changes
+---------------
+
+* Enhance OpenSSL::PKey's common interface.
+ [[GitHub #370]](https://github.com/ruby/openssl/issues/370)
+
+ - Key deserialization: Enhance `OpenSSL::PKey.read` to handle PEM encoding of
+ DH parameters, which used to be only deserialized by `OpenSSL::PKey::DH.new`.
+ [[GitHub #328]](https://github.com/ruby/openssl/issues/328)
+ - Key generation: Add `OpenSSL::PKey.generate_parameters` and
+ `OpenSSL::PKey.generate_key`.
+ [[GitHub #329]](https://github.com/ruby/openssl/issues/329)
+ - Public key signing: Enhance `OpenSSL::PKey::PKey#sign` and `#verify` to use
+ the new EVP_DigestSign() family to enable PureEdDSA support on OpenSSL 1.1.1
+ or later. They also now take optional algorithm-specific parameters for more
+ control.
+ [[GitHub #329]](https://github.com/ruby/openssl/issues/329)
+ - Low-level public key signing and verification: Add
+ `OpenSSL::PKey::PKey#sign_raw`, `#verify_raw`, and `#verify_recover`.
+ [[GitHub #382]](https://github.com/ruby/openssl/issues/382)
+ - Public key encryption: Add `OpenSSL::PKey::PKey#encrypt` and `#decrypt`.
+ [[GitHub #382]](https://github.com/ruby/openssl/issues/382)
+ - Key agreement: Add `OpenSSL::PKey::PKey#derive`.
+ [[GitHub #329]](https://github.com/ruby/openssl/issues/329)
+ - Key comparison: Add `OpenSSL::PKey::PKey#compare?` to conveniently check
+ that two keys have common parameters and a public key.
+ [[GitHub #383]](https://github.com/ruby/openssl/issues/383)
+
+* Add `OpenSSL::BN#set_flags` and `#get_flags`. This can be used in combination
+ with `OpenSSL::BN::CONSTTIME` to force constant-time computation.
+ [[GitHub #417]](https://github.com/ruby/openssl/issues/417)
+
+* Add `OpenSSL::BN#abs` to get the absolute value of the BIGNUM.
+ [[GitHub #430]](https://github.com/ruby/openssl/issues/430)
+
+* Add `OpenSSL::SSL::SSLSocket#getbyte`.
+ [[GitHub #438]](https://github.com/ruby/openssl/issues/438)
+
+* Add `OpenSSL::SSL::SSLContext#tmp_dh=`.
+ [[GitHub #459]](https://github.com/ruby/openssl/pull/459)
+
+* Add `OpenSSL::X509::Certificate.load` to load a PEM-encoded and concatenated
+ list of X.509 certificates at once.
+ [[GitHub #441]](https://github.com/ruby/openssl/pull/441)
+
+* Change `OpenSSL::X509::Certificate.new` to attempt to deserialize the given
+ string first as DER encoding first and then as PEM encoding to ensure the
+ round-trip consistency.
+ [[GitHub #442]](https://github.com/ruby/openssl/pull/442)
+
+* Update various part of the code base to use the modern API. No breaking
+ changes are intended with this. This includes:
+
+ - `OpenSSL::HMAC` uses the EVP API.
+ [[GitHub #371]](https://github.com/ruby/openssl/issues/371)
+ - `OpenSSL::Config` uses native OpenSSL API to parse config files.
+ [[GitHub #342]](https://github.com/ruby/openssl/issues/342)
+
+
+Version 2.2.3
+=============
+
+Bug fixes
+---------
+
+* Fix serveral methods in OpenSSL::PKey::EC::Point attempting to raise an error
+ with an incorrect class, which would end up with a TypeError.
+ [[GitHub #570]](https://github.com/ruby/openssl/pull/570)
+* Fix OpenSSL::PKey::EC::Point#eql? and OpenSSL::PKey::EC::Group#eql?
+ incorrectly treated OpenSSL's internal errors as "not equal".
+ [[GitHub #564]](https://github.com/ruby/openssl/pull/564)
+* Fix build with LibreSSL 3.5 or later.
+
+
+Version 2.2.2
+=============
+
+Merged changes in 2.1.4.
+
+
+Version 2.2.1
+=============
+
+Merged changes in 2.1.3. Additionally, the following issues are fixed by this
+release.
+
+Bug fixes
+---------
+
+* Fix crash in `OpenSSL::Timestamp::{Request,Response,TokenInfo}.new` when
+ invalid arguments are given.
+ [[GitHub #407]](https://github.com/ruby/openssl/pull/407)
+* Fix `OpenSSL::Timestamp::Factory#create_timestamp` with LibreSSL on platforms
+ where `time_t` has a different size from `long`.
+ [[GitHub #454]](https://github.com/ruby/openssl/pull/454)
+
+
+Version 2.2.0
+=============
+
+Compatibility notes
+-------------------
+
+* Remove unsupported MDC2, DSS, DSS1, and SHA algorithms.
+* Remove `OpenSSL::PKCS7::SignerInfo#name` alias for `#issuer`.
+ [[GitHub #266]](https://github.com/ruby/openssl/pull/266)
+* Deprecate `OpenSSL::Config#add_value` and `#[]=` for future removal.
+ [[GitHub #322]](https://github.com/ruby/openssl/pull/322)
+
+
+Notable changes
+---------------
+
+* Change default `OpenSSL::SSL::SSLServer#listen` backlog argument from
+ 5 to `Socket::SOMAXCONN`.
+ [[GitHub #286]](https://github.com/ruby/openssl/issues/286)
+* Make `OpenSSL::HMAC#==` use a timing safe string comparison.
+ [[GitHub #284]](https://github.com/ruby/openssl/pull/284)
+* Add support for SHA3 and BLAKE digests.
+ [[GitHub #282]](https://github.com/ruby/openssl/pull/282)
+* Add `OpenSSL::SSL::SSLSocket.open` for opening a `TCPSocket` and
+ returning an `OpenSSL::SSL::SSLSocket` for it.
+ [[GitHub #225]](https://github.com/ruby/openssl/issues/225)
+* Support marshalling of `OpenSSL::X509` and `OpenSSL::PKey` objects.
+ [[GitHub #281]](https://github.com/ruby/openssl/pull/281)
+ [[GitHub #363]](https://github.com/ruby/openssl/pull/363)
+* Add `OpenSSL.secure_compare` for timing safe string comparison for
+ strings of possibly unequal length.
+ [[GitHub #280]](https://github.com/ruby/openssl/pull/280)
+* Add `OpenSSL.fixed_length_secure_compare` for timing safe string
+ comparison for strings of equal length.
+ [[GitHub #269]](https://github.com/ruby/openssl/pull/269)
+* Add `OpenSSL::SSL::SSLSocket#{finished_message,peer_finished_message}`
+ for last finished message sent and received.
+ [[GitHub #250]](https://github.com/ruby/openssl/pull/250)
+* Add `OpenSSL::Timestamp` module for handing timestamp requests and
+ responses.
+ [[GitHub #204]](https://github.com/ruby/openssl/pull/204)
+* Add helper methods for `OpenSSL::X509::Certificate`:
+ `find_extension`, `subject_key_identifier`,
+ `authority_key_identifier`, `crl_uris`, `ca_issuer_uris` and
+ `ocsp_uris`, and for `OpenSSL::X509::CRL`:
+ `find_extension` and `subject_key_identifier`.
+ [[GitHub #260]](https://github.com/ruby/openssl/pull/260)
+ [[GitHub #275]](https://github.com/ruby/openssl/pull/275)
+ [[GitHub #293]](https://github.com/ruby/openssl/pull/293)
+* Add `OpenSSL::ECPoint#add` for performing elliptic curve point addition.
+ [[GitHub #261]](https://github.com/ruby/openssl/pull/261)
+* Make `OpenSSL::PKey::RSA#{export,to_der}` check `key`, `factors`, and
+ `crt_params` to do proper private key serialization.
+ [[GitHub #258]](https://github.com/ruby/openssl/pull/258)
+* Add `OpenSSL::SSL::{SSLSocket,SSLServer}#fileno`, returning the
+ underlying socket file descriptor number.
+ [[GitHub #247]](https://github.com/ruby/openssl/pull/247)
+* Support client certificates with TLS 1.3, and support post-handshake
+ authentication with OpenSSL 1.1.1+.
+ [[GitHub #239]](https://github.com/ruby/openssl/pull/239)
+* Add `OpenSSL::ASN1::ObjectId#==` for equality testing.
+* Add `OpenSSL::X509::Extension#value_der` for the raw value of
+ the extension.
+ [[GitHub #234]](https://github.com/ruby/openssl/pull/234)
+* Significantly reduce allocated memory in `OpenSSL::Buffering#do_write`.
+ [[GitHub #212]](https://github.com/ruby/openssl/pull/212)
+* Ensure all valid IPv6 addresses are considered valid as elements
+ of subjectAlternativeName in certificates.
+ [[GitHub #185]](https://github.com/ruby/openssl/pull/185)
+* Allow recipient's certificate to be omitted in PCKS7#decrypt.
+ [[GitHub #183]](https://github.com/ruby/openssl/pull/183)
+* Add support for reading keys in PKCS #8 format and export via instance methods
+ added to `OpenSSL::PKey` classes: `private_to_der`, `private_to_pem`,
+ `public_to_der` and `public_to_pem`.
+ [[GitHub #297]](https://github.com/ruby/openssl/pull/297)
+
+
+Version 2.1.4
+=============
+
+Bug fixes
+---------
+
+* Do not use pkg-config if --with-openssl-dir option is specified.
+ [[GitHub #486]](https://github.com/ruby/openssl/pull/486)
+
+
+Version 2.1.3
+=============
+
+Bug fixes
+---------
+
+* Fix deprecation warnings on Ruby 3.0.
+* Add ".include" directive support in `OpenSSL::Config`.
+ [[GitHub #216]](https://github.com/ruby/openssl/pull/216)
+* Fix handling of IPv6 address SANs.
+ [[GitHub #185]](https://github.com/ruby/openssl/pull/185)
+* Hostname verification failure with `OpenSSL::SSL::SSLContext#verify_hostname=`
+ sets a proper error code.
+ [[GitHub #350]](https://github.com/ruby/openssl/pull/350)
+* Fix crash with `OpenSSL::BN.new(nil, 2)`.
+ [[Bug #15760]](https://bugs.ruby-lang.org/issues/15760)
+* `OpenSSL::SSL::SSLSocket#sys{read,write}` prevent internal string buffers from
+ being modified by another thread.
+ [[GitHub #453]](https://github.com/ruby/openssl/pull/453)
+* Fix misuse of input record separator in `OpenSSL::Buffering` where it was
+ for output.
+* Fix wrong integer casting in `OpenSSL::PKey::EC#dsa_verify_asn1`.
+ [[GitHub #460]](https://github.com/ruby/openssl/pull/460)
+* `extconf.rb` explicitly checks that OpenSSL's version number is 1.0.1 or
+ newer but also less than 3.0. Ruby/OpenSSL v2.1.x and v2.2.x will not support
+ OpenSSL 3.0 API.
+ [[GitHub #458]](https://github.com/ruby/openssl/pull/458)
+* Activate `digest` gem correctly. `digest` library could go into an
+ inconsistent state if there are multiple versions of `digest` is installed
+ and `openssl` is `require`d before `digest`.
+ [[GitHub #463]](https://github.com/ruby/openssl/pull/463)
+* Fix GC.compact compatibility.
+ [[GitHub #464]](https://github.com/ruby/openssl/issues/464)
+ [[GitHub #465]](https://github.com/ruby/openssl/pull/465)
+
+
+Version 2.1.2
+=============
+
+Merged changes in 2.0.9.
+
+
+Version 2.1.1
+=============
+
+Merged changes in 2.0.8.
+
+
+Version 2.1.0
+=============
+
+Notable changes
+---------------
+
+* Support for OpenSSL versions before 1.0.1 and LibreSSL versions before 2.5
+ is removed.
+ [[GitHub #86]](https://github.com/ruby/openssl/pull/86)
+* OpenSSL::BN#negative?, #+@, and #-@ are added.
+* OpenSSL::SSL::SSLSocket#connect raises a more informative exception when
+ certificate verification fails.
+ [[GitHub #99]](https://github.com/ruby/openssl/pull/99)
+* OpenSSL::KDF module is newly added. In addition to PBKDF2-HMAC that has moved
+ from OpenSSL::PKCS5, scrypt and HKDF are supported.
+ [[GitHub #109]](https://github.com/ruby/openssl/pull/109)
+ [[GitHub #173]](https://github.com/ruby/openssl/pull/173)
+* OpenSSL.fips_mode is added. We had the setter, but not the getter.
+ [[GitHub #125]](https://github.com/ruby/openssl/pull/125)
+* OpenSSL::OCSP::Request#signed? is added.
+* OpenSSL::ASN1 handles the indefinite length form better. OpenSSL::ASN1.decode
+ no longer wrongly treats the end-of-contents octets as part of the content.
+ OpenSSL::ASN1::ASN1Data#infinite_length is renamed to #indefinite_length.
+ [[GitHub #98]](https://github.com/ruby/openssl/pull/98)
+* OpenSSL::X509::Name#add_entry now accepts two additional keyword arguments
+ 'loc' and 'set'.
+ [[GitHub #94]](https://github.com/ruby/openssl/issues/94)
+* OpenSSL::SSL::SSLContext#min_version= and #max_version= are added to replace
+ #ssl_version= that was built on top of the deprecated OpenSSL C API. Use of
+ that method and the constant OpenSSL::SSL::SSLContext::METHODS is now
+ deprecated.
+ [[GitHub #142]](https://github.com/ruby/openssl/pull/142)
+* OpenSSL::X509::Name#to_utf8 is added.
+ [[GitHub #26]](https://github.com/ruby/openssl/issues/26)
+ [[GitHub #143]](https://github.com/ruby/openssl/pull/143)
+* OpenSSL::X509::{Extension,Attribute,Certificate,CRL,Revoked,Request} can be
+ compared with == operator.
+ [[GitHub #161]](https://github.com/ruby/openssl/pull/161)
+* TLS Fallback Signaling Cipher Suite Value (SCSV) support is added.
+ [[GitHub #165]](https://github.com/ruby/openssl/pull/165)
+* Build failure with OpenSSL 1.1 built with no-deprecated is fixed.
+ [[GitHub #160]](https://github.com/ruby/openssl/pull/160)
+* OpenSSL::Buffering#write accepts an arbitrary number of arguments.
+ [[Feature #9323]](https://bugs.ruby-lang.org/issues/9323)
+ [[GitHub #162]](https://github.com/ruby/openssl/pull/162)
+* OpenSSL::PKey::RSA#sign_pss and #verify_pss are added. They perform RSA-PSS
+ signature and verification.
+ [[GitHub #75]](https://github.com/ruby/openssl/issues/75)
+ [[GitHub #76]](https://github.com/ruby/openssl/pull/76)
+ [[GitHub #169]](https://github.com/ruby/openssl/pull/169)
+* OpenSSL::SSL::SSLContext#add_certificate is added.
+ [[GitHub #167]](https://github.com/ruby/openssl/pull/167)
+* OpenSSL::PKey::EC::Point#to_octet_string is added.
+ OpenSSL::PKey::EC::Point.new can now take String as the second argument.
+ [[GitHub #177]](https://github.com/ruby/openssl/pull/177)
+
+
+Version 2.0.9
+=============
+
+Security fixes
+--------------
+
+* OpenSSL::X509::Name#<=> could incorrectly return 0 (= equal) for non-equal
+ objects. CVE-2018-16395 is assigned for this issue.
+ https://hackerone.com/reports/387250
+
+Bug fixes
+---------
+
+* Fixed OpenSSL::PKey::\*.{new,generate} immediately aborting if the thread is
+ interrupted.
+ [[Bug #14882]](https://bugs.ruby-lang.org/issues/14882)
+ [[GitHub #205]](https://github.com/ruby/openssl/pull/205)
+* Fixed OpenSSL::X509::Name#to_s failing with OpenSSL::X509::NameError if
+ called against an empty instance.
+ [[GitHub #200]](https://github.com/ruby/openssl/issues/200)
+ [[GitHub #211]](https://github.com/ruby/openssl/pull/211)
+
+
+Version 2.0.8
+=============
+
+Bug fixes
+---------
+
+* OpenSSL::Cipher#pkcs5_keyivgen raises an error when a negative iteration
+ count is given.
+ [[GitHub #184]](https://github.com/ruby/openssl/pull/184)
+* Fixed build with LibreSSL 2.7.
+ [[GitHub #192]](https://github.com/ruby/openssl/issues/192)
+ [[GitHub #193]](https://github.com/ruby/openssl/pull/193)
+
+
+Version 2.0.7
+=============
+
+Bug fixes
+---------
+
+* OpenSSL::Cipher#auth_data= could segfault if called against a non-AEAD cipher.
+ [[Bug #14024]](https://bugs.ruby-lang.org/issues/14024)
+* OpenSSL::X509::Certificate#public_key= (and similar methods) could segfault
+ when an instance of OpenSSL::PKey::PKey with no public key components is
+ passed.
+ [[Bug #14087]](https://bugs.ruby-lang.org/issues/14087)
+ [[GitHub #168]](https://github.com/ruby/openssl/pull/168)
+
+
+Version 2.0.6
+=============
+
+Bug fixes
+---------
+
+* The session_remove_cb set to an OpenSSL::SSL::SSLContext is no longer called
+ during GC.
+* A possible deadlock in OpenSSL::SSL::SSLSocket#sysread is fixed.
+ [[GitHub #139]](https://github.com/ruby/openssl/pull/139)
+* OpenSSL::BN#hash could return an unnormalized fixnum value on Windows.
+ [[Bug #13877]](https://bugs.ruby-lang.org/issues/13877)
+* OpenSSL::SSL::SSLSocket#sysread and #sysread_nonblock set the length of the
+ destination buffer String to 0 on error.
+ [[GitHub #153]](https://github.com/ruby/openssl/pull/153)
+* Possible deadlock is fixed. This happened only when built with older versions
+ of OpenSSL (before 1.1.0) or LibreSSL.
+ [[GitHub #155]](https://github.com/ruby/openssl/pull/155)
+
+
+Version 2.0.5
+=============
+
+Bug fixes
+---------
+
+* Reading a PEM/DER-encoded private key or certificate from an IO object did
+ not work properly on mswin platforms.
+ [[ruby/openssl#128]](https://github.com/ruby/openssl/issues/128)
+* Broken length check in the PEM passphrase callback is fixed.
+* It failed to compile when OpenSSL is configured without TLS 1.0 support.
+
+
+Version 2.0.4
+=============
+
+Bug fixes
+---------
+
+* It now compiles with LibreSSL without renaming on Windows (mswin).
+* A workaround for the error queue leak of X509_load_cert_crl_file() that
+ causes random errors is added.
+ [[Bug #11033]](https://bugs.ruby-lang.org/issues/11033)
+
+
+Version 2.0.3
+=============
+
+Bug fixes
+---------
+
+* OpenSSL::ASN1::Constructive#each which was broken by 2.0.0 is fixed.
+ [[ruby/openssl#96]](https://github.com/ruby/openssl/pull/96)
+* Fixed build with static OpenSSL libraries on Windows.
+ [[Bug #13080]](https://bugs.ruby-lang.org/issues/13080)
+* OpenSSL::X509::Name#eql? which was broken by 2.0.0 is fixed.
+
+
+Version 2.0.2
+=============
+
+Bug fixes
+---------
+
+* Fix build with early 0.9.8 series which did not have SSL_CTX_clear_options().
+ [ruby-core:78693]
+
+
+Version 2.0.1
+=============
+
+Bug fixes
+---------
+
+* A GC issue around OpenSSL::BN is fixed.
+ [[ruby/openssl#87]](https://github.com/ruby/openssl/issues/87)
+* OpenSSL::ASN1 now parses BER encoding of GeneralizedTime without seconds.
+ [[ruby/openssl#88]](https://github.com/ruby/openssl/pull/88)
+
+
+Version 2.0.0
+=============
+
+This is the first release of openssl gem, formerly a standard library of Ruby,
+ext/openssl. This is the successor of the version included in Ruby 2.3.
+
+Compatibility notes
+-------------------
+
+* Support for OpenSSL version 0.9.6 and 0.9.7 is completely removed. openssl gem
+ still works with OpenSSL 0.9.8, but users are strongly encouraged to upgrade
+ to at least 1.0.1, as OpenSSL < 1.0.1 will not receive any security fixes from
+ the OpenSSL development team.
+
+Supported platforms
+-------------------
+
+* OpenSSL 1.0.0, 1.0.1, 1.0.2, 1.1.0
+* OpenSSL < 0.9.8 is no longer supported.
+* LibreSSL 2.3, 2.4, 2.5
+* Ruby 2.3, 2.4
+
+Notable changes
+---------------
+
+* Add support for OpenSSL 1.1.0.
+ [[Feature #12324]](https://bugs.ruby-lang.org/issues/12324)
+* Add support for LibreSSL
+
+* OpenSSL::Cipher
+
+ - OpenSSL::Cipher#key= and #iv= reject too long inputs. They used to truncate
+ silently. [[Bug #12561]](https://bugs.ruby-lang.org/issues/12561)
+
+ - OpenSSL::Cipher#iv_len= is added. It allows changing IV (nonce) length if
+ using AEAD ciphers.
+ [[Bug #8667]](https://bugs.ruby-lang.org/issues/8667),
+ [[Bug #10420]](https://bugs.ruby-lang.org/issues/10420),
+ [[GH ruby/ruby#569]](https://github.com/ruby/ruby/pull/569),
+ [[GH ruby/openssl#58]](https://github.com/ruby/openssl/pull/58)
+
+ - OpenSSL::Cipher#auth_tag_len= is added. This sets the authentication tag
+ length to be generated by an AEAD cipher.
+
+* OpenSSL::OCSP
+
+ - Accessor methods are added to OpenSSL::OCSP::CertificateId.
+ [[Feature #7181]](https://bugs.ruby-lang.org/issues/7181)
+
+ - OpenSSL::OCSP::Request and BasicResponse can be signed with non-SHA-1 hash
+ algorithm. [[Feature #11552]](https://bugs.ruby-lang.org/issues/11552)
+
+ - OpenSSL::OCSP::CertificateId and BasicResponse can be encoded into DER.
+
+ - A new class OpenSSL::OCSP::SingleResponse is added for convenience.
+
+ - OpenSSL::OCSP::BasicResponse#add_status accepts absolute times. They used to
+ accept only relative seconds from the current time.
+
+* OpenSSL::PKey
+
+ - OpenSSL::PKey::EC follows the general PKey interface.
+ [[Bug #6567]](https://bugs.ruby-lang.org/issues/6567)
+
+ - OpenSSL::PKey.read raises OpenSSL::PKey::PKeyError instead of ArgumentError
+ for consistency with OpenSSL::PKey::{DH,DSA,RSA,EC}#new.
+ [[Bug #11774]](https://bugs.ruby-lang.org/issues/11774),
+ [[GH ruby/openssl#55]](https://github.com/ruby/openssl/pull/55)
+
+ - OpenSSL::PKey::EC::Group retrieved by OpenSSL::PKey::EC#group is no longer
+ linked with the EC key. Modifications to the EC::Group have no effect on the
+ key. [[GH ruby/openssl#71]](https://github.com/ruby/openssl/pull/71)
+
+ - OpenSSL::PKey::EC::Point#to_bn allows specifying the point conversion form
+ by the optional argument.
+
+* OpenSSL::SSL
+
+ - OpenSSL::SSL::SSLSocket#tmp_key is added. A client can call it after the
+ connection is established to retrieve the ephemeral key.
+ [[GH ruby/ruby#1318]](https://github.com/ruby/ruby/pull/1318)
+
+ - The automatic ephemeral ECDH curve selection is enabled by default when
+ built with OpenSSL >= 1.0.2 or LibreSSL.
+
+ - OpenSSL::SSL::SSLContext#security_level= is added. You can set the "security
+ level" of the SSL context. This is effective only when built with OpenSSL
+ 1.1.0.
+
+ - A new option 'verify_hostname' is added to OpenSSL::SSL::SSLContext. When it
+ is enabled, and the SNI hostname is also set, the hostname verification on
+ the server certificate is automatically performed. It is now enabled by
+ OpenSSL::SSL::SSLContext#set_params.
+ [[GH ruby/openssl#60]](https://github.com/ruby/openssl/pull/60)
+
+Removals
+--------
+
+* OpenSSL::Engine
+
+ - OpenSSL::Engine.cleanup does nothing when built with OpenSSL 1.1.0.
+
+* OpenSSL::SSL
+
+ - OpenSSL::PKey::DH::DEFAULT_512 is removed. Hence servers no longer use
+ 512-bit DH group by default. It is considered too weak nowadays.
+ [[Bug #11968]](https://bugs.ruby-lang.org/issues/11968),
+ [[GH ruby/ruby#1196]](https://github.com/ruby/ruby/pull/1196)
+
+ - RC4 cipher suites are removed from OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.
+ RC4 is now considered to be weak.
+ [[GH ruby/openssl#50]](https://github.com/ruby/openssl/pull/50)
+
+Deprecations
+------------
+
+* OpenSSL::PKey
+
+ - OpenSSL::PKey::RSA#n=, #e=, #d=, #p=, #q=, #dmp1=, #dmq1=, #iqmp=,
+ OpenSSL::PKey::DSA#p=, #q=, #g=, #priv_key=, #pub_key=,
+ OpenSSL::PKey::DH#p=, #g=, #priv_key= and #pub_key= are deprecated. They are
+ disabled when built with OpenSSL 1.1.0, due to its API change. Instead,
+ OpenSSL::PKey::RSA#set_key, #set_factors, #set_crt_params,
+ OpenSSL::PKey::DSA#set_pqg, #set_key, OpenSSL::PKey::DH#set_pqg and #set_key
+ are added.
+
+* OpenSSL::Random
+
+ - OpenSSL::Random.pseudo_bytes is deprecated, and not defined when built with
+ OpenSSL 1.1.0. Use OpenSSL::Random.random_bytes instead.
+
+* OpenSSL::SSL
+
+ - OpenSSL::SSL::SSLContext#tmp_ecdh_callback is deprecated, as the underlying
+ API SSL_CTX_set_tmp_ecdh_callback() is removed in OpenSSL 1.1.0. It was
+ first added in Ruby 2.3.0. To specify the curve to be used in ephemeral
+ ECDH, use OpenSSL::SSL::SSLContext#ecdh_curves=. The automatic curve
+ selection is also now enabled by default when built with a capable OpenSSL.
diff --git a/ext/openssl/depend b/ext/openssl/depend
new file mode 100644
index 0000000000..435f4a1c68
--- /dev/null
+++ b/ext/openssl/depend
@@ -0,0 +1,6507 @@
+# AUTOGENERATED DEPENDENCIES START
+openssl_missing.o: $(RUBY_EXTCONF_H)
+openssl_missing.o: $(arch_hdrdir)/ruby/config.h
+openssl_missing.o: openssl_missing.c
+openssl_missing.o: openssl_missing.h
+ossl.o: $(RUBY_EXTCONF_H)
+ossl.o: $(arch_hdrdir)/ruby/config.h
+ossl.o: $(hdrdir)/ruby.h
+ossl.o: $(hdrdir)/ruby/assert.h
+ossl.o: $(hdrdir)/ruby/backward.h
+ossl.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl.o: $(hdrdir)/ruby/defines.h
+ossl.o: $(hdrdir)/ruby/encoding.h
+ossl.o: $(hdrdir)/ruby/intern.h
+ossl.o: $(hdrdir)/ruby/internal/abi.h
+ossl.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl.o: $(hdrdir)/ruby/internal/assume.h
+ossl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl.o: $(hdrdir)/ruby/internal/cast.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl.o: $(hdrdir)/ruby/internal/config.h
+ossl.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl.o: $(hdrdir)/ruby/internal/core.h
+ossl.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl.o: $(hdrdir)/ruby/internal/ctype.h
+ossl.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl.o: $(hdrdir)/ruby/internal/dosish.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl.o: $(hdrdir)/ruby/internal/error.h
+ossl.o: $(hdrdir)/ruby/internal/eval.h
+ossl.o: $(hdrdir)/ruby/internal/event.h
+ossl.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl.o: $(hdrdir)/ruby/internal/gc.h
+ossl.o: $(hdrdir)/ruby/internal/glob.h
+ossl.o: $(hdrdir)/ruby/internal/globals.h
+ossl.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl.o: $(hdrdir)/ruby/internal/iterator.h
+ossl.o: $(hdrdir)/ruby/internal/memory.h
+ossl.o: $(hdrdir)/ruby/internal/method.h
+ossl.o: $(hdrdir)/ruby/internal/module.h
+ossl.o: $(hdrdir)/ruby/internal/newobj.h
+ossl.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl.o: $(hdrdir)/ruby/internal/symbol.h
+ossl.o: $(hdrdir)/ruby/internal/value.h
+ossl.o: $(hdrdir)/ruby/internal/value_type.h
+ossl.o: $(hdrdir)/ruby/internal/variable.h
+ossl.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl.o: $(hdrdir)/ruby/io.h
+ossl.o: $(hdrdir)/ruby/missing.h
+ossl.o: $(hdrdir)/ruby/onigmo.h
+ossl.o: $(hdrdir)/ruby/oniguruma.h
+ossl.o: $(hdrdir)/ruby/ractor.h
+ossl.o: $(hdrdir)/ruby/ruby.h
+ossl.o: $(hdrdir)/ruby/st.h
+ossl.o: $(hdrdir)/ruby/subst.h
+ossl.o: $(hdrdir)/ruby/thread.h
+ossl.o: openssl_missing.h
+ossl.o: ossl.c
+ossl.o: ossl.h
+ossl.o: ossl_asn1.h
+ossl.o: ossl_bio.h
+ossl.o: ossl_bn.h
+ossl.o: ossl_cipher.h
+ossl.o: ossl_config.h
+ossl.o: ossl_digest.h
+ossl.o: ossl_engine.h
+ossl.o: ossl_hmac.h
+ossl.o: ossl_kdf.h
+ossl.o: ossl_ns_spki.h
+ossl.o: ossl_ocsp.h
+ossl.o: ossl_pkcs12.h
+ossl.o: ossl_pkcs7.h
+ossl.o: ossl_pkey.h
+ossl.o: ossl_provider.h
+ossl.o: ossl_rand.h
+ossl.o: ossl_ssl.h
+ossl.o: ossl_ts.h
+ossl.o: ossl_x509.h
+ossl_asn1.o: $(RUBY_EXTCONF_H)
+ossl_asn1.o: $(arch_hdrdir)/ruby/config.h
+ossl_asn1.o: $(hdrdir)/ruby.h
+ossl_asn1.o: $(hdrdir)/ruby/assert.h
+ossl_asn1.o: $(hdrdir)/ruby/backward.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_asn1.o: $(hdrdir)/ruby/defines.h
+ossl_asn1.o: $(hdrdir)/ruby/encoding.h
+ossl_asn1.o: $(hdrdir)/ruby/intern.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/abi.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/assume.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/cast.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/config.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/error.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/eval.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/event.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/gc.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/glob.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/globals.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/memory.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/method.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/module.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/value.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/variable.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_asn1.o: $(hdrdir)/ruby/io.h
+ossl_asn1.o: $(hdrdir)/ruby/missing.h
+ossl_asn1.o: $(hdrdir)/ruby/onigmo.h
+ossl_asn1.o: $(hdrdir)/ruby/oniguruma.h
+ossl_asn1.o: $(hdrdir)/ruby/ractor.h
+ossl_asn1.o: $(hdrdir)/ruby/ruby.h
+ossl_asn1.o: $(hdrdir)/ruby/st.h
+ossl_asn1.o: $(hdrdir)/ruby/subst.h
+ossl_asn1.o: $(hdrdir)/ruby/thread.h
+ossl_asn1.o: openssl_missing.h
+ossl_asn1.o: ossl.h
+ossl_asn1.o: ossl_asn1.c
+ossl_asn1.o: ossl_asn1.h
+ossl_asn1.o: ossl_bio.h
+ossl_asn1.o: ossl_bn.h
+ossl_asn1.o: ossl_cipher.h
+ossl_asn1.o: ossl_config.h
+ossl_asn1.o: ossl_digest.h
+ossl_asn1.o: ossl_engine.h
+ossl_asn1.o: ossl_hmac.h
+ossl_asn1.o: ossl_kdf.h
+ossl_asn1.o: ossl_ns_spki.h
+ossl_asn1.o: ossl_ocsp.h
+ossl_asn1.o: ossl_pkcs12.h
+ossl_asn1.o: ossl_pkcs7.h
+ossl_asn1.o: ossl_pkey.h
+ossl_asn1.o: ossl_provider.h
+ossl_asn1.o: ossl_rand.h
+ossl_asn1.o: ossl_ssl.h
+ossl_asn1.o: ossl_ts.h
+ossl_asn1.o: ossl_x509.h
+ossl_bio.o: $(RUBY_EXTCONF_H)
+ossl_bio.o: $(arch_hdrdir)/ruby/config.h
+ossl_bio.o: $(hdrdir)/ruby.h
+ossl_bio.o: $(hdrdir)/ruby/assert.h
+ossl_bio.o: $(hdrdir)/ruby/backward.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_bio.o: $(hdrdir)/ruby/defines.h
+ossl_bio.o: $(hdrdir)/ruby/encoding.h
+ossl_bio.o: $(hdrdir)/ruby/intern.h
+ossl_bio.o: $(hdrdir)/ruby/internal/abi.h
+ossl_bio.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/assume.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_bio.o: $(hdrdir)/ruby/internal/cast.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_bio.o: $(hdrdir)/ruby/internal/config.h
+ossl_bio.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_bio.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_bio.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_bio.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_bio.o: $(hdrdir)/ruby/internal/error.h
+ossl_bio.o: $(hdrdir)/ruby/internal/eval.h
+ossl_bio.o: $(hdrdir)/ruby/internal/event.h
+ossl_bio.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_bio.o: $(hdrdir)/ruby/internal/gc.h
+ossl_bio.o: $(hdrdir)/ruby/internal/glob.h
+ossl_bio.o: $(hdrdir)/ruby/internal/globals.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_bio.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_bio.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_bio.o: $(hdrdir)/ruby/internal/memory.h
+ossl_bio.o: $(hdrdir)/ruby/internal/method.h
+ossl_bio.o: $(hdrdir)/ruby/internal/module.h
+ossl_bio.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_bio.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_bio.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_bio.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_bio.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_bio.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_bio.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_bio.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_bio.o: $(hdrdir)/ruby/internal/value.h
+ossl_bio.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_bio.o: $(hdrdir)/ruby/internal/variable.h
+ossl_bio.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_bio.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_bio.o: $(hdrdir)/ruby/io.h
+ossl_bio.o: $(hdrdir)/ruby/missing.h
+ossl_bio.o: $(hdrdir)/ruby/onigmo.h
+ossl_bio.o: $(hdrdir)/ruby/oniguruma.h
+ossl_bio.o: $(hdrdir)/ruby/ractor.h
+ossl_bio.o: $(hdrdir)/ruby/ruby.h
+ossl_bio.o: $(hdrdir)/ruby/st.h
+ossl_bio.o: $(hdrdir)/ruby/subst.h
+ossl_bio.o: $(hdrdir)/ruby/thread.h
+ossl_bio.o: openssl_missing.h
+ossl_bio.o: ossl.h
+ossl_bio.o: ossl_asn1.h
+ossl_bio.o: ossl_bio.c
+ossl_bio.o: ossl_bio.h
+ossl_bio.o: ossl_bn.h
+ossl_bio.o: ossl_cipher.h
+ossl_bio.o: ossl_config.h
+ossl_bio.o: ossl_digest.h
+ossl_bio.o: ossl_engine.h
+ossl_bio.o: ossl_hmac.h
+ossl_bio.o: ossl_kdf.h
+ossl_bio.o: ossl_ns_spki.h
+ossl_bio.o: ossl_ocsp.h
+ossl_bio.o: ossl_pkcs12.h
+ossl_bio.o: ossl_pkcs7.h
+ossl_bio.o: ossl_pkey.h
+ossl_bio.o: ossl_provider.h
+ossl_bio.o: ossl_rand.h
+ossl_bio.o: ossl_ssl.h
+ossl_bio.o: ossl_ts.h
+ossl_bio.o: ossl_x509.h
+ossl_bn.o: $(RUBY_EXTCONF_H)
+ossl_bn.o: $(arch_hdrdir)/ruby/config.h
+ossl_bn.o: $(hdrdir)/ruby.h
+ossl_bn.o: $(hdrdir)/ruby/assert.h
+ossl_bn.o: $(hdrdir)/ruby/backward.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_bn.o: $(hdrdir)/ruby/defines.h
+ossl_bn.o: $(hdrdir)/ruby/encoding.h
+ossl_bn.o: $(hdrdir)/ruby/intern.h
+ossl_bn.o: $(hdrdir)/ruby/internal/abi.h
+ossl_bn.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/assume.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_bn.o: $(hdrdir)/ruby/internal/cast.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_bn.o: $(hdrdir)/ruby/internal/config.h
+ossl_bn.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_bn.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_bn.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_bn.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_bn.o: $(hdrdir)/ruby/internal/error.h
+ossl_bn.o: $(hdrdir)/ruby/internal/eval.h
+ossl_bn.o: $(hdrdir)/ruby/internal/event.h
+ossl_bn.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_bn.o: $(hdrdir)/ruby/internal/gc.h
+ossl_bn.o: $(hdrdir)/ruby/internal/glob.h
+ossl_bn.o: $(hdrdir)/ruby/internal/globals.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_bn.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_bn.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_bn.o: $(hdrdir)/ruby/internal/memory.h
+ossl_bn.o: $(hdrdir)/ruby/internal/method.h
+ossl_bn.o: $(hdrdir)/ruby/internal/module.h
+ossl_bn.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_bn.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_bn.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_bn.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_bn.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_bn.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_bn.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_bn.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_bn.o: $(hdrdir)/ruby/internal/value.h
+ossl_bn.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_bn.o: $(hdrdir)/ruby/internal/variable.h
+ossl_bn.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_bn.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_bn.o: $(hdrdir)/ruby/io.h
+ossl_bn.o: $(hdrdir)/ruby/missing.h
+ossl_bn.o: $(hdrdir)/ruby/onigmo.h
+ossl_bn.o: $(hdrdir)/ruby/oniguruma.h
+ossl_bn.o: $(hdrdir)/ruby/ractor.h
+ossl_bn.o: $(hdrdir)/ruby/ruby.h
+ossl_bn.o: $(hdrdir)/ruby/st.h
+ossl_bn.o: $(hdrdir)/ruby/subst.h
+ossl_bn.o: $(hdrdir)/ruby/thread.h
+ossl_bn.o: openssl_missing.h
+ossl_bn.o: ossl.h
+ossl_bn.o: ossl_asn1.h
+ossl_bn.o: ossl_bio.h
+ossl_bn.o: ossl_bn.c
+ossl_bn.o: ossl_bn.h
+ossl_bn.o: ossl_cipher.h
+ossl_bn.o: ossl_config.h
+ossl_bn.o: ossl_digest.h
+ossl_bn.o: ossl_engine.h
+ossl_bn.o: ossl_hmac.h
+ossl_bn.o: ossl_kdf.h
+ossl_bn.o: ossl_ns_spki.h
+ossl_bn.o: ossl_ocsp.h
+ossl_bn.o: ossl_pkcs12.h
+ossl_bn.o: ossl_pkcs7.h
+ossl_bn.o: ossl_pkey.h
+ossl_bn.o: ossl_provider.h
+ossl_bn.o: ossl_rand.h
+ossl_bn.o: ossl_ssl.h
+ossl_bn.o: ossl_ts.h
+ossl_bn.o: ossl_x509.h
+ossl_cipher.o: $(RUBY_EXTCONF_H)
+ossl_cipher.o: $(arch_hdrdir)/ruby/config.h
+ossl_cipher.o: $(hdrdir)/ruby.h
+ossl_cipher.o: $(hdrdir)/ruby/assert.h
+ossl_cipher.o: $(hdrdir)/ruby/backward.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_cipher.o: $(hdrdir)/ruby/defines.h
+ossl_cipher.o: $(hdrdir)/ruby/encoding.h
+ossl_cipher.o: $(hdrdir)/ruby/intern.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/abi.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/assume.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/cast.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/config.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/error.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/eval.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/event.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/gc.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/glob.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/globals.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/memory.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/method.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/module.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/value.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/variable.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_cipher.o: $(hdrdir)/ruby/io.h
+ossl_cipher.o: $(hdrdir)/ruby/missing.h
+ossl_cipher.o: $(hdrdir)/ruby/onigmo.h
+ossl_cipher.o: $(hdrdir)/ruby/oniguruma.h
+ossl_cipher.o: $(hdrdir)/ruby/ractor.h
+ossl_cipher.o: $(hdrdir)/ruby/ruby.h
+ossl_cipher.o: $(hdrdir)/ruby/st.h
+ossl_cipher.o: $(hdrdir)/ruby/subst.h
+ossl_cipher.o: $(hdrdir)/ruby/thread.h
+ossl_cipher.o: openssl_missing.h
+ossl_cipher.o: ossl.h
+ossl_cipher.o: ossl_asn1.h
+ossl_cipher.o: ossl_bio.h
+ossl_cipher.o: ossl_bn.h
+ossl_cipher.o: ossl_cipher.c
+ossl_cipher.o: ossl_cipher.h
+ossl_cipher.o: ossl_config.h
+ossl_cipher.o: ossl_digest.h
+ossl_cipher.o: ossl_engine.h
+ossl_cipher.o: ossl_hmac.h
+ossl_cipher.o: ossl_kdf.h
+ossl_cipher.o: ossl_ns_spki.h
+ossl_cipher.o: ossl_ocsp.h
+ossl_cipher.o: ossl_pkcs12.h
+ossl_cipher.o: ossl_pkcs7.h
+ossl_cipher.o: ossl_pkey.h
+ossl_cipher.o: ossl_provider.h
+ossl_cipher.o: ossl_rand.h
+ossl_cipher.o: ossl_ssl.h
+ossl_cipher.o: ossl_ts.h
+ossl_cipher.o: ossl_x509.h
+ossl_config.o: $(RUBY_EXTCONF_H)
+ossl_config.o: $(arch_hdrdir)/ruby/config.h
+ossl_config.o: $(hdrdir)/ruby.h
+ossl_config.o: $(hdrdir)/ruby/assert.h
+ossl_config.o: $(hdrdir)/ruby/backward.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_config.o: $(hdrdir)/ruby/defines.h
+ossl_config.o: $(hdrdir)/ruby/encoding.h
+ossl_config.o: $(hdrdir)/ruby/intern.h
+ossl_config.o: $(hdrdir)/ruby/internal/abi.h
+ossl_config.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/assume.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_config.o: $(hdrdir)/ruby/internal/cast.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_config.o: $(hdrdir)/ruby/internal/config.h
+ossl_config.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_config.o: $(hdrdir)/ruby/internal/core.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_config.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_config.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_config.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_config.o: $(hdrdir)/ruby/internal/error.h
+ossl_config.o: $(hdrdir)/ruby/internal/eval.h
+ossl_config.o: $(hdrdir)/ruby/internal/event.h
+ossl_config.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_config.o: $(hdrdir)/ruby/internal/gc.h
+ossl_config.o: $(hdrdir)/ruby/internal/glob.h
+ossl_config.o: $(hdrdir)/ruby/internal/globals.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_config.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_config.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_config.o: $(hdrdir)/ruby/internal/memory.h
+ossl_config.o: $(hdrdir)/ruby/internal/method.h
+ossl_config.o: $(hdrdir)/ruby/internal/module.h
+ossl_config.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_config.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_config.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_config.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_config.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_config.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_config.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_config.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_config.o: $(hdrdir)/ruby/internal/value.h
+ossl_config.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_config.o: $(hdrdir)/ruby/internal/variable.h
+ossl_config.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_config.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_config.o: $(hdrdir)/ruby/io.h
+ossl_config.o: $(hdrdir)/ruby/missing.h
+ossl_config.o: $(hdrdir)/ruby/onigmo.h
+ossl_config.o: $(hdrdir)/ruby/oniguruma.h
+ossl_config.o: $(hdrdir)/ruby/ractor.h
+ossl_config.o: $(hdrdir)/ruby/ruby.h
+ossl_config.o: $(hdrdir)/ruby/st.h
+ossl_config.o: $(hdrdir)/ruby/subst.h
+ossl_config.o: $(hdrdir)/ruby/thread.h
+ossl_config.o: openssl_missing.h
+ossl_config.o: ossl.h
+ossl_config.o: ossl_asn1.h
+ossl_config.o: ossl_bio.h
+ossl_config.o: ossl_bn.h
+ossl_config.o: ossl_cipher.h
+ossl_config.o: ossl_config.c
+ossl_config.o: ossl_config.h
+ossl_config.o: ossl_digest.h
+ossl_config.o: ossl_engine.h
+ossl_config.o: ossl_hmac.h
+ossl_config.o: ossl_kdf.h
+ossl_config.o: ossl_ns_spki.h
+ossl_config.o: ossl_ocsp.h
+ossl_config.o: ossl_pkcs12.h
+ossl_config.o: ossl_pkcs7.h
+ossl_config.o: ossl_pkey.h
+ossl_config.o: ossl_provider.h
+ossl_config.o: ossl_rand.h
+ossl_config.o: ossl_ssl.h
+ossl_config.o: ossl_ts.h
+ossl_config.o: ossl_x509.h
+ossl_digest.o: $(RUBY_EXTCONF_H)
+ossl_digest.o: $(arch_hdrdir)/ruby/config.h
+ossl_digest.o: $(hdrdir)/ruby.h
+ossl_digest.o: $(hdrdir)/ruby/assert.h
+ossl_digest.o: $(hdrdir)/ruby/backward.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_digest.o: $(hdrdir)/ruby/defines.h
+ossl_digest.o: $(hdrdir)/ruby/encoding.h
+ossl_digest.o: $(hdrdir)/ruby/intern.h
+ossl_digest.o: $(hdrdir)/ruby/internal/abi.h
+ossl_digest.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/assume.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_digest.o: $(hdrdir)/ruby/internal/cast.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_digest.o: $(hdrdir)/ruby/internal/config.h
+ossl_digest.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_digest.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_digest.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_digest.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_digest.o: $(hdrdir)/ruby/internal/error.h
+ossl_digest.o: $(hdrdir)/ruby/internal/eval.h
+ossl_digest.o: $(hdrdir)/ruby/internal/event.h
+ossl_digest.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_digest.o: $(hdrdir)/ruby/internal/gc.h
+ossl_digest.o: $(hdrdir)/ruby/internal/glob.h
+ossl_digest.o: $(hdrdir)/ruby/internal/globals.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_digest.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_digest.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_digest.o: $(hdrdir)/ruby/internal/memory.h
+ossl_digest.o: $(hdrdir)/ruby/internal/method.h
+ossl_digest.o: $(hdrdir)/ruby/internal/module.h
+ossl_digest.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_digest.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_digest.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_digest.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_digest.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_digest.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_digest.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_digest.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_digest.o: $(hdrdir)/ruby/internal/value.h
+ossl_digest.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_digest.o: $(hdrdir)/ruby/internal/variable.h
+ossl_digest.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_digest.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_digest.o: $(hdrdir)/ruby/io.h
+ossl_digest.o: $(hdrdir)/ruby/missing.h
+ossl_digest.o: $(hdrdir)/ruby/onigmo.h
+ossl_digest.o: $(hdrdir)/ruby/oniguruma.h
+ossl_digest.o: $(hdrdir)/ruby/ractor.h
+ossl_digest.o: $(hdrdir)/ruby/ruby.h
+ossl_digest.o: $(hdrdir)/ruby/st.h
+ossl_digest.o: $(hdrdir)/ruby/subst.h
+ossl_digest.o: $(hdrdir)/ruby/thread.h
+ossl_digest.o: openssl_missing.h
+ossl_digest.o: ossl.h
+ossl_digest.o: ossl_asn1.h
+ossl_digest.o: ossl_bio.h
+ossl_digest.o: ossl_bn.h
+ossl_digest.o: ossl_cipher.h
+ossl_digest.o: ossl_config.h
+ossl_digest.o: ossl_digest.c
+ossl_digest.o: ossl_digest.h
+ossl_digest.o: ossl_engine.h
+ossl_digest.o: ossl_hmac.h
+ossl_digest.o: ossl_kdf.h
+ossl_digest.o: ossl_ns_spki.h
+ossl_digest.o: ossl_ocsp.h
+ossl_digest.o: ossl_pkcs12.h
+ossl_digest.o: ossl_pkcs7.h
+ossl_digest.o: ossl_pkey.h
+ossl_digest.o: ossl_provider.h
+ossl_digest.o: ossl_rand.h
+ossl_digest.o: ossl_ssl.h
+ossl_digest.o: ossl_ts.h
+ossl_digest.o: ossl_x509.h
+ossl_engine.o: $(RUBY_EXTCONF_H)
+ossl_engine.o: $(arch_hdrdir)/ruby/config.h
+ossl_engine.o: $(hdrdir)/ruby.h
+ossl_engine.o: $(hdrdir)/ruby/assert.h
+ossl_engine.o: $(hdrdir)/ruby/backward.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_engine.o: $(hdrdir)/ruby/defines.h
+ossl_engine.o: $(hdrdir)/ruby/encoding.h
+ossl_engine.o: $(hdrdir)/ruby/intern.h
+ossl_engine.o: $(hdrdir)/ruby/internal/abi.h
+ossl_engine.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/assume.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_engine.o: $(hdrdir)/ruby/internal/cast.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_engine.o: $(hdrdir)/ruby/internal/config.h
+ossl_engine.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_engine.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_engine.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_engine.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_engine.o: $(hdrdir)/ruby/internal/error.h
+ossl_engine.o: $(hdrdir)/ruby/internal/eval.h
+ossl_engine.o: $(hdrdir)/ruby/internal/event.h
+ossl_engine.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_engine.o: $(hdrdir)/ruby/internal/gc.h
+ossl_engine.o: $(hdrdir)/ruby/internal/glob.h
+ossl_engine.o: $(hdrdir)/ruby/internal/globals.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_engine.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_engine.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_engine.o: $(hdrdir)/ruby/internal/memory.h
+ossl_engine.o: $(hdrdir)/ruby/internal/method.h
+ossl_engine.o: $(hdrdir)/ruby/internal/module.h
+ossl_engine.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_engine.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_engine.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_engine.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_engine.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_engine.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_engine.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_engine.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_engine.o: $(hdrdir)/ruby/internal/value.h
+ossl_engine.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_engine.o: $(hdrdir)/ruby/internal/variable.h
+ossl_engine.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_engine.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_engine.o: $(hdrdir)/ruby/io.h
+ossl_engine.o: $(hdrdir)/ruby/missing.h
+ossl_engine.o: $(hdrdir)/ruby/onigmo.h
+ossl_engine.o: $(hdrdir)/ruby/oniguruma.h
+ossl_engine.o: $(hdrdir)/ruby/ractor.h
+ossl_engine.o: $(hdrdir)/ruby/ruby.h
+ossl_engine.o: $(hdrdir)/ruby/st.h
+ossl_engine.o: $(hdrdir)/ruby/subst.h
+ossl_engine.o: $(hdrdir)/ruby/thread.h
+ossl_engine.o: openssl_missing.h
+ossl_engine.o: ossl.h
+ossl_engine.o: ossl_asn1.h
+ossl_engine.o: ossl_bio.h
+ossl_engine.o: ossl_bn.h
+ossl_engine.o: ossl_cipher.h
+ossl_engine.o: ossl_config.h
+ossl_engine.o: ossl_digest.h
+ossl_engine.o: ossl_engine.c
+ossl_engine.o: ossl_engine.h
+ossl_engine.o: ossl_hmac.h
+ossl_engine.o: ossl_kdf.h
+ossl_engine.o: ossl_ns_spki.h
+ossl_engine.o: ossl_ocsp.h
+ossl_engine.o: ossl_pkcs12.h
+ossl_engine.o: ossl_pkcs7.h
+ossl_engine.o: ossl_pkey.h
+ossl_engine.o: ossl_provider.h
+ossl_engine.o: ossl_rand.h
+ossl_engine.o: ossl_ssl.h
+ossl_engine.o: ossl_ts.h
+ossl_engine.o: ossl_x509.h
+ossl_hmac.o: $(RUBY_EXTCONF_H)
+ossl_hmac.o: $(arch_hdrdir)/ruby/config.h
+ossl_hmac.o: $(hdrdir)/ruby.h
+ossl_hmac.o: $(hdrdir)/ruby/assert.h
+ossl_hmac.o: $(hdrdir)/ruby/backward.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_hmac.o: $(hdrdir)/ruby/defines.h
+ossl_hmac.o: $(hdrdir)/ruby/encoding.h
+ossl_hmac.o: $(hdrdir)/ruby/intern.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/abi.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/assume.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/cast.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/config.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/error.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/eval.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/event.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/gc.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/glob.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/globals.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/memory.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/method.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/module.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/value.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/variable.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_hmac.o: $(hdrdir)/ruby/io.h
+ossl_hmac.o: $(hdrdir)/ruby/missing.h
+ossl_hmac.o: $(hdrdir)/ruby/onigmo.h
+ossl_hmac.o: $(hdrdir)/ruby/oniguruma.h
+ossl_hmac.o: $(hdrdir)/ruby/ractor.h
+ossl_hmac.o: $(hdrdir)/ruby/ruby.h
+ossl_hmac.o: $(hdrdir)/ruby/st.h
+ossl_hmac.o: $(hdrdir)/ruby/subst.h
+ossl_hmac.o: $(hdrdir)/ruby/thread.h
+ossl_hmac.o: openssl_missing.h
+ossl_hmac.o: ossl.h
+ossl_hmac.o: ossl_asn1.h
+ossl_hmac.o: ossl_bio.h
+ossl_hmac.o: ossl_bn.h
+ossl_hmac.o: ossl_cipher.h
+ossl_hmac.o: ossl_config.h
+ossl_hmac.o: ossl_digest.h
+ossl_hmac.o: ossl_engine.h
+ossl_hmac.o: ossl_hmac.c
+ossl_hmac.o: ossl_hmac.h
+ossl_hmac.o: ossl_kdf.h
+ossl_hmac.o: ossl_ns_spki.h
+ossl_hmac.o: ossl_ocsp.h
+ossl_hmac.o: ossl_pkcs12.h
+ossl_hmac.o: ossl_pkcs7.h
+ossl_hmac.o: ossl_pkey.h
+ossl_hmac.o: ossl_provider.h
+ossl_hmac.o: ossl_rand.h
+ossl_hmac.o: ossl_ssl.h
+ossl_hmac.o: ossl_ts.h
+ossl_hmac.o: ossl_x509.h
+ossl_kdf.o: $(RUBY_EXTCONF_H)
+ossl_kdf.o: $(arch_hdrdir)/ruby/config.h
+ossl_kdf.o: $(hdrdir)/ruby.h
+ossl_kdf.o: $(hdrdir)/ruby/assert.h
+ossl_kdf.o: $(hdrdir)/ruby/backward.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_kdf.o: $(hdrdir)/ruby/defines.h
+ossl_kdf.o: $(hdrdir)/ruby/encoding.h
+ossl_kdf.o: $(hdrdir)/ruby/intern.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/abi.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/assume.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/cast.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/config.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/error.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/eval.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/event.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/gc.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/glob.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/globals.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/memory.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/method.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/module.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/value.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/variable.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_kdf.o: $(hdrdir)/ruby/io.h
+ossl_kdf.o: $(hdrdir)/ruby/missing.h
+ossl_kdf.o: $(hdrdir)/ruby/onigmo.h
+ossl_kdf.o: $(hdrdir)/ruby/oniguruma.h
+ossl_kdf.o: $(hdrdir)/ruby/ractor.h
+ossl_kdf.o: $(hdrdir)/ruby/ruby.h
+ossl_kdf.o: $(hdrdir)/ruby/st.h
+ossl_kdf.o: $(hdrdir)/ruby/subst.h
+ossl_kdf.o: $(hdrdir)/ruby/thread.h
+ossl_kdf.o: openssl_missing.h
+ossl_kdf.o: ossl.h
+ossl_kdf.o: ossl_asn1.h
+ossl_kdf.o: ossl_bio.h
+ossl_kdf.o: ossl_bn.h
+ossl_kdf.o: ossl_cipher.h
+ossl_kdf.o: ossl_config.h
+ossl_kdf.o: ossl_digest.h
+ossl_kdf.o: ossl_engine.h
+ossl_kdf.o: ossl_hmac.h
+ossl_kdf.o: ossl_kdf.c
+ossl_kdf.o: ossl_kdf.h
+ossl_kdf.o: ossl_ns_spki.h
+ossl_kdf.o: ossl_ocsp.h
+ossl_kdf.o: ossl_pkcs12.h
+ossl_kdf.o: ossl_pkcs7.h
+ossl_kdf.o: ossl_pkey.h
+ossl_kdf.o: ossl_provider.h
+ossl_kdf.o: ossl_rand.h
+ossl_kdf.o: ossl_ssl.h
+ossl_kdf.o: ossl_ts.h
+ossl_kdf.o: ossl_x509.h
+ossl_ns_spki.o: $(RUBY_EXTCONF_H)
+ossl_ns_spki.o: $(arch_hdrdir)/ruby/config.h
+ossl_ns_spki.o: $(hdrdir)/ruby.h
+ossl_ns_spki.o: $(hdrdir)/ruby/assert.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_ns_spki.o: $(hdrdir)/ruby/defines.h
+ossl_ns_spki.o: $(hdrdir)/ruby/encoding.h
+ossl_ns_spki.o: $(hdrdir)/ruby/intern.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/abi.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/assume.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/cast.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/config.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/error.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/eval.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/event.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/gc.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/glob.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/globals.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/memory.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/method.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/module.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/value.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/variable.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_ns_spki.o: $(hdrdir)/ruby/io.h
+ossl_ns_spki.o: $(hdrdir)/ruby/missing.h
+ossl_ns_spki.o: $(hdrdir)/ruby/onigmo.h
+ossl_ns_spki.o: $(hdrdir)/ruby/oniguruma.h
+ossl_ns_spki.o: $(hdrdir)/ruby/ractor.h
+ossl_ns_spki.o: $(hdrdir)/ruby/ruby.h
+ossl_ns_spki.o: $(hdrdir)/ruby/st.h
+ossl_ns_spki.o: $(hdrdir)/ruby/subst.h
+ossl_ns_spki.o: $(hdrdir)/ruby/thread.h
+ossl_ns_spki.o: openssl_missing.h
+ossl_ns_spki.o: ossl.h
+ossl_ns_spki.o: ossl_asn1.h
+ossl_ns_spki.o: ossl_bio.h
+ossl_ns_spki.o: ossl_bn.h
+ossl_ns_spki.o: ossl_cipher.h
+ossl_ns_spki.o: ossl_config.h
+ossl_ns_spki.o: ossl_digest.h
+ossl_ns_spki.o: ossl_engine.h
+ossl_ns_spki.o: ossl_hmac.h
+ossl_ns_spki.o: ossl_kdf.h
+ossl_ns_spki.o: ossl_ns_spki.c
+ossl_ns_spki.o: ossl_ns_spki.h
+ossl_ns_spki.o: ossl_ocsp.h
+ossl_ns_spki.o: ossl_pkcs12.h
+ossl_ns_spki.o: ossl_pkcs7.h
+ossl_ns_spki.o: ossl_pkey.h
+ossl_ns_spki.o: ossl_provider.h
+ossl_ns_spki.o: ossl_rand.h
+ossl_ns_spki.o: ossl_ssl.h
+ossl_ns_spki.o: ossl_ts.h
+ossl_ns_spki.o: ossl_x509.h
+ossl_ocsp.o: $(RUBY_EXTCONF_H)
+ossl_ocsp.o: $(arch_hdrdir)/ruby/config.h
+ossl_ocsp.o: $(hdrdir)/ruby.h
+ossl_ocsp.o: $(hdrdir)/ruby/assert.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_ocsp.o: $(hdrdir)/ruby/defines.h
+ossl_ocsp.o: $(hdrdir)/ruby/encoding.h
+ossl_ocsp.o: $(hdrdir)/ruby/intern.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/abi.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/assume.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/cast.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/config.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/error.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/eval.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/event.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/gc.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/glob.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/globals.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/memory.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/method.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/module.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/value.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/variable.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_ocsp.o: $(hdrdir)/ruby/io.h
+ossl_ocsp.o: $(hdrdir)/ruby/missing.h
+ossl_ocsp.o: $(hdrdir)/ruby/onigmo.h
+ossl_ocsp.o: $(hdrdir)/ruby/oniguruma.h
+ossl_ocsp.o: $(hdrdir)/ruby/ractor.h
+ossl_ocsp.o: $(hdrdir)/ruby/ruby.h
+ossl_ocsp.o: $(hdrdir)/ruby/st.h
+ossl_ocsp.o: $(hdrdir)/ruby/subst.h
+ossl_ocsp.o: $(hdrdir)/ruby/thread.h
+ossl_ocsp.o: openssl_missing.h
+ossl_ocsp.o: ossl.h
+ossl_ocsp.o: ossl_asn1.h
+ossl_ocsp.o: ossl_bio.h
+ossl_ocsp.o: ossl_bn.h
+ossl_ocsp.o: ossl_cipher.h
+ossl_ocsp.o: ossl_config.h
+ossl_ocsp.o: ossl_digest.h
+ossl_ocsp.o: ossl_engine.h
+ossl_ocsp.o: ossl_hmac.h
+ossl_ocsp.o: ossl_kdf.h
+ossl_ocsp.o: ossl_ns_spki.h
+ossl_ocsp.o: ossl_ocsp.c
+ossl_ocsp.o: ossl_ocsp.h
+ossl_ocsp.o: ossl_pkcs12.h
+ossl_ocsp.o: ossl_pkcs7.h
+ossl_ocsp.o: ossl_pkey.h
+ossl_ocsp.o: ossl_provider.h
+ossl_ocsp.o: ossl_rand.h
+ossl_ocsp.o: ossl_ssl.h
+ossl_ocsp.o: ossl_ts.h
+ossl_ocsp.o: ossl_x509.h
+ossl_pkcs12.o: $(RUBY_EXTCONF_H)
+ossl_pkcs12.o: $(arch_hdrdir)/ruby/config.h
+ossl_pkcs12.o: $(hdrdir)/ruby.h
+ossl_pkcs12.o: $(hdrdir)/ruby/assert.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_pkcs12.o: $(hdrdir)/ruby/defines.h
+ossl_pkcs12.o: $(hdrdir)/ruby/encoding.h
+ossl_pkcs12.o: $(hdrdir)/ruby/intern.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/abi.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_pkcs12.o: $(hdrdir)/ruby/io.h
+ossl_pkcs12.o: $(hdrdir)/ruby/missing.h
+ossl_pkcs12.o: $(hdrdir)/ruby/onigmo.h
+ossl_pkcs12.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkcs12.o: $(hdrdir)/ruby/ractor.h
+ossl_pkcs12.o: $(hdrdir)/ruby/ruby.h
+ossl_pkcs12.o: $(hdrdir)/ruby/st.h
+ossl_pkcs12.o: $(hdrdir)/ruby/subst.h
+ossl_pkcs12.o: $(hdrdir)/ruby/thread.h
+ossl_pkcs12.o: openssl_missing.h
+ossl_pkcs12.o: ossl.h
+ossl_pkcs12.o: ossl_asn1.h
+ossl_pkcs12.o: ossl_bio.h
+ossl_pkcs12.o: ossl_bn.h
+ossl_pkcs12.o: ossl_cipher.h
+ossl_pkcs12.o: ossl_config.h
+ossl_pkcs12.o: ossl_digest.h
+ossl_pkcs12.o: ossl_engine.h
+ossl_pkcs12.o: ossl_hmac.h
+ossl_pkcs12.o: ossl_kdf.h
+ossl_pkcs12.o: ossl_ns_spki.h
+ossl_pkcs12.o: ossl_ocsp.h
+ossl_pkcs12.o: ossl_pkcs12.c
+ossl_pkcs12.o: ossl_pkcs12.h
+ossl_pkcs12.o: ossl_pkcs7.h
+ossl_pkcs12.o: ossl_pkey.h
+ossl_pkcs12.o: ossl_provider.h
+ossl_pkcs12.o: ossl_rand.h
+ossl_pkcs12.o: ossl_ssl.h
+ossl_pkcs12.o: ossl_ts.h
+ossl_pkcs12.o: ossl_x509.h
+ossl_pkcs7.o: $(RUBY_EXTCONF_H)
+ossl_pkcs7.o: $(arch_hdrdir)/ruby/config.h
+ossl_pkcs7.o: $(hdrdir)/ruby.h
+ossl_pkcs7.o: $(hdrdir)/ruby/assert.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_pkcs7.o: $(hdrdir)/ruby/defines.h
+ossl_pkcs7.o: $(hdrdir)/ruby/encoding.h
+ossl_pkcs7.o: $(hdrdir)/ruby/intern.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/abi.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_pkcs7.o: $(hdrdir)/ruby/io.h
+ossl_pkcs7.o: $(hdrdir)/ruby/missing.h
+ossl_pkcs7.o: $(hdrdir)/ruby/onigmo.h
+ossl_pkcs7.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkcs7.o: $(hdrdir)/ruby/ractor.h
+ossl_pkcs7.o: $(hdrdir)/ruby/ruby.h
+ossl_pkcs7.o: $(hdrdir)/ruby/st.h
+ossl_pkcs7.o: $(hdrdir)/ruby/subst.h
+ossl_pkcs7.o: $(hdrdir)/ruby/thread.h
+ossl_pkcs7.o: openssl_missing.h
+ossl_pkcs7.o: ossl.h
+ossl_pkcs7.o: ossl_asn1.h
+ossl_pkcs7.o: ossl_bio.h
+ossl_pkcs7.o: ossl_bn.h
+ossl_pkcs7.o: ossl_cipher.h
+ossl_pkcs7.o: ossl_config.h
+ossl_pkcs7.o: ossl_digest.h
+ossl_pkcs7.o: ossl_engine.h
+ossl_pkcs7.o: ossl_hmac.h
+ossl_pkcs7.o: ossl_kdf.h
+ossl_pkcs7.o: ossl_ns_spki.h
+ossl_pkcs7.o: ossl_ocsp.h
+ossl_pkcs7.o: ossl_pkcs12.h
+ossl_pkcs7.o: ossl_pkcs7.c
+ossl_pkcs7.o: ossl_pkcs7.h
+ossl_pkcs7.o: ossl_pkey.h
+ossl_pkcs7.o: ossl_provider.h
+ossl_pkcs7.o: ossl_rand.h
+ossl_pkcs7.o: ossl_ssl.h
+ossl_pkcs7.o: ossl_ts.h
+ossl_pkcs7.o: ossl_x509.h
+ossl_pkey.o: $(RUBY_EXTCONF_H)
+ossl_pkey.o: $(arch_hdrdir)/ruby/config.h
+ossl_pkey.o: $(hdrdir)/ruby.h
+ossl_pkey.o: $(hdrdir)/ruby/assert.h
+ossl_pkey.o: $(hdrdir)/ruby/backward.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_pkey.o: $(hdrdir)/ruby/defines.h
+ossl_pkey.o: $(hdrdir)/ruby/encoding.h
+ossl_pkey.o: $(hdrdir)/ruby/intern.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/abi.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_pkey.o: $(hdrdir)/ruby/io.h
+ossl_pkey.o: $(hdrdir)/ruby/missing.h
+ossl_pkey.o: $(hdrdir)/ruby/onigmo.h
+ossl_pkey.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkey.o: $(hdrdir)/ruby/ractor.h
+ossl_pkey.o: $(hdrdir)/ruby/ruby.h
+ossl_pkey.o: $(hdrdir)/ruby/st.h
+ossl_pkey.o: $(hdrdir)/ruby/subst.h
+ossl_pkey.o: $(hdrdir)/ruby/thread.h
+ossl_pkey.o: openssl_missing.h
+ossl_pkey.o: ossl.h
+ossl_pkey.o: ossl_asn1.h
+ossl_pkey.o: ossl_bio.h
+ossl_pkey.o: ossl_bn.h
+ossl_pkey.o: ossl_cipher.h
+ossl_pkey.o: ossl_config.h
+ossl_pkey.o: ossl_digest.h
+ossl_pkey.o: ossl_engine.h
+ossl_pkey.o: ossl_hmac.h
+ossl_pkey.o: ossl_kdf.h
+ossl_pkey.o: ossl_ns_spki.h
+ossl_pkey.o: ossl_ocsp.h
+ossl_pkey.o: ossl_pkcs12.h
+ossl_pkey.o: ossl_pkcs7.h
+ossl_pkey.o: ossl_pkey.c
+ossl_pkey.o: ossl_pkey.h
+ossl_pkey.o: ossl_provider.h
+ossl_pkey.o: ossl_rand.h
+ossl_pkey.o: ossl_ssl.h
+ossl_pkey.o: ossl_ts.h
+ossl_pkey.o: ossl_x509.h
+ossl_pkey_dh.o: $(RUBY_EXTCONF_H)
+ossl_pkey_dh.o: $(arch_hdrdir)/ruby/config.h
+ossl_pkey_dh.o: $(hdrdir)/ruby.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/assert.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/defines.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/encoding.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/intern.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/abi.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/io.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/missing.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/onigmo.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/ractor.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/ruby.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/st.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/subst.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/thread.h
+ossl_pkey_dh.o: openssl_missing.h
+ossl_pkey_dh.o: ossl.h
+ossl_pkey_dh.o: ossl_asn1.h
+ossl_pkey_dh.o: ossl_bio.h
+ossl_pkey_dh.o: ossl_bn.h
+ossl_pkey_dh.o: ossl_cipher.h
+ossl_pkey_dh.o: ossl_config.h
+ossl_pkey_dh.o: ossl_digest.h
+ossl_pkey_dh.o: ossl_engine.h
+ossl_pkey_dh.o: ossl_hmac.h
+ossl_pkey_dh.o: ossl_kdf.h
+ossl_pkey_dh.o: ossl_ns_spki.h
+ossl_pkey_dh.o: ossl_ocsp.h
+ossl_pkey_dh.o: ossl_pkcs12.h
+ossl_pkey_dh.o: ossl_pkcs7.h
+ossl_pkey_dh.o: ossl_pkey.h
+ossl_pkey_dh.o: ossl_pkey_dh.c
+ossl_pkey_dh.o: ossl_provider.h
+ossl_pkey_dh.o: ossl_rand.h
+ossl_pkey_dh.o: ossl_ssl.h
+ossl_pkey_dh.o: ossl_ts.h
+ossl_pkey_dh.o: ossl_x509.h
+ossl_pkey_dsa.o: $(RUBY_EXTCONF_H)
+ossl_pkey_dsa.o: $(arch_hdrdir)/ruby/config.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/assert.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/defines.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/encoding.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/intern.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/abi.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/io.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/missing.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/onigmo.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/ractor.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/ruby.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/st.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/subst.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/thread.h
+ossl_pkey_dsa.o: openssl_missing.h
+ossl_pkey_dsa.o: ossl.h
+ossl_pkey_dsa.o: ossl_asn1.h
+ossl_pkey_dsa.o: ossl_bio.h
+ossl_pkey_dsa.o: ossl_bn.h
+ossl_pkey_dsa.o: ossl_cipher.h
+ossl_pkey_dsa.o: ossl_config.h
+ossl_pkey_dsa.o: ossl_digest.h
+ossl_pkey_dsa.o: ossl_engine.h
+ossl_pkey_dsa.o: ossl_hmac.h
+ossl_pkey_dsa.o: ossl_kdf.h
+ossl_pkey_dsa.o: ossl_ns_spki.h
+ossl_pkey_dsa.o: ossl_ocsp.h
+ossl_pkey_dsa.o: ossl_pkcs12.h
+ossl_pkey_dsa.o: ossl_pkcs7.h
+ossl_pkey_dsa.o: ossl_pkey.h
+ossl_pkey_dsa.o: ossl_pkey_dsa.c
+ossl_pkey_dsa.o: ossl_provider.h
+ossl_pkey_dsa.o: ossl_rand.h
+ossl_pkey_dsa.o: ossl_ssl.h
+ossl_pkey_dsa.o: ossl_ts.h
+ossl_pkey_dsa.o: ossl_x509.h
+ossl_pkey_ec.o: $(RUBY_EXTCONF_H)
+ossl_pkey_ec.o: $(arch_hdrdir)/ruby/config.h
+ossl_pkey_ec.o: $(hdrdir)/ruby.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/assert.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/defines.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/encoding.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/intern.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/abi.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/io.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/missing.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/onigmo.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/ractor.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/ruby.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/st.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/subst.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/thread.h
+ossl_pkey_ec.o: openssl_missing.h
+ossl_pkey_ec.o: ossl.h
+ossl_pkey_ec.o: ossl_asn1.h
+ossl_pkey_ec.o: ossl_bio.h
+ossl_pkey_ec.o: ossl_bn.h
+ossl_pkey_ec.o: ossl_cipher.h
+ossl_pkey_ec.o: ossl_config.h
+ossl_pkey_ec.o: ossl_digest.h
+ossl_pkey_ec.o: ossl_engine.h
+ossl_pkey_ec.o: ossl_hmac.h
+ossl_pkey_ec.o: ossl_kdf.h
+ossl_pkey_ec.o: ossl_ns_spki.h
+ossl_pkey_ec.o: ossl_ocsp.h
+ossl_pkey_ec.o: ossl_pkcs12.h
+ossl_pkey_ec.o: ossl_pkcs7.h
+ossl_pkey_ec.o: ossl_pkey.h
+ossl_pkey_ec.o: ossl_pkey_ec.c
+ossl_pkey_ec.o: ossl_provider.h
+ossl_pkey_ec.o: ossl_rand.h
+ossl_pkey_ec.o: ossl_ssl.h
+ossl_pkey_ec.o: ossl_ts.h
+ossl_pkey_ec.o: ossl_x509.h
+ossl_pkey_rsa.o: $(RUBY_EXTCONF_H)
+ossl_pkey_rsa.o: $(arch_hdrdir)/ruby/config.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/assert.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/defines.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/encoding.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/intern.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/abi.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/io.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/missing.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/onigmo.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/ractor.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/ruby.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/st.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/subst.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/thread.h
+ossl_pkey_rsa.o: openssl_missing.h
+ossl_pkey_rsa.o: ossl.h
+ossl_pkey_rsa.o: ossl_asn1.h
+ossl_pkey_rsa.o: ossl_bio.h
+ossl_pkey_rsa.o: ossl_bn.h
+ossl_pkey_rsa.o: ossl_cipher.h
+ossl_pkey_rsa.o: ossl_config.h
+ossl_pkey_rsa.o: ossl_digest.h
+ossl_pkey_rsa.o: ossl_engine.h
+ossl_pkey_rsa.o: ossl_hmac.h
+ossl_pkey_rsa.o: ossl_kdf.h
+ossl_pkey_rsa.o: ossl_ns_spki.h
+ossl_pkey_rsa.o: ossl_ocsp.h
+ossl_pkey_rsa.o: ossl_pkcs12.h
+ossl_pkey_rsa.o: ossl_pkcs7.h
+ossl_pkey_rsa.o: ossl_pkey.h
+ossl_pkey_rsa.o: ossl_pkey_rsa.c
+ossl_pkey_rsa.o: ossl_provider.h
+ossl_pkey_rsa.o: ossl_rand.h
+ossl_pkey_rsa.o: ossl_ssl.h
+ossl_pkey_rsa.o: ossl_ts.h
+ossl_pkey_rsa.o: ossl_x509.h
+ossl_provider.o: $(RUBY_EXTCONF_H)
+ossl_provider.o: $(arch_hdrdir)/ruby/config.h
+ossl_provider.o: $(hdrdir)/ruby.h
+ossl_provider.o: $(hdrdir)/ruby/assert.h
+ossl_provider.o: $(hdrdir)/ruby/backward.h
+ossl_provider.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_provider.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_provider.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_provider.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_provider.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_provider.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_provider.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_provider.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_provider.o: $(hdrdir)/ruby/defines.h
+ossl_provider.o: $(hdrdir)/ruby/encoding.h
+ossl_provider.o: $(hdrdir)/ruby/intern.h
+ossl_provider.o: $(hdrdir)/ruby/internal/abi.h
+ossl_provider.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_provider.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_provider.o: $(hdrdir)/ruby/internal/assume.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_provider.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_provider.o: $(hdrdir)/ruby/internal/cast.h
+ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_provider.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_provider.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_provider.o: $(hdrdir)/ruby/internal/config.h
+ossl_provider.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_provider.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_provider.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_provider.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_provider.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_provider.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_provider.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_provider.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_provider.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_provider.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_provider.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_provider.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_provider.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_provider.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_provider.o: $(hdrdir)/ruby/internal/error.h
+ossl_provider.o: $(hdrdir)/ruby/internal/eval.h
+ossl_provider.o: $(hdrdir)/ruby/internal/event.h
+ossl_provider.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_provider.o: $(hdrdir)/ruby/internal/gc.h
+ossl_provider.o: $(hdrdir)/ruby/internal/glob.h
+ossl_provider.o: $(hdrdir)/ruby/internal/globals.h
+ossl_provider.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_provider.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_provider.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_provider.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_provider.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_provider.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_provider.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_provider.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_provider.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_provider.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_provider.o: $(hdrdir)/ruby/internal/memory.h
+ossl_provider.o: $(hdrdir)/ruby/internal/method.h
+ossl_provider.o: $(hdrdir)/ruby/internal/module.h
+ossl_provider.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_provider.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_provider.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_provider.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_provider.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_provider.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_provider.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_provider.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_provider.o: $(hdrdir)/ruby/internal/value.h
+ossl_provider.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_provider.o: $(hdrdir)/ruby/internal/variable.h
+ossl_provider.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_provider.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_provider.o: $(hdrdir)/ruby/io.h
+ossl_provider.o: $(hdrdir)/ruby/missing.h
+ossl_provider.o: $(hdrdir)/ruby/onigmo.h
+ossl_provider.o: $(hdrdir)/ruby/oniguruma.h
+ossl_provider.o: $(hdrdir)/ruby/ractor.h
+ossl_provider.o: $(hdrdir)/ruby/ruby.h
+ossl_provider.o: $(hdrdir)/ruby/st.h
+ossl_provider.o: $(hdrdir)/ruby/subst.h
+ossl_provider.o: $(hdrdir)/ruby/thread.h
+ossl_provider.o: openssl_missing.h
+ossl_provider.o: ossl.h
+ossl_provider.o: ossl_asn1.h
+ossl_provider.o: ossl_bio.h
+ossl_provider.o: ossl_bn.h
+ossl_provider.o: ossl_cipher.h
+ossl_provider.o: ossl_config.h
+ossl_provider.o: ossl_digest.h
+ossl_provider.o: ossl_engine.h
+ossl_provider.o: ossl_hmac.h
+ossl_provider.o: ossl_kdf.h
+ossl_provider.o: ossl_ns_spki.h
+ossl_provider.o: ossl_ocsp.h
+ossl_provider.o: ossl_pkcs12.h
+ossl_provider.o: ossl_pkcs7.h
+ossl_provider.o: ossl_pkey.h
+ossl_provider.o: ossl_provider.c
+ossl_provider.o: ossl_provider.h
+ossl_provider.o: ossl_rand.h
+ossl_provider.o: ossl_ssl.h
+ossl_provider.o: ossl_ts.h
+ossl_provider.o: ossl_x509.h
+ossl_rand.o: $(RUBY_EXTCONF_H)
+ossl_rand.o: $(arch_hdrdir)/ruby/config.h
+ossl_rand.o: $(hdrdir)/ruby.h
+ossl_rand.o: $(hdrdir)/ruby/assert.h
+ossl_rand.o: $(hdrdir)/ruby/backward.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_rand.o: $(hdrdir)/ruby/defines.h
+ossl_rand.o: $(hdrdir)/ruby/encoding.h
+ossl_rand.o: $(hdrdir)/ruby/intern.h
+ossl_rand.o: $(hdrdir)/ruby/internal/abi.h
+ossl_rand.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/assume.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_rand.o: $(hdrdir)/ruby/internal/cast.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_rand.o: $(hdrdir)/ruby/internal/config.h
+ossl_rand.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_rand.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_rand.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_rand.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_rand.o: $(hdrdir)/ruby/internal/error.h
+ossl_rand.o: $(hdrdir)/ruby/internal/eval.h
+ossl_rand.o: $(hdrdir)/ruby/internal/event.h
+ossl_rand.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_rand.o: $(hdrdir)/ruby/internal/gc.h
+ossl_rand.o: $(hdrdir)/ruby/internal/glob.h
+ossl_rand.o: $(hdrdir)/ruby/internal/globals.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_rand.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_rand.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_rand.o: $(hdrdir)/ruby/internal/memory.h
+ossl_rand.o: $(hdrdir)/ruby/internal/method.h
+ossl_rand.o: $(hdrdir)/ruby/internal/module.h
+ossl_rand.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_rand.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_rand.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_rand.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_rand.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_rand.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_rand.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_rand.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_rand.o: $(hdrdir)/ruby/internal/value.h
+ossl_rand.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_rand.o: $(hdrdir)/ruby/internal/variable.h
+ossl_rand.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_rand.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_rand.o: $(hdrdir)/ruby/io.h
+ossl_rand.o: $(hdrdir)/ruby/missing.h
+ossl_rand.o: $(hdrdir)/ruby/onigmo.h
+ossl_rand.o: $(hdrdir)/ruby/oniguruma.h
+ossl_rand.o: $(hdrdir)/ruby/ractor.h
+ossl_rand.o: $(hdrdir)/ruby/ruby.h
+ossl_rand.o: $(hdrdir)/ruby/st.h
+ossl_rand.o: $(hdrdir)/ruby/subst.h
+ossl_rand.o: $(hdrdir)/ruby/thread.h
+ossl_rand.o: openssl_missing.h
+ossl_rand.o: ossl.h
+ossl_rand.o: ossl_asn1.h
+ossl_rand.o: ossl_bio.h
+ossl_rand.o: ossl_bn.h
+ossl_rand.o: ossl_cipher.h
+ossl_rand.o: ossl_config.h
+ossl_rand.o: ossl_digest.h
+ossl_rand.o: ossl_engine.h
+ossl_rand.o: ossl_hmac.h
+ossl_rand.o: ossl_kdf.h
+ossl_rand.o: ossl_ns_spki.h
+ossl_rand.o: ossl_ocsp.h
+ossl_rand.o: ossl_pkcs12.h
+ossl_rand.o: ossl_pkcs7.h
+ossl_rand.o: ossl_pkey.h
+ossl_rand.o: ossl_provider.h
+ossl_rand.o: ossl_rand.c
+ossl_rand.o: ossl_rand.h
+ossl_rand.o: ossl_ssl.h
+ossl_rand.o: ossl_ts.h
+ossl_rand.o: ossl_x509.h
+ossl_ssl.o: $(RUBY_EXTCONF_H)
+ossl_ssl.o: $(arch_hdrdir)/ruby/config.h
+ossl_ssl.o: $(hdrdir)/ruby.h
+ossl_ssl.o: $(hdrdir)/ruby/assert.h
+ossl_ssl.o: $(hdrdir)/ruby/backward.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_ssl.o: $(hdrdir)/ruby/defines.h
+ossl_ssl.o: $(hdrdir)/ruby/encoding.h
+ossl_ssl.o: $(hdrdir)/ruby/intern.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/abi.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/assume.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/cast.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/config.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/error.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/eval.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/event.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/gc.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/glob.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/globals.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/memory.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/method.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/module.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/value.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/variable.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_ssl.o: $(hdrdir)/ruby/io.h
+ossl_ssl.o: $(hdrdir)/ruby/missing.h
+ossl_ssl.o: $(hdrdir)/ruby/onigmo.h
+ossl_ssl.o: $(hdrdir)/ruby/oniguruma.h
+ossl_ssl.o: $(hdrdir)/ruby/ractor.h
+ossl_ssl.o: $(hdrdir)/ruby/ruby.h
+ossl_ssl.o: $(hdrdir)/ruby/st.h
+ossl_ssl.o: $(hdrdir)/ruby/subst.h
+ossl_ssl.o: $(hdrdir)/ruby/thread.h
+ossl_ssl.o: openssl_missing.h
+ossl_ssl.o: ossl.h
+ossl_ssl.o: ossl_asn1.h
+ossl_ssl.o: ossl_bio.h
+ossl_ssl.o: ossl_bn.h
+ossl_ssl.o: ossl_cipher.h
+ossl_ssl.o: ossl_config.h
+ossl_ssl.o: ossl_digest.h
+ossl_ssl.o: ossl_engine.h
+ossl_ssl.o: ossl_hmac.h
+ossl_ssl.o: ossl_kdf.h
+ossl_ssl.o: ossl_ns_spki.h
+ossl_ssl.o: ossl_ocsp.h
+ossl_ssl.o: ossl_pkcs12.h
+ossl_ssl.o: ossl_pkcs7.h
+ossl_ssl.o: ossl_pkey.h
+ossl_ssl.o: ossl_provider.h
+ossl_ssl.o: ossl_rand.h
+ossl_ssl.o: ossl_ssl.c
+ossl_ssl.o: ossl_ssl.h
+ossl_ssl.o: ossl_ts.h
+ossl_ssl.o: ossl_x509.h
+ossl_ssl_session.o: $(RUBY_EXTCONF_H)
+ossl_ssl_session.o: $(arch_hdrdir)/ruby/config.h
+ossl_ssl_session.o: $(hdrdir)/ruby.h
+ossl_ssl_session.o: $(hdrdir)/ruby/assert.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_ssl_session.o: $(hdrdir)/ruby/defines.h
+ossl_ssl_session.o: $(hdrdir)/ruby/encoding.h
+ossl_ssl_session.o: $(hdrdir)/ruby/intern.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/abi.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/assume.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/cast.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/config.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/error.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/eval.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/event.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/gc.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/glob.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/globals.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/memory.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/method.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/module.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/value.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/variable.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_ssl_session.o: $(hdrdir)/ruby/io.h
+ossl_ssl_session.o: $(hdrdir)/ruby/missing.h
+ossl_ssl_session.o: $(hdrdir)/ruby/onigmo.h
+ossl_ssl_session.o: $(hdrdir)/ruby/oniguruma.h
+ossl_ssl_session.o: $(hdrdir)/ruby/ractor.h
+ossl_ssl_session.o: $(hdrdir)/ruby/ruby.h
+ossl_ssl_session.o: $(hdrdir)/ruby/st.h
+ossl_ssl_session.o: $(hdrdir)/ruby/subst.h
+ossl_ssl_session.o: $(hdrdir)/ruby/thread.h
+ossl_ssl_session.o: openssl_missing.h
+ossl_ssl_session.o: ossl.h
+ossl_ssl_session.o: ossl_asn1.h
+ossl_ssl_session.o: ossl_bio.h
+ossl_ssl_session.o: ossl_bn.h
+ossl_ssl_session.o: ossl_cipher.h
+ossl_ssl_session.o: ossl_config.h
+ossl_ssl_session.o: ossl_digest.h
+ossl_ssl_session.o: ossl_engine.h
+ossl_ssl_session.o: ossl_hmac.h
+ossl_ssl_session.o: ossl_kdf.h
+ossl_ssl_session.o: ossl_ns_spki.h
+ossl_ssl_session.o: ossl_ocsp.h
+ossl_ssl_session.o: ossl_pkcs12.h
+ossl_ssl_session.o: ossl_pkcs7.h
+ossl_ssl_session.o: ossl_pkey.h
+ossl_ssl_session.o: ossl_provider.h
+ossl_ssl_session.o: ossl_rand.h
+ossl_ssl_session.o: ossl_ssl.h
+ossl_ssl_session.o: ossl_ssl_session.c
+ossl_ssl_session.o: ossl_ts.h
+ossl_ssl_session.o: ossl_x509.h
+ossl_ts.o: $(RUBY_EXTCONF_H)
+ossl_ts.o: $(arch_hdrdir)/ruby/config.h
+ossl_ts.o: $(hdrdir)/ruby.h
+ossl_ts.o: $(hdrdir)/ruby/assert.h
+ossl_ts.o: $(hdrdir)/ruby/backward.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_ts.o: $(hdrdir)/ruby/defines.h
+ossl_ts.o: $(hdrdir)/ruby/encoding.h
+ossl_ts.o: $(hdrdir)/ruby/intern.h
+ossl_ts.o: $(hdrdir)/ruby/internal/abi.h
+ossl_ts.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/assume.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_ts.o: $(hdrdir)/ruby/internal/cast.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_ts.o: $(hdrdir)/ruby/internal/config.h
+ossl_ts.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_ts.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_ts.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_ts.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_ts.o: $(hdrdir)/ruby/internal/error.h
+ossl_ts.o: $(hdrdir)/ruby/internal/eval.h
+ossl_ts.o: $(hdrdir)/ruby/internal/event.h
+ossl_ts.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_ts.o: $(hdrdir)/ruby/internal/gc.h
+ossl_ts.o: $(hdrdir)/ruby/internal/glob.h
+ossl_ts.o: $(hdrdir)/ruby/internal/globals.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_ts.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_ts.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_ts.o: $(hdrdir)/ruby/internal/memory.h
+ossl_ts.o: $(hdrdir)/ruby/internal/method.h
+ossl_ts.o: $(hdrdir)/ruby/internal/module.h
+ossl_ts.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_ts.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_ts.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_ts.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_ts.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_ts.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ts.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_ts.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_ts.o: $(hdrdir)/ruby/internal/value.h
+ossl_ts.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_ts.o: $(hdrdir)/ruby/internal/variable.h
+ossl_ts.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_ts.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_ts.o: $(hdrdir)/ruby/io.h
+ossl_ts.o: $(hdrdir)/ruby/missing.h
+ossl_ts.o: $(hdrdir)/ruby/onigmo.h
+ossl_ts.o: $(hdrdir)/ruby/oniguruma.h
+ossl_ts.o: $(hdrdir)/ruby/ractor.h
+ossl_ts.o: $(hdrdir)/ruby/ruby.h
+ossl_ts.o: $(hdrdir)/ruby/st.h
+ossl_ts.o: $(hdrdir)/ruby/subst.h
+ossl_ts.o: $(hdrdir)/ruby/thread.h
+ossl_ts.o: openssl_missing.h
+ossl_ts.o: ossl.h
+ossl_ts.o: ossl_asn1.h
+ossl_ts.o: ossl_bio.h
+ossl_ts.o: ossl_bn.h
+ossl_ts.o: ossl_cipher.h
+ossl_ts.o: ossl_config.h
+ossl_ts.o: ossl_digest.h
+ossl_ts.o: ossl_engine.h
+ossl_ts.o: ossl_hmac.h
+ossl_ts.o: ossl_kdf.h
+ossl_ts.o: ossl_ns_spki.h
+ossl_ts.o: ossl_ocsp.h
+ossl_ts.o: ossl_pkcs12.h
+ossl_ts.o: ossl_pkcs7.h
+ossl_ts.o: ossl_pkey.h
+ossl_ts.o: ossl_provider.h
+ossl_ts.o: ossl_rand.h
+ossl_ts.o: ossl_ssl.h
+ossl_ts.o: ossl_ts.c
+ossl_ts.o: ossl_ts.h
+ossl_ts.o: ossl_x509.h
+ossl_x509.o: $(RUBY_EXTCONF_H)
+ossl_x509.o: $(arch_hdrdir)/ruby/config.h
+ossl_x509.o: $(hdrdir)/ruby.h
+ossl_x509.o: $(hdrdir)/ruby/assert.h
+ossl_x509.o: $(hdrdir)/ruby/backward.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_x509.o: $(hdrdir)/ruby/defines.h
+ossl_x509.o: $(hdrdir)/ruby/encoding.h
+ossl_x509.o: $(hdrdir)/ruby/intern.h
+ossl_x509.o: $(hdrdir)/ruby/internal/abi.h
+ossl_x509.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_x509.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_x509.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_x509.o: $(hdrdir)/ruby/io.h
+ossl_x509.o: $(hdrdir)/ruby/missing.h
+ossl_x509.o: $(hdrdir)/ruby/onigmo.h
+ossl_x509.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509.o: $(hdrdir)/ruby/ractor.h
+ossl_x509.o: $(hdrdir)/ruby/ruby.h
+ossl_x509.o: $(hdrdir)/ruby/st.h
+ossl_x509.o: $(hdrdir)/ruby/subst.h
+ossl_x509.o: $(hdrdir)/ruby/thread.h
+ossl_x509.o: openssl_missing.h
+ossl_x509.o: ossl.h
+ossl_x509.o: ossl_asn1.h
+ossl_x509.o: ossl_bio.h
+ossl_x509.o: ossl_bn.h
+ossl_x509.o: ossl_cipher.h
+ossl_x509.o: ossl_config.h
+ossl_x509.o: ossl_digest.h
+ossl_x509.o: ossl_engine.h
+ossl_x509.o: ossl_hmac.h
+ossl_x509.o: ossl_kdf.h
+ossl_x509.o: ossl_ns_spki.h
+ossl_x509.o: ossl_ocsp.h
+ossl_x509.o: ossl_pkcs12.h
+ossl_x509.o: ossl_pkcs7.h
+ossl_x509.o: ossl_pkey.h
+ossl_x509.o: ossl_provider.h
+ossl_x509.o: ossl_rand.h
+ossl_x509.o: ossl_ssl.h
+ossl_x509.o: ossl_ts.h
+ossl_x509.o: ossl_x509.c
+ossl_x509.o: ossl_x509.h
+ossl_x509attr.o: $(RUBY_EXTCONF_H)
+ossl_x509attr.o: $(arch_hdrdir)/ruby/config.h
+ossl_x509attr.o: $(hdrdir)/ruby.h
+ossl_x509attr.o: $(hdrdir)/ruby/assert.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_x509attr.o: $(hdrdir)/ruby/defines.h
+ossl_x509attr.o: $(hdrdir)/ruby/encoding.h
+ossl_x509attr.o: $(hdrdir)/ruby/intern.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/abi.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_x509attr.o: $(hdrdir)/ruby/io.h
+ossl_x509attr.o: $(hdrdir)/ruby/missing.h
+ossl_x509attr.o: $(hdrdir)/ruby/onigmo.h
+ossl_x509attr.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509attr.o: $(hdrdir)/ruby/ractor.h
+ossl_x509attr.o: $(hdrdir)/ruby/ruby.h
+ossl_x509attr.o: $(hdrdir)/ruby/st.h
+ossl_x509attr.o: $(hdrdir)/ruby/subst.h
+ossl_x509attr.o: $(hdrdir)/ruby/thread.h
+ossl_x509attr.o: openssl_missing.h
+ossl_x509attr.o: ossl.h
+ossl_x509attr.o: ossl_asn1.h
+ossl_x509attr.o: ossl_bio.h
+ossl_x509attr.o: ossl_bn.h
+ossl_x509attr.o: ossl_cipher.h
+ossl_x509attr.o: ossl_config.h
+ossl_x509attr.o: ossl_digest.h
+ossl_x509attr.o: ossl_engine.h
+ossl_x509attr.o: ossl_hmac.h
+ossl_x509attr.o: ossl_kdf.h
+ossl_x509attr.o: ossl_ns_spki.h
+ossl_x509attr.o: ossl_ocsp.h
+ossl_x509attr.o: ossl_pkcs12.h
+ossl_x509attr.o: ossl_pkcs7.h
+ossl_x509attr.o: ossl_pkey.h
+ossl_x509attr.o: ossl_provider.h
+ossl_x509attr.o: ossl_rand.h
+ossl_x509attr.o: ossl_ssl.h
+ossl_x509attr.o: ossl_ts.h
+ossl_x509attr.o: ossl_x509.h
+ossl_x509attr.o: ossl_x509attr.c
+ossl_x509cert.o: $(RUBY_EXTCONF_H)
+ossl_x509cert.o: $(arch_hdrdir)/ruby/config.h
+ossl_x509cert.o: $(hdrdir)/ruby.h
+ossl_x509cert.o: $(hdrdir)/ruby/assert.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_x509cert.o: $(hdrdir)/ruby/defines.h
+ossl_x509cert.o: $(hdrdir)/ruby/encoding.h
+ossl_x509cert.o: $(hdrdir)/ruby/intern.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/abi.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_x509cert.o: $(hdrdir)/ruby/io.h
+ossl_x509cert.o: $(hdrdir)/ruby/missing.h
+ossl_x509cert.o: $(hdrdir)/ruby/onigmo.h
+ossl_x509cert.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509cert.o: $(hdrdir)/ruby/ractor.h
+ossl_x509cert.o: $(hdrdir)/ruby/ruby.h
+ossl_x509cert.o: $(hdrdir)/ruby/st.h
+ossl_x509cert.o: $(hdrdir)/ruby/subst.h
+ossl_x509cert.o: $(hdrdir)/ruby/thread.h
+ossl_x509cert.o: openssl_missing.h
+ossl_x509cert.o: ossl.h
+ossl_x509cert.o: ossl_asn1.h
+ossl_x509cert.o: ossl_bio.h
+ossl_x509cert.o: ossl_bn.h
+ossl_x509cert.o: ossl_cipher.h
+ossl_x509cert.o: ossl_config.h
+ossl_x509cert.o: ossl_digest.h
+ossl_x509cert.o: ossl_engine.h
+ossl_x509cert.o: ossl_hmac.h
+ossl_x509cert.o: ossl_kdf.h
+ossl_x509cert.o: ossl_ns_spki.h
+ossl_x509cert.o: ossl_ocsp.h
+ossl_x509cert.o: ossl_pkcs12.h
+ossl_x509cert.o: ossl_pkcs7.h
+ossl_x509cert.o: ossl_pkey.h
+ossl_x509cert.o: ossl_provider.h
+ossl_x509cert.o: ossl_rand.h
+ossl_x509cert.o: ossl_ssl.h
+ossl_x509cert.o: ossl_ts.h
+ossl_x509cert.o: ossl_x509.h
+ossl_x509cert.o: ossl_x509cert.c
+ossl_x509crl.o: $(RUBY_EXTCONF_H)
+ossl_x509crl.o: $(arch_hdrdir)/ruby/config.h
+ossl_x509crl.o: $(hdrdir)/ruby.h
+ossl_x509crl.o: $(hdrdir)/ruby/assert.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_x509crl.o: $(hdrdir)/ruby/defines.h
+ossl_x509crl.o: $(hdrdir)/ruby/encoding.h
+ossl_x509crl.o: $(hdrdir)/ruby/intern.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/abi.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_x509crl.o: $(hdrdir)/ruby/io.h
+ossl_x509crl.o: $(hdrdir)/ruby/missing.h
+ossl_x509crl.o: $(hdrdir)/ruby/onigmo.h
+ossl_x509crl.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509crl.o: $(hdrdir)/ruby/ractor.h
+ossl_x509crl.o: $(hdrdir)/ruby/ruby.h
+ossl_x509crl.o: $(hdrdir)/ruby/st.h
+ossl_x509crl.o: $(hdrdir)/ruby/subst.h
+ossl_x509crl.o: $(hdrdir)/ruby/thread.h
+ossl_x509crl.o: openssl_missing.h
+ossl_x509crl.o: ossl.h
+ossl_x509crl.o: ossl_asn1.h
+ossl_x509crl.o: ossl_bio.h
+ossl_x509crl.o: ossl_bn.h
+ossl_x509crl.o: ossl_cipher.h
+ossl_x509crl.o: ossl_config.h
+ossl_x509crl.o: ossl_digest.h
+ossl_x509crl.o: ossl_engine.h
+ossl_x509crl.o: ossl_hmac.h
+ossl_x509crl.o: ossl_kdf.h
+ossl_x509crl.o: ossl_ns_spki.h
+ossl_x509crl.o: ossl_ocsp.h
+ossl_x509crl.o: ossl_pkcs12.h
+ossl_x509crl.o: ossl_pkcs7.h
+ossl_x509crl.o: ossl_pkey.h
+ossl_x509crl.o: ossl_provider.h
+ossl_x509crl.o: ossl_rand.h
+ossl_x509crl.o: ossl_ssl.h
+ossl_x509crl.o: ossl_ts.h
+ossl_x509crl.o: ossl_x509.h
+ossl_x509crl.o: ossl_x509crl.c
+ossl_x509ext.o: $(RUBY_EXTCONF_H)
+ossl_x509ext.o: $(arch_hdrdir)/ruby/config.h
+ossl_x509ext.o: $(hdrdir)/ruby.h
+ossl_x509ext.o: $(hdrdir)/ruby/assert.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_x509ext.o: $(hdrdir)/ruby/defines.h
+ossl_x509ext.o: $(hdrdir)/ruby/encoding.h
+ossl_x509ext.o: $(hdrdir)/ruby/intern.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/abi.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_x509ext.o: $(hdrdir)/ruby/io.h
+ossl_x509ext.o: $(hdrdir)/ruby/missing.h
+ossl_x509ext.o: $(hdrdir)/ruby/onigmo.h
+ossl_x509ext.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509ext.o: $(hdrdir)/ruby/ractor.h
+ossl_x509ext.o: $(hdrdir)/ruby/ruby.h
+ossl_x509ext.o: $(hdrdir)/ruby/st.h
+ossl_x509ext.o: $(hdrdir)/ruby/subst.h
+ossl_x509ext.o: $(hdrdir)/ruby/thread.h
+ossl_x509ext.o: openssl_missing.h
+ossl_x509ext.o: ossl.h
+ossl_x509ext.o: ossl_asn1.h
+ossl_x509ext.o: ossl_bio.h
+ossl_x509ext.o: ossl_bn.h
+ossl_x509ext.o: ossl_cipher.h
+ossl_x509ext.o: ossl_config.h
+ossl_x509ext.o: ossl_digest.h
+ossl_x509ext.o: ossl_engine.h
+ossl_x509ext.o: ossl_hmac.h
+ossl_x509ext.o: ossl_kdf.h
+ossl_x509ext.o: ossl_ns_spki.h
+ossl_x509ext.o: ossl_ocsp.h
+ossl_x509ext.o: ossl_pkcs12.h
+ossl_x509ext.o: ossl_pkcs7.h
+ossl_x509ext.o: ossl_pkey.h
+ossl_x509ext.o: ossl_provider.h
+ossl_x509ext.o: ossl_rand.h
+ossl_x509ext.o: ossl_ssl.h
+ossl_x509ext.o: ossl_ts.h
+ossl_x509ext.o: ossl_x509.h
+ossl_x509ext.o: ossl_x509ext.c
+ossl_x509name.o: $(RUBY_EXTCONF_H)
+ossl_x509name.o: $(arch_hdrdir)/ruby/config.h
+ossl_x509name.o: $(hdrdir)/ruby.h
+ossl_x509name.o: $(hdrdir)/ruby/assert.h
+ossl_x509name.o: $(hdrdir)/ruby/backward.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_x509name.o: $(hdrdir)/ruby/defines.h
+ossl_x509name.o: $(hdrdir)/ruby/encoding.h
+ossl_x509name.o: $(hdrdir)/ruby/intern.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/abi.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_x509name.o: $(hdrdir)/ruby/io.h
+ossl_x509name.o: $(hdrdir)/ruby/missing.h
+ossl_x509name.o: $(hdrdir)/ruby/onigmo.h
+ossl_x509name.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509name.o: $(hdrdir)/ruby/ractor.h
+ossl_x509name.o: $(hdrdir)/ruby/ruby.h
+ossl_x509name.o: $(hdrdir)/ruby/st.h
+ossl_x509name.o: $(hdrdir)/ruby/subst.h
+ossl_x509name.o: $(hdrdir)/ruby/thread.h
+ossl_x509name.o: openssl_missing.h
+ossl_x509name.o: ossl.h
+ossl_x509name.o: ossl_asn1.h
+ossl_x509name.o: ossl_bio.h
+ossl_x509name.o: ossl_bn.h
+ossl_x509name.o: ossl_cipher.h
+ossl_x509name.o: ossl_config.h
+ossl_x509name.o: ossl_digest.h
+ossl_x509name.o: ossl_engine.h
+ossl_x509name.o: ossl_hmac.h
+ossl_x509name.o: ossl_kdf.h
+ossl_x509name.o: ossl_ns_spki.h
+ossl_x509name.o: ossl_ocsp.h
+ossl_x509name.o: ossl_pkcs12.h
+ossl_x509name.o: ossl_pkcs7.h
+ossl_x509name.o: ossl_pkey.h
+ossl_x509name.o: ossl_provider.h
+ossl_x509name.o: ossl_rand.h
+ossl_x509name.o: ossl_ssl.h
+ossl_x509name.o: ossl_ts.h
+ossl_x509name.o: ossl_x509.h
+ossl_x509name.o: ossl_x509name.c
+ossl_x509req.o: $(RUBY_EXTCONF_H)
+ossl_x509req.o: $(arch_hdrdir)/ruby/config.h
+ossl_x509req.o: $(hdrdir)/ruby.h
+ossl_x509req.o: $(hdrdir)/ruby/assert.h
+ossl_x509req.o: $(hdrdir)/ruby/backward.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_x509req.o: $(hdrdir)/ruby/defines.h
+ossl_x509req.o: $(hdrdir)/ruby/encoding.h
+ossl_x509req.o: $(hdrdir)/ruby/intern.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/abi.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_x509req.o: $(hdrdir)/ruby/io.h
+ossl_x509req.o: $(hdrdir)/ruby/missing.h
+ossl_x509req.o: $(hdrdir)/ruby/onigmo.h
+ossl_x509req.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509req.o: $(hdrdir)/ruby/ractor.h
+ossl_x509req.o: $(hdrdir)/ruby/ruby.h
+ossl_x509req.o: $(hdrdir)/ruby/st.h
+ossl_x509req.o: $(hdrdir)/ruby/subst.h
+ossl_x509req.o: $(hdrdir)/ruby/thread.h
+ossl_x509req.o: openssl_missing.h
+ossl_x509req.o: ossl.h
+ossl_x509req.o: ossl_asn1.h
+ossl_x509req.o: ossl_bio.h
+ossl_x509req.o: ossl_bn.h
+ossl_x509req.o: ossl_cipher.h
+ossl_x509req.o: ossl_config.h
+ossl_x509req.o: ossl_digest.h
+ossl_x509req.o: ossl_engine.h
+ossl_x509req.o: ossl_hmac.h
+ossl_x509req.o: ossl_kdf.h
+ossl_x509req.o: ossl_ns_spki.h
+ossl_x509req.o: ossl_ocsp.h
+ossl_x509req.o: ossl_pkcs12.h
+ossl_x509req.o: ossl_pkcs7.h
+ossl_x509req.o: ossl_pkey.h
+ossl_x509req.o: ossl_provider.h
+ossl_x509req.o: ossl_rand.h
+ossl_x509req.o: ossl_ssl.h
+ossl_x509req.o: ossl_ts.h
+ossl_x509req.o: ossl_x509.h
+ossl_x509req.o: ossl_x509req.c
+ossl_x509revoked.o: $(RUBY_EXTCONF_H)
+ossl_x509revoked.o: $(arch_hdrdir)/ruby/config.h
+ossl_x509revoked.o: $(hdrdir)/ruby.h
+ossl_x509revoked.o: $(hdrdir)/ruby/assert.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_x509revoked.o: $(hdrdir)/ruby/defines.h
+ossl_x509revoked.o: $(hdrdir)/ruby/encoding.h
+ossl_x509revoked.o: $(hdrdir)/ruby/intern.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/abi.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_x509revoked.o: $(hdrdir)/ruby/io.h
+ossl_x509revoked.o: $(hdrdir)/ruby/missing.h
+ossl_x509revoked.o: $(hdrdir)/ruby/onigmo.h
+ossl_x509revoked.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509revoked.o: $(hdrdir)/ruby/ractor.h
+ossl_x509revoked.o: $(hdrdir)/ruby/ruby.h
+ossl_x509revoked.o: $(hdrdir)/ruby/st.h
+ossl_x509revoked.o: $(hdrdir)/ruby/subst.h
+ossl_x509revoked.o: $(hdrdir)/ruby/thread.h
+ossl_x509revoked.o: openssl_missing.h
+ossl_x509revoked.o: ossl.h
+ossl_x509revoked.o: ossl_asn1.h
+ossl_x509revoked.o: ossl_bio.h
+ossl_x509revoked.o: ossl_bn.h
+ossl_x509revoked.o: ossl_cipher.h
+ossl_x509revoked.o: ossl_config.h
+ossl_x509revoked.o: ossl_digest.h
+ossl_x509revoked.o: ossl_engine.h
+ossl_x509revoked.o: ossl_hmac.h
+ossl_x509revoked.o: ossl_kdf.h
+ossl_x509revoked.o: ossl_ns_spki.h
+ossl_x509revoked.o: ossl_ocsp.h
+ossl_x509revoked.o: ossl_pkcs12.h
+ossl_x509revoked.o: ossl_pkcs7.h
+ossl_x509revoked.o: ossl_pkey.h
+ossl_x509revoked.o: ossl_provider.h
+ossl_x509revoked.o: ossl_rand.h
+ossl_x509revoked.o: ossl_ssl.h
+ossl_x509revoked.o: ossl_ts.h
+ossl_x509revoked.o: ossl_x509.h
+ossl_x509revoked.o: ossl_x509revoked.c
+ossl_x509store.o: $(RUBY_EXTCONF_H)
+ossl_x509store.o: $(arch_hdrdir)/ruby/config.h
+ossl_x509store.o: $(hdrdir)/ruby.h
+ossl_x509store.o: $(hdrdir)/ruby/assert.h
+ossl_x509store.o: $(hdrdir)/ruby/backward.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_x509store.o: $(hdrdir)/ruby/defines.h
+ossl_x509store.o: $(hdrdir)/ruby/encoding.h
+ossl_x509store.o: $(hdrdir)/ruby/intern.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/abi.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/set.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/stdckdint.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_x509store.o: $(hdrdir)/ruby/io.h
+ossl_x509store.o: $(hdrdir)/ruby/missing.h
+ossl_x509store.o: $(hdrdir)/ruby/onigmo.h
+ossl_x509store.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509store.o: $(hdrdir)/ruby/ractor.h
+ossl_x509store.o: $(hdrdir)/ruby/ruby.h
+ossl_x509store.o: $(hdrdir)/ruby/st.h
+ossl_x509store.o: $(hdrdir)/ruby/subst.h
+ossl_x509store.o: $(hdrdir)/ruby/thread.h
+ossl_x509store.o: openssl_missing.h
+ossl_x509store.o: ossl.h
+ossl_x509store.o: ossl_asn1.h
+ossl_x509store.o: ossl_bio.h
+ossl_x509store.o: ossl_bn.h
+ossl_x509store.o: ossl_cipher.h
+ossl_x509store.o: ossl_config.h
+ossl_x509store.o: ossl_digest.h
+ossl_x509store.o: ossl_engine.h
+ossl_x509store.o: ossl_hmac.h
+ossl_x509store.o: ossl_kdf.h
+ossl_x509store.o: ossl_ns_spki.h
+ossl_x509store.o: ossl_ocsp.h
+ossl_x509store.o: ossl_pkcs12.h
+ossl_x509store.o: ossl_pkcs7.h
+ossl_x509store.o: ossl_pkey.h
+ossl_x509store.o: ossl_provider.h
+ossl_x509store.o: ossl_rand.h
+ossl_x509store.o: ossl_ssl.h
+ossl_x509store.o: ossl_ts.h
+ossl_x509store.o: ossl_x509.h
+ossl_x509store.o: ossl_x509store.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index 11f74ff3d8..1f32980940 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -1,123 +1,189 @@
+# -*- coding: us-ascii -*-
+# frozen_string_literal: true
=begin
-= $RCSfile$ -- Generator for Makefile
-
= Info
'OpenSSL for Ruby 2' project
Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
All rights reserved.
= Licence
- This program is licenced under the same licence as Ruby.
- (See the file 'LICENCE'.)
-
-= Version
- $Id$
+ This program is licensed under the same licence as Ruby.
+ (See the file 'COPYING'.)
=end
require "mkmf"
-dir_config("openssl")
-dir_config("kerberos")
+ssl_dirs = dir_config("openssl")
+dir_config_given = ssl_dirs.any?
-message "=== OpenSSL for Ruby configurator ===\n"
+_, ssl_ldir = ssl_dirs
+if ssl_ldir&.split(File::PATH_SEPARATOR)&.none? { |dir| File.directory?(dir) }
+ # According to the `mkmf.rb#dir_config`, the `--with-openssl-dir=<dir>` uses
+ # the value of the `File.basename(RbConfig::MAKEFILE_CONFIG["libdir"])` as a
+ # loaded library directory name.
+ ruby_ldir_name = File.basename(RbConfig::MAKEFILE_CONFIG["libdir"])
-##
-# Adds -Wall -DOSSL_DEBUG for compilation and some more targets when GCC is used
-# To turn it on, use: --with-debug or --enable-debug
-#
-if with_config("debug") or enable_config("debug")
- $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
-
- if /gcc/ =~ CONFIG["CC"]
- $CPPFLAGS += " -Wall" unless $CPPFLAGS.split.include? "-Wall"
- end
+ raise "OpenSSL library directory could not be found in '#{ssl_ldir}'. " \
+ "You might want to fix this error in one of the following ways.\n" \
+ " * Recompile OpenSSL by configuring it with --libdir=#{ruby_ldir_name} " \
+ " to specify the OpenSSL library directory.\n" \
+ " * Recompile Ruby by configuring it with --libdir=<dir> to specify the " \
+ "Ruby library directory.\n" \
+ " * Compile this openssl gem with --with-openssl-include=<dir> and " \
+ "--with-openssl-lib=<dir> options to specify the OpenSSL include and " \
+ "library directories."
end
-message "=== Checking for system dependent stuff... ===\n"
+Logging::message "=== OpenSSL for Ruby configurator ===\n"
+
+$defs.push("-D""OPENSSL_SUPPRESS_DEPRECATED")
+
+# Missing in TruffleRuby
+have_func("rb_call_super_kw(0, NULL, 0)", "ruby.h")
+# Ruby 3.1
+have_func("rb_io_descriptor", "ruby/io.h")
+have_func("rb_io_maybe_wait(0, Qnil, Qnil, Qnil)", "ruby/io.h")
+# Ruby 3.2
+have_func("rb_io_timeout", "ruby/io.h")
+
+Logging::message "=== Checking for system dependent stuff... ===\n"
have_library("nsl", "t_open")
have_library("socket", "socket")
-have_header("unistd.h")
-have_header("sys/time.h")
-have_header("assert.h")
+if $mswin || $mingw
+ have_library("ws2_32")
+end
-message "=== Checking for required stuff... ===\n"
if $mingw
- have_library("wsock32")
- have_library("gdi32")
+ append_cflags '-D_FORTIFY_SOURCE=2'
+ append_ldflags '-fstack-protector'
+ have_library 'ssp'
end
-result = have_header("openssl/ssl.h")
-result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")}
-result &&= %w[ssl ssleay32].any? {|lib| have_library(lib, "SSL_library_init")}
-if !result
- unless pkg_config("openssl") and have_header("openssl/ssl.h")
- message "=== Checking for required stuff failed. ===\n"
- message "Makefile wasn't created. Fix the errors above.\n"
- exit 1
+
+def find_openssl_library
+ if $mswin || $mingw
+ # required for static OpenSSL libraries
+ have_library("crypt32")
+ end
+
+ return false unless have_header("openssl/ssl.h")
+
+ ret = have_library("crypto", "CRYPTO_malloc") &&
+ have_library("ssl", "SSL_new")
+ return ret if ret
+
+ if $mswin
+ # OpenSSL >= 1.1.0: libcrypto.lib and libssl.lib.
+ if have_library("libcrypto", "CRYPTO_malloc") &&
+ have_library("libssl", "SSL_new")
+ return true
+ end
+
+ # LibreSSL: libcrypto-##.lib and libssl-##.lib, where ## is the ABI version
+ # number. We have to find the version number out by scanning libpath.
+ libpath = $LIBPATH.dup
+ libpath |= ENV["LIB"].split(File::PATH_SEPARATOR)
+ libpath.map! { |d| d.tr(File::ALT_SEPARATOR, File::SEPARATOR) }
+
+ ret = [
+ ["crypto", "CRYPTO_malloc"],
+ ["ssl", "SSL_new"]
+ ].all? do |base, func|
+ result = false
+ libs = ["lib#{base}-[0-9][0-9]", "lib#{base}-[0-9][0-9][0-9]"]
+ libs = Dir.glob(libs.map{|l| libpath.map{|d| File.join(d, l + ".*")}}.flatten).map{|path| File.basename(path, ".*")}.uniq
+ libs.each do |lib|
+ result = have_library(lib, func)
+ break if result
+ end
+ result
+ end
+ return ret if ret
end
+ return false
end
-unless have_header("openssl/conf_api.h")
- message "OpenSSL 0.9.6 or later required.\n"
- exit 1
+Logging::message "=== Checking for required stuff... ===\n"
+pkg_config_found = !dir_config_given && pkg_config("openssl") && have_header("openssl/ssl.h")
+
+if !pkg_config_found && !find_openssl_library
+ Logging::message "=== Checking for required stuff failed. ===\n"
+ Logging::message "Makefile wasn't created. Fix the errors above.\n"
+ raise "OpenSSL library could not be found. You might want to use " \
+ "--with-openssl-dir=<dir> option to specify the prefix where OpenSSL " \
+ "is installed."
end
-message "=== Checking for OpenSSL features... ===\n"
-have_func("ERR_peek_last_error")
-have_func("BN_mod_add")
-have_func("BN_mod_sqr")
-have_func("BN_mod_sub")
-have_func("BN_pseudo_rand_range")
-have_func("BN_rand_range")
-have_func("CONF_get1_default_config_file")
-have_func("EVP_CIPHER_CTX_copy")
-have_func("EVP_CIPHER_CTX_set_padding")
-have_func("EVP_CipherFinal_ex")
-have_func("EVP_CipherInit_ex")
-have_func("EVP_DigestFinal_ex")
-have_func("EVP_DigestInit_ex")
-have_func("EVP_MD_CTX_cleanup")
-have_func("EVP_MD_CTX_create")
-have_func("EVP_MD_CTX_destroy")
-have_func("EVP_MD_CTX_init")
-have_func("HMAC_CTX_cleanup")
-have_func("HMAC_CTX_copy")
-have_func("HMAC_CTX_init")
-have_func("PEM_def_callback")
-have_func("X509V3_set_nconf")
-have_func("X509V3_EXT_nconf_nid")
-have_func("X509_CRL_add0_revoked")
-have_func("X509_CRL_set_issuer_name")
-have_func("X509_CRL_set_version")
-have_func("X509_CRL_sort")
-have_func("X509_STORE_get_ex_data")
-have_func("X509_STORE_set_ex_data")
-have_func("OBJ_NAME_do_all_sorted")
-have_func("OPENSSL_cleanse")
-if try_compile("#define FOO(a, ...) foo(a, ##__VA_ARGS__)\n int x(){FOO(1);FOO(1,2);FOO(1,2,3);}\n")
- $defs.push("-DHAVE_VA_ARGS_MACRO")
+version_ok = if have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h")
+ is_libressl = true
+ checking_for("LibreSSL version >= 3.9.0") {
+ try_static_assert("LIBRESSL_VERSION_NUMBER >= 0x30900000L", "openssl/opensslv.h") }
+else
+ is_openssl = true
+ checking_for("OpenSSL version >= 1.1.1") {
+ try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10101000L", "openssl/opensslv.h") }
end
-if have_header("openssl/engine.h")
- have_func("ENGINE_add")
- have_func("ENGINE_load_builtin_engines")
- have_func("ENGINE_load_openbsd_dev_crypto")
- have_func("ENGINE_get_digest")
- have_func("ENGINE_get_cipher")
- have_func("ENGINE_cleanup")
+unless version_ok
+ raise "OpenSSL >= 1.1.1 or LibreSSL >= 3.9.0 is required"
end
-if try_compile(<<SRC)
-#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
-# error "OpenSSL version is less than 0.9.7."
-#endif
-SRC
- have_header("openssl/ocsp.h")
+
+# Prevent wincrypt.h from being included, which defines conflicting macro with openssl/x509.h
+if is_libressl && ($mswin || $mingw)
+ $defs.push("-DNOCRYPT")
end
-have_struct_member("EVP_CIPHER_CTX", "flags", "openssl/evp.h")
-have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h")
-have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h")
-message "=== Checking done. ===\n"
+Logging::message "=== Checking for OpenSSL features... ===\n"
+evp_h = "openssl/evp.h".freeze
+ts_h = "openssl/ts.h".freeze
+ssl_h = "openssl/ssl.h".freeze
+stack_h = "openssl/stack.h".freeze
+
+# compile options
+have_func("RAND_egd()", "openssl/rand.h")
+
+# added in OpenSSL 1.0.2, not in LibreSSL yet
+have_func("SSL_CTX_set1_sigalgs_list(NULL, NULL)", ssl_h)
+# added in OpenSSL 1.0.2, not in LibreSSL or AWS-LC yet
+have_func("SSL_CTX_set1_client_sigalgs_list(NULL, NULL)", ssl_h)
+
+# added in 1.1.0, currently not in LibreSSL
+have_func("EVP_PBE_scrypt(\"\", 0, (unsigned char *)\"\", 0, 0, 0, 0, 0, NULL, 0)", evp_h)
+
+# added in OpenSSL 1.1.1 and LibreSSL 3.5.0, then removed in LibreSSL 4.0.0
+have_func("EVP_PKEY_check(NULL)", evp_h)
+
+# added in OpenSSL 1.1.1, currently not in LibreSSL
+have_func("OPENSSL_sk_new_reserve(NULL, 0)", stack_h)
+
+# added in 3.0.0
+have_func("SSL_CTX_set0_tmp_dh_pkey(NULL, NULL)", ssl_h)
+have_func("ERR_get_error_all(NULL, NULL, NULL, NULL, NULL)", "openssl/err.h")
+have_func("SSL_CTX_load_verify_file(NULL, \"\")", ssl_h)
+have_func("BN_check_prime(NULL, NULL, NULL)", "openssl/bn.h")
+have_func("EVP_MD_CTX_get0_md(NULL)", evp_h)
+have_func("EVP_MD_CTX_get_pkey_ctx(NULL)", evp_h)
+have_func("EVP_PKEY_eq(NULL, NULL)", evp_h)
+have_func("EVP_PKEY_dup(NULL)", evp_h)
+
+# added in 3.2.0
+have_func("SSL_get0_group_name(NULL)", ssl_h)
+
+# added in 3.4.0
+have_func("TS_VERIFY_CTX_set0_certs(NULL, NULL)", ts_h)
+
+# added in 3.5.0
+have_func("SSL_get0_peer_signature_name(NULL, NULL)", ssl_h)
+
+# added in 4.0.0
+have_func("ASN1_BIT_STRING_set1(NULL, NULL, 0, 0)", "openssl/asn1.h")
+
+Logging::message "=== Checking done. ===\n"
+
+# Append flags from environment variables.
+extcflags = ENV["RUBY_OPENSSL_EXTCFLAGS"]
+append_cflags(extcflags.split) if extcflags
+extldflags = ENV["RUBY_OPENSSL_EXTLDFLAGS"]
+append_ldflags(extldflags.split) if extldflags
create_header
create_makefile("openssl")
-message "Done.\n"
+Logging::message "Done.\n"
diff --git a/ext/openssl/lib/net/ftptls.rb b/ext/openssl/lib/net/ftptls.rb
deleted file mode 100644
index f433457923..0000000000
--- a/ext/openssl/lib/net/ftptls.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-=begin
-= $RCSfile$ -- SSL/TLS enhancement for Net::HTTP.
-
-= Info
- 'OpenSSL for Ruby 2' project
- Copyright (C) 2003 Blaz Grilc <farmer@gmx.co.uk>
- All rights reserved.
-
-= Licence
- This program is licenced under the same licence as Ruby.
- (See the file 'LICENCE'.)
-
-= Requirements
-
-= Version
- $Id$
-
-= Notes
- Tested on FreeBSD 5-CURRENT and 4-STABLE
- - ruby 1.6.8 (2003-01-17) [i386-freebsd5]
- - OpenSSL 0.9.7a Feb 19 2003
- - ruby-openssl-0.2.0.p0
- tested on ftp server: glftpd 1.30
-=end
-
-require 'socket'
-require 'openssl'
-require 'net/ftp'
-
-module Net
- class FTPTLS < FTP
- def login(user = "anonymous", passwd = nil, acct = nil)
- ctx = OpenSSL::SSL::SSLContext.new('SSLv23')
- ctx.key = nil
- ctx.cert = nil
- voidcmd("AUTH TLS")
- @sock = OpenSSL::SSL::SSLSocket.new(@sock, ctx)
- @sock.connect
- super(user, passwd, acct)
- voidcmd("PBSZ 0")
- end
- end
-end
diff --git a/ext/openssl/lib/net/telnets.rb b/ext/openssl/lib/net/telnets.rb
deleted file mode 100644
index a872f41e6a..0000000000
--- a/ext/openssl/lib/net/telnets.rb
+++ /dev/null
@@ -1,248 +0,0 @@
-=begin
-= $RCSfile$ -- SSL/TLS enhancement for Net::Telnet.
-
-= Info
- 'OpenSSL for Ruby 2' project
- Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
- All rights reserved.
-
-= Licence
- This program is licenced under the same licence as Ruby.
- (See the file 'LICENCE'.)
-
-= Version
- $Id$
-
- 2001/11/06: Contiributed to Ruby/OpenSSL project.
-
-== class Net::Telnet
-
-This class will initiate SSL/TLS session automaticaly if the server
-sent OPT_STARTTLS. Some options are added for SSL/TLS.
-
- host = Net::Telnet::new({
- "Host" => "localhost",
- "Port" => "telnets",
- ## follows are new options.
- 'CertFile' => "user.crt",
- 'KeyFile' => "user.key",
- 'CAFile' => "/some/where/certs/casert.pem",
- 'CAPath' => "/some/where/caserts",
- 'VerifyMode' => SSL::VERIFY_PEER,
- 'VerifyCallback' => verify_proc
- })
-
-Or, the new options ('Cert', 'Key' and 'CACert') are available from
-Michal Rokos's OpenSSL module.
-
- cert_data = File.open("user.crt"){|io| io.read }
- pkey_data = File.open("user.key"){|io| io.read }
- cacert_data = File.open("your_ca.pem"){|io| io.read }
- host = Net::Telnet::new({
- "Host" => "localhost",
- "Port" => "telnets",
- 'Cert' => OpenSSL::X509::Certificate.new(cert_data)
- 'Key' => OpenSSL::PKey::RSA.new(pkey_data)
- 'CACert' => OpenSSL::X509::Certificate.new(cacert_data)
- 'CAFile' => "/some/where/certs/casert.pem",
- 'CAPath' => "/some/where/caserts",
- 'VerifyMode' => SSL::VERIFY_PEER,
- 'VerifyCallback' => verify_proc
- })
-
-This class is expected to be a superset of usual Net::Telnet.
-=end
-
-require "net/telnet"
-require "openssl"
-
-module Net
- class Telnet
- attr_reader :ssl
-
- OPT_STARTTLS = 46.chr # "\056" # "\x2e" # Start TLS
- TLS_FOLLOWS = 1.chr # "\001" # "\x01" # FOLLOWS (for STARTTLS)
-
- alias preprocess_orig preprocess
-
- def ssl?; @ssl; end
-
- def preprocess(string)
- # combine CR+NULL into CR
- string = string.gsub(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"]
-
- # combine EOL into "\n"
- string = string.gsub(/#{EOL}/no, "\n") unless @options["Binmode"]
-
- string.gsub(/#{IAC}(
- [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]|
- [#{DO}#{DONT}#{WILL}#{WONT}][#{OPT_BINARY}-#{OPT_EXOPL}]|
- #{SB}[#{OPT_BINARY}-#{OPT_EXOPL}]
- (#{IAC}#{IAC}|[^#{IAC}])+#{IAC}#{SE}
- )/xno) do
- if IAC == $1 # handle escaped IAC characters
- IAC
- elsif AYT == $1 # respond to "IAC AYT" (are you there)
- self.write("nobody here but us pigeons" + EOL)
- ''
- elsif DO[0] == $1[0] # respond to "IAC DO x"
- if OPT_BINARY[0] == $1[1]
- @telnet_option["BINARY"] = true
- self.write(IAC + WILL + OPT_BINARY)
- elsif OPT_STARTTLS[0] == $1[1]
- self.write(IAC + WILL + OPT_STARTTLS)
- self.write(IAC + SB + OPT_STARTTLS + TLS_FOLLOWS + IAC + SE)
- else
- self.write(IAC + WONT + $1[1..1])
- end
- ''
- elsif DONT[0] == $1[0] # respond to "IAC DON'T x" with "IAC WON'T x"
- self.write(IAC + WONT + $1[1..1])
- ''
- elsif WILL[0] == $1[0] # respond to "IAC WILL x"
- if OPT_BINARY[0] == $1[1]
- self.write(IAC + DO + OPT_BINARY)
- elsif OPT_ECHO[0] == $1[1]
- self.write(IAC + DO + OPT_ECHO)
- elsif OPT_SGA[0] == $1[1]
- @telnet_option["SGA"] = true
- self.write(IAC + DO + OPT_SGA)
- else
- self.write(IAC + DONT + $1[1..1])
- end
- ''
- elsif WONT[0] == $1[0] # respond to "IAC WON'T x"
- if OPT_ECHO[0] == $1[1]
- self.write(IAC + DONT + OPT_ECHO)
- elsif OPT_SGA[0] == $1[1]
- @telnet_option["SGA"] = false
- self.write(IAC + DONT + OPT_SGA)
- else
- self.write(IAC + DONT + $1[1..1])
- end
- ''
- elsif SB[0] == $1[0] # respond to "IAC SB xxx IAC SE"
- if OPT_STARTTLS[0] == $1[1] && TLS_FOLLOWS[0] == $2[0]
- @sock = OpenSSL::SSL::SSLSocket.new(@sock)
- @sock.cert = @options['Cert'] unless @sock.cert
- @sock.key = @options['Key'] unless @sock.key
- @sock.ca_cert = @options['CACert']
- @sock.ca_file = @options['CAFile']
- @sock.ca_path = @options['CAPath']
- @sock.timeout = @options['Timeout']
- @sock.verify_mode = @options['VerifyMode']
- @sock.verify_callback = @options['VerifyCallback']
- @sock.verify_depth = @options['VerifyDepth']
- @sock.connect
- @ssl = true
- end
- ''
- else
- ''
- end
- end
- end # preprocess
-
- alias waitfor_org waitfor
-
- def waitfor(options)
- time_out = @options["Timeout"]
- waittime = @options["Waittime"]
-
- if options.kind_of?(Hash)
- prompt = if options.has_key?("Match")
- options["Match"]
- elsif options.has_key?("Prompt")
- options["Prompt"]
- elsif options.has_key?("String")
- Regexp.new( Regexp.quote(options["String"]) )
- end
- time_out = options["Timeout"] if options.has_key?("Timeout")
- waittime = options["Waittime"] if options.has_key?("Waittime")
- else
- prompt = options
- end
-
- if time_out == false
- time_out = nil
- end
-
- line = ''
- buf = ''
- @rest = '' unless @rest
-
- until(prompt === line and not IO::select([@sock], nil, nil, waittime))
- unless IO::select([@sock], nil, nil, time_out)
- raise TimeoutError, "timed-out; wait for the next data"
- end
- begin
- c = @rest + @sock.sysread(1024 * 1024)
- @dumplog.log_dump('<', c) if @options.has_key?("Dump_log")
- if @options["Telnetmode"]
- pos = 0
- catch(:next){
- while true
- case c[pos]
- when IAC[0]
- case c[pos+1]
- when DO[0], DONT[0], WILL[0], WONT[0]
- throw :next unless c[pos+2]
- pos += 3
- when SB[0]
- ret = detect_sub_negotiation(c, pos)
- throw :next unless ret
- pos = ret
- when nil
- throw :next
- else
- pos += 2
- end
- when nil
- throw :next
- else
- pos += 1
- end
- end
- }
-
- buf = preprocess(c[0...pos])
- @rest = c[pos..-1]
- end
- @log.print(buf) if @options.has_key?("Output_log")
- line.concat(buf)
- yield buf if block_given?
- rescue EOFError # End of file reached
- if line == ''
- line = nil
- yield nil if block_given?
- end
- break
- end
- end
- line
- end
-
- private
-
- def detect_sub_negotiation(data, pos)
- return nil if data.length < pos+6 # IAC SB x param IAC SE
- pos += 3
- while true
- case data[pos]
- when IAC[0]
- if data[pos+1] == SE[0]
- pos += 2
- return pos
- else
- pos += 2
- end
- when nil
- return nil
- else
- pos += 1
- end
- end
- end
-
- end
-end
diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb
index 24a9eed136..98fa8d39f2 100644
--- a/ext/openssl/lib/openssl.rb
+++ b/ext/openssl/lib/openssl.rb
@@ -1,24 +1,41 @@
+# frozen_string_literal: true
=begin
-= $RCSfile$ -- Loader for all OpenSSL C-space and Ruby-space definitions
-
= Info
'OpenSSL for Ruby 2' project
Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
All rights reserved.
= Licence
- This program is licenced under the same licence as Ruby.
- (See the file 'LICENCE'.)
-
-= Version
- $Id$
+ This program is licensed under the same licence as Ruby.
+ (See the file 'COPYING'.)
=end
require 'openssl.so'
-require 'openssl/bn'
-require 'openssl/cipher'
-require 'openssl/digest'
-require 'openssl/ssl'
-require 'openssl/x509'
+require_relative 'openssl/bn'
+require_relative 'openssl/cipher'
+require_relative 'openssl/digest'
+require_relative 'openssl/hmac'
+require_relative 'openssl/pkcs5'
+require_relative 'openssl/pkey'
+require_relative 'openssl/ssl'
+require_relative 'openssl/version'
+require_relative 'openssl/x509'
+module OpenSSL
+ # :call-seq:
+ # OpenSSL.secure_compare(string, string) -> true or false
+ #
+ # Constant time memory comparison. Inputs are hashed using SHA-256 to mask
+ # the length of the secret. Returns +true+ if the strings are identical,
+ # +false+ otherwise.
+ #
+ # This method is expensive due to the SHA-256 hashing. In most cases, where
+ # the input lengths are known to be equal or are not sensitive,
+ # OpenSSL.fixed_length_secure_compare should be used instead.
+ def self.secure_compare(a, b)
+ hashed_a = OpenSSL::Digest.digest('SHA256', a)
+ hashed_b = OpenSSL::Digest.digest('SHA256', b)
+ OpenSSL.fixed_length_secure_compare(hashed_a, hashed_b) && a == b
+ end
+end
diff --git a/ext/openssl/lib/openssl/bn.rb b/ext/openssl/lib/openssl/bn.rb
index e7cbf2cfaf..e4889a140c 100644
--- a/ext/openssl/lib/openssl/bn.rb
+++ b/ext/openssl/lib/openssl/bn.rb
@@ -1,35 +1,40 @@
-=begin
-= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for BN
-
-= Info
- 'OpenSSL for Ruby 2' project
- Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
- All rights reserved.
-
-= Licence
- This program is licenced under the same licence as Ruby.
- (See the file 'LICENCE'.)
-
-= Version
- $Id$
-=end
-
-##
-# Should we care what if somebody require this file directly?
-#require 'openssl'
+# frozen_string_literal: true
+#--
+#
+# = Ruby-space definitions that completes C-space funcs for BN
+#
+# = Info
+# 'OpenSSL for Ruby 2' project
+# Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+# All rights reserved.
+#
+# = Licence
+# This program is licensed under the same licence as Ruby.
+# (See the file 'COPYING'.)
+#++
module OpenSSL
class BN
include Comparable
+
+ def pretty_print(q)
+ q.object_group(self) {
+ q.text ' '
+ q.text to_i.to_s
+ }
+ end
end # BN
end # OpenSSL
##
+#--
# Add double dispatch to Integer
-#
+#++
class Integer
+ # Casts an Integer as an OpenSSL::BN
+ #
+ # See `man bn` for more info.
def to_bn
OpenSSL::BN::new(self)
end
end # Integer
-
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb
index 761a017487..1464a4292d 100644
--- a/ext/openssl/lib/openssl/buffering.rb
+++ b/ext/openssl/lib/openssl/buffering.rb
@@ -1,27 +1,65 @@
-=begin
-= $RCSfile$ -- Buffering mix-in module.
+# coding: binary
+# frozen_string_literal: true
+#--
+#= Info
+# 'OpenSSL for Ruby 2' project
+# Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
+# All rights reserved.
+#
+#= Licence
+# This program is licensed under the same licence as Ruby.
+# (See the file 'COPYING'.)
+#++
-= Info
- 'OpenSSL for Ruby 2' project
- Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
- All rights reserved.
+##
+# OpenSSL IO buffering mix-in module.
+#
+# This module allows an OpenSSL::SSL::SSLSocket to behave like an IO.
+#
+# You typically won't use this module directly, you can see it implemented in
+# OpenSSL::SSL::SSLSocket.
-= Licence
- This program is licenced under the same licence as Ruby.
- (See the file 'LICENCE'.)
+module OpenSSL::Buffering
+ include Enumerable
-= Version
- $Id$
-=end
+ # A buffer which will retain binary encoding.
+ class Buffer < String
+ unless String.method_defined?(:append_as_bytes)
+ alias_method :_append, :<<
+ def append_as_bytes(string)
+ if string.encoding == Encoding::BINARY
+ _append(string)
+ else
+ _append(string.b)
+ end
+
+ self
+ end
+ end
+
+ undef_method :concat
+ undef_method :<<
+ end
+
+ ##
+ # The "sync mode" of the SSLSocket.
+ #
+ # See IO#sync for full details.
-module Buffering
- include Enumerable
attr_accessor :sync
+
+ ##
+ # Default size to read from or write to the SSLSocket for buffer operations.
+
BLOCK_SIZE = 1024*16
- def initialize(*args)
+ ##
+ # Creates an instance of OpenSSL's buffering IO module.
+
+ def initialize(*)
+ super
@eof = false
- @rbuffer = ""
+ @rbuffer = Buffer.new
@sync = @io.sync
end
@@ -30,9 +68,12 @@ module Buffering
#
private
+ ##
+ # Fills the buffer from the underlying SSLSocket
+
def fill_rbuff
begin
- @rbuffer << self.sysread(BLOCK_SIZE)
+ @rbuffer.append_as_bytes(self.sysread(BLOCK_SIZE))
rescue Errno::EAGAIN
retry
rescue EOFError
@@ -40,27 +81,48 @@ module Buffering
end
end
+ ##
+ # Consumes _size_ bytes from the buffer
+
def consume_rbuff(size=nil)
if @rbuffer.empty?
nil
else
size = @rbuffer.size unless size
- ret = @rbuffer[0, size]
- @rbuffer[0, size] = ""
- ret
+ @rbuffer.slice!(0, size)
end
end
public
+ # call-seq:
+ # ssl.getbyte => 81
+ #
+ # Get the next 8bit byte from `ssl`. Returns `nil` on EOF
+ def getbyte
+ read(1)&.ord
+ end
+
+ # Get the next 8bit byte. Raises EOFError on EOF
+ def readbyte
+ raise EOFError if eof?
+ getbyte
+ end
+
+ ##
+ # Reads _size_ bytes from the stream. If _buf_ is provided it must
+ # reference a string which will receive the data.
+ #
+ # See IO#read for full details.
+
def read(size=nil, buf=nil)
if size == 0
if buf
buf.clear
+ return buf
else
- buf = ""
+ return ""
end
- return @eof ? nil : buf
end
until @eof
break if size && size <= @rbuffer.size
@@ -74,14 +136,20 @@ module Buffering
(size && ret.empty?) ? nil : ret
end
+ ##
+ # Reads at most _maxlen_ bytes from the stream. If _buf_ is provided it
+ # must reference a string which will receive the data.
+ #
+ # See IO#readpartial for full details.
+
def readpartial(maxlen, buf=nil)
if maxlen == 0
if buf
buf.clear
+ return buf
else
- buf = ""
+ return ""
end
- return @eof ? nil : buf
end
if @rbuffer.empty?
begin
@@ -95,11 +163,75 @@ module Buffering
buf.replace(ret)
ret = buf
end
- raise EOFError if ret.empty?
ret
end
- def gets(eol=$/)
+ ##
+ # Reads at most _maxlen_ bytes in the non-blocking manner.
+ #
+ # When no data can be read without blocking it raises
+ # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable.
+ #
+ # IO::WaitReadable means SSL needs to read internally so read_nonblock
+ # should be called again when the underlying IO is readable.
+ #
+ # IO::WaitWritable means SSL needs to write internally so read_nonblock
+ # should be called again after the underlying IO is writable.
+ #
+ # OpenSSL::Buffering#read_nonblock needs two rescue clause as follows:
+ #
+ # # emulates blocking read (readpartial).
+ # begin
+ # result = ssl.read_nonblock(maxlen)
+ # rescue IO::WaitReadable
+ # IO.select([io])
+ # retry
+ # rescue IO::WaitWritable
+ # IO.select(nil, [io])
+ # retry
+ # end
+ #
+ # Note that one reason that read_nonblock writes to the underlying IO is
+ # when the peer requests a new TLS/SSL handshake. See openssl the FAQ for
+ # more details. http://www.openssl.org/support/faq.html
+ #
+ # By specifying a keyword argument _exception_ to +false+, you can indicate
+ # that read_nonblock should not raise an IO::Wait*able exception, but
+ # return the symbol +:wait_writable+ or +:wait_readable+ instead. At EOF,
+ # it will return +nil+ instead of raising EOFError.
+
+ def read_nonblock(maxlen, buf=nil, exception: true)
+ if maxlen == 0
+ if buf
+ buf.clear
+ return buf
+ else
+ return ""
+ end
+ end
+ if @rbuffer.empty?
+ return sysread_nonblock(maxlen, buf, exception: exception)
+ end
+ ret = consume_rbuff(maxlen)
+ if buf
+ buf.replace(ret)
+ ret = buf
+ end
+ ret
+ end
+
+ ##
+ # Reads the next "line" from the stream. Lines are separated by _eol_. If
+ # _limit_ is provided the result will not be longer than the given number of
+ # bytes.
+ #
+ # _eol_ may be a String or Regexp.
+ #
+ # Unlike IO#gets the line read will not be assigned to +$_+.
+ #
+ # Unlike IO#gets the separator must be provided if a limit is provided.
+
+ def gets(eol=$/, limit=nil, chomp: false)
idx = @rbuffer.index(eol)
until @eof
break if idx
@@ -111,9 +243,22 @@ module Buffering
else
size = idx ? idx+eol.size : nil
end
- consume_rbuff(size)
+ if size && limit && limit >= 0
+ size = [size, limit].min
+ end
+ line = consume_rbuff(size)
+ if chomp && line
+ line.chomp!(eol)
+ end
+ line
end
+ ##
+ # Executes the block for every line in the stream where lines are separated
+ # by _eol_.
+ #
+ # See also #gets
+
def each(eol=$/)
while line = self.gets(eol)
yield line
@@ -121,6 +266,11 @@ module Buffering
end
alias each_line each
+ ##
+ # Reads lines from the stream which are separated by _eol_.
+ #
+ # See also #gets
+
def readlines(eol=$/)
ary = []
while line = self.gets(eol)
@@ -129,31 +279,58 @@ module Buffering
ary
end
+ ##
+ # Reads a line from the stream which is separated by _eol_.
+ #
+ # Raises EOFError if at end of file.
+
def readline(eol=$/)
raise EOFError if eof?
gets(eol)
end
+ ##
+ # Reads one character from the stream. Returns nil if called at end of
+ # file.
+
def getc
- c = read(1)
- c ? c[0] : nil
+ read(1)
end
- def each_byte
+ ##
+ # Calls the given block once for each byte in the stream.
+
+ def each_byte # :yields: byte
while c = getc
- yield(c)
+ yield(c.ord)
end
end
+ ##
+ # Reads a one-character string from the stream. Raises an EOFError at end
+ # of file.
+
def readchar
raise EOFError if eof?
getc
end
+ ##
+ # Pushes character _c_ back onto the stream such that a subsequent buffered
+ # character read will return it.
+ #
+ # Unlike IO#getc multiple bytes may be pushed back onto the stream.
+ #
+ # Has no effect on unbuffered reads (such as #sysread).
+
def ungetc(c)
@rbuffer[0,0] = c.chr
end
+ ##
+ # Returns true if the stream is at file which means there is no more data to
+ # be read.
+
def eof?
fill_rbuff if !@eof && @rbuffer.empty?
@eof && @rbuffer.empty?
@@ -165,73 +342,162 @@ module Buffering
#
private
+ ##
+ # Writes _s_ to the buffer. When the buffer is full or #sync is true the
+ # buffer is flushed to the underlying socket.
+
def do_write(s)
- @wbuffer = "" unless defined? @wbuffer
- @wbuffer << s
+ @wbuffer = Buffer.new unless defined? @wbuffer
+ @wbuffer.append_as_bytes(s)
+
@sync ||= false
- if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/)
- remain = idx ? idx + $/.size : @wbuffer.length
- nwritten = 0
- while remain > 0
- str = @wbuffer[nwritten,remain]
- begin
- nwrote = syswrite(str)
- rescue Errno::EAGAIN
- retry
+ buffer_size = @wbuffer.bytesize
+ if @sync or buffer_size > BLOCK_SIZE
+ nwrote = 0
+ begin
+ while nwrote < buffer_size do
+ begin
+ chunk = if nwrote > 0
+ @wbuffer.byteslice(nwrote, @wbuffer.bytesize)
+ else
+ @wbuffer
+ end
+
+ nwrote += syswrite(chunk)
+ rescue Errno::EAGAIN
+ retry
+ end
+ end
+ ensure
+ if nwrote < @wbuffer.bytesize
+ @wbuffer[0, nwrote] = ""
+ else
+ @wbuffer.clear
end
- remain -= nwrote
- nwritten += nwrote
end
- @wbuffer[0,nwritten] = ""
end
end
public
- def write(s)
- do_write(s)
- s.length
+ ##
+ # Writes _s_ to the stream. If the argument is not a String it will be
+ # converted using +.to_s+ method. Returns the number of bytes written.
+
+ def write(*s)
+ s.inject(0) do |written, str|
+ do_write(str)
+ written + str.bytesize
+ end
+ end
+
+ ##
+ # Writes _s_ in the non-blocking manner.
+ #
+ # If there is buffered data, it is flushed first. This may block.
+ #
+ # write_nonblock returns number of bytes written to the SSL connection.
+ #
+ # When no data can be written without blocking it raises
+ # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable.
+ #
+ # IO::WaitReadable means SSL needs to read internally so write_nonblock
+ # should be called again after the underlying IO is readable.
+ #
+ # IO::WaitWritable means SSL needs to write internally so write_nonblock
+ # should be called again after underlying IO is writable.
+ #
+ # So OpenSSL::Buffering#write_nonblock needs two rescue clause as follows.
+ #
+ # # emulates blocking write.
+ # begin
+ # result = ssl.write_nonblock(str)
+ # rescue IO::WaitReadable
+ # IO.select([io])
+ # retry
+ # rescue IO::WaitWritable
+ # IO.select(nil, [io])
+ # retry
+ # end
+ #
+ # Note that one reason that write_nonblock reads from the underlying IO
+ # is when the peer requests a new TLS/SSL handshake. See the openssl FAQ
+ # for more details. http://www.openssl.org/support/faq.html
+ #
+ # By specifying a keyword argument _exception_ to +false+, you can indicate
+ # that write_nonblock should not raise an IO::Wait*able exception, but
+ # return the symbol +:wait_writable+ or +:wait_readable+ instead.
+
+ def write_nonblock(s, exception: true)
+ flush
+ syswrite_nonblock(s, exception: exception)
end
- def << (s)
+ ##
+ # Writes _s_ to the stream. _s_ will be converted to a String using
+ # +.to_s+ method.
+
+ def <<(s)
do_write(s)
self
end
+ ##
+ # Writes _args_ to the stream along with a record separator.
+ #
+ # See IO#puts for full details.
+
def puts(*args)
- s = ""
+ s = Buffer.new
if args.empty?
- s << "\n"
+ s.append_as_bytes("\n")
end
args.each{|arg|
- s << arg.to_s
- if $/ && /\n\z/ !~ s
- s << "\n"
- end
+ s.append_as_bytes(arg.to_s)
+ s.sub!(/(?<!\n)\z/, "\n")
}
do_write(s)
nil
end
+ ##
+ # Writes _args_ to the stream.
+ #
+ # See IO#print for full details.
+
def print(*args)
- s = ""
- args.each{ |arg| s << arg.to_s }
+ s = Buffer.new
+ args.each{ |arg| s.append_as_bytes(arg.to_s) }
do_write(s)
nil
end
+ ##
+ # Formats and writes to the stream converting parameters under control of
+ # the format string.
+ #
+ # See Kernel#sprintf for format string details.
+
def printf(s, *args)
do_write(s % args)
nil
end
+ ##
+ # Flushes buffered data to the SSLSocket.
+
def flush
osync = @sync
@sync = true
do_write ""
+ return self
+ ensure
@sync = osync
end
+ ##
+ # Closes the SSLSocket and flushes any unwritten data.
+
def close
flush rescue nil
sysclose
diff --git a/ext/openssl/lib/openssl/cipher.rb b/ext/openssl/lib/openssl/cipher.rb
index 049533d06b..ab75ac8e1a 100644
--- a/ext/openssl/lib/openssl/cipher.rb
+++ b/ext/openssl/lib/openssl/cipher.rb
@@ -1,30 +1,24 @@
-=begin
-= $RCSfile$ -- Ruby-space predefined Cipher subclasses
-
-= Info
- 'OpenSSL for Ruby 2' project
- Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
- All rights reserved.
-
-= Licence
- This program is licenced under the same licence as Ruby.
- (See the file 'LICENCE'.)
-
-= Version
- $Id$
-=end
-
-##
-# Should we care what if somebody require this file directly?
-#require 'openssl'
+# frozen_string_literal: true
+#--
+# = Ruby-space predefined Cipher subclasses
+#
+# = Info
+# 'OpenSSL for Ruby 2' project
+# Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+# All rights reserved.
+#
+# = Licence
+# This program is licensed under the same licence as Ruby.
+# (See the file 'COPYING'.)
+#++
module OpenSSL
- module Cipher
+ class Cipher
%w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name|
klass = Class.new(Cipher){
define_method(:initialize){|*args|
cipher_name = args.inject(name){|n, arg| "#{n}-#{arg}" }
- super(cipher_name)
+ super(cipher_name.downcase)
}
}
const_set(name, klass)
@@ -32,27 +26,42 @@ module OpenSSL
%w(128 192 256).each{|keylen|
klass = Class.new(Cipher){
- define_method(:initialize){|mode|
- mode ||= "CBC"
- cipher_name = "AES-#{keylen}-#{mode}"
- super(cipher_name)
+ define_method(:initialize){|mode = "CBC"|
+ super("aes-#{keylen}-#{mode}".downcase)
}
}
const_set("AES#{keylen}", klass)
}
- class Cipher
- def random_key
- str = OpenSSL::Random.random_bytes(self.key_len)
- self.key = str
- return str
- end
+ # call-seq:
+ # cipher.random_key -> key
+ #
+ # Generate a random key with OpenSSL::Random.random_bytes and sets it to
+ # the cipher, and returns it.
+ #
+ # You must call #encrypt or #decrypt before calling this method.
+ def random_key
+ str = OpenSSL::Random.random_bytes(self.key_len)
+ self.key = str
+ end
- def random_iv
- str = OpenSSL::Random.random_bytes(self.iv_len)
- self.iv = str
- return str
- end
+ # call-seq:
+ # cipher.random_iv -> iv
+ #
+ # Generate a random IV with OpenSSL::Random.random_bytes and sets it to the
+ # cipher, and returns it.
+ #
+ # You must call #encrypt or #decrypt before calling this method.
+ def random_iv
+ str = OpenSSL::Random.random_bytes(self.iv_len)
+ self.iv = str
end
+
+ # Deprecated.
+ #
+ # This class is only provided for backwards compatibility.
+ # Use OpenSSL::Cipher.
+ class Cipher < Cipher; end
+ deprecate_constant :Cipher
end # Cipher
end # OpenSSL
diff --git a/ext/openssl/lib/openssl/digest.rb b/ext/openssl/lib/openssl/digest.rb
index b3e4484805..4e6dea8d03 100644
--- a/ext/openssl/lib/openssl/digest.rb
+++ b/ext/openssl/lib/openssl/digest.rb
@@ -1,49 +1,73 @@
-=begin
-= $RCSfile$ -- Ruby-space predefined Digest subclasses
+# frozen_string_literal: true
+#--
+# = Ruby-space predefined Digest subclasses
+#
+# = Info
+# 'OpenSSL for Ruby 2' project
+# Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+# All rights reserved.
+#
+# = Licence
+# This program is licensed under the same licence as Ruby.
+# (See the file 'COPYING'.)
+#++
-= Info
- 'OpenSSL for Ruby 2' project
- Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
- All rights reserved.
+module OpenSSL
+ class Digest
-= Licence
- This program is licenced under the same licence as Ruby.
- (See the file 'LICENCE'.)
+ # Return the hash value computed with _name_ Digest. _name_ is either the
+ # long name or short name of a supported digest algorithm.
+ #
+ # === Example
+ #
+ # OpenSSL::Digest.digest("SHA256", "abc")
-= Version
- $Id$
-=end
+ def self.digest(name, data)
+ super(data, name)
+ end
-##
-# Should we care what if somebody require this file directly?
-#require 'openssl'
+ %w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512).each do |name|
+ klass = Class.new(self)
+ klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def initialize(data = nil)
+ super("#{name}", data)
+ end
+ RUBY
-module OpenSSL
- module Digest
-
- alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1)
- if OPENSSL_VERSION_NUMBER > 0x00908000
- alg += %w(SHA224 SHA256 SHA384 SHA512)
+ klass.singleton_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def digest(data)
+ new.digest(data)
+ end
+ def hexdigest(data)
+ new.hexdigest(data)
+ end
+ RUBY
+ const_set(name.tr('-', '_'), klass)
end
- alg.each{|name|
- klass = Class.new(Digest){
- define_method(:initialize){|*data|
- if data.length > 1
- raise ArgumentError,
- "wrong number of arguments (#{data.length} for 1)"
- end
- super(name, data.first)
- }
- }
- singleton = (class <<klass; self; end)
- singleton.class_eval{
- define_method(:digest){|data| Digest.digest(name, data) }
- define_method(:hexdigest){|data| Digest.hexdigest(name, data) }
- }
- const_set(name, klass)
- }
+ # Deprecated.
+ #
+ # This class is only provided for backwards compatibility.
+ # Use OpenSSL::Digest instead.
+ class Digest < Digest; end # :nodoc:
+ deprecate_constant :Digest
end # Digest
-end # OpenSSL
+ # Returns a Digest subclass by _name_
+ #
+ # require 'openssl'
+ #
+ # OpenSSL::Digest("MD5")
+ # # => OpenSSL::Digest::MD5
+ #
+ # OpenSSL::Digest("Foo")
+ # # => NameError: wrong constant name Foo
+
+ def Digest(name)
+ OpenSSL::Digest.const_get(name)
+ end
+
+ module_function :Digest
+
+end # OpenSSL
diff --git a/ext/openssl/lib/openssl/hmac.rb b/ext/openssl/lib/openssl/hmac.rb
new file mode 100644
index 0000000000..c8c844d8d7
--- /dev/null
+++ b/ext/openssl/lib/openssl/hmac.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+module OpenSSL
+ class HMAC
+ # Securely compare with another HMAC instance in constant time.
+ def ==(other)
+ return false unless HMAC === other
+ return false unless self.digest.bytesize == other.digest.bytesize
+
+ OpenSSL.fixed_length_secure_compare(self.digest, other.digest)
+ end
+
+ # :call-seq:
+ # hmac.base64digest -> string
+ #
+ # Returns the authentication code an a Base64-encoded string.
+ def base64digest
+ [digest].pack("m0")
+ end
+
+ class << self
+ # :call-seq:
+ # HMAC.digest(digest, key, data) -> aString
+ #
+ # Returns the authentication code as a binary string. The _digest_ parameter
+ # specifies the digest algorithm to use. This may be a String representing
+ # the algorithm name or an instance of OpenSSL::Digest.
+ #
+ # === Example
+ # key = 'key'
+ # data = 'The quick brown fox jumps over the lazy dog'
+ #
+ # hmac = OpenSSL::HMAC.digest('SHA1', key, data)
+ # #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9"
+ def digest(digest, key, data)
+ hmac = new(key, digest)
+ hmac << data
+ hmac.digest
+ end
+
+ # :call-seq:
+ # HMAC.hexdigest(digest, key, data) -> aString
+ #
+ # Returns the authentication code as a hex-encoded string. The _digest_
+ # parameter specifies the digest algorithm to use. This may be a String
+ # representing the algorithm name or an instance of OpenSSL::Digest.
+ #
+ # === Example
+ # key = 'key'
+ # data = 'The quick brown fox jumps over the lazy dog'
+ #
+ # hmac = OpenSSL::HMAC.hexdigest('SHA1', key, data)
+ # #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
+ def hexdigest(digest, key, data)
+ hmac = new(key, digest)
+ hmac << data
+ hmac.hexdigest
+ end
+
+ # :call-seq:
+ # HMAC.base64digest(digest, key, data) -> aString
+ #
+ # Returns the authentication code as a Base64-encoded string. The _digest_
+ # parameter specifies the digest algorithm to use. This may be a String
+ # representing the algorithm name or an instance of OpenSSL::Digest.
+ #
+ # === Example
+ # key = 'key'
+ # data = 'The quick brown fox jumps over the lazy dog'
+ #
+ # hmac = OpenSSL::HMAC.base64digest('SHA1', key, data)
+ # #=> "3nybhbi3iqa8ino29wqQcBydtNk="
+ def base64digest(digest, key, data)
+ [digest(digest, key, data)].pack("m0")
+ end
+ end
+ end
+end
diff --git a/ext/openssl/lib/openssl/marshal.rb b/ext/openssl/lib/openssl/marshal.rb
new file mode 100644
index 0000000000..eb8eda4748
--- /dev/null
+++ b/ext/openssl/lib/openssl/marshal.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+#--
+# = Ruby-space definitions to add DER (de)serialization to classes
+#
+# = Info
+# 'OpenSSL for Ruby 2' project
+# Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+# All rights reserved.
+#
+# = Licence
+# This program is licensed under the same licence as Ruby.
+# (See the file 'COPYING'.)
+#++
+module OpenSSL
+ module Marshal
+ def self.included(base)
+ base.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ def _load(string)
+ new(string)
+ end
+ end
+
+ def _dump(_level)
+ to_der
+ end
+ end
+end
diff --git a/ext/openssl/lib/openssl/pkcs5.rb b/ext/openssl/lib/openssl/pkcs5.rb
new file mode 100644
index 0000000000..8dedc4beef
--- /dev/null
+++ b/ext/openssl/lib/openssl/pkcs5.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+#--
+# Ruby/OpenSSL Project
+# Copyright (C) 2017 Ruby/OpenSSL Project Authors
+#++
+
+module OpenSSL
+ module PKCS5
+ module_function
+
+ # OpenSSL::PKCS5.pbkdf2_hmac has been renamed to OpenSSL::KDF.pbkdf2_hmac.
+ # This method is provided for backwards compatibility.
+ def pbkdf2_hmac(pass, salt, iter, keylen, digest)
+ OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter,
+ length: keylen, hash: digest)
+ end
+
+ def pbkdf2_hmac_sha1(pass, salt, iter, keylen)
+ pbkdf2_hmac(pass, salt, iter, keylen, "sha1")
+ end
+ end
+end
diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb
new file mode 100644
index 0000000000..39871e15dd
--- /dev/null
+++ b/ext/openssl/lib/openssl/pkey.rb
@@ -0,0 +1,493 @@
+# frozen_string_literal: true
+#--
+# Ruby/OpenSSL Project
+# Copyright (C) 2017 Ruby/OpenSSL Project Authors
+#++
+
+require_relative 'marshal'
+
+module OpenSSL::PKey
+ # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError.
+ DHError = PKeyError
+
+ class DH
+ include OpenSSL::Marshal
+
+ # :call-seq:
+ # dh.public_key -> dhnew
+ #
+ # Returns a new DH instance that carries just the \DH parameters.
+ #
+ # Contrary to the method name, the returned DH object contains only
+ # parameters and not the public key.
+ #
+ # This method is provided for backwards compatibility. In most cases, there
+ # is no need to call this method.
+ #
+ # For the purpose of re-generating the key pair while keeping the
+ # parameters, check OpenSSL::PKey.generate_key.
+ #
+ # Example:
+ # # OpenSSL::PKey::DH.generate by default generates a random key pair
+ # dh1 = OpenSSL::PKey::DH.generate(2048)
+ # p dh1.priv_key #=> #<OpenSSL::BN 1288347...>
+ # dhcopy = dh1.public_key
+ # p dhcopy.priv_key #=> nil
+ def public_key
+ DH.new(to_der)
+ end
+
+ # :call-seq:
+ # dh.params -> hash
+ #
+ # Stores all parameters of key to a Hash.
+ #
+ # The hash has keys 'p', 'q', 'g', 'pub_key', and 'priv_key'.
+ def params
+ %w{p q g pub_key priv_key}.map { |name|
+ [name, send(name)]
+ }.to_h
+ end
+
+ # :call-seq:
+ # dh.compute_key(pub_bn) -> string
+ #
+ # Returns a String containing a shared secret computed from the other
+ # party's public value.
+ #
+ # This method is provided for backwards compatibility, and calls #derive
+ # internally.
+ #
+ # === Parameters
+ # * _pub_bn_ is a OpenSSL::BN, *not* the DH instance returned by
+ # DH#public_key as that contains the DH parameters only.
+ def compute_key(pub_bn)
+ # FIXME: This is constructing an X.509 SubjectPublicKeyInfo and is very
+ # inefficient
+ obj = OpenSSL::ASN1.Sequence([
+ OpenSSL::ASN1.Sequence([
+ OpenSSL::ASN1.ObjectId("dhKeyAgreement"),
+ OpenSSL::ASN1.Sequence([
+ OpenSSL::ASN1.Integer(p),
+ OpenSSL::ASN1.Integer(g),
+ ]),
+ ]),
+ OpenSSL::ASN1.BitString(OpenSSL::ASN1.Integer(pub_bn).to_der),
+ ])
+ derive(OpenSSL::PKey.read(obj.to_der))
+ end
+
+ # :call-seq:
+ # dh.generate_key! -> self
+ #
+ # Generates a private and public key unless a private key already exists.
+ # If this DH instance was generated from public \DH parameters (e.g. by
+ # encoding the result of DH#public_key), then this method needs to be
+ # called first in order to generate the per-session keys before performing
+ # the actual key exchange.
+ #
+ # <b>Deprecated in version 3.0</b>. This method is incompatible with
+ # OpenSSL 3.0.0 or later.
+ #
+ # See also OpenSSL::PKey.generate_key.
+ #
+ # Example:
+ # # DEPRECATED USAGE: This will not work on OpenSSL 3.0 or later
+ # dh0 = OpenSSL::PKey::DH.new(2048)
+ # dh = dh0.public_key # #public_key only copies the DH parameters (contrary to the name)
+ # dh.generate_key!
+ # puts dh.private? # => true
+ # puts dh0.pub_key == dh.pub_key #=> false
+ #
+ # # With OpenSSL::PKey.generate_key
+ # dh0 = OpenSSL::PKey::DH.new(2048)
+ # dh = OpenSSL::PKey.generate_key(dh0)
+ # puts dh0.pub_key == dh.pub_key #=> false
+ def generate_key!
+ if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x30000000
+ raise PKeyError, "OpenSSL::PKey::DH is immutable on OpenSSL 3.0; " \
+ "use OpenSSL::PKey.generate_key instead"
+ end
+
+ unless priv_key
+ tmp = OpenSSL::PKey.generate_key(self)
+ set_key(tmp.pub_key, tmp.priv_key)
+ end
+ self
+ end
+
+ class << self
+ # :call-seq:
+ # DH.generate(size, generator = 2) -> dh
+ #
+ # Creates a new DH instance from scratch by generating random parameters
+ # and a key pair.
+ #
+ # See also OpenSSL::PKey.generate_parameters and
+ # OpenSSL::PKey.generate_key.
+ #
+ # +size+::
+ # The desired key size in bits.
+ # +generator+::
+ # The generator.
+ def generate(size, generator = 2, &blk)
+ dhparams = OpenSSL::PKey.generate_parameters("DH", {
+ "dh_paramgen_prime_len" => size,
+ "dh_paramgen_generator" => generator,
+ }, &blk)
+ OpenSSL::PKey.generate_key(dhparams)
+ end
+
+ # Handle DH.new(size, generator) form here; new(str) and new() forms
+ # are handled by #initialize
+ def new(*args, &blk) # :nodoc:
+ if args[0].is_a?(Integer)
+ generate(*args, &blk)
+ else
+ super
+ end
+ end
+ end
+ end
+
+ # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError.
+ DSAError = PKeyError
+
+ class DSA
+ include OpenSSL::Marshal
+
+ # :call-seq:
+ # dsa.public_key -> dsanew
+ #
+ # Returns a new DSA instance that carries just the \DSA parameters and the
+ # public key.
+ #
+ # This method is provided for backwards compatibility. In most cases, there
+ # is no need to call this method.
+ #
+ # For the purpose of serializing the public key, to PEM or DER encoding of
+ # X.509 SubjectPublicKeyInfo format, check PKey#public_to_pem and
+ # PKey#public_to_der.
+ def public_key
+ OpenSSL::PKey.read(public_to_der)
+ end
+
+ # :call-seq:
+ # dsa.params -> hash
+ #
+ # Stores all parameters of key to a Hash.
+ #
+ # The hash has keys 'p', 'q', 'g', 'pub_key', and 'priv_key'.
+ def params
+ %w{p q g pub_key priv_key}.map { |name|
+ [name, send(name)]
+ }.to_h
+ end
+
+ class << self
+ # :call-seq:
+ # DSA.generate(size) -> dsa
+ #
+ # Creates a new DSA instance by generating a private/public key pair
+ # from scratch.
+ #
+ # See also OpenSSL::PKey.generate_parameters and
+ # OpenSSL::PKey.generate_key.
+ #
+ # +size+::
+ # The desired key size in bits.
+ def generate(size, &blk)
+ # FIPS 186-4 specifies four (L,N) pairs: (1024,160), (2048,224),
+ # (2048,256), and (3072,256).
+ #
+ # q size is derived here with compatibility with
+ # DSA_generator_parameters_ex() which previous versions of ruby/openssl
+ # used to call.
+ qsize = size >= 2048 ? 256 : 160
+ dsaparams = OpenSSL::PKey.generate_parameters("DSA", {
+ "dsa_paramgen_bits" => size,
+ "dsa_paramgen_q_bits" => qsize,
+ }, &blk)
+ OpenSSL::PKey.generate_key(dsaparams)
+ end
+
+ # Handle DSA.new(size) form here; new(str) and new() forms
+ # are handled by #initialize
+ def new(*args, &blk) # :nodoc:
+ if args[0].is_a?(Integer)
+ generate(*args, &blk)
+ else
+ super
+ end
+ end
+ end
+
+ # :call-seq:
+ # dsa.syssign(string) -> string
+ #
+ # Computes and returns the \DSA signature of +string+, where +string+ is
+ # expected to be an already-computed message digest of the original input
+ # data. The signature is issued using the private key of this DSA instance.
+ #
+ # <b>Deprecated in version 3.0</b>.
+ # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead.
+ #
+ # +string+::
+ # A message digest of the original input data to be signed.
+ #
+ # Example:
+ # dsa = OpenSSL::PKey::DSA.new(2048)
+ # doc = "Sign me"
+ # digest = OpenSSL::Digest.digest('SHA1', doc)
+ #
+ # # With legacy #syssign and #sysverify:
+ # sig = dsa.syssign(digest)
+ # p dsa.sysverify(digest, sig) #=> true
+ #
+ # # With #sign_raw and #verify_raw:
+ # sig = dsa.sign_raw(nil, digest)
+ # p dsa.verify_raw(nil, sig, digest) #=> true
+ def syssign(string)
+ q or raise PKeyError, "incomplete DSA"
+ private? or raise PKeyError, "Private DSA key needed!"
+ sign_raw(nil, string)
+ end
+
+ # :call-seq:
+ # dsa.sysverify(digest, sig) -> true | false
+ #
+ # Verifies whether the signature is valid given the message digest input.
+ # It does so by validating +sig+ using the public key of this DSA instance.
+ #
+ # <b>Deprecated in version 3.0</b>.
+ # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead.
+ #
+ # +digest+::
+ # A message digest of the original input data to be signed.
+ # +sig+::
+ # A \DSA signature value.
+ def sysverify(digest, sig)
+ verify_raw(nil, sig, digest)
+ end
+ end
+
+ if defined?(EC)
+ # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError.
+ ECError = PKeyError
+
+ class EC
+ include OpenSSL::Marshal
+
+ # :call-seq:
+ # key.dsa_sign_asn1(data) -> String
+ #
+ # <b>Deprecated in version 3.0</b>.
+ # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead.
+ def dsa_sign_asn1(data)
+ sign_raw(nil, data)
+ end
+
+ # :call-seq:
+ # key.dsa_verify_asn1(data, sig) -> true | false
+ #
+ # <b>Deprecated in version 3.0</b>.
+ # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead.
+ def dsa_verify_asn1(data, sig)
+ verify_raw(nil, sig, data)
+ end
+
+ # :call-seq:
+ # ec.dh_compute_key(pubkey) -> string
+ #
+ # Derives a shared secret by ECDH. _pubkey_ must be an instance of
+ # OpenSSL::PKey::EC::Point and must belong to the same group.
+ #
+ # This method is provided for backwards compatibility, and calls #derive
+ # internally.
+ def dh_compute_key(pubkey)
+ obj = OpenSSL::ASN1.Sequence([
+ OpenSSL::ASN1.Sequence([
+ OpenSSL::ASN1.ObjectId("id-ecPublicKey"),
+ group.to_der,
+ ]),
+ OpenSSL::ASN1.BitString(pubkey.to_octet_string(:uncompressed)),
+ ])
+ derive(OpenSSL::PKey.read(obj.to_der))
+ end
+ end
+
+ class EC::Point
+ # :call-seq:
+ # point.to_bn([conversion_form]) -> OpenSSL::BN
+ #
+ # Returns the octet string representation of the EC point as an instance of
+ # OpenSSL::BN.
+ #
+ # If _conversion_form_ is not given, the _point_conversion_form_ attribute
+ # set to the group is used.
+ #
+ # See #to_octet_string for more information.
+ def to_bn(conversion_form = group.point_conversion_form)
+ OpenSSL::BN.new(to_octet_string(conversion_form), 2)
+ end
+ end
+ end
+
+ # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError.
+ RSAError = PKeyError
+
+ class RSA
+ include OpenSSL::Marshal
+
+ # :call-seq:
+ # rsa.public_key -> rsanew
+ #
+ # Returns a new RSA instance that carries just the public key components.
+ #
+ # This method is provided for backwards compatibility. In most cases, there
+ # is no need to call this method.
+ #
+ # For the purpose of serializing the public key, to PEM or DER encoding of
+ # X.509 SubjectPublicKeyInfo format, check PKey#public_to_pem and
+ # PKey#public_to_der.
+ def public_key
+ OpenSSL::PKey.read(public_to_der)
+ end
+
+ # :call-seq:
+ # rsa.params -> hash
+ #
+ # Stores all parameters of key to a Hash.
+ #
+ # The hash has keys 'n', 'e', 'd', 'p', 'q', 'dmp1', 'dmq1', and 'iqmp'.
+ def params
+ %w{n e d p q dmp1 dmq1 iqmp}.map { |name|
+ [name, send(name)]
+ }.to_h
+ end
+
+ class << self
+ # :call-seq:
+ # RSA.generate(size, exponent = 65537) -> RSA
+ #
+ # Generates an \RSA keypair.
+ #
+ # See also OpenSSL::PKey.generate_key.
+ #
+ # +size+::
+ # The desired key size in bits.
+ # +exponent+::
+ # An odd Integer, normally 3, 17, or 65537.
+ def generate(size, exp = 0x10001, &blk)
+ OpenSSL::PKey.generate_key("RSA", {
+ "rsa_keygen_bits" => size,
+ "rsa_keygen_pubexp" => exp,
+ }, &blk)
+ end
+
+ # Handle RSA.new(size, exponent) form here; new(str) and new() forms
+ # are handled by #initialize
+ def new(*args, &blk) # :nodoc:
+ if args[0].is_a?(Integer)
+ generate(*args, &blk)
+ else
+ super
+ end
+ end
+ end
+
+ # :call-seq:
+ # rsa.private_encrypt(string) -> String
+ # rsa.private_encrypt(string, padding) -> String
+ #
+ # Encrypt +string+ with the private key. +padding+ defaults to
+ # PKCS1_PADDING, which is known to be insecure but is kept for backwards
+ # compatibility. The encrypted string output can be decrypted using
+ # #public_decrypt.
+ #
+ # <b>Deprecated in version 3.0</b>.
+ # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and
+ # PKey::PKey#verify_recover instead.
+ def private_encrypt(string, padding = PKCS1_PADDING)
+ n or raise PKeyError, "incomplete RSA"
+ private? or raise PKeyError, "private key needed."
+ sign_raw(nil, string, {
+ "rsa_padding_mode" => translate_padding_mode(padding),
+ })
+ end
+
+ # :call-seq:
+ # rsa.public_decrypt(string) -> String
+ # rsa.public_decrypt(string, padding) -> String
+ #
+ # Decrypt +string+, which has been encrypted with the private key, with the
+ # public key. +padding+ defaults to PKCS1_PADDING which is known to be
+ # insecure but is kept for backwards compatibility.
+ #
+ # <b>Deprecated in version 3.0</b>.
+ # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and
+ # PKey::PKey#verify_recover instead.
+ def public_decrypt(string, padding = PKCS1_PADDING)
+ n or raise PKeyError, "incomplete RSA"
+ verify_recover(nil, string, {
+ "rsa_padding_mode" => translate_padding_mode(padding),
+ })
+ end
+
+ # :call-seq:
+ # rsa.public_encrypt(string) -> String
+ # rsa.public_encrypt(string, padding) -> String
+ #
+ # Encrypt +string+ with the public key. +padding+ defaults to
+ # PKCS1_PADDING, which is known to be insecure but is kept for backwards
+ # compatibility. The encrypted string output can be decrypted using
+ # #private_decrypt.
+ #
+ # <b>Deprecated in version 3.0</b>.
+ # Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead.
+ def public_encrypt(data, padding = PKCS1_PADDING)
+ n or raise PKeyError, "incomplete RSA"
+ encrypt(data, {
+ "rsa_padding_mode" => translate_padding_mode(padding),
+ })
+ end
+
+ # :call-seq:
+ # rsa.private_decrypt(string) -> String
+ # rsa.private_decrypt(string, padding) -> String
+ #
+ # Decrypt +string+, which has been encrypted with the public key, with the
+ # private key. +padding+ defaults to PKCS1_PADDING, which is known to be
+ # insecure but is kept for backwards compatibility.
+ #
+ # <b>Deprecated in version 3.0</b>.
+ # Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead.
+ def private_decrypt(data, padding = PKCS1_PADDING)
+ n or raise PKeyError, "incomplete RSA"
+ private? or raise PKeyError, "private key needed."
+ decrypt(data, {
+ "rsa_padding_mode" => translate_padding_mode(padding),
+ })
+ end
+
+ PKCS1_PADDING = 1
+ SSLV23_PADDING = 2
+ NO_PADDING = 3
+ PKCS1_OAEP_PADDING = 4
+
+ private def translate_padding_mode(num)
+ case num
+ when PKCS1_PADDING
+ "pkcs1"
+ when SSLV23_PADDING
+ "sslv23"
+ when NO_PADDING
+ "none"
+ when PKCS1_OAEP_PADDING
+ "oaep"
+ else
+ raise PKeyError, "unsupported padding mode"
+ end
+ end
+ end
+end
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index ef7415f478..3268c126b9 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -1,26 +1,184 @@
+# frozen_string_literal: true
=begin
-= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for SSL
-
= Info
'OpenSSL for Ruby 2' project
Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
All rights reserved.
= Licence
- This program is licenced under the same licence as Ruby.
- (See the file 'LICENCE'.)
-
-= Version
- $Id$
+ This program is licensed under the same licence as Ruby.
+ (See the file 'COPYING'.)
=end
-require "openssl"
require "openssl/buffering"
-require "fcntl"
+
+if defined?(OpenSSL::SSL)
+
+require "io/nonblock"
+require "ipaddr"
+require "socket"
module OpenSSL
module SSL
+ class SSLContext
+ DEFAULT_PARAMS = { # :nodoc:
+ :verify_mode => OpenSSL::SSL::VERIFY_PEER,
+ :verify_hostname => true,
+ :options => -> {
+ opts = OpenSSL::SSL::OP_ALL
+ opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
+ opts |= OpenSSL::SSL::OP_NO_COMPRESSION
+ opts
+ }.call
+ }
+
+ if !OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL")
+ DEFAULT_PARAMS.merge!(
+ min_version: OpenSSL::SSL::TLS1_VERSION,
+ ciphers: %w{
+ ECDHE-ECDSA-AES128-GCM-SHA256
+ ECDHE-RSA-AES128-GCM-SHA256
+ ECDHE-ECDSA-AES256-GCM-SHA384
+ ECDHE-RSA-AES256-GCM-SHA384
+ DHE-RSA-AES128-GCM-SHA256
+ DHE-DSS-AES128-GCM-SHA256
+ DHE-RSA-AES256-GCM-SHA384
+ DHE-DSS-AES256-GCM-SHA384
+ ECDHE-ECDSA-AES128-SHA256
+ ECDHE-RSA-AES128-SHA256
+ ECDHE-ECDSA-AES128-SHA
+ ECDHE-RSA-AES128-SHA
+ ECDHE-ECDSA-AES256-SHA384
+ ECDHE-RSA-AES256-SHA384
+ ECDHE-ECDSA-AES256-SHA
+ ECDHE-RSA-AES256-SHA
+ DHE-RSA-AES128-SHA256
+ DHE-RSA-AES256-SHA256
+ DHE-RSA-AES128-SHA
+ DHE-RSA-AES256-SHA
+ DHE-DSS-AES128-SHA256
+ DHE-DSS-AES256-SHA256
+ DHE-DSS-AES128-SHA
+ DHE-DSS-AES256-SHA
+ AES128-GCM-SHA256
+ AES256-GCM-SHA384
+ AES128-SHA256
+ AES256-SHA256
+ AES128-SHA
+ AES256-SHA
+ }.join(":").freeze,
+ )
+ end
+ DEFAULT_PARAMS.freeze
+
+ DEFAULT_CERT_STORE = OpenSSL::X509::Store.new # :nodoc:
+ DEFAULT_CERT_STORE.set_default_paths
+
+ # A callback invoked at connect time to distinguish between multiple
+ # server names.
+ #
+ # The callback is invoked with an SSLSocket and a server name. The
+ # callback must return an SSLContext for the server name or nil.
+ attr_accessor :servername_cb
+
+ # call-seq:
+ # SSLContext.new -> ctx
+ # SSLContext.new(:TLSv1) -> ctx
+ # SSLContext.new("SSLv23") -> ctx
+ #
+ # Creates a new SSL context.
+ #
+ # If an argument is given, #ssl_version= is called with the value. Note
+ # that this form is deprecated. New applications should use #min_version=
+ # and #max_version= as necessary.
+ def initialize(version = nil)
+ self.ssl_version = version if version
+ self.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ self.verify_hostname = false
+ end
+
+ ##
+ # call-seq:
+ # ctx.set_params(params = {}) -> params
+ #
+ # Sets saner defaults optimized for the use with HTTP-like protocols.
+ #
+ # If a Hash _params_ is given, the parameters are overridden with it.
+ # The keys in _params_ must be assignment methods on SSLContext.
+ #
+ # If the verify_mode is not VERIFY_NONE and ca_file, ca_path and
+ # cert_store are not set then the system default certificate store is
+ # used.
+ def set_params(params={})
+ params = DEFAULT_PARAMS.merge(params)
+ self.options |= params.delete(:options) # set before min_version/max_version
+ params.each{|name, value| self.__send__("#{name}=", value) }
+ if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
+ unless self.ca_file or self.ca_path or self.cert_store
+ if not defined?(Ractor) or Ractor.current == Ractor.main
+ self.cert_store = DEFAULT_CERT_STORE
+ else
+ self.cert_store = Ractor.current[:__openssl_default_store__] ||=
+ OpenSSL::X509::Store.new.tap { |store|
+ store.set_default_paths
+ }
+ end
+ end
+ end
+ return params
+ end
+
+ # call-seq:
+ # ctx.ssl_version = :TLSv1
+ # ctx.ssl_version = "SSLv23"
+ #
+ # Sets the SSL/TLS protocol version for the context. This forces
+ # connections to use only the specified protocol version. This is
+ # deprecated and only provided for backwards compatibility. Use
+ # #min_version= and #max_version= instead.
+ #
+ # === History
+ # As the name hints, this used to call the SSL_CTX_set_ssl_version()
+ # function which sets the SSL method used for connections created from
+ # the context. As of Ruby/OpenSSL 2.1, this accessor method is
+ # implemented to call #min_version= and #max_version= instead.
+ def ssl_version=(meth)
+ meth = meth.to_s if meth.is_a?(Symbol)
+ if /(?<type>_client|_server)\z/ =~ meth
+ meth = $`
+ if $VERBOSE
+ warn "#{caller(1, 1)[0]}: method type #{type.inspect} is ignored"
+ end
+ end
+ version = METHODS_MAP[meth.intern] or
+ raise ArgumentError, "unknown SSL method `%s'" % meth
+ self.min_version = self.max_version = version
+ end
+
+ METHODS_MAP = {
+ SSLv23: 0,
+ SSLv2: OpenSSL::SSL::SSL2_VERSION,
+ SSLv3: OpenSSL::SSL::SSL3_VERSION,
+ TLSv1: OpenSSL::SSL::TLS1_VERSION,
+ TLSv1_1: OpenSSL::SSL::TLS1_1_VERSION,
+ TLSv1_2: OpenSSL::SSL::TLS1_2_VERSION,
+ }.freeze
+ private_constant :METHODS_MAP
+
+ # The list of available SSL/TLS methods. This constant is only provided
+ # for backwards compatibility.
+ METHODS = METHODS_MAP.flat_map { |name,|
+ [name, :"#{name}_client", :"#{name}_server"]
+ }.freeze
+ deprecate_constant :METHODS
+ end
+
module SocketForwarder
+ # The file descriptor for the socket.
+ def fileno
+ to_io.fileno
+ end
+
def addr
to_io.addr
end
@@ -29,6 +187,14 @@ module OpenSSL
to_io.peeraddr
end
+ def local_address
+ to_io.local_address
+ end
+
+ def remote_address
+ to_io.remote_address
+ end
+
def setsockopt(level, optname, optval)
to_io.setsockopt(level, optname, optval)
end
@@ -48,88 +214,329 @@ module OpenSSL
def do_not_reverse_lookup=(flag)
to_io.do_not_reverse_lookup = flag
end
+
+ def close_on_exec=(value)
+ to_io.close_on_exec = value
+ end
+
+ def close_on_exec?
+ to_io.close_on_exec?
+ end
+
+ def wait(*args)
+ to_io.wait(*args)
+ end
+
+ def wait_readable(*args)
+ to_io.wait_readable(*args)
+ end
+
+ def wait_writable(*args)
+ to_io.wait_writable(*args)
+ end
+
+ if IO.method_defined?(:timeout)
+ def timeout
+ to_io.timeout
+ end
+
+ def timeout=(value)
+ to_io.timeout=(value)
+ end
+ end
end
- module Nonblock
- def initialize(*args)
- flag = File::NONBLOCK
- flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL)
- @io.fcntl(Fcntl::F_SETFL, flag)
- super
+ def verify_certificate_identity(cert, hostname)
+ should_verify_common_name = true
+ cert.extensions.each{|ext|
+ next if ext.oid != "subjectAltName"
+ ostr = OpenSSL::ASN1.decode(ext.to_der).value.last
+ sequence = OpenSSL::ASN1.decode(ostr.value)
+ sequence.value.each{|san|
+ case san.tag
+ when 2 # dNSName in GeneralName (RFC5280)
+ should_verify_common_name = false
+ return true if verify_hostname(hostname, san.value)
+ when 7 # iPAddress in GeneralName (RFC5280)
+ should_verify_common_name = false
+ if san.value.size == 4 || san.value.size == 16
+ begin
+ return true if san.value == IPAddr.new(hostname).hton
+ rescue IPAddr::InvalidAddressError
+ end
+ end
+ end
+ }
+ }
+ if should_verify_common_name
+ cert.subject.to_a.each{|oid, value|
+ if oid == "CN"
+ return true if verify_hostname(hostname, value)
+ end
+ }
end
+ return false
+ end
+ module_function :verify_certificate_identity
+
+ def verify_hostname(hostname, san) # :nodoc:
+ # RFC 5280, IA5String is limited to the set of ASCII characters
+ return false unless san.ascii_only?
+ return false unless hostname.ascii_only?
+
+ # See RFC 6125, section 6.4.1
+ # Matching is case-insensitive.
+ san_parts = san.downcase.split(".")
+
+ # TODO: this behavior should probably be more strict
+ return san == hostname if san_parts.size < 2
+
+ # Matching is case-insensitive.
+ host_parts = hostname.downcase.split(".")
+
+ # RFC 6125, section 6.4.3, subitem 2.
+ # If the wildcard character is the only character of the left-most
+ # label in the presented identifier, the client SHOULD NOT compare
+ # against anything but the left-most label of the reference
+ # identifier (e.g., *.example.com would match foo.example.com but
+ # not bar.foo.example.com or example.com).
+ return false unless san_parts.size == host_parts.size
+
+ # RFC 6125, section 6.4.3, subitem 1.
+ # The client SHOULD NOT attempt to match a presented identifier in
+ # which the wildcard character comprises a label other than the
+ # left-most label (e.g., do not match bar.*.example.net).
+ return false unless verify_wildcard(host_parts.shift, san_parts.shift)
+
+ san_parts.join(".") == host_parts.join(".")
+ end
+ module_function :verify_hostname
+
+ def verify_wildcard(domain_component, san_component) # :nodoc:
+ parts = san_component.split("*", -1)
+
+ return false if parts.size > 2
+ return san_component == domain_component if parts.size == 1
+
+ # RFC 6125, section 6.4.3, subitem 3.
+ # The client SHOULD NOT attempt to match a presented identifier
+ # where the wildcard character is embedded within an A-label or
+ # U-label of an internationalized domain name.
+ return false if domain_component.start_with?("xn--") && san_component != "*"
+
+ parts[0].length + parts[1].length < domain_component.length &&
+ domain_component.start_with?(parts[0]) &&
+ domain_component.end_with?(parts[1])
end
+ module_function :verify_wildcard
class SSLSocket
include Buffering
include SocketForwarder
- include Nonblock
+ attr_reader :hostname
+
+ # The underlying IO object.
+ attr_reader :io
+ alias :to_io :io
+
+ # The SSLContext object used in this connection.
+ attr_reader :context
+
+ # Whether to close the underlying socket as well, when the SSL/TLS
+ # connection is shut down. This defaults to +false+.
+ attr_accessor :sync_close
+
+ # call-seq:
+ # ssl.sysclose => nil
+ #
+ # Sends "close notify" to the peer and tries to shut down the SSL
+ # connection gracefully.
+ #
+ # If sync_close is set to +true+, the underlying IO is also closed.
+ def sysclose
+ return if closed?
+ stop
+ io.close if sync_close
+ end
+
+ # call-seq:
+ # ssl.post_connection_check(hostname) -> true
+ #
+ # Perform hostname verification following RFC 6125.
+ #
+ # This method MUST be called after calling #connect to ensure that the
+ # hostname of a remote peer has been verified.
def post_connection_check(hostname)
- check_common_name = true
- cert = peer_cert
- cert.extensions.each{|ext|
- next if ext.oid != "subjectAltName"
- ext.value.split(/,\s+/).each{|general_name|
- if /\ADNS:(.*)/ =~ general_name
- check_common_name = false
- reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
- return true if /\A#{reg}\z/i =~ hostname
- elsif /\AIP Address:(.*)/ =~ general_name
- check_common_name = false
- return true if $1 == hostname
- end
- }
- }
- if check_common_name
- cert.subject.to_a.each{|oid, value|
- if oid == "CN"
- reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
- return true if /\A#{reg}\z/i =~ hostname
- end
- }
+ if peer_cert.nil?
+ msg = "Peer verification enabled, but no certificate received."
+ if using_anon_cipher?
+ msg += " Anonymous cipher suite #{cipher[0]} was negotiated. " \
+ "Anonymous suites must be disabled to use peer verification."
+ end
+ raise SSLError, msg
+ end
+
+ unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
+ raise SSLError, "hostname \"#{hostname}\" does not match the server certificate"
+ end
+ return true
+ end
+
+ # call-seq:
+ # ssl.session -> aSession
+ #
+ # Returns the SSLSession object currently used, or nil if the session is
+ # not established.
+ def session
+ SSL::Session.new(self)
+ rescue SSL::Session::SessionError
+ nil
+ end
+
+ # Close the stream for reading.
+ # This method is ignored by OpenSSL as there is no reasonable way to
+ # implement it, but exists for compatibility with IO.
+ def close_read
+ # Unsupported and ignored.
+ # Just don't read any more.
+ end
+
+ # Closes the stream for writing. The behavior of this method depends on
+ # the version of OpenSSL and the TLS protocol in use.
+ #
+ # - Sends a 'close_notify' alert to the peer.
+ # - Does not wait for the peer's 'close_notify' alert in response.
+ #
+ # In TLS 1.2 and earlier:
+ # - On receipt of a 'close_notify' alert, responds with a 'close_notify'
+ # alert of its own and close down the connection immediately,
+ # discarding any pending writes.
+ #
+ # Therefore, on TLS 1.2, this method will cause the connection to be
+ # completely shut down. On TLS 1.3, the connection will remain open for
+ # reading only.
+ def close_write
+ stop
+ end
+
+ private
+
+ def using_anon_cipher?
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ciphers = "aNULL"
+ ctx.ciphers.include?(cipher)
+ end
+
+ def client_cert_cb
+ @context.client_cert_cb
+ end
+
+ def session_new_cb
+ @context.session_new_cb
+ end
+
+ def session_get_cb
+ @context.session_get_cb
+ end
+
+ class << self
+
+ # call-seq:
+ # open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil)
+ #
+ # Creates a new instance of SSLSocket.
+ # _remote\_host_ and _remote\_port_ are used to open TCPSocket.
+ # If _local\_host_ and _local\_port_ are specified,
+ # then those parameters are used on the local end to establish the connection.
+ # If _context_ is provided,
+ # the SSL Sockets initial params will be taken from the context.
+ #
+ # === Examples
+ #
+ # sock = OpenSSL::SSL::SSLSocket.open('localhost', 443)
+ # sock.connect # Initiates a connection to localhost:443
+ #
+ # with SSLContext:
+ #
+ # ctx = OpenSSL::SSL::SSLContext.new
+ # sock = OpenSSL::SSL::SSLSocket.open('localhost', 443, context: ctx)
+ # sock.connect # Initiates a connection to localhost:443 with SSLContext
+ def open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil)
+ sock = ::TCPSocket.open(remote_host, remote_port, local_host, local_port)
+ if context.nil?
+ return OpenSSL::SSL::SSLSocket.new(sock)
+ else
+ return OpenSSL::SSL::SSLSocket.new(sock, context)
+ end
end
- raise SSLError, "hostname not match"
end
end
+ ##
+ # SSLServer represents a TCP/IP server socket with Secure Sockets Layer.
class SSLServer
include SocketForwarder
+ # When true then #accept works exactly the same as TCPServer#accept
attr_accessor :start_immediately
+ # Creates a new instance of SSLServer.
+ # * _srv_ is an instance of TCPServer.
+ # * _ctx_ is an instance of OpenSSL::SSL::SSLContext.
def initialize(svr, ctx)
@svr = svr
@ctx = ctx
unless ctx.session_id_context
- session_id = OpenSSL::Digest::MD5.hexdigest($0)
+ # see #6137 - session id may not exceed 32 bytes
+ prng = ::Random.new($0.hash)
+ session_id = prng.bytes(16).unpack1('H*')
@ctx.session_id_context = session_id
end
@start_immediately = true
end
+ # Returns the TCPServer passed to the SSLServer when initialized.
def to_io
@svr
end
- def listen(backlog=5)
+ # See TCPServer#listen for details.
+ def listen(backlog=Socket::SOMAXCONN)
@svr.listen(backlog)
end
+ # See BasicSocket#shutdown for details.
+ def shutdown(how=Socket::SHUT_RDWR)
+ @svr.shutdown(how)
+ end
+
+ # Works similar to TCPServer#accept.
def accept
- sock = @svr.accept
+ # Socket#accept returns [socket, addrinfo].
+ # TCPServer#accept returns a socket.
+ # The following comma strips addrinfo.
+ sock, = @svr.accept
begin
ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
ssl.sync_close = true
ssl.accept if @start_immediately
ssl
- rescue SSLError => ex
- sock.close
+ rescue Exception => ex
+ if ssl
+ ssl.close
+ else
+ sock.close
+ end
raise ex
end
end
+ # See IO#close for details.
def close
@svr.close
end
end
end
end
+
+end
diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb
new file mode 100644
index 0000000000..395a720a31
--- /dev/null
+++ b/ext/openssl/lib/openssl/version.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+module OpenSSL
+ # The version string of Ruby/OpenSSL.
+ VERSION = "4.0.2"
+end
diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb
index e711bda39c..66765ffeab 100644
--- a/ext/openssl/lib/openssl/x509.rb
+++ b/ext/openssl/lib/openssl/x509.rb
@@ -1,20 +1,18 @@
-=begin
-= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for X509 and subclasses
+# frozen_string_literal: true
+#--
+# = Ruby-space definitions that completes C-space funcs for X509 and subclasses
+#
+# = Info
+# 'OpenSSL for Ruby 2' project
+# Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+# All rights reserved.
+#
+# = Licence
+# This program is licensed under the same licence as Ruby.
+# (See the file 'COPYING'.)
+#++
-= Info
- 'OpenSSL for Ruby 2' project
- Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
- All rights reserved.
-
-= Licence
- This program is licenced under the same licence as Ruby.
- (See the file 'LICENCE'.)
-
-= Version
- $Id$
-=end
-
-require "openssl"
+require_relative 'marshal'
module OpenSSL
module X509
@@ -28,7 +26,7 @@ module OpenSSL
end
def create_ext_from_array(ary)
- raise ExtensionError, "unexpected array form" if ary.size > 3
+ raise ExtensionError, "unexpected array form" if ary.size > 3
create_ext(ary[0], ary[1], ary[2])
end
@@ -38,20 +36,27 @@ module OpenSSL
value.strip!
create_ext(oid, value)
end
-
+
def create_ext_from_hash(hash)
create_ext(hash["oid"], hash["value"], hash["critical"])
end
end
-
+
class Extension
+ include OpenSSL::Marshal
+
+ def ==(other)
+ return false unless Extension === other
+ to_der == other.to_der
+ end
+
def to_s # "oid = critical, value"
str = self.oid
str << " = "
str << "critical, " if self.critical?
str << self.value.gsub(/\n/, ", ")
end
-
+
def to_h # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false}
{"oid"=>self.oid,"value"=>self.value,"critical"=>self.critical?}
end
@@ -59,16 +64,153 @@ module OpenSSL
def to_a
[ self.oid, self.value, self.critical? ]
end
+
+ module Helpers
+ def find_extension(oid)
+ extensions.find { |e| e.oid == oid }
+ end
+ end
+
+ module SubjectKeyIdentifier
+ include Helpers
+
+ # Get the subject's key identifier from the subjectKeyIdentifier
+ # exteension, as described in RFC5280 Section 4.2.1.2.
+ #
+ # Returns the binary String key identifier or nil or raises
+ # ASN1::ASN1Error.
+ def subject_key_identifier
+ ext = find_extension("subjectKeyIdentifier")
+ return nil if ext.nil?
+
+ ski_asn1 = ASN1.decode(ext.value_der)
+ if ext.critical? || ski_asn1.tag_class != :UNIVERSAL || ski_asn1.tag != ASN1::OCTET_STRING
+ raise ASN1::ASN1Error, "invalid extension"
+ end
+
+ ski_asn1.value
+ end
+ end
+
+ module AuthorityKeyIdentifier
+ include Helpers
+
+ # Get the issuing certificate's key identifier from the
+ # authorityKeyIdentifier extension, as described in RFC5280
+ # Section 4.2.1.1
+ #
+ # Returns the binary String keyIdentifier or nil or raises
+ # ASN1::ASN1Error.
+ def authority_key_identifier
+ ext = find_extension("authorityKeyIdentifier")
+ return nil if ext.nil?
+
+ aki_asn1 = ASN1.decode(ext.value_der)
+ if ext.critical? || aki_asn1.tag_class != :UNIVERSAL || aki_asn1.tag != ASN1::SEQUENCE
+ raise ASN1::ASN1Error, "invalid extension"
+ end
+
+ key_id = aki_asn1.value.find do |v|
+ v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
+ end
+
+ key_id.nil? ? nil : key_id.value
+ end
+ end
+
+ module CRLDistributionPoints
+ include Helpers
+
+ # Get the distributionPoint fullName URI from the certificate's CRL
+ # distribution points extension, as described in RFC 5280 Section
+ # 4.2.1.13.
+ #
+ # Returns an array of strings or nil or raises ASN1::ASN1Error.
+ def crl_uris
+ ext = find_extension("crlDistributionPoints")
+ return nil if ext.nil?
+
+ cdp_asn1 = ASN1.decode(ext.value_der)
+ if cdp_asn1.tag_class != :UNIVERSAL || cdp_asn1.tag != ASN1::SEQUENCE
+ raise ASN1::ASN1Error, "invalid extension"
+ end
+
+ crl_uris = cdp_asn1.flat_map do |crl_distribution_point|
+ distribution_point = crl_distribution_point.value.find do |v|
+ v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
+ end
+ full_name = distribution_point&.value&.find do |v|
+ v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
+ end
+ full_name&.value&.select do |v|
+ v.tag_class == :CONTEXT_SPECIFIC && v.tag == 6 # uniformResourceIdentifier
+ end
+ end
+
+ crl_uris.empty? ? nil : crl_uris.map(&:value)
+ end
+ end
+
+ module AuthorityInfoAccess
+ include Helpers
+
+ # Get the information and services for the issuer from the certificate's
+ # authority information access extension exteension, as described in RFC5280
+ # Section 4.2.2.1.
+ #
+ # Returns an array of strings or nil or raises ASN1::ASN1Error.
+ def ca_issuer_uris
+ aia_asn1 = parse_aia_asn1
+ return nil if aia_asn1.nil?
+
+ ca_issuer = aia_asn1.value.select do |authority_info_access|
+ authority_info_access.value.first.value == "caIssuers"
+ end
+
+ ca_issuer&.map(&:value)&.map(&:last)&.map(&:value)
+ end
+
+ # Get the URIs for OCSP from the certificate's authority information access
+ # extension exteension, as described in RFC5280 Section 4.2.2.1.
+ #
+ # Returns an array of strings or nil or raises ASN1::ASN1Error.
+ def ocsp_uris
+ aia_asn1 = parse_aia_asn1
+ return nil if aia_asn1.nil?
+
+ ocsp = aia_asn1.value.select do |authority_info_access|
+ authority_info_access.value.first.value == "OCSP"
+ end
+
+ ocsp&.map(&:value)&.map(&:last)&.map(&:value)
+ end
+
+ private
+
+ def parse_aia_asn1
+ ext = find_extension("authorityInfoAccess")
+ return nil if ext.nil?
+
+ aia_asn1 = ASN1.decode(ext.value_der)
+ if ext.critical? || aia_asn1.tag_class != :UNIVERSAL || aia_asn1.tag != ASN1::SEQUENCE
+ raise ASN1::ASN1Error, "invalid extension"
+ end
+
+ aia_asn1
+ end
+ end
end
class Name
+ include OpenSSL::Marshal
+
module RFC2253DN
Special = ',=+<>#;'
HexChar = /[0-9a-fA-F]/
HexPair = /#{HexChar}#{HexChar}/
HexString = /#{HexPair}+/
Pair = /\\(?:[#{Special}]|\\|"|#{HexPair})/
- StringChar = /[^#{Special}\\"]/
+ StringChar = /[^\\"#{Special}]/
QuoteChar = /[^\\"]/
AttributeType = /[a-zA-Z][0-9a-zA-Z]*|[0-9]+(?:\.[0-9]+)*/
AttributeValue = /
@@ -82,7 +224,8 @@ module OpenSSL
def expand_pair(str)
return nil unless str
- return str.gsub(Pair){|pair|
+ return str.gsub(Pair){
+ pair = $&
case pair.size
when 2 then pair[1,1]
when 3 then Integer("0x#{pair[1,2]}").chr
@@ -93,7 +236,7 @@ module OpenSSL
def expand_hexstring(str)
return nil unless str
- der = str.gsub(HexPair){|hex| Integer("0x#{hex}").chr }
+ der = str.gsub(HexPair){$&.to_i(16).chr }
a1 = OpenSSL::ASN1.decode(der)
return a1.value, a1.tag
end
@@ -110,7 +253,6 @@ module OpenSSL
ary = []
while true
if md = TypeAndValue.match(str)
- matched = md.to_s
remain = md.post_match
type = md[1]
value, tag = expand_value(md[2], md[3], md[4]) rescue nil
@@ -136,19 +278,123 @@ module OpenSSL
end
end
- class <<self
+ class << self
+ # Parses the UTF-8 string representation of a distinguished name,
+ # according to RFC 2253.
+ #
+ # See also #to_utf8 for the opposite operation.
def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE)
ary = OpenSSL::X509::Name::RFC2253DN.scan(str)
self.new(ary, template)
end
+ # Parses the string representation of a distinguished name. Two
+ # different forms are supported:
+ #
+ # - \OpenSSL format (<tt>X509_NAME_oneline()</tt>) used by
+ # <tt>#to_s</tt>. For example: <tt>/DC=com/DC=example/CN=nobody</tt>
+ # - \OpenSSL format (<tt>X509_NAME_print()</tt>)
+ # used by <tt>#to_s(OpenSSL::X509::Name::COMPAT)</tt>. For example:
+ # <tt>DC=com, DC=example, CN=nobody</tt>
+ #
+ # Neither of them is standardized and has quirks and inconsistencies
+ # in handling of escaped characters or multi-valued RDNs.
+ #
+ # Use of this method is discouraged in new applications. See
+ # Name.parse_rfc2253 and #to_utf8 for the alternative.
def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE)
- ary = str.scan(/\s*([^\/,]+)\s*/).collect{|i| i[0].split("=", 2) }
+ if str.start_with?("/")
+ # /A=B/C=D format
+ ary = str[1..-1].split("/").map { |i| i.split("=", 2) }
+ else
+ # Comma-separated
+ ary = str.split(",").map { |i| i.strip.split("=", 2) }
+ end
self.new(ary, template)
end
alias parse parse_openssl
end
+
+ def pretty_print(q)
+ q.object_group(self) {
+ q.text ' '
+ q.text to_s(OpenSSL::X509::Name::RFC2253)
+ }
+ end
+ end
+
+ class Attribute
+ include OpenSSL::Marshal
+
+ def ==(other)
+ return false unless Attribute === other
+ to_der == other.to_der
+ end
+ end
+
+ class StoreContext
+ def cleanup
+ warn "(#{caller.first}) OpenSSL::X509::StoreContext#cleanup is deprecated with no replacement" if $VERBOSE
+ end
+ end
+
+ class Certificate
+ include OpenSSL::Marshal
+ include Extension::SubjectKeyIdentifier
+ include Extension::AuthorityKeyIdentifier
+ include Extension::CRLDistributionPoints
+ include Extension::AuthorityInfoAccess
+
+ def inspect
+ "#<#{self.class}: " \
+ "subject=#{subject.inspect}, " \
+ "issuer=#{issuer.inspect}, " \
+ "serial=#{serial.inspect}, " \
+ "not_before=#{not_before.inspect rescue "(error)"}, " \
+ "not_after=#{not_after.inspect rescue "(error)"}>"
+ end
+
+ def pretty_print(q)
+ q.object_group(self) {
+ q.breakable
+ q.text 'subject='; q.pp self.subject; q.text ','; q.breakable
+ q.text 'issuer='; q.pp self.issuer; q.text ','; q.breakable
+ q.text 'serial='; q.pp self.serial; q.text ','; q.breakable
+ q.text 'not_before='; q.pp self.not_before; q.text ','; q.breakable
+ q.text 'not_after='; q.pp self.not_after
+ }
+ end
+
+ def self.load_file(path)
+ load(File.binread(path))
+ end
+ end
+
+ class CRL
+ include OpenSSL::Marshal
+ include Extension::AuthorityKeyIdentifier
+
+ def ==(other)
+ return false unless CRL === other
+ to_der == other.to_der
+ end
+ end
+
+ class Revoked
+ def ==(other)
+ return false unless Revoked === other
+ to_der == other.to_der
+ end
+ end
+
+ class Request
+ include OpenSSL::Marshal
+
+ def ==(other)
+ return false unless Request === other
+ to_der == other.to_der
+ end
end
end
end
diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec
new file mode 100644
index 0000000000..af1775e3b0
--- /dev/null
+++ b/ext/openssl/openssl.gemspec
@@ -0,0 +1,28 @@
+Gem::Specification.new do |spec|
+ spec.name = "openssl"
+ spec.version = "4.0.2"
+ spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"]
+ spec.email = ["ruby-core@ruby-lang.org"]
+ spec.summary = %q{SSL/TLS and general-purpose cryptography for Ruby}
+ spec.description = %q{OpenSSL for Ruby provides access to SSL/TLS and general-purpose cryptography based on the OpenSSL library.}
+ spec.homepage = "https://github.com/ruby/openssl"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby'
+ spec.platform = "java"
+ spec.files = []
+ spec.add_runtime_dependency('jruby-openssl', '~> 0.14')
+ else
+ spec.files = Dir.glob(["lib/**/*.rb", "ext/**/*.{c,h,rb}", "*.md"], base: File.expand_path("..", __FILE__)) +
+ ["BSDL", "COPYING"]
+ spec.require_paths = ["lib"]
+ spec.extensions = ["ext/openssl/extconf.rb"]
+ end
+
+ spec.extra_rdoc_files = Dir["*.md"]
+ spec.rdoc_options = ["--main", "README.md"]
+
+ spec.required_ruby_version = ">= 2.7.0"
+
+ spec.metadata["msys2_mingw_dependencies"] = "openssl"
+end
diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c
deleted file mode 100644
index f77731ed65..0000000000
--- a/ext/openssl/openssl_missing.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * $Id$
- * 'OpenSSL for Ruby' project
- * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
- * All rights reserved.
- */
-/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
- */
-#include RUBY_EXTCONF_H
-
-#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ST_ENGINE)
-# include <openssl/engine.h>
-#endif
-#include <openssl/x509_vfy.h>
-
-#if !defined(OPENSSL_NO_HMAC)
-#include <string.h> /* memcpy() */
-#include <openssl/hmac.h>
-
-#include "openssl_missing.h"
-
-#if !defined(HAVE_HMAC_CTX_COPY)
-int
-HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
-{
- if (!out || !in) return 0;
- memcpy(out, in, sizeof(HMAC_CTX));
-
- if (!EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx)
- || !EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx)
- || !EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx))
- return 0;
- return 1;
-}
-#endif /* HAVE_HMAC_CTX_COPY */
-#endif /* NO_HMAC */
-
-#if !defined(HAVE_X509_STORE_SET_EX_DATA)
-
-int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data)
-{
- return CRYPTO_set_ex_data(&str->ex_data, idx, data);
-}
-
-void *X509_STORE_get_ex_data(X509_STORE *str, int idx)
-{
- return CRYPTO_get_ex_data(&str->ex_data, idx);
-}
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_CREATE)
-EVP_MD_CTX *
-EVP_MD_CTX_create(void)
-{
- EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX));
- if (!ctx) return NULL;
-
- memset(ctx, 0, sizeof(EVP_MD_CTX));
-
- return ctx;
-}
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_CLEANUP)
-int
-EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
-{
- /* FIXME!!! */
- memset(ctx, 0, sizeof(EVP_MD_CTX));
-
- return 1;
-}
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_DESTROY)
-void
-EVP_MD_CTX_destroy(EVP_MD_CTX *ctx)
-{
- EVP_MD_CTX_cleanup(ctx);
- OPENSSL_free(ctx);
-}
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_INIT)
-void
-EVP_MD_CTX_init(EVP_MD_CTX *ctx)
-{
- memset(ctx, 0, sizeof(EVP_MD_CTX));
-}
-#endif
-
-#if !defined(HAVE_HMAC_CTX_INIT)
-void
-HMAC_CTX_init(HMAC_CTX *ctx)
-{
- EVP_MD_CTX_init(&ctx->i_ctx);
- EVP_MD_CTX_init(&ctx->o_ctx);
- EVP_MD_CTX_init(&ctx->md_ctx);
-}
-#endif
-
-#if !defined(HAVE_HMAC_CTX_CLEANUP)
-void
-HMAC_CTX_cleanup(HMAC_CTX *ctx)
-{
- EVP_MD_CTX_cleanup(&ctx->i_ctx);
- EVP_MD_CTX_cleanup(&ctx->o_ctx);
- EVP_MD_CTX_cleanup(&ctx->md_ctx);
- memset(ctx, 0, sizeof(HMAC_CTX));
-}
-#endif
-
-#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
-/*
- * this function does not exist in OpenSSL yet... or ever?.
- * a future version may break this function.
- * tested on 0.9.7d.
- */
-int
-EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in)
-{
- memcpy(out, in, sizeof(EVP_CIPHER_CTX));
-
-#if defined(HAVE_ENGINE_ADD) && defined(HAVE_ST_ENGINE)
- if (in->engine) ENGINE_add(out->engine);
- if (in->cipher_data) {
- out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
- memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
- }
-#endif
-
- return 1;
-}
-#endif
-
-#if !defined(HAVE_X509_CRL_SET_VERSION)
-int
-X509_CRL_set_version(X509_CRL *x, long version)
-{
- if (x == NULL || x->crl == NULL) return 0;
- if (x->crl->version == NULL) {
- x->crl->version = M_ASN1_INTEGER_new();
- if (x->crl->version == NULL) return 0;
- }
- return ASN1_INTEGER_set(x->crl->version, version);
-}
-#endif
-
-#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME)
-int
-X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name)
-{
- if (x == NULL || x->crl == NULL) return 0;
- return X509_NAME_set(&x->crl->issuer, name);
-}
-#endif
-
-#if !defined(HAVE_X509_CRL_SORT)
-int
-X509_CRL_sort(X509_CRL *c)
-{
- int i;
- X509_REVOKED *r;
- /* sort the data so it will be written in serial
- * number order */
- sk_X509_REVOKED_sort(c->crl->revoked);
- for (i=0; i<sk_X509_REVOKED_num(c->crl->revoked); i++) {
- r=sk_X509_REVOKED_value(c->crl->revoked, i);
- r->sequence=i;
- }
- return 1;
-}
-#endif
-
-#if !defined(HAVE_X509_CRL_ADD0_REVOKED)
-static int
-OSSL_X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const *b)
-{
- return(ASN1_STRING_cmp(
- (ASN1_STRING *)(*a)->serialNumber,
- (ASN1_STRING *)(*b)->serialNumber));
-}
-
-int
-X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
-{
- X509_CRL_INFO *inf;
-
- inf = crl->crl;
- if (!inf->revoked)
- inf->revoked = sk_X509_REVOKED_new(OSSL_X509_REVOKED_cmp);
- if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev))
- return 0;
- return 1;
-}
-#endif
-
-#if !defined(HAVE_BN_MOD_SQR)
-int
-BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
-{
- if (!BN_sqr(r, (BIGNUM*)a, ctx)) return 0;
- return BN_mod(r, r, m, ctx);
-}
-#endif
-
-#if !defined(HAVE_BN_MOD_ADD) || !defined(HAVE_BN_MOD_SUB)
-int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
-{
- if (!BN_mod(r,m,d,ctx)) return 0;
- if (!r->neg) return 1;
- return (d->neg ? BN_sub : BN_add)(r, r, d);
-}
-#endif
-
-#if !defined(HAVE_BN_MOD_ADD)
-int
-BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
-{
- if (!BN_add(r, a, b)) return 0;
- return BN_nnmod(r, r, m, ctx);
-}
-#endif
-
-#if !defined(HAVE_BN_MOD_SUB)
-int
-BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
-{
- if (!BN_sub(r, a, b)) return 0;
- return BN_nnmod(r, r, m, ctx);
-}
-#endif
-
-#if !defined(HAVE_BN_RAND_RANGE) || !defined(HAVE_BN_PSEUDO_RAND_RANGE)
-static int
-bn_rand_range(int pseudo, BIGNUM *r, BIGNUM *range)
-{
- int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand;
- int n;
-
- if (range->neg || BN_is_zero(range)) return 0;
-
- n = BN_num_bits(range);
-
- if (n == 1) {
- if (!BN_zero(r)) return 0;
- } else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) {
- do {
- if (!bn_rand(r, n + 1, -1, 0)) return 0;
- if (BN_cmp(r ,range) >= 0) {
- if (!BN_sub(r, r, range)) return 0;
- if (BN_cmp(r, range) >= 0)
- if (!BN_sub(r, r, range)) return 0;
- }
- } while (BN_cmp(r, range) >= 0);
- } else {
- do {
- if (!bn_rand(r, n, -1, 0)) return 0;
- } while (BN_cmp(r, range) >= 0);
- }
-
- return 1;
-}
-#endif
-
-#if !defined(HAVE_BN_RAND_RANGE)
-int
-BN_rand_range(BIGNUM *r, BIGNUM *range)
-{
- return bn_rand_range(0, r, range);
-}
-#endif
-
-#if !defined(HAVE_BN_PSEUDO_RAND_RANGE)
-int
-BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range)
-{
- return bn_rand_range(1, r, range);
-}
-#endif
-
-#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE)
-#define OPENSSL_CONF "openssl.cnf"
-char *
-CONF_get1_default_config_file(void)
-{
- char *file;
- int len;
-
- file = getenv("OPENSSL_CONF");
- if (file) return BUF_strdup(file);
- len = strlen(X509_get_default_cert_area());
-#ifndef OPENSSL_SYS_VMS
- len++;
-#endif
- len += strlen(OPENSSL_CONF);
- file = OPENSSL_malloc(len + 1);
- if (!file) return NULL;
- strcpy(file,X509_get_default_cert_area());
-#ifndef OPENSSL_SYS_VMS
- strcat(file,"/");
-#endif
- strcat(file,OPENSSL_CONF);
-
- return file;
-}
-#endif
-
-#if !defined(HAVE_PEM_DEF_CALLBACK)
-#define OSSL_PASS_MIN_LENGTH 4
-int
-PEM_def_callback(char *buf, int num, int w, void *key)
-{
- int i,j;
- const char *prompt;
-
- if (key) {
- i = strlen(key);
- i = (i > num) ? num : i;
- memcpy(buf, key, i);
- return i;
- }
-
- prompt = EVP_get_pw_prompt();
- if (prompt == NULL) prompt = "Enter PEM pass phrase:";
- for (;;) {
- i = EVP_read_pw_string(buf, num, prompt, w);
- if (i != 0) {
- memset(buf, 0, (unsigned int)num);
- return(-1);
- }
- j = strlen(buf);
- if (j < OSSL_PASS_MIN_LENGTH) {
- fprintf(stderr,
- "phrase is too short, needs to be at least %d chars\n",
- OSSL_PASS_MIN_LENGTH);
- }
- else break;
- }
- return j;
-}
-#endif
-
diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
index e8c75ca42c..ed3b5b7c0f 100644
--- a/ext/openssl/openssl_missing.h
+++ b/ext/openssl/openssl_missing.h
@@ -1,130 +1,55 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_OPENSSL_MISSING_H_)
#define _OSSL_OPENSSL_MISSING_H_
-#if defined(__cplusplus)
-extern "C" {
+#include "ruby/config.h"
+
+/* added in 3.0.0 */
+#ifndef HAVE_EVP_MD_CTX_GET0_MD
+# define EVP_MD_CTX_get0_md(ctx) EVP_MD_CTX_md(ctx)
#endif
/*
- * These functions are not included in headers of OPENSSL <= 0.9.6b
+ * OpenSSL 1.1.0 added EVP_MD_CTX_pkey_ctx(), and then it was renamed to
+ * EVP_MD_CTX_get_pkey_ctx(x) in OpenSSL 3.0.
*/
-
-#if !defined(PEM_read_bio_DSAPublicKey)
-# define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
- (char *(*)())d2i_DSAPublicKey,PEM_STRING_DSA_PUBLIC,bp,(char **)x,cb,u)
-#endif
-
-#if !defined(PEM_write_bio_DSAPublicKey)
-# define PEM_write_bio_DSAPublicKey(bp,x) \
- PEM_ASN1_write_bio((int (*)())i2d_DSAPublicKey,\
- PEM_STRING_DSA_PUBLIC,\
- bp,(char *)x, NULL, NULL, 0, NULL, NULL)
-#endif
-
-#if !defined(DSAPrivateKey_dup)
-# define DSAPrivateKey_dup(dsa) (DSA *)ASN1_dup((int (*)())i2d_DSAPrivateKey, \
- (char *(*)())d2i_DSAPrivateKey,(char *)dsa)
-#endif
-
-#if !defined(DSAPublicKey_dup)
-# define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup((int (*)())i2d_DSAPublicKey, \
- (char *(*)())d2i_DSAPublicKey,(char *)dsa)
-#endif
-
-#if !defined(X509_REVOKED_dup)
-# define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((int (*)())i2d_X509_REVOKED, \
- (char *(*)())d2i_X509_REVOKED, (char *)rev)
+#ifndef HAVE_EVP_MD_CTX_GET_PKEY_CTX
+# define EVP_MD_CTX_get_pkey_ctx(x) EVP_MD_CTX_pkey_ctx(x)
#endif
-#if !defined(PKCS7_SIGNER_INFO_dup)
-# define PKCS7_SIGNER_INFO_dup(si) (PKCS7_SIGNER_INFO *)ASN1_dup((int (*)())i2d_PKCS7_SIGNER_INFO, \
- (char *(*)())d2i_PKCS7_SIGNER_INFO, (char *)si)
-#endif
-
-#if !defined(PKCS7_RECIP_INFO_dup)
-# define PKCS7_RECIP_INFO_dup(ri) (PKCS7_RECIP_INFO *)ASN1_dup((int (*)())i2d_PKCS7_RECIP_INFO, \
- (char *(*)())d2i_PKCS7_RECIP_INFO, (char *)ri)
-#endif
-
-void HMAC_CTX_init(HMAC_CTX *ctx);
-int HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
-void HMAC_CTX_cleanup(HMAC_CTX *ctx);
-
-EVP_MD_CTX *EVP_MD_CTX_create(void);
-void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
-int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
-void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
-
-#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
-int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in);
-#endif
-
-#if !defined(HAVE_EVP_DIGESTINIT_EX)
-# define EVP_DigestInit_ex(ctx, md, engine) EVP_DigestInit(ctx, md)
-#endif
-#if !defined(HAVE_EVP_DIGESTFINAL_EX)
-# define EVP_DigestFinal_ex(ctx, buf, len) EVP_DigestFinal(ctx, buf, len)
+#ifndef HAVE_EVP_PKEY_EQ
+# define EVP_PKEY_eq(a, b) EVP_PKEY_cmp(a, b)
#endif
-#if !defined(HAVE_EVP_CIPHERINIT_EX)
-# define EVP_CipherInit_ex(ctx, type, impl, key, iv, enc) EVP_CipherInit(ctx, type, key, iv, enc)
-#endif
-#if !defined(HAVE_EVP_CIPHERFINAL_EX)
-# define EVP_CipherFinal_ex(ctx, outm, outl) EVP_CipherFinal(ctx, outm, outl)
-#endif
-
-#if !defined(EVP_CIPHER_name)
-# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e))
-#endif
-
-#if !defined(EVP_MD_name)
-# define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_type(e))
-#endif
-
-#if !defined(HAVE_EVP_HMAC_INIT_EX)
-# define HMAC_Init_ex(ctx, key, len, digest, engine) HMAC_Init(ctx, key, len, digest)
-#endif
-
-#if !defined(PKCS7_is_detached)
-# define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7))
-#endif
-
-#if !defined(PKCS7_type_is_encrypted)
-# define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted)
-#endif
-
-#if !defined(HAVE_OPENSSL_CLEANSE)
-#define OPENSSL_cleanse(p, l) memset(p, 0, l)
-#endif
-
-void *X509_STORE_get_ex_data(X509_STORE *str, int idx);
-int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data);
-int X509_CRL_set_version(X509_CRL *x, long version);
-int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
-int X509_CRL_sort(X509_CRL *c);
-int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
-int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
-int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
-int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
-int BN_rand_range(BIGNUM *r, BIGNUM *range);
-int BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range);
-char *CONF_get1_default_config_file(void);
-int PEM_def_callback(char *buf, int num, int w, void *key);
+/* added in 4.0.0 */
+#ifndef HAVE_ASN1_BIT_STRING_SET1
+static inline int
+ASN1_BIT_STRING_set1(ASN1_BIT_STRING *bitstr, const uint8_t *data,
+ size_t length, int unused_bits)
+{
+ if (length > INT_MAX || !ASN1_STRING_set(bitstr, data, (int)length))
+ return 0;
+ bitstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+ bitstr->flags |= ASN1_STRING_FLAG_BITS_LEFT | unused_bits;
+ return 1;
+}
-#if defined(__cplusplus)
+static inline int
+ASN1_BIT_STRING_get_length(const ASN1_BIT_STRING *bitstr, size_t *length,
+ int *unused_bits)
+{
+ *length = bitstr->length;
+ *unused_bits = bitstr->flags & 0x07;
+ return 1;
}
#endif
-
#endif /* _OSSL_OPENSSL_MISSING_H_ */
-
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index a98f2641cc..5716e6f100 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -1,238 +1,224 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
#include <stdarg.h> /* for ossl_raise */
/*
- * String to HEXString conversion
- */
-int
-string2hex(char *buf, int buf_len, char **hexbuf, int *hexbuf_len)
-{
- static const char hex[]="0123456789abcdef";
- int i, len = 2 * buf_len;
-
- if (buf_len < 0 || len < buf_len) { /* PARANOIA? */
- return -1;
- }
- if (!hexbuf) { /* if no buf, return calculated len */
- if (hexbuf_len) {
- *hexbuf_len = len;
- }
- return len;
- }
- if (!(*hexbuf = OPENSSL_malloc(len + 1))) {
- return -1;
- }
- for (i = 0; i < buf_len; i++) {
- (*hexbuf)[2 * i] = hex[((unsigned char)buf[i]) >> 4];
- (*hexbuf)[2 * i + 1] = hex[buf[i] & 0x0f];
- }
- (*hexbuf)[2 * i] = '\0';
-
- if (hexbuf_len) {
- *hexbuf_len = len;
- }
- return len;
-}
-
-/*
* Data Conversion
*/
-STACK_OF(X509) *
-ossl_x509_ary2sk0(VALUE ary)
-{
- STACK_OF(X509) *sk;
- VALUE val;
- X509 *x509;
- int i;
-
- Check_Type(ary, T_ARRAY);
- sk = sk_X509_new_null();
- if (!sk) ossl_raise(eOSSLError, NULL);
-
- for (i = 0; i < RARRAY(ary)->len; i++) {
- val = rb_ary_entry(ary, i);
- if (!rb_obj_is_kind_of(val, cX509Cert)) {
- sk_X509_pop_free(sk, X509_free);
- ossl_raise(eOSSLError, "object not X509 cert in array");
- }
- x509 = DupX509CertPtr(val); /* NEED TO DUP */
- sk_X509_push(sk, x509);
- }
- return sk;
-}
-
-STACK_OF(X509) *
-ossl_protect_x509_ary2sk(VALUE ary, int *status)
-{
- return (STACK_OF(X509)*)rb_protect((VALUE(*)_((VALUE)))ossl_x509_ary2sk0,
- ary, status);
-}
-
-STACK_OF(X509) *
-ossl_x509_ary2sk(VALUE ary)
-{
- STACK_OF(X509) *sk;
- int status = 0;
-
- sk = ossl_protect_x509_ary2sk(ary, &status);
- if(status) rb_jump_tag(status);
-
- return sk;
+#define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \
+VALUE \
+ossl_##name##_ary2sk0(VALUE ary) \
+{ \
+ STACK_OF(type) *sk; \
+ VALUE val; \
+ type *x; \
+ int i; \
+ \
+ Check_Type(ary, T_ARRAY); \
+ sk = sk_##type##_new_null(); \
+ if (!sk) ossl_raise(eOSSLError, NULL); \
+ \
+ for (i = 0; i < RARRAY_LEN(ary); i++) { \
+ val = rb_ary_entry(ary, i); \
+ if (!rb_obj_is_kind_of(val, expected_class)) { \
+ sk_##type##_pop_free(sk, type##_free); \
+ ossl_raise(eOSSLError, "object in array not" \
+ " of class ##type##"); \
+ } \
+ x = dup(val); /* NEED TO DUP */ \
+ if (!sk_##type##_push(sk, x)) { \
+ type##_free(x); \
+ sk_##type##_pop_free(sk, type##_free); \
+ ossl_raise(eOSSLError, NULL); \
+ } \
+ } \
+ return (VALUE)sk; \
+} \
+ \
+STACK_OF(type) * \
+ossl_protect_##name##_ary2sk(VALUE ary, int *status) \
+{ \
+ return (STACK_OF(type)*)rb_protect( \
+ (VALUE (*)(VALUE))ossl_##name##_ary2sk0, \
+ ary, \
+ status); \
+} \
+ \
+STACK_OF(type) * \
+ossl_##name##_ary2sk(VALUE ary) \
+{ \
+ STACK_OF(type) *sk; \
+ int status = 0; \
+ \
+ sk = ossl_protect_##name##_ary2sk(ary, &status); \
+ if (status) rb_jump_tag(status); \
+ \
+ return sk; \
}
+OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr)
-#define OSSL_IMPL_SK2ARY(name, type) \
-VALUE \
-ossl_##name##_sk2ary(STACK *sk) \
-{ \
- type *t; \
- int i, num; \
- VALUE ary; \
- \
- if (!sk) { \
- OSSL_Debug("empty sk!"); \
- return Qnil; \
- } \
- num = sk_num(sk); \
- if (num < 0) { \
- OSSL_Debug("items in sk < -1???"); \
- return rb_ary_new(); \
- } \
- ary = rb_ary_new2(num); \
- \
- for (i=0; i<num; i++) { \
- t = (type *)sk_value(sk, i); \
- rb_ary_push(ary, ossl_##name##_new(t)); \
- } \
- return ary; \
+#define OSSL_IMPL_SK2ARY(name, type) \
+VALUE \
+ossl_##name##_sk2ary(const STACK_OF(type) *sk) \
+{ \
+ type *t; \
+ int i, num; \
+ VALUE ary; \
+ \
+ RUBY_ASSERT(sk != NULL); \
+ num = sk_##type##_num(sk); \
+ ary = rb_ary_new_capa(num); \
+ \
+ for (i=0; i<num; i++) { \
+ t = sk_##type##_value(sk, i); \
+ rb_ary_push(ary, ossl_##name##_new(t)); \
+ } \
+ return ary; \
}
OSSL_IMPL_SK2ARY(x509, X509)
OSSL_IMPL_SK2ARY(x509crl, X509_CRL)
+OSSL_IMPL_SK2ARY(x509name, X509_NAME)
static VALUE
-ossl_str_new(int size)
+ossl_str_new_i(VALUE size)
{
- return rb_str_new(0, size);
+ return rb_str_new(NULL, (long)size);
+}
+
+VALUE
+ossl_str_new(const char *ptr, long len, int *pstate)
+{
+ VALUE str;
+ int state;
+
+ str = rb_protect(ossl_str_new_i, len, &state);
+ if (pstate)
+ *pstate = state;
+ if (state) {
+ if (!pstate)
+ rb_set_errinfo(Qnil);
+ return Qnil;
+ }
+ if (ptr)
+ memcpy(RSTRING_PTR(str), ptr, len);
+ return str;
}
VALUE
ossl_buf2str(char *buf, int len)
{
VALUE str;
- int status = 0;
+ int state;
- str = rb_protect((VALUE(*)_((VALUE)))ossl_str_new, len, &status);
- if(!NIL_P(str)) memcpy(RSTRING(str)->ptr, buf, len);
+ str = ossl_str_new(buf, len, &state);
OPENSSL_free(buf);
- if(status) rb_jump_tag(status);
-
+ if (state)
+ rb_jump_tag(state);
return str;
}
+void
+ossl_bin2hex(const unsigned char *in, char *out, size_t inlen)
+{
+ const char *hex = "0123456789abcdef";
+ size_t i;
+
+ assert(inlen <= LONG_MAX / 2);
+ for (i = 0; i < inlen; i++) {
+ unsigned char p = in[i];
+
+ out[i * 2 + 0] = hex[p >> 4];
+ out[i * 2 + 1] = hex[p & 0x0f];
+ }
+}
+
/*
* our default PEM callback
*/
-static VALUE
-ossl_pem_passwd_cb0(VALUE flag)
-{
- VALUE pass;
+VALUE
+ossl_pem_passwd_value(VALUE pass)
+{
+ if (NIL_P(pass))
+ return Qnil;
+
+ StringValue(pass);
- pass = rb_yield(flag);
- SafeStringValue(pass);
+ /* PEM_BUFSIZE is currently used as the second argument of pem_password_cb,
+ * that is +max_len+ of ossl_pem_passwd_cb() */
+ if (RSTRING_LEN(pass) > PEM_BUFSIZE)
+ ossl_raise(eOSSLError, "password must not be longer than %d bytes", PEM_BUFSIZE);
return pass;
}
+static VALUE
+ossl_pem_passwd_cb0(VALUE flag)
+{
+ VALUE pass = rb_yield(flag);
+ if (NIL_P(pass))
+ return Qnil;
+ StringValue(pass);
+ return pass;
+}
+
int
-ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
+ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
{
- int len, status = 0;
- VALUE rflag, pass;
-
- if (pwd || !rb_block_given_p())
- return PEM_def_callback(buf, max_len, flag, pwd);
+ long len;
+ int status;
+ VALUE rflag, pass = (VALUE)pwd_;
- while (1) {
- /*
- * when the flag is nonzero, this passphrase
- * will be used to perform encryption; otherwise it will
- * be used to perform decryption.
- */
- rflag = flag ? Qtrue : Qfalse;
- pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status);
- if (status) return -1; /* exception was raised. */
- len = RSTRING(pass)->len;
- if (len < 4) { /* 4 is OpenSSL hardcoded limit */
- rb_warning("password must be longer than 4 bytes");
- continue;
- }
- if (len > max_len) {
- rb_warning("password must be shorter then %d bytes", max_len-1);
- continue;
- }
- memcpy(buf, RSTRING(pass)->ptr, len);
- break;
+ if (RTEST(pass)) {
+ /* PEM_def_callback(buf, max_len, flag, StringValueCStr(pass)) does not
+ * work because it does not allow NUL characters and truncates to 1024
+ * bytes silently if the input is over 1024 bytes */
+ if (RB_TYPE_P(pass, T_STRING)) {
+ len = RSTRING_LEN(pass);
+ if (len <= max_len) {
+ memcpy(buf, RSTRING_PTR(pass), len);
+ return (int)len;
+ }
+ }
+ OSSL_Debug("passed data is not valid String???");
+ return -1;
}
- return len;
-}
-/*
- * Verify callback
- */
-int ossl_verify_cb_idx;
-
-VALUE
-ossl_call_verify_cb_proc(struct ossl_verify_cb_args *args)
-{
- return rb_funcall(args->proc, rb_intern("call"), 2,
- args->preverify_ok, args->store_ctx);
-}
-
-int
-ossl_verify_cb(int ok, X509_STORE_CTX *ctx)
-{
- VALUE proc, rctx, ret;
- struct ossl_verify_cb_args args;
- int state = 0;
-
- proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_verify_cb_idx);
- if ((void*)proc == 0)
- proc = (VALUE)X509_STORE_get_ex_data(ctx->ctx, ossl_verify_cb_idx);
- if ((void*)proc == 0)
- return ok;
- if (!NIL_P(proc)) {
- rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new,
- (VALUE)ctx, &state);
- ret = Qfalse;
- if (!state) {
- args.proc = proc;
- args.preverify_ok = ok ? Qtrue : Qfalse;
- args.store_ctx = rctx;
- ret = rb_ensure(ossl_call_verify_cb_proc, (VALUE)&args,
- ossl_x509stctx_clear_ptr, rctx);
- }
- if (ret == Qtrue) {
- X509_STORE_CTX_set_error(ctx, X509_V_OK);
- ok = 1;
- }
- else{
- if (X509_STORE_CTX_get_error(ctx) == X509_V_OK) {
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
- }
- ok = 0;
- }
+ if (!rb_block_given_p()) {
+ return PEM_def_callback(buf, max_len, flag, NULL);
}
- return ok;
+ while (1) {
+ /*
+ * when the flag is nonzero, this password
+ * will be used to perform encryption; otherwise it will
+ * be used to perform decryption.
+ */
+ rflag = flag ? Qtrue : Qfalse;
+ pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status);
+ if (status) {
+ /* ignore an exception raised. */
+ rb_set_errinfo(Qnil);
+ return -1;
+ }
+ if (NIL_P(pass))
+ return -1;
+ len = RSTRING_LEN(pass);
+ if (len > max_len) {
+ rb_warning("password must not be longer than %d bytes", max_len);
+ continue;
+ }
+ memcpy(buf, RSTRING_PTR(pass), len);
+ break;
+ }
+ return (int)len;
}
/*
@@ -248,7 +234,7 @@ VALUE eOSSLError;
/*
* Convert to DER string
*/
-ID ossl_s_to_der;
+static ID ossl_s_to_der;
VALUE
ossl_to_der(VALUE obj)
@@ -265,53 +251,158 @@ VALUE
ossl_to_der_if_possible(VALUE obj)
{
if(rb_respond_to(obj, ossl_s_to_der))
- return ossl_to_der(obj);
+ return ossl_to_der(obj);
return obj;
}
/*
* Errors
*/
+static ID id_i_errors;
+
+static void collect_errors_into(VALUE ary);
+
+VALUE
+ossl_make_error(VALUE exc, VALUE str)
+{
+ unsigned long e;
+ const char *data;
+ int flags;
+ VALUE errors = rb_ary_new();
+
+ if (NIL_P(str))
+ str = rb_str_new(NULL, 0);
+
+#ifdef HAVE_ERR_GET_ERROR_ALL
+ e = ERR_peek_last_error_all(NULL, NULL, NULL, &data, &flags);
+#else
+ e = ERR_peek_last_error_line_data(NULL, NULL, &data, &flags);
+#endif
+ if (e) {
+ const char *msg = ERR_reason_error_string(e);
+
+ if (RSTRING_LEN(str)) rb_str_cat_cstr(str, ": ");
+ rb_str_cat_cstr(str, msg ? msg : "(null)");
+ if (flags & ERR_TXT_STRING && data)
+ rb_str_catf(str, " (%s)", data);
+ collect_errors_into(errors);
+ }
+
+ VALUE obj = rb_exc_new_str(exc, str);
+ rb_ivar_set(obj, id_i_errors, errors);
+ return obj;
+}
+
void
ossl_raise(VALUE exc, const char *fmt, ...)
{
va_list args;
- char buf[BUFSIZ];
- const char *msg;
- long e;
- int len = 0;
+ VALUE err;
-#ifdef HAVE_ERR_PEEK_LAST_ERROR
- e = ERR_peek_last_error();
-#else
- e = ERR_peek_error();
-#endif
if (fmt) {
- va_start(args, fmt);
- len = vsnprintf(buf, BUFSIZ, fmt, args);
- va_end(args);
+ va_start(args, fmt);
+ err = rb_vsprintf(fmt, args);
+ va_end(args);
}
- if (len < BUFSIZ && e) {
- if (dOSSL == Qtrue) /* FULL INFO */
- msg = ERR_error_string(e, NULL);
- else
- msg = ERR_reason_error_string(e);
- fmt = len ? ": %s" : "%s";
- len += snprintf(buf+len, BUFSIZ-len, fmt, msg);
+ else {
+ err = Qnil;
}
- if (dOSSL == Qtrue){ /* show all errors on the stack */
- while ((e = ERR_get_error()) != 0){
- rb_warn("error on stack: %s", ERR_error_string(e, NULL));
- }
+
+ rb_exc_raise(ossl_make_error(exc, err));
+}
+
+static void
+collect_errors_into(VALUE ary)
+{
+ if (dOSSL == Qtrue || !NIL_P(ary)) {
+ unsigned long e;
+ const char *file, *data, *func, *lib, *reason;
+ int line, flags;
+
+#ifdef HAVE_ERR_GET_ERROR_ALL
+ while ((e = ERR_get_error_all(&file, &line, &func, &data, &flags))) {
+#else
+ while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) {
+ func = ERR_func_error_string(e);
+#endif
+ lib = ERR_lib_error_string(e);
+ reason = ERR_reason_error_string(e);
+
+ VALUE str = rb_sprintf("error:%08lX:%s:%s:%s", e, lib ? lib : "",
+ func ? func : "", reason ? reason : "");
+ if (flags & ERR_TXT_STRING) {
+ if (!data)
+ data = "(null)";
+ rb_str_catf(str, " (%s)", data);
+ }
+
+ if (dOSSL == Qtrue)
+ rb_warn("error on stack: %"PRIsVALUE, str);
+ if (!NIL_P(ary))
+ rb_ary_push(ary, str);
+ }
+ }
+ else {
+ ERR_clear_error();
}
- ERR_clear_error();
+}
- if(len > BUFSIZ) len = strlen(buf);
- rb_exc_raise(rb_exc_new(exc, buf, len));
+void
+ossl_clear_error(void)
+{
+ collect_errors_into(Qnil);
}
-VALUE
-ossl_get_errors()
+/*
+ * call-seq:
+ * ossl_error.detailed_message(**) -> string
+ *
+ * Returns the exception message decorated with the captured \OpenSSL error
+ * queue entries.
+ */
+static VALUE
+osslerror_detailed_message(int argc, VALUE *argv, VALUE self)
+{
+ VALUE str;
+#ifdef HAVE_RB_CALL_SUPER_KW
+ // Ruby >= 3.2
+ if (RTEST(rb_funcall(rb_eException, rb_intern("method_defined?"), 1,
+ ID2SYM(rb_intern("detailed_message")))))
+ str = rb_call_super_kw(argc, argv, RB_PASS_CALLED_KEYWORDS);
+ else
+#endif
+ str = rb_funcall(self, rb_intern("message"), 0);
+ VALUE errors = rb_attr_get(self, id_i_errors);
+
+ // OpenSSLError was not created by ossl_make_error()
+ if (!RB_TYPE_P(errors, T_ARRAY))
+ return str;
+
+ str = rb_str_resurrect(str);
+ rb_str_catf(str, "\nOpenSSL error queue reported %ld errors:",
+ RARRAY_LEN(errors));
+ for (long i = 0; i < RARRAY_LEN(errors); i++) {
+ VALUE err = RARRAY_AREF(errors, i);
+ rb_str_catf(str, "\n%"PRIsVALUE, err);
+ }
+ return str;
+}
+
+/*
+ * call-seq:
+ * OpenSSL.errors -> [String...]
+ *
+ * Returns any remaining errors held in the \OpenSSL thread-local error queue
+ * and clears the queue. This should normally return an empty array.
+ *
+ * This is intended for debugging Ruby/OpenSSL. If you see any errors here,
+ * it likely indicates a bug in the extension. Please file an issue at
+ * https://github.com/ruby/openssl.
+ *
+ * For debugging your program, OpenSSL.debug= may be useful.
+ */
+static VALUE
+ossl_get_errors(VALUE _)
{
VALUE ary;
long e;
@@ -329,52 +420,594 @@ ossl_get_errors()
*/
VALUE dOSSL;
-#if !defined(HAVE_VA_ARGS_MACRO)
-void
-ossl_debug(const char *fmt, ...)
+/*
+ * call-seq:
+ * OpenSSL.debug -> true | false
+ *
+ * Returns whether Ruby/OpenSSL's debug mode is currently enabled.
+ */
+static VALUE
+ossl_debug_get(VALUE self)
{
- va_list args;
-
- if (dOSSL == Qtrue) {
- fprintf(stderr, "OSSL_DEBUG: ");
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- fprintf(stderr, " [CONTEXT N/A]\n");
- }
+ return dOSSL;
}
+
+/*
+ * call-seq:
+ * OpenSSL.debug = boolean
+ *
+ * Turns on or off debug mode. With debug mode, all errors added to the \OpenSSL
+ * error queue will be printed to stderr.
+ */
+static VALUE
+ossl_debug_set(VALUE self, VALUE val)
+{
+ dOSSL = RTEST(val) ? Qtrue : Qfalse;
+
+ return val;
+}
+
+/*
+ * call-seq:
+ * OpenSSL.fips_mode -> true | false
+ *
+ * Returns whether the FIPS mode is currently enabled.
+ */
+static VALUE
+ossl_fips_mode_get(VALUE self)
+{
+
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+ VALUE enabled;
+ enabled = EVP_default_properties_is_fips_enabled(NULL) ? Qtrue : Qfalse;
+ return enabled;
+#elif defined(OPENSSL_FIPS) || defined(OPENSSL_IS_AWSLC)
+ VALUE enabled;
+ enabled = FIPS_mode() ? Qtrue : Qfalse;
+ return enabled;
+#else
+ return Qfalse;
#endif
+}
+/*
+ * call-seq:
+ * OpenSSL.fips_mode = boolean
+ *
+ * Turns FIPS mode on or off. Turning on FIPS mode will obviously only have an
+ * effect for FIPS-capable installations of the \OpenSSL library. Trying to do
+ * so otherwise will result in an error.
+ *
+ * === Examples
+ * OpenSSL.fips_mode = true # turn FIPS mode on
+ * OpenSSL.fips_mode = false # and off again
+ */
static VALUE
-ossl_debug_get(VALUE self)
+ossl_fips_mode_set(VALUE self, VALUE enabled)
{
- return dOSSL;
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+ if (RTEST(enabled)) {
+ if (!EVP_default_properties_enable_fips(NULL, 1)) {
+ ossl_raise(eOSSLError, "Turning on FIPS mode failed");
+ }
+ } else {
+ if (!EVP_default_properties_enable_fips(NULL, 0)) {
+ ossl_raise(eOSSLError, "Turning off FIPS mode failed");
+ }
+ }
+ return enabled;
+#elif defined(OPENSSL_FIPS) || defined(OPENSSL_IS_AWSLC)
+ if (RTEST(enabled)) {
+ int mode = FIPS_mode();
+ if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */
+ ossl_raise(eOSSLError, "Turning on FIPS mode failed");
+ } else {
+ if(!FIPS_mode_set(0)) /* turning off twice is OK */
+ ossl_raise(eOSSLError, "Turning off FIPS mode failed");
+ }
+ return enabled;
+#else
+ if (RTEST(enabled))
+ ossl_raise(eOSSLError, "This version of OpenSSL does not support FIPS mode");
+ return enabled;
+#endif
}
+/*
+ * call-seq:
+ * OpenSSL.fixed_length_secure_compare(string, string) -> true or false
+ *
+ * Constant time memory comparison for fixed length strings, such as results
+ * of \HMAC calculations.
+ *
+ * Returns +true+ if the strings are identical, +false+ if they are of the same
+ * length but not identical. If the length is different, ArgumentError is
+ * raised.
+ */
static VALUE
-ossl_debug_set(VALUE self, VALUE val)
+ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
{
- VALUE old = dOSSL;
- dOSSL = val;
-
- if (old != dOSSL) {
- if (dOSSL == Qtrue) {
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
- fprintf(stderr, "OSSL_DEBUG: IS NOW ON!\n");
- } else if (old == Qtrue) {
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);
- fprintf(stderr, "OSSL_DEBUG: IS NOW OFF!\n");
- }
+ const unsigned char *p1;
+ const unsigned char *p2;
+ long len1;
+ long len2;
+
+ StringValue(str1);
+ StringValue(str2);
+
+ p1 = (const unsigned char *)RSTRING_PTR(str1);
+ p2 = (const unsigned char *)RSTRING_PTR(str2);
+ len1 = RSTRING_LEN(str1);
+ len2 = RSTRING_LEN(str2);
+
+ if (len1 != len2) {
+ ossl_raise(rb_eArgError, "inputs must be of equal length");
+ }
+
+ switch (CRYPTO_memcmp(p1, p2, len1)) {
+ case 0: return Qtrue;
+ default: return Qfalse;
}
- return val;
}
/*
- * OSSL library init
+ * OpenSSL provides \SSL, TLS and general purpose cryptography. It wraps the
+ * OpenSSL[https://www.openssl.org/] library.
+ *
+ * = Examples
+ *
+ * All examples assume you have loaded OpenSSL with:
+ *
+ * require 'openssl'
+ *
+ * These examples build atop each other. For example the key created in the
+ * next is used in throughout these examples.
+ *
+ * == Keys
+ *
+ * === Creating a Key
+ *
+ * This example creates a 2048 bit RSA keypair and writes it to the current
+ * directory.
+ *
+ * key = OpenSSL::PKey::RSA.new 2048
+ *
+ * File.write 'private_key.pem', key.private_to_pem
+ * File.write 'public_key.pem', key.public_to_pem
+ *
+ * === Exporting a Key
+ *
+ * Keys saved to disk without encryption are not secure as anyone who gets
+ * ahold of the key may use it unless it is encrypted. In order to securely
+ * export a key you may export it with a password.
+ *
+ * cipher = OpenSSL::Cipher.new 'aes-256-cbc'
+ * password = 'my secure password goes here'
+ *
+ * key_secure = key.private_to_pem cipher, password
+ *
+ * File.write 'private.secure.pem', key_secure
+ *
+ * OpenSSL::Cipher.ciphers returns a list of available ciphers.
+ *
+ * === Loading a Key
+ *
+ * A key can also be loaded from a file.
+ *
+ * key2 = OpenSSL::PKey.read File.read 'private_key.pem'
+ * key2.public? # => true
+ * key2.private? # => true
+ *
+ * or
+ *
+ * key3 = OpenSSL::PKey.read File.read 'public_key.pem'
+ * key3.public? # => true
+ * key3.private? # => false
+ *
+ * === Loading an Encrypted Key
+ *
+ * \OpenSSL will prompt you for your password when loading an encrypted key.
+ * If you will not be able to type in the password you may provide it when
+ * loading the key:
+ *
+ * key4_pem = File.read 'private.secure.pem'
+ * password = 'my secure password goes here'
+ * key4 = OpenSSL::PKey.read key4_pem, password
+ *
+ * == RSA Encryption
+ *
+ * RSA provides encryption and decryption using the public and private keys.
+ * You can use a variety of padding methods depending upon the intended use of
+ * encrypted data.
+ *
+ * === Encryption & Decryption
+ *
+ * Asymmetric public/private key encryption is slow and victim to attack in
+ * cases where it is used without padding or directly to encrypt larger chunks
+ * of data. Typical use cases for RSA encryption involve "wrapping" a symmetric
+ * key with the public key of the recipient who would "unwrap" that symmetric
+ * key again using their private key.
+ * The following illustrates a simplified example of such a key transport
+ * scheme. It shouldn't be used in practice, though, standardized protocols
+ * should always be preferred.
+ *
+ * wrapped_key = key.public_encrypt key
+ *
+ * A symmetric key encrypted with the public key can only be decrypted with
+ * the corresponding private key of the recipient.
+ *
+ * original_key = key.private_decrypt wrapped_key
+ *
+ * By default PKCS#1 padding will be used, but it is also possible to use
+ * other forms of padding, see PKey::RSA for further details.
+ *
+ * === Signatures
+ *
+ * Using "private_encrypt" to encrypt some data with the private key is
+ * equivalent to applying a digital signature to the data. A verifying
+ * party may validate the signature by comparing the result of decrypting
+ * the signature with "public_decrypt" to the original data. However,
+ * OpenSSL::PKey already has methods "sign" and "verify" that handle
+ * digital signatures in a standardized way - "private_encrypt" and
+ * "public_decrypt" shouldn't be used in practice.
+ *
+ * To sign a document, a cryptographically secure hash of the document is
+ * computed first, which is then signed using the private key.
+ *
+ * signature = key.sign 'SHA256', document
+ *
+ * To validate the signature, again a hash of the document is computed and
+ * the signature is decrypted using the public key. The result is then
+ * compared to the hash just computed, if they are equal the signature was
+ * valid.
+ *
+ * if key.verify 'SHA256', signature, document
+ * puts 'Valid'
+ * else
+ * puts 'Invalid'
+ * end
+ *
+ * == PBKDF2 Password-based Encryption
+ *
+ * If supported by the underlying \OpenSSL version used, Password-based
+ * Encryption should use the features of PKCS5. If not supported or if
+ * required by legacy applications, the older, less secure methods specified
+ * in RFC 2898 are also supported (see below).
+ *
+ * PKCS5 supports PBKDF2 as it was specified in PKCS#5
+ * v2.0[http://www.rsa.com/rsalabs/node.asp?id=2127]. It still uses a
+ * password, a salt, and additionally a number of iterations that will
+ * slow the key derivation process down. The slower this is, the more work
+ * it requires being able to brute-force the resulting key.
+ *
+ * === Encryption
+ *
+ * The strategy is to first instantiate a Cipher for encryption, and
+ * then to generate a random IV plus a key derived from the password
+ * using PBKDF2. PKCS #5 v2.0 recommends at least 8 bytes for the salt,
+ * the number of iterations largely depends on the hardware being used.
+ *
+ * cipher = OpenSSL::Cipher.new 'aes-256-cbc'
+ * cipher.encrypt
+ * iv = cipher.random_iv
+ *
+ * pwd = 'some hopefully not to easily guessable password'
+ * salt = OpenSSL::Random.random_bytes 16
+ * iter = 20000
+ * key_len = cipher.key_len
+ * digest = OpenSSL::Digest.new('SHA256')
+ *
+ * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
+ * cipher.key = key
+ *
+ * Now encrypt the data:
+ *
+ * encrypted = cipher.update document
+ * encrypted << cipher.final
+ *
+ * === Decryption
+ *
+ * Use the same steps as before to derive the symmetric AES key, this time
+ * setting the Cipher up for decryption.
+ *
+ * cipher = OpenSSL::Cipher.new 'aes-256-cbc'
+ * cipher.decrypt
+ * cipher.iv = iv # the one generated with #random_iv
+ *
+ * pwd = 'some hopefully not to easily guessable password'
+ * salt = ... # the one generated above
+ * iter = 20000
+ * key_len = cipher.key_len
+ * digest = OpenSSL::Digest.new('SHA256')
+ *
+ * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
+ * cipher.key = key
+ *
+ * Now decrypt the data:
+ *
+ * decrypted = cipher.update encrypted
+ * decrypted << cipher.final
+ *
+ * == \X509 Certificates
+ *
+ * === Creating a Certificate
+ *
+ * This example creates a self-signed certificate using an RSA key and a SHA1
+ * signature.
+ *
+ * key = OpenSSL::PKey::RSA.new 2048
+ * name = OpenSSL::X509::Name.parse '/CN=nobody/DC=example'
+ *
+ * cert = OpenSSL::X509::Certificate.new
+ * cert.version = 2
+ * cert.serial = 0
+ * cert.not_before = Time.now
+ * cert.not_after = Time.now + 3600
+ *
+ * cert.public_key = key.public_key
+ * cert.subject = name
+ *
+ * === Certificate Extensions
+ *
+ * You can add extensions to the certificate with
+ * OpenSSL::SSL::ExtensionFactory to indicate the purpose of the certificate.
+ *
+ * extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert
+ *
+ * cert.add_extension \
+ * extension_factory.create_extension('basicConstraints', 'CA:FALSE', true)
+ *
+ * cert.add_extension \
+ * extension_factory.create_extension(
+ * 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
+ *
+ * cert.add_extension \
+ * extension_factory.create_extension('subjectKeyIdentifier', 'hash')
+ *
+ * The list of supported extensions (and in some cases their possible values)
+ * can be derived from the "objects.h" file in the \OpenSSL source code.
+ *
+ * === Signing a Certificate
+ *
+ * To sign a certificate set the issuer and use OpenSSL::X509::Certificate#sign
+ * with a digest algorithm. This creates a self-signed cert because we're using
+ * the same name and key to sign the certificate as was used to create the
+ * certificate.
+ *
+ * cert.issuer = name
+ * cert.sign key, OpenSSL::Digest.new('SHA1')
+ *
+ * open 'certificate.pem', 'w' do |io| io.write cert.to_pem end
+ *
+ * === Loading a Certificate
+ *
+ * Like a key, a cert can also be loaded from a file.
+ *
+ * cert2 = OpenSSL::X509::Certificate.new File.read 'certificate.pem'
+ *
+ * === Verifying a Certificate
+ *
+ * Certificate#verify will return true when a certificate was signed with the
+ * given public key.
+ *
+ * raise 'certificate can not be verified' unless cert2.verify key
+ *
+ * == Certificate Authority
+ *
+ * A certificate authority (CA) is a trusted third party that allows you to
+ * verify the ownership of unknown certificates. The CA issues key signatures
+ * that indicate it trusts the user of that key. A user encountering the key
+ * can verify the signature by using the CA's public key.
+ *
+ * === CA Key
+ *
+ * CA keys are valuable, so we encrypt and save it to disk and make sure it is
+ * not readable by other users.
+ *
+ * ca_key = OpenSSL::PKey::RSA.new 2048
+ * password = 'my secure password goes here'
+ *
+ * cipher = 'aes-256-cbc'
+ *
+ * open 'ca_key.pem', 'w', 0400 do |io|
+ * io.write ca_key.private_to_pem(cipher, password)
+ * end
+ *
+ * === CA Certificate
+ *
+ * A CA certificate is created the same way we created a certificate above, but
+ * with different extensions.
+ *
+ * ca_name = OpenSSL::X509::Name.parse '/CN=ca/DC=example'
+ *
+ * ca_cert = OpenSSL::X509::Certificate.new
+ * ca_cert.serial = 0
+ * ca_cert.version = 2
+ * ca_cert.not_before = Time.now
+ * ca_cert.not_after = Time.now + 86400
+ *
+ * ca_cert.public_key = ca_key.public_key
+ * ca_cert.subject = ca_name
+ * ca_cert.issuer = ca_name
+ *
+ * extension_factory = OpenSSL::X509::ExtensionFactory.new
+ * extension_factory.subject_certificate = ca_cert
+ * extension_factory.issuer_certificate = ca_cert
+ *
+ * ca_cert.add_extension \
+ * extension_factory.create_extension('subjectKeyIdentifier', 'hash')
+ *
+ * This extension indicates the CA's key may be used as a CA.
+ *
+ * ca_cert.add_extension \
+ * extension_factory.create_extension('basicConstraints', 'CA:TRUE', true)
+ *
+ * This extension indicates the CA's key may be used to verify signatures on
+ * both certificates and certificate revocations.
+ *
+ * ca_cert.add_extension \
+ * extension_factory.create_extension(
+ * 'keyUsage', 'cRLSign,keyCertSign', true)
+ *
+ * Root CA certificates are self-signed.
+ *
+ * ca_cert.sign ca_key, OpenSSL::Digest.new('SHA1')
+ *
+ * The CA certificate is saved to disk so it may be distributed to all the
+ * users of the keys this CA will sign.
+ *
+ * open 'ca_cert.pem', 'w' do |io|
+ * io.write ca_cert.to_pem
+ * end
+ *
+ * === Certificate Signing Request
+ *
+ * The CA signs keys through a Certificate Signing Request (CSR). The CSR
+ * contains the information necessary to identify the key.
+ *
+ * csr = OpenSSL::X509::Request.new
+ * csr.version = 0
+ * csr.subject = name
+ * csr.public_key = key.public_key
+ * csr.sign key, OpenSSL::Digest.new('SHA1')
+ *
+ * A CSR is saved to disk and sent to the CA for signing.
+ *
+ * open 'csr.pem', 'w' do |io|
+ * io.write csr.to_pem
+ * end
+ *
+ * === Creating a Certificate from a CSR
+ *
+ * Upon receiving a CSR the CA will verify it before signing it. A minimal
+ * verification would be to check the CSR's signature.
+ *
+ * csr = OpenSSL::X509::Request.new File.read 'csr.pem'
+ *
+ * raise 'CSR can not be verified' unless csr.verify csr.public_key
+ *
+ * After verification a certificate is created, marked for various usages,
+ * signed with the CA key and returned to the requester.
+ *
+ * csr_cert = OpenSSL::X509::Certificate.new
+ * csr_cert.serial = 0
+ * csr_cert.version = 2
+ * csr_cert.not_before = Time.now
+ * csr_cert.not_after = Time.now + 600
+ *
+ * csr_cert.subject = csr.subject
+ * csr_cert.public_key = csr.public_key
+ * csr_cert.issuer = ca_cert.subject
+ *
+ * extension_factory = OpenSSL::X509::ExtensionFactory.new
+ * extension_factory.subject_certificate = csr_cert
+ * extension_factory.issuer_certificate = ca_cert
+ *
+ * csr_cert.add_extension \
+ * extension_factory.create_extension('basicConstraints', 'CA:FALSE')
+ *
+ * csr_cert.add_extension \
+ * extension_factory.create_extension(
+ * 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
+ *
+ * csr_cert.add_extension \
+ * extension_factory.create_extension('subjectKeyIdentifier', 'hash')
+ *
+ * csr_cert.sign ca_key, OpenSSL::Digest.new('SHA1')
+ *
+ * open 'csr_cert.pem', 'w' do |io|
+ * io.write csr_cert.to_pem
+ * end
+ *
+ * == \SSL and TLS Connections
+ *
+ * Using our created key and certificate we can create an \SSL or TLS
+ * connection. An OpenSSL::SSL::SSLContext is used to set up an \SSL session.
+ *
+ * context = OpenSSL::SSL::SSLContext.new
+ *
+ * === \SSL Server
+ *
+ * An \SSL server requires the certificate and private key to communicate
+ * securely with its clients:
+ *
+ * context.cert = cert
+ * context.key = key
+ *
+ * Then create an OpenSSL::SSL::SSLServer with a TCP server socket and the
+ * context. Use the SSLServer like an ordinary TCP server.
+ *
+ * require 'socket'
+ *
+ * tcp_server = TCPServer.new 5000
+ * ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context
+ *
+ * loop do
+ * ssl_connection = ssl_server.accept
+ *
+ * data = ssl_connection.gets
+ *
+ * response = "I got #{data.dump}"
+ * puts response
+ *
+ * ssl_connection.puts "I got #{data.dump}"
+ * ssl_connection.close
+ * end
+ *
+ * === \SSL client
+ *
+ * An \SSL client is created with a TCP socket and the context.
+ * OpenSSL::SSL::SSLSocket#connect must be called to initiate the \SSL handshake
+ * and start encryption. A key and certificate are not required for the client
+ * socket.
+ *
+ * Note that OpenSSL::SSL::SSLSocket#close doesn't close the underlying socket
+ * by default. Set OpenSSL::SSL::SSLSocket#sync_close to true if you want.
+ *
+ * require 'socket'
+ *
+ * tcp_socket = TCPSocket.new 'localhost', 5000
+ * ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context
+ * ssl_client.sync_close = true
+ * ssl_client.connect
+ *
+ * ssl_client.puts "hello server!"
+ * puts ssl_client.gets
+ *
+ * ssl_client.close # shutdown the TLS connection and close tcp_socket
+ *
+ * === Peer Verification
+ *
+ * An unverified \SSL connection does not provide much security. For enhanced
+ * security the client or server can verify the certificate of its peer.
+ *
+ * The client can be modified to verify the server's certificate against the
+ * certificate authority's certificate:
+ *
+ * context.ca_file = 'ca_cert.pem'
+ * context.verify_mode = OpenSSL::SSL::VERIFY_PEER
+ *
+ * require 'socket'
+ *
+ * tcp_socket = TCPSocket.new 'localhost', 5000
+ * ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context
+ * ssl_client.connect
+ *
+ * ssl_client.puts "hello server!"
+ * puts ssl_client.gets
+ *
+ * If the server certificate is invalid or <tt>context.ca_file</tt> is not set
+ * when verifying peers an OpenSSL::SSL::SSLError will be raised.
+ *
*/
void
-Init_openssl()
+Init_openssl(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
+#undef rb_intern
/*
* Init timezone info
*/
@@ -385,55 +1018,116 @@ Init_openssl()
/*
* Init all digests, ciphers
*/
- /* CRYPTO_malloc_init(); */
- /* ENGINE_load_builtin_engines(); */
- OpenSSL_add_ssl_algorithms();
- OpenSSL_add_all_algorithms();
- ERR_load_crypto_strings();
- SSL_load_error_strings();
+ if (!OPENSSL_init_ssl(0, NULL))
+ rb_raise(rb_eRuntimeError, "OPENSSL_init_ssl");
/*
- * FIXME:
- * On unload do:
+ * Init main module
*/
-#if 0
- CONF_modules_unload(1);
- destroy_ui_method();
- EVP_cleanup();
- ENGINE_cleanup();
- CRYPTO_cleanup_all_ex_data();
- ERR_remove_state(0);
- ERR_free_strings();
-#endif
+ rb_global_variable(&mOSSL);
+ mOSSL = rb_define_module("OpenSSL");
+ rb_define_singleton_method(mOSSL, "fixed_length_secure_compare", ossl_crypto_fixed_length_secure_compare, 2);
/*
- * Init main module
+ * \OpenSSL library version string used to compile the Ruby/OpenSSL
+ * extension. This may differ from the version used at runtime.
*/
- mOSSL = rb_define_module("OpenSSL");
+ rb_define_const(mOSSL, "OPENSSL_VERSION",
+ rb_obj_freeze(rb_str_new_cstr(OPENSSL_VERSION_TEXT)));
+
+ /*
+ * \OpenSSL library version string currently used at runtime.
+ */
+ rb_define_const(
+ mOSSL,
+ "OPENSSL_LIBRARY_VERSION",
+ rb_obj_freeze(rb_str_new_cstr(OpenSSL_version(OPENSSL_VERSION)))
+ );
/*
- * Constants
+ * \OpenSSL library version number used to compile the Ruby/OpenSSL
+ * extension. This may differ from the version used at runtime.
+ *
+ * The version number is encoded into a single integer value. The number
+ * follows the format:
+ *
+ * [\OpenSSL 3.0.0 or later]
+ * <tt>0xMNN00PP0</tt> (major minor 00 patch 0)
+ * [\OpenSSL 1.1.1 or earlier]
+ * <tt>0xMNNFFPPS</tt> (major minor fix patch status)
+ * [LibreSSL]
+ * <tt>0x20000000</tt> (a fixed value)
+ *
+ * See also the man page OPENSSL_VERSION_NUMBER(3).
*/
- rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION));
- rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER));
+#if defined(LIBRESSL_VERSION_NUMBER)
/*
- * Generic error,
- * common for all classes under OpenSSL module
+ * LibreSSL library version number used to compile the Ruby/OpenSSL
+ * extension. This may differ from the version used at runtime.
+ *
+ * This constant is only defined if the extension was compiled against
+ * LibreSSL. The number follows the format:
+ * <tt>0xMNNFF00f</tt> (major minor fix 00 status).
+ *
+ * See also the man page LIBRESSL_VERSION_NUMBER(3).
*/
- eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError);
+ rb_define_const(mOSSL, "LIBRESSL_VERSION_NUMBER", INT2NUM(LIBRESSL_VERSION_NUMBER));
+#endif
+
+ /*
+ * Boolean indicating whether the \OpenSSL library is FIPS-capable or not.
+ * Always <tt>true</tt> for \OpenSSL 3.0 and later.
+ *
+ * This is obsolete and will be removed in the future.
+ * See also OpenSSL.fips_mode.
+ */
+ rb_define_const(mOSSL, "OPENSSL_FIPS",
+/* OpenSSL 3 is FIPS-capable even when it is installed without fips option */
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+ Qtrue
+#elif defined(OPENSSL_FIPS)
+ Qtrue
+#elif defined(OPENSSL_IS_AWSLC) // AWS-LC FIPS can only be enabled during compile time.
+ FIPS_mode() ? Qtrue : Qfalse
+#else
+ Qfalse
+#endif
+ );
+ rb_define_module_function(mOSSL, "fips_mode", ossl_fips_mode_get, 0);
+ rb_define_module_function(mOSSL, "fips_mode=", ossl_fips_mode_set, 1);
+
+ rb_global_variable(&eOSSLError);
+ /*
+ * Generic error class for OpenSSL. All error classes in this library
+ * inherit from this class.
+ *
+ * This class indicates that an error was reported by the underlying
+ * \OpenSSL library.
+ */
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
/*
- * Verify callback Proc index for ext-data
+ * \OpenSSL error queue entries captured at the time the exception was
+ * raised. The same information is printed to stderr if OpenSSL.debug is
+ * set to +true+.
+ *
+ * This is an array of zero or more strings, ordered from the oldest to the
+ * newest. The format of the strings is not stable and may vary across
+ * versions of \OpenSSL or versions of this Ruby extension.
+ *
+ * See also the man page ERR_get_error(3).
*/
- ossl_verify_cb_idx =
- X509_STORE_CTX_get_ex_new_index(0, "ossl_verify_cb_idx", 0, 0, 0);
+ rb_attr(eOSSLError, rb_intern_const("errors"), 1, 0, 0);
+ rb_define_method(eOSSLError, "detailed_message", osslerror_detailed_message, -1);
/*
* Init debug core
*/
dOSSL = Qfalse;
+ rb_global_variable(&dOSSL);
+
rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0);
rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1);
rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0);
@@ -442,35 +1136,27 @@ Init_openssl()
* Get ID of to_der
*/
ossl_s_to_der = rb_intern("to_der");
+ id_i_errors = rb_intern("@errors");
/*
* Init components
*/
+ Init_ossl_asn1();
Init_ossl_bn();
Init_ossl_cipher();
Init_ossl_config();
Init_ossl_digest();
+ Init_ossl_engine();
Init_ossl_hmac();
+ Init_ossl_kdf();
Init_ossl_ns_spki();
+ Init_ossl_ocsp();
Init_ossl_pkcs12();
Init_ossl_pkcs7();
Init_ossl_pkey();
+ Init_ossl_provider();
Init_ossl_rand();
Init_ossl_ssl();
+ Init_ossl_ts();
Init_ossl_x509();
- Init_ossl_ocsp();
- Init_ossl_engine();
- Init_ossl_asn1();
}
-
-#if defined(OSSL_DEBUG)
-/*
- * Check if all symbols are OK with 'make LDSHARED=gcc all'
- */
-int
-main(int argc, char *argv[], char *env[])
-{
- return 0;
-}
-#endif /* OSSL_DEBUG */
-
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index c0325229c1..0b479a7200 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -1,71 +1,81 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_H_)
#define _OSSL_H_
#include RUBY_EXTCONF_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/*
-* OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it!
-*/
-#if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/
-# undef RFILE
-#endif
+#include <assert.h>
#include <ruby.h>
-#include <rubyio.h>
-
-/*
- * Check the OpenSSL version
- * The only supported are:
- * OpenSSL >= 0.9.7
- */
-#include <openssl/opensslv.h>
-
-#ifdef HAVE_ASSERT_H
-# include <assert.h>
+#include <errno.h>
+#include <ruby/io.h>
+#include <ruby/thread.h>
+#ifdef HAVE_RUBY_RACTOR_H
+#include <ruby/ractor.h>
#else
-# define assert(condition)
+#define RUBY_TYPED_FROZEN_SHAREABLE 0
#endif
-#if defined(_WIN32)
-# define OpenFile WINAPI_OpenFile
-# define OSSL_NO_CONF_API 1
-#endif
-#include <errno.h>
+#include <openssl/opensslv.h>
+
#include <openssl/err.h>
-#include <openssl/asn1_mac.h>
+#include <openssl/asn1.h>
#include <openssl/x509v3.h>
#include <openssl/ssl.h>
#include <openssl/pkcs12.h>
#include <openssl/pkcs7.h>
-#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/conf.h>
-#include <openssl/conf_api.h>
-#undef X509_NAME
-#undef PKCS7_SIGNER_INFO
-#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ST_ENGINE)
-# define OSSL_ENGINE_ENABLED
-# include <openssl/engine.h>
+#ifndef OPENSSL_NO_TS
+ #include <openssl/ts.h>
#endif
-#if defined(HAVE_OPENSSL_OCSP_H)
-# define OSSL_OCSP_ENABLED
+#include <openssl/crypto.h>
+#if !defined(OPENSSL_NO_OCSP)
# include <openssl/ocsp.h>
#endif
-#if defined(_WIN32)
-# undef OpenFile
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/evp.h>
+#include <openssl/dh.h>
+#include "openssl_missing.h"
+
+#ifndef LIBRESSL_VERSION_NUMBER
+# define OSSL_IS_LIBRESSL 0
+# define OSSL_OPENSSL_PREREQ(maj, min, pat) \
+ (OPENSSL_VERSION_NUMBER >= ((maj << 28) | (min << 20) | (pat << 12)))
+# define OSSL_LIBRESSL_PREREQ(maj, min, pat) 0
+#else
+# define OSSL_IS_LIBRESSL 1
+# define OSSL_OPENSSL_PREREQ(maj, min, pat) 0
+# define OSSL_LIBRESSL_PREREQ(maj, min, pat) \
+ (LIBRESSL_VERSION_NUMBER >= ((maj << 28) | (min << 20) | (pat << 12)))
+#endif
+
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+# define OSSL_3_const const
+#else
+# define OSSL_3_const /* const */
+#endif
+
+#if !defined(OPENSSL_NO_ENGINE) && !OSSL_OPENSSL_PREREQ(3, 0, 0)
+# define OSSL_USE_ENGINE
+#endif
+
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+# define OSSL_USE_PROVIDER
+# include <openssl/provider.h>
+#endif
+
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+# define OSSL_HAVE_IMMUTABLE_PKEY
#endif
/*
@@ -82,77 +92,79 @@ extern VALUE eOSSLError;
* CheckTypes
*/
#define OSSL_Check_Kind(obj, klass) do {\
- if (!rb_obj_is_kind_of(obj, klass)) {\
- ossl_raise(rb_eTypeError, "wrong argument (%s)! (Expected kind of %s)",\
- rb_obj_classname(obj), rb_class2name(klass));\
- }\
-} while (0)
-
-#define OSSL_Check_Instance(obj, klass) do {\
- if (!rb_obj_is_instance_of(obj, klass)) {\
- ossl_raise(rb_eTypeError, "wrong argument (%s)! (Expected instance of %s)",\
- rb_obj_classname(obj), rb_class2name(klass));\
- }\
-} while (0)
-
-#define OSSL_Check_Same_Class(obj1, obj2) do {\
- if (!rb_obj_is_instance_of(obj1, rb_obj_class(obj2))) {\
- ossl_raise(rb_eTypeError, "wrong argument type");\
- }\
+ if (!rb_obj_is_kind_of((obj), (klass))) {\
+ ossl_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected kind of %"PRIsVALUE")",\
+ rb_obj_class(obj), (klass));\
+ }\
} while (0)
/*
- * String to HEXString conversion
+ * Type conversions
*/
-int string2hex(char *, int, char **, int *);
+#if !defined(NUM2UINT64T) /* in case Ruby starts to provide */
+# if SIZEOF_LONG == 8
+# define NUM2UINT64T(x) ((uint64_t)NUM2ULONG(x))
+# elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
+# define NUM2UINT64T(x) ((uint64_t)NUM2ULL(x))
+# else
+# error "unknown platform; no 64-bit width integer"
+# endif
+#endif
/*
* Data Conversion
*/
-STACK_OF(X509) *ossl_x509_ary2sk0(VALUE);
STACK_OF(X509) *ossl_x509_ary2sk(VALUE);
STACK_OF(X509) *ossl_protect_x509_ary2sk(VALUE,int*);
-VALUE ossl_x509_sk2ary(STACK_OF(X509) *certs);
-VALUE ossl_x509crl_sk2ary(STACK_OF(X509_CRL) *crl);
+VALUE ossl_x509_sk2ary(const STACK_OF(X509) *certs);
+VALUE ossl_x509crl_sk2ary(const STACK_OF(X509_CRL) *crl);
+VALUE ossl_x509name_sk2ary(const STACK_OF(X509_NAME) *names);
VALUE ossl_buf2str(char *buf, int len);
+VALUE ossl_str_new(const char *, long, int *);
#define ossl_str_adjust(str, p) \
do{\
- int len = RSTRING(str)->len;\
- int newlen = (p) - (unsigned char*)RSTRING(str)->ptr;\
- assert(newlen <= len);\
- RSTRING(str)->len = newlen;\
- RSTRING(str)->ptr[newlen] = 0;\
+ long newlen = (long)((p) - (unsigned char*)RSTRING_PTR(str));\
+ assert(newlen <= RSTRING_LEN(str));\
+ rb_str_set_len((str), newlen);\
}while(0)
+/*
+ * Convert binary string to hex string. The caller is responsible for
+ * ensuring out has (2 * len) bytes of capacity.
+ */
+void ossl_bin2hex(const unsigned char *in, char *out, size_t len);
/*
- * our default PEM callback
+ * Our default PEM callback
*/
+/* Convert the argument to String and validate the length. Note this may raise. */
+VALUE ossl_pem_passwd_value(VALUE);
+/* Can be casted to pem_password_cb. If a password (String) is passed as the
+ * "arbitrary data" (typically the last parameter of PEM_{read,write}_
+ * functions), uses the value. If not, but a block is given, yields to it.
+ * If not either, fallbacks to PEM_def_callback() which reads from stdin. */
int ossl_pem_passwd_cb(char *, int, int, void *);
/*
- * ERRor messages
+ * Clear BIO* with this in PEM/DER fallback scenarios to avoid decoding
+ * errors piling up in OpenSSL::Errors
*/
-#define OSSL_ErrMsg() ERR_reason_error_string(ERR_get_error())
-NORETURN(void ossl_raise(VALUE, const char *, ...));
+#define OSSL_BIO_reset(bio) do { \
+ (void)BIO_reset((bio)); \
+ ossl_clear_error(); \
+} while (0)
/*
- * Verify callback
+ * ERRor messages
*/
-extern int ossl_verify_cb_idx;
-
-struct ossl_verify_cb_args {
- VALUE proc;
- VALUE preverify_ok;
- VALUE store_ctx;
-};
-
-VALUE ossl_call_verify_cb_proc(struct ossl_verify_cb_args *);
-int ossl_verify_cb(int, X509_STORE_CTX *);
+PRINTF_ARGS(NORETURN(void ossl_raise(VALUE, const char *, ...)), 2, 3);
+/* Make exception instance from str and OpenSSL error reason string. */
+VALUE ossl_make_error(VALUE exc, VALUE str);
+/* Clear OpenSSL error queue. If dOSSL is set, rb_warn() them. */
+void ossl_clear_error(void);
/*
* String to DER String
*/
-extern ID ossl_s_to_der;
VALUE ossl_to_der(VALUE);
VALUE ossl_to_der_if_possible(VALUE);
@@ -161,59 +173,37 @@ VALUE ossl_to_der_if_possible(VALUE);
*/
extern VALUE dOSSL;
-#if defined(HAVE_VA_ARGS_MACRO)
-#define OSSL_Debug(fmt, ...) do { \
- if (dOSSL == Qtrue) { \
- fprintf(stderr, "OSSL_DEBUG: "); \
- fprintf(stderr, fmt, ##__VA_ARGS__); \
- fprintf(stderr, " [%s:%d]\n", __FILE__, __LINE__); \
- } \
+#define OSSL_Debug(...) do { \
+ if (dOSSL == Qtrue) { \
+ fprintf(stderr, "OSSL_DEBUG: "); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, " [%s:%d]\n", __FILE__, __LINE__); \
+ } \
} while (0)
-#define OSSL_Warning(fmt, ...) do { \
- OSSL_Debug(fmt, ##__VA_ARGS__); \
- rb_warning(fmt, ##__VA_ARGS__); \
-} while (0)
-
-#define OSSL_Warn(fmt, ...) do { \
- OSSL_Debug(fmt, ##__VA_ARGS__); \
- rb_warn(fmt, ##__VA_ARGS__); \
-} while (0)
-#else
-void ossl_debug(const char *, ...);
-#define OSSL_Debug ossl_debug
-#define OSSL_Warning rb_warning
-#define OSSL_Warn rb_warn
-#endif
-
/*
* Include all parts
*/
-#include "openssl_missing.h"
-#include "ruby_missing.h"
#include "ossl_asn1.h"
#include "ossl_bio.h"
#include "ossl_bn.h"
#include "ossl_cipher.h"
#include "ossl_config.h"
#include "ossl_digest.h"
+#include "ossl_engine.h"
#include "ossl_hmac.h"
+#include "ossl_kdf.h"
#include "ossl_ns_spki.h"
#include "ossl_ocsp.h"
#include "ossl_pkcs12.h"
#include "ossl_pkcs7.h"
#include "ossl_pkey.h"
+#include "ossl_provider.h"
#include "ossl_rand.h"
#include "ossl_ssl.h"
-#include "ossl_version.h"
+#include "ossl_ts.h"
#include "ossl_x509.h"
-#include "ossl_engine.h"
void Init_openssl(void);
-#if defined(__cplusplus)
-}
-#endif
-
#endif /* _OSSL_H_ */
-
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index ee3d8599ad..517212b4d5 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -1,194 +1,213 @@
/*
- * $Id$
* 'OpenSSL for Ruby' team members
* Copyright (C) 2003
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#if defined(HAVE_SYS_TIME_H)
-# include <sys/time.h>
-#elif !defined(NT) && !defined(_WIN32)
-struct timeval {
- long tv_sec; /* seconds */
- long tv_usec; /* and microseconds */
-};
-#endif
+/********/
+/*
+ * ASN1 module
+ */
+#define ossl_asn1_get_value(o) rb_attr_get((o),sivVALUE)
+#define ossl_asn1_get_tag(o) rb_attr_get((o),sivTAG)
+#define ossl_asn1_get_tagging(o) rb_attr_get((o),sivTAGGING)
+#define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS)
+#define ossl_asn1_get_indefinite_length(o) rb_attr_get((o),sivINDEFINITE_LENGTH)
+
+#define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v))
+#define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v))
+#define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v))
+#define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v))
+#define ossl_asn1_set_indefinite_length(o,v) rb_ivar_set((o),sivINDEFINITE_LENGTH,(v))
+
+VALUE mASN1;
+static VALUE eASN1Error;
+
+VALUE cASN1Data;
+static VALUE cASN1Primitive;
+static VALUE cASN1Constructive;
+
+static VALUE cASN1EndOfContent;
+static VALUE cASN1Boolean; /* BOOLEAN */
+static VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
+static VALUE cASN1BitString; /* BIT STRING */
+static VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */
+static VALUE cASN1NumericString, cASN1PrintableString;
+static VALUE cASN1T61String, cASN1VideotexString;
+static VALUE cASN1IA5String, cASN1GraphicString;
+static VALUE cASN1ISO64String, cASN1GeneralString;
+static VALUE cASN1UniversalString, cASN1BMPString;
+static VALUE cASN1Null; /* NULL */
+static VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
+static VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
+static VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
+
+static VALUE sym_IMPLICIT, sym_EXPLICIT;
+static VALUE sym_UNIVERSAL, sym_APPLICATION, sym_CONTEXT_SPECIFIC, sym_PRIVATE;
+static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINDEFINITE_LENGTH, sivUNUSED_BITS;
+static ID id_each;
/*
* DATE conversion
*/
+static VALUE
+time_utc_new(VALUE args)
+{
+ return rb_funcallv(rb_cTime, rb_intern("utc"), 6, (VALUE *)args);
+}
+
+static VALUE
+time_utc_new_rescue(VALUE args, VALUE exc)
+{
+ rb_raise(eASN1Error, "invalid time");
+}
+
VALUE
-asn1time_to_time(ASN1_TIME *time)
+asn1time_to_time(const ASN1_TIME *time)
{
struct tm tm;
- VALUE argv[6];
-
- if (!time || !time->data) return Qnil;
- memset(&tm, 0, sizeof(struct tm));
-
- switch (time->type) {
- case V_ASN1_UTCTIME:
- if (sscanf(time->data, "%2d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
- &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
- ossl_raise(rb_eTypeError, "bad UTCTIME format");
- }
- if (tm.tm_year < 69) {
- tm.tm_year += 2000;
- } else {
- tm.tm_year += 1900;
- }
- break;
- case V_ASN1_GENERALIZEDTIME:
- if (sscanf(time->data, "%4d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
- &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
- ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format" );
- }
- break;
- default:
- rb_warning("unknown time format");
- return Qnil;
- }
- argv[0] = INT2NUM(tm.tm_year);
- argv[1] = INT2NUM(tm.tm_mon);
- argv[2] = INT2NUM(tm.tm_mday);
- argv[3] = INT2NUM(tm.tm_hour);
- argv[4] = INT2NUM(tm.tm_min);
- argv[5] = INT2NUM(tm.tm_sec);
-
- return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
+ if (!ASN1_TIME_to_tm(time, &tm))
+ ossl_raise(eASN1Error, "ASN1_TIME_to_tm");
+
+ VALUE args[] = {
+ INT2NUM(tm.tm_year + 1900),
+ INT2NUM(tm.tm_mon + 1),
+ INT2NUM(tm.tm_mday),
+ INT2NUM(tm.tm_hour),
+ INT2NUM(tm.tm_min),
+ INT2NUM(tm.tm_sec),
+ };
+ return rb_rescue2(time_utc_new, (VALUE)args, time_utc_new_rescue, Qnil,
+ rb_eArgError, 0);
}
-/*
- * This function is not exported in Ruby's *.h
- */
-extern struct timeval rb_time_timeval(VALUE);
+static VALUE
+asn1time_to_time_i(VALUE arg)
+{
+ return asn1time_to_time((ASN1_TIME *)arg);
+}
-time_t
-time_to_time_t(VALUE time)
+void
+ossl_time_split(VALUE time, time_t *sec, int *days)
{
- return (time_t)NUM2LONG(rb_Integer(time));
+ VALUE num = rb_Integer(time);
+
+ if (FIXNUM_P(num)) {
+ time_t t = FIX2LONG(num);
+ *sec = t % 86400;
+ *days = rb_long2int(t / 86400);
+ }
+ else {
+ *days = NUM2INT(rb_funcall(num, rb_intern("/"), 1, INT2FIX(86400)));
+ *sec = NUM2TIMET(rb_funcall(num, rb_intern("%"), 1, INT2FIX(86400)));
+ }
}
/*
* STRING conversion
*/
VALUE
-asn1str_to_str(ASN1_STRING *str)
+asn1str_to_str(const ASN1_STRING *str)
{
- return rb_str_new(str->data, str->length);
+ return rb_str_new((const char *)ASN1_STRING_get0_data(str),
+ ASN1_STRING_length(str));
}
/*
* ASN1_INTEGER conversions
- * TODO: Make a decision what's the right way to do this.
*/
-#define DO_IT_VIA_RUBY 0
VALUE
-asn1integer_to_num(ASN1_INTEGER *ai)
+asn1integer_to_num(const ASN1_INTEGER *ai)
{
BIGNUM *bn;
-#if DO_IT_VIA_RUBY
- char *txt;
-#endif
VALUE num;
if (!ai) {
- ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!");
+ ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!");
}
- if (!(bn = ASN1_INTEGER_to_BN(ai, NULL))) {
- ossl_raise(eOSSLError, NULL);
- }
-#if DO_IT_VIA_RUBY
- if (!(txt = BN_bn2dec(bn))) {
- BN_free(bn);
- ossl_raise(eOSSLError, NULL);
- }
- num = rb_cstr_to_inum(txt, 10, Qtrue);
- OPENSSL_free(txt);
-#else
- num = ossl_bn_new(bn);
-#endif
- BN_free(bn);
+
+ num = ossl_bn_new(BN_value_one());
+ bn = GetBNPtr(num);
+
+ if (ASN1_STRING_type(ai) == V_ASN1_ENUMERATED)
+ bn = ASN1_ENUMERATED_to_BN(ai, bn);
+ else
+ bn = ASN1_INTEGER_to_BN(ai, bn);
+
+ if (!bn)
+ ossl_raise(eOSSLError, NULL);
return num;
}
-#if DO_IT_VIA_RUBY
ASN1_INTEGER *
num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
{
- BIGNUM *bn = NULL;
-
- if (RTEST(rb_obj_is_kind_of(obj, cBN))) {
- bn = GetBNPtr(obj);
- } else {
- obj = rb_String(obj);
- if (!BN_dec2bn(&bn, StringValuePtr(obj))) {
- ossl_raise(eOSSLError, NULL);
- }
- }
- if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
- BN_free(bn);
- ossl_raise(eOSSLError, NULL);
- }
- BN_free(bn);
+ BIGNUM *bn;
+
+ if (NIL_P(obj))
+ ossl_raise(rb_eTypeError, "Can't convert nil into Integer");
+
+ bn = GetBNPtr(obj);
+
+ if (!(ai = BN_to_ASN1_INTEGER(bn, ai)))
+ ossl_raise(eOSSLError, NULL);
+
return ai;
}
-#else
-ASN1_INTEGER *
-num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
+
+static VALUE
+asn1integer_to_num_i(VALUE arg)
{
- BIGNUM *bn = GetBNPtr(obj);
-
- if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
- ossl_raise(eOSSLError, NULL);
- }
- return ai;
+ return asn1integer_to_num((ASN1_INTEGER *)arg);
}
-#endif
-/********/
/*
- * ASN1 module
+ * ASN1_OBJECT conversions
*/
-#define ossl_asn1_get_value(o) rb_attr_get((o),rb_intern("@value"))
-#define ossl_asn1_get_tag(o) rb_attr_get((o),rb_intern("@tag"))
-#define ossl_asn1_get_tagging(o) rb_attr_get((o),rb_intern("@tagging"))
-#define ossl_asn1_get_tag_class(o) rb_attr_get((o),rb_intern("@tag_class"))
-
-#define ossl_asn1_set_value(o,v) rb_iv_set((o),"@value",(v))
-#define ossl_asn1_set_tag(o,v) rb_iv_set((o),"@tag",(v))
-#define ossl_asn1_set_tagging(o,v) rb_iv_set((o),"@tagging",(v))
-#define ossl_asn1_set_tag_class(o,v) rb_iv_set((o),"@tag_class",(v))
+VALUE
+ossl_asn1obj_to_string_oid(const ASN1_OBJECT *a1obj)
+{
+ VALUE str;
+ int len;
+
+ str = rb_usascii_str_new(NULL, 127);
+ len = OBJ_obj2txt(RSTRING_PTR(str), RSTRING_LENINT(str), a1obj, 1);
+ if (len <= 0 || len == INT_MAX)
+ ossl_raise(eOSSLError, "OBJ_obj2txt");
+ if (len > RSTRING_LEN(str)) {
+ /* +1 is for the \0 terminator added by OBJ_obj2txt() */
+ rb_str_resize(str, len + 1);
+ len = OBJ_obj2txt(RSTRING_PTR(str), len + 1, a1obj, 1);
+ if (len <= 0)
+ ossl_raise(eOSSLError, "OBJ_obj2txt");
+ }
+ rb_str_set_len(str, len);
+ return str;
+}
-VALUE mASN1;
-VALUE eASN1Error;
+VALUE
+ossl_asn1obj_to_string(const ASN1_OBJECT *obj)
+{
+ int nid = OBJ_obj2nid(obj);
+ if (nid != NID_undef)
+ return rb_str_new_cstr(OBJ_nid2sn(nid));
+ return ossl_asn1obj_to_string_oid(obj);
+}
-VALUE cASN1Data;
-VALUE cASN1Primitive;
-VALUE cASN1Constructive;
-
-VALUE cASN1Boolean; /* BOOLEAN */
-VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
-VALUE cASN1BitString; /* BIT STRING */
-VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */
-VALUE cASN1NumericString, cASN1PrintableString;
-VALUE cASN1T61String, cASN1VideotexString;
-VALUE cASN1IA5String, cASN1GraphicString;
-VALUE cASN1ISO64String, cASN1GeneralString;
-VALUE cASN1UniversalString, cASN1BMPString;
-VALUE cASN1Null; /* NULL */
-VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
-VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
-VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
-
-static ID sIMPLICIT, sEXPLICIT;
-static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
+VALUE
+ossl_asn1obj_to_string_long_name(const ASN1_OBJECT *obj)
+{
+ int nid = OBJ_obj2nid(obj);
+ if (nid != NID_undef)
+ return rb_str_new_cstr(OBJ_nid2ln(nid));
+ return ossl_asn1obj_to_string_oid(obj);
+}
/*
* Ruby to ASN1 converters
@@ -196,7 +215,10 @@ static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
static ASN1_BOOLEAN
obj_to_asn1bool(VALUE obj)
{
- return RTEST(obj) ? 0xff : 0x100;
+ if (NIL_P(obj))
+ ossl_raise(rb_eTypeError, "Can't convert nil into Boolean");
+
+ return RTEST(obj) ? 0xff : 0x0;
}
static ASN1_INTEGER*
@@ -206,17 +228,19 @@ obj_to_asn1int(VALUE obj)
}
static ASN1_BIT_STRING*
-obj_to_asn1bstr(VALUE obj, long unused_bits)
+obj_to_asn1bstr(VALUE obj, int unused_bits)
{
ASN1_BIT_STRING *bstr;
- if(unused_bits < 0) unused_bits = 0;
+ if (unused_bits < 0 || unused_bits > 7)
+ ossl_raise(eASN1Error, "unused_bits for a bitstring value must be in "\
+ "the range 0 to 7");
StringValue(obj);
- if(!(bstr = ASN1_BIT_STRING_new()))
- ossl_raise(eASN1Error, NULL);
- ASN1_BIT_STRING_set(bstr, RSTRING(obj)->ptr, RSTRING(obj)->len);
- bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
- bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07);
+ if (!(bstr = ASN1_BIT_STRING_new()))
+ ossl_raise(eASN1Error, "ASN1_BIT_STRING_new");
+ if (!ASN1_BIT_STRING_set1(bstr, (uint8_t *)RSTRING_PTR(obj),
+ RSTRING_LEN(obj), unused_bits))
+ ossl_raise(eASN1Error, "ASN1_BIT_STRING_set1");
return bstr;
}
@@ -228,8 +252,11 @@ obj_to_asn1str(VALUE obj)
StringValue(obj);
if(!(str = ASN1_STRING_new()))
- ossl_raise(eASN1Error, NULL);
- ASN1_STRING_set(str, RSTRING(obj)->ptr, RSTRING(obj)->len);
+ ossl_raise(eASN1Error, NULL);
+ if(!ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LENINT(obj))) {
+ ASN1_STRING_free(str);
+ ossl_raise(eASN1Error, NULL);
+ }
return str;
}
@@ -240,47 +267,51 @@ obj_to_asn1null(VALUE obj)
ASN1_NULL *null;
if(!NIL_P(obj))
- ossl_raise(eASN1Error, "nil expected");
+ ossl_raise(eASN1Error, "nil expected");
if(!(null = ASN1_NULL_new()))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
return null;
}
-static ASN1_OBJECT*
-obj_to_asn1obj(VALUE obj)
+ASN1_OBJECT *
+ossl_to_asn1obj(VALUE obj)
{
ASN1_OBJECT *a1obj;
- StringValue(obj);
- a1obj = OBJ_txt2obj(RSTRING(obj)->ptr, 0);
- if(!a1obj) a1obj = OBJ_txt2obj(RSTRING(obj)->ptr, 1);
- if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
+ StringValueCStr(obj);
+ a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
+ if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
+ if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID %"PRIsVALUE, obj);
return a1obj;
}
-static ASN1_UTCTIME*
+static ASN1_UTCTIME *
obj_to_asn1utime(VALUE time)
{
time_t sec;
ASN1_UTCTIME *t;
- sec = time_to_time_t(time);
- if(!(t = ASN1_UTCTIME_set(NULL, sec)))
+ int off_days;
+
+ ossl_time_split(time, &sec, &off_days);
+ if (!(t = ASN1_UTCTIME_adj(NULL, sec, off_days, 0)))
ossl_raise(eASN1Error, NULL);
return t;
}
-static ASN1_GENERALIZEDTIME*
+static ASN1_GENERALIZEDTIME *
obj_to_asn1gtime(VALUE time)
{
time_t sec;
ASN1_GENERALIZEDTIME *t;
- sec = time_to_time_t(time);
- if(!(t =ASN1_GENERALIZEDTIME_set(NULL, sec)))
+ int off_days;
+
+ ossl_time_split(time, &sec, &off_days);
+ if (!(t = ASN1_GENERALIZEDTIME_adj(NULL, sec, off_days, 0)))
ossl_raise(eASN1Error, NULL);
return t;
@@ -294,8 +325,11 @@ obj_to_asn1derstr(VALUE obj)
str = ossl_to_der(obj);
if(!(a1str = ASN1_STRING_new()))
- ossl_raise(eASN1Error, NULL);
- ASN1_STRING_set(a1str, RSTRING(str)->ptr, RSTRING(str)->len);
+ ossl_raise(eASN1Error, NULL);
+ if(!ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LENINT(str))) {
+ ASN1_STRING_free(a1str);
+ ossl_raise(eASN1Error, NULL);
+ }
return a1str;
}
@@ -304,31 +338,31 @@ obj_to_asn1derstr(VALUE obj)
* DER to Ruby converters
*/
static VALUE
-decode_bool(unsigned char* der, int length)
+decode_bool(unsigned char* der, long length)
{
- int bool;
- unsigned char *p;
+ const unsigned char *p = der;
- p = der;
- if((bool = d2i_ASN1_BOOLEAN(NULL, &p, length)) < 0)
- ossl_raise(eASN1Error, NULL);
+ if (length != 3)
+ ossl_raise(eASN1Error, "invalid length for BOOLEAN");
+ if (p[0] != 1 || p[1] != 1)
+ ossl_raise(eASN1Error, "invalid BOOLEAN");
- return bool ? Qtrue : Qfalse;
+ return p[2] ? Qtrue : Qfalse;
}
static VALUE
-decode_int(unsigned char* der, int length)
+decode_int(unsigned char* der, long length)
{
ASN1_INTEGER *ai;
- unsigned char *p;
- VALUE ret;
+ const unsigned char *p;
+ VALUE ret;
int status = 0;
p = der;
if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length)))
- ossl_raise(eASN1Error, NULL);
- ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
- (VALUE)ai, &status);
+ ossl_raise(eASN1Error, NULL);
+ ret = rb_protect(asn1integer_to_num_i,
+ (VALUE)ai, &status);
ASN1_INTEGER_free(ai);
if(status) rb_jump_tag(status);
@@ -336,44 +370,42 @@ decode_int(unsigned char* der, int length)
}
static VALUE
-decode_bstr(unsigned char* der, int length, long *unused_bits)
+decode_bstr(unsigned char* der, long length, int *unused_bits)
{
ASN1_BIT_STRING *bstr;
- unsigned char *p, *buf;
- long len;
+ const unsigned char *p;
+ size_t len;
VALUE ret;
+ int state;
p = der;
- if(!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length)))
- ossl_raise(eASN1Error, NULL);
- len = bstr->length;
- if(!(buf = OPENSSL_malloc(len))){
- ASN1_BIT_STRING_free(bstr);
- ossl_raise(eASN1Error, NULL);
+ if (!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length)))
+ ossl_raise(eASN1Error, "d2i_ASN1_BIT_STRING");
+ if (!ASN1_BIT_STRING_get_length(bstr, &len, unused_bits)) {
+ ASN1_BIT_STRING_free(bstr);
+ ossl_raise(eASN1Error, "ASN1_BIT_STRING_get_length");
}
- *unused_bits = 0;
- if(bstr->flags & ASN1_STRING_FLAG_BITS_LEFT)
- *unused_bits = bstr->flags & 0x07;
- memcpy(buf, bstr->data, len);
+ ret = ossl_str_new((const char *)ASN1_STRING_get0_data(bstr), len, &state);
ASN1_BIT_STRING_free(bstr);
- ret = ossl_buf2str(buf, len);
+ if (state)
+ rb_jump_tag(state);
return ret;
}
static VALUE
-decode_enum(unsigned char* der, int length)
+decode_enum(unsigned char* der, long length)
{
ASN1_ENUMERATED *ai;
- unsigned char *p;
- VALUE ret;
+ const unsigned char *p;
+ VALUE ret;
int status = 0;
p = der;
if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length)))
- ossl_raise(eASN1Error, NULL);
- ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
- (VALUE)ai, &status);
+ ossl_raise(eASN1Error, NULL);
+ ret = rb_protect(asn1integer_to_num_i,
+ (VALUE)ai, &status);
ASN1_ENUMERATED_free(ai);
if(status) rb_jump_tag(status);
@@ -381,76 +413,80 @@ decode_enum(unsigned char* der, int length)
}
static VALUE
-decode_null(unsigned char* der, int length)
+decode_null(unsigned char* der, long length)
{
ASN1_NULL *null;
- unsigned char *p;
+ const unsigned char *p;
p = der;
if(!(null = d2i_ASN1_NULL(NULL, &p, length)))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
ASN1_NULL_free(null);
return Qnil;
}
+VALUE
+asn1obj_to_string_i(VALUE arg)
+{
+ return ossl_asn1obj_to_string((const ASN1_OBJECT *)arg);
+}
+
static VALUE
-decode_obj(unsigned char* der, int length)
+decode_obj(unsigned char* der, long length)
{
ASN1_OBJECT *obj;
- unsigned char *p;
+ const unsigned char *p;
VALUE ret;
- int nid;
- BIO *bio;
+ int state;
p = der;
- if(!(obj = d2i_ASN1_OBJECT(NULL, &p, length)))
- ossl_raise(eASN1Error, NULL);
- if((nid = OBJ_obj2nid(obj)) != NID_undef){
- ASN1_OBJECT_free(obj);
- ret = rb_str_new2(OBJ_nid2sn(nid));
- }
- else{
- if(!(bio = BIO_new(BIO_s_mem()))){
- ASN1_OBJECT_free(obj);
- ossl_raise(eASN1Error, NULL);
- }
- i2a_ASN1_OBJECT(bio, obj);
- ASN1_OBJECT_free(obj);
- ret = ossl_membio2str(bio);
- }
-
+ if (!(obj = d2i_ASN1_OBJECT(NULL, &p, length)))
+ ossl_raise(eASN1Error, "d2i_ASN1_OBJECT");
+ ret = rb_protect(asn1obj_to_string_i, (VALUE)obj, &state);
+ ASN1_OBJECT_free(obj);
+ if (state)
+ rb_jump_tag(state);
return ret;
}
static VALUE
-decode_time(unsigned char* der, int length)
+decode_time(unsigned char* der, long length)
{
ASN1_TIME *time;
- unsigned char *p;
+ const unsigned char *p;
VALUE ret;
int status = 0;
p = der;
if(!(time = d2i_ASN1_TIME(NULL, &p, length)))
- ossl_raise(eASN1Error, NULL);
- ret = rb_protect((VALUE(*)_((VALUE)))asn1time_to_time,
- (VALUE)time, &status);
+ ossl_raise(eASN1Error, NULL);
+ ret = rb_protect(asn1time_to_time_i,
+ (VALUE)time, &status);
ASN1_TIME_free(time);
if(status) rb_jump_tag(status);
return ret;
}
+static VALUE
+decode_eoc(unsigned char *der, long length)
+{
+ if (length != 2 || !(der[0] == 0x00 && der[1] == 0x00))
+ ossl_raise(eASN1Error, NULL);
+
+ return rb_str_new("", 0);
+}
+
/********/
typedef struct {
- char *name;
+ const char *name;
VALUE *klass;
} ossl_asn1_info_t;
-static ossl_asn1_info_t ossl_asn1_info[] = {
- { "EOC", NULL, }, /* 0 */
+static const ossl_asn1_info_t ossl_asn1_info[] = {
+ { "EOC", &cASN1EndOfContent, }, /* 0 */
{ "BOOLEAN", &cASN1Boolean, }, /* 1 */
{ "INTEGER", &cASN1Integer, }, /* 2 */
{ "BIT_STRING", &cASN1BitString, }, /* 3 */
@@ -483,79 +519,81 @@ static ossl_asn1_info_t ossl_asn1_info[] = {
{ "BMPSTRING", &cASN1BMPString, }, /* 30 */
};
-int ossl_asn1_info_size = (sizeof(ossl_asn1_info)/sizeof(ossl_asn1_info[0]));
+enum {ossl_asn1_info_size = (sizeof(ossl_asn1_info)/sizeof(ossl_asn1_info[0]))};
+
+static VALUE class_tag_map;
static int ossl_asn1_default_tag(VALUE obj);
-ASN1_TYPE*
+static ASN1_TYPE *
ossl_asn1_get_asn1type(VALUE obj)
{
ASN1_TYPE *ret;
VALUE value, rflag;
void *ptr;
- void (*free_func)();
- long tag, flag;
+ typedef void free_func_type(void *);
+ free_func_type *free_func;
+ int tag;
tag = ossl_asn1_default_tag(obj);
value = ossl_asn1_get_value(obj);
switch(tag){
- case V_ASN1_BOOLEAN:
- ptr = (void*)obj_to_asn1bool(value);
- free_func = NULL;
- break;
- case V_ASN1_INTEGER: /* FALLTHROUGH */
- case V_ASN1_ENUMERATED:
- ptr = obj_to_asn1int(value);
- free_func = ASN1_INTEGER_free;
- break;
- case V_ASN1_BIT_STRING:
- rflag = rb_attr_get(obj, rb_intern("@unused_bits"));
- flag = NIL_P(rflag) ? -1 : NUM2INT(rflag);
- ptr = obj_to_asn1bstr(value, flag);
- free_func = ASN1_BIT_STRING_free;
- break;
- case V_ASN1_NULL:
- ptr = obj_to_asn1null(value);
- free_func = ASN1_NULL_free;
- break;
- case V_ASN1_OCTET_STRING: /* FALLTHROUGH */
- case V_ASN1_UTF8STRING: /* FALLTHROUGH */
- case V_ASN1_NUMERICSTRING: /* FALLTHROUGH */
- case V_ASN1_PRINTABLESTRING: /* FALLTHROUGH */
- case V_ASN1_T61STRING: /* FALLTHROUGH */
- case V_ASN1_VIDEOTEXSTRING: /* FALLTHROUGH */
- case V_ASN1_IA5STRING: /* FALLTHROUGH */
- case V_ASN1_GRAPHICSTRING: /* FALLTHROUGH */
- case V_ASN1_ISO64STRING: /* FALLTHROUGH */
- case V_ASN1_GENERALSTRING: /* FALLTHROUGH */
- case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */
- case V_ASN1_BMPSTRING:
- ptr = obj_to_asn1str(value);
- free_func = ASN1_STRING_free;
- break;
- case V_ASN1_OBJECT:
- ptr = obj_to_asn1obj(value);
- free_func = ASN1_OBJECT_free;
- break;
- case V_ASN1_UTCTIME:
- ptr = obj_to_asn1utime(value);
- free_func = ASN1_TIME_free;
- break;
- case V_ASN1_GENERALIZEDTIME:
- ptr = obj_to_asn1gtime(value);
- free_func = ASN1_TIME_free;
- break;
- case V_ASN1_SET: /* FALLTHROUGH */
- case V_ASN1_SEQUENCE:
- ptr = obj_to_asn1derstr(obj);
- free_func = ASN1_STRING_free;
- break;
- default:
- ossl_raise(eASN1Error, "unsupported ASN.1 type");
+ case V_ASN1_BOOLEAN:
+ ptr = (void*)(VALUE)obj_to_asn1bool(value);
+ free_func = NULL;
+ break;
+ case V_ASN1_INTEGER: /* FALLTHROUGH */
+ case V_ASN1_ENUMERATED:
+ ptr = obj_to_asn1int(value);
+ free_func = (free_func_type *)ASN1_INTEGER_free;
+ break;
+ case V_ASN1_BIT_STRING:
+ rflag = rb_attr_get(obj, sivUNUSED_BITS);
+ ptr = obj_to_asn1bstr(value, NUM2INT(rflag));
+ free_func = (free_func_type *)ASN1_BIT_STRING_free;
+ break;
+ case V_ASN1_NULL:
+ ptr = obj_to_asn1null(value);
+ free_func = (free_func_type *)ASN1_NULL_free;
+ break;
+ case V_ASN1_OCTET_STRING: /* FALLTHROUGH */
+ case V_ASN1_UTF8STRING: /* FALLTHROUGH */
+ case V_ASN1_NUMERICSTRING: /* FALLTHROUGH */
+ case V_ASN1_PRINTABLESTRING: /* FALLTHROUGH */
+ case V_ASN1_T61STRING: /* FALLTHROUGH */
+ case V_ASN1_VIDEOTEXSTRING: /* FALLTHROUGH */
+ case V_ASN1_IA5STRING: /* FALLTHROUGH */
+ case V_ASN1_GRAPHICSTRING: /* FALLTHROUGH */
+ case V_ASN1_ISO64STRING: /* FALLTHROUGH */
+ case V_ASN1_GENERALSTRING: /* FALLTHROUGH */
+ case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */
+ case V_ASN1_BMPSTRING:
+ ptr = obj_to_asn1str(value);
+ free_func = (free_func_type *)ASN1_STRING_free;
+ break;
+ case V_ASN1_OBJECT:
+ ptr = ossl_to_asn1obj(value);
+ free_func = (free_func_type *)ASN1_OBJECT_free;
+ break;
+ case V_ASN1_UTCTIME:
+ ptr = obj_to_asn1utime(value);
+ free_func = (free_func_type *)ASN1_TIME_free;
+ break;
+ case V_ASN1_GENERALIZEDTIME:
+ ptr = obj_to_asn1gtime(value);
+ free_func = (free_func_type *)ASN1_TIME_free;
+ break;
+ case V_ASN1_SET: /* FALLTHROUGH */
+ case V_ASN1_SEQUENCE:
+ ptr = obj_to_asn1derstr(obj);
+ free_func = (free_func_type *)ASN1_STRING_free;
+ break;
+ default:
+ ossl_raise(eASN1Error, "unsupported ASN.1 type");
}
if(!(ret = OPENSSL_malloc(sizeof(ASN1_TYPE)))){
- if(free_func) free_func(ptr);
- ossl_raise(eASN1Error, "ASN1_TYPE alloc failure");
+ if(free_func) free_func(ptr);
+ ossl_raise(eASN1Error, "ASN1_TYPE alloc failure");
}
memset(ret, 0, sizeof(ASN1_TYPE));
ASN1_TYPE_set(ret, tag, ptr);
@@ -566,18 +604,17 @@ ossl_asn1_get_asn1type(VALUE obj)
static int
ossl_asn1_default_tag(VALUE obj)
{
- int i;
-
- for(i = 0; i < ossl_asn1_info_size; i++){
- if(ossl_asn1_info[i].klass &&
- rb_obj_is_kind_of(obj, *ossl_asn1_info[i].klass)){
- return i;
- }
+ VALUE tmp_class, tag;
+
+ tmp_class = CLASS_OF(obj);
+ while (!NIL_P(tmp_class)) {
+ tag = rb_hash_lookup(class_tag_map, tmp_class);
+ if (tag != Qnil)
+ return NUM2INT(tag);
+ tmp_class = rb_class_superclass(tmp_class);
}
- ossl_raise(eASN1Error, "universal tag for %s not found",
- rb_class2name(CLASS_OF(obj)));
- return -1; /* dummy */
+ return -1;
}
static int
@@ -587,432 +624,684 @@ ossl_asn1_tag(VALUE obj)
tag = ossl_asn1_get_tag(obj);
if(NIL_P(tag))
- ossl_raise(eASN1Error, "tag number not specified");
+ ossl_raise(eASN1Error, "tag number not specified");
return NUM2INT(tag);
}
static int
-ossl_asn1_is_explicit(VALUE obj)
-{
- VALUE s;
- int ret = -1;
-
- s = ossl_asn1_get_tagging(obj);
- if(NIL_P(s)) return 0;
- else if(SYMBOL_P(s)){
- if (SYM2ID(s) == sIMPLICIT)
- ret = 0;
- else if (SYM2ID(s) == sEXPLICIT)
- ret = 1;
- }
- if(ret < 0){
- ossl_raise(eASN1Error, "invalid tag default");
- }
-
- return ret;
-}
-
-static int
ossl_asn1_tag_class(VALUE obj)
{
VALUE s;
- int ret = -1;
s = ossl_asn1_get_tag_class(obj);
- if(NIL_P(s)) ret = V_ASN1_UNIVERSAL;
- else if(SYMBOL_P(s)){
- if (SYM2ID(s) == sUNIVERSAL)
- ret = V_ASN1_UNIVERSAL;
- else if (SYM2ID(s) == sAPPLICATION)
- ret = V_ASN1_APPLICATION;
- else if (SYM2ID(s) == sCONTEXT_SPECIFIC)
- ret = V_ASN1_CONTEXT_SPECIFIC;
- else if (SYM2ID(s) == sPRIVATE)
- ret = V_ASN1_PRIVATE;
- }
- if(ret < 0){
- ossl_raise(eASN1Error, "invalid tag class");
- }
-
- return ret;
+ if (NIL_P(s) || s == sym_UNIVERSAL)
+ return V_ASN1_UNIVERSAL;
+ else if (s == sym_APPLICATION)
+ return V_ASN1_APPLICATION;
+ else if (s == sym_CONTEXT_SPECIFIC)
+ return V_ASN1_CONTEXT_SPECIFIC;
+ else if (s == sym_PRIVATE)
+ return V_ASN1_PRIVATE;
+ else
+ ossl_raise(eASN1Error, "invalid tag class");
}
static VALUE
ossl_asn1_class2sym(int tc)
{
if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
- return ID2SYM(sPRIVATE);
+ return sym_PRIVATE;
else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
- return ID2SYM(sCONTEXT_SPECIFIC);
+ return sym_CONTEXT_SPECIFIC;
else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
- return ID2SYM(sAPPLICATION);
+ return sym_APPLICATION;
else
- return ID2SYM(sUNIVERSAL);
+ return sym_UNIVERSAL;
}
+/*
+ * call-seq:
+ * OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) => ASN1Data
+ *
+ * _value_: Please have a look at Constructive and Primitive to see how Ruby
+ * types are mapped to ASN.1 types and vice versa.
+ *
+ * _tag_: An Integer indicating the tag number.
+ *
+ * _tag_class_: A Symbol indicating the tag class. Please cf. ASN1 for
+ * possible values.
+ *
+ * == Example
+ * asn1_int = OpenSSL::ASN1Data.new(42, 2, :UNIVERSAL) # => Same as OpenSSL::ASN1::Integer.new(42)
+ * tagged_int = OpenSSL::ASN1Data.new(42, 0, :CONTEXT_SPECIFIC) # implicitly 0-tagged INTEGER
+ */
static VALUE
ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
{
if(!SYMBOL_P(tag_class))
- ossl_raise(eASN1Error, "invalid tag class");
- if((SYM2ID(tag_class) == sUNIVERSAL) && NUM2INT(tag) > 31)
- ossl_raise(eASN1Error, "tag number for Universal too large");
+ ossl_raise(eASN1Error, "invalid tag class");
ossl_asn1_set_tag(self, tag);
ossl_asn1_set_value(self, value);
ossl_asn1_set_tag_class(self, tag_class);
+ ossl_asn1_set_indefinite_length(self, Qfalse);
return self;
}
-static VALUE
-join_der_i(VALUE i, VALUE str)
+static VALUE
+to_der_internal(VALUE self, int constructed, int indef_len, VALUE body)
{
- i = ossl_to_der_if_possible(i);
- StringValue(i);
- rb_str_append(str, i);
- return Qnil;
+ int encoding = constructed ? indef_len ? 2 : 1 : 0;
+ int tag_class = ossl_asn1_tag_class(self);
+ int tag_number = ossl_asn1_tag(self);
+ int default_tag_number = ossl_asn1_default_tag(self);
+ int body_length, total_length;
+ VALUE str;
+ unsigned char *p;
+
+ body_length = RSTRING_LENINT(body);
+ if (ossl_asn1_get_tagging(self) == sym_EXPLICIT) {
+ int inner_length, e_encoding = indef_len ? 2 : 1;
+
+ if (default_tag_number == -1)
+ ossl_raise(eASN1Error, "explicit tagging of unknown tag");
+
+ inner_length = ASN1_object_size(encoding, body_length, default_tag_number);
+ total_length = ASN1_object_size(e_encoding, inner_length, tag_number);
+ str = rb_str_new(NULL, total_length);
+ p = (unsigned char *)RSTRING_PTR(str);
+ /* Put explicit tag */
+ ASN1_put_object(&p, e_encoding, inner_length, tag_number, tag_class);
+ /* Append inner object */
+ ASN1_put_object(&p, encoding, body_length, default_tag_number, V_ASN1_UNIVERSAL);
+ memcpy(p, RSTRING_PTR(body), body_length);
+ p += body_length;
+ if (indef_len) {
+ ASN1_put_eoc(&p); /* For inner object */
+ ASN1_put_eoc(&p); /* For wrapper object */
+ }
+ }
+ else {
+ total_length = ASN1_object_size(encoding, body_length, tag_number);
+ str = rb_str_new(NULL, total_length);
+ p = (unsigned char *)RSTRING_PTR(str);
+ ASN1_put_object(&p, encoding, body_length, tag_number, tag_class);
+ memcpy(p, RSTRING_PTR(body), body_length);
+ p += body_length;
+ if (indef_len)
+ ASN1_put_eoc(&p);
+ }
+ assert(p - (unsigned char *)RSTRING_PTR(str) == total_length);
+ return str;
}
+static VALUE ossl_asn1prim_to_der(VALUE);
+static VALUE ossl_asn1cons_to_der(VALUE);
+/*
+ * call-seq:
+ * asn1.to_der => DER-encoded String
+ *
+ * Encodes this ASN1Data into a DER-encoded String value. The result is
+ * DER-encoded except for the possibility of indefinite length forms.
+ * Indefinite length forms are not allowed in strict DER, so strictly speaking
+ * the result of such an encoding would be a BER-encoding.
+ */
static VALUE
-join_der(VALUE enumerable)
+ossl_asn1data_to_der(VALUE self)
{
- VALUE str = rb_str_new(0, 0);
- rb_iterate(rb_each, enumerable, join_der_i, str);
- return str;
+ VALUE value = ossl_asn1_get_value(self);
+
+ if (rb_obj_is_kind_of(value, rb_cArray))
+ return ossl_asn1cons_to_der(self);
+ else {
+ if (RTEST(ossl_asn1_get_indefinite_length(self)))
+ ossl_raise(eASN1Error, "indefinite length form cannot be used " \
+ "with primitive encoding");
+ return ossl_asn1prim_to_der(self);
+ }
}
+static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self);
+static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset,
+ int depth, int yield, long *num_read);
+
static VALUE
-ossl_asn1data_to_der(VALUE self)
+int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag,
+ VALUE tc, long *num_read)
{
- VALUE value, der;
- int tag, tag_class, is_cons = 0;
- long length;
+ VALUE value, asn1data;
unsigned char *p;
+ int flag = 0;
- value = ossl_asn1_get_value(self);
- if(rb_obj_is_kind_of(value, rb_cArray)){
- is_cons = 1;
- value = join_der(value);
+ p = *pp;
+
+ if(tc == sym_UNIVERSAL && tag < ossl_asn1_info_size) {
+ switch(tag){
+ case V_ASN1_EOC:
+ value = decode_eoc(p, hlen+length);
+ break;
+ case V_ASN1_BOOLEAN:
+ value = decode_bool(p, hlen+length);
+ break;
+ case V_ASN1_INTEGER:
+ value = decode_int(p, hlen+length);
+ break;
+ case V_ASN1_BIT_STRING:
+ value = decode_bstr(p, hlen+length, &flag);
+ break;
+ case V_ASN1_NULL:
+ value = decode_null(p, hlen+length);
+ break;
+ case V_ASN1_ENUMERATED:
+ value = decode_enum(p, hlen+length);
+ break;
+ case V_ASN1_OBJECT:
+ value = decode_obj(p, hlen+length);
+ break;
+ case V_ASN1_UTCTIME: /* FALLTHROUGH */
+ case V_ASN1_GENERALIZEDTIME:
+ value = decode_time(p, hlen+length);
+ break;
+ default:
+ /* use original value */
+ p += hlen;
+ value = rb_str_new((const char *)p, length);
+ break;
+ }
+ }
+ else {
+ p += hlen;
+ value = rb_str_new((const char *)p, length);
+ }
+
+ *pp += hlen + length;
+ *num_read = hlen + length;
+
+ if (tc == sym_UNIVERSAL &&
+ tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) {
+ VALUE klass = *ossl_asn1_info[tag].klass;
+ VALUE args[4];
+ args[0] = value;
+ args[1] = INT2NUM(tag);
+ args[2] = Qnil;
+ args[3] = tc;
+ asn1data = rb_obj_alloc(klass);
+ ossl_asn1_initialize(4, args, asn1data);
+ if(tag == V_ASN1_BIT_STRING){
+ rb_ivar_set(asn1data, sivUNUSED_BITS, INT2NUM(flag));
+ }
+ }
+ else {
+ asn1data = rb_obj_alloc(cASN1Data);
+ ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), tc);
}
- StringValue(value);
-
- tag = ossl_asn1_tag(self);
- tag_class = ossl_asn1_tag_class(self);
- if((length = ASN1_object_size(1, RSTRING(value)->len, tag)) <= 0)
- ossl_raise(eASN1Error, NULL);
- der = rb_str_new(0, length);
- p = RSTRING(der)->ptr;
- ASN1_put_object(&p, is_cons, RSTRING(value)->len, tag, tag_class);
- memcpy(p, RSTRING(value)->ptr, RSTRING(value)->len);
- p += RSTRING(value)->len;
- ossl_str_adjust(der, p);
-
- return der;
+
+ return asn1data;
}
static VALUE
-ossl_asn1_decode0(unsigned char **pp, long length, long *offset, long depth,
- int once, int yield)
+int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
+ long *offset, int depth, int yield, int j,
+ int tag, VALUE tc, long *num_read)
{
- unsigned char *start, *p;
- long len, off = *offset;
- int hlen, tag, tc, j;
- VALUE ary, asn1data, value, tag_class;
+ VALUE value, asn1data, ary;
+ int indefinite;
+ long available_len, off = *offset;
+ indefinite = (j == 0x21);
ary = rb_ary_new();
+
+ available_len = indefinite ? max_len : length;
+ while (available_len > 0) {
+ long inner_read = 0;
+ value = ossl_asn1_decode0(pp, available_len, &off, depth + 1, yield, &inner_read);
+ *num_read += inner_read;
+ available_len -= inner_read;
+
+ if (indefinite) {
+ if (ossl_asn1_tag(value) == V_ASN1_EOC &&
+ ossl_asn1_get_tag_class(value) == sym_UNIVERSAL)
+ break;
+ if (available_len == 0)
+ ossl_raise(eASN1Error, "EOC missing in indefinite length encoding");
+ }
+ rb_ary_push(ary, value);
+ }
+
+ if (tc == sym_UNIVERSAL) {
+ VALUE args[4];
+ if (tag == V_ASN1_SEQUENCE || tag == V_ASN1_SET)
+ asn1data = rb_obj_alloc(*ossl_asn1_info[tag].klass);
+ else
+ asn1data = rb_obj_alloc(cASN1Constructive);
+ args[0] = ary;
+ args[1] = INT2NUM(tag);
+ args[2] = Qnil;
+ args[3] = tc;
+ ossl_asn1_initialize(4, args, asn1data);
+ }
+ else {
+ asn1data = rb_obj_alloc(cASN1Data);
+ ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), tc);
+ }
+
+ if (indefinite)
+ ossl_asn1_set_indefinite_length(asn1data, Qtrue);
+ else
+ ossl_asn1_set_indefinite_length(asn1data, Qfalse);
+
+ *offset = off;
+ return asn1data;
+}
+
+#define MAX_NESTING_DEPTH 200
+
+static VALUE
+ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth,
+ int yield, long *num_read)
+{
+ unsigned char *start, *p;
+ const unsigned char *p0;
+ long len = 0, inner_read = 0, off = *offset, hlen;
+ int tag, tc, j;
+ VALUE asn1data, tag_class;
+
+ if (depth > MAX_NESTING_DEPTH) {
+ ossl_raise(eASN1Error, "nesting depth %d exceeds limit", depth);
+ }
+
p = *pp;
- while(length > 0){
- start = p;
- j = ASN1_get_object(&p, &len, &tag, &tc, length);
- if(j & 0x80) ossl_raise(eASN1Error, NULL);
- hlen = p - start;
- if(yield){
- VALUE arg = rb_ary_new();
- rb_ary_push(arg, LONG2NUM(depth));
- rb_ary_push(arg, LONG2NUM(off));
- rb_ary_push(arg, LONG2NUM(hlen));
- rb_ary_push(arg, LONG2NUM(len));
- rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse);
- rb_ary_push(arg, ossl_asn1_class2sym(tc));
- rb_ary_push(arg, INT2NUM(tag));
- rb_yield(arg);
- }
- length -= hlen;
- off += hlen;
- if(len > length) ossl_raise(eASN1Error, "value is too short");
- if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
- tag_class = sPRIVATE;
- else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
- tag_class = sCONTEXT_SPECIFIC;
- else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
- tag_class = sAPPLICATION;
- else
- tag_class = sUNIVERSAL;
- if(j & V_ASN1_CONSTRUCTED){
- /* TODO: if j == 0x21 it is indefinite length object. */
- if((j == 0x21) && (len == 0)){
- long lastoff = off;
- value = ossl_asn1_decode0(&p, length, &off, depth+1, 0, yield);
- len = off - lastoff;
- }
- else value = ossl_asn1_decode0(&p, len, &off, depth+1, 0, yield);
- }
- else{
- value = rb_str_new(p, len);
- p += len;
- off += len;
- }
- if(tag_class == sUNIVERSAL &&
- tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass){
- VALUE klass = *ossl_asn1_info[tag].klass;
- long flag = 0;
- if(!rb_obj_is_kind_of(value, rb_cArray)){
- switch(tag){
- case V_ASN1_BOOLEAN:
- value = decode_bool(start, hlen+len);
- break;
- case V_ASN1_INTEGER:
- value = decode_int(start, hlen+len);
- break;
- case V_ASN1_BIT_STRING:
- value = decode_bstr(start, hlen+len, &flag);
- break;
- case V_ASN1_NULL:
- value = decode_null(start, hlen+len);
- break;
- case V_ASN1_ENUMERATED:
- value = decode_enum(start, hlen+len);
- break;
- case V_ASN1_OBJECT:
- value = decode_obj(start, hlen+len);
- break;
- case V_ASN1_UTCTIME: /* FALLTHROUGH */
- case V_ASN1_GENERALIZEDTIME:
- value = decode_time(start, hlen+len);
- break;
- default:
- /* use original value */
- break;
- }
- }
- asn1data = rb_funcall(klass, rb_intern("new"), 1, value);
- if(tag == V_ASN1_BIT_STRING){
- rb_iv_set(asn1data, "@unused_bits", LONG2NUM(flag));
- }
- }
- else{
- asn1data = rb_funcall(cASN1Data, rb_intern("new"), 3,
- value, INT2NUM(tag), ID2SYM(tag_class));
- }
- rb_ary_push(ary, asn1data);
- length -= len;
- if(once) break;
+ start = p;
+ p0 = p;
+ j = ASN1_get_object(&p0, &len, &tag, &tc, length);
+ p = (unsigned char *)p0;
+ if(j & 0x80) ossl_raise(eASN1Error, NULL);
+ if(len > length) ossl_raise(eASN1Error, "value is too short");
+ if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
+ tag_class = sym_PRIVATE;
+ else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
+ tag_class = sym_CONTEXT_SPECIFIC;
+ else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
+ tag_class = sym_APPLICATION;
+ else
+ tag_class = sym_UNIVERSAL;
+
+ hlen = p - start;
+
+ if(yield) {
+ VALUE arg = rb_ary_new();
+ rb_ary_push(arg, LONG2NUM(depth));
+ rb_ary_push(arg, LONG2NUM(*offset));
+ rb_ary_push(arg, LONG2NUM(hlen));
+ rb_ary_push(arg, LONG2NUM(len));
+ rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse);
+ rb_ary_push(arg, ossl_asn1_class2sym(tc));
+ rb_ary_push(arg, INT2NUM(tag));
+ rb_yield(arg);
+ }
+
+ if(j & V_ASN1_CONSTRUCTED) {
+ *pp += hlen;
+ off += hlen;
+ asn1data = int_ossl_asn1_decode0_cons(pp, length - hlen, len, &off, depth, yield, j, tag, tag_class, &inner_read);
+ inner_read += hlen;
}
- *pp = p;
+ else {
+ if ((j & 0x01) && (len == 0))
+ ossl_raise(eASN1Error, "indefinite length for primitive value");
+ asn1data = int_ossl_asn1_decode0_prim(pp, len, hlen, tag, tag_class, &inner_read);
+ off += hlen + len;
+ }
+ if (num_read)
+ *num_read = inner_read;
+ if (len != 0 && inner_read != hlen + len) {
+ ossl_raise(eASN1Error,
+ "Type mismatch. Bytes read: %ld Bytes available: %ld",
+ inner_read, hlen + len);
+ }
+
*offset = off;
+ return asn1data;
+}
- return ary;
+static void
+int_ossl_decode_sanity_check(long len, long read, long offset)
+{
+ if (len != 0 && (read != len || offset != len)) {
+ ossl_raise(eASN1Error,
+ "Type mismatch. Total bytes read: %ld Bytes available: %ld Offset: %ld",
+ read, len, offset);
+ }
}
+/*
+ * call-seq:
+ * OpenSSL::ASN1.traverse(asn1) -> nil
+ *
+ * If a block is given, it prints out each of the elements encountered.
+ * Block parameters are (in that order):
+ * * depth: The recursion depth, plus one with each constructed value being encountered (Integer)
+ * * offset: Current byte offset (Integer)
+ * * header length: Combined length in bytes of the Tag and Length headers. (Integer)
+ * * length: The overall remaining length of the entire data (Integer)
+ * * constructed: Whether this value is constructed or not (Boolean)
+ * * tag_class: Current tag class (Symbol)
+ * * tag: The current tag number (Integer)
+ *
+ * == Example
+ * der = File.binread('asn1data.der')
+ * OpenSSL::ASN1.traverse(der) do | depth, offset, header_len, length, constructed, tag_class, tag|
+ * puts "Depth: #{depth} Offset: #{offset} Length: #{length}"
+ * puts "Header length: #{header_len} Tag: #{tag} Tag class: #{tag_class} Constructed: #{constructed}"
+ * end
+ */
static VALUE
ossl_asn1_traverse(VALUE self, VALUE obj)
{
unsigned char *p;
- long offset = 0;
- volatile VALUE tmp;
+ VALUE tmp;
+ long len, read = 0, offset = 0;
obj = ossl_to_der_if_possible(obj);
tmp = rb_str_new4(StringValue(obj));
- p = RSTRING(tmp)->ptr;
- ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 0, 1);
-
+ p = (unsigned char *)RSTRING_PTR(tmp);
+ len = RSTRING_LEN(tmp);
+ ossl_asn1_decode0(&p, len, &offset, 0, 1, &read);
+ RB_GC_GUARD(tmp);
+ int_ossl_decode_sanity_check(len, read, offset);
return Qnil;
}
+/*
+ * call-seq:
+ * OpenSSL::ASN1.decode(der) -> ASN1Data
+ *
+ * Decodes a BER- or DER-encoded value and creates an ASN1Data instance. _der_
+ * may be a String or any object that features a +.to_der+ method transforming
+ * it into a BER-/DER-encoded String+
+ *
+ * == Example
+ * der = File.binread('asn1data')
+ * asn1 = OpenSSL::ASN1.decode(der)
+ */
static VALUE
ossl_asn1_decode(VALUE self, VALUE obj)
{
- VALUE ret, ary;
+ VALUE ret;
unsigned char *p;
- long offset = 0;
- volatile VALUE tmp;
+ VALUE tmp;
+ long len, read = 0, offset = 0;
obj = ossl_to_der_if_possible(obj);
tmp = rb_str_new4(StringValue(obj));
- p = RSTRING(tmp)->ptr;
- ary = ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 1, 0);
- ret = rb_ary_entry(ary, 0);
-
+ p = (unsigned char *)RSTRING_PTR(tmp);
+ len = RSTRING_LEN(tmp);
+ ret = ossl_asn1_decode0(&p, len, &offset, 0, 0, &read);
+ RB_GC_GUARD(tmp);
+ int_ossl_decode_sanity_check(len, read, offset);
return ret;
}
+/*
+ * call-seq:
+ * OpenSSL::ASN1.decode_all(der) -> Array of ASN1Data
+ *
+ * Similar to #decode with the difference that #decode expects one
+ * distinct value represented in _der_. #decode_all on the contrary
+ * decodes a sequence of sequential BER/DER values lined up in _der_
+ * and returns them as an array.
+ *
+ * == Example
+ * ders = File.binread('asn1data_seq')
+ * asn1_ary = OpenSSL::ASN1.decode_all(ders)
+ */
static VALUE
ossl_asn1_decode_all(VALUE self, VALUE obj)
{
- VALUE ret;
+ VALUE ary, val;
unsigned char *p;
- long offset = 0;
- volatile VALUE tmp;
+ long len, tmp_len = 0, read = 0, offset = 0;
+ VALUE tmp;
obj = ossl_to_der_if_possible(obj);
tmp = rb_str_new4(StringValue(obj));
- p = RSTRING(tmp)->ptr;
- ret = ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 0, 0);
-
- return ret;
+ p = (unsigned char *)RSTRING_PTR(tmp);
+ len = RSTRING_LEN(tmp);
+ tmp_len = len;
+ ary = rb_ary_new();
+ while (tmp_len > 0) {
+ long tmp_read = 0;
+ val = ossl_asn1_decode0(&p, tmp_len, &offset, 0, 0, &tmp_read);
+ rb_ary_push(ary, val);
+ read += tmp_read;
+ tmp_len -= tmp_read;
+ }
+ RB_GC_GUARD(tmp);
+ int_ossl_decode_sanity_check(len, read, offset);
+ return ary;
}
+/*
+ * call-seq:
+ * OpenSSL::ASN1::Primitive.new(value [, tag, tagging, tag_class ]) => Primitive
+ *
+ * _value_: is mandatory.
+ *
+ * _tag_: optional, may be specified for tagged values. If no _tag_ is
+ * specified, the UNIVERSAL tag corresponding to the Primitive sub-class
+ * is used by default.
+ *
+ * _tagging_: may be used as an encoding hint to encode a value either
+ * explicitly or implicitly, see ASN1 for possible values.
+ *
+ * _tag_class_: if _tag_ and _tagging_ are +nil+ then this is set to
+ * +:UNIVERSAL+ by default. If either _tag_ or _tagging_ are set then
+ * +:CONTEXT_SPECIFIC+ is used as the default. For possible values please
+ * cf. ASN1.
+ *
+ * == Example
+ * int = OpenSSL::ASN1::Integer.new(42)
+ * zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :IMPLICIT)
+ * private_explicit_zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :EXPLICIT, :PRIVATE)
+ */
static VALUE
ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE value, tag, tagging, tag_class;
+ int default_tag;
rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class);
- if(argc > 1){
- if(NIL_P(tag))
- ossl_raise(eASN1Error, "must specify tag number");
- if(NIL_P(tagging))
- tagging = ID2SYM(sEXPLICIT);
- if(!SYMBOL_P(tagging))
- ossl_raise(eASN1Error, "invalid tag default");
- if(NIL_P(tag_class))
- tag_class = ID2SYM(sCONTEXT_SPECIFIC);
- if(!SYMBOL_P(tag_class))
- ossl_raise(eASN1Error, "invalid tag class");
- if(SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31)
- ossl_raise(eASN1Error, "tag number for Universal too large");
+ default_tag = ossl_asn1_default_tag(self);
+
+ if (default_tag == -1 || argc > 1) {
+ if(NIL_P(tag))
+ ossl_raise(eASN1Error, "must specify tag number");
+ if(!NIL_P(tagging) && !SYMBOL_P(tagging))
+ ossl_raise(eASN1Error, "invalid tagging method");
+ if(NIL_P(tag_class)) {
+ if (NIL_P(tagging))
+ tag_class = sym_UNIVERSAL;
+ else
+ tag_class = sym_CONTEXT_SPECIFIC;
+ }
+ if(!SYMBOL_P(tag_class))
+ ossl_raise(eASN1Error, "invalid tag class");
}
else{
- tag = INT2NUM(ossl_asn1_default_tag(self));
+ tag = INT2NUM(default_tag);
tagging = Qnil;
- tag_class = ID2SYM(sUNIVERSAL);
+ tag_class = sym_UNIVERSAL;
}
ossl_asn1_set_tag(self, tag);
ossl_asn1_set_value(self, value);
ossl_asn1_set_tagging(self, tagging);
ossl_asn1_set_tag_class(self, tag_class);
+ ossl_asn1_set_indefinite_length(self, Qfalse);
+ if (default_tag == V_ASN1_BIT_STRING)
+ rb_ivar_set(self, sivUNUSED_BITS, INT2FIX(0));
return self;
}
-static int
-ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp)
-{
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
- if(!a) return 0;
- if(a->type == V_ASN1_BOOLEAN)
- return i2d_ASN1_BOOLEAN(a->value.boolean, pp);
-#endif
- return i2d_ASN1_TYPE(a, pp);
+static VALUE
+ossl_asn1eoc_initialize(VALUE self) {
+ VALUE tag, tagging, tag_class, value;
+ tag = INT2FIX(0);
+ tagging = Qnil;
+ tag_class = sym_UNIVERSAL;
+ value = rb_str_new("", 0);
+ ossl_asn1_set_tag(self, tag);
+ ossl_asn1_set_value(self, value);
+ ossl_asn1_set_tagging(self, tagging);
+ ossl_asn1_set_tag_class(self, tag_class);
+ ossl_asn1_set_indefinite_length(self, Qfalse);
+ return self;
}
-static void
-ossl_ASN1_TYPE_free(ASN1_TYPE *a)
+static VALUE
+ossl_asn1eoc_to_der(VALUE self)
{
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
- if(!a) return;
- if(a->type == V_ASN1_BOOLEAN){
- OPENSSL_free(a);
- return;
- }
-#endif
- ASN1_TYPE_free(a);
+ return rb_str_new("\0\0", 2);
}
+/*
+ * call-seq:
+ * asn1.to_der => DER-encoded String
+ *
+ * See ASN1Data#to_der for details.
+ */
static VALUE
ossl_asn1prim_to_der(VALUE self)
{
ASN1_TYPE *asn1;
- int tn, tc, explicit;
- long length, reallen;
- unsigned char *buf, *p;
+ long alllen, bodylen;
+ unsigned char *p0, *p1;
+ int j, tag, tc, state;
VALUE str;
- tn = NUM2INT(ossl_asn1_get_tag(self));
- tc = ossl_asn1_tag_class(self);
- explicit = ossl_asn1_is_explicit(self);
- asn1 = ossl_asn1_get_asn1type(self);
+ if (ossl_asn1_default_tag(self) == -1) {
+ str = ossl_asn1_get_value(self);
+ return to_der_internal(self, 0, 0, StringValue(str));
+ }
- length = ASN1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn);
- if(!(buf = OPENSSL_malloc(length))){
- ossl_ASN1_TYPE_free(asn1);
- ossl_raise(eASN1Error, "cannot alloc buffer");
+ asn1 = ossl_asn1_get_asn1type(self);
+ alllen = i2d_ASN1_TYPE(asn1, NULL);
+ if (alllen < 0) {
+ ASN1_TYPE_free(asn1);
+ ossl_raise(eASN1Error, "i2d_ASN1_TYPE");
}
- p = buf;
- if(tc == V_ASN1_UNIVERSAL) ossl_i2d_ASN1_TYPE(asn1, &p);
- else{
- if(explicit){
- ASN1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc);
- ossl_i2d_ASN1_TYPE(asn1, &p);
- }
- else{
- ossl_i2d_ASN1_TYPE(asn1, &p);
- *buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED);
- }
+ str = ossl_str_new(NULL, alllen, &state);
+ if (state) {
+ ASN1_TYPE_free(asn1);
+ rb_jump_tag(state);
}
- ossl_ASN1_TYPE_free(asn1);
- reallen = p - buf;
- assert(reallen <= length);
- str = ossl_buf2str(buf, reallen); /* buf will be free in ossl_buf2str */
+ p0 = p1 = (unsigned char *)RSTRING_PTR(str);
+ if (i2d_ASN1_TYPE(asn1, &p0) < 0) {
+ ASN1_TYPE_free(asn1);
+ ossl_raise(eASN1Error, "i2d_ASN1_TYPE");
+ }
+ ASN1_TYPE_free(asn1);
+ ossl_str_adjust(str, p0);
- return str;
+ /* Strip header since to_der_internal() wants only the payload */
+ j = ASN1_get_object((const unsigned char **)&p1, &bodylen, &tag, &tc, alllen);
+ if (j & 0x80)
+ ossl_raise(eASN1Error, "ASN1_get_object"); /* should not happen */
+
+ return to_der_internal(self, 0, 0, rb_str_drop_bytes(str, alllen - bodylen));
}
+/*
+ * call-seq:
+ * asn1.to_der => DER-encoded String
+ *
+ * See ASN1Data#to_der for details.
+ */
static VALUE
ossl_asn1cons_to_der(VALUE self)
{
- int tag, tn, tc, explicit;
- long seq_len, length;
- unsigned char *p;
- VALUE value, str;
-
- tag = ossl_asn1_default_tag(self);
- tn = NUM2INT(ossl_asn1_get_tag(self));
- tc = ossl_asn1_tag_class(self);
- explicit = ossl_asn1_is_explicit(self);
- value = join_der(ossl_asn1_get_value(self));
-
- seq_len = ASN1_object_size(1, RSTRING(value)->len, tag);
- length = ASN1_object_size(1, seq_len, tn);
- str = rb_str_new(0, length);
- p = RSTRING(str)->ptr;
- if(tc == V_ASN1_UNIVERSAL)
- ASN1_put_object(&p, 1, RSTRING(value)->len, tn, tc);
- else{
- if(explicit){
- ASN1_put_object(&p, 1, seq_len, tn, tc);
- ASN1_put_object(&p, 1, RSTRING(value)->len, tag, V_ASN1_UNIVERSAL);
- }
- else ASN1_put_object(&p, 1, RSTRING(value)->len, tn, tc);
+ VALUE ary, str;
+ long i;
+ int indef_len;
+
+ indef_len = RTEST(ossl_asn1_get_indefinite_length(self));
+ ary = rb_convert_type(ossl_asn1_get_value(self), T_ARRAY, "Array", "to_a");
+ str = rb_str_new(NULL, 0);
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ VALUE item = RARRAY_AREF(ary, i);
+
+ if (indef_len && rb_obj_is_kind_of(item, cASN1EndOfContent)) {
+ if (i != RARRAY_LEN(ary) - 1)
+ ossl_raise(eASN1Error, "illegal EOC octets in value");
+
+ /*
+ * EOC is not really part of the content, but we required to add one
+ * at the end in the past.
+ */
+ break;
+ }
+
+ item = ossl_to_der_if_possible(item);
+ StringValue(item);
+ rb_str_append(str, item);
}
- memcpy(p, RSTRING(value)->ptr, RSTRING(value)->len);
- p += RSTRING(value)->len;
- ossl_str_adjust(str, p);
- return str;
+ return to_der_internal(self, 1, indef_len, str);
}
+/*
+ * call-seq:
+ * asn1_ary.each { |asn1| block } => asn1_ary
+ *
+ * Calls the given block once for each element in self, passing that element
+ * as parameter _asn1_. If no block is given, an enumerator is returned
+ * instead.
+ *
+ * == Example
+ * asn1_ary.each do |asn1|
+ * puts asn1
+ * end
+ */
static VALUE
ossl_asn1cons_each(VALUE self)
{
- rb_ary_each(ossl_asn1_get_value(self));
+ rb_block_call(ossl_asn1_get_value(self), id_each, 0, 0, 0, 0);
+
return self;
}
+/*
+ * call-seq:
+ * OpenSSL::ASN1::ObjectId.register(object_id, short_name, long_name)
+ *
+ * This adds a new ObjectId to the internal tables. Where _object_id_ is the
+ * numerical form, _short_name_ is the short name, and _long_name_ is the long
+ * name.
+ *
+ * Returns +true+ if successful. Raises an OpenSSL::ASN1::ASN1Error if it fails.
+ *
+ */
static VALUE
ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln)
{
- StringValue(oid);
- StringValue(sn);
- StringValue(ln);
+ StringValueCStr(oid);
+ StringValueCStr(sn);
+ StringValueCStr(ln);
- if(!OBJ_create(RSTRING(oid)->ptr, RSTRING(sn)->ptr, RSTRING(ln)->ptr))
- ossl_raise(eASN1Error, NULL);
+ if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln)))
+ ossl_raise(eASN1Error, NULL);
return Qtrue;
}
+/*
+ * call-seq:
+ * oid.sn -> string
+ * oid.short_name -> string
+ *
+ * The short name of the ObjectId, as defined in <openssl/objects.h>.
+ */
static VALUE
ossl_asn1obj_get_sn(VALUE self)
{
@@ -1020,12 +1309,19 @@ ossl_asn1obj_get_sn(VALUE self)
int nid;
val = ossl_asn1_get_value(self);
- if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
- ret = rb_str_new2(OBJ_nid2sn(nid));
+ if ((nid = OBJ_txt2nid(StringValueCStr(val))) != NID_undef)
+ ret = rb_str_new2(OBJ_nid2sn(nid));
return ret;
}
+/*
+ * call-seq:
+ * oid.ln -> string
+ * oid.long_name -> string
+ *
+ * The long name of the ObjectId, as defined in <openssl/objects.h>.
+ */
static VALUE
ossl_asn1obj_get_ln(VALUE self)
{
@@ -1033,25 +1329,57 @@ ossl_asn1obj_get_ln(VALUE self)
int nid;
val = ossl_asn1_get_value(self);
- if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
- ret = rb_str_new2(OBJ_nid2ln(nid));
+ if ((nid = OBJ_txt2nid(StringValueCStr(val))) != NID_undef)
+ ret = rb_str_new2(OBJ_nid2ln(nid));
return ret;
}
static VALUE
+asn1obj_get_oid_i(VALUE vobj)
+{
+ return ossl_asn1obj_to_string_oid((const ASN1_OBJECT *)vobj);
+}
+
+/*
+ * call-seq:
+ * oid.oid -> string
+ *
+ * Returns a String representing the Object Identifier in the dot notation,
+ * e.g. "1.2.3.4.5"
+ */
+static VALUE
ossl_asn1obj_get_oid(VALUE self)
{
- VALUE val;
+ VALUE str;
ASN1_OBJECT *a1obj;
- char buf[128];
+ int state;
- val = ossl_asn1_get_value(self);
- a1obj = obj_to_asn1obj(val);
- OBJ_obj2txt(buf, sizeof(buf), a1obj, 1);
+ a1obj = ossl_to_asn1obj(ossl_asn1_get_value(self));
+ str = rb_protect(asn1obj_get_oid_i, (VALUE)a1obj, &state);
ASN1_OBJECT_free(a1obj);
+ if (state)
+ rb_jump_tag(state);
+ return str;
+}
- return rb_str_new2(buf);
+/*
+ * call-seq:
+ * oid == other_oid => true or false
+ *
+ * Returns +true+ if _other_oid_ is the same as _oid_.
+ */
+static VALUE
+ossl_asn1obj_eq(VALUE self, VALUE other)
+{
+ VALUE oid1, oid2;
+
+ if (!rb_obj_is_kind_of(other, cASN1ObjectId))
+ return Qfalse;
+
+ oid1 = ossl_asn1obj_get_oid(self);
+ oid2 = ossl_asn1obj_get_oid(other);
+ return rb_str_equal(oid1, oid2);
}
#define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \
@@ -1080,47 +1408,414 @@ OSSL_ASN1_IMPL_FACTORY_METHOD(UTCTime)
OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralizedTime)
OSSL_ASN1_IMPL_FACTORY_METHOD(Sequence)
OSSL_ASN1_IMPL_FACTORY_METHOD(Set)
+OSSL_ASN1_IMPL_FACTORY_METHOD(EndOfContent)
void
-Init_ossl_asn1()
+Init_ossl_asn1(void)
{
- VALUE ary;
- int i;
-
- sUNIVERSAL = rb_intern("UNIVERSAL");
- sCONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC");
- sAPPLICATION = rb_intern("APPLICATION");
- sPRIVATE = rb_intern("PRIVATE");
- sEXPLICIT = rb_intern("EXPLICIT");
- sIMPLICIT = rb_intern("IMPLICIT");
-
+#undef rb_intern
+
+ sym_UNIVERSAL = ID2SYM(rb_intern_const("UNIVERSAL"));
+ sym_CONTEXT_SPECIFIC = ID2SYM(rb_intern_const("CONTEXT_SPECIFIC"));
+ sym_APPLICATION = ID2SYM(rb_intern_const("APPLICATION"));
+ sym_PRIVATE = ID2SYM(rb_intern_const("PRIVATE"));
+ sym_EXPLICIT = ID2SYM(rb_intern_const("EXPLICIT"));
+ sym_IMPLICIT = ID2SYM(rb_intern_const("IMPLICIT"));
+
+ sivVALUE = rb_intern("@value");
+ sivTAG = rb_intern("@tag");
+ sivTAGGING = rb_intern("@tagging");
+ sivTAG_CLASS = rb_intern("@tag_class");
+ sivINDEFINITE_LENGTH = rb_intern("@indefinite_length");
+ sivUNUSED_BITS = rb_intern("@unused_bits");
+
+ /*
+ * Document-module: OpenSSL::ASN1
+ *
+ * Abstract Syntax Notation One (or ASN.1) is a notation syntax to
+ * describe data structures and is defined in ITU-T X.680. ASN.1 itself
+ * does not mandate any encoding or parsing rules, but usually ASN.1 data
+ * structures are encoded using the Distinguished Encoding Rules (DER) or
+ * less often the Basic Encoding Rules (BER) described in ITU-T X.690. DER
+ * and BER encodings are binary Tag-Length-Value (TLV) encodings that are
+ * quite concise compared to other popular data description formats such
+ * as XML, JSON etc.
+ * ASN.1 data structures are very common in cryptographic applications,
+ * e.g. X.509 public key certificates or certificate revocation lists
+ * (CRLs) are all defined in ASN.1 and DER-encoded. ASN.1, DER and BER are
+ * the building blocks of applied cryptography.
+ * The ASN1 module provides the necessary classes that allow generation
+ * of ASN.1 data structures and the methods to encode them using a DER
+ * encoding. The decode method allows parsing arbitrary BER-/DER-encoded
+ * data to a Ruby object that can then be modified and re-encoded at will.
+ *
+ * == ASN.1 class hierarchy
+ *
+ * The base class representing ASN.1 structures is ASN1Data. ASN1Data offers
+ * attributes to read and set the _tag_, the _tag_class_ and finally the
+ * _value_ of a particular ASN.1 item. Upon parsing, any tagged values
+ * (implicit or explicit) will be represented by ASN1Data instances because
+ * their "real type" can only be determined using out-of-band information
+ * from the ASN.1 type declaration. Since this information is normally
+ * known when encoding a type, all sub-classes of ASN1Data offer an
+ * additional attribute _tagging_ that allows to encode a value implicitly
+ * (+:IMPLICIT+) or explicitly (+:EXPLICIT+).
+ *
+ * === Constructive
+ *
+ * Constructive is, as its name implies, the base class for all
+ * constructed encodings, i.e. those that consist of several values,
+ * opposed to "primitive" encodings with just one single value. The value of
+ * an Constructive is always an Array.
+ *
+ * ==== ASN1::Set and ASN1::Sequence
+ *
+ * The most common constructive encodings are SETs and SEQUENCEs, which is
+ * why there are two sub-classes of Constructive representing each of
+ * them.
+ *
+ * === Primitive
+ *
+ * This is the super class of all primitive values. Primitive
+ * itself is not used when parsing ASN.1 data, all values are either
+ * instances of a corresponding sub-class of Primitive or they are
+ * instances of ASN1Data if the value was tagged implicitly or explicitly.
+ * Please cf. Primitive documentation for details on sub-classes and
+ * their respective mappings of ASN.1 data types to Ruby objects.
+ *
+ * == Possible values for _tagging_
+ *
+ * When constructing an ASN1Data object the ASN.1 type definition may
+ * require certain elements to be either implicitly or explicitly tagged.
+ * This can be achieved by setting the _tagging_ attribute manually for
+ * sub-classes of ASN1Data. Use the symbol +:IMPLICIT+ for implicit
+ * tagging and +:EXPLICIT+ if the element requires explicit tagging.
+ *
+ * == Possible values for _tag_class_
+ *
+ * It is possible to create arbitrary ASN1Data objects that also support
+ * a PRIVATE or APPLICATION tag class. Possible values for the _tag_class_
+ * attribute are:
+ * * +:UNIVERSAL+ (the default for untagged values)
+ * * +:CONTEXT_SPECIFIC+ (the default for tagged values)
+ * * +:APPLICATION+
+ * * +:PRIVATE+
+ *
+ * == Tag constants
+ *
+ * There is a constant defined for each universal tag:
+ * * OpenSSL::ASN1::EOC (0)
+ * * OpenSSL::ASN1::BOOLEAN (1)
+ * * OpenSSL::ASN1::INTEGER (2)
+ * * OpenSSL::ASN1::BIT_STRING (3)
+ * * OpenSSL::ASN1::OCTET_STRING (4)
+ * * OpenSSL::ASN1::NULL (5)
+ * * OpenSSL::ASN1::OBJECT (6)
+ * * OpenSSL::ASN1::ENUMERATED (10)
+ * * OpenSSL::ASN1::UTF8STRING (12)
+ * * OpenSSL::ASN1::SEQUENCE (16)
+ * * OpenSSL::ASN1::SET (17)
+ * * OpenSSL::ASN1::NUMERICSTRING (18)
+ * * OpenSSL::ASN1::PRINTABLESTRING (19)
+ * * OpenSSL::ASN1::T61STRING (20)
+ * * OpenSSL::ASN1::VIDEOTEXSTRING (21)
+ * * OpenSSL::ASN1::IA5STRING (22)
+ * * OpenSSL::ASN1::UTCTIME (23)
+ * * OpenSSL::ASN1::GENERALIZEDTIME (24)
+ * * OpenSSL::ASN1::GRAPHICSTRING (25)
+ * * OpenSSL::ASN1::ISO64STRING (26)
+ * * OpenSSL::ASN1::GENERALSTRING (27)
+ * * OpenSSL::ASN1::UNIVERSALSTRING (28)
+ * * OpenSSL::ASN1::BMPSTRING (30)
+ *
+ * == UNIVERSAL_TAG_NAME constant
+ *
+ * An Array that stores the name of a given tag number. These names are
+ * the same as the name of the tag constant that is additionally defined,
+ * e.g. <tt>UNIVERSAL_TAG_NAME[2] = "INTEGER"</tt> and <tt>OpenSSL::ASN1::INTEGER = 2</tt>.
+ *
+ * == Example usage
+ *
+ * === Decoding and viewing a DER-encoded file
+ * require 'openssl'
+ * require 'pp'
+ * der = File.binread('data.der')
+ * asn1 = OpenSSL::ASN1.decode(der)
+ * pp der
+ *
+ * === Creating an ASN.1 structure and DER-encoding it
+ * require 'openssl'
+ * version = OpenSSL::ASN1::Integer.new(1)
+ * # Explicitly 0-tagged implies context-specific tag class
+ * serial = OpenSSL::ASN1::Integer.new(12345, 0, :EXPLICIT, :CONTEXT_SPECIFIC)
+ * name = OpenSSL::ASN1::PrintableString.new('Data 1')
+ * sequence = OpenSSL::ASN1::Sequence.new( [ version, serial, name ] )
+ * der = sequence.to_der
+ */
mASN1 = rb_define_module_under(mOSSL, "ASN1");
+
+ /* Document-class: OpenSSL::ASN1::ASN1Error
+ *
+ * Generic error class for all errors raised in ASN1 and any of the
+ * classes defined in it.
+ */
eASN1Error = rb_define_class_under(mASN1, "ASN1Error", eOSSLError);
rb_define_module_function(mASN1, "traverse", ossl_asn1_traverse, 1);
rb_define_module_function(mASN1, "decode", ossl_asn1_decode, 1);
rb_define_module_function(mASN1, "decode_all", ossl_asn1_decode_all, 1);
- ary = rb_ary_new();
- rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary);
- for(i = 0; i < ossl_asn1_info_size; i++){
- if(ossl_asn1_info[i].name[0] == '[') continue;
- rb_define_const(mASN1, ossl_asn1_info[i].name, INT2NUM(i));
- rb_ary_store(ary, i, rb_str_new2(ossl_asn1_info[i].name));
+
+ VALUE ary = rb_ary_new_capa(ossl_asn1_info_size);
+ for (int i = 0; i < ossl_asn1_info_size; i++) {
+ const char *name = ossl_asn1_info[i].name;
+ if (name[0] == '[')
+ continue;
+ rb_define_const(mASN1, name, INT2NUM(i));
+ rb_ary_store(ary, i, rb_obj_freeze(rb_str_new_cstr(name)));
}
+ rb_obj_freeze(ary);
+ /*
+ * Array storing tag names at the tag's index.
+ */
+ rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary);
+ /* Document-class: OpenSSL::ASN1::ASN1Data
+ *
+ * The top-level class representing any ASN.1 object. When parsed by
+ * ASN1.decode, tagged values are always represented by an instance
+ * of ASN1Data.
+ *
+ * == The role of ASN1Data for parsing tagged values
+ *
+ * When encoding an ASN.1 type it is inherently clear what original
+ * type (e.g. INTEGER, OCTET STRING etc.) this value has, regardless
+ * of its tagging.
+ * But opposed to the time an ASN.1 type is to be encoded, when parsing
+ * them it is not possible to deduce the "real type" of tagged
+ * values. This is why tagged values are generally parsed into ASN1Data
+ * instances, but with a different outcome for implicit and explicit
+ * tagging.
+ *
+ * === Example of a parsed implicitly tagged value
+ *
+ * An implicitly 1-tagged INTEGER value will be parsed as an
+ * ASN1Data with
+ * * _tag_ equal to 1
+ * * _tag_class_ equal to +:CONTEXT_SPECIFIC+
+ * * _value_ equal to a String that carries the raw encoding
+ * of the INTEGER.
+ * This implies that a subsequent decoding step is required to
+ * completely decode implicitly tagged values.
+ *
+ * === Example of a parsed explicitly tagged value
+ *
+ * An explicitly 1-tagged INTEGER value will be parsed as an
+ * ASN1Data with
+ * * _tag_ equal to 1
+ * * _tag_class_ equal to +:CONTEXT_SPECIFIC+
+ * * _value_ equal to an Array with one single element, an
+ * instance of OpenSSL::ASN1::Integer, i.e. the inner element
+ * is the non-tagged primitive value, and the tagging is represented
+ * in the outer ASN1Data
+ *
+ * == Example - Decoding an implicitly tagged INTEGER
+ * int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT) # implicit 0-tagged
+ * seq = OpenSSL::ASN1::Sequence.new( [int] )
+ * der = seq.to_der
+ * asn1 = OpenSSL::ASN1.decode(der)
+ * # pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0
+ * # @indefinite_length=false,
+ * # @tag=16,
+ * # @tag_class=:UNIVERSAL,
+ * # @tagging=nil,
+ * # @value=
+ * # [#<OpenSSL::ASN1::ASN1Data:0x87326f4
+ * # @indefinite_length=false,
+ * # @tag=0,
+ * # @tag_class=:CONTEXT_SPECIFIC,
+ * # @value="\x01">]>
+ * raw_int = asn1.value[0]
+ * # manually rewrite tag and tag class to make it an UNIVERSAL value
+ * raw_int.tag = OpenSSL::ASN1::INTEGER
+ * raw_int.tag_class = :UNIVERSAL
+ * int2 = OpenSSL::ASN1.decode(raw_int)
+ * puts int2.value # => 1
+ *
+ * == Example - Decoding an explicitly tagged INTEGER
+ * int = OpenSSL::ASN1::Integer.new(1, 0, :EXPLICIT) # explicit 0-tagged
+ * seq = OpenSSL::ASN1::Sequence.new( [int] )
+ * der = seq.to_der
+ * asn1 = OpenSSL::ASN1.decode(der)
+ * # pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0
+ * # @indefinite_length=false,
+ * # @tag=16,
+ * # @tag_class=:UNIVERSAL,
+ * # @tagging=nil,
+ * # @value=
+ * # [#<OpenSSL::ASN1::ASN1Data:0x87326f4
+ * # @indefinite_length=false,
+ * # @tag=0,
+ * # @tag_class=:CONTEXT_SPECIFIC,
+ * # @value=
+ * # [#<OpenSSL::ASN1::Integer:0x85bf308
+ * # @indefinite_length=false,
+ * # @tag=2,
+ * # @tag_class=:UNIVERSAL
+ * # @tagging=nil,
+ * # @value=1>]>]>
+ * int2 = asn1.value[0].value[0]
+ * puts int2.value # => 1
+ */
cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
- rb_attr(cASN1Data, rb_intern("value"), 1, 1, Qtrue);
- rb_attr(cASN1Data, rb_intern("tag"), 1, 1, Qtrue);
- rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, Qtrue);
+ /*
+ * Carries the value of a ASN.1 type.
+ * Please confer Constructive and Primitive for the mappings between
+ * ASN.1 data types and Ruby classes.
+ */
+ rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
+ /*
+ * An Integer representing the tag number of this ASN1Data. Never +nil+.
+ */
+ rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
+ /*
+ * A Symbol representing the tag class of this ASN1Data. Never +nil+.
+ * See ASN1Data for possible values.
+ */
+ rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
+ /*
+ * Never +nil+. A boolean value indicating whether the encoding uses
+ * indefinite length (in the case of parsing) or whether an indefinite
+ * length form shall be used (in the encoding case).
+ * In DER, every value uses definite length form. But in scenarios where
+ * large amounts of data need to be transferred it might be desirable to
+ * have some kind of streaming support available.
+ * For example, huge OCTET STRINGs are preferably sent in smaller-sized
+ * chunks, each at a time.
+ * This is possible in BER by setting the length bytes of an encoding
+ * to zero and by this indicating that the following value will be
+ * sent in chunks. Indefinite length encodings are always constructed.
+ * The end of such a stream of chunks is indicated by sending a EOC
+ * (End of Content) tag. SETs and SEQUENCEs may use an indefinite length
+ * encoding, but also primitive types such as e.g. OCTET STRINGS or
+ * BIT STRINGS may leverage this functionality (cf. ITU-T X.690).
+ */
+ rb_attr(cASN1Data, rb_intern("indefinite_length"), 1, 1, 0);
+ rb_define_alias(cASN1Data, "infinite_length", "indefinite_length");
+ rb_define_alias(cASN1Data, "infinite_length=", "indefinite_length=");
rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
+ /* Document-class: OpenSSL::ASN1::Primitive
+ *
+ * The parent class for all primitive encodings. Attributes are the same as
+ * for ASN1Data, with the addition of _tagging_.
+ * Primitive values can never be encoded with indefinite length form, thus
+ * it is not possible to set the _indefinite_length_ attribute for Primitive
+ * and its sub-classes.
+ *
+ * == Primitive sub-classes and their mapping to Ruby classes
+ * * OpenSSL::ASN1::EndOfContent <=> _value_ is always +nil+
+ * * OpenSSL::ASN1::Boolean <=> _value_ is +true+ or +false+
+ * * OpenSSL::ASN1::Integer <=> _value_ is an OpenSSL::BN
+ * * OpenSSL::ASN1::BitString <=> _value_ is a String
+ * * OpenSSL::ASN1::OctetString <=> _value_ is a String
+ * * OpenSSL::ASN1::Null <=> _value_ is always +nil+
+ * * OpenSSL::ASN1::Object <=> _value_ is a String
+ * * OpenSSL::ASN1::Enumerated <=> _value_ is an OpenSSL::BN
+ * * OpenSSL::ASN1::UTF8String <=> _value_ is a String
+ * * OpenSSL::ASN1::NumericString <=> _value_ is a String
+ * * OpenSSL::ASN1::PrintableString <=> _value_ is a String
+ * * OpenSSL::ASN1::T61String <=> _value_ is a String
+ * * OpenSSL::ASN1::VideotexString <=> _value_ is a String
+ * * OpenSSL::ASN1::IA5String <=> _value_ is a String
+ * * OpenSSL::ASN1::UTCTime <=> _value_ is a Time
+ * * OpenSSL::ASN1::GeneralizedTime <=> _value_ is a Time
+ * * OpenSSL::ASN1::GraphicString <=> _value_ is a String
+ * * OpenSSL::ASN1::ISO64String <=> _value_ is a String
+ * * OpenSSL::ASN1::GeneralString <=> _value_ is a String
+ * * OpenSSL::ASN1::UniversalString <=> _value_ is a String
+ * * OpenSSL::ASN1::BMPString <=> _value_ is a String
+ *
+ * == OpenSSL::ASN1::BitString
+ *
+ * === Additional attributes
+ * _unused_bits_: if the underlying BIT STRING's
+ * length is a multiple of 8 then _unused_bits_ is 0. Otherwise
+ * _unused_bits_ indicates the number of bits that are to be ignored in
+ * the final octet of the BitString's _value_.
+ *
+ * == OpenSSL::ASN1::ObjectId
+ *
+ * NOTE: While OpenSSL::ASN1::ObjectId.new will allocate a new ObjectId,
+ * it is not typically allocated this way, but rather that are received from
+ * parsed ASN1 encodings.
+ *
+ * === Additional attributes
+ * * _sn_: the short name as defined in <openssl/objects.h>.
+ * * _ln_: the long name as defined in <openssl/objects.h>.
+ * * _oid_: the object identifier as a String, e.g. "1.2.3.4.5"
+ * * _short_name_: alias for _sn_.
+ * * _long_name_: alias for _ln_.
+ *
+ * == Examples
+ * With the Exception of OpenSSL::ASN1::EndOfContent, each Primitive class
+ * constructor takes at least one parameter, the _value_.
+ *
+ * === Creating EndOfContent
+ * eoc = OpenSSL::ASN1::EndOfContent.new
+ *
+ * === Creating any other Primitive
+ * prim = <class>.new(value) # <class> being one of the sub-classes except EndOfContent
+ * prim_zero_tagged_implicit = <class>.new(value, 0, :IMPLICIT)
+ * prim_zero_tagged_explicit = <class>.new(value, 0, :EXPLICIT)
+ */
cASN1Primitive = rb_define_class_under(mASN1, "Primitive", cASN1Data);
+ /*
+ * May be used as a hint for encoding a value either implicitly or
+ * explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+.
+ * _tagging_ is not set when a ASN.1 structure is parsed using
+ * OpenSSL::ASN1.decode.
+ */
rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue);
+ rb_undef_method(cASN1Primitive, "indefinite_length=");
+ rb_undef_method(cASN1Primitive, "infinite_length=");
rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1);
rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0);
+ /* Document-class: OpenSSL::ASN1::Constructive
+ *
+ * The parent class for all constructed encodings. The _value_ attribute
+ * of a Constructive is always an Array. Attributes are the same as
+ * for ASN1Data, with the addition of _tagging_.
+ *
+ * == SET and SEQUENCE
+ *
+ * Most constructed encodings come in the form of a SET or a SEQUENCE.
+ * These encodings are represented by one of the two sub-classes of
+ * Constructive:
+ * * OpenSSL::ASN1::Set
+ * * OpenSSL::ASN1::Sequence
+ * Please note that tagged sequences and sets are still parsed as
+ * instances of ASN1Data. Find further details on tagged values
+ * there.
+ *
+ * === Example - constructing a SEQUENCE
+ * int = OpenSSL::ASN1::Integer.new(1)
+ * str = OpenSSL::ASN1::PrintableString.new('abc')
+ * sequence = OpenSSL::ASN1::Sequence.new( [ int, str ] )
+ *
+ * === Example - constructing a SET
+ * int = OpenSSL::ASN1::Integer.new(1)
+ * str = OpenSSL::ASN1::PrintableString.new('abc')
+ * set = OpenSSL::ASN1::Set.new( [ int, str ] )
+ */
cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data);
rb_include_module(cASN1Constructive, rb_mEnumerable);
+ /*
+ * May be used as a hint for encoding a value either implicitly or
+ * explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+.
+ * _tagging_ is not set when a ASN.1 structure is parsed using
+ * OpenSSL::ASN1.decode.
+ */
rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue);
rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1);
rb_define_method(cASN1Constructive, "to_der", ossl_asn1cons_to_der, 0);
@@ -1156,11 +1851,54 @@ do{\
OSSL_ASN1_DEFINE_CLASS(Sequence, Constructive);
OSSL_ASN1_DEFINE_CLASS(Set, Constructive);
+ OSSL_ASN1_DEFINE_CLASS(EndOfContent, Data);
+
+
+ /* Document-class: OpenSSL::ASN1::ObjectId
+ *
+ * Represents the primitive object id for OpenSSL::ASN1
+ */
+#if 0
+ cASN1ObjectId = rb_define_class_under(mASN1, "ObjectId", cASN1Primitive); /* let rdoc know */
+#endif
rb_define_singleton_method(cASN1ObjectId, "register", ossl_asn1obj_s_register, 3);
rb_define_method(cASN1ObjectId, "sn", ossl_asn1obj_get_sn, 0);
rb_define_method(cASN1ObjectId, "ln", ossl_asn1obj_get_ln, 0);
rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
rb_define_alias(cASN1ObjectId, "short_name", "sn");
rb_define_alias(cASN1ObjectId, "long_name", "ln");
- rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, Qtrue);
+ rb_define_method(cASN1ObjectId, "==", ossl_asn1obj_eq, 1);
+ rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
+
+ rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0);
+ rb_define_method(cASN1EndOfContent, "to_der", ossl_asn1eoc_to_der, 0);
+
+ class_tag_map = rb_hash_new();
+ rb_gc_register_mark_object(class_tag_map);
+ rb_hash_aset(class_tag_map, cASN1EndOfContent, INT2NUM(V_ASN1_EOC));
+ rb_hash_aset(class_tag_map, cASN1Boolean, INT2NUM(V_ASN1_BOOLEAN));
+ rb_hash_aset(class_tag_map, cASN1Integer, INT2NUM(V_ASN1_INTEGER));
+ rb_hash_aset(class_tag_map, cASN1BitString, INT2NUM(V_ASN1_BIT_STRING));
+ rb_hash_aset(class_tag_map, cASN1OctetString, INT2NUM(V_ASN1_OCTET_STRING));
+ rb_hash_aset(class_tag_map, cASN1Null, INT2NUM(V_ASN1_NULL));
+ rb_hash_aset(class_tag_map, cASN1ObjectId, INT2NUM(V_ASN1_OBJECT));
+ rb_hash_aset(class_tag_map, cASN1Enumerated, INT2NUM(V_ASN1_ENUMERATED));
+ rb_hash_aset(class_tag_map, cASN1UTF8String, INT2NUM(V_ASN1_UTF8STRING));
+ rb_hash_aset(class_tag_map, cASN1Sequence, INT2NUM(V_ASN1_SEQUENCE));
+ rb_hash_aset(class_tag_map, cASN1Set, INT2NUM(V_ASN1_SET));
+ rb_hash_aset(class_tag_map, cASN1NumericString, INT2NUM(V_ASN1_NUMERICSTRING));
+ rb_hash_aset(class_tag_map, cASN1PrintableString, INT2NUM(V_ASN1_PRINTABLESTRING));
+ rb_hash_aset(class_tag_map, cASN1T61String, INT2NUM(V_ASN1_T61STRING));
+ rb_hash_aset(class_tag_map, cASN1VideotexString, INT2NUM(V_ASN1_VIDEOTEXSTRING));
+ rb_hash_aset(class_tag_map, cASN1IA5String, INT2NUM(V_ASN1_IA5STRING));
+ rb_hash_aset(class_tag_map, cASN1UTCTime, INT2NUM(V_ASN1_UTCTIME));
+ rb_hash_aset(class_tag_map, cASN1GeneralizedTime, INT2NUM(V_ASN1_GENERALIZEDTIME));
+ rb_hash_aset(class_tag_map, cASN1GraphicString, INT2NUM(V_ASN1_GRAPHICSTRING));
+ rb_hash_aset(class_tag_map, cASN1ISO64String, INT2NUM(V_ASN1_ISO64STRING));
+ rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING));
+ rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING));
+ rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING));
+ rb_obj_freeze(class_tag_map);
+
+ id_each = rb_intern_const("each");
}
diff --git a/ext/openssl/ossl_asn1.h b/ext/openssl/ossl_asn1.h
index 8aad9f970d..b605df8f3f 100644
--- a/ext/openssl/ossl_asn1.h
+++ b/ext/openssl/ossl_asn1.h
@@ -1,12 +1,11 @@
/*
- * $Id$
* 'OpenSSL for Ruby' team members
* Copyright (C) 2003
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_ASN1_H_)
#define _OSSL_ASN1_H_
@@ -14,45 +13,45 @@
/*
* ASN1_DATE conversions
*/
-VALUE asn1time_to_time(ASN1_TIME *);
-time_t time_to_time_t(VALUE);
+VALUE asn1time_to_time(const ASN1_TIME *);
+/* Splits VALUE to seconds and offset days. VALUE is typically a Time or an
+ * Integer. This is used when updating ASN1_*TIME with ASN1_TIME_adj() or
+ * X509_time_adj_ex(). We can't use ASN1_TIME_set() and X509_time_adj() because
+ * they have the Year 2038 issue on sizeof(time_t) == 4 environment */
+void ossl_time_split(VALUE, time_t *, int *);
/*
* ASN1_STRING conversions
*/
-VALUE asn1str_to_str(ASN1_STRING *);
+VALUE asn1str_to_str(const ASN1_STRING *);
/*
* ASN1_INTEGER conversions
*/
-VALUE asn1integer_to_num(ASN1_INTEGER *);
+VALUE asn1integer_to_num(const ASN1_INTEGER *);
ASN1_INTEGER *num_to_asn1integer(VALUE, ASN1_INTEGER *);
/*
+ * ASN1_OBJECT conversions
+ */
+ASN1_OBJECT *ossl_to_asn1obj(VALUE obj);
+/*
+ * Returns the short name if available, the dotted decimal notation otherwise.
+ * This is the most common way to return ASN1_OBJECT to Ruby.
+ */
+VALUE ossl_asn1obj_to_string(const ASN1_OBJECT *a1obj);
+/*
+ * However, some places use long names instead. This is likely unintentional,
+ * but we keep the current behavior in existing methods.
+ */
+VALUE ossl_asn1obj_to_string_long_name(const ASN1_OBJECT *a1obj);
+
+/*
* ASN1 module
*/
extern VALUE mASN1;
-extern VALUE eASN1Error;
extern VALUE cASN1Data;
-extern VALUE cASN1Primitive;
-extern VALUE cASN1Constructive;
-
-extern VALUE cASN1Boolean; /* BOOLEAN */
-extern VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
-extern VALUE cASN1BitString; /* BIT STRING */
-extern VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */
-extern VALUE cASN1NumericString, cASN1PrintableString;
-extern VALUE cASN1T61String, cASN1VideotexString;
-extern VALUE cASN1IA5String, cASN1GraphicString;
-extern VALUE cASN1ISO64String, cASN1GeneralString;
-extern VALUE cASN1UniversalString, cASN1BMPString;
-extern VALUE cASN1Null; /* NULL */
-extern VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
-extern VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
-extern VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
-
-ASN1_TYPE *ossl_asn1_get_asn1type(VALUE);
void Init_ossl_asn1(void);
diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c
index 9c9aa24197..cc03c5d5f7 100644
--- a/ext/openssl/ossl_bio.c
+++ b/ext/openssl/ossl_bio.c
@@ -1,73 +1,46 @@
/*
- * $Id$
* 'OpenSSL for Ruby' team members
* Copyright (C) 2003
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
BIO *
-ossl_obj2bio(VALUE obj)
+ossl_obj2bio(volatile VALUE *pobj)
{
+ VALUE obj = *pobj;
BIO *bio;
- if (TYPE(obj) == T_FILE) {
- OpenFile *fptr;
- GetOpenFile(obj, fptr);
- rb_io_check_readable(fptr);
- bio = BIO_new_fp(fptr->f, BIO_NOCLOSE);
- }
- else {
- StringValue(obj);
- bio = BIO_new_mem_buf(RSTRING(obj)->ptr, RSTRING(obj)->len);
- }
- if (!bio) ossl_raise(eOSSLError, NULL);
-
+ if (RB_TYPE_P(obj, T_FILE))
+ obj = rb_funcallv(obj, rb_intern("read"), 0, NULL);
+ StringValue(obj);
+ bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LENINT(obj));
+ if (!bio)
+ ossl_raise(eOSSLError, "BIO_new_mem_buf");
+ *pobj = obj;
return bio;
}
-BIO *
-ossl_protect_obj2bio(VALUE obj, int *status)
-{
- BIO *ret = NULL;
- ret = (BIO*)rb_protect((VALUE(*)_((VALUE)))ossl_obj2bio, obj, status);
- return ret;
-}
-
VALUE
-ossl_membio2str0(BIO *bio)
+ossl_membio2str(BIO *bio)
{
VALUE ret;
+ int state;
BUF_MEM *buf;
- BIO_get_mem_ptr(bio, &buf);
- ret = rb_str_new(buf->data, buf->length);
-
- return ret;
-}
-
-VALUE
-ossl_protect_membio2str(BIO *bio, int *status)
-{
- return rb_protect((VALUE(*)_((VALUE)))ossl_membio2str0, (VALUE)bio, status);
-}
-
-VALUE
-ossl_membio2str(BIO *bio)
-{
- VALUE ret;
- int status = 0;
+ if (BIO_get_mem_ptr(bio, &buf) <= 0) {
+ BIO_free(bio);
+ ossl_raise(eOSSLError, "BIO_get_mem_ptr");
+ }
- ret = ossl_protect_membio2str(bio, &status);
+ ret = ossl_str_new(buf->data, buf->length, &state);
BIO_free(bio);
- if(status) rb_jump_tag(status);
+ if (state)
+ rb_jump_tag(state);
return ret;
}
diff --git a/ext/openssl/ossl_bio.h b/ext/openssl/ossl_bio.h
index 2d8f675c5b..1b871f1cd7 100644
--- a/ext/openssl/ossl_bio.h
+++ b/ext/openssl/ossl_bio.h
@@ -1,21 +1,16 @@
/*
- * $Id$
* 'OpenSSL for Ruby' team members
* Copyright (C) 2003
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_BIO_H_)
#define _OSSL_BIO_H_
-BIO *ossl_obj2bio(VALUE);
-BIO *ossl_protect_obj2bio(VALUE,int*);
-VALUE ossl_membio2str0(BIO*);
+BIO *ossl_obj2bio(volatile VALUE *);
VALUE ossl_membio2str(BIO*);
-VALUE ossl_protect_membio2str(BIO*,int*);
#endif
-
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index 47a607e60f..9014f2df2b 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -1,154 +1,330 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Technorama team <oss-ruby@technorama.net>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
/* modified by Michal Rokos <m.rokos@sh.cvut.cz> */
#include "ossl.h"
-#define WrapBN(klass, obj, bn) do { \
- if (!bn) { \
- ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
- } \
- obj = Data_Wrap_Struct(klass, 0, BN_clear_free, bn); \
+#define NewBN(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_bn_type, 0)
+#define SetBN(obj, bn) do { \
+ if (!(bn)) { \
+ ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
+ } \
+ RTYPEDDATA_DATA(obj) = (bn); \
} while (0)
#define GetBN(obj, bn) do { \
- Data_Get_Struct(obj, BIGNUM, bn); \
- if (!bn) { \
- ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
- } \
+ TypedData_Get_Struct((obj), BIGNUM, &ossl_bn_type, (bn)); \
+ if (!(bn)) { \
+ ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
+ } \
} while (0)
-#define SafeGetBN(obj, bn) do { \
- OSSL_Check_Kind(obj, cBN); \
- GetBN(obj, bn); \
-} while (0)
+static void
+ossl_bn_free(void *ptr)
+{
+ BN_clear_free(ptr);
+}
+
+static const rb_data_type_t ossl_bn_type = {
+ "OpenSSL/BN",
+ {
+ 0, ossl_bn_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
+};
/*
* Classes
*/
VALUE cBN;
-VALUE eBNError;
+
+/* Document-class: OpenSSL::BNError
+ *
+ * Generic Error for all of OpenSSL::BN (big num)
+ */
+static VALUE eBNError;
/*
* Public
*/
VALUE
-ossl_bn_new(BIGNUM *bn)
+ossl_bn_new(const BIGNUM *bn)
{
BIGNUM *newbn;
VALUE obj;
- newbn = bn ? BN_dup(bn) : BN_new();
- if (!newbn) {
- ossl_raise(eBNError, NULL);
- }
- WrapBN(cBN, obj, newbn);
+ obj = NewBN(cBN);
+ newbn = BN_dup(bn);
+ if (!newbn)
+ ossl_raise(eBNError, "BN_dup");
+ SetBN(obj, newbn);
return obj;
}
-BIGNUM *
-GetBNPtr(VALUE obj)
-{
- BIGNUM *bn = NULL;
-
- if (RTEST(rb_obj_is_kind_of(obj, cBN))) {
- GetBN(obj, bn);
- } else switch (TYPE(obj)) {
- case T_FIXNUM:
- case T_BIGNUM:
- obj = rb_String(obj);
- if (!BN_dec2bn(&bn, StringValuePtr(obj))) {
- ossl_raise(eBNError, NULL);
- }
- WrapBN(cBN, obj, bn); /* Handle potencial mem leaks */
- break;
- default:
- ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN");
+static BIGNUM *
+integer_to_bnptr(VALUE obj, BIGNUM *orig)
+{
+ BIGNUM *bn;
+
+ if (FIXNUM_P(obj)) {
+ long i;
+ unsigned char bin[sizeof(long)];
+ long n = FIX2LONG(obj);
+ unsigned long un = labs(n);
+
+ for (i = sizeof(long) - 1; 0 <= i; i--) {
+ bin[i] = un & 0xff;
+ un >>= 8;
+ }
+
+ bn = BN_bin2bn(bin, sizeof(bin), orig);
+ if (!bn)
+ ossl_raise(eBNError, "BN_bin2bn");
+ if (n < 0)
+ BN_set_negative(bn, 1);
+ }
+ else { /* assuming Bignum */
+ size_t len = rb_absint_size(obj, NULL);
+ unsigned char *bin;
+ VALUE buf;
+ int sign;
+
+ if (INT_MAX < len) {
+ rb_raise(eBNError, "bignum too long");
+ }
+ bin = (unsigned char*)ALLOCV_N(unsigned char, buf, len);
+ sign = rb_integer_pack(obj, bin, len, 1, 0, INTEGER_PACK_BIG_ENDIAN);
+
+ bn = BN_bin2bn(bin, (int)len, orig);
+ ALLOCV_END(buf);
+ if (!bn)
+ ossl_raise(eBNError, "BN_bin2bn");
+ if (sign < 0)
+ BN_set_negative(bn, 1);
}
+
+ return bn;
+}
+
+static VALUE
+try_convert_to_bn(VALUE obj)
+{
+ BIGNUM *bn;
+ VALUE newobj = Qnil;
+
+ if (rb_obj_is_kind_of(obj, cBN))
+ return obj;
+ if (RB_INTEGER_TYPE_P(obj)) {
+ newobj = NewBN(cBN); /* Handle potential mem leaks */
+ bn = integer_to_bnptr(obj, NULL);
+ SetBN(newobj, bn);
+ }
+
+ return newobj;
+}
+
+BIGNUM *
+ossl_bn_value_ptr(volatile VALUE *ptr)
+{
+ VALUE tmp;
+ BIGNUM *bn;
+
+ tmp = try_convert_to_bn(*ptr);
+ if (NIL_P(tmp))
+ ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN");
+ GetBN(tmp, bn);
+ *ptr = tmp;
+
return bn;
}
/*
* Private
*/
-/*
- * BN_CTX - is used in more difficult math. ops
- * (Why just 1? Because Ruby itself isn't thread safe,
- * we don't need to care about threads)
- */
-BN_CTX *ossl_bn_ctx;
+
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+static void
+ossl_bn_ctx_free(void *ptr)
+{
+ BN_CTX *ctx = (BN_CTX *)ptr;
+ BN_CTX_free(ctx);
+}
+
+static struct rb_ractor_local_storage_type ossl_bn_ctx_key_type = {
+ NULL, // mark
+ ossl_bn_ctx_free,
+};
+
+static rb_ractor_local_key_t ossl_bn_ctx_key;
+
+BN_CTX *
+ossl_bn_ctx_get(void)
+{
+ // stored in ractor local storage
+
+ BN_CTX *ctx = rb_ractor_local_storage_ptr(ossl_bn_ctx_key);
+ if (!ctx) {
+ if (!(ctx = BN_CTX_new())) {
+ ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
+ }
+ rb_ractor_local_storage_ptr_set(ossl_bn_ctx_key, ctx);
+ }
+ return ctx;
+}
+#else
+// for ruby 2.x
+static BN_CTX *gv_ossl_bn_ctx;
+
+BN_CTX *
+ossl_bn_ctx_get(void)
+{
+ if (gv_ossl_bn_ctx == NULL) {
+ if (!(gv_ossl_bn_ctx = BN_CTX_new())) {
+ ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
+ }
+ }
+ return gv_ossl_bn_ctx;
+}
+
+void
+ossl_bn_ctx_free(void)
+{
+ BN_CTX_free(gv_ossl_bn_ctx);
+ gv_ossl_bn_ctx = NULL;
+}
+#endif
static VALUE
ossl_bn_alloc(VALUE klass)
{
BIGNUM *bn;
- VALUE obj;
-
+ VALUE obj = NewBN(klass);
+
if (!(bn = BN_new())) {
- ossl_raise(eBNError, NULL);
+ ossl_raise(eBNError, NULL);
}
- WrapBN(klass, obj, bn);
+ SetBN(obj, bn);
return obj;
}
+/*
+ * call-seq:
+ * OpenSSL::BN.new(bn) -> aBN
+ * OpenSSL::BN.new(integer) -> aBN
+ * OpenSSL::BN.new(string, base = 10) -> aBN
+ *
+ * Construct a new \OpenSSL BIGNUM object.
+ *
+ * If +bn+ is an Integer or OpenSSL::BN, a new instance of OpenSSL::BN
+ * representing the same value is returned. See also Integer#to_bn for the
+ * short-hand.
+ *
+ * If a String is given, the content will be parsed according to +base+.
+ *
+ * +string+::
+ * The string to be parsed.
+ * +base+::
+ * The format. Must be one of the following:
+ * - +0+ - MPI format. See the man page BN_mpi2bn(3) for details.
+ * - +2+ - Variable-length and big-endian binary encoding of a positive
+ * number.
+ * - +10+ - Decimal number representation, with a leading '-' for a negative
+ * number.
+ * - +16+ - Hexadecimal number representation, with a leading '-' for a
+ * negative number.
+ */
static VALUE
ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
{
BIGNUM *bn;
VALUE str, bs;
int base = 10;
+ char *ptr;
if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) {
- base = NUM2INT(bs);
+ base = NUM2INT(bs);
+ }
+
+ if (NIL_P(str)) {
+ ossl_raise(rb_eArgError, "invalid argument");
+ }
+
+ rb_check_frozen(self);
+ if (RB_INTEGER_TYPE_P(str)) {
+ GetBN(self, bn);
+ integer_to_bnptr(str, bn);
+
+ return self;
}
- StringValue(str);
- GetBN(self, bn);
- if (RTEST(rb_obj_is_kind_of(str, cBN))) {
- BIGNUM *other;
- GetBN(str, other); /* Safe - we checked kind_of? above */
- if (!BN_copy(bn, other)) {
- ossl_raise(eBNError, NULL);
- }
- return self;
+ if (RTEST(rb_obj_is_kind_of(str, cBN))) {
+ BIGNUM *other;
+
+ GetBN(self, bn);
+ GetBN(str, other); /* Safe - we checked kind_of? above */
+ if (!BN_copy(bn, other)) {
+ ossl_raise(eBNError, NULL);
+ }
+ return self;
}
+ GetBN(self, bn);
switch (base) {
- case 0:
- if (!BN_mpi2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) {
- ossl_raise(eBNError, NULL);
- }
- break;
- case 2:
- if (!BN_bin2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) {
- ossl_raise(eBNError, NULL);
- }
- break;
- case 10:
- if (!BN_dec2bn(&bn, RSTRING(str)->ptr)) {
- ossl_raise(eBNError, NULL);
- }
- break;
- case 16:
- if (!BN_hex2bn(&bn, RSTRING(str)->ptr)) {
- ossl_raise(eBNError, NULL);
- }
- break;
- default:
- ossl_raise(rb_eArgError, "illegal radix %d", base);
+ case 0:
+ ptr = StringValuePtr(str);
+ if (!BN_mpi2bn((unsigned char *)ptr, RSTRING_LENINT(str), bn)) {
+ ossl_raise(eBNError, NULL);
+ }
+ break;
+ case 2:
+ ptr = StringValuePtr(str);
+ if (!BN_bin2bn((unsigned char *)ptr, RSTRING_LENINT(str), bn)) {
+ ossl_raise(eBNError, NULL);
+ }
+ break;
+ case 10:
+ if (!BN_dec2bn(&bn, StringValueCStr(str))) {
+ ossl_raise(eBNError, NULL);
+ }
+ break;
+ case 16:
+ if (!BN_hex2bn(&bn, StringValueCStr(str))) {
+ ossl_raise(eBNError, NULL);
+ }
+ break;
+ default:
+ ossl_raise(rb_eArgError, "invalid radix %d", base);
}
return self;
}
+/*
+ * call-seq:
+ * bn.to_s(base = 10) -> string
+ *
+ * Returns the string representation of the bignum.
+ *
+ * BN.new can parse the encoded string to convert back into an OpenSSL::BN.
+ *
+ * +base+::
+ * The format. Must be one of the following:
+ * - +0+ - MPI format. See the man page BN_bn2mpi(3) for details.
+ * - +2+ - Variable-length and big-endian binary encoding. The sign of
+ * the bignum is ignored.
+ * - +10+ - Decimal number representation, with a leading '-' for a negative
+ * bignum.
+ * - +16+ - Hexadecimal number representation, with a leading '-' for a
+ * negative bignum.
+ */
static VALUE
ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
{
@@ -158,37 +334,41 @@ ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
char *buf;
if (rb_scan_args(argc, argv, "01", &bs) == 1) {
- base = NUM2INT(bs);
+ base = NUM2INT(bs);
}
GetBN(self, bn);
switch (base) {
- case 0:
- len = BN_bn2mpi(bn, NULL);
+ case 0:
+ len = BN_bn2mpi(bn, NULL);
str = rb_str_new(0, len);
- if (BN_bn2mpi(bn, RSTRING(str)->ptr) != len)
- ossl_raise(eBNError, NULL);
- break;
- case 2:
- len = BN_num_bytes(bn);
+ if (BN_bn2mpi(bn, (unsigned char *)RSTRING_PTR(str)) != len)
+ ossl_raise(eBNError, NULL);
+ break;
+ case 2:
+ len = BN_num_bytes(bn);
str = rb_str_new(0, len);
- if (BN_bn2bin(bn, RSTRING(str)->ptr) != len)
- ossl_raise(eBNError, NULL);
- break;
- case 10:
- if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL);
- str = ossl_buf2str(buf, strlen(buf));
- break;
- case 16:
- if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL);
- str = ossl_buf2str(buf, strlen(buf));
- break;
- default:
- ossl_raise(rb_eArgError, "illegal radix %d", base);
+ if (BN_bn2bin(bn, (unsigned char *)RSTRING_PTR(str)) != len)
+ ossl_raise(eBNError, NULL);
+ break;
+ case 10:
+ if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL);
+ str = ossl_buf2str(buf, rb_long2int(strlen(buf)));
+ break;
+ case 16:
+ if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL);
+ str = ossl_buf2str(buf, rb_long2int(strlen(buf)));
+ break;
+ default:
+ ossl_raise(rb_eArgError, "invalid radix %d", base);
}
return str;
}
+/*
+ * call-seq:
+ * bn.to_i => integer
+ */
static VALUE
ossl_bn_to_i(VALUE self)
{
@@ -198,10 +378,10 @@ ossl_bn_to_i(VALUE self)
GetBN(self, bn);
- if (!(txt = BN_bn2dec(bn))) {
- ossl_raise(eBNError, NULL);
+ if (!(txt = BN_bn2hex(bn))) {
+ ossl_raise(eBNError, NULL);
}
- num = rb_cstr_to_inum(txt, 10, Qtrue);
+ num = rb_cstr_to_inum(txt, 16, Qtrue);
OPENSSL_free(txt);
return num;
@@ -217,163 +397,333 @@ static VALUE
ossl_bn_coerce(VALUE self, VALUE other)
{
switch(TYPE(other)) {
- case T_STRING:
- self = ossl_bn_to_s(0, NULL, self);
- break;
- case T_FIXNUM:
- case T_BIGNUM:
- self = ossl_bn_to_i(self);
- break;
- default:
- if (!RTEST(rb_obj_is_kind_of(other, cBN))) {
- ossl_raise(rb_eTypeError, "Don't know how to coerce");
- }
+ case T_STRING:
+ self = ossl_bn_to_s(0, NULL, self);
+ break;
+ case T_FIXNUM:
+ case T_BIGNUM:
+ self = ossl_bn_to_i(self);
+ break;
+ default:
+ if (!RTEST(rb_obj_is_kind_of(other, cBN))) {
+ ossl_raise(rb_eTypeError, "Don't know how to coerce");
+ }
}
return rb_assoc_new(other, self);
}
-#define BIGNUM_BOOL1(func) \
- static VALUE \
- ossl_bn_##func(VALUE self) \
- { \
- BIGNUM *bn; \
- GetBN(self, bn); \
- if (BN_##func(bn)) { \
- return Qtrue; \
- } \
- return Qfalse; \
- }
-BIGNUM_BOOL1(is_zero);
-BIGNUM_BOOL1(is_one);
-BIGNUM_BOOL1(is_odd);
-
-#define BIGNUM_1c(func) \
- static VALUE \
- ossl_bn_##func(VALUE self) \
- { \
- BIGNUM *bn, *result; \
- VALUE obj; \
- GetBN(self, bn); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (!BN_##func(result, bn, ossl_bn_ctx)) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- WrapBN(CLASS_OF(self), obj, result); \
- return obj; \
- }
-BIGNUM_1c(sqr);
-
-#define BIGNUM_2(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE other) \
- { \
- BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
- VALUE obj; \
- GetBN(self, bn1); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (!BN_##func(result, bn1, bn2)) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- WrapBN(CLASS_OF(self), obj, result); \
- return obj; \
- }
-BIGNUM_2(add);
-BIGNUM_2(sub);
-
-#define BIGNUM_2c(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE other) \
- { \
- BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
- VALUE obj; \
- GetBN(self, bn1); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (!BN_##func(result, bn1, bn2, ossl_bn_ctx)) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- WrapBN(CLASS_OF(self), obj, result); \
- return obj; \
- }
-BIGNUM_2c(mul);
-BIGNUM_2c(mod);
-BIGNUM_2c(exp);
-BIGNUM_2c(gcd);
-BIGNUM_2c(mod_sqr);
-BIGNUM_2c(mod_inverse);
+#define BIGNUM_BOOL1(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self) \
+ { \
+ BIGNUM *bn; \
+ GetBN(self, bn); \
+ if (BN_##func(bn)) { \
+ return Qtrue; \
+ } \
+ return Qfalse; \
+ }
+/*
+ * Document-method: OpenSSL::BN#zero?
+ * call-seq:
+ * bn.zero? => true | false
+ */
+BIGNUM_BOOL1(is_zero)
+
+/*
+ * Document-method: OpenSSL::BN#one?
+ * call-seq:
+ * bn.one? => true | false
+ */
+BIGNUM_BOOL1(is_one)
+
+/*
+ * Document-method: OpenSSL::BN#odd?
+ * call-seq:
+ * bn.odd? => true | false
+ */
+BIGNUM_BOOL1(is_odd)
+
+/*
+ * call-seq:
+ * bn.negative? => true | false
+ */
+static VALUE
+ossl_bn_is_negative(VALUE self)
+{
+ BIGNUM *bn;
+
+ GetBN(self, bn);
+ if (BN_is_zero(bn))
+ return Qfalse;
+ return BN_is_negative(bn) ? Qtrue : Qfalse;
+}
+
+#define BIGNUM_1c(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self) \
+ { \
+ BIGNUM *bn, *result; \
+ VALUE obj; \
+ GetBN(self, bn); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (BN_##func(result, bn, ossl_bn_ctx) <= 0) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ SetBN(obj, result); \
+ return obj; \
+ }
+
+/*
+ * Document-method: OpenSSL::BN#sqr
+ * call-seq:
+ * bn.sqr => aBN
+ */
+BIGNUM_1c(sqr)
+
+#define BIGNUM_2(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (BN_##func(result, bn1, bn2) <= 0) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ SetBN(obj, result); \
+ return obj; \
+ }
+
+/*
+ * Document-method: OpenSSL::BN#+
+ * call-seq:
+ * bn + bn2 => aBN
+ */
+BIGNUM_2(add)
+
+/*
+ * Document-method: OpenSSL::BN#-
+ * call-seq:
+ * bn - bn2 => aBN
+ */
+BIGNUM_2(sub)
+
+#define BIGNUM_2c(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (BN_##func(result, bn1, bn2, ossl_bn_ctx) <= 0) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ SetBN(obj, result); \
+ return obj; \
+ }
+
+/*
+ * Document-method: OpenSSL::BN#*
+ * call-seq:
+ * bn * bn2 => aBN
+ */
+BIGNUM_2c(mul)
+
+/*
+ * Document-method: OpenSSL::BN#%
+ * call-seq:
+ * bn % bn2 => aBN
+ */
+BIGNUM_2c(mod)
+
+/*
+ * Document-method: OpenSSL::BN#**
+ * call-seq:
+ * bn ** bn2 => aBN
+ */
+BIGNUM_2c(exp)
+
+/*
+ * Document-method: OpenSSL::BN#gcd
+ * call-seq:
+ * bn.gcd(bn2) => aBN
+ */
+BIGNUM_2c(gcd)
+
+/*
+ * Document-method: OpenSSL::BN#mod_sqr
+ * call-seq:
+ * bn.mod_sqr(bn2) => aBN
+ */
+BIGNUM_2c(mod_sqr)
+
+#define BIGNUM_2cr(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_##func(NULL, bn1, bn2, ossl_bn_ctx))) \
+ ossl_raise(eBNError, NULL); \
+ SetBN(obj, result); \
+ return obj; \
+ }
+
+/*
+ * Document-method: OpenSSL::BN#mod_sqrt
+ * call-seq:
+ * bn.mod_sqrt(bn2) => aBN
+ */
+BIGNUM_2cr(mod_sqrt)
+
+/*
+ * Document-method: OpenSSL::BN#mod_inverse
+ * call-seq:
+ * bn.mod_inverse(bn2) => aBN
+ */
+BIGNUM_2cr(mod_inverse)
+
+/*
+ * call-seq:
+ * bn1 / bn2 => [result, remainder]
+ *
+ * Division of OpenSSL::BN instances
+ */
static VALUE
ossl_bn_div(VALUE self, VALUE other)
{
BIGNUM *bn1, *bn2 = GetBNPtr(other), *r1, *r2;
- VALUE obj1, obj2;
+ VALUE klass, obj1, obj2;
GetBN(self, bn1);
+ klass = rb_obj_class(self);
+ obj1 = NewBN(klass);
+ obj2 = NewBN(klass);
if (!(r1 = BN_new())) {
- ossl_raise(eBNError, NULL);
+ ossl_raise(eBNError, NULL);
}
if (!(r2 = BN_new())) {
- BN_free(r1);
- ossl_raise(eBNError, NULL);
+ BN_free(r1);
+ ossl_raise(eBNError, NULL);
}
if (!BN_div(r1, r2, bn1, bn2, ossl_bn_ctx)) {
- BN_free(r1);
- BN_free(r2);
- ossl_raise(eBNError, NULL);
+ BN_free(r1);
+ BN_free(r2);
+ ossl_raise(eBNError, NULL);
}
- WrapBN(CLASS_OF(self), obj1, r1);
- WrapBN(CLASS_OF(self), obj2, r2);
-
+ SetBN(obj1, r1);
+ SetBN(obj2, r2);
+
return rb_ary_new3(2, obj1, obj2);
}
-#define BIGNUM_3c(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \
- { \
- BIGNUM *bn1, *bn2 = GetBNPtr(other1); \
- BIGNUM *bn3 = GetBNPtr(other2), *result; \
- VALUE obj; \
- GetBN(self, bn1); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (!BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx)) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- WrapBN(CLASS_OF(self), obj, result); \
- return obj; \
- }
-BIGNUM_3c(mod_add);
-BIGNUM_3c(mod_sub);
-BIGNUM_3c(mod_mul);
-BIGNUM_3c(mod_exp);
-
-#define BIGNUM_BIT(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE bit) \
- { \
- BIGNUM *bn; \
- GetBN(self, bn); \
- if (!BN_##func(bn, NUM2INT(bit))) { \
- ossl_raise(eBNError, NULL); \
- } \
- return self; \
- }
-BIGNUM_BIT(set_bit);
-BIGNUM_BIT(clear_bit);
-BIGNUM_BIT(mask_bits);
+#define BIGNUM_3c(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other1); \
+ BIGNUM *bn3 = GetBNPtr(other2), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx) <= 0) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ SetBN(obj, result); \
+ return obj; \
+ }
+
+/*
+ * Document-method: OpenSSL::BN#mod_add
+ * call-seq:
+ * bn.mod_add(bn1, bn2) -> aBN
+ */
+BIGNUM_3c(mod_add)
+
+/*
+ * Document-method: OpenSSL::BN#mod_sub
+ * call-seq:
+ * bn.mod_sub(bn1, bn2) -> aBN
+ */
+BIGNUM_3c(mod_sub)
+
+/*
+ * Document-method: OpenSSL::BN#mod_mul
+ * call-seq:
+ * bn.mod_mul(bn1, bn2) -> aBN
+ */
+BIGNUM_3c(mod_mul)
+
+/*
+ * Document-method: OpenSSL::BN#mod_exp
+ * call-seq:
+ * bn.mod_exp(bn1, bn2) -> aBN
+ */
+BIGNUM_3c(mod_exp)
+
+#define BIGNUM_BIT(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE bit) \
+ { \
+ BIGNUM *bn; \
+ rb_check_frozen(self); \
+ GetBN(self, bn); \
+ if (BN_##func(bn, NUM2INT(bit)) <= 0) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ return self; \
+ }
+
+/*
+ * Document-method: OpenSSL::BN#set_bit!
+ * call-seq:
+ * bn.set_bit!(bit) -> self
+ */
+BIGNUM_BIT(set_bit)
+
+/*
+ * Document-method: OpenSSL::BN#clear_bit!
+ * call-seq:
+ * bn.clear_bit!(bit) -> self
+ */
+BIGNUM_BIT(clear_bit)
+/*
+ * Document-method: OpenSSL::BN#mask_bit!
+ * call-seq:
+ * bn.mask_bit!(bit) -> self
+ */
+BIGNUM_BIT(mask_bits)
+
+/*
+ * call-seq:
+ * bn.bit_set?(bit) => true | false
+ *
+ * Tests bit _bit_ in _bn_ and returns +true+ if set, +false+ if not set.
+ */
static VALUE
ossl_bn_is_bit_set(VALUE self, VALUE bit)
{
@@ -383,81 +733,147 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
b = NUM2INT(bit);
GetBN(self, bn);
if (BN_is_bit_set(bn, b)) {
- return Qtrue;
+ return Qtrue;
}
return Qfalse;
}
-#define BIGNUM_SHIFT(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE bits) \
- { \
- BIGNUM *bn, *result; \
- int b; \
- VALUE obj; \
- b = NUM2INT(bits); \
- GetBN(self, bn); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (!BN_##func(result, bn, b)) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- WrapBN(CLASS_OF(self), obj, result); \
- return obj; \
- }
-BIGNUM_SHIFT(lshift);
-BIGNUM_SHIFT(rshift);
-
-#define BIGNUM_RAND(func) \
- static VALUE \
- ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \
- { \
- BIGNUM *result; \
- int bottom = 0, top = 0, b; \
- VALUE bits, fill, odd, obj; \
- \
- switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { \
- case 3: \
- bottom = (odd == Qtrue) ? 1 : 0; \
- /* FALLTHROUGH */ \
- case 2: \
- top = FIX2INT(fill); \
- } \
- b = NUM2INT(bits); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (!BN_##func(result, b, top, bottom)) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- WrapBN(klass, obj, result); \
- return obj; \
- }
-BIGNUM_RAND(rand);
-BIGNUM_RAND(pseudo_rand);
-
-#define BIGNUM_RAND_RANGE(func) \
- static VALUE \
- ossl_bn_s_##func##_range(VALUE klass, VALUE range) \
- { \
- BIGNUM *bn = GetBNPtr(range), *result; \
- VALUE obj; \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (!BN_##func##_range(result, bn)) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- WrapBN(klass, obj, result); \
- return obj; \
- }
-BIGNUM_RAND_RANGE(rand);
-BIGNUM_RAND_RANGE(pseudo_rand);
+#define BIGNUM_SHIFT(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE bits) \
+ { \
+ BIGNUM *bn, *result; \
+ int b; \
+ VALUE obj; \
+ b = NUM2INT(bits); \
+ GetBN(self, bn); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (BN_##func(result, bn, b) <= 0) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ SetBN(obj, result); \
+ return obj; \
+ }
+/*
+ * Document-method: OpenSSL::BN#<<
+ * call-seq:
+ * bn << bits -> aBN
+ */
+BIGNUM_SHIFT(lshift)
+
+/*
+ * Document-method: OpenSSL::BN#>>
+ * call-seq:
+ * bn >> bits -> aBN
+ */
+BIGNUM_SHIFT(rshift)
+
+#define BIGNUM_SELF_SHIFT(func) \
+ static VALUE \
+ ossl_bn_self_##func(VALUE self, VALUE bits) \
+ { \
+ BIGNUM *bn; \
+ int b; \
+ rb_check_frozen(self); \
+ b = NUM2INT(bits); \
+ GetBN(self, bn); \
+ if (BN_##func(bn, bn, b) <= 0) \
+ ossl_raise(eBNError, NULL); \
+ return self; \
+ }
+
+/*
+ * Document-method: OpenSSL::BN#lshift!
+ * call-seq:
+ * bn.lshift!(bits) -> self
+ */
+BIGNUM_SELF_SHIFT(lshift)
+
+/*
+ * Document-method: OpenSSL::BN#rshift!
+ * call-seq:
+ * bn.rshift!(bits) -> self
+ */
+BIGNUM_SELF_SHIFT(rshift)
+
+/*
+ * call-seq:
+ * BN.rand(bits [, fill [, odd]]) -> aBN
+ *
+ * Generates a cryptographically strong pseudo-random number of +bits+.
+ *
+ * See also the man page BN_rand(3).
+ */
+static VALUE
+ossl_bn_s_rand(int argc, VALUE *argv, VALUE klass)
+{
+ BIGNUM *result;
+ int bottom = 0, top = 0, b;
+ VALUE bits, fill, odd, obj;
+
+ switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) {
+ case 3:
+ bottom = (odd == Qtrue) ? 1 : 0;
+ /* FALLTHROUGH */
+ case 2:
+ top = NUM2INT(fill);
+ }
+ b = NUM2INT(bits);
+ obj = NewBN(klass);
+ if (!(result = BN_new())) {
+ ossl_raise(eBNError, "BN_new");
+ }
+ if (BN_rand(result, b, top, bottom) <= 0) {
+ BN_free(result);
+ ossl_raise(eBNError, "BN_rand");
+ }
+ SetBN(obj, result);
+ return obj;
+}
+
+/*
+ * call-seq:
+ * BN.rand_range(range) -> aBN
+ *
+ * Generates a cryptographically strong pseudo-random number in the range
+ * 0...+range+.
+ *
+ * See also the man page BN_rand_range(3).
+ */
+static VALUE
+ossl_bn_s_rand_range(VALUE klass, VALUE range)
+{
+ BIGNUM *bn = GetBNPtr(range), *result;
+ VALUE obj = NewBN(klass);
+ if (!(result = BN_new()))
+ ossl_raise(eBNError, "BN_new");
+ if (BN_rand_range(result, bn) <= 0) {
+ BN_free(result);
+ ossl_raise(eBNError, "BN_rand_range");
+ }
+ SetBN(obj, result);
+ return obj;
+}
+
+/*
+ * call-seq:
+ * BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn
+ *
+ * Generates a random prime number of bit length _bits_. If _safe_ is set to
+ * +true+, generates a safe prime. If _add_ is specified, generates a prime that
+ * fulfills condition <tt>p % add = rem</tt>.
+ *
+ * === Parameters
+ * * _bits_ - integer
+ * * _safe_ - boolean
+ * * _add_ - BN
+ * * _rem_ - BN
+ */
static VALUE
ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
{
@@ -466,130 +882,316 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
VALUE vnum, vsafe, vadd, vrem, obj;
rb_scan_args(argc, argv, "13", &vnum, &vsafe, &vadd, &vrem);
-
+
num = NUM2INT(vnum);
if (vsafe == Qfalse) {
- safe = 0;
+ safe = 0;
}
if (!NIL_P(vadd)) {
- if (NIL_P(vrem)) {
- ossl_raise(rb_eArgError,
- "if ADD is specified, REM must be also given");
- }
- add = GetBNPtr(vadd);
- rem = GetBNPtr(vrem);
+ add = GetBNPtr(vadd);
+ rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem);
}
+ obj = NewBN(klass);
if (!(result = BN_new())) {
- ossl_raise(eBNError, NULL);
+ ossl_raise(eBNError, NULL);
}
- if (!BN_generate_prime(result, num, safe, add, rem, NULL, NULL)) {
- BN_free(result);
- ossl_raise(eBNError, NULL);
+ if (!BN_generate_prime_ex(result, num, safe, add, rem, NULL)) {
+ BN_free(result);
+ ossl_raise(eBNError, NULL);
}
- WrapBN(klass, obj, result);
-
- return obj;
+ SetBN(obj, result);
+
+ return obj;
}
-#define BIGNUM_NUM(func) \
- static VALUE \
- ossl_bn_##func(VALUE self) \
- { \
- BIGNUM *bn; \
- GetBN(self, bn); \
- return INT2FIX(BN_##func(bn)); \
+#define BIGNUM_NUM(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self) \
+ { \
+ BIGNUM *bn; \
+ GetBN(self, bn); \
+ return INT2NUM(BN_##func(bn)); \
}
-BIGNUM_NUM(num_bytes);
-BIGNUM_NUM(num_bits);
+/*
+ * Document-method: OpenSSL::BN#num_bytes
+ * call-seq:
+ * bn.num_bytes => integer
+ */
+BIGNUM_NUM(num_bytes)
+
+/*
+ * Document-method: OpenSSL::BN#num_bits
+ * call-seq:
+ * bn.num_bits => integer
+ */
+BIGNUM_NUM(num_bits)
+
+/* :nodoc: */
static VALUE
ossl_bn_copy(VALUE self, VALUE other)
{
BIGNUM *bn1, *bn2;
-
+
rb_check_frozen(self);
-
+
if (self == other) return self;
-
+
GetBN(self, bn1);
bn2 = GetBNPtr(other);
-
+
if (!BN_copy(bn1, bn2)) {
- ossl_raise(eBNError, NULL);
+ ossl_raise(eBNError, NULL);
}
return self;
}
-#define BIGNUM_CMP(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE other) \
- { \
- BIGNUM *bn1, *bn2 = GetBNPtr(other); \
- GetBN(self, bn1); \
- return INT2FIX(BN_##func(bn1, bn2)); \
+/*
+ * call-seq:
+ * +bn -> aBN
+ */
+static VALUE
+ossl_bn_uplus(VALUE self)
+{
+ VALUE obj;
+ BIGNUM *bn1, *bn2;
+
+ GetBN(self, bn1);
+ obj = NewBN(cBN);
+ bn2 = BN_dup(bn1);
+ if (!bn2)
+ ossl_raise(eBNError, "BN_dup");
+ SetBN(obj, bn2);
+
+ return obj;
+}
+
+/*
+ * call-seq:
+ * -bn -> aBN
+ */
+static VALUE
+ossl_bn_uminus(VALUE self)
+{
+ VALUE obj;
+ BIGNUM *bn1, *bn2;
+
+ GetBN(self, bn1);
+ obj = NewBN(cBN);
+ bn2 = BN_dup(bn1);
+ if (!bn2)
+ ossl_raise(eBNError, "BN_dup");
+ SetBN(obj, bn2);
+ BN_set_negative(bn2, !BN_is_negative(bn2));
+
+ return obj;
+}
+
+/*
+ * call-seq:
+ * bn.abs -> aBN
+ */
+static VALUE
+ossl_bn_abs(VALUE self)
+{
+ BIGNUM *bn1;
+
+ GetBN(self, bn1);
+ if (BN_is_negative(bn1)) {
+ return ossl_bn_uminus(self);
+ }
+ else {
+ return ossl_bn_uplus(self);
+ }
+}
+
+#define BIGNUM_CMP(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other); \
+ GetBN(self, bn1); \
+ return INT2NUM(BN_##func(bn1, bn2)); \
}
-BIGNUM_CMP(cmp);
-BIGNUM_CMP(ucmp);
+/*
+ * Document-method: OpenSSL::BN#cmp
+ * call-seq:
+ * bn.cmp(bn2) => integer
+ */
+/*
+ * Document-method: OpenSSL::BN#<=>
+ * call-seq:
+ * bn <=> bn2 => integer
+ */
+BIGNUM_CMP(cmp)
+
+/*
+ * Document-method: OpenSSL::BN#ucmp
+ * call-seq:
+ * bn.ucmp(bn2) => integer
+ */
+BIGNUM_CMP(ucmp)
+
+/*
+ * call-seq:
+ * bn == obj => true or false
+ *
+ * Returns +true+ only if _obj_ has the same value as _bn_. Contrast this
+ * with OpenSSL::BN#eql?, which requires obj to be OpenSSL::BN.
+ */
static VALUE
-ossl_bn_eql(VALUE self, VALUE other)
+ossl_bn_eq(VALUE self, VALUE other)
{
- if (ossl_bn_cmp(self, other) == INT2FIX(0)) {
- return Qtrue;
+ BIGNUM *bn1, *bn2;
+
+ GetBN(self, bn1);
+ other = try_convert_to_bn(other);
+ if (NIL_P(other))
+ return Qfalse;
+ GetBN(other, bn2);
+
+ if (!BN_cmp(bn1, bn2)) {
+ return Qtrue;
}
return Qfalse;
}
+/*
+ * call-seq:
+ * bn.eql?(obj) => true or false
+ *
+ * Returns <code>true</code> only if <i>obj</i> is a
+ * <code>OpenSSL::BN</code> with the same value as <i>bn</i>. Contrast this
+ * with OpenSSL::BN#==, which performs type conversions.
+ */
static VALUE
-ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
+ossl_bn_eql(VALUE self, VALUE other)
+{
+ BIGNUM *bn1, *bn2;
+
+ if (!rb_obj_is_kind_of(other, cBN))
+ return Qfalse;
+ GetBN(self, bn1);
+ GetBN(other, bn2);
+
+ return BN_cmp(bn1, bn2) ? Qfalse : Qtrue;
+}
+
+/*
+ * call-seq:
+ * bn.hash => Integer
+ *
+ * Returns a hash code for this object.
+ *
+ * See also Object#hash.
+ */
+static VALUE
+ossl_bn_hash(VALUE self)
{
BIGNUM *bn;
- VALUE vchecks;
- int checks = BN_prime_checks;
+ VALUE tmp, hash;
+ unsigned char *buf;
+ int len;
- if (rb_scan_args(argc, argv, "01", &vchecks) == 0) {
- checks = NUM2INT(vchecks);
+ GetBN(self, bn);
+ len = BN_num_bytes(bn);
+ buf = ALLOCV(tmp, len);
+ if (BN_bn2bin(bn, buf) != len) {
+ ALLOCV_END(tmp);
+ ossl_raise(eBNError, "BN_bn2bin");
}
+
+ hash = ST2FIX(rb_memhash(buf, len));
+ ALLOCV_END(tmp);
+
+ return hash;
+}
+
+/*
+ * call-seq:
+ * bn.prime? => true | false
+ * bn.prime?(checks) => true | false
+ *
+ * Performs a Miller-Rabin probabilistic primality test for +bn+.
+ *
+ * <b>+checks+ parameter is deprecated in version 3.0.</b> It has no effect.
+ */
+static VALUE
+ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
+{
+ BIGNUM *bn;
+ int ret;
+
+ rb_check_arity(argc, 0, 1);
GetBN(self, bn);
- switch (BN_is_prime(bn, checks, NULL, ossl_bn_ctx, NULL)) {
- case 1:
- return Qtrue;
- case 0:
- return Qfalse;
- default:
- ossl_raise(eBNError, NULL);
- }
- /* not reachable */
- return Qnil;
+
+#ifdef HAVE_BN_CHECK_PRIME
+ ret = BN_check_prime(bn, ossl_bn_ctx, NULL);
+ if (ret < 0)
+ ossl_raise(eBNError, "BN_check_prime");
+#else
+ ret = BN_is_prime_fasttest_ex(bn, BN_prime_checks, ossl_bn_ctx, 1, NULL);
+ if (ret < 0)
+ ossl_raise(eBNError, "BN_is_prime_fasttest_ex");
+#endif
+ return ret ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * bn.prime_fasttest? => true | false
+ * bn.prime_fasttest?(checks) => true | false
+ * bn.prime_fasttest?(checks, trial_div) => true | false
+ *
+ * Performs a Miller-Rabin probabilistic primality test for +bn+.
+ *
+ * <b>Deprecated in version 3.0.</b> Use #prime? instead.
+ *
+ * +checks+ and +trial_div+ parameters no longer have any effect.
+ */
static VALUE
ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
{
+ rb_check_arity(argc, 0, 2);
+ return ossl_bn_is_prime(0, argv, self);
+}
+
+/*
+ * call-seq:
+ * bn.get_flags(flags) => flags
+ *
+ * Returns the flags on the BN object.
+ * The argument is used as a bit mask.
+ *
+ * === Parameters
+ * * _flags_ - integer
+ */
+static VALUE
+ossl_bn_get_flags(VALUE self, VALUE arg)
+{
BIGNUM *bn;
- VALUE vchecks, vtrivdiv;
- int checks = BN_prime_checks, do_trial_division = 1;
+ GetBN(self, bn);
- rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv);
+ return INT2NUM(BN_get_flags(bn, NUM2INT(arg)));
+}
- if (!NIL_P(vchecks)) {
- checks = NUM2INT(vchecks);
- }
+/*
+ * call-seq:
+ * bn.set_flags(flags) => nil
+ *
+ * Enables the flags on the BN object.
+ * Currently, the flags argument can contain zero of OpenSSL::BN::CONSTTIME.
+ */
+static VALUE
+ossl_bn_set_flags(VALUE self, VALUE arg)
+{
+ BIGNUM *bn;
GetBN(self, bn);
- /* handle true/false */
- if (vtrivdiv == Qfalse) {
- do_trial_division = 0;
- }
- switch (BN_is_prime_fasttest(bn, checks, NULL, ossl_bn_ctx, NULL, do_trial_division)) {
- case 1:
- return Qtrue;
- case 0:
- return Qfalse;
- default:
- ossl_raise(eBNError, NULL);
- }
- /* not reachable */
+
+ rb_check_frozen(self);
+ BN_set_flags(bn, NUM2INT(arg));
return Qnil;
}
@@ -598,11 +1200,13 @@ ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
* (NOTE: ordering of methods is the same as in 'man bn')
*/
void
-Init_ossl_bn()
+Init_ossl_bn(void)
{
- if (!(ossl_bn_ctx = BN_CTX_new())) {
- ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
- }
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ ossl_bn_ctx_key = rb_ractor_local_storage_ptr_newkey(&ossl_bn_ctx_key_type);
+#else
+ ossl_bn_ctx_get();
+#endif
eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError);
@@ -610,8 +1214,8 @@ Init_ossl_bn()
rb_define_alloc_func(cBN, ossl_bn_alloc);
rb_define_method(cBN, "initialize", ossl_bn_initialize, -1);
-
- rb_define_copy_func(cBN, ossl_bn_copy);
+
+ rb_define_method(cBN, "initialize_copy", ossl_bn_copy, 1);
rb_define_method(cBN, "copy", ossl_bn_copy, 1);
/* swap (=coerce?) */
@@ -620,6 +1224,10 @@ Init_ossl_bn()
rb_define_method(cBN, "num_bits", ossl_bn_num_bits, 0);
/* num_bits_word */
+ rb_define_method(cBN, "+@", ossl_bn_uplus, 0);
+ rb_define_method(cBN, "-@", ossl_bn_uminus, 0);
+ rb_define_method(cBN, "abs", ossl_bn_abs, 0);
+
rb_define_method(cBN, "+", ossl_bn_add, 1);
rb_define_method(cBN, "-", ossl_bn_sub, 1);
rb_define_method(cBN, "*", ossl_bn_mul, 1);
@@ -632,6 +1240,7 @@ Init_ossl_bn()
rb_define_method(cBN, "mod_sub", ossl_bn_mod_sub, 2);
rb_define_method(cBN, "mod_mul", ossl_bn_mod_mul, 2);
rb_define_method(cBN, "mod_sqr", ossl_bn_mod_sqr, 1);
+ rb_define_method(cBN, "mod_sqrt", ossl_bn_mod_sqrt, 1);
rb_define_method(cBN, "**", ossl_bn_exp, 1);
rb_define_method(cBN, "mod_exp", ossl_bn_mod_exp, 2);
rb_define_method(cBN, "gcd", ossl_bn_gcd, 1);
@@ -646,36 +1255,58 @@ Init_ossl_bn()
rb_define_alias(cBN, "<=>", "cmp");
rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1);
rb_define_method(cBN, "eql?", ossl_bn_eql, 1);
- rb_define_alias(cBN, "==", "eql?");
- rb_define_alias(cBN, "===", "eql?");
+ rb_define_method(cBN, "hash", ossl_bn_hash, 0);
+ rb_define_method(cBN, "==", ossl_bn_eq, 1);
+ rb_define_alias(cBN, "===", "==");
rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0);
rb_define_method(cBN, "one?", ossl_bn_is_one, 0);
/* is_word */
rb_define_method(cBN, "odd?", ossl_bn_is_odd, 0);
+ rb_define_method(cBN, "negative?", ossl_bn_is_negative, 0);
/* zero
* one
* value_one - DON'T IMPL.
* set_word
* get_word */
-
+
rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1);
- rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1);
rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1);
- rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1);
+ rb_define_alias(rb_singleton_class(cBN), "pseudo_rand", "rand");
+ rb_define_alias(rb_singleton_class(cBN), "pseudo_rand_range", "rand_range");
rb_define_singleton_method(cBN, "generate_prime", ossl_bn_s_generate_prime, -1);
rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1);
+ rb_define_method(cBN, "prime_fasttest?", ossl_bn_is_prime_fasttest, -1);
rb_define_method(cBN, "set_bit!", ossl_bn_set_bit, 1);
rb_define_method(cBN, "clear_bit!", ossl_bn_clear_bit, 1);
rb_define_method(cBN, "bit_set?", ossl_bn_is_bit_set, 1);
rb_define_method(cBN, "mask_bits!", ossl_bn_mask_bits, 1);
rb_define_method(cBN, "<<", ossl_bn_lshift, 1);
- /* lshift1 - DON'T IMPL. */
rb_define_method(cBN, ">>", ossl_bn_rshift, 1);
+ rb_define_method(cBN, "lshift!", ossl_bn_self_lshift, 1);
+ rb_define_method(cBN, "rshift!", ossl_bn_self_rshift, 1);
+ /* lshift1 - DON'T IMPL. */
/* rshift1 - DON'T IMPL. */
+ rb_define_method(cBN, "get_flags", ossl_bn_get_flags, 1);
+ rb_define_method(cBN, "set_flags", ossl_bn_set_flags, 1);
+
+#ifdef BN_FLG_CONSTTIME
+ rb_define_const(cBN, "CONSTTIME", INT2NUM(BN_FLG_CONSTTIME));
+#endif
+ /* BN_FLG_MALLOCED and BN_FLG_STATIC_DATA seems for C programming.
+ * Allowing them leads to memory leak.
+ * So, for now, they are not exported
+#ifdef BN_FLG_MALLOCED
+ rb_define_const(cBN, "MALLOCED", INT2NUM(BN_FLG_MALLOCED));
+#endif
+#ifdef BN_FLG_STATIC_DATA
+ rb_define_const(cBN, "STATIC_DATA", INT2NUM(BN_FLG_STATIC_DATA));
+#endif
+ */
+
/*
* bn2bin
* bin2bn
@@ -693,7 +1324,7 @@ Init_ossl_bn()
rb_define_alias(cBN, "to_int", "to_i");
rb_define_method(cBN, "to_bn", ossl_bn_to_bn, 0);
rb_define_method(cBN, "coerce", ossl_bn_coerce, 1);
-
+
/*
* TODO:
* But how to: from_bin, from_mpi? PACK?
@@ -705,11 +1336,4 @@ Init_ossl_bn()
/* RECiProcal
* MONTgomery */
-
- /*
- * TODO:
- * Where to belong these?
- */
- rb_define_method(cBN, "prime_fasttest?", ossl_bn_is_prime_fasttest, -1);
}
-
diff --git a/ext/openssl/ossl_bn.h b/ext/openssl/ossl_bn.h
index 12aa484873..0c186bd1c5 100644
--- a/ext/openssl/ossl_bn.h
+++ b/ext/openssl/ossl_bn.h
@@ -1,22 +1,25 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_BN_H_)
#define _OSSL_BN_H_
extern VALUE cBN;
-extern VALUE eBNError;
-VALUE ossl_bn_new(BIGNUM *);
-BIGNUM *GetBNPtr(VALUE);
+BN_CTX *ossl_bn_ctx_get(void);
+#define ossl_bn_ctx ossl_bn_ctx_get()
+
+#define GetBNPtr(obj) ossl_bn_value_ptr(&(obj))
+
+VALUE ossl_bn_new(const BIGNUM *);
+BIGNUM *ossl_bn_value_ptr(volatile VALUE *);
void Init_ossl_bn(void);
-#endif /* _OSS_BN_H_ */
+#endif /* _OSS_BN_H_ */
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 67e7573ae4..e9dcd943e3 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -1,48 +1,103 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#define MakeCipher(obj, klass, ctx) \
- obj = Data_Make_Struct(klass, EVP_CIPHER_CTX, 0, ossl_cipher_free, ctx)
+#define NewCipher(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_cipher_type, 0)
+#define AllocCipher(obj, ctx) do { \
+ (ctx) = EVP_CIPHER_CTX_new(); \
+ if (!(ctx)) \
+ ossl_raise(rb_eRuntimeError, NULL); \
+ RTYPEDDATA_DATA(obj) = (ctx); \
+} while (0)
+#define GetCipherInit(obj, ctx) do { \
+ TypedData_Get_Struct((obj), EVP_CIPHER_CTX, &ossl_cipher_type, (ctx)); \
+} while (0)
#define GetCipher(obj, ctx) do { \
- Data_Get_Struct(obj, EVP_CIPHER_CTX, ctx); \
- if (!ctx) { \
- ossl_raise(rb_eRuntimeError, "Cipher not inititalized!"); \
+ GetCipherInit((obj), (ctx)); \
+ if (!(ctx)) { \
+ ossl_raise(rb_eRuntimeError, "Cipher not initialized!"); \
} \
} while (0)
-#define SafeGetCipher(obj, ctx) do { \
- OSSL_Check_Kind(obj, cCipher); \
- GetCipher(obj, ctx); \
-} while (0)
/*
* Classes
*/
-VALUE mCipher;
-VALUE cCipher;
-VALUE eCipherError;
+static VALUE cCipher;
+static VALUE eCipherError;
+static VALUE eAuthTagError;
+static ID id_auth_tag_len, id_key_set, id_cipher_holder;
static VALUE ossl_cipher_alloc(VALUE klass);
+static void ossl_cipher_free(void *ptr);
+
+static const rb_data_type_t ossl_cipher_type = {
+ "OpenSSL/Cipher",
+ {
+ 0, ossl_cipher_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+#ifdef OSSL_USE_PROVIDER
+static void
+ossl_evp_cipher_free(void *ptr)
+{
+ // This is safe to call against const EVP_CIPHER * returned by
+ // EVP_get_cipherbyname()
+ EVP_CIPHER_free(ptr);
+}
+
+static const rb_data_type_t ossl_evp_cipher_holder_type = {
+ "OpenSSL/EVP_CIPHER",
+ {
+ .dfree = ossl_evp_cipher_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+#endif
/*
* PUBLIC
*/
const EVP_CIPHER *
-GetCipherPtr(VALUE obj)
+ossl_evp_cipher_fetch(VALUE obj, volatile VALUE *holder)
{
- EVP_CIPHER_CTX *ctx;
-
- SafeGetCipher(obj, ctx);
+ *holder = Qnil;
+ if (rb_obj_is_kind_of(obj, cCipher)) {
+ EVP_CIPHER_CTX *ctx;
+ GetCipher(obj, ctx);
+ EVP_CIPHER *cipher = (EVP_CIPHER *)EVP_CIPHER_CTX_cipher(ctx);
+#ifdef OSSL_USE_PROVIDER
+ *holder = TypedData_Wrap_Struct(0, &ossl_evp_cipher_holder_type, NULL);
+ if (!EVP_CIPHER_up_ref(cipher))
+ ossl_raise(eCipherError, "EVP_CIPHER_up_ref");
+ RTYPEDDATA_DATA(*holder) = cipher;
+#endif
+ return cipher;
+ }
- return EVP_CIPHER_CTX_cipher(ctx);
+ const char *name = StringValueCStr(obj);
+ EVP_CIPHER *cipher = (EVP_CIPHER *)EVP_get_cipherbyname(name);
+#ifdef OSSL_USE_PROVIDER
+ if (!cipher) {
+ ossl_clear_error();
+ *holder = TypedData_Wrap_Struct(0, &ossl_evp_cipher_holder_type, NULL);
+ cipher = EVP_CIPHER_fetch(NULL, name, NULL);
+ RTYPEDDATA_DATA(*holder) = cipher;
+ }
+#endif
+ if (!cipher)
+ ossl_raise(eCipherError, "unsupported cipher algorithm: %"PRIsVALUE,
+ obj);
+ return cipher;
}
VALUE
@@ -51,11 +106,13 @@ ossl_cipher_new(const EVP_CIPHER *cipher)
VALUE ret;
EVP_CIPHER_CTX *ctx;
+ // NOTE: This does not set id_cipher_holder because this function should
+ // only be called from ossl_engine.c, which will not use any
+ // reference-counted ciphers.
ret = ossl_cipher_alloc(cCipher);
- GetCipher(ret, ctx);
- EVP_CIPHER_CTX_init(ctx);
+ AllocCipher(ret, ctx);
if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, NULL);
return ret;
}
@@ -64,83 +121,100 @@ ossl_cipher_new(const EVP_CIPHER *cipher)
* PRIVATE
*/
static void
-ossl_cipher_free(EVP_CIPHER_CTX *ctx)
+ossl_cipher_free(void *ptr)
{
- if (ctx) {
- EVP_CIPHER_CTX_cleanup(ctx);
- free(ctx);
- }
+ EVP_CIPHER_CTX_free(ptr);
}
static VALUE
ossl_cipher_alloc(VALUE klass)
{
- EVP_CIPHER_CTX *ctx;
- VALUE obj;
-
- MakeCipher(obj, klass, ctx);
- EVP_CIPHER_CTX_init(ctx);
-
- return obj;
+ return NewCipher(klass);
}
+/*
+ * call-seq:
+ * Cipher.new(string) -> cipher
+ *
+ * The string must contain a valid cipher name like "aes-256-cbc".
+ *
+ * A list of cipher names is available by calling OpenSSL::Cipher.ciphers.
+ */
static VALUE
ossl_cipher_initialize(VALUE self, VALUE str)
{
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher;
- char *name;
+ VALUE cipher_holder;
- name = StringValuePtr(str);
- GetCipher(self, ctx);
- if (!(cipher = EVP_get_cipherbyname(name))) {
- ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%s)", name);
+ GetCipherInit(self, ctx);
+ if (ctx) {
+ ossl_raise(rb_eRuntimeError, "Cipher already initialized!");
}
+ cipher = ossl_evp_cipher_fetch(str, &cipher_holder);
+ AllocCipher(self, ctx);
if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, "EVP_CipherInit_ex");
+ rb_ivar_set(self, id_cipher_holder, cipher_holder);
return self;
}
+
+/* :nodoc: */
static VALUE
ossl_cipher_copy(VALUE self, VALUE other)
{
EVP_CIPHER_CTX *ctx1, *ctx2;
-
+
rb_check_frozen(self);
if (self == other) return self;
- GetCipher(self, ctx1);
- SafeGetCipher(other, ctx2);
+ GetCipherInit(self, ctx1);
+ if (!ctx1) {
+ AllocCipher(self, ctx1);
+ }
+ GetCipher(other, ctx2);
if (EVP_CIPHER_CTX_copy(ctx1, ctx2) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, NULL);
return self;
}
-static void*
-add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
+static void
+add_cipher_name_to_ary(const OBJ_NAME *name, void *arg)
{
+ VALUE ary = (VALUE)arg;
rb_ary_push(ary, rb_str_new2(name->name));
- return NULL;
}
+/*
+ * call-seq:
+ * OpenSSL::Cipher.ciphers -> array[string...]
+ *
+ * Returns the names of all available ciphers in an array.
+ */
static VALUE
ossl_s_ciphers(VALUE self)
{
-#ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
VALUE ary;
ary = rb_ary_new();
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
- (void(*)(const OBJ_NAME*,void*))add_cipher_name_to_ary,
- (void*)ary);
+ add_cipher_name_to_ary,
+ (void*)ary);
return ary;
-#else
- rb_notimplement();
-#endif
}
+/*
+ * call-seq:
+ * cipher.reset -> self
+ *
+ * Fully resets the internal state of the Cipher. By using this, the same
+ * Cipher instance may be used several times for encryption or decryption tasks.
+ *
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1).
+ */
static VALUE
ossl_cipher_reset(VALUE self)
{
@@ -148,130 +222,221 @@ ossl_cipher_reset(VALUE self)
GetCipher(self, ctx);
if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1) != 1)
- ossl_raise(eCipherError, NULL);
-
+ ossl_raise(eCipherError, NULL);
+
return self;
}
static VALUE
-ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
+ossl_cipher_init(VALUE self, int enc)
{
EVP_CIPHER_CTX *ctx;
- unsigned char key[EVP_MAX_KEY_LENGTH], *p_key = NULL;
- unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv = NULL;
- VALUE pass, init_v;
-
- if(rb_scan_args(argc, argv, "02", &pass, &init_v) > 0){
- /*
- * oops. this code mistakes salt for IV.
- * We deprecated the arguments for this method, but we decided
- * keeping this behaviour for backward compatibility.
- */
- StringValue(pass);
- GetCipher(self, ctx);
- if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv));
- else{
- char *cname = rb_class2name(rb_obj_class(self));
- rb_warning("key derivation by %s#encrypt is deprecated; "
- "use %s::pkcs5_keyivgen instead", cname, cname);
- StringValue(init_v);
- if (EVP_MAX_IV_LENGTH > RSTRING(init_v)->len) {
- memset(iv, 0, EVP_MAX_IV_LENGTH);
- memcpy(iv, RSTRING(init_v)->ptr, RSTRING(init_v)->len);
- }
- else memcpy(iv, RSTRING(init_v)->ptr, sizeof(iv));
- }
- EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
- RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL);
- p_key = key;
- p_iv = iv;
- }
- else {
- GetCipher(self, ctx);
- }
- if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) {
- ossl_raise(eCipherError, NULL);
+
+ GetCipher(self, ctx);
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, enc) != 1) {
+ ossl_raise(eCipherError, "EVP_CipherInit_ex");
}
+ rb_ivar_set(self, id_key_set, Qfalse);
+
return self;
}
+/*
+ * call-seq:
+ * cipher.encrypt -> self
+ *
+ * Initializes the Cipher for encryption.
+ *
+ * Make sure to call either #encrypt or #decrypt before using the Cipher for
+ * any operation or setting any parameters.
+ *
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1).
+ */
static VALUE
-ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self)
+ossl_cipher_encrypt(VALUE self)
{
- return ossl_cipher_init(argc, argv, self, 1);
+ return ossl_cipher_init(self, 1);
}
+/*
+ * call-seq:
+ * cipher.decrypt -> self
+ *
+ * Initializes the Cipher for decryption.
+ *
+ * Make sure to call either #encrypt or #decrypt before using the Cipher for
+ * any operation or setting any parameters.
+ *
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0).
+ */
static VALUE
-ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self)
+ossl_cipher_decrypt(VALUE self)
{
- return ossl_cipher_init(argc, argv, self, 0);
+ return ossl_cipher_init(self, 0);
}
+/*
+ * call-seq:
+ * cipher.pkcs5_keyivgen(pass, salt = nil, iterations = 2048, digest = "MD5") -> nil
+ *
+ * Generates and sets the key/IV based on a password.
+ *
+ * *WARNING*: This method is deprecated and should not be used. This method
+ * corresponds to EVP_BytesToKey(), a non-standard OpenSSL extension of the
+ * legacy PKCS #5 v1.5 key derivation function. See OpenSSL::KDF for other
+ * options to derive keys from passwords.
+ *
+ * === Parameters
+ * * _salt_ must be an 8 byte string if provided.
+ * * _iterations_ is an integer with a default of 2048.
+ * * _digest_ is a Digest object that defaults to 'MD5'
+ */
static VALUE
ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
{
EVP_CIPHER_CTX *ctx;
const EVP_MD *digest;
- VALUE vpass, vsalt, viter, vdigest;
+ VALUE vpass, vsalt, viter, vdigest, md_holder;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH], *salt = NULL;
int iter;
rb_scan_args(argc, argv, "13", &vpass, &vsalt, &viter, &vdigest);
StringValue(vpass);
if(!NIL_P(vsalt)){
- StringValue(vsalt);
- if(RSTRING(vsalt)->len != PKCS5_SALT_LEN)
- rb_raise(eCipherError, "salt must be an 8-octet string");
- salt = RSTRING(vsalt)->ptr;
+ StringValue(vsalt);
+ if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN)
+ ossl_raise(eCipherError, "salt must be an 8-octet string");
+ salt = (unsigned char *)RSTRING_PTR(vsalt);
}
iter = NIL_P(viter) ? 2048 : NUM2INT(viter);
- digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest);
+ if (iter <= 0)
+ rb_raise(rb_eArgError, "iterations must be a positive integer");
+ digest = NIL_P(vdigest) ? EVP_md5() : ossl_evp_md_fetch(vdigest, &md_holder);
GetCipher(self, ctx);
EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt,
- RSTRING(vpass)->ptr, RSTRING(vpass)->len, iter, key, iv);
+ (unsigned char *)RSTRING_PTR(vpass), RSTRING_LENINT(vpass), iter, key, iv);
if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, NULL);
OPENSSL_cleanse(key, sizeof key);
OPENSSL_cleanse(iv, sizeof iv);
+ rb_ivar_set(self, id_key_set, Qtrue);
+
return Qnil;
}
-static VALUE
-ossl_cipher_update(VALUE self, VALUE data)
+static int
+ossl_cipher_update_long(EVP_CIPHER_CTX *ctx, unsigned char *out, long *out_len_ptr,
+ const unsigned char *in, long in_len)
{
- EVP_CIPHER_CTX *ctx;
- char *in;
- int in_len, out_len;
- VALUE str;
+ int out_part_len;
+ int limit = INT_MAX / 2 + 1;
+ long out_len = 0;
- StringValue(data);
- in = RSTRING(data)->ptr;
- if ((in_len = RSTRING(data)->len) == 0)
- rb_raise(rb_eArgError, "data must not be empty");
- GetCipher(self, ctx);
- str = rb_str_new(0, in_len+EVP_CIPHER_CTX_block_size(ctx));
- if (!EVP_CipherUpdate(ctx, RSTRING(str)->ptr, &out_len, in, in_len))
- ossl_raise(eCipherError, NULL);
- assert(out_len < RSTRING(str)->len);
- RSTRING(str)->len = out_len;
- RSTRING(str)->ptr[out_len] = 0;
+ do {
+ int in_part_len = in_len > limit ? limit : (int)in_len;
- return str;
+ if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
+ &out_part_len, in, in_part_len))
+ return 0;
+
+ out_len += out_part_len;
+ in += in_part_len;
+ } while ((in_len -= limit) > 0);
+
+ if (out_len_ptr)
+ *out_len_ptr = out_len;
+
+ return 1;
}
+/*
+ * call-seq:
+ * cipher.update(data [, buffer]) -> string or buffer
+ *
+ * Encrypts data in a streaming fashion. Hand consecutive blocks of data
+ * to the #update method in order to encrypt it. Returns the encrypted
+ * data chunk. When done, the output of Cipher#final should be additionally
+ * added to the result.
+ *
+ * If _buffer_ is given, the encryption/decryption result will be written to
+ * it. _buffer_ will be resized automatically.
+ *
+ * *NOTE*: When decrypting using an AEAD cipher, the integrity of the output
+ * is not verified until #final has been called.
+ */
static VALUE
-ossl_cipher_update_deprecated(VALUE self, VALUE data)
+ossl_cipher_update(int argc, VALUE *argv, VALUE self)
{
- char *cname;
+ EVP_CIPHER_CTX *ctx;
+ unsigned char *in;
+ long in_len, out_len;
+ VALUE data, str;
+
+ rb_scan_args(argc, argv, "11", &data, &str);
+
+ if (!RTEST(rb_attr_get(self, id_key_set)))
+ ossl_raise(eCipherError, "key not set");
+
+ StringValue(data);
+ in = (unsigned char *)RSTRING_PTR(data);
+ in_len = RSTRING_LEN(data);
+ GetCipher(self, ctx);
- cname = rb_class2name(rb_obj_class(self));
- rb_warning("%s#<< is deprecated; use %s#update instead", cname, cname);
- return ossl_cipher_update(self, data);
+ /*
+ * As of OpenSSL 3.2, there is no reliable way to determine the required
+ * output buffer size for arbitrary cipher modes.
+ * https://github.com/openssl/openssl/issues/22628
+ *
+ * in_len+block_size is usually sufficient, but AES key wrap with padding
+ * ciphers require in_len+15 even though they have a block size of 8 bytes.
+ *
+ * Using EVP_MAX_BLOCK_LENGTH (32) as a safe upper bound for ciphers
+ * currently implemented in OpenSSL, but this can change in the future.
+ */
+ if (in_len > LONG_MAX - EVP_MAX_BLOCK_LENGTH) {
+ ossl_raise(rb_eRangeError,
+ "data too big to make output buffer: %ld bytes", in_len);
+ }
+ out_len = in_len + EVP_MAX_BLOCK_LENGTH;
+
+ if (NIL_P(str))
+ str = rb_str_buf_new(out_len);
+ else {
+ StringValue(str);
+ if ((long)rb_str_capacity(str) >= out_len)
+ rb_str_modify(str);
+ else
+ rb_str_modify_expand(str, out_len - RSTRING_LEN(str));
+ }
+
+ if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str),
+ &out_len, in, in_len))
+ ossl_raise(eCipherError, "EVP_CipherUpdate");
+ rb_str_set_len(str, out_len);
+
+ return str;
}
-static VALUE
+/*
+ * call-seq:
+ * cipher.final -> string
+ *
+ * Returns the remaining data held in the cipher object. Further calls to
+ * Cipher#update or Cipher#final are invalid. This call should always
+ * be made as the last call of an encryption or decryption operation, after
+ * having fed the entire plaintext or ciphertext to the Cipher instance.
+ *
+ * When encrypting using an AEAD cipher, the authentication tag can be
+ * retrieved by #auth_tag after #final has been called.
+ *
+ * When decrypting using an AEAD cipher, this method will verify the integrity
+ * of the ciphertext and the associated data with the authentication tag,
+ * which must be set by #auth_tag= prior to calling this method.
+ * If the verification fails, CipherError will be raised.
+ */
+static VALUE
ossl_cipher_final(VALUE self)
{
EVP_CIPHER_CTX *ctx;
@@ -280,15 +445,29 @@ ossl_cipher_final(VALUE self)
GetCipher(self, ctx);
str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx));
- if (!EVP_CipherFinal_ex(ctx, RSTRING(str)->ptr, &out_len))
- ossl_raise(eCipherError, NULL);
- assert(out_len <= RSTRING(str)->len);
- RSTRING(str)->len = out_len;
- RSTRING(str)->ptr[out_len] = 0;
+ if (!EVP_CipherFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), &out_len)) {
+ /* For AEAD ciphers, this is likely an authentication failure */
+ if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER) {
+ /* For AEAD ciphers, EVP_CipherFinal_ex failures are authentication tag verification failures */
+ ossl_raise(eAuthTagError, "AEAD authentication tag verification failed");
+ }
+ else {
+ /* For non-AEAD ciphers */
+ ossl_raise(eCipherError, "cipher final failed");
+ }
+ }
+ rb_str_set_len(str, out_len);
return str;
}
+/*
+ * call-seq:
+ * cipher.name -> string
+ *
+ * Returns the short name of the cipher which may differ slightly from the
+ * original name provided.
+ */
static VALUE
ossl_cipher_name(VALUE self)
{
@@ -299,46 +478,308 @@ ossl_cipher_name(VALUE self)
return rb_str_new2(EVP_CIPHER_name(EVP_CIPHER_CTX_cipher(ctx)));
}
+/*
+ * call-seq:
+ * cipher.key = string
+ *
+ * Sets the cipher key. To generate a key, you should either use a secure
+ * random byte string or, if the key is to be derived from a password, you
+ * should rely on PBKDF2 functionality provided by OpenSSL::PKCS5. To
+ * generate a secure random-based key, Cipher#random_key may be used.
+ *
+ * Only call this method after calling Cipher#encrypt or Cipher#decrypt.
+ *
+ * See also the man page EVP_CipherInit_ex(3).
+ */
static VALUE
ossl_cipher_set_key(VALUE self, VALUE key)
{
EVP_CIPHER_CTX *ctx;
+ int key_len;
StringValue(key);
GetCipher(self, ctx);
- if (RSTRING(key)->len < EVP_CIPHER_CTX_key_length(ctx))
- ossl_raise(eCipherError, "key length too short");
+ key_len = EVP_CIPHER_CTX_key_length(ctx);
+ if (RSTRING_LEN(key) != key_len)
+ ossl_raise(rb_eArgError, "key must be %d bytes", key_len);
- if (EVP_CipherInit_ex(ctx, NULL, NULL, RSTRING(key)->ptr, NULL, -1) != 1)
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, (unsigned char *)RSTRING_PTR(key), NULL, -1) != 1)
ossl_raise(eCipherError, NULL);
+ rb_ivar_set(self, id_key_set, Qtrue);
+
return key;
}
+/*
+ * call-seq:
+ * cipher.iv = string
+ *
+ * Sets the cipher IV. Please note that since you should never be using ECB
+ * mode, an IV is always explicitly required and should be set prior to
+ * encryption. The IV itself can be safely transmitted in public.
+ *
+ * This method expects the String to have the length equal to #iv_len. To use
+ * a different IV length with an AEAD cipher, #iv_len= must be set prior to
+ * calling this method.
+ *
+ * *NOTE*: In OpenSSL API conventions, the IV value may correspond to the
+ * "nonce" instead in some cipher modes. Refer to the OpenSSL man pages for
+ * details.
+ *
+ * See also the man page EVP_CipherInit_ex(3).
+ */
static VALUE
ossl_cipher_set_iv(VALUE self, VALUE iv)
{
EVP_CIPHER_CTX *ctx;
+ int iv_len = 0;
StringValue(iv);
GetCipher(self, ctx);
- if (RSTRING(iv)->len < EVP_CIPHER_CTX_iv_length(ctx))
- ossl_raise(eCipherError, "iv length too short");
+ if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)
+ iv_len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
+ if (!iv_len)
+ iv_len = EVP_CIPHER_CTX_iv_length(ctx);
+ if (RSTRING_LEN(iv) != iv_len)
+ ossl_raise(rb_eArgError, "iv must be %d bytes", iv_len);
- if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, RSTRING(iv)->ptr, -1) != 1)
- ossl_raise(eCipherError, NULL);
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, (unsigned char *)RSTRING_PTR(iv), -1) != 1)
+ ossl_raise(eCipherError, NULL);
return iv;
}
+/*
+ * call-seq:
+ * cipher.authenticated? -> true | false
+ *
+ * Indicates whether this Cipher instance uses an AEAD mode.
+ */
static VALUE
-ossl_cipher_set_key_length(VALUE self, VALUE key_length)
+ossl_cipher_is_authenticated(VALUE self)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ GetCipher(self, ctx);
+
+ return (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER) ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * cipher.auth_data = string
+ *
+ * Sets additional authenticated data (AAD), also called associated data, for
+ * this Cipher. This method is available for AEAD ciphers.
+ *
+ * The contents of this field should be non-sensitive data which will be
+ * added to the ciphertext to generate the authentication tag which validates
+ * the contents of the ciphertext.
+ *
+ * This method must be called after #key= and #iv= have been set, but before
+ * starting actual encryption or decryption with #update. In some cipher modes,
+ * #auth_tag_len= and #ccm_data_len= may also need to be called before this
+ * method.
+ *
+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
+ * This method internally calls EVP_CipherUpdate() with the output buffer
+ * set to NULL.
+ */
+static VALUE
+ossl_cipher_set_auth_data(VALUE self, VALUE data)
+{
+ EVP_CIPHER_CTX *ctx;
+ unsigned char *in;
+ long in_len, out_len;
+
+ StringValue(data);
+
+ in = (unsigned char *) RSTRING_PTR(data);
+ in_len = RSTRING_LEN(data);
+
+ GetCipher(self, ctx);
+ if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
+ ossl_raise(eCipherError, "AEAD not supported by this cipher");
+
+ if (!ossl_cipher_update_long(ctx, NULL, &out_len, in, in_len))
+ ossl_raise(eCipherError, "couldn't set additional authenticated data");
+
+ return data;
+}
+
+/*
+ * call-seq:
+ * cipher.auth_tag(tag_len = 16) -> String
+ *
+ * Gets the generated authentication tag. This method is available for AEAD
+ * ciphers, and should be called after encryption has been finalized by calling
+ * #final.
+ *
+ * The returned tag will be _tag_len_ bytes long. Some cipher modes require
+ * the desired length in advance using a separate call to #auth_tag_len=,
+ * before starting encryption.
+ *
+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
+ * This method internally calls EVP_CIPHER_CTX_ctrl() with
+ * EVP_CTRL_AEAD_GET_TAG.
+ */
+static VALUE
+ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self)
+{
+ VALUE vtag_len, ret;
+ EVP_CIPHER_CTX *ctx;
+ int tag_len = 16;
+
+ rb_scan_args(argc, argv, "01", &vtag_len);
+ if (NIL_P(vtag_len))
+ vtag_len = rb_attr_get(self, id_auth_tag_len);
+ if (!NIL_P(vtag_len))
+ tag_len = NUM2INT(vtag_len);
+
+ GetCipher(self, ctx);
+
+ if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
+ ossl_raise(eCipherError, "authentication tag not supported by this cipher");
+
+ ret = rb_str_new(NULL, tag_len);
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag_len, RSTRING_PTR(ret)) <= 0)
+ ossl_raise(eCipherError, "retrieving the authentication tag failed");
+
+ return ret;
+}
+
+/*
+ * call-seq:
+ * cipher.auth_tag = string
+ *
+ * Sets the authentication tag to verify the integrity of the ciphertext.
+ *
+ * The authentication tag must be set before #final is called. The tag is
+ * verified during the #final call.
+ *
+ * Note that, for CCM mode and OCB mode, the expected length of the tag must
+ * be set before starting decryption by a separate call to #auth_tag_len=.
+ * The content of the tag can be provided at any time before #final is called.
+ *
+ * *NOTE*: The caller must ensure that the String passed to this method has
+ * the desired length. Some cipher modes support variable tag lengths, and
+ * this method may accept a truncated tag without raising an exception.
+ *
+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
+ * This method internally calls EVP_CIPHER_CTX_ctrl() with
+ * EVP_CTRL_AEAD_SET_TAG.
+ */
+static VALUE
+ossl_cipher_set_auth_tag(VALUE self, VALUE vtag)
+{
+ EVP_CIPHER_CTX *ctx;
+ unsigned char *tag;
+ int tag_len;
+
+ StringValue(vtag);
+ tag = (unsigned char *) RSTRING_PTR(vtag);
+ tag_len = RSTRING_LENINT(vtag);
+
+ GetCipher(self, ctx);
+ if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
+ ossl_raise(eCipherError, "authentication tag not supported by this cipher");
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, tag) <= 0)
+ ossl_raise(eCipherError, "unable to set AEAD tag");
+
+ return vtag;
+}
+
+/*
+ * call-seq:
+ * cipher.auth_tag_len = integer
+ *
+ * Sets the length of the expected authentication tag for this Cipher. This
+ * method is available for some of AEAD ciphers that require the length to be
+ * set before starting encryption or decryption, such as CCM mode or OCB mode.
+ *
+ * For CCM mode and OCB mode, the tag length must be set before #iv= is set.
+ *
+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
+ * This method internally calls EVP_CIPHER_CTX_ctrl() with
+ * EVP_CTRL_AEAD_SET_TAG and a NULL buffer.
+ */
+static VALUE
+ossl_cipher_set_auth_tag_len(VALUE self, VALUE vlen)
{
+ int tag_len = NUM2INT(vlen);
EVP_CIPHER_CTX *ctx;
+
+ GetCipher(self, ctx);
+ if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
+ ossl_raise(eCipherError, "AEAD not supported by this cipher");
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, NULL) <= 0)
+ ossl_raise(eCipherError, "unable to set authentication tag length");
+
+ /* for #auth_tag */
+ rb_ivar_set(self, id_auth_tag_len, INT2NUM(tag_len));
+
+ return vlen;
+}
+
+/*
+ * call-seq:
+ * cipher.iv_len = integer
+ *
+ * Sets the IV/nonce length for this Cipher. This method is available for AEAD
+ * ciphers that support variable IV lengths. This method can be called if a
+ * different IV length than OpenSSL's default is desired, prior to calling
+ * #iv=.
+ *
+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
+ * This method internally calls EVP_CIPHER_CTX_ctrl() with
+ * EVP_CTRL_AEAD_SET_IVLEN.
+ */
+static VALUE
+ossl_cipher_set_iv_length(VALUE self, VALUE iv_length)
+{
+ int len = NUM2INT(iv_length);
+ EVP_CIPHER_CTX *ctx;
+
+ GetCipher(self, ctx);
+ if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
+ ossl_raise(eCipherError, "cipher does not support AEAD");
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, len, NULL) <= 0)
+ ossl_raise(eCipherError, "unable to set IV length");
+
+ /*
+ * EVP_CIPHER_CTX_iv_length() returns the default length. So we need to save
+ * the length somewhere. Luckily currently we aren't using app_data.
+ */
+ EVP_CIPHER_CTX_set_app_data(ctx, (void *)(VALUE)len);
+
+ return iv_length;
+}
+
+/*
+ * call-seq:
+ * cipher.key_len = integer
+ *
+ * Sets the key length of the cipher. If the cipher is a fixed length cipher
+ * then attempting to set the key length to any value other than the fixed
+ * value is an error.
+ *
+ * Under normal circumstances you do not need to call this method (and
+ * probably shouldn't).
+ *
+ * See EVP_CIPHER_CTX_set_key_length for further information.
+ */
+static VALUE
+ossl_cipher_set_key_length(VALUE self, VALUE key_length)
+{
int len = NUM2INT(key_length);
-
+ EVP_CIPHER_CTX *ctx;
+
GetCipher(self, ctx);
if (EVP_CIPHER_CTX_set_key_length(ctx, len) != 1)
ossl_raise(eCipherError, NULL);
@@ -346,61 +787,351 @@ ossl_cipher_set_key_length(VALUE self, VALUE key_length)
return key_length;
}
+// TODO: Should #padding= take a boolean value instead?
+/*
+ * call-seq:
+ * cipher.padding = 1 or 0
+ *
+ * Enables or disables padding. By default encryption operations are padded
+ * using standard block padding and the padding is checked and removed when
+ * decrypting. If the pad parameter is zero then no padding is performed, the
+ * total amount of data encrypted or decrypted must then be a multiple of the
+ * block size or an error will occur.
+ *
+ * See EVP_CIPHER_CTX_set_padding for further information.
+ */
static VALUE
ossl_cipher_set_padding(VALUE self, VALUE padding)
{
-#if defined(HAVE_EVP_CIPHER_CTX_SET_PADDING)
EVP_CIPHER_CTX *ctx;
int pad = NUM2INT(padding);
GetCipher(self, ctx);
if (EVP_CIPHER_CTX_set_padding(ctx, pad) != 1)
- ossl_raise(eCipherError, NULL);
-#else
- rb_notimplement();
-#endif
+ ossl_raise(eCipherError, NULL);
return padding;
}
-#define CIPHER_0ARG_INT(func) \
- static VALUE \
- ossl_cipher_##func(VALUE self) \
- { \
- EVP_CIPHER_CTX *ctx; \
- GetCipher(self, ctx); \
- return INT2NUM(EVP_CIPHER_##func(EVP_CIPHER_CTX_cipher(ctx))); \
- }
-CIPHER_0ARG_INT(key_length)
-CIPHER_0ARG_INT(iv_length)
-CIPHER_0ARG_INT(block_size)
+/*
+ * call-seq:
+ * cipher.key_len -> integer
+ *
+ * Returns the key length in bytes of the Cipher.
+ */
+static VALUE
+ossl_cipher_key_length(VALUE self)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ GetCipher(self, ctx);
+
+ return INT2NUM(EVP_CIPHER_CTX_key_length(ctx));
+}
+
+/*
+ * call-seq:
+ * cipher.iv_len -> integer
+ *
+ * Returns the expected length in bytes for an IV for this Cipher.
+ */
+static VALUE
+ossl_cipher_iv_length(VALUE self)
+{
+ EVP_CIPHER_CTX *ctx;
+ int len = 0;
+
+ GetCipher(self, ctx);
+ if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)
+ len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
+ if (!len)
+ len = EVP_CIPHER_CTX_iv_length(ctx);
+
+ return INT2NUM(len);
+}
+
+/*
+ * call-seq:
+ * cipher.block_size -> integer
+ *
+ * Returns the size in bytes of the blocks on which this Cipher operates on.
+ */
+static VALUE
+ossl_cipher_block_size(VALUE self)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ GetCipher(self, ctx);
+
+ return INT2NUM(EVP_CIPHER_CTX_block_size(ctx));
+}
+
+/*
+ * call-seq:
+ * cipher.ccm_data_len = integer
+ *
+ * Sets the total length of the plaintext / ciphertext message that will be
+ * processed by #update in CCM mode.
+ *
+ * Make sure to call this method after #key= and #iv= have been set, and
+ * before #auth_data= or #update are called.
+ *
+ * This method is only available for CCM mode ciphers.
+ *
+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
+ */
+static VALUE
+ossl_cipher_set_ccm_data_len(VALUE self, VALUE data_len)
+{
+ int in_len, out_len;
+ EVP_CIPHER_CTX *ctx;
+
+ in_len = NUM2INT(data_len);
+
+ GetCipher(self, ctx);
+ if (EVP_CipherUpdate(ctx, NULL, &out_len, NULL, in_len) != 1)
+ ossl_raise(eCipherError, NULL);
+
+ return data_len;
+}
/*
* INIT
*/
-void
+void
Init_ossl_cipher(void)
{
- mCipher = rb_define_module_under(mOSSL, "Cipher");
- eCipherError = rb_define_class_under(mOSSL, "CipherError", eOSSLError);
- cCipher = rb_define_class_under(mCipher, "Cipher", rb_cObject);
+ /* Document-class: OpenSSL::Cipher
+ *
+ * Provides symmetric algorithms for encryption and decryption. The
+ * algorithms that are available depend on the particular version
+ * of OpenSSL that is installed.
+ *
+ * === Listing all supported algorithms
+ *
+ * A list of supported algorithms can be obtained by
+ *
+ * puts OpenSSL::Cipher.ciphers
+ *
+ * === Instantiating a Cipher
+ *
+ * There are several ways to create a Cipher instance. Generally, a
+ * Cipher algorithm is categorized by its name, the key length in bits
+ * and the cipher mode to be used. The most generic way to create a
+ * Cipher is the following
+ *
+ * cipher = OpenSSL::Cipher.new('<name>-<key length>-<mode>')
+ *
+ * That is, a string consisting of the hyphenated concatenation of the
+ * individual components name, key length and mode. Either all uppercase
+ * or all lowercase strings may be used, for example:
+ *
+ * cipher = OpenSSL::Cipher.new('aes-128-cbc')
+ *
+ * === Choosing either encryption or decryption mode
+ *
+ * Encryption and decryption are often very similar operations for
+ * symmetric algorithms, this is reflected by not having to choose
+ * different classes for either operation, both can be done using the
+ * same class. Still, after obtaining a Cipher instance, we need to
+ * tell the instance what it is that we intend to do with it, so we
+ * need to call either
+ *
+ * cipher.encrypt
+ *
+ * or
+ *
+ * cipher.decrypt
+ *
+ * on the Cipher instance. This should be the first call after creating
+ * the instance, otherwise configuration that has already been set could
+ * get lost in the process.
+ *
+ * === Choosing a key
+ *
+ * Symmetric encryption requires a key that is the same for the encrypting
+ * and for the decrypting party and after initial key establishment should
+ * be kept as private information. There are a lot of ways to create
+ * insecure keys, the most notable is to simply take a password as the key
+ * without processing the password further. A simple and secure way to
+ * create a key for a particular Cipher is
+ *
+ * cipher = OpenSSL::Cipher.new('aes-256-cfb')
+ * cipher.encrypt
+ * key = cipher.random_key # also sets the generated key on the Cipher
+ *
+ * If you absolutely need to use passwords as encryption keys, you
+ * should use Password-Based Key Derivation Function 2 (PBKDF2) by
+ * generating the key with the help of the functionality provided by
+ * OpenSSL::PKCS5.pbkdf2_hmac_sha1 or OpenSSL::PKCS5.pbkdf2_hmac.
+ *
+ * Although there is Cipher#pkcs5_keyivgen, its use is deprecated and
+ * it should only be used in legacy applications because it does not use
+ * the newer PKCS#5 v2 algorithms.
+ *
+ * === Choosing an IV
+ *
+ * The cipher modes CBC, CFB, OFB and CTR all need an "initialization
+ * vector", or short, IV. ECB mode is the only mode that does not require
+ * an IV, but there is almost no legitimate use case for this mode
+ * because of the fact that it does not sufficiently hide plaintext
+ * patterns. Therefore
+ *
+ * <b>You should never use ECB mode unless you are absolutely sure that
+ * you absolutely need it</b>
+ *
+ * Because of this, you will end up with a mode that explicitly requires
+ * an IV in any case. Although the IV can be seen as public information,
+ * i.e. it may be transmitted in public once generated, it should still
+ * stay unpredictable to prevent certain kinds of attacks. Therefore,
+ * ideally
+ *
+ * <b>Always create a secure random IV for every encryption of your
+ * Cipher</b>
+ *
+ * A new, random IV should be created for every encryption of data. Think
+ * of the IV as a nonce (number used once) - it's public but random and
+ * unpredictable. A secure random IV can be created as follows
+ *
+ * cipher = ...
+ * cipher.encrypt
+ * key = cipher.random_key
+ * iv = cipher.random_iv # also sets the generated IV on the Cipher
+ *
+ * Although the key is generally a random value, too, it is a bad choice
+ * as an IV. There are elaborate ways how an attacker can take advantage
+ * of such an IV. As a general rule of thumb, exposing the key directly
+ * or indirectly should be avoided at all cost and exceptions only be
+ * made with good reason.
+ *
+ * === Calling Cipher#final
+ *
+ * ECB (which should not be used) and CBC are both block-based modes.
+ * This means that unlike for the other streaming-based modes, they
+ * operate on fixed-size blocks of data, and therefore they require a
+ * "finalization" step to produce or correctly decrypt the last block of
+ * data by appropriately handling some form of padding. Therefore it is
+ * essential to add the output of OpenSSL::Cipher#final to your
+ * encryption/decryption buffer or you will end up with decryption errors
+ * or truncated data.
+ *
+ * Although this is not really necessary for streaming-mode ciphers, it is
+ * still recommended to apply the same pattern of adding the output of
+ * Cipher#final there as well - it also enables you to switch between
+ * modes more easily in the future.
+ *
+ * === Encrypting and decrypting some data
+ *
+ * data = "Very, very confidential data"
+ *
+ * cipher = OpenSSL::Cipher.new('aes-128-cbc')
+ * cipher.encrypt
+ * key = cipher.random_key
+ * iv = cipher.random_iv
+ *
+ * encrypted = cipher.update(data) + cipher.final
+ * ...
+ * decipher = OpenSSL::Cipher.new('aes-128-cbc')
+ * decipher.decrypt
+ * decipher.key = key
+ * decipher.iv = iv
+ *
+ * plain = decipher.update(encrypted) + decipher.final
+ *
+ * puts data == plain #=> true
+ *
+ * === Authenticated Encryption and Associated Data (AEAD)
+ *
+ * If the OpenSSL version used supports it, an Authenticated Encryption
+ * mode (such as GCM or CCM) should always be preferred over any
+ * unauthenticated mode. Currently, OpenSSL supports AE only in combination
+ * with Associated Data (AEAD) where additional associated data is included
+ * in the encryption process to compute a tag at the end of the encryption.
+ * This tag will also be used in the decryption process and by verifying
+ * its validity, the authenticity of a given ciphertext is established.
+ *
+ * This is superior to unauthenticated modes in that it allows to detect
+ * if somebody effectively changed the ciphertext after it had been
+ * encrypted. This prevents malicious modifications of the ciphertext that
+ * could otherwise be exploited to modify ciphertexts in ways beneficial to
+ * potential attackers.
+ *
+ * Associated data, also called additional authenticated data (AAD), is
+ * optionally used where there is additional information, such as
+ * headers or some metadata, that must be also authenticated but not
+ * necessarily need to be encrypted.
+ *
+ * An example using the GCM (Galois/Counter Mode). You have 16 bytes _key_,
+ * 12 bytes (96 bits) _nonce_ and the associated data _auth_data_. Be sure
+ * not to reuse the _key_ and _nonce_ pair. Reusing an nonce ruins the
+ * security guarantees of GCM mode.
+ *
+ * key = OpenSSL::Random.random_bytes(16)
+ * nonce = OpenSSL::Random.random_bytes(12)
+ * auth_data = "authenticated but unencrypted data"
+ * data = "encrypted data"
+ *
+ * cipher = OpenSSL::Cipher.new('aes-128-gcm').encrypt
+ * cipher.key = key
+ * cipher.iv = nonce
+ * cipher.auth_data = auth_data
+ *
+ * encrypted = cipher.update(data) + cipher.final
+ * tag = cipher.auth_tag(16)
+ *
+ * Now you are the receiver. You know the _key_ and have received _nonce_,
+ * _auth_data_, _encrypted_ and _tag_ through an untrusted network. Note
+ * that GCM accepts an arbitrary length tag between 1 and 16 bytes. You may
+ * additionally need to check that the received tag has the correct length,
+ * or you allow attackers to forge a valid single byte tag for the tampered
+ * ciphertext with a probability of 1/256.
+ *
+ * raise "tag is truncated!" unless tag.bytesize == 16
+ * decipher = OpenSSL::Cipher.new('aes-128-gcm').decrypt
+ * decipher.key = key
+ * decipher.iv = nonce
+ * decipher.auth_tag = tag # could be called at any time before #final
+ * decipher.auth_data = auth_data
+ *
+ * decrypted = decipher.update(encrypted) + decipher.final
+ *
+ * puts data == decrypted #=> true
+ *
+ * Note that other AEAD ciphers may require additional steps, such as
+ * setting the expected tag length (#auth_tag_len=) or the total data
+ * length (#ccm_data_len=) in advance. Make sure to read the relevant man
+ * page for details.
+ */
+ cCipher = rb_define_class_under(mOSSL, "Cipher", rb_cObject);
+ eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError);
+ eAuthTagError = rb_define_class_under(cCipher, "AuthTagError", eCipherError);
rb_define_alloc_func(cCipher, ossl_cipher_alloc);
- rb_define_copy_func(cCipher, ossl_cipher_copy);
- rb_define_module_function(mCipher, "ciphers", ossl_s_ciphers, 0);
+ rb_define_method(cCipher, "initialize_copy", ossl_cipher_copy, 1);
+ rb_define_module_function(cCipher, "ciphers", ossl_s_ciphers, 0);
rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1);
rb_define_method(cCipher, "reset", ossl_cipher_reset, 0);
- rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1);
- rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1);
+ rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, 0);
+ rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, 0);
rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1);
- rb_define_method(cCipher, "update", ossl_cipher_update, 1);
- rb_define_method(cCipher, "<<", ossl_cipher_update_deprecated, 1);
+ rb_define_method(cCipher, "update", ossl_cipher_update, -1);
rb_define_method(cCipher, "final", ossl_cipher_final, 0);
rb_define_method(cCipher, "name", ossl_cipher_name, 0);
rb_define_method(cCipher, "key=", ossl_cipher_set_key, 1);
+ rb_define_method(cCipher, "auth_data=", ossl_cipher_set_auth_data, 1);
+ rb_define_method(cCipher, "auth_tag=", ossl_cipher_set_auth_tag, 1);
+ rb_define_method(cCipher, "auth_tag", ossl_cipher_get_auth_tag, -1);
+ rb_define_method(cCipher, "auth_tag_len=", ossl_cipher_set_auth_tag_len, 1);
+ rb_define_method(cCipher, "authenticated?", ossl_cipher_is_authenticated, 0);
rb_define_method(cCipher, "key_len=", ossl_cipher_set_key_length, 1);
rb_define_method(cCipher, "key_len", ossl_cipher_key_length, 0);
rb_define_method(cCipher, "iv=", ossl_cipher_set_iv, 1);
+ rb_define_method(cCipher, "iv_len=", ossl_cipher_set_iv_length, 1);
rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0);
rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
+ rb_define_method(cCipher, "ccm_data_len=", ossl_cipher_set_ccm_data_len, 1);
+
+ id_auth_tag_len = rb_intern_const("auth_tag_len");
+ id_key_set = rb_intern_const("key_set");
+ id_cipher_holder = rb_intern_const("EVP_CIPHER_holder");
}
diff --git a/ext/openssl/ossl_cipher.h b/ext/openssl/ossl_cipher.h
index 63c7a875e8..fba63a140f 100644
--- a/ext/openssl/ossl_cipher.h
+++ b/ext/openssl/ossl_cipher.h
@@ -1,23 +1,26 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_CIPHER_H_)
#define _OSSL_CIPHER_H_
-extern VALUE mCipher;
-extern VALUE cCipher;
-extern VALUE eCipherError;
-
-const EVP_CIPHER *GetCipherPtr(VALUE);
+/*
+ * Gets EVP_CIPHER from a String or an OpenSSL::Digest instance (discouraged,
+ * but still supported for compatibility). A holder object is created if the
+ * EVP_CIPHER is a "fetched" algorithm.
+ */
+const EVP_CIPHER *ossl_evp_cipher_fetch(VALUE obj, volatile VALUE *holder);
+/*
+ * This is meant for OpenSSL::Engine#cipher. EVP_CIPHER must not be a fetched
+ * one.
+ */
VALUE ossl_cipher_new(const EVP_CIPHER *);
void Init_ossl_cipher(void);
#endif /* _OSSL_CIPHER_H_ */
-
diff --git a/ext/openssl/ossl_config.c b/ext/openssl/ossl_config.c
index ef89fdfe0d..274875a978 100644
--- a/ext/openssl/ossl_config.c
+++ b/ext/openssl/ossl_config.c
@@ -1,459 +1,456 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#define WrapConfig(klass, obj, conf) do { \
- if (!conf) { \
- ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \
- } \
- obj = Data_Wrap_Struct(klass, 0, NCONF_free, conf); \
-} while (0)
-#define GetConfig(obj, conf) do { \
- Data_Get_Struct(obj, CONF, conf); \
- if (!conf) { \
- ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \
- } \
-} while (0)
-#define SafeGetConfig(obj, conf) do { \
- OSSL_Check_Kind(obj, cConfig); \
- GetConfig(obj, conf); \
-} while(0);
+static VALUE cConfig, eConfigError;
-/*
- * Classes
- */
-VALUE cConfig;
-VALUE eConfigError;
-
-/*
- * Public
- */
+static void
+nconf_free(void *conf)
+{
+ NCONF_free(conf);
+}
-static CONF *parse_config(VALUE, CONF*);
+static const rb_data_type_t ossl_config_type = {
+ "OpenSSL/CONF",
+ {
+ 0, nconf_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
+};
CONF *
-GetConfigPtr(VALUE obj)
+GetConfig(VALUE obj)
{
CONF *conf;
- SafeGetConfig(obj, conf);
-
+ TypedData_Get_Struct(obj, CONF, &ossl_config_type, conf);
+ if (!conf)
+ rb_raise(rb_eRuntimeError, "CONF is not initialized");
return conf;
}
-CONF *
-DupConfigPtr(VALUE obj)
+static VALUE
+config_s_alloc(VALUE klass)
{
- VALUE str;
-
- OSSL_Check_Kind(obj, cConfig);
- str = rb_funcall(obj, rb_intern("to_s"), 0);
+ VALUE obj;
+ CONF *conf;
- return parse_config(str, NULL);
+ obj = TypedData_Wrap_Struct(klass, &ossl_config_type, 0);
+ conf = NCONF_new(NULL);
+ if (!conf)
+ ossl_raise(eConfigError, "NCONF_new");
+ RTYPEDDATA_DATA(obj) = conf;
+ return obj;
}
-/*
- * Private
- */
-static CONF *
-parse_config(VALUE str, CONF *dst)
+static void
+config_load_bio(CONF *conf, BIO *bio)
{
- CONF *conf;
- BIO *bio;
long eline = -1;
- bio = ossl_obj2bio(str);
- conf = dst ? dst : NCONF_new(NULL);
- if(!conf){
- BIO_free(bio);
- ossl_raise(eConfigError, NULL);
- }
- if(!NCONF_load_bio(conf, bio, &eline)){
- BIO_free(bio);
- if(!dst) NCONF_free(conf);
- if (eline <= 0) ossl_raise(eConfigError, "wrong config format");
- else ossl_raise(eConfigError, "error in line %d", eline);
- ossl_raise(eConfigError, NULL);
+ if (!NCONF_load_bio(conf, bio, &eline)) {
+ BIO_free(bio);
+ if (eline <= 0)
+ ossl_raise(eConfigError, "wrong config format");
+ else
+ ossl_raise(eConfigError, "error in line %ld", eline);
}
BIO_free(bio);
- return conf;
-}
-
-static VALUE
-ossl_config_s_parse(VALUE klass, VALUE str)
-{
- CONF *conf;
- VALUE obj;
-
- conf = parse_config(str, NULL);
- WrapConfig(klass, obj, conf);
-
- return obj;
+ /*
+ * Clear the error queue even if it is parsed successfully.
+ * Particularly, when the .include directive refers to a non-existent file,
+ * it is only reported in the error queue.
+ */
+ ossl_clear_error();
}
+/*
+ * call-seq:
+ * Config.parse(string) -> OpenSSL::Config
+ *
+ * Parses a given _string_ as a blob that contains configuration for OpenSSL.
+ */
static VALUE
-ossl_config_s_alloc(VALUE klass)
+config_s_parse(VALUE klass, VALUE str)
{
- CONF *conf;
- VALUE obj;
-
- if(!(conf = NCONF_new(NULL)))
- ossl_raise(eConfigError, NULL);
- WrapConfig(klass, obj, conf);
+ VALUE obj = config_s_alloc(klass);
+ CONF *conf = GetConfig(obj);
+ BIO *bio;
+ bio = ossl_obj2bio(&str);
+ config_load_bio(conf, bio); /* Consumes BIO */
+ rb_obj_freeze(obj);
return obj;
}
-static VALUE
-ossl_config_copy(VALUE self, VALUE other)
-{
- VALUE str;
- CONF *conf;
-
- str = rb_funcall(self, rb_intern("to_s"), 0);
- GetConfig(other, conf);
- parse_config(str, conf);
-
- return self;
-}
+static VALUE config_get_sections(VALUE self);
+static VALUE config_get_section(VALUE self, VALUE section);
+/*
+ * call-seq:
+ * Config.parse_config(io) -> hash
+ *
+ * Parses the configuration data read from _io_ and returns the whole content
+ * as a Hash.
+ */
static VALUE
-ossl_config_initialize(int argc, VALUE *argv, VALUE self)
+config_s_parse_config(VALUE klass, VALUE io)
{
- CONF *conf;
- long eline = -1;
- char *filename;
- VALUE path;
-
- rb_scan_args(argc, argv, "01", &path);
- if(!NIL_P(path)){
- SafeStringValue(path);
- filename = StringValuePtr(path);
- GetConfig(self, conf);
- if (!NCONF_load(conf, filename, &eline)){
- if (eline <= 0)
- ossl_raise(eConfigError, "wrong config file %s", filename);
- else
- ossl_raise(eConfigError, "error in %s:%d", filename, eline);
- }
+ VALUE obj, sections, ret;
+ long i;
+
+ obj = config_s_parse(klass, io);
+ sections = config_get_sections(obj);
+ ret = rb_hash_new();
+ for (i = 0; i < RARRAY_LEN(sections); i++) {
+ VALUE section = rb_ary_entry(sections, i);
+ rb_hash_aset(ret, section, config_get_section(obj, section));
}
-#ifdef OSSL_NO_CONF_API
- else rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
-#else
- else {
- GetConfig(self, conf);
- _CONF_new_data(conf);
- }
-#endif
-
- return self;
+ return ret;
}
+/*
+ * call-seq:
+ * Config.new(filename) -> OpenSSL::Config
+ *
+ * Creates an instance of OpenSSL::Config from the content of the file
+ * specified by _filename_.
+ *
+ * This can be used in contexts like OpenSSL::X509::ExtensionFactory.config=
+ *
+ * This can raise IO exceptions based on the access, or availability of the
+ * file. A ConfigError exception may be raised depending on the validity of
+ * the data being configured.
+ */
static VALUE
-ossl_config_add_value(VALUE self, VALUE section, VALUE name, VALUE value)
+config_initialize(int argc, VALUE *argv, VALUE self)
{
-#ifdef OSSL_NO_CONF_API
- rb_notimplement();
-#else
- CONF *conf;
- CONF_VALUE *sv, *cv;
-
- StringValue(section);
- StringValue(name);
- StringValue(value);
- GetConfig(self, conf);
- if(!(sv = _CONF_get_section(conf, RSTRING(section)->ptr))){
- if(!(sv = _CONF_new_section(conf, RSTRING(section)->ptr))){
- ossl_raise(eConfigError, NULL);
- }
- }
- if(!(cv = OPENSSL_malloc(sizeof(CONF_VALUE)))){
- ossl_raise(eConfigError, NULL);
- }
- cv->name = BUF_strdup(RSTRING(name)->ptr);
- cv->value = BUF_strdup(RSTRING(value)->ptr);
- if(!cv->name || !cv->value || !_CONF_add_string(conf, sv, cv)){
- OPENSSL_free(cv->name);
- OPENSSL_free(cv->value);
- OPENSSL_free(cv);
- ossl_raise(eConfigError, "_CONF_add_string failure");
+ CONF *conf = GetConfig(self);
+ VALUE filename;
+
+ /* 0-arguments call has no use-case, but is kept for compatibility */
+ rb_scan_args(argc, argv, "01", &filename);
+ rb_check_frozen(self);
+ if (!NIL_P(filename)) {
+ BIO *bio = BIO_new_file(StringValueCStr(filename), "rb");
+ if (!bio)
+ ossl_raise(eConfigError, "BIO_new_file");
+ config_load_bio(conf, bio); /* Consumes BIO */
}
-
- return value;
-#endif
+ rb_obj_freeze(self);
+ return self;
}
static VALUE
-ossl_config_get_value(VALUE self, VALUE section, VALUE name)
+config_initialize_copy(VALUE self, VALUE other)
{
- CONF *conf;
- char *str;
-
- StringValue(section);
- StringValue(name);
- GetConfig(self, conf);
- str = NCONF_get_string(conf, RSTRING(section)->ptr, RSTRING(name)->ptr);
- if(!str){
- ERR_clear_error();
- return Qnil;
- }
+ CONF *conf = GetConfig(self);
+ VALUE str;
+ BIO *bio;
- return rb_str_new2(str);
+ str = rb_funcall(other, rb_intern("to_s"), 0);
+ rb_check_frozen(self);
+ bio = ossl_obj2bio(&str);
+ config_load_bio(conf, bio); /* Consumes BIO */
+ rb_obj_freeze(self);
+ return self;
}
+/*
+ * call-seq:
+ * config.get_value(section, key) -> string
+ *
+ * Gets the value of _key_ from the given _section_.
+ *
+ * Given the following configurating file being loaded:
+ *
+ * config = OpenSSL::Config.load('foo.cnf')
+ * #=> #<OpenSSL::Config sections=["default"]>
+ * puts config.to_s
+ * #=> [ default ]
+ * # foo=bar
+ *
+ * You can get a specific value from the config if you know the _section_
+ * and _key_ like so:
+ *
+ * config.get_value('default','foo')
+ * #=> "bar"
+ */
static VALUE
-ossl_config_get_value_old(int argc, VALUE *argv, VALUE self)
+config_get_value(VALUE self, VALUE section, VALUE key)
{
- VALUE section, name;
-
- rb_scan_args(argc, argv, "11", &section, &name);
-
- /* support conf.value(nil, "HOME") -> conf.get_value("", "HOME") */
- if (NIL_P(section)) section = rb_str_new2("");
- /* support conf.value("HOME") -> conf.get_value("", "HOME") */
- if (NIL_P(name)) {
- name = section;
- section = rb_str_new2("");
+ CONF *conf = GetConfig(self);
+ const char *str, *sectionp;
+
+ StringValueCStr(section);
+ StringValueCStr(key);
+ /* For compatibility; NULL means "default". */
+ sectionp = RSTRING_LEN(section) ? RSTRING_PTR(section) : NULL;
+ str = NCONF_get_string(conf, sectionp, RSTRING_PTR(key));
+ if (!str) {
+ ossl_clear_error();
+ return Qnil;
}
- /* NOTE: Don't care about conf.get_value(nil, nil) */
- rb_warn("Config#value is deprecated; use Config#get_value");
- return ossl_config_get_value(self, section, name);
-}
-
-static VALUE
-set_conf_section_i(VALUE i, VALUE *arg)
-{
- VALUE name, value;
-
- Check_Type(i, T_ARRAY);
- name = rb_ary_entry(i, 0);
- value = rb_ary_entry(i, 1);
- ossl_config_add_value(arg[0], arg[1], name, value);
-
- return Qnil;
-}
-
-static VALUE
-ossl_config_set_section(VALUE self, VALUE section, VALUE hash)
-{
- VALUE arg[2] = { self, section };
- rb_iterate(rb_each, hash, set_conf_section_i, (VALUE)arg);
- return hash;
+ return rb_str_new_cstr(str);
}
/*
- * Get all numbers as strings - use str.to_i to convert
- * long number = CONF_get_number(confp->config, sect, StringValuePtr(item));
+ * call-seq:
+ * config[section] -> hash
+ *
+ * Gets all key-value pairs in a specific _section_ from the current
+ * configuration.
+ *
+ * Given the following configurating file being loaded:
+ *
+ * config = OpenSSL::Config.load('foo.cnf')
+ * #=> #<OpenSSL::Config sections=["default"]>
+ * puts config.to_s
+ * #=> [ default ]
+ * # foo=bar
+ *
+ * You can get a hash of the specific section like so:
+ *
+ * config['default']
+ * #=> {"foo"=>"bar"}
+ *
*/
static VALUE
-ossl_config_get_section(VALUE self, VALUE section)
+config_get_section(VALUE self, VALUE section)
{
- CONF *conf;
+ CONF *conf = GetConfig(self);
STACK_OF(CONF_VALUE) *sk;
- CONF_VALUE *entry;
int i, entries;
VALUE hash;
hash = rb_hash_new();
- StringValue(section);
- GetConfig(self, conf);
- if (!(sk = NCONF_get_section(conf, StringValuePtr(section)))) {
- ERR_clear_error();
- return hash;
+ StringValueCStr(section);
+ if (!(sk = NCONF_get_section(conf, RSTRING_PTR(section)))) {
+ ossl_clear_error();
+ return hash;
}
- if ((entries = sk_CONF_VALUE_num(sk)) < 0) {
- OSSL_Debug("# of items in section is < 0?!?");
- return hash;
+ entries = sk_CONF_VALUE_num(sk);
+ for (i = 0; i < entries; i++) {
+ CONF_VALUE *entry = sk_CONF_VALUE_value(sk, i);
+ rb_hash_aset(hash, rb_str_new_cstr(entry->name),
+ rb_str_new_cstr(entry->value));
}
- for (i=0; i<entries; i++) {
- entry = sk_CONF_VALUE_value(sk, i);
- rb_hash_aset(hash, rb_str_new2(entry->name), rb_str_new2(entry->value));
- }
-
return hash;
}
-static VALUE
-ossl_config_get_section_old(VALUE self, VALUE section)
-{
- rb_warn("Config#section is deprecated; use Config#[]");
- return ossl_config_get_section(self, section);
-}
-
-#ifdef IMPLEMENT_LHASH_DOALL_ARG_FN
static void
-get_conf_section(CONF_VALUE *cv, VALUE ary)
+get_conf_section_doall_arg(CONF_VALUE *cv, VALUE *aryp)
{
- if(cv->name) return;
- rb_ary_push(ary, rb_str_new2(cv->section));
+ if (cv->name)
+ return;
+ rb_ary_push(*aryp, rb_str_new_cstr(cv->section));
}
-static IMPLEMENT_LHASH_DOALL_ARG_FN(get_conf_section, CONF_VALUE*, VALUE);
+/* IMPLEMENT_LHASH_DOALL_ARG_CONST() requires >= OpenSSL 1.1.0 */
+static IMPLEMENT_LHASH_DOALL_ARG_FN(get_conf_section, CONF_VALUE, VALUE)
+/*
+ * call-seq:
+ * config.sections -> array of string
+ *
+ * Get the names of all sections in the current configuration.
+ */
static VALUE
-ossl_config_get_sections(VALUE self)
+config_get_sections(VALUE self)
{
- CONF *conf;
+ CONF *conf = GetConfig(self);
VALUE ary;
- GetConfig(self, conf);
ary = rb_ary_new();
- lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(get_conf_section), (void*)ary);
-
+ lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(get_conf_section),
+ &ary);
return ary;
}
static void
-dump_conf_value(CONF_VALUE *cv, VALUE str)
+dump_conf_value_doall_arg(CONF_VALUE *cv, VALUE *strp)
{
+ VALUE str = *strp;
STACK_OF(CONF_VALUE) *sk;
- CONF_VALUE *v;
int i, num;
- if (cv->name) return;
- sk = (STACK_OF(CONF_VALUE)*)cv->value;
+ if (cv->name)
+ return;
+ sk = (STACK_OF(CONF_VALUE) *)cv->value;
num = sk_CONF_VALUE_num(sk);
- rb_str_cat2(str, "[ ");
- rb_str_cat2(str, cv->section);
- rb_str_cat2(str, " ]\n");
- for(i = 0; i < num; i++){
- v = sk_CONF_VALUE_value(sk, i);
- rb_str_cat2(str, v->name ? v->name : "None");
- rb_str_cat2(str, "=");
- rb_str_cat2(str, v->value ? v->value : "None");
- rb_str_cat2(str, "\n");
+ rb_str_cat_cstr(str, "[ ");
+ rb_str_cat_cstr(str, cv->section);
+ rb_str_cat_cstr(str, " ]\n");
+ for (i = 0; i < num; i++){
+ CONF_VALUE *v = sk_CONF_VALUE_value(sk, i);
+ rb_str_cat_cstr(str, v->name ? v->name : "None");
+ rb_str_cat_cstr(str, "=");
+ rb_str_cat_cstr(str, v->value ? v->value : "None");
+ rb_str_cat_cstr(str, "\n");
}
- rb_str_cat2(str, "\n");
+ rb_str_cat_cstr(str, "\n");
}
-static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_conf_value, CONF_VALUE*, VALUE);
+static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_conf_value, CONF_VALUE, VALUE)
+/*
+ * call-seq:
+ * config.to_s -> string
+ *
+ *
+ * Gets the parsable form of the current configuration.
+ *
+ * Given the following configuration file being loaded:
+ *
+ * config = OpenSSL::Config.load('baz.cnf')
+ * #=> #<OpenSSL::Config sections=["default"]>
+ * puts config.to_s
+ * #=> [ default ]
+ * # foo=bar
+ * # baz=buz
+ *
+ * You can get the serialized configuration using #to_s and then parse
+ * it later:
+ *
+ * serialized_config = config.to_s
+ * # much later...
+ * new_config = OpenSSL::Config.parse(serialized_config)
+ * #=> #<OpenSSL::Config sections=["default"]>
+ * puts new_config
+ * #=> [ default ]
+ * foo=bar
+ * baz=buz
+ */
static VALUE
-dump_conf(CONF *conf)
+config_to_s(VALUE self)
{
+ CONF *conf = GetConfig(self);
VALUE str;
- str = rb_str_new(0, 0);
- lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_conf_value), (void*)str);
-
+ str = rb_str_new(NULL, 0);
+ lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(dump_conf_value),
+ &str);
return str;
}
-static VALUE
-ossl_config_to_s(VALUE self)
-{
- CONF *conf;
-
- GetConfig(self, conf);
-
- return dump_conf(conf);
-}
-
static void
-each_conf_value(CONF_VALUE *cv, void* dummy)
+each_conf_value_doall_arg(CONF_VALUE *cv, void *unused)
{
STACK_OF(CONF_VALUE) *sk;
- CONF_VALUE *v;
- VALUE section, name, value, args;
+ VALUE section;
int i, num;
- if (cv->name) return;
- sk = (STACK_OF(CONF_VALUE)*)cv->value;
+ if (cv->name)
+ return;
+ sk = (STACK_OF(CONF_VALUE) *)cv->value;
num = sk_CONF_VALUE_num(sk);
- section = rb_str_new2(cv->section);
- for(i = 0; i < num; i++){
- v = sk_CONF_VALUE_value(sk, i);
- name = v->name ? rb_str_new2(v->name) : Qnil;
- value = v->value ? rb_str_new2(v->value) : Qnil;
- args = rb_ary_new3(3, section, name, value);
- rb_yield(args);
+ section = rb_str_new_cstr(cv->section);
+ for (i = 0; i < num; i++){
+ CONF_VALUE *v = sk_CONF_VALUE_value(sk, i);
+ VALUE name = v->name ? rb_str_new_cstr(v->name) : Qnil;
+ VALUE value = v->value ? rb_str_new_cstr(v->value) : Qnil;
+ rb_yield(rb_ary_new3(3, section, name, value));
}
}
-static IMPLEMENT_LHASH_DOALL_ARG_FN(each_conf_value, CONF_VALUE*, void*);
+static IMPLEMENT_LHASH_DOALL_ARG_FN(each_conf_value, CONF_VALUE, void)
+/*
+ * call-seq:
+ * config.each { |section, key, value| }
+ *
+ * Retrieves the section and its pairs for the current configuration.
+ *
+ * config.each do |section, key, value|
+ * # ...
+ * end
+ */
static VALUE
-ossl_config_each(VALUE self)
-{
- CONF *conf;
-
- GetConfig(self, conf);
- lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(each_conf_value), (void*)NULL);
-
- return self;
-}
-#else
-static VALUE
-ossl_config_get_sections(VALUE self)
+config_each(VALUE self)
{
- rb_warn("#sections don't work with %s", OPENSSL_VERSION_TEXT);
- return rb_ary_new();
-}
+ CONF *conf = GetConfig(self);
-static VALUE
-ossl_config_to_s(VALUE self)
-{
- rb_warn("#to_s don't work with %s", OPENSSL_VERSION_TEXT);
- return rb_str_new(0, 0);
-}
+ RETURN_ENUMERATOR(self, 0, 0);
-static VALUE
-ossl_config_each(VALUE self)
-{
- rb_warn("#each don't work with %s", OPENSSL_VERSION_TEXT);
+ lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(each_conf_value),
+ NULL);
return self;
}
-#endif
+/*
+ * call-seq:
+ * config.inspect -> string
+ *
+ * String representation of this configuration object, including the class
+ * name and its sections.
+ */
static VALUE
-ossl_config_inspect(VALUE self)
+config_inspect(VALUE self)
{
- VALUE str, ary = ossl_config_get_sections(self);
- char *cname = rb_class2name(rb_obj_class(self));
+ VALUE str, ary = config_get_sections(self);
+ const char *cname = rb_class2name(rb_obj_class(self));
- str = rb_str_new2("#<");
- rb_str_cat2(str, cname);
- rb_str_cat2(str, " sections=");
+ str = rb_str_new_cstr("#<");
+ rb_str_cat_cstr(str, cname);
+ rb_str_cat_cstr(str, " sections=");
rb_str_append(str, rb_inspect(ary));
- rb_str_cat2(str, ">");
+ rb_str_cat_cstr(str, ">");
return str;
}
-/*
- * INIT
- */
void
-Init_ossl_config()
+Init_ossl_config(void)
{
- eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);
+ char *path;
+ VALUE path_str;
+
+ /* Document-class: OpenSSL::Config
+ *
+ * Configuration for the openssl library.
+ *
+ * Many system's installation of openssl library will depend on your system
+ * configuration. See the value of OpenSSL::Config::DEFAULT_CONFIG_FILE for
+ * the location of the file for your host.
+ *
+ * See also https://docs.openssl.org/master/man5/config/
+ */
cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject);
- rb_define_const(cConfig, "DEFAULT_CONFIG_FILE",
- rb_str_new2(CONF_get1_default_config_file()));
+ /* Document-class: OpenSSL::ConfigError
+ *
+ * General error for openssl library configuration files. Including formatting,
+ * parsing errors, etc.
+ */
+ eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);
+
rb_include_module(cConfig, rb_mEnumerable);
- rb_define_singleton_method(cConfig, "parse", ossl_config_s_parse, 1);
+ rb_define_singleton_method(cConfig, "parse", config_s_parse, 1);
+ rb_define_singleton_method(cConfig, "parse_config", config_s_parse_config, 1);
rb_define_alias(CLASS_OF(cConfig), "load", "new");
- rb_define_alloc_func(cConfig, ossl_config_s_alloc);
- rb_define_copy_func(cConfig, ossl_config_copy);
- rb_define_method(cConfig, "initialize", ossl_config_initialize, -1);
- rb_define_method(cConfig, "get_value", ossl_config_get_value, 2);
- rb_define_method(cConfig, "value", ossl_config_get_value_old, -1);
- rb_define_method(cConfig, "add_value", ossl_config_add_value, 3);
- rb_define_method(cConfig, "[]", ossl_config_get_section, 1);
- rb_define_method(cConfig, "section", ossl_config_get_section_old, 1);
- rb_define_method(cConfig, "[]=", ossl_config_set_section, 2);
- rb_define_method(cConfig, "sections", ossl_config_get_sections, 0);
- rb_define_method(cConfig, "to_s", ossl_config_to_s, 0);
- rb_define_method(cConfig, "each", ossl_config_each, 0);
- rb_define_method(cConfig, "inspect", ossl_config_inspect, 0);
+ rb_define_alloc_func(cConfig, config_s_alloc);
+ rb_define_method(cConfig, "initialize", config_initialize, -1);
+ rb_define_method(cConfig, "initialize_copy", config_initialize_copy, 1);
+ rb_define_method(cConfig, "get_value", config_get_value, 2);
+ rb_define_method(cConfig, "[]", config_get_section, 1);
+ rb_define_method(cConfig, "sections", config_get_sections, 0);
+ rb_define_method(cConfig, "to_s", config_to_s, 0);
+ rb_define_method(cConfig, "each", config_each, 0);
+ rb_define_method(cConfig, "inspect", config_inspect, 0);
+
+ /* Document-const: DEFAULT_CONFIG_FILE
+ *
+ * The default system configuration file for OpenSSL.
+ */
+ path = CONF_get1_default_config_file();
+ path_str = rb_obj_freeze(ossl_buf2str(path, rb_long2int(strlen(path))));
+ rb_define_const(cConfig, "DEFAULT_CONFIG_FILE", path_str);
}
diff --git a/ext/openssl/ossl_config.h b/ext/openssl/ossl_config.h
index cb226b27e5..a254360c2c 100644
--- a/ext/openssl/ossl_config.h
+++ b/ext/openssl/ossl_config.h
@@ -1,22 +1,16 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
-#if !defined(_OSSL_CONFIG_H_)
-#define _OSSL_CONFIG_H_
+#ifndef OSSL_CONFIG_H
+#define OSSL_CONFIG_H
-extern VALUE cConfig;
-extern VALUE eConfigError;
-
-CONF* GetConfigPtr(VALUE obj);
-CONF* DupConfigPtr(VALUE obj);
+CONF *GetConfig(VALUE obj);
void Init_ossl_config(void);
-#endif /* _OSSL_CONFIG_H_ */
-
+#endif /* OSSL_CONFIG_H */
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index d22f022442..e23968b1e3 100644
--- a/ext/openssl/ossl_digest.c
+++ b/ext/openssl/ossl_digest.c
@@ -1,59 +1,121 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
#define GetDigest(obj, ctx) do { \
- Data_Get_Struct(obj, EVP_MD_CTX, ctx); \
- if (!ctx) { \
- ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \
+ TypedData_Get_Struct((obj), EVP_MD_CTX, &ossl_digest_type, (ctx)); \
+ if (!(ctx)) { \
+ ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \
} \
} while (0)
-#define SafeGetDigest(obj, ctx) do { \
- OSSL_Check_Kind(obj, cDigest); \
- GetDigest(obj, ctx); \
-} while (0)
/*
* Classes
*/
-VALUE mDigest;
-VALUE cDigest;
-VALUE eDigestError;
+static VALUE cDigest;
+static VALUE eDigestError;
+static ID id_md_holder;
static VALUE ossl_digest_alloc(VALUE klass);
+static void
+ossl_digest_free(void *ctx)
+{
+ EVP_MD_CTX_destroy(ctx);
+}
+
+static const rb_data_type_t ossl_digest_type = {
+ "OpenSSL/Digest",
+ {
+ 0, ossl_digest_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+#ifdef OSSL_USE_PROVIDER
+static void
+ossl_evp_md_free(void *ptr)
+{
+ // This is safe to call against const EVP_MD * returned by
+ // EVP_get_digestbyname()
+ EVP_MD_free(ptr);
+}
+
+static const rb_data_type_t ossl_evp_md_holder_type = {
+ "OpenSSL/EVP_MD",
+ {
+ .dfree = ossl_evp_md_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+#endif
+
/*
* Public
*/
const EVP_MD *
-GetDigestPtr(VALUE obj)
+ossl_evp_md_fetch(VALUE obj, volatile VALUE *holder)
{
- EVP_MD_CTX *ctx;
-
- SafeGetDigest(obj, ctx);
+ *holder = Qnil;
+ if (rb_obj_is_kind_of(obj, cDigest)) {
+ EVP_MD_CTX *ctx;
+ GetDigest(obj, ctx);
+ EVP_MD *md = (EVP_MD *)EVP_MD_CTX_get0_md(ctx);
+#ifdef OSSL_USE_PROVIDER
+ *holder = TypedData_Wrap_Struct(0, &ossl_evp_md_holder_type, NULL);
+ if (!EVP_MD_up_ref(md))
+ ossl_raise(eDigestError, "EVP_MD_up_ref");
+ RTYPEDDATA_DATA(*holder) = md;
+#endif
+ return md;
+ }
- return EVP_MD_CTX_md(ctx); /*== ctx->digest*/
+ const char *name = StringValueCStr(obj);
+ EVP_MD *md = (EVP_MD *)EVP_get_digestbyname(name);
+ if (!md) {
+ ASN1_OBJECT *oid = OBJ_txt2obj(name, 0);
+ md = (EVP_MD *)EVP_get_digestbyobj(oid);
+ ASN1_OBJECT_free(oid);
+ }
+#ifdef OSSL_USE_PROVIDER
+ if (!md) {
+ ossl_clear_error();
+ *holder = TypedData_Wrap_Struct(0, &ossl_evp_md_holder_type, NULL);
+ md = EVP_MD_fetch(NULL, name, NULL);
+ RTYPEDDATA_DATA(*holder) = md;
+ }
+#endif
+ if (!md)
+ ossl_raise(eDigestError, "unsupported digest algorithm: %"PRIsVALUE,
+ obj);
+ return md;
}
VALUE
ossl_digest_new(const EVP_MD *md)
-{
+{
VALUE ret;
EVP_MD_CTX *ctx;
+ // NOTE: This does not set id_md_holder because this function should
+ // only be called from ossl_engine.c, which will not use any
+ // reference-counted digests.
ret = ossl_digest_alloc(cDigest);
- GetDigest(ret, ctx);
- EVP_MD_CTX_init(ctx);
- EVP_DigestInit_ex(ctx, md, NULL);
-
+ ctx = EVP_MD_CTX_new();
+ if (!ctx)
+ ossl_raise(eDigestError, "EVP_MD_CTX_new");
+ RTYPEDDATA_DATA(ret) = ctx;
+
+ if (!EVP_DigestInit_ex(ctx, md, NULL))
+ ossl_raise(eDigestError, "Digest initialization failed");
+
return ret;
}
@@ -63,232 +125,351 @@ ossl_digest_new(const EVP_MD *md)
static VALUE
ossl_digest_alloc(VALUE klass)
{
- EVP_MD_CTX *ctx;
- VALUE obj;
-
- ctx = EVP_MD_CTX_create();
- if (ctx == NULL)
- ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed");
- EVP_MD_CTX_init(ctx);
- obj = Data_Wrap_Struct(klass, 0, EVP_MD_CTX_destroy, ctx);
-
- return obj;
+ return TypedData_Wrap_Struct(klass, &ossl_digest_type, 0);
}
-VALUE ossl_digest_update(VALUE, VALUE);
+static VALUE ossl_digest_update(VALUE, VALUE);
+/*
+ * call-seq:
+ * Digest.new(string [, data]) -> Digest
+ *
+ * Creates a Digest instance based on _string_, which is either the ln
+ * (long name) or sn (short name) of a supported digest algorithm. A list of
+ * supported algorithms can be obtained by calling OpenSSL::Digest.digests.
+ *
+ * If _data_ (a String) is given, it is used as the initial input to the
+ * Digest instance, i.e.
+ *
+ * digest = OpenSSL::Digest.new('sha256', 'digestdata')
+ *
+ * is equivalent to
+ *
+ * digest = OpenSSL::Digest.new('sha256')
+ * digest.update('digestdata')
+ */
static VALUE
ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
{
EVP_MD_CTX *ctx;
const EVP_MD *md;
- char *name;
- VALUE type, data;
+ VALUE type, data, md_holder;
rb_scan_args(argc, argv, "11", &type, &data);
- StringValue(type);
+ md = ossl_evp_md_fetch(type, &md_holder);
if (!NIL_P(data)) StringValue(data);
- name = StringValuePtr(type);
-
- md = EVP_get_digestbyname(name);
- if (!md) {
- ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
+
+ TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx);
+ if (!ctx) {
+ RTYPEDDATA_DATA(self) = ctx = EVP_MD_CTX_new();
+ if (!ctx)
+ ossl_raise(eDigestError, "EVP_MD_CTX_new");
}
- GetDigest(self, ctx);
- EVP_DigestInit_ex(ctx, md, NULL);
-
+
+ if (!EVP_DigestInit_ex(ctx, md, NULL))
+ ossl_raise(eDigestError, "Digest initialization failed");
+ rb_ivar_set(self, id_md_holder, md_holder);
+
if (!NIL_P(data)) return ossl_digest_update(self, data);
return self;
}
+/* :nodoc: */
static VALUE
ossl_digest_copy(VALUE self, VALUE other)
{
EVP_MD_CTX *ctx1, *ctx2;
-
+
rb_check_frozen(self);
if (self == other) return self;
- GetDigest(self, ctx1);
- SafeGetDigest(other, ctx2);
+ TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx1);
+ if (!ctx1) {
+ RTYPEDDATA_DATA(self) = ctx1 = EVP_MD_CTX_new();
+ if (!ctx1)
+ ossl_raise(eDigestError, "EVP_MD_CTX_new");
+ }
+ GetDigest(other, ctx2);
if (!EVP_MD_CTX_copy(ctx1, ctx2)) {
- ossl_raise(eDigestError, NULL);
+ ossl_raise(eDigestError, NULL);
}
return self;
}
-static VALUE
-ossl_digest_reset(VALUE self)
-{
- EVP_MD_CTX *ctx;
-
- GetDigest(self, ctx);
- EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL);
-
- return self;
-}
-
-VALUE
-ossl_digest_update(VALUE self, VALUE data)
-{
- EVP_MD_CTX *ctx;
-
- StringValue(data);
- GetDigest(self, ctx);
- EVP_DigestUpdate(ctx, RSTRING(data)->ptr, RSTRING(data)->len);
-
- return self;
-}
-
static void
-digest_final(EVP_MD_CTX *ctx, char **buf, int *buf_len)
+add_digest_name_to_ary(const OBJ_NAME *name, void *arg)
{
- EVP_MD_CTX final;
-
- if (!EVP_MD_CTX_copy(&final, ctx)) {
- ossl_raise(eDigestError, NULL);
- }
- if (!(*buf = OPENSSL_malloc(EVP_MD_CTX_size(&final)))) {
- EVP_MD_CTX_cleanup(&final);
- ossl_raise(eDigestError, "Cannot allocate mem for digest");
- }
- EVP_DigestFinal_ex(&final, *buf, buf_len);
- EVP_MD_CTX_cleanup(&final);
+ VALUE ary = (VALUE)arg;
+ rb_ary_push(ary, rb_str_new2(name->name));
}
+/*
+ * call-seq:
+ * OpenSSL::Digest.digests -> array[string...]
+ *
+ * Returns the names of all available digests in an array.
+ */
static VALUE
-ossl_digest_digest(VALUE self)
+ossl_s_digests(VALUE self)
{
- EVP_MD_CTX *ctx;
- char *buf;
- int buf_len;
- VALUE digest;
-
- GetDigest(self, ctx);
- digest_final(ctx, &buf, &buf_len);
- digest = ossl_buf2str(buf, buf_len);
-
- return digest;
+ VALUE ary;
+
+ ary = rb_ary_new();
+ OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,
+ add_digest_name_to_ary,
+ (void*)ary);
+
+ return ary;
}
+/*
+ * call-seq:
+ * digest.reset -> self
+ *
+ * Resets the Digest in the sense that any Digest#update that has been
+ * performed is abandoned and the Digest is set to its initial state again.
+ *
+ */
static VALUE
-ossl_digest_hexdigest(VALUE self)
+ossl_digest_reset(VALUE self)
{
EVP_MD_CTX *ctx;
- char *buf, *hexbuf;
- int buf_len;
- VALUE hexdigest;
GetDigest(self, ctx);
- digest_final(ctx, &buf, &buf_len);
- if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
- OPENSSL_free(buf);
- ossl_raise(eDigestError, "Memory alloc error");
+ if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_get0_md(ctx), NULL) != 1) {
+ ossl_raise(eDigestError, "Digest initialization failed.");
}
- OPENSSL_free(buf);
- hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
- return hexdigest;
+ return self;
}
+/*
+ * call-seq:
+ * digest.update(string) -> aString
+ *
+ * Not every message digest can be computed in one single pass. If a message
+ * digest is to be computed from several subsequent sources, then each may
+ * be passed individually to the Digest instance.
+ *
+ * === Example
+ * digest = OpenSSL::Digest.new('SHA256')
+ * digest.update('First input')
+ * digest << 'Second input' # equivalent to digest.update('Second input')
+ * result = digest.digest
+ *
+ */
static VALUE
-ossl_digest_s_digest(VALUE klass, VALUE str, VALUE data)
+ossl_digest_update(VALUE self, VALUE data)
{
- VALUE obj = rb_class_new_instance(1, &str, klass);
+ EVP_MD_CTX *ctx;
+
+ StringValue(data);
+ GetDigest(self, ctx);
- ossl_digest_update(obj, data);
+ if (!EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)))
+ ossl_raise(eDigestError, "EVP_DigestUpdate");
- return ossl_digest_digest(obj);
+ return self;
}
+/*
+ * call-seq:
+ * digest.finish -> aString
+ *
+ */
static VALUE
-ossl_digest_s_hexdigest(VALUE klass, VALUE str, VALUE data)
+ossl_digest_finish(VALUE self)
{
- VALUE obj = rb_class_new_instance(1, &str, klass);
+ EVP_MD_CTX *ctx;
+ VALUE str;
- ossl_digest_update(obj, data);
+ GetDigest(self, ctx);
+ str = rb_str_new(NULL, EVP_MD_CTX_size(ctx));
+ if (!EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL))
+ ossl_raise(eDigestError, "EVP_DigestFinal_ex");
- return ossl_digest_hexdigest(obj);
+ return str;
}
+/*
+ * call-seq:
+ * digest.name -> string
+ *
+ * Returns the short name of this Digest algorithm which may differ slightly
+ * from the original name provided.
+ *
+ * === Example
+ * digest = OpenSSL::Digest.new('SHA512')
+ * puts digest.name # => SHA512
+ *
+ */
static VALUE
-ossl_digest_equal(VALUE self, VALUE other)
+ossl_digest_name(VALUE self)
{
EVP_MD_CTX *ctx;
- VALUE str1, str2;
- if (rb_obj_is_kind_of(other, cDigest) == Qtrue) {
- str2 = ossl_digest_digest(other);
- } else {
- StringValue(other);
- str2 = other;
- }
GetDigest(self, ctx);
- if (RSTRING(str2)->len == EVP_MD_CTX_size(ctx)) {
- str1 = ossl_digest_digest(self);
- } else {
- str1 = ossl_digest_hexdigest(self);
- }
- if (RSTRING(str1)->len == RSTRING(str2)->len
- && rb_str_cmp(str1, str2) == 0) {
- return Qtrue;
- }
- return Qfalse;
+ return rb_str_new_cstr(EVP_MD_name(EVP_MD_CTX_get0_md(ctx)));
}
+/*
+ * call-seq:
+ * digest.digest_length -> integer
+ *
+ * Returns the output size of the digest, i.e. the length in bytes of the
+ * final message digest result.
+ *
+ * === Example
+ * digest = OpenSSL::Digest.new('SHA1')
+ * puts digest.digest_length # => 20
+ *
+ */
static VALUE
-ossl_digest_name(VALUE self)
+ossl_digest_size(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
- return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
+ return INT2NUM(EVP_MD_CTX_size(ctx));
}
+/*
+ * call-seq:
+ * digest.block_length -> integer
+ *
+ * Returns the block length of the digest algorithm, i.e. the length in bytes
+ * of an individual block. Most modern algorithms partition a message to be
+ * digested into a sequence of fix-sized blocks that are processed
+ * consecutively.
+ *
+ * === Example
+ * digest = OpenSSL::Digest.new('SHA1')
+ * puts digest.block_length # => 64
+ */
static VALUE
-ossl_digest_size(VALUE self)
+ossl_digest_block_length(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
- return INT2NUM(EVP_MD_CTX_size(ctx));
+ return INT2NUM(EVP_MD_CTX_block_size(ctx));
}
/*
* INIT
*/
void
-Init_ossl_digest()
+Init_ossl_digest(void)
{
- mDigest = rb_define_module_under(mOSSL, "Digest");
-
- eDigestError = rb_define_class_under(mDigest, "DigestError", eOSSLError);
-
- cDigest = rb_define_class_under(mDigest, "Digest", rb_cObject);
-
+ /* Document-class: OpenSSL::Digest
+ *
+ * OpenSSL::Digest allows you to compute message digests (sometimes
+ * interchangeably called "hashes") of arbitrary data that are
+ * cryptographically secure, i.e. a Digest implements a secure one-way
+ * function.
+ *
+ * One-way functions offer some useful properties. E.g. given two
+ * distinct inputs the probability that both yield the same output
+ * is highly unlikely. Combined with the fact that every message digest
+ * algorithm has a fixed-length output of just a few bytes, digests are
+ * often used to create unique identifiers for arbitrary data. A common
+ * example is the creation of a unique id for binary documents that are
+ * stored in a database.
+ *
+ * Another useful characteristic of one-way functions (and thus the name)
+ * is that given a digest there is no indication about the original
+ * data that produced it, i.e. the only way to identify the original input
+ * is to "brute-force" through every possible combination of inputs.
+ *
+ * These characteristics make one-way functions also ideal companions
+ * for public key signature algorithms: instead of signing an entire
+ * document, first a hash of the document is produced with a considerably
+ * faster message digest algorithm and only the few bytes of its output
+ * need to be signed using the slower public key algorithm. To validate
+ * the integrity of a signed document, it suffices to re-compute the hash
+ * and verify that it is equal to that in the signature.
+ *
+ * You can get a list of all digest algorithms supported on your system by
+ * running this command in your terminal:
+ *
+ * openssl list -digest-algorithms
+ *
+ * Among the OpenSSL 1.1.1 supported message digest algorithms are:
+ * * SHA224, SHA256, SHA384, SHA512, SHA512-224 and SHA512-256
+ * * SHA3-224, SHA3-256, SHA3-384 and SHA3-512
+ * * BLAKE2s256 and BLAKE2b512
+ *
+ * Each of these algorithms can be instantiated using the name:
+ *
+ * digest = OpenSSL::Digest.new('SHA256')
+ *
+ * "Breaking" a message digest algorithm means defying its one-way
+ * function characteristics, i.e. producing a collision or finding a way
+ * to get to the original data by means that are more efficient than
+ * brute-forcing etc. Most of the supported digest algorithms can be
+ * considered broken in this sense, even the very popular MD5 and SHA1
+ * algorithms. Should security be your highest concern, then you should
+ * probably rely on SHA224, SHA256, SHA384 or SHA512.
+ *
+ * === Hashing a file
+ *
+ * data = File.binread('document')
+ * sha256 = OpenSSL::Digest.new('SHA256')
+ * digest = sha256.digest(data)
+ *
+ * === Hashing several pieces of data at once
+ *
+ * data1 = File.binread('file1')
+ * data2 = File.binread('file2')
+ * data3 = File.binread('file3')
+ * sha256 = OpenSSL::Digest.new('SHA256')
+ * sha256 << data1
+ * sha256 << data2
+ * sha256 << data3
+ * digest = sha256.digest
+ *
+ * === Reuse a Digest instance
+ *
+ * data1 = File.binread('file1')
+ * sha256 = OpenSSL::Digest.new('SHA256')
+ * digest1 = sha256.digest(data1)
+ *
+ * data2 = File.binread('file2')
+ * sha256.reset
+ * digest2 = sha256.digest(data2)
+ *
+ */
+
+ /*
+ * Digest::Class is defined by the digest library. rb_require() cannot be
+ * used here because it bypasses RubyGems.
+ */
+ rb_funcall(Qnil, rb_intern_const("require"), 1, rb_str_new_cstr("digest"));
+ cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
+ /* Document-class: OpenSSL::Digest::DigestError
+ *
+ * Generic Exception class that is raised if an error occurs during a
+ * Digest operation.
+ */
+ eDigestError = rb_define_class_under(cDigest, "DigestError", eOSSLError);
+
rb_define_alloc_func(cDigest, ossl_digest_alloc);
- rb_define_singleton_method(cDigest, "digest", ossl_digest_s_digest, 2);
- rb_define_singleton_method(cDigest, "hexdigest", ossl_digest_s_hexdigest, 2);
-
+
+ rb_define_module_function(cDigest, "digests", ossl_s_digests, 0);
rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1);
+ rb_define_method(cDigest, "initialize_copy", ossl_digest_copy, 1);
rb_define_method(cDigest, "reset", ossl_digest_reset, 0);
-
- rb_define_copy_func(cDigest, ossl_digest_copy);
-
- rb_define_method(cDigest, "digest", ossl_digest_digest, 0);
- rb_define_method(cDigest, "hexdigest", ossl_digest_hexdigest, 0);
- rb_define_alias(cDigest, "inspect", "hexdigest");
- rb_define_alias(cDigest, "to_s", "hexdigest");
-
rb_define_method(cDigest, "update", ossl_digest_update, 1);
rb_define_alias(cDigest, "<<", "update");
-
- rb_define_method(cDigest, "==", ossl_digest_equal, 1);
-
+ rb_define_private_method(cDigest, "finish", ossl_digest_finish, 0);
+ rb_define_method(cDigest, "digest_length", ossl_digest_size, 0);
+ rb_define_method(cDigest, "block_length", ossl_digest_block_length, 0);
+
rb_define_method(cDigest, "name", ossl_digest_name, 0);
- rb_define_method(cDigest, "size", ossl_digest_size, 0);
+
+ id_md_holder = rb_intern_const("EVP_MD_holder");
}
diff --git a/ext/openssl/ossl_digest.h b/ext/openssl/ossl_digest.h
index 8a1f7964f2..9c3bb2b149 100644
--- a/ext/openssl/ossl_digest.h
+++ b/ext/openssl/ossl_digest.h
@@ -1,23 +1,25 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_DIGEST_H_)
#define _OSSL_DIGEST_H_
-extern VALUE mDigest;
-extern VALUE cDigest;
-extern VALUE eDigestError;
-
-const EVP_MD *GetDigestPtr(VALUE);
+/*
+ * Gets EVP_MD from a String or an OpenSSL::Digest instance (discouraged, but
+ * still supported for compatibility). A holder object is created if the EVP_MD
+ * is a "fetched" algorithm.
+ */
+const EVP_MD *ossl_evp_md_fetch(VALUE obj, volatile VALUE *holder);
+/*
+ * This is meant for OpenSSL::Engine#digest. EVP_MD must not be a fetched one.
+ */
VALUE ossl_digest_new(const EVP_MD *);
void Init_ossl_digest(void);
#endif /* _OSSL_DIGEST_H_ */
-
diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
index 71586e3620..a2bcb07ea4 100644
--- a/ext/openssl/ossl_engine.c
+++ b/ext/openssl/ossl_engine.c
@@ -1,57 +1,89 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#if defined(OSSL_ENGINE_ENABLED)
+#ifdef OSSL_USE_ENGINE
+# include <openssl/engine.h>
-#define WrapEngine(klass, obj, engine) do { \
- if (!engine) { \
- ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
+#define NewEngine(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_engine_type, 0)
+#define SetEngine(obj, engine) do { \
+ if (!(engine)) { \
+ ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
} \
- obj = Data_Wrap_Struct(klass, 0, ENGINE_free, engine); \
+ RTYPEDDATA_DATA(obj) = (engine); \
} while(0)
#define GetEngine(obj, engine) do { \
- Data_Get_Struct(obj, ENGINE, engine); \
- if (!engine) { \
+ TypedData_Get_Struct((obj), ENGINE, &ossl_engine_type, (engine)); \
+ if (!(engine)) { \
ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
} \
} while (0)
-#define SafeGetEngine(obj, engine) do { \
- OSSL_Check_Kind(obj, cEngine); \
- GetPKCS7(obj, engine); \
-} while (0)
-/*
+/*
* Classes
*/
-VALUE cEngine;
-VALUE eEngineError;
+/* Document-class: OpenSSL::Engine
+ *
+ * This class is the access to openssl's ENGINE cryptographic module
+ * implementation.
+ *
+ * See also, https://www.openssl.org/docs/crypto/engine.html
+ */
+static VALUE cEngine;
+/* Document-class: OpenSSL::Engine::EngineError
+ *
+ * This is the generic exception for OpenSSL::Engine related errors
+ */
+static VALUE eEngineError;
/*
* Private
*/
-#define OSSL_ENGINE_LOAD_IF_MATCH(x) \
+#define OSSL_ENGINE_LOAD_IF_MATCH(engine_name, x) \
do{\
- if(!strcmp(#x, RSTRING(name)->ptr)){\
- ENGINE_load_##x();\
- return Qtrue;\
- }\
+ if(!strcmp(#engine_name, RSTRING_PTR(name))){\
+ if (OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_##x, NULL))\
+ return Qtrue;\
+ else\
+ ossl_raise(eEngineError, "OPENSSL_init_crypto"); \
+ }\
}while(0)
+static void
+ossl_engine_free(void *engine)
+{
+ ENGINE_free(engine);
+}
+
+static const rb_data_type_t ossl_engine_type = {
+ "OpenSSL/Engine",
+ {
+ 0, ossl_engine_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+/*
+ * call-seq:
+ * OpenSSL::Engine.load(name = nil)
+ *
+ * This method loads engines. If _name_ is nil, then all builtin engines are
+ * loaded. Otherwise, the given _name_, as a String, is loaded if available to
+ * your runtime, and returns true. If _name_ is not found, then nil is
+ * returned.
+ *
+ */
static VALUE
ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
{
-#if !defined(HAVE_ENGINE_LOAD_BUILTIN_ENGINES)
- return Qnil;
-#else
VALUE name;
rb_scan_args(argc, argv, "01", &name);
@@ -59,36 +91,37 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
ENGINE_load_builtin_engines();
return Qtrue;
}
- StringValue(name);
-#ifndef OPENSSL_NO_STATIC_ENGINE
- OSSL_ENGINE_LOAD_IF_MATCH(dynamic);
- OSSL_ENGINE_LOAD_IF_MATCH(cswift);
- OSSL_ENGINE_LOAD_IF_MATCH(chil);
- OSSL_ENGINE_LOAD_IF_MATCH(atalla);
- OSSL_ENGINE_LOAD_IF_MATCH(nuron);
- OSSL_ENGINE_LOAD_IF_MATCH(ubsec);
- OSSL_ENGINE_LOAD_IF_MATCH(aep);
- OSSL_ENGINE_LOAD_IF_MATCH(sureware);
- OSSL_ENGINE_LOAD_IF_MATCH(4758cca);
-#endif
-#ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO
- OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto);
-#endif
- OSSL_ENGINE_LOAD_IF_MATCH(openssl);
- rb_warning("no such builtin loader for `%s'", RSTRING(name)->ptr);
+ StringValueCStr(name);
+ OSSL_ENGINE_LOAD_IF_MATCH(dynamic, DYNAMIC);
+ OSSL_ENGINE_LOAD_IF_MATCH(padlock, PADLOCK);
+ OSSL_ENGINE_LOAD_IF_MATCH(capi, CAPI);
+ OSSL_ENGINE_LOAD_IF_MATCH(cryptodev, CRYPTODEV);
+ OSSL_ENGINE_LOAD_IF_MATCH(openssl, OPENSSL);
+ rb_warning("no such builtin loader for `%"PRIsVALUE"'", name);
return Qnil;
-#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
}
+/*
+ * call-seq:
+ * OpenSSL::Engine.cleanup
+ *
+ * It is only necessary to run cleanup when engines are loaded via
+ * OpenSSL::Engine.load. However, running cleanup before exit is recommended.
+ *
+ * Note that this is needed and works only in OpenSSL < 1.1.0.
+ */
static VALUE
ossl_engine_s_cleanup(VALUE self)
{
-#if defined(HAVE_ENGINE_CLEANUP)
- ENGINE_cleanup();
-#endif
return Qnil;
}
+/*
+ * call-seq:
+ * OpenSSL::Engine.engines -> [engine, ...]
+ *
+ * Returns an array of currently loaded engines.
+ */
static VALUE
ossl_engine_s_engines(VALUE klass)
{
@@ -97,48 +130,62 @@ ossl_engine_s_engines(VALUE klass)
ary = rb_ary_new();
for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)){
- WrapEngine(klass, obj, e);
+ obj = NewEngine(klass);
+ /* Need a ref count of two here because of ENGINE_free being
+ * called internally by OpenSSL when moving to the next ENGINE
+ * and by us when releasing the ENGINE reference */
+ ENGINE_up_ref(e);
+ SetEngine(obj, e);
rb_ary_push(ary, obj);
}
return ary;
}
+/*
+ * call-seq:
+ * OpenSSL::Engine.by_id(name) -> engine
+ *
+ * Fetches the engine as specified by the _id_ String.
+ *
+ * OpenSSL::Engine.by_id("openssl")
+ * => #<OpenSSL::Engine id="openssl" name="Software engine support">
+ *
+ * See OpenSSL::Engine.engines for the currently loaded engines.
+ */
static VALUE
ossl_engine_s_by_id(VALUE klass, VALUE id)
{
ENGINE *e;
VALUE obj;
- StringValue(id);
+ StringValueCStr(id);
ossl_engine_s_load(1, &id, klass);
- if(!(e = ENGINE_by_id(RSTRING(id)->ptr)))
- ossl_raise(eEngineError, NULL);
- WrapEngine(klass, obj, e);
+ obj = NewEngine(klass);
+ if(!(e = ENGINE_by_id(RSTRING_PTR(id))))
+ ossl_raise(eEngineError, NULL);
+ SetEngine(obj, e);
if(rb_block_given_p()) rb_yield(obj);
if(!ENGINE_init(e))
- ossl_raise(eEngineError, NULL);
+ ossl_raise(eEngineError, NULL);
ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK,
- 0, NULL, (void(*)())ossl_pem_passwd_cb);
- ERR_clear_error();
-
- return obj;
-}
-
-static VALUE
-ossl_engine_s_alloc(VALUE klass)
-{
- ENGINE *e;
- VALUE obj;
-
- if (!(e = ENGINE_new())) {
- ossl_raise(eEngineError, NULL);
- }
- WrapEngine(klass, obj, e);
+ 0, NULL, (void(*)(void))ossl_pem_passwd_cb);
+ ossl_clear_error();
return obj;
}
+/*
+ * call-seq:
+ * engine.id -> string
+ *
+ * Gets the id for this engine.
+ *
+ * OpenSSL::Engine.load
+ * OpenSSL::Engine.engines #=> [#<OpenSSL::Engine#>, ...]
+ * OpenSSL::Engine.engines.first.id
+ * #=> "rsax"
+ */
static VALUE
ossl_engine_get_id(VALUE self)
{
@@ -147,6 +194,18 @@ ossl_engine_get_id(VALUE self)
return rb_str_new2(ENGINE_get_id(e));
}
+/*
+ * call-seq:
+ * engine.name -> string
+ *
+ * Get the descriptive name for this engine.
+ *
+ * OpenSSL::Engine.load
+ * OpenSSL::Engine.engines #=> [#<OpenSSL::Engine#>, ...]
+ * OpenSSL::Engine.engines.first.name
+ * #=> "RSAX engine support"
+ *
+ */
static VALUE
ossl_engine_get_name(VALUE self)
{
@@ -155,6 +214,14 @@ ossl_engine_get_name(VALUE self)
return rb_str_new2(ENGINE_get_name(e));
}
+/*
+ * call-seq:
+ * engine.finish -> nil
+ *
+ * Releases all internal structural references for this engine.
+ *
+ * May raise an EngineError if the engine is unavailable
+ */
static VALUE
ossl_engine_finish(VALUE self)
{
@@ -166,52 +233,79 @@ ossl_engine_finish(VALUE self)
return Qnil;
}
+/*
+ * call-seq:
+ * engine.cipher(name) -> OpenSSL::Cipher
+ *
+ * Returns a new instance of OpenSSL::Cipher by _name_, if it is available in
+ * this engine.
+ *
+ * An EngineError will be raised if the cipher is unavailable.
+ *
+ * e = OpenSSL::Engine.by_id("openssl")
+ * => #<OpenSSL::Engine id="openssl" name="Software engine support">
+ * e.cipher("RC4")
+ * => #<OpenSSL::Cipher:0x007fc5cacc3048>
+ *
+ */
static VALUE
ossl_engine_get_cipher(VALUE self, VALUE name)
{
-#if defined(HAVE_ENGINE_GET_CIPHER)
ENGINE *e;
const EVP_CIPHER *ciph, *tmp;
- char *s;
int nid;
- s = StringValuePtr(name);
- tmp = EVP_get_cipherbyname(s);
- if(!tmp) ossl_raise(eEngineError, "no such cipher `%s'", s);
+ tmp = EVP_get_cipherbyname(StringValueCStr(name));
+ if(!tmp) ossl_raise(eEngineError, "no such cipher `%"PRIsVALUE"'", name);
nid = EVP_CIPHER_nid(tmp);
GetEngine(self, e);
ciph = ENGINE_get_cipher(e, nid);
if(!ciph) ossl_raise(eEngineError, NULL);
return ossl_cipher_new(ciph);
-#else
- rb_notimplement();
-#endif
}
+/*
+ * call-seq:
+ * engine.digest(name) -> OpenSSL::Digest
+ *
+ * Returns a new instance of OpenSSL::Digest by _name_.
+ *
+ * Will raise an EngineError if the digest is unavailable.
+ *
+ * e = OpenSSL::Engine.by_id("openssl")
+ * #=> #<OpenSSL::Engine id="openssl" name="Software engine support">
+ * e.digest("SHA1")
+ * #=> #<OpenSSL::Digest: da39a3ee5e6b4b0d3255bfef95601890afd80709>
+ * e.digest("zomg")
+ * #=> OpenSSL::Engine::EngineError: no such digest `zomg'
+ */
static VALUE
ossl_engine_get_digest(VALUE self, VALUE name)
{
-#if defined(HAVE_ENGINE_GET_DIGEST)
ENGINE *e;
const EVP_MD *md, *tmp;
- char *s;
int nid;
- s = StringValuePtr(name);
- tmp = EVP_get_digestbyname(s);
- if(!tmp) ossl_raise(eEngineError, "no such digest `%s'", s);
+ tmp = EVP_get_digestbyname(StringValueCStr(name));
+ if(!tmp) ossl_raise(eEngineError, "no such digest `%"PRIsVALUE"'", name);
nid = EVP_MD_nid(tmp);
GetEngine(self, e);
md = ENGINE_get_digest(e, nid);
if(!md) ossl_raise(eEngineError, NULL);
return ossl_digest_new(md);
-#else
- rb_notimplement();
-#endif
}
+/*
+ * call-seq:
+ * engine.load_private_key(id = nil, data = nil) -> OpenSSL::PKey
+ *
+ * Loads the given private key identified by _id_ and _data_.
+ *
+ * An EngineError is raised of the OpenSSL::PKey is unavailable.
+ *
+ */
static VALUE
ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self)
{
@@ -221,21 +315,26 @@ ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self)
char *sid, *sdata;
rb_scan_args(argc, argv, "02", &id, &data);
- sid = NIL_P(id) ? NULL : StringValuePtr(id);
- sdata = NIL_P(data) ? NULL : StringValuePtr(data);
+ sid = NIL_P(id) ? NULL : StringValueCStr(id);
+ sdata = NIL_P(data) ? NULL : StringValueCStr(data);
GetEngine(self, e);
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
- pkey = ENGINE_load_private_key(e, sid, sdata);
-#else
pkey = ENGINE_load_private_key(e, sid, NULL, sdata);
-#endif
if (!pkey) ossl_raise(eEngineError, NULL);
- obj = ossl_pkey_new(pkey);
+ obj = ossl_pkey_wrap(pkey);
OSSL_PKEY_SET_PRIVATE(obj);
return obj;
}
+/*
+ * call-seq:
+ * engine.load_public_key(id = nil, data = nil) -> OpenSSL::PKey
+ *
+ * Loads the given public key identified by _id_ and _data_.
+ *
+ * An EngineError is raised of the OpenSSL::PKey is unavailable.
+ *
+ */
static VALUE
ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self)
{
@@ -245,19 +344,31 @@ ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self)
char *sid, *sdata;
rb_scan_args(argc, argv, "02", &id, &data);
- sid = NIL_P(id) ? NULL : StringValuePtr(id);
- sdata = NIL_P(data) ? NULL : StringValuePtr(data);
+ sid = NIL_P(id) ? NULL : StringValueCStr(id);
+ sdata = NIL_P(data) ? NULL : StringValueCStr(data);
GetEngine(self, e);
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
- pkey = ENGINE_load_public_key(e, sid, sdata);
-#else
pkey = ENGINE_load_public_key(e, sid, NULL, sdata);
-#endif
if (!pkey) ossl_raise(eEngineError, NULL);
- return ossl_pkey_new(pkey);
+ return ossl_pkey_wrap(pkey);
}
+/*
+ * call-seq:
+ * engine.set_default(flag)
+ *
+ * Set the defaults for this engine with the given _flag_.
+ *
+ * These flags are used to control combinations of algorithm methods.
+ *
+ * _flag_ can be one of the following, other flags are available depending on
+ * your OS.
+ *
+ * [All flags] 0xFFFF
+ * [No flags] 0x0000
+ *
+ * See also <openssl/engine.h>
+ */
static VALUE
ossl_engine_set_default(VALUE self, VALUE flag)
{
@@ -270,6 +381,14 @@ ossl_engine_set_default(VALUE self, VALUE flag)
return Qtrue;
}
+/*
+ * call-seq:
+ * engine.ctrl_cmd(command, value = nil) -> engine
+ *
+ * Sends the given _command_ to this engine.
+ *
+ * Raises an EngineError if the command fails.
+ */
static VALUE
ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
{
@@ -279,10 +398,8 @@ ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
GetEngine(self, e);
rb_scan_args(argc, argv, "11", &cmd, &val);
- StringValue(cmd);
- if (!NIL_P(val)) StringValue(val);
- ret = ENGINE_ctrl_cmd_string(e, RSTRING(cmd)->ptr,
- NIL_P(val) ? NULL : RSTRING(val)->ptr, 0);
+ ret = ENGINE_ctrl_cmd_string(e, StringValueCStr(cmd),
+ NIL_P(val) ? NULL : StringValueCStr(val), 0);
if (!ret) ossl_raise(eEngineError, NULL);
return self;
@@ -292,14 +409,20 @@ static VALUE
ossl_engine_cmd_flag_to_name(int flag)
{
switch(flag){
- case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC");
- case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING");
- case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT");
- case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL");
- default: return rb_str_new2("UNKNOWN");
+ case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC");
+ case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING");
+ case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT");
+ case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL");
+ default: return rb_str_new2("UNKNOWN");
}
}
+/*
+ * call-seq:
+ * engine.cmds -> [["name", "description", "flags"], ...]
+ *
+ * Returns an array of command definitions for the current engine
+ */
static VALUE
ossl_engine_get_cmds(VALUE self)
{
@@ -310,49 +433,47 @@ ossl_engine_get_cmds(VALUE self)
GetEngine(self, e);
ary = rb_ary_new();
if ((defn = ENGINE_get_cmd_defns(e)) != NULL){
- for (p = defn; p->cmd_num > 0; p++){
- tmp = rb_ary_new();
- rb_ary_push(tmp, rb_str_new2(p->cmd_name));
- rb_ary_push(tmp, rb_str_new2(p->cmd_desc));
- rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags));
- rb_ary_push(ary, tmp);
- }
+ for (p = defn; p->cmd_num > 0; p++){
+ tmp = rb_ary_new();
+ rb_ary_push(tmp, rb_str_new2(p->cmd_name));
+ rb_ary_push(tmp, rb_str_new2(p->cmd_desc));
+ rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags));
+ rb_ary_push(ary, tmp);
+ }
}
return ary;
}
+/*
+ * call-seq:
+ * engine.inspect -> string
+ *
+ * Pretty prints this engine.
+ */
static VALUE
ossl_engine_inspect(VALUE self)
{
- VALUE str;
- char *cname = rb_class2name(rb_obj_class(self));
-
- str = rb_str_new2("#<");
- rb_str_cat2(str, cname);
- rb_str_cat2(str, " id=\"");
- rb_str_append(str, ossl_engine_get_id(self));
- rb_str_cat2(str, "\" name=\"");
- rb_str_append(str, ossl_engine_get_name(self));
- rb_str_cat2(str, "\">");
-
- return str;
+ ENGINE *e;
+
+ GetEngine(self, e);
+ return rb_sprintf("#<%"PRIsVALUE" id=\"%s\" name=\"%s\">",
+ rb_obj_class(self), ENGINE_get_id(e), ENGINE_get_name(e));
}
#define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x))
void
-Init_ossl_engine()
+Init_ossl_engine(void)
{
cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject);
eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError);
- rb_define_alloc_func(cEngine, ossl_engine_s_alloc);
+ rb_undef_alloc_func(cEngine);
rb_define_singleton_method(cEngine, "load", ossl_engine_s_load, -1);
rb_define_singleton_method(cEngine, "cleanup", ossl_engine_s_cleanup, 0);
rb_define_singleton_method(cEngine, "engines", ossl_engine_s_engines, 0);
rb_define_singleton_method(cEngine, "by_id", ossl_engine_s_by_id, 1);
- rb_undef_method(CLASS_OF(cEngine), "new");
rb_define_method(cEngine, "id", ossl_engine_get_id, 0);
rb_define_method(cEngine, "name", ossl_engine_get_name, 0);
@@ -370,24 +491,14 @@ Init_ossl_engine()
DefEngineConst(METHOD_DSA);
DefEngineConst(METHOD_DH);
DefEngineConst(METHOD_RAND);
-#ifdef ENGINE_METHOD_BN_MOD_EXP
- DefEngineConst(METHOD_BN_MOD_EXP);
-#endif
-#ifdef ENGINE_METHOD_BN_MOD_EXP_CRT
- DefEngineConst(METHOD_BN_MOD_EXP_CRT);
-#endif
-#ifdef ENGINE_METHOD_CIPHERS
DefEngineConst(METHOD_CIPHERS);
-#endif
-#ifdef ENGINE_METHOD_DIGESTS
DefEngineConst(METHOD_DIGESTS);
-#endif
DefEngineConst(METHOD_ALL);
DefEngineConst(METHOD_NONE);
}
#else
void
-Init_ossl_engine()
+Init_ossl_engine(void)
{
}
#endif
diff --git a/ext/openssl/ossl_engine.h b/ext/openssl/ossl_engine.h
index ea2f256912..cedcebb772 100644
--- a/ext/openssl/ossl_engine.h
+++ b/ext/openssl/ossl_engine.h
@@ -1,20 +1,16 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
* Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(OSSL_ENGINE_H)
#define OSSL_ENGINE_H
-extern VALUE cEngine;
-extern VALUE eEngineError;
-
void Init_ossl_engine(void);
#endif /* OSSL_ENGINE_H */
diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c
index ca5917518f..ddcc6a5f8d 100644
--- a/ext/openssl/ossl_hmac.c
+++ b/ext/openssl/ossl_hmac.c
@@ -1,35 +1,29 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
-#if !defined(OPENSSL_NO_HMAC)
-
#include "ossl.h"
-#define MakeHMAC(obj, klass, ctx) \
- obj = Data_Make_Struct(klass, HMAC_CTX, 0, ossl_hmac_free, ctx)
+#define NewHMAC(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_hmac_type, 0)
#define GetHMAC(obj, ctx) do { \
- Data_Get_Struct(obj, HMAC_CTX, ctx); \
- if (!ctx) { \
- ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \
+ TypedData_Get_Struct((obj), EVP_MD_CTX, &ossl_hmac_type, (ctx)); \
+ if (!(ctx)) { \
+ ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \
} \
} while (0)
-#define SafeGetHMAC(obj, ctx) do { \
- OSSL_Check_Kind(obj, cHMAC); \
- GetHMAC(obj, ctx); \
-} while (0)
/*
* Classes
*/
-VALUE cHMAC;
-VALUE eHMACError;
+static VALUE cHMAC;
+static VALUE eHMACError;
+static ID id_md_holder;
/*
* Public
@@ -39,182 +33,272 @@ VALUE eHMACError;
* Private
*/
static void
-ossl_hmac_free(HMAC_CTX *ctx)
+ossl_hmac_free(void *ctx)
{
- HMAC_CTX_cleanup(ctx);
- free(ctx);
+ EVP_MD_CTX_free(ctx);
}
+static const rb_data_type_t ossl_hmac_type = {
+ "OpenSSL/HMAC",
+ {
+ 0, ossl_hmac_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
static VALUE
ossl_hmac_alloc(VALUE klass)
{
- HMAC_CTX *ctx;
VALUE obj;
+ EVP_MD_CTX *ctx;
+
+ obj = NewHMAC(klass);
+ ctx = EVP_MD_CTX_new();
+ if (!ctx)
+ ossl_raise(eHMACError, "EVP_MD_CTX");
+ RTYPEDDATA_DATA(obj) = ctx;
- MakeHMAC(obj, klass, ctx);
- HMAC_CTX_init(ctx);
-
return obj;
}
+
+/*
+ * call-seq:
+ * HMAC.new(key, digest) -> hmac
+ *
+ * Returns an instance of OpenSSL::HMAC set with the key and digest
+ * algorithm to be used. The instance represents the initial state of
+ * the message authentication code before any data has been processed.
+ * To process data with it, use the instance method #update with your
+ * data as an argument.
+ *
+ * === Example
+ *
+ * key = 'key'
+ * instance = OpenSSL::HMAC.new(key, 'SHA1')
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
+ * instance.class
+ * #=> OpenSSL::HMAC
+ *
+ * === A note about comparisons
+ *
+ * Two instances can be securely compared with #== in constant time:
+ *
+ * other_instance = OpenSSL::HMAC.new('key', 'SHA1')
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
+ * instance == other_instance
+ * #=> true
+ *
+ */
static VALUE
ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
{
- HMAC_CTX *ctx;
+ EVP_MD_CTX *ctx;
+ EVP_PKEY *pkey;
+ const EVP_MD *md;
+ VALUE md_holder;
- StringValue(key);
GetHMAC(self, ctx);
- HMAC_Init_ex(ctx, RSTRING(key)->ptr, RSTRING(key)->len,
- GetDigestPtr(digest), NULL);
+ StringValue(key);
+ md = ossl_evp_md_fetch(digest, &md_holder);
+ pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
+ (unsigned char *)RSTRING_PTR(key),
+ RSTRING_LENINT(key));
+ if (!pkey)
+ ossl_raise(eHMACError, "EVP_PKEY_new_raw_private_key");
+ if (EVP_DigestSignInit(ctx, NULL, md, NULL, pkey) != 1) {
+ EVP_PKEY_free(pkey);
+ ossl_raise(eHMACError, "EVP_DigestSignInit");
+ }
+ rb_ivar_set(self, id_md_holder, md_holder);
+ /* Decrement reference counter; EVP_MD_CTX still keeps it */
+ EVP_PKEY_free(pkey);
return self;
}
+/* :nodoc: */
static VALUE
ossl_hmac_copy(VALUE self, VALUE other)
{
- HMAC_CTX *ctx1, *ctx2;
-
+ EVP_MD_CTX *ctx1, *ctx2;
+
rb_check_frozen(self);
if (self == other) return self;
GetHMAC(self, ctx1);
- SafeGetHMAC(other, ctx2);
-
- if (!HMAC_CTX_copy(ctx1, ctx2)) {
- ossl_raise(eHMACError, NULL);
- }
+ GetHMAC(other, ctx2);
+ if (EVP_MD_CTX_copy(ctx1, ctx2) != 1)
+ ossl_raise(eHMACError, "EVP_MD_CTX_copy");
return self;
}
+/*
+ * call-seq:
+ * hmac.update(string) -> self
+ *
+ * Returns _hmac_ updated with the message to be authenticated.
+ * Can be called repeatedly with chunks of the message.
+ *
+ * === Example
+ *
+ * first_chunk = 'The quick brown fox jumps '
+ * second_chunk = 'over the lazy dog'
+ *
+ * instance.update(first_chunk)
+ * #=> 5b9a8038a65d571076d97fe783989e52278a492a
+ * instance.update(second_chunk)
+ * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
+ *
+ */
static VALUE
ossl_hmac_update(VALUE self, VALUE data)
{
- HMAC_CTX *ctx;
+ EVP_MD_CTX *ctx;
StringValue(data);
GetHMAC(self, ctx);
- HMAC_Update(ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+ if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
+ ossl_raise(eHMACError, "EVP_DigestSignUpdate");
return self;
}
-static void
-hmac_final(HMAC_CTX *ctx, char **buf, int *buf_len)
-{
- HMAC_CTX final;
-
- if (!HMAC_CTX_copy(&final, ctx)) {
- ossl_raise(eHMACError, NULL);
- }
- if (!(*buf = OPENSSL_malloc(HMAC_size(&final)))) {
- HMAC_CTX_cleanup(&final);
- OSSL_Debug("Allocating %d mem", HMAC_size(&final));
- ossl_raise(eHMACError, "Cannot allocate memory for hmac");
- }
- HMAC_Final(&final, *buf, buf_len);
- HMAC_CTX_cleanup(&final);
-}
-
+/*
+ * call-seq:
+ * hmac.digest -> string
+ *
+ * Returns the authentication code an instance represents as a binary string.
+ *
+ * === Example
+ * instance = OpenSSL::HMAC.new('key', 'SHA1')
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
+ * instance.digest
+ * #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?"
+ */
static VALUE
ossl_hmac_digest(VALUE self)
{
- HMAC_CTX *ctx;
- char *buf;
- int buf_len;
- VALUE digest;
-
- GetHMAC(self, ctx);
- hmac_final(ctx, &buf, &buf_len);
- digest = ossl_buf2str(buf, buf_len);
-
- return digest;
-}
+ EVP_MD_CTX *ctx;
+ size_t buf_len = EVP_MAX_MD_SIZE;
+ VALUE ret;
-static VALUE
-ossl_hmac_hexdigest(VALUE self)
-{
- HMAC_CTX *ctx;
- char *buf, *hexbuf;
- int buf_len;
- VALUE hexdigest;
-
GetHMAC(self, ctx);
- hmac_final(ctx, &buf, &buf_len);
- if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
- OPENSSL_free(buf);
- ossl_raise(eHMACError, "Memory alloc error");
- }
- OPENSSL_free(buf);
- hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
+ ret = rb_str_new(NULL, EVP_MAX_MD_SIZE);
+ if (EVP_DigestSignFinal(ctx, (unsigned char *)RSTRING_PTR(ret),
+ &buf_len) != 1)
+ ossl_raise(eHMACError, "EVP_DigestSignFinal");
+ rb_str_set_len(ret, (long)buf_len);
- return hexdigest;
+ return ret;
}
+/*
+ * call-seq:
+ * hmac.hexdigest -> string
+ *
+ * Returns the authentication code an instance represents as a hex-encoded
+ * string.
+ */
static VALUE
-ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
+ossl_hmac_hexdigest(VALUE self)
{
- char *buf;
- int buf_len;
-
- StringValue(key);
- StringValue(data);
- buf = HMAC(GetDigestPtr(digest), RSTRING(key)->ptr, RSTRING(key)->len,
- RSTRING(data)->ptr, RSTRING(data)->len, NULL, &buf_len);
+ EVP_MD_CTX *ctx;
+ unsigned char buf[EVP_MAX_MD_SIZE];
+ size_t buf_len = EVP_MAX_MD_SIZE;
+ VALUE ret;
+
+ GetHMAC(self, ctx);
+ if (EVP_DigestSignFinal(ctx, buf, &buf_len) != 1)
+ ossl_raise(eHMACError, "EVP_DigestSignFinal");
+ ret = rb_str_new(NULL, buf_len * 2);
+ ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len);
- return rb_str_new(buf, buf_len);
+ return ret;
}
+/*
+ * call-seq:
+ * hmac.reset -> self
+ *
+ * Returns _hmac_ as it was when it was first initialized, with all processed
+ * data cleared from it.
+ *
+ * === Example
+ *
+ * data = "The quick brown fox jumps over the lazy dog"
+ * instance = OpenSSL::HMAC.new('key', 'SHA1')
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
+ *
+ * instance.update(data)
+ * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
+ * instance.reset
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
+ *
+ */
static VALUE
-ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
+ossl_hmac_reset(VALUE self)
{
- char *buf, *hexbuf;
- int buf_len;
- VALUE hexdigest;
+ EVP_MD_CTX *ctx;
+ EVP_PKEY *pkey;
- StringValue(key);
- StringValue(data);
-
- buf = HMAC(GetDigestPtr(digest), RSTRING(key)->ptr, RSTRING(key)->len,
- RSTRING(data)->ptr, RSTRING(data)->len, NULL, &buf_len);
- if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
- ossl_raise(eHMACError, "Cannot convert buf to hexbuf");
- }
- hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
+ GetHMAC(self, ctx);
+ pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
+ if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_get0_md(ctx), NULL, pkey) != 1)
+ ossl_raise(eHMACError, "EVP_DigestSignInit");
- return hexdigest;
+ return self;
}
/*
* INIT
*/
void
-Init_ossl_hmac()
+Init_ossl_hmac(void)
{
+ /*
+ * Document-class: OpenSSL::HMAC
+ *
+ * OpenSSL::HMAC allows computing Hash-based Message Authentication Code
+ * (HMAC). It is a type of message authentication code (MAC) involving a
+ * hash function in combination with a key. HMAC can be used to verify the
+ * integrity of a message as well as the authenticity.
+ *
+ * OpenSSL::HMAC has a similar interface to OpenSSL::Digest.
+ *
+ * === HMAC-SHA256 using one-shot interface
+ *
+ * key = "key"
+ * data = "message-to-be-authenticated"
+ * mac = OpenSSL::HMAC.hexdigest("SHA256", key, data)
+ * #=> "cddb0db23f469c8bf072b21fd837149bd6ace9ab771cceef14c9e517cc93282e"
+ *
+ * === HMAC-SHA256 using incremental interface
+ *
+ * data1 = File.binread("file1")
+ * data2 = File.binread("file2")
+ * key = "key"
+ * hmac = OpenSSL::HMAC.new(key, 'SHA256')
+ * hmac << data1
+ * hmac << data2
+ * mac = hmac.digest
+ */
eHMACError = rb_define_class_under(mOSSL, "HMACError", eOSSLError);
-
+
cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject);
rb_define_alloc_func(cHMAC, ossl_hmac_alloc);
- rb_define_singleton_method(cHMAC, "digest", ossl_hmac_s_digest, 3);
- rb_define_singleton_method(cHMAC, "hexdigest", ossl_hmac_s_hexdigest, 3);
-
+
rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2);
- rb_define_copy_func(cHMAC, ossl_hmac_copy);
+ rb_define_method(cHMAC, "initialize_copy", ossl_hmac_copy, 1);
+ rb_define_method(cHMAC, "reset", ossl_hmac_reset, 0);
rb_define_method(cHMAC, "update", ossl_hmac_update, 1);
rb_define_alias(cHMAC, "<<", "update");
rb_define_method(cHMAC, "digest", ossl_hmac_digest, 0);
rb_define_method(cHMAC, "hexdigest", ossl_hmac_hexdigest, 0);
rb_define_alias(cHMAC, "inspect", "hexdigest");
rb_define_alias(cHMAC, "to_s", "hexdigest");
-}
-#else /* NO_HMAC */
-# warning >>> OpenSSL is compiled without HMAC support <<<
-void
-Init_ossl_hmac()
-{
- rb_warning("HMAC will NOT be avaible: OpenSSL is compiled without HMAC.");
+ id_md_holder = rb_intern_const("EVP_MD_holder");
}
-#endif /* NO_HMAC */
diff --git a/ext/openssl/ossl_hmac.h b/ext/openssl/ossl_hmac.h
index 1a2978b39a..e5bed37c9f 100644
--- a/ext/openssl/ossl_hmac.h
+++ b/ext/openssl/ossl_hmac.h
@@ -1,19 +1,15 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_HMAC_H_)
#define _OSSL_HMAC_H_
-extern VALUE cHMAC;
-extern VALUE eHMACError;
-
void Init_ossl_hmac(void);
#endif /* _OSSL_HMAC_H_ */
diff --git a/ext/openssl/ossl_kdf.c b/ext/openssl/ossl_kdf.c
new file mode 100644
index 0000000000..99a3589b39
--- /dev/null
+++ b/ext/openssl/ossl_kdf.c
@@ -0,0 +1,376 @@
+/*
+ * Ruby/OpenSSL Project
+ * Copyright (C) 2007, 2017 Ruby/OpenSSL Project Authors
+ */
+#include "ossl.h"
+#include <openssl/kdf.h>
+
+static VALUE mKDF, eKDF;
+
+struct pbkdf2_hmac_args {
+ char *pass;
+ int passlen;
+ unsigned char *salt;
+ int saltlen;
+ int iters;
+ const EVP_MD *md;
+ int len;
+ unsigned char *out;
+};
+
+static void *
+pbkdf2_hmac_nogvl(void *args_)
+{
+ struct pbkdf2_hmac_args *args = (struct pbkdf2_hmac_args *)args_;
+ int ret = PKCS5_PBKDF2_HMAC(args->pass, args->passlen, args->salt,
+ args->saltlen, args->iters, args->md,
+ args->len, args->out);
+ return (void *)(uintptr_t)ret;
+}
+
+/*
+ * call-seq:
+ * KDF.pbkdf2_hmac(pass, salt:, iterations:, length:, hash:) -> aString
+ *
+ * PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in combination
+ * with HMAC. Takes _pass_, _salt_ and _iterations_, and then derives a key
+ * of _length_ bytes.
+ *
+ * For more information about PBKDF2, see RFC 2898 Section 5.2
+ * (https://www.rfc-editor.org/rfc/rfc2898#section-5.2).
+ *
+ * *NOTE*: This method cannot be interrupted by Timeout.timeout from the
+ * "timeout" library. Do not take parameters from untrusted sources without
+ * enforcing reasonable limits.
+ *
+ * === Parameters
+ * pass :: The password.
+ * salt :: The salt. Salts prevent attacks based on dictionaries of common
+ * passwords and attacks based on rainbow tables. It is a public
+ * value that can be safely stored along with the password (e.g.
+ * if the derived value is used for password storage).
+ * iterations :: The iteration count. This provides the ability to tune the
+ * algorithm. It is better to use the highest count possible for
+ * the maximum resistance to brute-force attacks.
+ * length :: The desired length of the derived key in octets.
+ * hash :: The hash algorithm used with HMAC for the PRF. May be a String
+ * representing the algorithm name, or an instance of
+ * OpenSSL::Digest.
+ */
+static VALUE
+kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self)
+{
+ VALUE pass, salt, opts, kwargs[4], str, md_holder, pass_tmp, salt_tmp;
+ static ID kwargs_ids[4];
+ int passlen, saltlen, iters, len;
+ const EVP_MD *md;
+
+ if (!kwargs_ids[0]) {
+ kwargs_ids[0] = rb_intern_const("salt");
+ kwargs_ids[1] = rb_intern_const("iterations");
+ kwargs_ids[2] = rb_intern_const("length");
+ kwargs_ids[3] = rb_intern_const("hash");
+ }
+ rb_scan_args(argc, argv, "1:", &pass, &opts);
+ rb_get_kwargs(opts, kwargs_ids, 4, 0, kwargs);
+
+ StringValue(pass);
+ salt = StringValue(kwargs[0]);
+ iters = NUM2INT(kwargs[1]);
+ len = NUM2INT(kwargs[2]);
+ md = ossl_evp_md_fetch(kwargs[3], &md_holder);
+ passlen = RSTRING_LENINT(pass);
+ saltlen = RSTRING_LENINT(salt);
+ str = rb_str_new(NULL, len);
+ struct pbkdf2_hmac_args args = {
+ .pass = ALLOCV(pass_tmp, passlen),
+ .passlen = passlen,
+ .salt = ALLOCV(salt_tmp, saltlen),
+ .saltlen = saltlen,
+ .iters = iters,
+ .md = md,
+ .len = len,
+ .out = (unsigned char *)RSTRING_PTR(str),
+ };
+ memcpy(args.pass, RSTRING_PTR(pass), passlen);
+ memcpy(args.salt, RSTRING_PTR(salt), saltlen);
+ if (!rb_thread_call_without_gvl(pbkdf2_hmac_nogvl, &args, NULL, NULL))
+ ossl_raise(eKDF, "PKCS5_PBKDF2_HMAC");
+ OPENSSL_cleanse(args.pass, passlen);
+ ALLOCV_END(pass_tmp);
+ ALLOCV_END(salt_tmp);
+ return str;
+}
+
+#if defined(HAVE_EVP_PBE_SCRYPT)
+struct scrypt_args {
+ char *pass;
+ size_t passlen;
+ unsigned char *salt;
+ size_t saltlen;
+ uint64_t N, r, p;
+ size_t len;
+ unsigned char *out;
+};
+
+static void *
+scrypt_nogvl(void *args_)
+{
+ struct scrypt_args *args = (struct scrypt_args *)args_;
+ /*
+ * OpenSSL uses 32MB by default (if zero is specified), which is too
+ * small. Let's not limit memory consumption but just let malloc() fail
+ * inside OpenSSL. The amount is controllable by other parameters.
+ */
+ uint64_t maxmem = UINT64_MAX;
+ int ret = EVP_PBE_scrypt(args->pass, args->passlen,
+ args->salt, args->saltlen, args->N, args->r,
+ args->p, maxmem, args->out, args->len);
+ return (void *)(uintptr_t)ret;
+}
+
+/*
+ * call-seq:
+ * KDF.scrypt(pass, salt:, N:, r:, p:, length:) -> aString
+ *
+ * Derives a key from _pass_ using given parameters with the scrypt
+ * password-based key derivation function. The result can be used for password
+ * storage.
+ *
+ * scrypt is designed to be memory-hard and more secure against brute-force
+ * attacks using custom hardwares than alternative KDFs such as PBKDF2 or
+ * bcrypt.
+ *
+ * The keyword arguments _N_, _r_ and _p_ can be used to tune scrypt. RFC 7914
+ * (published on 2016-08, https://www.rfc-editor.org/rfc/rfc7914#section-2) states
+ * that using values r=8 and p=1 appears to yield good results.
+ *
+ * See RFC 7914 (https://www.rfc-editor.org/rfc/rfc7914) for more information.
+ *
+ * *NOTE*: This method cannot be interrupted by Timeout.timeout from the
+ * "timeout" library. Do not take parameters from untrusted sources without
+ * enforcing reasonable limits.
+ *
+ * === Parameters
+ * pass :: Passphrase.
+ * salt :: Salt.
+ * N :: CPU/memory cost parameter. This must be a power of 2.
+ * r :: Block size parameter.
+ * p :: Parallelization parameter.
+ * length :: Length in octets of the derived key.
+ *
+ * === Example
+ * pass = "password"
+ * salt = SecureRandom.random_bytes(16)
+ * dk = OpenSSL::KDF.scrypt(pass, salt: salt, N: 2**14, r: 8, p: 1, length: 32)
+ * p dk #=> "\xDA\xE4\xE2...\x7F\xA1\x01T"
+ */
+static VALUE
+kdf_scrypt(int argc, VALUE *argv, VALUE self)
+{
+ VALUE pass, salt, opts, kwargs[5], str, pass_tmp, salt_tmp;
+ static ID kwargs_ids[5];
+ size_t passlen, saltlen;
+ long len;
+ uint64_t N, r, p;
+
+ if (!kwargs_ids[0]) {
+ kwargs_ids[0] = rb_intern_const("salt");
+ kwargs_ids[1] = rb_intern_const("N");
+ kwargs_ids[2] = rb_intern_const("r");
+ kwargs_ids[3] = rb_intern_const("p");
+ kwargs_ids[4] = rb_intern_const("length");
+ }
+ rb_scan_args(argc, argv, "1:", &pass, &opts);
+ rb_get_kwargs(opts, kwargs_ids, 5, 0, kwargs);
+
+ StringValue(pass);
+ salt = StringValue(kwargs[0]);
+ N = NUM2UINT64T(kwargs[1]);
+ r = NUM2UINT64T(kwargs[2]);
+ p = NUM2UINT64T(kwargs[3]);
+ len = NUM2LONG(kwargs[4]);
+ passlen = RSTRING_LEN(pass);
+ saltlen = RSTRING_LEN(salt);
+ str = rb_str_new(NULL, len);
+ struct scrypt_args args = {
+ .pass = ALLOCV(pass_tmp, passlen),
+ .passlen = passlen,
+ .salt = ALLOCV(salt_tmp, saltlen),
+ .saltlen = saltlen,
+ .N = N,
+ .r = r,
+ .p = p,
+ .len = len,
+ .out = (unsigned char *)RSTRING_PTR(str),
+ };
+ memcpy(args.pass, RSTRING_PTR(pass), passlen);
+ memcpy(args.salt, RSTRING_PTR(salt), saltlen);
+ if (!rb_thread_call_without_gvl(scrypt_nogvl, &args, NULL, NULL))
+ ossl_raise(eKDF, "EVP_PBE_scrypt");
+ OPENSSL_cleanse(args.pass, passlen);
+ ALLOCV_END(pass_tmp);
+ ALLOCV_END(salt_tmp);
+ return str;
+}
+#endif
+
+/*
+ * call-seq:
+ * KDF.hkdf(ikm, salt:, info:, length:, hash:) -> String
+ *
+ * HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as specified in
+ * {RFC 5869}[https://www.rfc-editor.org/rfc/rfc5869].
+ *
+ * New in OpenSSL 1.1.0.
+ *
+ * === Parameters
+ * _ikm_::
+ * The input keying material.
+ * _salt_::
+ * The salt.
+ * _info_::
+ * The context and application specific information.
+ * _length_::
+ * The output length in octets. Must be <= <tt>255 * HashLen</tt>, where
+ * HashLen is the length of the hash function output in octets.
+ * _hash_::
+ * The hash function.
+ *
+ * === Example
+ * # The values from https://www.rfc-editor.org/rfc/rfc5869#appendix-A.1
+ * ikm = ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*")
+ * salt = ["000102030405060708090a0b0c"].pack("H*")
+ * info = ["f0f1f2f3f4f5f6f7f8f9"].pack("H*")
+ * p OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: 42, hash: "SHA256").unpack1("H*")
+ * # => "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
+ */
+static VALUE
+kdf_hkdf(int argc, VALUE *argv, VALUE self)
+{
+ VALUE ikm, salt, info, opts, kwargs[4], str, md_holder;
+ static ID kwargs_ids[4];
+ int saltlen, ikmlen, infolen;
+ size_t len;
+ const EVP_MD *md;
+ EVP_PKEY_CTX *pctx;
+
+ if (!kwargs_ids[0]) {
+ kwargs_ids[0] = rb_intern_const("salt");
+ kwargs_ids[1] = rb_intern_const("info");
+ kwargs_ids[2] = rb_intern_const("length");
+ kwargs_ids[3] = rb_intern_const("hash");
+ }
+ rb_scan_args(argc, argv, "1:", &ikm, &opts);
+ rb_get_kwargs(opts, kwargs_ids, 4, 0, kwargs);
+
+ StringValue(ikm);
+ ikmlen = RSTRING_LENINT(ikm);
+ salt = StringValue(kwargs[0]);
+ saltlen = RSTRING_LENINT(salt);
+ info = StringValue(kwargs[1]);
+ infolen = RSTRING_LENINT(info);
+ len = (size_t)NUM2LONG(kwargs[2]);
+ if (len > LONG_MAX)
+ rb_raise(rb_eArgError, "length must be non-negative");
+ md = ossl_evp_md_fetch(kwargs[3], &md_holder);
+
+ str = rb_str_new(NULL, (long)len);
+ pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
+ if (!pctx)
+ ossl_raise(eKDF, "EVP_PKEY_CTX_new_id");
+ if (EVP_PKEY_derive_init(pctx) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eKDF, "EVP_PKEY_derive_init");
+ }
+ if (EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_md");
+ }
+ if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, (unsigned char *)RSTRING_PTR(salt),
+ saltlen) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_salt");
+ }
+ if (EVP_PKEY_CTX_set1_hkdf_key(pctx, (unsigned char *)RSTRING_PTR(ikm),
+ ikmlen) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_key");
+ }
+ if (EVP_PKEY_CTX_add1_hkdf_info(pctx, (unsigned char *)RSTRING_PTR(info),
+ infolen) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_info");
+ }
+ if (EVP_PKEY_derive(pctx, (unsigned char *)RSTRING_PTR(str), &len) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eKDF, "EVP_PKEY_derive");
+ }
+ rb_str_set_len(str, (long)len);
+ EVP_PKEY_CTX_free(pctx);
+
+ return str;
+}
+
+void
+Init_ossl_kdf(void)
+{
+ /*
+ * Document-module: OpenSSL::KDF
+ *
+ * Provides functionality of various KDFs (key derivation function).
+ *
+ * KDF is typically used for securely deriving arbitrary length symmetric
+ * keys to be used with an OpenSSL::Cipher from passwords. Another use case
+ * is for storing passwords: Due to the ability to tweak the effort of
+ * computation by increasing the iteration count, computation can be slowed
+ * down artificially in order to render possible attacks infeasible.
+ *
+ * Currently, OpenSSL::KDF provides implementations for the following KDF:
+ *
+ * * PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in
+ * combination with HMAC
+ * * scrypt
+ * * HKDF
+ *
+ * == Examples
+ * === Generating a 128 bit key for a Cipher (e.g. AES)
+ * pass = "secret"
+ * salt = OpenSSL::Random.random_bytes(16)
+ * iter = 20_000
+ * key_len = 16
+ * key = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter,
+ * length: key_len, hash: "sha1")
+ *
+ * === Storing Passwords
+ * pass = "secret"
+ * # store this with the generated value
+ * salt = OpenSSL::Random.random_bytes(16)
+ * iter = 20_000
+ * hash = OpenSSL::Digest.new('SHA256')
+ * len = hash.digest_length
+ * # the final value to be stored
+ * value = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter,
+ * length: len, hash: hash)
+ *
+ * == Important Note on Checking Passwords
+ * When comparing passwords provided by the user with previously stored
+ * values, a common mistake made is comparing the two values using "==".
+ * Typically, "==" short-circuits on evaluation, and is therefore
+ * vulnerable to timing attacks. The proper way is to use a method that
+ * always takes the same amount of time when comparing two values, thus
+ * not leaking any information to potential attackers. To do this, use
+ * +OpenSSL.fixed_length_secure_compare+.
+ */
+ mKDF = rb_define_module_under(mOSSL, "KDF");
+ /*
+ * Generic exception class raised if an error occurs in OpenSSL::KDF module.
+ */
+ eKDF = rb_define_class_under(mKDF, "KDFError", eOSSLError);
+
+ rb_define_module_function(mKDF, "pbkdf2_hmac", kdf_pbkdf2_hmac, -1);
+#if defined(HAVE_EVP_PBE_SCRYPT)
+ rb_define_module_function(mKDF, "scrypt", kdf_scrypt, -1);
+#endif
+ rb_define_module_function(mKDF, "hkdf", kdf_hkdf, -1);
+}
diff --git a/ext/openssl/ossl_kdf.h b/ext/openssl/ossl_kdf.h
new file mode 100644
index 0000000000..b6503f8d9d
--- /dev/null
+++ b/ext/openssl/ossl_kdf.h
@@ -0,0 +1,6 @@
+#if !defined(OSSL_KDF_H)
+#define OSSL_KDF_H
+
+void Init_ossl_kdf(void);
+
+#endif
diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c
index b90a6b195e..8440c2ee82 100644
--- a/ext/openssl/ossl_ns_spki.c
+++ b/ext/openssl/ossl_ns_spki.c
@@ -1,34 +1,35 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#define WrapSPKI(klass, obj, spki) do { \
- if (!spki) { \
- ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
+#define NewSPKI(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_netscape_spki_type, 0)
+#define SetSPKI(obj, spki) do { \
+ if (!(spki)) { \
+ ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
} \
- obj = Data_Wrap_Struct(klass, 0, NETSCAPE_SPKI_free, spki); \
+ RTYPEDDATA_DATA(obj) = (spki); \
} while (0)
#define GetSPKI(obj, spki) do { \
- Data_Get_Struct(obj, NETSCAPE_SPKI, spki); \
- if (!spki) { \
- ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
+ TypedData_Get_Struct((obj), NETSCAPE_SPKI, &ossl_netscape_spki_type, (spki)); \
+ if (!(spki)) { \
+ ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
} \
} while (0)
/*
* Classes
*/
-VALUE mNetscape;
-VALUE cSPKI;
-VALUE eSPKIError;
+static VALUE mNetscape;
+static VALUE cSPKI;
+static VALUE eSPKIError;
/*
* Public functions
@@ -37,43 +38,73 @@ VALUE eSPKIError;
/*
* Private functions
*/
+
+static void
+ossl_netscape_spki_free(void *spki)
+{
+ NETSCAPE_SPKI_free(spki);
+}
+
+static const rb_data_type_t ossl_netscape_spki_type = {
+ "OpenSSL/NETSCAPE_SPKI",
+ {
+ 0, ossl_netscape_spki_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
static VALUE
ossl_spki_alloc(VALUE klass)
{
NETSCAPE_SPKI *spki;
VALUE obj;
-
+
+ obj = NewSPKI(klass);
if (!(spki = NETSCAPE_SPKI_new())) {
- ossl_raise(eSPKIError, NULL);
- }
- WrapSPKI(klass, obj, spki);
-
+ ossl_raise(eSPKIError, NULL);
+ }
+ SetSPKI(obj, spki);
+
return obj;
}
+/*
+ * call-seq:
+ * SPKI.new([request]) => spki
+ *
+ * === Parameters
+ * * _request_ - optional raw request, either in PEM or DER format.
+ */
static VALUE
ossl_spki_initialize(int argc, VALUE *argv, VALUE self)
{
NETSCAPE_SPKI *spki;
VALUE buffer;
- unsigned char *p;
-
+ const unsigned char *p;
+
if (rb_scan_args(argc, argv, "01", &buffer) == 0) {
- return self;
+ return self;
}
StringValue(buffer);
- if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING(buffer)->ptr, -1))) {
- p = RSTRING(buffer)->ptr;
- if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING(buffer)->len))) {
- ossl_raise(eSPKIError, NULL);
- }
+ if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), RSTRING_LENINT(buffer)))) {
+ ossl_clear_error();
+ p = (unsigned char *)RSTRING_PTR(buffer);
+ if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING_LEN(buffer)))) {
+ ossl_raise(eSPKIError, NULL);
+ }
}
NETSCAPE_SPKI_free(DATA_PTR(self));
- DATA_PTR(self) = spki;
+ SetSPKI(self, spki);
return self;
}
+/*
+ * call-seq:
+ * spki.to_der => DER-encoded string
+ *
+ * Returns the DER encoding of this SPKI.
+ */
static VALUE
ossl_spki_to_der(VALUE self)
{
@@ -84,55 +115,70 @@ ossl_spki_to_der(VALUE self)
GetSPKI(self, spki);
if ((len = i2d_NETSCAPE_SPKI(spki, NULL)) <= 0)
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eSPKIError, "i2d_NETSCAPE_SPKI");
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = (unsigned char *)RSTRING_PTR(str);
if (i2d_NETSCAPE_SPKI(spki, &p) <= 0)
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eSPKIError, "i2d_NETSCAPE_SPKI");
ossl_str_adjust(str, p);
-
+
return str;
}
+/*
+ * call-seq:
+ * spki.to_pem => PEM-encoded string
+ *
+ * Returns the PEM encoding of this SPKI.
+ */
static VALUE
ossl_spki_to_pem(VALUE self)
{
NETSCAPE_SPKI *spki;
char *data;
VALUE str;
-
+
GetSPKI(self, spki);
if (!(data = NETSCAPE_SPKI_b64_encode(spki))) {
- ossl_raise(eSPKIError, NULL);
+ ossl_raise(eSPKIError, NULL);
}
- str = ossl_buf2str(data, strlen(data));
+ str = ossl_buf2str(data, rb_long2int(strlen(data)));
return str;
}
+/*
+ * call-seq:
+ * spki.to_text => string
+ *
+ * Returns a textual representation of this SPKI, useful for debugging
+ * purposes.
+ */
static VALUE
ossl_spki_print(VALUE self)
{
NETSCAPE_SPKI *spki;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
-
+
GetSPKI(self, spki);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eSPKIError, NULL);
+ ossl_raise(eSPKIError, NULL);
}
if (!NETSCAPE_SPKI_print(out, spki)) {
- BIO_free(out);
- ossl_raise(eSPKIError, NULL);
+ BIO_free(out);
+ ossl_raise(eSPKIError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
-
- return str;
+
+ return ossl_membio2str(out);
}
+/*
+ * call-seq:
+ * spki.public_key => pkey
+ *
+ * Returns the public key associated with the SPKI, an instance of
+ * OpenSSL::PKey.
+ */
static VALUE
ossl_spki_get_public_key(VALUE self)
{
@@ -141,40 +187,67 @@ ossl_spki_get_public_key(VALUE self)
GetSPKI(self, spki);
if (!(pkey = NETSCAPE_SPKI_get_pubkey(spki))) { /* adds an reference */
- ossl_raise(eSPKIError, NULL);
+ ossl_raise(eSPKIError, NULL);
}
- return ossl_pkey_new(pkey); /* NO DUP - OK */
+ return ossl_pkey_wrap(pkey);
}
+/*
+ * call-seq:
+ * spki.public_key = pub => pkey
+ *
+ * === Parameters
+ * * _pub_ - the public key to be set for this instance
+ *
+ * Sets the public key to be associated with the SPKI, an instance of
+ * OpenSSL::PKey. This should be the public key corresponding to the
+ * private key used for signing the SPKI.
+ */
static VALUE
ossl_spki_set_public_key(VALUE self, VALUE key)
{
NETSCAPE_SPKI *spki;
+ EVP_PKEY *pkey;
GetSPKI(self, spki);
- if (!NETSCAPE_SPKI_set_pubkey(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
- ossl_raise(eSPKIError, NULL);
- }
-
+ pkey = GetPKeyPtr(key);
+ ossl_pkey_check_public_key(pkey);
+ if (!NETSCAPE_SPKI_set_pubkey(spki, pkey))
+ ossl_raise(eSPKIError, "NETSCAPE_SPKI_set_pubkey");
return key;
}
+/*
+ * call-seq:
+ * spki.challenge => string
+ *
+ * Returns the challenge string associated with this SPKI.
+ */
static VALUE
ossl_spki_get_challenge(VALUE self)
{
NETSCAPE_SPKI *spki;
GetSPKI(self, spki);
- if (spki->spkac->challenge->length <= 0) {
- OSSL_Debug("Challenge.length <= 0?");
- return rb_str_new(0, 0);
+ if (ASN1_STRING_length(spki->spkac->challenge) <= 0) {
+ OSSL_Debug("Challenge.length <= 0?");
+ return rb_str_new(0, 0);
}
- return rb_str_new(spki->spkac->challenge->data,
- spki->spkac->challenge->length);
+ return asn1str_to_str(spki->spkac->challenge);
}
+/*
+ * call-seq:
+ * spki.challenge = str => string
+ *
+ * === Parameters
+ * * _str_ - the challenge string to be set for this instance
+ *
+ * Sets the challenge to be associated with the SPKI. May be used by the
+ * server, e.g. to prevent replay.
+ */
static VALUE
ossl_spki_set_challenge(VALUE self, VALUE str)
{
@@ -182,66 +255,137 @@ ossl_spki_set_challenge(VALUE self, VALUE str)
StringValue(str);
GetSPKI(self, spki);
- if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING(str)->ptr,
- RSTRING(str)->len)) {
- ossl_raise(eSPKIError, NULL);
+ if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING_PTR(str),
+ RSTRING_LENINT(str))) {
+ ossl_raise(eSPKIError, NULL);
}
-
+
return str;
}
+/*
+ * call-seq:
+ * spki.sign(key, digest) => spki
+ *
+ * === Parameters
+ * * _key_ - the private key to be used for signing this instance
+ * * _digest_ - the digest to be used for signing this instance
+ *
+ * To sign an SPKI, the private key corresponding to the public key set
+ * for this instance should be used, in addition to a digest algorithm in
+ * the form of an OpenSSL::Digest. The private key should be an instance of
+ * OpenSSL::PKey.
+ */
static VALUE
ossl_spki_sign(VALUE self, VALUE key, VALUE digest)
{
NETSCAPE_SPKI *spki;
EVP_PKEY *pkey;
const EVP_MD *md;
+ VALUE md_holder;
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
- md = GetDigestPtr(digest);
+ md = ossl_evp_md_fetch(digest, &md_holder);
GetSPKI(self, spki);
- if (!NETSCAPE_SPKI_sign(spki, pkey, md)) {
- ossl_raise(eSPKIError, NULL);
- }
+ if (!NETSCAPE_SPKI_sign(spki, pkey, md))
+ ossl_raise(eSPKIError, "NETSCAPE_SPKI_sign");
return self;
}
/*
- * Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
+ * call-seq:
+ * spki.verify(key) => boolean
+ *
+ * === Parameters
+ * * _key_ - the public key to be used for verifying the SPKI signature
+ *
+ * Returns +true+ if the signature is valid, +false+ otherwise. To verify an
+ * SPKI, the public key contained within the SPKI should be used.
*/
static VALUE
ossl_spki_verify(VALUE self, VALUE key)
{
NETSCAPE_SPKI *spki;
+ EVP_PKEY *pkey;
GetSPKI(self, spki);
- switch (NETSCAPE_SPKI_verify(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
- case 0:
- return Qfalse;
- case 1:
- return Qtrue;
- default:
- ossl_raise(eSPKIError, NULL);
+ pkey = GetPKeyPtr(key);
+ ossl_pkey_check_public_key(pkey);
+ switch (NETSCAPE_SPKI_verify(spki, pkey)) {
+ case 0:
+ ossl_clear_error();
+ return Qfalse;
+ case 1:
+ return Qtrue;
+ default:
+ ossl_raise(eSPKIError, "NETSCAPE_SPKI_verify");
}
- return Qnil; /* dummy */
}
-/*
- * NETSCAPE_SPKI init
+/* Document-class: OpenSSL::Netscape::SPKI
+ *
+ * A Simple Public Key Infrastructure implementation (pronounced "spooky").
+ * The structure is defined as
+ * PublicKeyAndChallenge ::= SEQUENCE {
+ * spki SubjectPublicKeyInfo,
+ * challenge IA5STRING
+ * }
+ *
+ * SignedPublicKeyAndChallenge ::= SEQUENCE {
+ * publicKeyAndChallenge PublicKeyAndChallenge,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING
+ * }
+ * where the definitions of SubjectPublicKeyInfo and AlgorithmIdentifier can
+ * be found in RFC5280. SPKI is typically used in browsers for generating
+ * a public/private key pair and a subsequent certificate request, using
+ * the HTML <keygen> element.
+ *
+ * == Examples
+ *
+ * === Creating an SPKI
+ * key = OpenSSL::PKey::RSA.new 2048
+ * spki = OpenSSL::Netscape::SPKI.new
+ * spki.challenge = "RandomChallenge"
+ * spki.public_key = key.public_key
+ * spki.sign(key, OpenSSL::Digest.new('SHA256'))
+ * #send a request containing this to a server generating a certificate
+ * === Verifying an SPKI request
+ * request = #...
+ * spki = OpenSSL::Netscape::SPKI.new request
+ * unless spki.verify(spki.public_key)
+ * # signature is invalid
+ * end
+ * #proceed
+ */
+
+/* Document-module: OpenSSL::Netscape
+ *
+ * OpenSSL::Netscape is a namespace for SPKI (Simple Public Key
+ * Infrastructure) which implements Signed Public Key and Challenge.
+ * See {RFC 2692}[https://www.rfc-editor.org/rfc/rfc2692] and {RFC
+ * 2693}[https://www.rfc-editor.org/rfc/rfc2692] for details.
+ */
+
+/* Document-class: OpenSSL::Netscape::SPKIError
+ *
+ * Generic Exception class that is raised if an error occurs during an
+ * operation on an instance of OpenSSL::Netscape::SPKI.
*/
+
void
-Init_ossl_ns_spki()
+Init_ossl_ns_spki(void)
{
mNetscape = rb_define_module_under(mOSSL, "Netscape");
-
+
eSPKIError = rb_define_class_under(mNetscape, "SPKIError", eOSSLError);
-
+
cSPKI = rb_define_class_under(mNetscape, "SPKI", rb_cObject);
-
+
rb_define_alloc_func(cSPKI, ossl_spki_alloc);
rb_define_method(cSPKI, "initialize", ossl_spki_initialize, -1);
-
+
rb_define_method(cSPKI, "to_der", ossl_spki_to_der, 0);
rb_define_method(cSPKI, "to_pem", ossl_spki_to_pem, 0);
rb_define_alias(cSPKI, "to_s", "to_pem");
@@ -253,4 +397,3 @@ Init_ossl_ns_spki()
rb_define_method(cSPKI, "challenge", ossl_spki_get_challenge, 0);
rb_define_method(cSPKI, "challenge=", ossl_spki_set_challenge, 1);
}
-
diff --git a/ext/openssl/ossl_ns_spki.h b/ext/openssl/ossl_ns_spki.h
index 9977035a9c..043b6cdb66 100644
--- a/ext/openssl/ossl_ns_spki.h
+++ b/ext/openssl/ossl_ns_spki.h
@@ -1,21 +1,15 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_NS_SPKI_H_)
#define _OSSL_NS_SPKI_H_
-extern VALUE mNetscape;
-extern VALUE cSPKI;
-extern VALUE eSPKIError;
-
void Init_ossl_ns_spki(void);
#endif /* _OSSL_NS_SPKI_H_ */
-
diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c
index b1e721c24c..9dd4b466d2 100644
--- a/ext/openssl/ossl_ocsp.c
+++ b/ext/openssl/ossl_ocsp.c
@@ -1,90 +1,167 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
* Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#if defined(OSSL_OCSP_ENABLED)
+#if !defined(OPENSSL_NO_OCSP)
-#define WrapOCSPReq(klass, obj, req) do { \
- if(!req) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \
- obj = Data_Wrap_Struct(klass, 0, OCSP_REQUEST_free, req); \
+#define NewOCSPReq(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_ocsp_request_type, 0)
+#define SetOCSPReq(obj, req) do { \
+ if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \
+ RTYPEDDATA_DATA(obj) = (req); \
} while (0)
#define GetOCSPReq(obj, req) do { \
- Data_Get_Struct(obj, OCSP_REQUEST, req); \
- if(!req) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \
-} while (0)
-#define SafeGetOCSPReq(obj, req) do { \
- OSSL_Check_Kind(obj, cOCSPReq); \
- GetOCSPReq(obj, req); \
+ TypedData_Get_Struct((obj), OCSP_REQUEST, &ossl_ocsp_request_type, (req)); \
+ if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \
} while (0)
-#define WrapOCSPRes(klass, obj, res) do { \
- if(!res) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
- obj = Data_Wrap_Struct(klass, 0, OCSP_RESPONSE_free, res); \
+#define NewOCSPRes(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_ocsp_response_type, 0)
+#define SetOCSPRes(obj, res) do { \
+ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
+ RTYPEDDATA_DATA(obj) = (res); \
} while (0)
#define GetOCSPRes(obj, res) do { \
- Data_Get_Struct(obj, OCSP_RESPONSE, res); \
- if(!res) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
-} while (0)
-#define SafeGetOCSPRes(obj, res) do { \
- OSSL_Check_Kind(obj, cOCSPRes); \
- GetOCSPRes(obj, res); \
+ TypedData_Get_Struct((obj), OCSP_RESPONSE, &ossl_ocsp_response_type, (res)); \
+ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
} while (0)
-#define WrapOCSPBasicRes(klass, obj, res) do { \
- if(!res) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
- obj = Data_Wrap_Struct(klass, 0, OCSP_BASICRESP_free, res); \
+#define NewOCSPBasicRes(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_ocsp_basicresp_type, 0)
+#define SetOCSPBasicRes(obj, res) do { \
+ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
+ RTYPEDDATA_DATA(obj) = (res); \
} while (0)
#define GetOCSPBasicRes(obj, res) do { \
- Data_Get_Struct(obj, OCSP_BASICRESP, res); \
- if(!res) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
+ TypedData_Get_Struct((obj), OCSP_BASICRESP, &ossl_ocsp_basicresp_type, (res)); \
+ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
+} while (0)
+
+#define NewOCSPSingleRes(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_ocsp_singleresp_type, 0)
+#define SetOCSPSingleRes(obj, res) do { \
+ if(!(res)) ossl_raise(rb_eRuntimeError, "SingleResponse wasn't initialized!"); \
+ RTYPEDDATA_DATA(obj) = (res); \
} while (0)
-#define SafeGetOCSPBasicRes(obj, res) do { \
- OSSL_Check_Kind(obj, cOCSPBasicRes); \
- GetOCSPBasicRes(obj, res); \
+#define GetOCSPSingleRes(obj, res) do { \
+ TypedData_Get_Struct((obj), OCSP_SINGLERESP, &ossl_ocsp_singleresp_type, (res)); \
+ if(!(res)) ossl_raise(rb_eRuntimeError, "SingleResponse wasn't initialized!"); \
} while (0)
-#define WrapOCSPCertId(klass, obj, cid) do { \
- if(!cid) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
- obj = Data_Wrap_Struct(klass, 0, OCSP_CERTID_free, cid); \
+#define NewOCSPCertId(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_ocsp_certid_type, 0)
+#define SetOCSPCertId(obj, cid) do { \
+ if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
+ RTYPEDDATA_DATA(obj) = (cid); \
} while (0)
#define GetOCSPCertId(obj, cid) do { \
- Data_Get_Struct(obj, OCSP_CERTID, cid); \
- if(!cid) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
-} while (0)
-#define SafeGetOCSPCertId(obj, cid) do { \
- OSSL_Check_Kind(obj, cOCSPCertId); \
- GetOCSPCertId(obj, cid); \
+ TypedData_Get_Struct((obj), OCSP_CERTID, &ossl_ocsp_certid_type, (cid)); \
+ if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
} while (0)
-VALUE mOCSP;
-VALUE eOCSPError;
-VALUE cOCSPReq;
-VALUE cOCSPRes;
-VALUE cOCSPBasicRes;
-VALUE cOCSPCertId;
+static VALUE mOCSP;
+static VALUE eOCSPError;
+static VALUE cOCSPReq;
+static VALUE cOCSPRes;
+static VALUE cOCSPBasicRes;
+static VALUE cOCSPSingleRes;
+static VALUE cOCSPCertId;
+
+static void
+ossl_ocsp_request_free(void *ptr)
+{
+ OCSP_REQUEST_free(ptr);
+}
+
+static const rb_data_type_t ossl_ocsp_request_type = {
+ "OpenSSL/OCSP/REQUEST",
+ {
+ 0, ossl_ocsp_request_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static void
+ossl_ocsp_response_free(void *ptr)
+{
+ OCSP_RESPONSE_free(ptr);
+}
+
+static const rb_data_type_t ossl_ocsp_response_type = {
+ "OpenSSL/OCSP/RESPONSE",
+ {
+ 0, ossl_ocsp_response_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static void
+ossl_ocsp_basicresp_free(void *ptr)
+{
+ OCSP_BASICRESP_free(ptr);
+}
+
+static const rb_data_type_t ossl_ocsp_basicresp_type = {
+ "OpenSSL/OCSP/BASICRESP",
+ {
+ 0, ossl_ocsp_basicresp_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static void
+ossl_ocsp_singleresp_free(void *ptr)
+{
+ OCSP_SINGLERESP_free(ptr);
+}
+
+static const rb_data_type_t ossl_ocsp_singleresp_type = {
+ "OpenSSL/OCSP/SINGLERESP",
+ {
+ 0, ossl_ocsp_singleresp_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static void
+ossl_ocsp_certid_free(void *ptr)
+{
+ OCSP_CERTID_free(ptr);
+}
+
+static const rb_data_type_t ossl_ocsp_certid_type = {
+ "OpenSSL/OCSP/CERTID",
+ {
+ 0, ossl_ocsp_certid_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
/*
* Public
*/
static VALUE
-ossl_ocspcertid_new(OCSP_CERTID *cid)
+ossl_ocspcid_new(const OCSP_CERTID *cid)
{
- VALUE obj;
- WrapOCSPCertId(cOCSPCertId, obj, cid);
+ VALUE obj = NewOCSPCertId(cOCSPCertId);
+ /* OpenSSL 1.1.1 takes a non-const pointer */
+ OCSP_CERTID *cid_new = OCSP_CERTID_dup((OCSP_CERTID *)cid);
+ if (!cid_new)
+ ossl_raise(eOCSPError, "OCSP_CERTID_dup");
+ SetOCSPCertId(obj, cid_new);
return obj;
}
/*
- * OCSP::Resquest
+ * OCSP::Request
*/
static VALUE
ossl_ocspreq_alloc(VALUE klass)
@@ -92,33 +169,77 @@ ossl_ocspreq_alloc(VALUE klass)
OCSP_REQUEST *req;
VALUE obj;
+ obj = NewOCSPReq(klass);
if (!(req = OCSP_REQUEST_new()))
- ossl_raise(eOCSPError, NULL);
- WrapOCSPReq(klass, obj, req);
+ ossl_raise(eOCSPError, NULL);
+ SetOCSPReq(obj, req);
return obj;
}
+/* :nodoc: */
+static VALUE
+ossl_ocspreq_initialize_copy(VALUE self, VALUE other)
+{
+ OCSP_REQUEST *req, *req_old, *req_new;
+
+ rb_check_frozen(self);
+ GetOCSPReq(self, req_old);
+ GetOCSPReq(other, req);
+
+ req_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_REQUEST), req);
+ if (!req_new)
+ ossl_raise(eOCSPError, "ASN1_item_dup");
+
+ SetOCSPReq(self, req_new);
+ OCSP_REQUEST_free(req_old);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * OpenSSL::OCSP::Request.new -> request
+ * OpenSSL::OCSP::Request.new(request_der) -> request
+ *
+ * Creates a new OpenSSL::OCSP::Request. The request may be created empty or
+ * from a _request_der_ string.
+ */
+
static VALUE
ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE arg;
- unsigned char *p;
+ OCSP_REQUEST *req, *req_new;
+ const unsigned char *p;
rb_scan_args(argc, argv, "01", &arg);
if(!NIL_P(arg)){
- arg = ossl_to_der_if_possible(arg);
- StringValue(arg);
- p = (unsigned char*)RSTRING(arg)->ptr;
- if(!d2i_OCSP_REQUEST((OCSP_REQUEST**)&DATA_PTR(self), &p,
- RSTRING(arg)->len)){
- ossl_raise(eOCSPError, "cannot load DER encoded request");
- }
+ GetOCSPReq(self, req);
+ arg = ossl_to_der_if_possible(arg);
+ StringValue(arg);
+ p = (unsigned char *)RSTRING_PTR(arg);
+ req_new = d2i_OCSP_REQUEST(NULL, &p, RSTRING_LEN(arg));
+ if (!req_new)
+ ossl_raise(eOCSPError, "d2i_OCSP_REQUEST");
+ SetOCSPReq(self, req_new);
+ OCSP_REQUEST_free(req);
}
return self;
}
+/*
+ * call-seq:
+ * request.add_nonce(nonce = nil) -> request
+ *
+ * Adds a _nonce_ to the OCSP request. If no nonce is given a random one will
+ * be generated.
+ *
+ * The nonce is used to prevent replay attacks but some servers do not support
+ * it.
+ */
+
static VALUE
ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self)
{
@@ -128,31 +249,38 @@ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "01", &val);
if(NIL_P(val)) {
- GetOCSPReq(self, req);
- ret = OCSP_request_add1_nonce(req, NULL, -1);
+ GetOCSPReq(self, req);
+ ret = OCSP_request_add1_nonce(req, NULL, -1);
}
else{
- StringValue(val);
- GetOCSPReq(self, req);
- ret = OCSP_request_add1_nonce(req, RSTRING(val)->ptr, RSTRING(val)->len);
+ StringValue(val);
+ GetOCSPReq(self, req);
+ ret = OCSP_request_add1_nonce(req, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val));
}
if(!ret) ossl_raise(eOCSPError, NULL);
return self;
}
-/* Check nonce validity in a request and response.
- * Return value reflects result:
- * 1: nonces present and equal.
- * 2: nonces both absent.
- * 3: nonce present in response only.
- * 0: nonces both present and not equal.
- * -1: nonce in request only.
+/*
+ * call-seq:
+ * request.check_nonce(response) -> result
*
- * For most responders clients can check return > 0.
- * If responder doesn't handle nonces return != 0 may be
- * necessary. return == 0 is always an error.
+ * Checks the nonce validity for this request and _response_.
+ *
+ * The return value is one of the following:
+ *
+ * -1 :: nonce in request only.
+ * 0 :: nonces both present and not equal.
+ * 1 :: nonces present and equal.
+ * 2 :: nonces both absent.
+ * 3 :: nonce present in response only.
+ *
+ * For most responses, clients can check _result_ > 0. If a responder doesn't
+ * handle nonces <code>result.nonzero?</code> may be necessary. A result of
+ * <code>0</code> is always an error.
*/
+
static VALUE
ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp)
{
@@ -161,77 +289,127 @@ ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp)
int res;
GetOCSPReq(self, req);
- SafeGetOCSPBasicRes(basic_resp, bs);
+ GetOCSPBasicRes(basic_resp, bs);
res = OCSP_check_nonce(req, bs);
return INT2NUM(res);
}
+/*
+ * call-seq:
+ * request.add_certid(certificate_id) -> request
+ *
+ * Adds _certificate_id_ to the request.
+ */
+
static VALUE
ossl_ocspreq_add_certid(VALUE self, VALUE certid)
{
OCSP_REQUEST *req;
- OCSP_CERTID *id;
+ OCSP_CERTID *id, *id_new;
GetOCSPReq(self, req);
GetOCSPCertId(certid, id);
- if(!OCSP_request_add0_id(req, OCSP_CERTID_dup(id)))
- ossl_raise(eOCSPError, NULL);
+
+ if (!(id_new = OCSP_CERTID_dup(id)))
+ ossl_raise(eOCSPError, "OCSP_CERTID_dup");
+ if (!OCSP_request_add0_id(req, id_new)) {
+ OCSP_CERTID_free(id_new);
+ ossl_raise(eOCSPError, "OCSP_request_add0_id");
+ }
return self;
}
+/*
+ * call-seq:
+ * request.certid -> [certificate_id, ...]
+ *
+ * Returns all certificate IDs in this request.
+ */
+
static VALUE
ossl_ocspreq_get_certid(VALUE self)
{
OCSP_REQUEST *req;
- OCSP_ONEREQ *one;
- OCSP_CERTID *id;
- VALUE ary, tmp;
- int i, count;
GetOCSPReq(self, req);
- count = OCSP_request_onereq_count(req);
- ary = (count > 0) ? rb_ary_new() : Qnil;
- for(i = 0; i < count; i++){
- one = OCSP_request_onereq_get0(req, i);
- if(!(id = OCSP_CERTID_dup(OCSP_onereq_get0_id(one))))
- ossl_raise(eOCSPError, NULL);
- WrapOCSPCertId(cOCSPCertId, tmp, id);
- rb_ary_push(ary, tmp);
+ int count = OCSP_request_onereq_count(req);
+ if (count < 0)
+ ossl_raise(eOCSPError, "OCSP_request_onereq_count");
+ if (count == 0)
+ return Qnil;
+
+ VALUE ary = rb_ary_new_capa(count);
+ for (int i = 0; i < count; i++) {
+ OCSP_ONEREQ *one = OCSP_request_onereq_get0(req, i);
+ OCSP_CERTID *cid = OCSP_onereq_get0_id(one);
+ rb_ary_push(ary, ossl_ocspcid_new(cid));
}
return ary;
}
+/*
+ * call-seq:
+ * request.sign(cert, key, certs = nil, flags = 0, digest = nil) -> self
+ *
+ * Signs this OCSP request using _cert_, _key_ and optional _digest_. If
+ * _digest_ is not specified, SHA-1 is used. _certs_ is an optional Array of
+ * additional certificates which are included in the request in addition to
+ * the signer certificate. Note that if _certs_ is +nil+ or not given, flag
+ * OpenSSL::OCSP::NOCERTS is enabled. Pass an empty array to include only the
+ * signer certificate.
+ *
+ * _flags_ is a bitwise OR of the following constants:
+ *
+ * OpenSSL::OCSP::NOCERTS::
+ * Don't include any certificates in the request. _certs_ will be ignored.
+ */
static VALUE
ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
{
- VALUE signer_cert, signer_key, certs, flags;
+ VALUE signer_cert, signer_key, certs, flags, digest, md_holder;
OCSP_REQUEST *req;
X509 *signer;
EVP_PKEY *key;
- STACK_OF(X509) *x509s;
- unsigned long flg;
+ STACK_OF(X509) *x509s = NULL;
+ unsigned long flg = 0;
+ const EVP_MD *md;
int ret;
- rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags);
+ rb_scan_args(argc, argv, "23", &signer_cert, &signer_key, &certs, &flags, &digest);
+ GetOCSPReq(self, req);
signer = GetX509CertPtr(signer_cert);
key = GetPrivPKeyPtr(signer_key);
- flg = NIL_P(flags) ? 0 : NUM2INT(flags);
- if(NIL_P(certs)){
- x509s = sk_X509_new_null();
- flags |= OCSP_NOCERTS;
- }
- else x509s = ossl_x509_ary2sk(certs);
- GetOCSPReq(self, req);
- ret = OCSP_request_sign(req, signer, key, EVP_sha1(), x509s, flg);
+ if (!NIL_P(flags))
+ flg = NUM2INT(flags);
+ md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder);
+ if (NIL_P(certs))
+ flg |= OCSP_NOCERTS;
+ else
+ x509s = ossl_x509_ary2sk(certs);
+
+ ret = OCSP_request_sign(req, signer, key, md, x509s, flg);
sk_X509_pop_free(x509s, X509_free);
- if(!ret) ossl_raise(eOCSPError, NULL);
+ if (!ret)
+ ossl_raise(eOCSPError, "OCSP_request_sign");
return self;
}
+/*
+ * call-seq:
+ * request.verify(certificates, store, flags = 0) -> true or false
+ *
+ * Verifies this request using the given _certificates_ and _store_.
+ * _certificates_ is an array of OpenSSL::X509::Certificate, _store_ is an
+ * OpenSSL::X509::Store.
+ *
+ * Note that +false+ is returned if the request does not have a signature.
+ * Use #signed? to check whether the request is signed or not.
+ */
+
static VALUE
ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self)
{
@@ -242,17 +420,22 @@ ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self)
int flg, result;
rb_scan_args(argc, argv, "21", &certs, &store, &flags);
+ GetOCSPReq(self, req);
x509st = GetX509StorePtr(store);
- flg = NIL_P(flags) ? 0 : INT2NUM(flags);
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
x509s = ossl_x509_ary2sk(certs);
- GetOCSPReq(self, req);
result = OCSP_request_verify(req, x509s, x509st, flg);
sk_X509_pop_free(x509s, X509_free);
- if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL));
+ if (result <= 0)
+ ossl_clear_error();
- return result ? Qtrue : Qfalse;
+ return result > 0 ? Qtrue : Qfalse;
}
+/*
+ * Returns this request as a DER-encoded string
+ */
+
static VALUE
ossl_ocspreq_to_der(VALUE self)
{
@@ -263,19 +446,42 @@ ossl_ocspreq_to_der(VALUE self)
GetOCSPReq(self, req);
if((len = i2d_OCSP_REQUEST(req, NULL)) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = (unsigned char *)RSTRING_PTR(str);
if(i2d_OCSP_REQUEST(req, &p) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
ossl_str_adjust(str, p);
return str;
}
/*
+ * call-seq:
+ * request.signed? -> true or false
+ *
+ * Returns +true+ if the request is signed, +false+ otherwise. Note that the
+ * validity of the signature is *not* checked. Use #verify to verify that.
+ */
+static VALUE
+ossl_ocspreq_signed_p(VALUE self)
+{
+ OCSP_REQUEST *req;
+
+ GetOCSPReq(self, req);
+ return OCSP_request_is_signed(req) ? Qtrue : Qfalse;
+}
+
+/*
* OCSP::Response
*/
+
+/* call-seq:
+ * OpenSSL::OCSP::Response.create(status, basic_response = nil) -> response
+ *
+ * Creates an OpenSSL::OCSP::Response from _status_ and _basic_response_.
+ */
+
static VALUE
ossl_ocspres_s_create(VALUE klass, VALUE status, VALUE basic_resp)
{
@@ -286,9 +492,10 @@ ossl_ocspres_s_create(VALUE klass, VALUE status, VALUE basic_resp)
if(NIL_P(basic_resp)) bs = NULL;
else GetOCSPBasicRes(basic_resp, bs); /* NO NEED TO DUP */
+ obj = NewOCSPRes(klass);
if(!(res = OCSP_response_create(st, bs)))
- ossl_raise(eOCSPError, NULL);
- WrapOCSPRes(klass, obj, res);
+ ossl_raise(eOCSPError, NULL);
+ SetOCSPRes(obj, res);
return obj;
}
@@ -299,33 +506,73 @@ ossl_ocspres_alloc(VALUE klass)
OCSP_RESPONSE *res;
VALUE obj;
+ obj = NewOCSPRes(klass);
if(!(res = OCSP_RESPONSE_new()))
- ossl_raise(eOCSPError, NULL);
- WrapOCSPRes(klass, obj, res);
+ ossl_raise(eOCSPError, NULL);
+ SetOCSPRes(obj, res);
return obj;
}
+/* :nodoc: */
+static VALUE
+ossl_ocspres_initialize_copy(VALUE self, VALUE other)
+{
+ OCSP_RESPONSE *res, *res_old, *res_new;
+
+ rb_check_frozen(self);
+ GetOCSPRes(self, res_old);
+ GetOCSPRes(other, res);
+
+ res_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_RESPONSE), res);
+ if (!res_new)
+ ossl_raise(eOCSPError, "ASN1_item_dup");
+
+ SetOCSPRes(self, res_new);
+ OCSP_RESPONSE_free(res_old);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * OpenSSL::OCSP::Response.new -> response
+ * OpenSSL::OCSP::Response.new(response_der) -> response
+ *
+ * Creates a new OpenSSL::OCSP::Response. The response may be created empty or
+ * from a _response_der_ string.
+ */
+
static VALUE
ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE arg;
- unsigned char *p;
+ OCSP_RESPONSE *res, *res_new;
+ const unsigned char *p;
rb_scan_args(argc, argv, "01", &arg);
if(!NIL_P(arg)){
- arg = ossl_to_der_if_possible(arg);
- StringValue(arg);
- p = RSTRING(arg)->ptr;
- if(!d2i_OCSP_RESPONSE((OCSP_RESPONSE**)&DATA_PTR(self), &p,
- RSTRING(arg)->len)){
- ossl_raise(eOCSPError, "cannot load DER encoded response");
- }
+ GetOCSPRes(self, res);
+ arg = ossl_to_der_if_possible(arg);
+ StringValue(arg);
+ p = (unsigned char *)RSTRING_PTR(arg);
+ res_new = d2i_OCSP_RESPONSE(NULL, &p, RSTRING_LEN(arg));
+ if (!res_new)
+ ossl_raise(eOCSPError, "d2i_OCSP_RESPONSE");
+ SetOCSPRes(self, res_new);
+ OCSP_RESPONSE_free(res);
}
return self;
}
+/*
+ * call-seq:
+ * response.status -> Integer
+ *
+ * Returns the status of the response.
+ */
+
static VALUE
ossl_ocspres_status(VALUE self)
{
@@ -338,6 +585,13 @@ ossl_ocspres_status(VALUE self)
return INT2NUM(st);
}
+/*
+ * call-seq:
+ * response.status_string -> String
+ *
+ * Returns a status string for the response.
+ */
+
static VALUE
ossl_ocspres_status_string(VALUE self)
{
@@ -350,6 +604,13 @@ ossl_ocspres_status_string(VALUE self)
return rb_str_new2(OCSP_response_status_str(st));
}
+/*
+ * call-seq:
+ * response.basic
+ *
+ * Returns a BasicResponse for this response
+ */
+
static VALUE
ossl_ocspres_get_basic(VALUE self)
{
@@ -358,13 +619,21 @@ ossl_ocspres_get_basic(VALUE self)
VALUE ret;
GetOCSPRes(self, res);
+ ret = NewOCSPBasicRes(cOCSPBasicRes);
if(!(bs = OCSP_response_get1_basic(res)))
- return Qnil;
- WrapOCSPBasicRes(cOCSPBasicRes, ret, bs);
+ return Qnil;
+ SetOCSPBasicRes(ret, bs);
return ret;
}
+/*
+ * call-seq:
+ * response.to_der -> String
+ *
+ * Returns this response as a DER-encoded string.
+ */
+
static VALUE
ossl_ocspres_to_der(VALUE self)
{
@@ -375,11 +644,11 @@ ossl_ocspres_to_der(VALUE self)
GetOCSPRes(self, res);
if((len = i2d_OCSP_RESPONSE(res, NULL)) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
- if(i2d_OCSP_RESPONSE(res, NULL) <= 0)
- ossl_raise(eOCSPError, NULL);
+ p = (unsigned char *)RSTRING_PTR(str);
+ if(i2d_OCSP_RESPONSE(res, &p) <= 0)
+ ossl_raise(eOCSPError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -394,19 +663,73 @@ ossl_ocspbres_alloc(VALUE klass)
OCSP_BASICRESP *bs;
VALUE obj;
+ obj = NewOCSPBasicRes(klass);
if(!(bs = OCSP_BASICRESP_new()))
- ossl_raise(eOCSPError, NULL);
- WrapOCSPBasicRes(klass, obj, bs);
+ ossl_raise(eOCSPError, NULL);
+ SetOCSPBasicRes(obj, bs);
return obj;
}
+/* :nodoc: */
+static VALUE
+ossl_ocspbres_initialize_copy(VALUE self, VALUE other)
+{
+ OCSP_BASICRESP *bs, *bs_old, *bs_new;
+
+ rb_check_frozen(self);
+ GetOCSPBasicRes(self, bs_old);
+ GetOCSPBasicRes(other, bs);
+
+ bs_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_BASICRESP), bs);
+ if (!bs_new)
+ ossl_raise(eOCSPError, "ASN1_item_dup");
+
+ SetOCSPBasicRes(self, bs_new);
+ OCSP_BASICRESP_free(bs_old);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * OpenSSL::OCSP::BasicResponse.new(der_string = nil) -> basic_response
+ *
+ * Creates a new BasicResponse. If _der_string_ is given, decodes _der_string_
+ * as DER.
+ */
+
static VALUE
ossl_ocspbres_initialize(int argc, VALUE *argv, VALUE self)
{
+ VALUE arg;
+ OCSP_BASICRESP *res, *res_new;
+ const unsigned char *p;
+
+ rb_scan_args(argc, argv, "01", &arg);
+ if (!NIL_P(arg)) {
+ GetOCSPBasicRes(self, res);
+ arg = ossl_to_der_if_possible(arg);
+ StringValue(arg);
+ p = (unsigned char *)RSTRING_PTR(arg);
+ res_new = d2i_OCSP_BASICRESP(NULL, &p, RSTRING_LEN(arg));
+ if (!res_new)
+ ossl_raise(eOCSPError, "d2i_OCSP_BASICRESP");
+ SetOCSPBasicRes(self, res_new);
+ OCSP_BASICRESP_free(res);
+ }
+
return self;
}
+/*
+ * call-seq:
+ * basic_response.copy_nonce(request) -> Integer
+ *
+ * Copies the nonce from _request_ into this response. Returns 1 on success
+ * and 0 on failure.
+ */
+
static VALUE
ossl_ocspbres_copy_nonce(VALUE self, VALUE request)
{
@@ -415,12 +738,20 @@ ossl_ocspbres_copy_nonce(VALUE self, VALUE request)
int ret;
GetOCSPBasicRes(self, bs);
- SafeGetOCSPReq(request, req);
+ GetOCSPReq(request, req);
ret = OCSP_copy_nonce(bs, req);
return INT2NUM(ret);
}
+/*
+ * call-seq:
+ * basic_response.add_nonce(nonce = nil)
+ *
+ * Adds _nonce_ to this response. If no nonce was provided a random nonce
+ * will be added.
+ */
+
static VALUE
ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
{
@@ -430,13 +761,13 @@ ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "01", &val);
if(NIL_P(val)) {
- GetOCSPBasicRes(self, bs);
- ret = OCSP_basic_add1_nonce(bs, NULL, -1);
+ GetOCSPBasicRes(self, bs);
+ ret = OCSP_basic_add1_nonce(bs, NULL, -1);
}
else{
- StringValue(val);
- GetOCSPBasicRes(self, bs);
- ret = OCSP_basic_add1_nonce(bs, RSTRING(val)->ptr, RSTRING(val)->len);
+ StringValue(val);
+ GetOCSPBasicRes(self, bs);
+ ret = OCSP_basic_add1_nonce(bs, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val));
}
if(!ret) ossl_raise(eOCSPError, NULL);
@@ -444,64 +775,105 @@ ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
}
static VALUE
+add_status_convert_time(VALUE obj)
+{
+ ASN1_TIME *time;
+
+ if (RB_INTEGER_TYPE_P(obj))
+ time = X509_gmtime_adj(NULL, NUM2INT(obj));
+ else
+ time = ossl_x509_time_adjust(NULL, obj);
+
+ if (!time)
+ ossl_raise(eOCSPError, NULL);
+
+ return (VALUE)time;
+}
+
+/*
+ * call-seq:
+ * basic_response.add_status(certificate_id, status, reason, revocation_time, this_update, next_update, extensions) -> basic_response
+ *
+ * Adds a certificate status for _certificate_id_. _status_ is the status, and
+ * must be one of these:
+ *
+ * - OpenSSL::OCSP::V_CERTSTATUS_GOOD
+ * - OpenSSL::OCSP::V_CERTSTATUS_REVOKED
+ * - OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
+ *
+ * _reason_ and _revocation_time_ can be given only when _status_ is
+ * OpenSSL::OCSP::V_CERTSTATUS_REVOKED. _reason_ describes the reason for the
+ * revocation, and must be one of OpenSSL::OCSP::REVOKED_STATUS_* constants.
+ * _revocation_time_ is the time when the certificate is revoked.
+ *
+ * _this_update_ and _next_update_ indicate the time at which the status is
+ * verified to be correct and the time at or before which newer information
+ * will be available, respectively. _next_update_ is optional.
+ *
+ * _extensions_ is an Array of OpenSSL::X509::Extension to be included in the
+ * SingleResponse. This is also optional.
+ *
+ * Note that the times, _revocation_time_, _this_update_ and _next_update_
+ * can be specified in either of Integer or Time object. If they are Integer, it
+ * is treated as the relative seconds from the current time.
+ */
+static VALUE
ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
- VALUE reason, VALUE revtime,
- VALUE thisupd, VALUE nextupd, VALUE ext)
+ VALUE reason, VALUE revtime,
+ VALUE thisupd, VALUE nextupd, VALUE ext)
{
OCSP_BASICRESP *bs;
OCSP_SINGLERESP *single;
OCSP_CERTID *id;
- int st, rsn;
- ASN1_TIME *ths, *nxt, *rev;
- int error, i, rstatus = 0;
+ ASN1_TIME *ths = NULL, *nxt = NULL, *rev = NULL;
+ int st, rsn = 0, error = 0, rstatus = 0;
+ long i;
VALUE tmp;
+ GetOCSPBasicRes(self, bs);
+ GetOCSPCertId(cid, id);
st = NUM2INT(status);
- rsn = NIL_P(status) ? 0 : NUM2INT(reason);
- if(!NIL_P(ext)){
- /* All ary's members should be X509Extension */
- Check_Type(ext, T_ARRAY);
- for (i = 0; i < RARRAY(ext)->len; i++)
- OSSL_Check_Kind(RARRAY(ext)->ptr[i], cX509Ext);
+ if (!NIL_P(ext)) { /* All ext's members must be X509::Extension */
+ ext = rb_check_array_type(ext);
+ for (i = 0; i < RARRAY_LEN(ext); i++)
+ OSSL_Check_Kind(RARRAY_AREF(ext, i), cX509Ext);
}
- error = 0;
- ths = nxt = rev = NULL;
- if(!NIL_P(revtime)){
- tmp = rb_protect(rb_Integer, revtime, &rstatus);
- if(rstatus) goto err;
- rev = X509_gmtime_adj(NULL, NUM2INT(tmp));
+ if (st == V_OCSP_CERTSTATUS_REVOKED) {
+ rsn = NUM2INT(reason);
+ tmp = rb_protect(add_status_convert_time, revtime, &rstatus);
+ if (rstatus) goto err;
+ rev = (ASN1_TIME *)tmp;
+ }
+
+ tmp = rb_protect(add_status_convert_time, thisupd, &rstatus);
+ if (rstatus) goto err;
+ ths = (ASN1_TIME *)tmp;
+
+ if (!NIL_P(nextupd)) {
+ tmp = rb_protect(add_status_convert_time, nextupd, &rstatus);
+ if (rstatus) goto err;
+ nxt = (ASN1_TIME *)tmp;
}
- tmp = rb_protect(rb_Integer, thisupd, &rstatus);
- if(rstatus) goto err;
- ths = X509_gmtime_adj(NULL, NUM2INT(tmp));
- tmp = rb_protect(rb_Integer, nextupd, &rstatus);
- if(rstatus) goto err;
- nxt = X509_gmtime_adj(NULL, NUM2INT(tmp));
- GetOCSPBasicRes(self, bs);
- SafeGetOCSPCertId(cid, id);
if(!(single = OCSP_basic_add1_status(bs, id, st, rsn, rev, ths, nxt))){
- error = 1;
- goto err;
+ error = 1;
+ goto err;
}
if(!NIL_P(ext)){
- X509_EXTENSION *x509ext;
- sk_X509_EXTENSION_pop_free(single->singleExtensions, X509_EXTENSION_free);
- single->singleExtensions = NULL;
- for(i = 0; i < RARRAY(ext)->len; i++){
- x509ext = DupX509ExtPtr(RARRAY(ext)->ptr[i]);
- if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
- X509_EXTENSION_free(x509ext);
- error = 1;
- goto err;
- }
- X509_EXTENSION_free(x509ext);
- }
+ X509_EXTENSION *x509ext;
+
+ for(i = 0; i < RARRAY_LEN(ext); i++){
+ x509ext = GetX509ExtPtr(RARRAY_AREF(ext, i));
+ if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
+ error = 1;
+ goto err;
+ }
+ }
}
- err:
+ err:
ASN1_TIME_free(ths);
ASN1_TIME_free(nxt);
ASN1_TIME_free(rev);
@@ -511,81 +883,157 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
return self;
}
+/*
+ * call-seq:
+ * basic_response.status -> statuses
+ *
+ * Returns an Array of statuses for this response. Each status contains a
+ * CertificateId, the status (0 for good, 1 for revoked, 2 for unknown), the
+ * reason for the status, the revocation time, the time of this update, the time
+ * for the next update and a list of OpenSSL::X509::Extension.
+ *
+ * This should be superseded by BasicResponse#responses and #find_response that
+ * return SingleResponse.
+ */
static VALUE
ossl_ocspbres_get_status(VALUE self)
{
OCSP_BASICRESP *bs;
- OCSP_SINGLERESP *single;
- OCSP_CERTID *cid;
- ASN1_TIME *revtime, *thisupd, *nextupd;
- int status, reason;
- X509_EXTENSION *x509ext;
- VALUE ret, ary, ext;
- int count, ext_count, i, j;
GetOCSPBasicRes(self, bs);
- ret = rb_ary_new();
+ VALUE ret = rb_ary_new();
+ int count = OCSP_resp_count(bs);
+ for (int i = 0; i < count; i++) {
+ OCSP_SINGLERESP *single = OCSP_resp_get0(bs, i);
+ ASN1_TIME *revtime = NULL, *thisupd = NULL, *nextupd = NULL;
+ int reason = -1;
+
+ int status = OCSP_single_get0_status(single, &reason, &revtime, &thisupd, &nextupd);
+ if (status < 0)
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
+
+ VALUE ary = rb_ary_new();
+ rb_ary_push(ary, ossl_ocspcid_new(OCSP_SINGLERESP_get0_id(single)));
+ rb_ary_push(ary, INT2NUM(status));
+ rb_ary_push(ary, INT2NUM(reason));
+ rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil);
+ rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil);
+ rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil);
+ VALUE ext = rb_ary_new();
+ int ext_count = OCSP_SINGLERESP_get_ext_count(single);
+ for (int j = 0; j < ext_count; j++) {
+ const X509_EXTENSION *x509ext = OCSP_SINGLERESP_get_ext(single, j);
+ rb_ary_push(ext, ossl_x509ext_new(x509ext));
+ }
+ rb_ary_push(ary, ext);
+ rb_ary_push(ret, ary);
+ }
+
+ return ret;
+}
+
+static VALUE ossl_ocspsres_new(const OCSP_SINGLERESP *);
+
+/*
+ * call-seq:
+ * basic_response.responses -> Array of SingleResponse
+ *
+ * Returns an Array of SingleResponse for this BasicResponse.
+ */
+
+static VALUE
+ossl_ocspbres_get_responses(VALUE self)
+{
+ OCSP_BASICRESP *bs;
+ VALUE ret;
+ int count, i;
+
+ GetOCSPBasicRes(self, bs);
count = OCSP_resp_count(bs);
- for(i = 0; i < count; i++){
- single = OCSP_resp_get0(bs, i);
- if(!single) continue;
-
- revtime = thisupd = nextupd = NULL;
- status = OCSP_single_get0_status(single, &reason, &revtime,
- &thisupd, &nextupd);
- if(status < 0) continue;
- if(!(cid = OCSP_CERTID_dup(single->certId)))
- ossl_raise(eOCSPError, NULL);
- ary = rb_ary_new();
- rb_ary_push(ary, ossl_ocspcertid_new(cid));
- rb_ary_push(ary, INT2NUM(status));
- rb_ary_push(ary, INT2NUM(reason));
- rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil);
- rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil);
- rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil);
- ext = rb_ary_new();
- ext_count = OCSP_SINGLERESP_get_ext_count(single);
- for(j = 0; j < ext_count; j++){
- x509ext = OCSP_SINGLERESP_get_ext(single, j);
- rb_ary_push(ext, ossl_x509ext_new(x509ext));
- }
- rb_ary_push(ary, ext);
- rb_ary_push(ret, ary);
+ ret = rb_ary_new_capa(count);
+
+ for (i = 0; i < count; i++) {
+ rb_ary_push(ret, ossl_ocspsres_new(OCSP_resp_get0(bs, i)));
}
return ret;
-}
+}
+
+
+/*
+ * call-seq:
+ * basic_response.find_response(certificate_id) -> SingleResponse | nil
+ *
+ * Returns a SingleResponse whose CertId matches with _certificate_id_, or +nil+
+ * if this BasicResponse does not contain it.
+ */
+static VALUE
+ossl_ocspbres_find_response(VALUE self, VALUE target)
+{
+ OCSP_BASICRESP *bs;
+ OCSP_CERTID *id;
+ int n;
+
+ GetOCSPCertId(target, id);
+ GetOCSPBasicRes(self, bs);
+
+ if ((n = OCSP_resp_find(bs, id, -1)) == -1)
+ return Qnil;
+ return ossl_ocspsres_new(OCSP_resp_get0(bs, n));
+}
+
+/*
+ * call-seq:
+ * basic_response.sign(cert, key, certs = nil, flags = 0, digest = nil) -> self
+ *
+ * Signs this OCSP response using the _cert_, _key_ and optional _digest_. This
+ * behaves in the similar way as OpenSSL::OCSP::Request#sign.
+ *
+ * _flags_ can include:
+ * OpenSSL::OCSP::NOCERTS:: don't include certificates
+ * OpenSSL::OCSP::NOTIME:: don't set producedAt
+ * OpenSSL::OCSP::RESPID_KEY:: use signer's public key hash as responderID
+ */
static VALUE
ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self)
{
- VALUE signer_cert, signer_key, certs, flags;
+ VALUE signer_cert, signer_key, certs, flags, digest, md_holder;
OCSP_BASICRESP *bs;
X509 *signer;
EVP_PKEY *key;
- STACK_OF(X509) *x509s;
- unsigned long flg;
+ STACK_OF(X509) *x509s = NULL;
+ unsigned long flg = 0;
+ const EVP_MD *md;
int ret;
- rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags);
+ rb_scan_args(argc, argv, "23", &signer_cert, &signer_key, &certs, &flags, &digest);
+ GetOCSPBasicRes(self, bs);
signer = GetX509CertPtr(signer_cert);
key = GetPrivPKeyPtr(signer_key);
- flg = NIL_P(flags) ? 0 : NUM2INT(flags);
- if(NIL_P(certs)){
- x509s = sk_X509_new_null();
- flg |= OCSP_NOCERTS;
- }
- else{
- x509s = ossl_x509_ary2sk(certs);
- }
- GetOCSPBasicRes(self, bs);
- ret = OCSP_basic_sign(bs, signer, key, EVP_sha1(), x509s, flg);
+ if (!NIL_P(flags))
+ flg = NUM2INT(flags);
+ md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder);
+ if (NIL_P(certs))
+ flg |= OCSP_NOCERTS;
+ else
+ x509s = ossl_x509_ary2sk(certs);
+
+ ret = OCSP_basic_sign(bs, signer, key, md, x509s, flg);
sk_X509_pop_free(x509s, X509_free);
- if(!ret) ossl_raise(eOCSPError, NULL);
+ if (!ret)
+ ossl_raise(eOCSPError, "OCSP_basic_sign");
return self;
}
+/*
+ * call-seq:
+ * basic_response.verify(certificates, store, flags = 0) -> true or false
+ *
+ * Verifies the signature of the response using the given _certificates_ and
+ * _store_. This works in the similar way as OpenSSL::OCSP::Request#verify.
+ */
static VALUE
ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self)
{
@@ -596,17 +1044,345 @@ ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self)
int flg, result;
rb_scan_args(argc, argv, "21", &certs, &store, &flags);
+ GetOCSPBasicRes(self, bs);
x509st = GetX509StorePtr(store);
- flg = NIL_P(flags) ? 0 : INT2NUM(flags);
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
x509s = ossl_x509_ary2sk(certs);
- GetOCSPBasicRes(self, bs);
result = OCSP_basic_verify(bs, x509s, x509st, flg);
sk_X509_pop_free(x509s, X509_free);
- if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL));
+ if (result <= 0)
+ ossl_clear_error();
+
+ return result > 0 ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * basic_response.to_der -> String
+ *
+ * Encodes this basic response into a DER-encoded string.
+ */
+static VALUE
+ossl_ocspbres_to_der(VALUE self)
+{
+ OCSP_BASICRESP *res;
+ VALUE str;
+ long len;
+ unsigned char *p;
- return result ? Qtrue : Qfalse;
+ GetOCSPBasicRes(self, res);
+ if ((len = i2d_OCSP_BASICRESP(res, NULL)) <= 0)
+ ossl_raise(eOCSPError, NULL);
+ str = rb_str_new(0, len);
+ p = (unsigned char *)RSTRING_PTR(str);
+ if (i2d_OCSP_BASICRESP(res, &p) <= 0)
+ ossl_raise(eOCSPError, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
+/*
+ * OCSP::SingleResponse
+ */
+static VALUE
+ossl_ocspsres_new(const OCSP_SINGLERESP *sres)
+{
+ VALUE obj;
+ OCSP_SINGLERESP *sres_new;
+
+ obj = NewOCSPSingleRes(cOCSPSingleRes);
+ /* OpenSSL 1.1.1 takes a non-const pointer */
+ sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP),
+ (OCSP_SINGLERESP *)sres);
+ if (!sres_new)
+ ossl_raise(eOCSPError, "ASN1_item_dup");
+ SetOCSPSingleRes(obj, sres_new);
+
+ return obj;
+}
+
+static VALUE
+ossl_ocspsres_alloc(VALUE klass)
+{
+ OCSP_SINGLERESP *sres;
+ VALUE obj;
+
+ obj = NewOCSPSingleRes(klass);
+ if (!(sres = OCSP_SINGLERESP_new()))
+ ossl_raise(eOCSPError, NULL);
+ SetOCSPSingleRes(obj, sres);
+
+ return obj;
+}
+
+/*
+ * call-seq:
+ * OpenSSL::OCSP::SingleResponse.new(der_string) -> SingleResponse
+ *
+ * Creates a new SingleResponse from _der_string_.
+ */
+static VALUE
+ossl_ocspsres_initialize(VALUE self, VALUE arg)
+{
+ OCSP_SINGLERESP *res, *res_new;
+ const unsigned char *p;
+
+ arg = ossl_to_der_if_possible(arg);
+ StringValue(arg);
+ GetOCSPSingleRes(self, res);
+
+ p = (unsigned char*)RSTRING_PTR(arg);
+ res_new = d2i_OCSP_SINGLERESP(NULL, &p, RSTRING_LEN(arg));
+ if (!res_new)
+ ossl_raise(eOCSPError, "d2i_OCSP_SINGLERESP");
+ SetOCSPSingleRes(self, res_new);
+ OCSP_SINGLERESP_free(res);
+
+ return self;
+}
+
+/* :nodoc: */
+static VALUE
+ossl_ocspsres_initialize_copy(VALUE self, VALUE other)
+{
+ OCSP_SINGLERESP *sres, *sres_old, *sres_new;
+
+ rb_check_frozen(self);
+ GetOCSPSingleRes(self, sres_old);
+ GetOCSPSingleRes(other, sres);
+
+ sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres);
+ if (!sres_new)
+ ossl_raise(eOCSPError, "ASN1_item_dup");
+
+ SetOCSPSingleRes(self, sres_new);
+ OCSP_SINGLERESP_free(sres_old);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * single_response.check_validity(nsec = 0, maxsec = -1) -> true | false
+ *
+ * Checks the validity of thisUpdate and nextUpdate fields of this
+ * SingleResponse. This checks the current time is within the range thisUpdate
+ * to nextUpdate.
+ *
+ * It is possible that the OCSP request takes a few seconds or the time is not
+ * accurate. To avoid rejecting a valid response, this method allows the times
+ * to be within _nsec_ seconds of the current time.
+ *
+ * Some responders don't set the nextUpdate field. This may cause a very old
+ * response to be considered valid. The _maxsec_ parameter can be used to limit
+ * the age of responses.
+ */
+static VALUE
+ossl_ocspsres_check_validity(int argc, VALUE *argv, VALUE self)
+{
+ OCSP_SINGLERESP *sres;
+ ASN1_GENERALIZEDTIME *this_update, *next_update;
+ VALUE nsec_v, maxsec_v;
+ int nsec, maxsec, status, ret;
+
+ rb_scan_args(argc, argv, "02", &nsec_v, &maxsec_v);
+ nsec = NIL_P(nsec_v) ? 0 : NUM2INT(nsec_v);
+ maxsec = NIL_P(maxsec_v) ? -1 : NUM2INT(maxsec_v);
+
+ GetOCSPSingleRes(self, sres);
+ status = OCSP_single_get0_status(sres, NULL, NULL, &this_update, &next_update);
+ if (status < 0)
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
+
+ ret = OCSP_check_validity(this_update, next_update, nsec, maxsec);
+
+ if (ret)
+ return Qtrue;
+ else {
+ ossl_clear_error();
+ return Qfalse;
+ }
+}
+
+/*
+ * call-seq:
+ * single_response.certid -> CertificateId
+ *
+ * Returns the CertificateId for which this SingleResponse is.
+ */
+static VALUE
+ossl_ocspsres_get_certid(VALUE self)
+{
+ OCSP_SINGLERESP *sres;
+
+ GetOCSPSingleRes(self, sres);
+ return ossl_ocspcid_new(OCSP_SINGLERESP_get0_id(sres));
+}
+
+/*
+ * call-seq:
+ * single_response.cert_status -> Integer
+ *
+ * Returns the status of the certificate identified by the certid.
+ * The return value may be one of these constant:
+ *
+ * - V_CERTSTATUS_GOOD
+ * - V_CERTSTATUS_REVOKED
+ * - V_CERTSTATUS_UNKNOWN
+ *
+ * When the status is V_CERTSTATUS_REVOKED, the time at which the certificate
+ * was revoked can be retrieved by #revocation_time.
+ */
+static VALUE
+ossl_ocspsres_get_cert_status(VALUE self)
+{
+ OCSP_SINGLERESP *sres;
+ int status;
+
+ GetOCSPSingleRes(self, sres);
+ status = OCSP_single_get0_status(sres, NULL, NULL, NULL, NULL);
+ if (status < 0)
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
+
+ return INT2NUM(status);
+}
+
+/*
+ * call-seq:
+ * single_response.this_update -> Time
+ */
+static VALUE
+ossl_ocspsres_get_this_update(VALUE self)
+{
+ OCSP_SINGLERESP *sres;
+ int status;
+ ASN1_GENERALIZEDTIME *time;
+
+ GetOCSPSingleRes(self, sres);
+ status = OCSP_single_get0_status(sres, NULL, NULL, &time, NULL);
+ if (status < 0)
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
+ if (!time)
+ return Qnil;
+
+ return asn1time_to_time(time);
+}
+
+/*
+ * call-seq:
+ * single_response.next_update -> Time | nil
+ */
+static VALUE
+ossl_ocspsres_get_next_update(VALUE self)
+{
+ OCSP_SINGLERESP *sres;
+ int status;
+ ASN1_GENERALIZEDTIME *time;
+
+ GetOCSPSingleRes(self, sres);
+ status = OCSP_single_get0_status(sres, NULL, NULL, NULL, &time);
+ if (status < 0)
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
+ if (!time)
+ return Qnil;
+
+ return asn1time_to_time(time);
+}
+
+/*
+ * call-seq:
+ * single_response.revocation_time -> Time | nil
+ */
+static VALUE
+ossl_ocspsres_get_revocation_time(VALUE self)
+{
+ OCSP_SINGLERESP *sres;
+ int status;
+ ASN1_GENERALIZEDTIME *time;
+
+ GetOCSPSingleRes(self, sres);
+ status = OCSP_single_get0_status(sres, NULL, &time, NULL, NULL);
+ if (status < 0)
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
+ if (status != V_OCSP_CERTSTATUS_REVOKED)
+ ossl_raise(eOCSPError, "certificate is not revoked");
+ if (!time)
+ return Qnil;
+
+ return asn1time_to_time(time);
+}
+
+/*
+ * call-seq:
+ * single_response.revocation_reason -> Integer | nil
+ */
+static VALUE
+ossl_ocspsres_get_revocation_reason(VALUE self)
+{
+ OCSP_SINGLERESP *sres;
+ int status, reason;
+
+ GetOCSPSingleRes(self, sres);
+ status = OCSP_single_get0_status(sres, &reason, NULL, NULL, NULL);
+ if (status < 0)
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
+ if (status != V_OCSP_CERTSTATUS_REVOKED)
+ ossl_raise(eOCSPError, "certificate is not revoked");
+
+ return INT2NUM(reason);
+}
+
+/*
+ * call-seq:
+ * single_response.extensions -> Array of X509::Extension
+ */
+static VALUE
+ossl_ocspsres_get_extensions(VALUE self)
+{
+ OCSP_SINGLERESP *sres;
+ int count, i;
+ VALUE ary;
+
+ GetOCSPSingleRes(self, sres);
+
+ count = OCSP_SINGLERESP_get_ext_count(sres);
+ ary = rb_ary_new2(count);
+ for (i = 0; i < count; i++) {
+ const X509_EXTENSION *ext = OCSP_SINGLERESP_get_ext(sres, i);
+ rb_ary_push(ary, ossl_x509ext_new(ext)); /* will dup */
+ }
+
+ return ary;
+}
+
+/*
+ * call-seq:
+ * single_response.to_der -> String
+ *
+ * Encodes this SingleResponse into a DER-encoded string.
+ */
+static VALUE
+ossl_ocspsres_to_der(VALUE self)
+{
+ OCSP_SINGLERESP *sres;
+ VALUE str;
+ long len;
+ unsigned char *p;
+
+ GetOCSPSingleRes(self, sres);
+ if ((len = i2d_OCSP_SINGLERESP(sres, NULL)) <= 0)
+ ossl_raise(eOCSPError, NULL);
+ str = rb_str_new(0, len);
+ p = (unsigned char *)RSTRING_PTR(str);
+ if (i2d_OCSP_SINGLERESP(sres, &p) <= 0)
+ ossl_raise(eOCSPError, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
}
+
/*
* OCSP::CertificateId
*/
@@ -616,30 +1392,93 @@ ossl_ocspcid_alloc(VALUE klass)
OCSP_CERTID *id;
VALUE obj;
+ obj = NewOCSPCertId(klass);
if(!(id = OCSP_CERTID_new()))
- ossl_raise(eOCSPError, NULL);
- WrapOCSPCertId(klass, obj, id);
+ ossl_raise(eOCSPError, NULL);
+ SetOCSPCertId(obj, id);
return obj;
}
+/* :nodoc: */
static VALUE
-ossl_ocspcid_initialize(VALUE self, VALUE subject, VALUE issuer)
+ossl_ocspcid_initialize_copy(VALUE self, VALUE other)
+{
+ OCSP_CERTID *cid, *cid_old, *cid_new;
+
+ rb_check_frozen(self);
+ GetOCSPCertId(self, cid_old);
+ GetOCSPCertId(other, cid);
+
+ cid_new = OCSP_CERTID_dup(cid);
+ if (!cid_new)
+ ossl_raise(eOCSPError, "OCSP_CERTID_dup");
+
+ SetOCSPCertId(self, cid_new);
+ OCSP_CERTID_free(cid_old);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * OpenSSL::OCSP::CertificateId.new(subject, issuer, digest = nil) -> certificate_id
+ * OpenSSL::OCSP::CertificateId.new(der_string) -> certificate_id
+ * OpenSSL::OCSP::CertificateId.new(obj) -> certificate_id
+ *
+ * Creates a new OpenSSL::OCSP::CertificateId for the given _subject_ and
+ * _issuer_ X509 certificates. The _digest_ is a digest algorithm that is used
+ * to compute the hash values. This defaults to SHA-1.
+ *
+ * If only one argument is given, decodes it as DER representation of a
+ * certificate ID or generates certificate ID from the object that responds to
+ * the to_der method.
+ */
+static VALUE
+ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self)
{
OCSP_CERTID *id, *newid;
- X509 *x509s, *x509i;
+ VALUE subject, issuer, digest;
- x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */
- x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */
- if(!(newid = OCSP_cert_to_id(NULL, x509s, x509i)))
- ossl_raise(eOCSPError, NULL);
GetOCSPCertId(self, id);
+ if (rb_scan_args(argc, argv, "12", &subject, &issuer, &digest) == 1) {
+ VALUE arg;
+ const unsigned char *p;
+
+ arg = ossl_to_der_if_possible(subject);
+ StringValue(arg);
+ p = (unsigned char *)RSTRING_PTR(arg);
+ newid = d2i_OCSP_CERTID(NULL, &p, RSTRING_LEN(arg));
+ if (!newid)
+ ossl_raise(eOCSPError, "d2i_OCSP_CERTID");
+ }
+ else {
+ X509 *x509s, *x509i;
+ const EVP_MD *md;
+ VALUE md_holder;
+
+ x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */
+ x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */
+ md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder);
+
+ newid = OCSP_cert_to_id(md, x509s, x509i);
+ if (!newid)
+ ossl_raise(eOCSPError, "OCSP_cert_to_id");
+ }
+
+ SetOCSPCertId(self, newid);
OCSP_CERTID_free(id);
- RDATA(self)->data = newid;
return self;
}
+/*
+ * call-seq:
+ * certificate_id.cmp(other) -> true or false
+ *
+ * Compares this certificate id with _other_ and returns +true+ if they are the
+ * same.
+ */
static VALUE
ossl_ocspcid_cmp(VALUE self, VALUE other)
{
@@ -647,12 +1486,20 @@ ossl_ocspcid_cmp(VALUE self, VALUE other)
int result;
GetOCSPCertId(self, id);
- SafeGetOCSPCertId(other, id2);
+ GetOCSPCertId(other, id2);
result = OCSP_id_cmp(id, id2);
return (result == 0) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * certificate_id.cmp_issuer(other) -> true or false
+ *
+ * Compares this certificate id's issuer with _other_ and returns +true+ if
+ * they are the same.
+ */
+
static VALUE
ossl_ocspcid_cmp_issuer(VALUE self, VALUE other)
{
@@ -660,110 +1507,431 @@ ossl_ocspcid_cmp_issuer(VALUE self, VALUE other)
int result;
GetOCSPCertId(self, id);
- SafeGetOCSPCertId(other, id2);
+ GetOCSPCertId(other, id2);
result = OCSP_id_issuer_cmp(id, id2);
return (result == 0) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * certificate_id.serial -> Integer
+ *
+ * Returns the serial number of the certificate for which status is being
+ * requested.
+ */
static VALUE
ossl_ocspcid_get_serial(VALUE self)
{
OCSP_CERTID *id;
+ ASN1_INTEGER *serial;
GetOCSPCertId(self, id);
+ OCSP_id_get0_info(NULL, NULL, NULL, &serial, id);
- return asn1integer_to_num(id->serialNumber);
+ return asn1integer_to_num(serial);
+}
+
+/*
+ * call-seq:
+ * certificate_id.issuer_name_hash -> String
+ *
+ * Returns the issuerNameHash of this certificate ID, the hash of the
+ * issuer's distinguished name calculated with the hashAlgorithm.
+ */
+static VALUE
+ossl_ocspcid_get_issuer_name_hash(VALUE self)
+{
+ OCSP_CERTID *id;
+ ASN1_OCTET_STRING *name_hash;
+ VALUE ret;
+
+ GetOCSPCertId(self, id);
+ OCSP_id_get0_info(&name_hash, NULL, NULL, NULL, id);
+
+ ret = rb_str_new(NULL, ASN1_STRING_length(name_hash) * 2);
+ ossl_bin2hex(ASN1_STRING_get0_data(name_hash), RSTRING_PTR(ret),
+ ASN1_STRING_length(name_hash));
+
+ return ret;
+}
+
+/*
+ * call-seq:
+ * certificate_id.issuer_key_hash -> String
+ *
+ * Returns the issuerKeyHash of this certificate ID, the hash of the issuer's
+ * public key.
+ */
+static VALUE
+ossl_ocspcid_get_issuer_key_hash(VALUE self)
+{
+ OCSP_CERTID *id;
+ ASN1_OCTET_STRING *key_hash;
+ VALUE ret;
+
+ GetOCSPCertId(self, id);
+ OCSP_id_get0_info(NULL, NULL, &key_hash, NULL, id);
+
+ ret = rb_str_new(NULL, ASN1_STRING_length(key_hash) * 2);
+ ossl_bin2hex(ASN1_STRING_get0_data(key_hash), RSTRING_PTR(ret),
+ ASN1_STRING_length(key_hash));
+
+ return ret;
+}
+
+/*
+ * call-seq:
+ * certificate_id.hash_algorithm -> String
+ *
+ * Returns the ln (long name) of the hash algorithm used to generate
+ * the issuerNameHash and the issuerKeyHash values.
+ */
+static VALUE
+ossl_ocspcid_get_hash_algorithm(VALUE self)
+{
+ OCSP_CERTID *id;
+ ASN1_OBJECT *oid;
+
+ GetOCSPCertId(self, id);
+ OCSP_id_get0_info(NULL, &oid, NULL, NULL, id);
+ return ossl_asn1obj_to_string_long_name(oid);
+}
+
+/*
+ * call-seq:
+ * certificate_id.to_der -> String
+ *
+ * Encodes this certificate identifier into a DER-encoded string.
+ */
+static VALUE
+ossl_ocspcid_to_der(VALUE self)
+{
+ OCSP_CERTID *id;
+ VALUE str;
+ long len;
+ unsigned char *p;
+
+ GetOCSPCertId(self, id);
+ if ((len = i2d_OCSP_CERTID(id, NULL)) <= 0)
+ ossl_raise(eOCSPError, NULL);
+ str = rb_str_new(0, len);
+ p = (unsigned char *)RSTRING_PTR(str);
+ if (i2d_OCSP_CERTID(id, &p) <= 0)
+ ossl_raise(eOCSPError, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
}
void
-Init_ossl_ocsp()
+Init_ossl_ocsp(void)
{
+ /*
+ * OpenSSL::OCSP implements Online Certificate Status Protocol requests
+ * and responses.
+ *
+ * Creating and sending an OCSP request requires a subject certificate
+ * that contains an OCSP URL in an authorityInfoAccess extension and the
+ * issuer certificate for the subject certificate. First, load the issuer
+ * and subject certificates:
+ *
+ * subject = OpenSSL::X509::Certificate.new subject_pem
+ * issuer = OpenSSL::X509::Certificate.new issuer_pem
+ *
+ * To create the request we need to create a certificate ID for the
+ * subject certificate so the CA knows which certificate we are asking
+ * about:
+ *
+ * digest = OpenSSL::Digest.new('SHA1')
+ * certificate_id =
+ * OpenSSL::OCSP::CertificateId.new subject, issuer, digest
+ *
+ * Then create a request and add the certificate ID to it:
+ *
+ * request = OpenSSL::OCSP::Request.new
+ * request.add_certid certificate_id
+ *
+ * Adding a nonce to the request protects against replay attacks but not
+ * all CA process the nonce.
+ *
+ * request.add_nonce
+ *
+ * To submit the request to the CA for verification we need to extract the
+ * OCSP URI from the subject certificate:
+ *
+ * ocsp_uris = subject.ocsp_uris
+ *
+ * require 'uri'
+ *
+ * ocsp_uri = URI ocsp_uris[0]
+ *
+ * To submit the request we'll POST the request to the OCSP URI (per RFC
+ * 2560). Note that we only handle HTTP requests and don't handle any
+ * redirects in this example, so this is insufficient for serious use.
+ *
+ * require 'net/http'
+ *
+ * http_response =
+ * Net::HTTP.start ocsp_uri.hostname, ocsp_uri.port do |http|
+ * http.post ocsp_uri.path, request.to_der,
+ * 'content-type' => 'application/ocsp-request'
+ * end
+ *
+ * response = OpenSSL::OCSP::Response.new http_response.body
+ * response_basic = response.basic
+ *
+ * First we check if the response has a valid signature. Without a valid
+ * signature we cannot trust it. If you get a failure here you may be
+ * missing a system certificate store or may be missing the intermediate
+ * certificates.
+ *
+ * store = OpenSSL::X509::Store.new
+ * store.set_default_paths
+ *
+ * unless response_basic.verify [], store then
+ * raise 'response is not signed by a trusted certificate'
+ * end
+ *
+ * The response contains the status information (success/fail). We can
+ * display the status as a string:
+ *
+ * puts response.status_string #=> successful
+ *
+ * Next we need to know the response details to determine if the response
+ * matches our request. First we check the nonce. Again, not all CAs
+ * support a nonce. See Request#check_nonce for the meanings of the
+ * return values.
+ *
+ * p request.check_nonce basic_response #=> value from -1 to 3
+ *
+ * Then extract the status information for the certificate from the basic
+ * response.
+ *
+ * single_response = basic_response.find_response(certificate_id)
+ *
+ * unless single_response
+ * raise 'basic_response does not have the status for the certificate'
+ * end
+ *
+ * Then check the validity. A status issued in the future must be rejected.
+ *
+ * unless single_response.check_validity
+ * raise 'this_update is in the future or next_update time has passed'
+ * end
+ *
+ * case single_response.cert_status
+ * when OpenSSL::OCSP::V_CERTSTATUS_GOOD
+ * puts 'certificate is still valid'
+ * when OpenSSL::OCSP::V_CERTSTATUS_REVOKED
+ * puts "certificate has been revoked at #{single_response.revocation_time}"
+ * when OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
+ * puts 'responder doesn't know about the certificate'
+ * end
+ */
+
mOCSP = rb_define_module_under(mOSSL, "OCSP");
- eOCSPError = rb_define_class_under(mOCSP, "OCSPError", rb_cObject);
+ /*
+ * OCSP error class.
+ */
+
+ eOCSPError = rb_define_class_under(mOCSP, "OCSPError", eOSSLError);
+
+ /*
+ * An OpenSSL::OCSP::Request contains the certificate information for
+ * determining if a certificate has been revoked or not. A Request can be
+ * created for a certificate or from a DER-encoded request created
+ * elsewhere.
+ */
cOCSPReq = rb_define_class_under(mOCSP, "Request", rb_cObject);
rb_define_alloc_func(cOCSPReq, ossl_ocspreq_alloc);
+ rb_define_method(cOCSPReq, "initialize_copy", ossl_ocspreq_initialize_copy, 1);
rb_define_method(cOCSPReq, "initialize", ossl_ocspreq_initialize, -1);
rb_define_method(cOCSPReq, "add_nonce", ossl_ocspreq_add_nonce, -1);
rb_define_method(cOCSPReq, "check_nonce", ossl_ocspreq_check_nonce, 1);
rb_define_method(cOCSPReq, "add_certid", ossl_ocspreq_add_certid, 1);
rb_define_method(cOCSPReq, "certid", ossl_ocspreq_get_certid, 0);
+ rb_define_method(cOCSPReq, "signed?", ossl_ocspreq_signed_p, 0);
rb_define_method(cOCSPReq, "sign", ossl_ocspreq_sign, -1);
rb_define_method(cOCSPReq, "verify", ossl_ocspreq_verify, -1);
rb_define_method(cOCSPReq, "to_der", ossl_ocspreq_to_der, 0);
+ /*
+ * An OpenSSL::OCSP::Response contains the status of a certificate check
+ * which is created from an OpenSSL::OCSP::Request.
+ */
+
cOCSPRes = rb_define_class_under(mOCSP, "Response", rb_cObject);
rb_define_singleton_method(cOCSPRes, "create", ossl_ocspres_s_create, 2);
rb_define_alloc_func(cOCSPRes, ossl_ocspres_alloc);
+ rb_define_method(cOCSPRes, "initialize_copy", ossl_ocspres_initialize_copy, 1);
rb_define_method(cOCSPRes, "initialize", ossl_ocspres_initialize, -1);
rb_define_method(cOCSPRes, "status", ossl_ocspres_status, 0);
rb_define_method(cOCSPRes, "status_string", ossl_ocspres_status_string, 0);
rb_define_method(cOCSPRes, "basic", ossl_ocspres_get_basic, 0);
rb_define_method(cOCSPRes, "to_der", ossl_ocspres_to_der, 0);
+ /*
+ * An OpenSSL::OCSP::BasicResponse contains the status of a certificate
+ * check which is created from an OpenSSL::OCSP::Request. A
+ * BasicResponse is more detailed than a Response.
+ */
+
cOCSPBasicRes = rb_define_class_under(mOCSP, "BasicResponse", rb_cObject);
rb_define_alloc_func(cOCSPBasicRes, ossl_ocspbres_alloc);
+ rb_define_method(cOCSPBasicRes, "initialize_copy", ossl_ocspbres_initialize_copy, 1);
rb_define_method(cOCSPBasicRes, "initialize", ossl_ocspbres_initialize, -1);
rb_define_method(cOCSPBasicRes, "copy_nonce", ossl_ocspbres_copy_nonce, 1);
rb_define_method(cOCSPBasicRes, "add_nonce", ossl_ocspbres_add_nonce, -1);
rb_define_method(cOCSPBasicRes, "add_status", ossl_ocspbres_add_status, 7);
rb_define_method(cOCSPBasicRes, "status", ossl_ocspbres_get_status, 0);
+ rb_define_method(cOCSPBasicRes, "responses", ossl_ocspbres_get_responses, 0);
+ rb_define_method(cOCSPBasicRes, "find_response", ossl_ocspbres_find_response, 1);
rb_define_method(cOCSPBasicRes, "sign", ossl_ocspbres_sign, -1);
rb_define_method(cOCSPBasicRes, "verify", ossl_ocspbres_verify, -1);
+ rb_define_method(cOCSPBasicRes, "to_der", ossl_ocspbres_to_der, 0);
+
+ /*
+ * An OpenSSL::OCSP::SingleResponse represents an OCSP SingleResponse
+ * structure, which contains the basic information of the status of the
+ * certificate.
+ */
+ cOCSPSingleRes = rb_define_class_under(mOCSP, "SingleResponse", rb_cObject);
+ rb_define_alloc_func(cOCSPSingleRes, ossl_ocspsres_alloc);
+ rb_define_method(cOCSPSingleRes, "initialize_copy", ossl_ocspsres_initialize_copy, 1);
+ rb_define_method(cOCSPSingleRes, "initialize", ossl_ocspsres_initialize, 1);
+ rb_define_method(cOCSPSingleRes, "check_validity", ossl_ocspsres_check_validity, -1);
+ rb_define_method(cOCSPSingleRes, "certid", ossl_ocspsres_get_certid, 0);
+ rb_define_method(cOCSPSingleRes, "cert_status", ossl_ocspsres_get_cert_status, 0);
+ rb_define_method(cOCSPSingleRes, "this_update", ossl_ocspsres_get_this_update, 0);
+ rb_define_method(cOCSPSingleRes, "next_update", ossl_ocspsres_get_next_update, 0);
+ rb_define_method(cOCSPSingleRes, "revocation_time", ossl_ocspsres_get_revocation_time, 0);
+ rb_define_method(cOCSPSingleRes, "revocation_reason", ossl_ocspsres_get_revocation_reason, 0);
+ rb_define_method(cOCSPSingleRes, "extensions", ossl_ocspsres_get_extensions, 0);
+ rb_define_method(cOCSPSingleRes, "to_der", ossl_ocspsres_to_der, 0);
+
+ /*
+ * An OpenSSL::OCSP::CertificateId identifies a certificate to the CA so
+ * that a status check can be performed.
+ */
cOCSPCertId = rb_define_class_under(mOCSP, "CertificateId", rb_cObject);
rb_define_alloc_func(cOCSPCertId, ossl_ocspcid_alloc);
- rb_define_method(cOCSPCertId, "initialize", ossl_ocspcid_initialize, 2);
+ rb_define_method(cOCSPCertId, "initialize_copy", ossl_ocspcid_initialize_copy, 1);
+ rb_define_method(cOCSPCertId, "initialize", ossl_ocspcid_initialize, -1);
rb_define_method(cOCSPCertId, "cmp", ossl_ocspcid_cmp, 1);
rb_define_method(cOCSPCertId, "cmp_issuer", ossl_ocspcid_cmp_issuer, 1);
rb_define_method(cOCSPCertId, "serial", ossl_ocspcid_get_serial, 0);
+ rb_define_method(cOCSPCertId, "issuer_name_hash", ossl_ocspcid_get_issuer_name_hash, 0);
+ rb_define_method(cOCSPCertId, "issuer_key_hash", ossl_ocspcid_get_issuer_key_hash, 0);
+ rb_define_method(cOCSPCertId, "hash_algorithm", ossl_ocspcid_get_hash_algorithm, 0);
+ rb_define_method(cOCSPCertId, "to_der", ossl_ocspcid_to_der, 0);
+
+ /* Internal error in issuer */
+ rb_define_const(mOCSP, "RESPONSE_STATUS_INTERNALERROR", INT2NUM(OCSP_RESPONSE_STATUS_INTERNALERROR));
-#define DefOCSPConst(x) rb_define_const(mOCSP, #x, INT2NUM(OCSP_##x))
-
- DefOCSPConst(RESPONSE_STATUS_SUCCESSFUL);
- DefOCSPConst(RESPONSE_STATUS_MALFORMEDREQUEST);
- DefOCSPConst(RESPONSE_STATUS_INTERNALERROR);
- DefOCSPConst(RESPONSE_STATUS_TRYLATER);
- DefOCSPConst(RESPONSE_STATUS_SIGREQUIRED);
- DefOCSPConst(RESPONSE_STATUS_UNAUTHORIZED);
-
- DefOCSPConst(REVOKED_STATUS_NOSTATUS);
- DefOCSPConst(REVOKED_STATUS_UNSPECIFIED);
- DefOCSPConst(REVOKED_STATUS_KEYCOMPROMISE);
- DefOCSPConst(REVOKED_STATUS_CACOMPROMISE);
- DefOCSPConst(REVOKED_STATUS_AFFILIATIONCHANGED);
- DefOCSPConst(REVOKED_STATUS_SUPERSEDED);
- DefOCSPConst(REVOKED_STATUS_CESSATIONOFOPERATION);
- DefOCSPConst(REVOKED_STATUS_CERTIFICATEHOLD);
- DefOCSPConst(REVOKED_STATUS_REMOVEFROMCRL);
-
- DefOCSPConst(NOCERTS);
- DefOCSPConst(NOINTERN);
- DefOCSPConst(NOSIGS);
- DefOCSPConst(NOCHAIN);
- DefOCSPConst(NOVERIFY);
- DefOCSPConst(NOEXPLICIT);
- DefOCSPConst(NOCASIGN);
- DefOCSPConst(NODELEGATED);
- DefOCSPConst(NOCHECKS);
- DefOCSPConst(TRUSTOTHER);
- DefOCSPConst(RESPID_KEY);
- DefOCSPConst(NOTIME);
-
-#define DefOCSPVConst(x) rb_define_const(mOCSP, "V_" #x, INT2NUM(V_OCSP_##x))
-
- DefOCSPVConst(CERTSTATUS_GOOD);
- DefOCSPVConst(CERTSTATUS_REVOKED);
- DefOCSPVConst(CERTSTATUS_UNKNOWN);
- DefOCSPVConst(RESPID_NAME);
- DefOCSPVConst(RESPID_KEY);
-}
-
-#else /* ! OSSL_OCSP_ENABLED */
+ /* Illegal confirmation request */
+ rb_define_const(mOCSP, "RESPONSE_STATUS_MALFORMEDREQUEST", INT2NUM(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST));
+
+ /* The certificate was revoked for an unknown reason */
+ rb_define_const(mOCSP, "REVOKED_STATUS_NOSTATUS", INT2NUM(OCSP_REVOKED_STATUS_NOSTATUS));
+
+ /* You must sign the request and resubmit */
+ rb_define_const(mOCSP, "RESPONSE_STATUS_SIGREQUIRED", INT2NUM(OCSP_RESPONSE_STATUS_SIGREQUIRED));
+
+ /* Response has valid confirmations */
+ rb_define_const(mOCSP, "RESPONSE_STATUS_SUCCESSFUL", INT2NUM(OCSP_RESPONSE_STATUS_SUCCESSFUL));
+
+ /* Try again later */
+ rb_define_const(mOCSP, "RESPONSE_STATUS_TRYLATER", INT2NUM(OCSP_RESPONSE_STATUS_TRYLATER));
+
+ /* The certificate subject's name or other information changed */
+ rb_define_const(mOCSP, "REVOKED_STATUS_AFFILIATIONCHANGED", INT2NUM(OCSP_REVOKED_STATUS_AFFILIATIONCHANGED));
+
+ /* This CA certificate was revoked due to a key compromise */
+ rb_define_const(mOCSP, "REVOKED_STATUS_CACOMPROMISE", INT2NUM(OCSP_REVOKED_STATUS_CACOMPROMISE));
+
+ /* The certificate is on hold */
+ rb_define_const(mOCSP, "REVOKED_STATUS_CERTIFICATEHOLD", INT2NUM(OCSP_REVOKED_STATUS_CERTIFICATEHOLD));
+
+ /* The certificate is no longer needed */
+ rb_define_const(mOCSP, "REVOKED_STATUS_CESSATIONOFOPERATION", INT2NUM(OCSP_REVOKED_STATUS_CESSATIONOFOPERATION));
+
+ /* The certificate was revoked due to a key compromise */
+ rb_define_const(mOCSP, "REVOKED_STATUS_KEYCOMPROMISE", INT2NUM(OCSP_REVOKED_STATUS_KEYCOMPROMISE));
+
+ /* The certificate was previously on hold and should now be removed from
+ * the CRL */
+ rb_define_const(mOCSP, "REVOKED_STATUS_REMOVEFROMCRL", INT2NUM(OCSP_REVOKED_STATUS_REMOVEFROMCRL));
+
+ /* The certificate was superseded by a new certificate */
+ rb_define_const(mOCSP, "REVOKED_STATUS_SUPERSEDED", INT2NUM(OCSP_REVOKED_STATUS_SUPERSEDED));
+
+ /* Your request is unauthorized. */
+ rb_define_const(mOCSP, "RESPONSE_STATUS_UNAUTHORIZED", INT2NUM(OCSP_RESPONSE_STATUS_UNAUTHORIZED));
+
+ /* The certificate was revoked for an unspecified reason */
+ rb_define_const(mOCSP, "REVOKED_STATUS_UNSPECIFIED", INT2NUM(OCSP_REVOKED_STATUS_UNSPECIFIED));
+
+ /* Do not include certificates in the response */
+ rb_define_const(mOCSP, "NOCERTS", INT2NUM(OCSP_NOCERTS));
+
+ /* Do not search certificates contained in the response for a signer */
+ rb_define_const(mOCSP, "NOINTERN", INT2NUM(OCSP_NOINTERN));
+
+ /* Do not check the signature on the response */
+ rb_define_const(mOCSP, "NOSIGS", INT2NUM(OCSP_NOSIGS));
+
+ /* Do not verify the certificate chain on the response */
+ rb_define_const(mOCSP, "NOCHAIN", INT2NUM(OCSP_NOCHAIN));
+
+ /* Do not verify the response at all */
+ rb_define_const(mOCSP, "NOVERIFY", INT2NUM(OCSP_NOVERIFY));
+
+ /* Do not check trust */
+ rb_define_const(mOCSP, "NOEXPLICIT", INT2NUM(OCSP_NOEXPLICIT));
+
+ /* (This flag is not used by OpenSSL 1.0.1g) */
+ rb_define_const(mOCSP, "NOCASIGN", INT2NUM(OCSP_NOCASIGN));
+
+ /* (This flag is not used by OpenSSL 1.0.1g) */
+ rb_define_const(mOCSP, "NODELEGATED", INT2NUM(OCSP_NODELEGATED));
+
+ /* Do not make additional signing certificate checks */
+ rb_define_const(mOCSP, "NOCHECKS", INT2NUM(OCSP_NOCHECKS));
+
+ /* Do not verify additional certificates */
+ rb_define_const(mOCSP, "TRUSTOTHER", INT2NUM(OCSP_TRUSTOTHER));
+
+ /* Identify the response by signing the certificate key ID */
+ rb_define_const(mOCSP, "RESPID_KEY", INT2NUM(OCSP_RESPID_KEY));
+
+ /* Do not include producedAt time in response */
+ rb_define_const(mOCSP, "NOTIME", INT2NUM(OCSP_NOTIME));
+
+ /* Indicates the certificate is not revoked but does not necessarily mean
+ * the certificate was issued or that this response is within the
+ * certificate's validity interval */
+ rb_define_const(mOCSP, "V_CERTSTATUS_GOOD", INT2NUM(V_OCSP_CERTSTATUS_GOOD));
+ /* Indicates the certificate has been revoked either permanently or
+ * temporarily (on hold). */
+ rb_define_const(mOCSP, "V_CERTSTATUS_REVOKED", INT2NUM(V_OCSP_CERTSTATUS_REVOKED));
+
+ /* Indicates the responder does not know about the certificate being
+ * requested. */
+ rb_define_const(mOCSP, "V_CERTSTATUS_UNKNOWN", INT2NUM(V_OCSP_CERTSTATUS_UNKNOWN));
+
+ /* The responder ID is based on the key name. */
+ rb_define_const(mOCSP, "V_RESPID_NAME", INT2NUM(V_OCSP_RESPID_NAME));
+
+ /* The responder ID is based on the public key. */
+ rb_define_const(mOCSP, "V_RESPID_KEY", INT2NUM(V_OCSP_RESPID_KEY));
+}
+#else
void
-Init_ossl_ocsp()
+Init_ossl_ocsp(void)
{
}
#endif
diff --git a/ext/openssl/ossl_ocsp.h b/ext/openssl/ossl_ocsp.h
index 65b4f2e23f..becd70ffed 100644
--- a/ext/openssl/ossl_ocsp.h
+++ b/ext/openssl/ossl_ocsp.h
@@ -1,24 +1,16 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
* Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_OCSP_H_)
#define _OSSL_OCSP_H_
-#if defined(OSSL_OCSP_ENABLED)
-extern VALUE mOCSP;
-extern VALUE cOPCSReq;
-extern VALUE cOPCSRes;
-extern VALUE cOPCSBasicRes;
-#endif
-
void Init_ossl_ocsp(void);
#endif /* _OSSL_OCSP_H_ */
diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c
index e7d9954c5a..a47c81354c 100644
--- a/ext/openssl/ossl_pkcs12.c
+++ b/ext/openssl/ossl_pkcs12.c
@@ -1,23 +1,20 @@
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
- * $Id$
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#define WrapPKCS12(klass, obj, p12) do { \
- if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
- obj = Data_Wrap_Struct(klass, 0, PKCS12_free, p12); \
-} while (0)
+#define NewPKCS12(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_pkcs12_type, 0)
-#define GetPKCS12(obj, p12) do { \
- Data_Get_Struct(obj, PKCS12, p12); \
- if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
+#define SetPKCS12(obj, p12) do { \
+ if(!(p12)) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
+ RTYPEDDATA_DATA(obj) = (p12); \
} while (0)
-#define SafeGetPKCS12(obj, p12) do { \
- OSSL_Check_Kind(obj, cPKCS12); \
- GetPKCS12(obj, p12); \
+#define GetPKCS12(obj, p12) do { \
+ TypedData_Get_Struct((obj), PKCS12, &ossl_pkcs12_type, (p12)); \
+ if(!(p12)) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
} while (0)
#define ossl_pkcs12_set_key(o,v) rb_iv_set((o), "@key", (v))
@@ -30,54 +27,171 @@
/*
* Classes
*/
-VALUE mPKCS12;
-VALUE cPKCS12;
-VALUE ePKCS12Error;
+static VALUE cPKCS12;
+static VALUE ePKCS12Error;
/*
* Private
*/
+static void
+ossl_pkcs12_free(void *ptr)
+{
+ PKCS12_free(ptr);
+}
+
+static const rb_data_type_t ossl_pkcs12_type = {
+ "OpenSSL/PKCS12",
+ {
+ 0, ossl_pkcs12_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
static VALUE
ossl_pkcs12_s_allocate(VALUE klass)
{
PKCS12 *p12;
VALUE obj;
+ obj = NewPKCS12(klass);
if(!(p12 = PKCS12_new())) ossl_raise(ePKCS12Error, NULL);
- WrapPKCS12(klass, obj, p12);
+ SetPKCS12(obj, p12);
return obj;
}
+/* :nodoc: */
+static VALUE
+ossl_pkcs12_initialize_copy(VALUE self, VALUE other)
+{
+ PKCS12 *p12, *p12_old, *p12_new;
+
+ rb_check_frozen(self);
+ GetPKCS12(self, p12_old);
+ GetPKCS12(other, p12);
+
+ p12_new = ASN1_dup((i2d_of_void *)i2d_PKCS12, (d2i_of_void *)d2i_PKCS12, (char *)p12);
+ if (!p12_new)
+ ossl_raise(ePKCS12Error, "ASN1_dup");
+
+ SetPKCS12(self, p12_new);
+ PKCS12_free(p12_old);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
+ *
+ * === Parameters
+ * * _pass_ - string
+ * * _name_ - A string describing the key.
+ * * _key_ - Any PKey.
+ * * _cert_ - A X509::Certificate.
+ * * The public_key portion of the certificate must contain a valid public key.
+ * * The not_before and not_after fields must be filled in.
+ * * _ca_ - An optional array of X509::Certificate's.
+ * * _key_pbe_ - string
+ * * _cert_pbe_ - string
+ * * _key_iter_ - integer
+ * * _mac_iter_ - integer
+ * * _keytype_ - An integer representing an MSIE specific extension.
+ *
+ * Any optional arguments may be supplied as +nil+ to preserve the OpenSSL defaults.
+ *
+ * See the OpenSSL documentation for PKCS12_create().
+ */
static VALUE
ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
{
- VALUE pass, name, pkey, cert, ca;
+ VALUE pass, name, pkey, cert, ca, key_nid, cert_nid, key_iter, mac_iter, keytype;
VALUE obj;
char *passphrase, *friendlyname;
EVP_PKEY *key;
X509 *x509;
STACK_OF(X509) *x509s;
+ int nkey = 0, ncert = 0, kiter = 0, miter = 0, ktype = 0;
PKCS12 *p12;
-
- rb_scan_args(argc, argv, "41", &pass, &name, &pkey, &cert, &ca);
- passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
- friendlyname = NIL_P(name) ? NULL : StringValuePtr(name);
+
+ rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype);
+ passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass);
+ friendlyname = NIL_P(name) ? NULL : StringValueCStr(name);
key = GetPKeyPtr(pkey);
x509 = GetX509CertPtr(cert);
+/* TODO: make a VALUE to nid function */
+ if (!NIL_P(key_nid)) {
+ if ((nkey = OBJ_txt2nid(StringValueCStr(key_nid))) == NID_undef)
+ ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, key_nid);
+ }
+ if (!NIL_P(cert_nid)) {
+ if ((ncert = OBJ_txt2nid(StringValueCStr(cert_nid))) == NID_undef)
+ ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, cert_nid);
+ }
+ if (!NIL_P(key_iter))
+ kiter = NUM2INT(key_iter);
+ if (!NIL_P(mac_iter))
+ miter = NUM2INT(mac_iter);
+ if (!NIL_P(keytype))
+ ktype = NUM2INT(keytype);
+
+#if defined(OPENSSL_IS_AWSLC)
+ if (ktype != 0) {
+ ossl_raise(rb_eArgError, "Unknown key usage type %"PRIsVALUE, INT2NUM(ktype));
+ }
+#else
+ if (ktype != 0 && ktype != KEY_SIG && ktype != KEY_EX) {
+ ossl_raise(rb_eArgError, "Unknown key usage type %"PRIsVALUE, INT2NUM(ktype));
+ }
+#endif
+
+ obj = NewPKCS12(cPKCS12);
x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
- 0, 0, 0, 0, 0);
+ nkey, ncert, kiter, miter, ktype);
sk_X509_pop_free(x509s, X509_free);
if(!p12) ossl_raise(ePKCS12Error, NULL);
- WrapPKCS12(cPKCS12, obj, p12);
+ SetPKCS12(obj, p12);
+
+ ossl_pkcs12_set_key(obj, pkey);
+ ossl_pkcs12_set_cert(obj, cert);
+ ossl_pkcs12_set_ca_certs(obj, ca);
return obj;
}
static VALUE
+ossl_pkey_wrap_i(VALUE arg)
+{
+ return ossl_pkey_wrap((EVP_PKEY *)arg);
+}
+
+static VALUE
+ossl_x509_new_i(VALUE arg)
+{
+ return ossl_x509_new((X509 *)arg);
+}
+
+static VALUE
+ossl_x509_sk2ary_i(VALUE arg)
+{
+ return ossl_x509_sk2ary((STACK_OF(X509) *)arg);
+}
+
+/*
+ * call-seq:
+ * PKCS12.new -> pkcs12
+ * PKCS12.new(str) -> pkcs12
+ * PKCS12.new(str, pass) -> pkcs12
+ *
+ * === Parameters
+ * * _str_ - Must be a DER encoded PKCS12 string.
+ * * _pass_ - string
+ */
+static VALUE
ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
{
+ PKCS12 *p12, *p12_orig = DATA_PTR(self);
BIO *in;
VALUE arg, pass, pkey, cert, ca;
char *passphrase;
@@ -87,23 +201,29 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
int st = 0;
if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self;
- passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
- in = ossl_obj2bio(arg);
- d2i_PKCS12_bio(in, (PKCS12 **)&DATA_PTR(self));
+ passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass);
+ in = ossl_obj2bio(&arg);
+ p12 = d2i_PKCS12_bio(in, NULL);
BIO_free(in);
+ if (!p12)
+ ossl_raise(ePKCS12Error, "d2i_PKCS12_bio");
+ PKCS12_free(p12_orig);
+ RTYPEDDATA_DATA(self) = p12;
pkey = cert = ca = Qnil;
- if(!PKCS12_parse((PKCS12*)DATA_PTR(self), passphrase, &key, &x509, &x509s))
- ossl_raise(ePKCS12Error, NULL);
- pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key,
- &st); /* NO DUP */
- if(st) goto err;
- cert = rb_protect((VALUE(*)_((VALUE)))ossl_x509_new, (VALUE)x509, &st);
- if(st) goto err;
- if(x509s){
- ca =
- rb_protect((VALUE(*)_((VALUE)))ossl_x509_sk2ary, (VALUE)x509s, &st);
- if(st) goto err;
+ if (!PKCS12_parse(p12, passphrase, &key, &x509, &x509s))
+ ossl_raise(ePKCS12Error, "PKCS12_parse");
+ if (key) {
+ pkey = rb_protect(ossl_pkey_wrap_i, (VALUE)key, &st);
+ if (st) goto err;
+ }
+ if (x509) {
+ cert = rb_protect(ossl_x509_new_i, (VALUE)x509, &st);
+ if (st) goto err;
+ }
+ if (x509s) {
+ ca = rb_protect(ossl_x509_sk2ary_i, (VALUE)x509s, &st);
+ if (st) goto err;
}
err:
@@ -127,28 +247,83 @@ ossl_pkcs12_to_der(VALUE self)
GetPKCS12(self, p12);
if((len = i2d_PKCS12(p12, NULL)) <= 0)
- ossl_raise(ePKCS12Error, NULL);
+ ossl_raise(ePKCS12Error, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = (unsigned char *)RSTRING_PTR(str);
if(i2d_PKCS12(p12, &p) <= 0)
- ossl_raise(ePKCS12Error, NULL);
+ ossl_raise(ePKCS12Error, NULL);
ossl_str_adjust(str, p);
return str;
}
+/*
+ * call-seq:
+ * pkcs12.set_mac(pass, salt = nil, iter = nil, md_type = nil)
+ *
+ * Sets MAC parameters and generates MAC over the PKCS #12 structure.
+ *
+ * This method uses HMAC and the PKCS #12 specific password-based KDF as
+ * specified in the original PKCS #12.
+ *
+ * See also the man page PKCS12_set_mac(3).
+ *
+ * Added in version 3.3.0.
+ */
+static VALUE
+pkcs12_set_mac(int argc, VALUE *argv, VALUE self)
+{
+ PKCS12 *p12;
+ VALUE pass, salt, iter, md_name, md_holder = Qnil;
+ int iter_i = 0;
+ const EVP_MD *md_type = NULL;
+
+ rb_scan_args(argc, argv, "13", &pass, &salt, &iter, &md_name);
+ rb_check_frozen(self);
+ GetPKCS12(self, p12);
+
+ StringValue(pass);
+ if (!NIL_P(salt))
+ StringValue(salt);
+ if (!NIL_P(iter))
+ iter_i = NUM2INT(iter);
+ if (!NIL_P(md_name))
+ md_type = ossl_evp_md_fetch(md_name, &md_holder);
+
+ if (!PKCS12_set_mac(p12, RSTRING_PTR(pass), RSTRING_LENINT(pass),
+ !NIL_P(salt) ? (unsigned char *)RSTRING_PTR(salt) : NULL,
+ !NIL_P(salt) ? RSTRING_LENINT(salt) : 0,
+ iter_i, md_type))
+ ossl_raise(ePKCS12Error, "PKCS12_set_mac");
+
+ return Qnil;
+}
+
void
-Init_ossl_pkcs12()
+Init_ossl_pkcs12(void)
{
- mPKCS12 = rb_define_module_under(mOSSL, "PKCS12");
- cPKCS12 = rb_define_class_under(mPKCS12, "PKCS12", rb_cObject);
- ePKCS12Error = rb_define_class_under(mPKCS12, "PKCS12Error", eOSSLError);
- rb_define_module_function(mPKCS12, "create", ossl_pkcs12_s_create, -1);
+#undef rb_intern
+ /*
+ * Defines a file format commonly used to store private keys with
+ * accompanying public key certificates, protected with a password-based
+ * symmetric key.
+ */
+ cPKCS12 = rb_define_class_under(mOSSL, "PKCS12", rb_cObject);
+ ePKCS12Error = rb_define_class_under(cPKCS12, "PKCS12Error", eOSSLError);
+ rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1);
rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate);
+ rb_define_method(cPKCS12, "initialize_copy", ossl_pkcs12_initialize_copy, 1);
rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse);
rb_attr(cPKCS12, rb_intern("certificate"), 1, 0, Qfalse);
rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse);
rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1);
rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0);
+ rb_define_method(cPKCS12, "set_mac", pkcs12_set_mac, -1);
+
+#if !defined(OPENSSL_IS_AWSLC)
+ /* MSIE specific PKCS12 key usage extensions */
+ rb_define_const(cPKCS12, "KEY_EX", INT2NUM(KEY_EX));
+ rb_define_const(cPKCS12, "KEY_SIG", INT2NUM(KEY_SIG));
+#endif
}
diff --git a/ext/openssl/ossl_pkcs12.h b/ext/openssl/ossl_pkcs12.h
index 01dde2bc30..6d2cd901cb 100644
--- a/ext/openssl/ossl_pkcs12.h
+++ b/ext/openssl/ossl_pkcs12.h
@@ -1,16 +1,10 @@
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
- * $Id$
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_PKCS12_H_)
#define _OSSL_PKCS12_H_
-extern VALUE mPKCS12;
-extern VALUE cPKCS12;
-extern VALUE ePKCS12Error;
-
void Init_ossl_pkcs12(void);
#endif /* _OSSL_PKCS12_H_ */
-
diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index 38a7dce7a2..44e8cb305b 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -1,140 +1,197 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#define WrapPKCS7(klass, obj, pkcs7) do { \
- if (!pkcs7) { \
- ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
+#define NewPKCS7(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_pkcs7_type, 0)
+#define SetPKCS7(obj, pkcs7) do { \
+ if (!(pkcs7)) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
} \
- obj = Data_Wrap_Struct(klass, 0, PKCS7_free, pkcs7); \
+ RTYPEDDATA_DATA(obj) = (pkcs7); \
} while (0)
#define GetPKCS7(obj, pkcs7) do { \
- Data_Get_Struct(obj, PKCS7, pkcs7); \
- if (!pkcs7) { \
- ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
+ TypedData_Get_Struct((obj), PKCS7, &ossl_pkcs7_type, (pkcs7)); \
+ if (!(pkcs7)) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
} \
} while (0)
-#define SafeGetPKCS7(obj, pkcs7) do { \
- OSSL_Check_Kind(obj, cPKCS7); \
- GetPKCS7(obj, pkcs7); \
-} while (0)
-#define WrapPKCS7si(klass, obj, p7si) do { \
- if (!p7si) { \
- ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
+#define NewPKCS7si(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_pkcs7_signer_info_type, 0)
+#define SetPKCS7si(obj, p7si) do { \
+ if (!(p7si)) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
} \
- obj = Data_Wrap_Struct(klass, 0, PKCS7_SIGNER_INFO_free, p7si); \
+ RTYPEDDATA_DATA(obj) = (p7si); \
} while (0)
#define GetPKCS7si(obj, p7si) do { \
- Data_Get_Struct(obj, PKCS7_SIGNER_INFO, p7si); \
- if (!p7si) { \
- ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
+ TypedData_Get_Struct((obj), PKCS7_SIGNER_INFO, &ossl_pkcs7_signer_info_type, (p7si)); \
+ if (!(p7si)) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
} \
} while (0)
-#define SafeGetPKCS7si(obj, p7si) do { \
- OSSL_Check_Kind(obj, cPKCS7Signer); \
- GetPKCS7si(obj, p7si); \
-} while (0)
-#define WrapPKCS7ri(klass, obj, p7ri) do { \
- if (!p7ri) { \
- ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
+#define NewPKCS7ri(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_pkcs7_recip_info_type, 0)
+#define SetPKCS7ri(obj, p7ri) do { \
+ if (!(p7ri)) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
} \
- obj = Data_Wrap_Struct(klass, 0, PKCS7_RECIP_INFO_free, p7ri); \
+ RTYPEDDATA_DATA(obj) = (p7ri); \
} while (0)
#define GetPKCS7ri(obj, p7ri) do { \
- Data_Get_Struct(obj, PKCS7_RECIP_INFO, p7ri); \
- if (!p7ri) { \
- ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
+ TypedData_Get_Struct((obj), PKCS7_RECIP_INFO, &ossl_pkcs7_recip_info_type, (p7ri)); \
+ if (!(p7ri)) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
} \
} while (0)
-#define SafeGetPKCS7ri(obj, p7ri) do { \
- OSSL_Check_Kind(obj, cPKCS7Recipient); \
- GetPKCS7ri(obj, p7ri); \
-} while (0)
-#define numberof(ary) (sizeof(ary)/sizeof(ary[0]))
+#define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
#define ossl_pkcs7_set_data(o,v) rb_iv_set((o), "@data", (v))
#define ossl_pkcs7_get_data(o) rb_iv_get((o), "@data")
#define ossl_pkcs7_set_err_string(o,v) rb_iv_set((o), "@error_string", (v))
#define ossl_pkcs7_get_err_string(o) rb_iv_get((o), "@error_string")
-/*
+/*
* Classes
*/
-VALUE mPKCS7;
-VALUE cPKCS7;
-VALUE cPKCS7Signer;
-VALUE cPKCS7Recipient;
-VALUE ePKCS7Error;
+static VALUE cPKCS7;
+static VALUE cPKCS7Signer;
+static VALUE cPKCS7Recipient;
+static VALUE ePKCS7Error;
+static ID id_md_holder, id_cipher_holder;
+
+static void
+ossl_pkcs7_free(void *ptr)
+{
+ PKCS7_free(ptr);
+}
-/*
- * Public
- * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM)
- */
-static VALUE
-ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
+static const rb_data_type_t ossl_pkcs7_type = {
+ "OpenSSL/PKCS7",
+ {
+ 0, ossl_pkcs7_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+VALUE
+ossl_pkcs7_new(PKCS7 *p7)
{
- PKCS7_SIGNER_INFO *pkcs7;
- VALUE obj;
+ PKCS7 *new;
+ VALUE obj = NewPKCS7(cPKCS7);
- pkcs7 = p7si ? PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new();
- if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
- WrapPKCS7si(cPKCS7Signer, obj, pkcs7);
+ new = PKCS7_dup(p7);
+ if (!new)
+ ossl_raise(ePKCS7Error, "PKCS7_dup");
+ SetPKCS7(obj, new);
return obj;
}
+static void
+ossl_pkcs7_signer_info_free(void *ptr)
+{
+ PKCS7_SIGNER_INFO_free(ptr);
+}
+
+static const rb_data_type_t ossl_pkcs7_signer_info_type = {
+ "OpenSSL/PKCS7/SIGNER_INFO",
+ {
+ 0, ossl_pkcs7_signer_info_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static void
+ossl_pkcs7_recip_info_free(void *ptr)
+{
+ PKCS7_RECIP_INFO_free(ptr);
+}
+
+static const rb_data_type_t ossl_pkcs7_recip_info_type = {
+ "OpenSSL/PKCS7/RECIP_INFO",
+ {
+ 0, ossl_pkcs7_recip_info_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+/*
+ * Public
+ * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM)
+ */
static PKCS7_SIGNER_INFO *
-DupPKCS7SignerPtr(VALUE obj)
+ossl_PKCS7_SIGNER_INFO_dup(PKCS7_SIGNER_INFO *si)
{
- PKCS7_SIGNER_INFO *p7si, *pkcs7;
-
- SafeGetPKCS7si(obj, p7si);
- if (!(pkcs7 = PKCS7_SIGNER_INFO_dup(p7si))) {
- ossl_raise(ePKCS7Error, NULL);
+ PKCS7_SIGNER_INFO *si_new = ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO,
+ (d2i_of_void *)d2i_PKCS7_SIGNER_INFO,
+ si);
+ if (si_new && si->pkey) {
+ EVP_PKEY_up_ref(si->pkey);
+ si_new->pkey = si->pkey;
}
+ return si_new;
+}
- return pkcs7;
+static PKCS7_RECIP_INFO *
+ossl_PKCS7_RECIP_INFO_dup(PKCS7_RECIP_INFO *ri)
+{
+ PKCS7_RECIP_INFO *ri_new = ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO,
+ (d2i_of_void *)d2i_PKCS7_RECIP_INFO,
+ ri);
+ if (ri_new && ri->cert) {
+ if (!X509_up_ref(ri->cert)) {
+ PKCS7_RECIP_INFO_free(ri_new);
+ return NULL;
+ }
+ ri_new->cert = ri->cert;
+ }
+ return ri_new;
}
static VALUE
-ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri)
+ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
{
- PKCS7_RECIP_INFO *pkcs7;
+ PKCS7_SIGNER_INFO *p7si_new;
VALUE obj;
- pkcs7 = p7ri ? PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new();
- if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
- WrapPKCS7ri(cPKCS7Recipient, obj, pkcs7);
+ obj = NewPKCS7si(cPKCS7Signer);
+ p7si_new = ossl_PKCS7_SIGNER_INFO_dup(p7si);
+ if (!p7si_new)
+ ossl_raise(ePKCS7Error, "ASN1_dup");
+ SetPKCS7si(obj, p7si_new);
return obj;
}
-static PKCS7_RECIP_INFO *
-DupPKCS7RecipientPtr(VALUE obj)
+static VALUE
+ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri)
{
- PKCS7_RECIP_INFO *p7ri, *pkcs7;
-
- SafeGetPKCS7ri(obj, p7ri);
- if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) {
- ossl_raise(ePKCS7Error, NULL);
- }
+ PKCS7_RECIP_INFO *p7ri_new;
+ VALUE obj;
+
+ obj = NewPKCS7ri(cPKCS7Recipient);
+ p7ri_new = ossl_PKCS7_RECIP_INFO_dup(p7ri);
+ if (!p7ri_new)
+ ossl_raise(ePKCS7Error,"ASN1_dup");
+ SetPKCS7ri(obj, p7ri_new);
- return pkcs7;
+ return obj;
}
/*
- * Private
+ * call-seq:
+ * PKCS7.read_smime(string) => pkcs7
*/
static VALUE
ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
@@ -143,19 +200,30 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
PKCS7 *pkcs7;
VALUE ret, data;
- in = ossl_obj2bio(arg);
+ ret = NewPKCS7(cPKCS7);
+ in = ossl_obj2bio(&arg);
out = NULL;
pkcs7 = SMIME_read_PKCS7(in, &out);
BIO_free(in);
- if(!pkcs7) ossl_raise(ePKCS7Error, NULL);
+ if (!pkcs7)
+ ossl_raise(ePKCS7Error, "Could not parse the PKCS7");
+ if (!pkcs7->d.ptr) {
+ PKCS7_free(pkcs7);
+ ossl_raise(ePKCS7Error, "No content in PKCS7");
+ }
+
data = out ? ossl_membio2str(out) : Qnil;
- WrapPKCS7(cPKCS7, ret, pkcs7);
+ SetPKCS7(ret, pkcs7);
ossl_pkcs7_set_data(ret, data);
ossl_pkcs7_set_err_string(ret, Qnil);
return ret;
}
+/*
+ * call-seq:
+ * PKCS7.write_smime(pkcs7 [, data [, flags]]) => string
+ */
static VALUE
ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
{
@@ -168,10 +236,10 @@ ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
rb_scan_args(argc, argv, "12", &pkcs7, &data, &flags);
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
if(NIL_P(data)) data = ossl_pkcs7_get_data(pkcs7);
- SafeGetPKCS7(pkcs7, p7);
+ GetPKCS7(pkcs7, p7);
if(!NIL_P(data) && PKCS7_is_detached(p7))
- flg |= PKCS7_DETACHED;
- in = NIL_P(data) ? NULL : ossl_obj2bio(data);
+ flg |= PKCS7_DETACHED;
+ in = NIL_P(data) ? NULL : ossl_obj2bio(&data);
if(!(out = BIO_new(BIO_s_mem()))){
BIO_free(in);
ossl_raise(ePKCS7Error, NULL);
@@ -187,6 +255,10 @@ ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
return str;
}
+/*
+ * call-seq:
+ * PKCS7.sign(cert, key, data, [, certs [, flags]]) => pkcs7
+ */
static VALUE
ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
{
@@ -203,21 +275,22 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
- in = ossl_obj2bio(data);
+ ret = NewPKCS7(cPKCS7);
+ in = ossl_obj2bio(&data);
if(NIL_P(certs)) x509s = NULL;
else{
- x509s = ossl_protect_x509_ary2sk(certs, &status);
- if(status){
- BIO_free(in);
- rb_jump_tag(status);
- }
+ x509s = ossl_protect_x509_ary2sk(certs, &status);
+ if(status){
+ BIO_free(in);
+ rb_jump_tag(status);
+ }
}
if(!(pkcs7 = PKCS7_sign(x509, pkey, x509s, in, flg))){
- BIO_free(in);
- sk_X509_pop_free(x509s, X509_free);
- ossl_raise(ePKCS7Error, NULL);
+ BIO_free(in);
+ sk_X509_pop_free(x509s, X509_free);
+ ossl_raise(ePKCS7Error, NULL);
}
- WrapPKCS7(cPKCS7, ret, pkcs7);
+ SetPKCS7(ret, pkcs7);
ossl_pkcs7_set_data(ret, data);
ossl_pkcs7_set_err_string(ret, Qnil);
BIO_free(in);
@@ -226,10 +299,21 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
return ret;
}
+/*
+ * call-seq:
+ * PKCS7.encrypt(certs, data, cipher, flags = 0) => pkcs7
+ *
+ * Creates a PKCS #7 enveloped-data structure.
+ *
+ * Before version 3.3.0, +cipher+ was optional and defaulted to
+ * <tt>"RC2-40-CBC"</tt>.
+ *
+ * See also the man page PKCS7_encrypt(3).
+ */
static VALUE
ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
{
- VALUE certs, data, cipher, flags;
+ VALUE certs, data, cipher, flags, cipher_holder;
STACK_OF(X509) *x509s;
BIO *in;
const EVP_CIPHER *ciph;
@@ -238,36 +322,29 @@ ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
PKCS7 *p7;
rb_scan_args(argc, argv, "22", &certs, &data, &cipher, &flags);
- if(NIL_P(cipher)){
-#if !defined(OPENSSL_NO_RC2)
- ciph = EVP_rc2_40_cbc();
-#elif !defined(OPENSSL_NO_DES)
- ciph = EVP_des_ede3_cbc();
-#elif !defined(OPENSSL_NO_RC2)
- ciph = EVP_rc2_40_cbc();
-#elif !defined(OPENSSL_NO_AES)
- ciph = EVP_EVP_aes_128_cbc();
-#else
- ossl_raise(ePKCS7Error, "Must specify cipher");
-#endif
-
- }
- else ciph = GetCipherPtr(cipher); /* NO NEED TO DUP */
+ if (NIL_P(cipher)) {
+ rb_raise(rb_eArgError,
+ "cipher must be specified. Before version 3.3, " \
+ "the default cipher was RC2-40-CBC.");
+ }
+ ciph = ossl_evp_cipher_fetch(cipher, &cipher_holder);
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
- in = ossl_obj2bio(data);
+ ret = NewPKCS7(cPKCS7);
+ in = ossl_obj2bio(&data);
x509s = ossl_protect_x509_ary2sk(certs, &status);
if(status){
- BIO_free(in);
- rb_jump_tag(status);
+ BIO_free(in);
+ rb_jump_tag(status);
}
- if(!(p7 = PKCS7_encrypt(x509s, in, (EVP_CIPHER*)ciph, flg))){
- BIO_free(in);
- sk_X509_pop_free(x509s, X509_free);
- ossl_raise(ePKCS7Error, NULL);
+ if (!(p7 = PKCS7_encrypt(x509s, in, ciph, flg))) {
+ BIO_free(in);
+ sk_X509_pop_free(x509s, X509_free);
+ ossl_raise(ePKCS7Error, NULL);
}
BIO_free(in);
- WrapPKCS7(cPKCS7, ret, p7);
+ SetPKCS7(ret, p7);
ossl_pkcs7_set_data(ret, data);
+ rb_ivar_set(ret, id_cipher_holder, cipher_holder);
sk_X509_pop_free(x509s, X509_free);
return ret;
@@ -279,37 +356,55 @@ ossl_pkcs7_alloc(VALUE klass)
PKCS7 *pkcs7;
VALUE obj;
+ obj = NewPKCS7(klass);
if (!(pkcs7 = PKCS7_new())) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
- WrapPKCS7(klass, obj, pkcs7);
-
+ SetPKCS7(obj, pkcs7);
+
return obj;
}
+/*
+ * call-seq:
+ * PKCS7.new => pkcs7
+ * PKCS7.new(string) => pkcs7
+ *
+ * Many methods in this class aren't documented.
+ */
static VALUE
ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
{
- PKCS7 *p7;
+ PKCS7 *p7, *p7_orig = RTYPEDDATA_DATA(self);
BIO *in;
VALUE arg;
if(rb_scan_args(argc, argv, "01", &arg) == 0)
- return self;
+ return self;
arg = ossl_to_der_if_possible(arg);
- in = ossl_obj2bio(arg);
- p7 = PEM_read_bio_PKCS7(in, (PKCS7 **)&DATA_PTR(self), NULL, NULL);
+ in = ossl_obj2bio(&arg);
+ p7 = d2i_PKCS7_bio(in, NULL);
if (!p7) {
- BIO_reset(in);
- p7 = d2i_PKCS7_bio(in, (PKCS7 **)&DATA_PTR(self));
+ OSSL_BIO_reset(in);
+ p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
}
BIO_free(in);
+ if (!p7)
+ ossl_raise(ePKCS7Error, "Could not parse the PKCS7");
+ if (!p7->d.ptr) {
+ PKCS7_free(p7);
+ ossl_raise(ePKCS7Error, "No content in PKCS7");
+ }
+
+ RTYPEDDATA_DATA(self) = p7;
+ PKCS7_free(p7_orig);
ossl_pkcs7_set_data(self, Qnil);
ossl_pkcs7_set_err_string(self, Qnil);
return self;
}
+/* :nodoc: */
static VALUE
ossl_pkcs7_copy(VALUE self, VALUE other)
{
@@ -319,11 +414,11 @@ ossl_pkcs7_copy(VALUE self, VALUE other)
if (self == other) return self;
GetPKCS7(self, a);
- SafeGetPKCS7(other, b);
+ GetPKCS7(other, b);
pkcs7 = PKCS7_dup(b);
if (!pkcs7) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
DATA_PTR(self) = pkcs7;
PKCS7_free(a);
@@ -335,10 +430,11 @@ static int
ossl_pkcs7_sym2typeid(VALUE sym)
{
int i, ret = Qnil;
- char *s;
+ const char *s;
+ size_t l;
- static struct {
- const char *name;
+ static const struct {
+ char name[20];
int nid;
} p7_type_tab[] = {
{ "signed", NID_pkcs7_signed },
@@ -347,23 +443,29 @@ ossl_pkcs7_sym2typeid(VALUE sym)
{ "enveloped", NID_pkcs7_enveloped },
{ "encrypted", NID_pkcs7_encrypted },
{ "digest", NID_pkcs7_digest },
- { NULL, 0 },
};
- if(TYPE(sym) == T_SYMBOL) s = rb_id2name(SYM2ID(sym));
- else s = StringValuePtr(sym);
- for(i = 0; i < numberof(p7_type_tab); i++){
- if(p7_type_tab[i].name == NULL)
- ossl_raise(ePKCS7Error, "unknown type \"%s\"", s);
- if(strcmp(p7_type_tab[i].name, s) == 0){
- ret = p7_type_tab[i].nid;
- break;
- }
+ if (SYMBOL_P(sym)) sym = rb_sym2str(sym);
+ else StringValue(sym);
+ RSTRING_GETMEM(sym, s, l);
+
+ for(i = 0; ; i++){
+ if(i == numberof(p7_type_tab))
+ ossl_raise(ePKCS7Error, "unknown type \"%"PRIsVALUE"\"", sym);
+ if(strlen(p7_type_tab[i].name) != l) continue;
+ if(memcmp(p7_type_tab[i].name, s, l) == 0){
+ ret = p7_type_tab[i].nid;
+ break;
+ }
}
return ret;
}
+/*
+ * call-seq:
+ * pkcs7.type = type => type
+ */
static VALUE
ossl_pkcs7_set_type(VALUE self, VALUE type)
{
@@ -371,11 +473,15 @@ ossl_pkcs7_set_type(VALUE self, VALUE type)
GetPKCS7(self, p7);
if(!PKCS7_set_type(p7, ossl_pkcs7_sym2typeid(type)))
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
return type;
}
+/*
+ * call-seq:
+ * pkcs7.type => string or nil
+ */
static VALUE
ossl_pkcs7_get_type(VALUE self)
{
@@ -383,15 +489,15 @@ ossl_pkcs7_get_type(VALUE self)
GetPKCS7(self, p7);
if(PKCS7_type_is_signed(p7))
- return ID2SYM(rb_intern("signed"));
+ return ID2SYM(rb_intern("signed"));
if(PKCS7_type_is_encrypted(p7))
- return ID2SYM(rb_intern("encrypted"));
+ return ID2SYM(rb_intern("encrypted"));
if(PKCS7_type_is_enveloped(p7))
- return ID2SYM(rb_intern("enveloped"));
+ return ID2SYM(rb_intern("enveloped"));
if(PKCS7_type_is_signedAndEnveloped(p7))
- return ID2SYM(rb_intern("signedAndEnveloped"));
+ return ID2SYM(rb_intern("signedAndEnveloped"));
if(PKCS7_type_is_data(p7))
- return ID2SYM(rb_intern("data"));
+ return ID2SYM(rb_intern("data"));
return Qnil;
}
@@ -402,9 +508,9 @@ ossl_pkcs7_set_detached(VALUE self, VALUE flag)
GetPKCS7(self, p7);
if(flag != Qtrue && flag != Qfalse)
- ossl_raise(ePKCS7Error, "must specify a boolean");
+ ossl_raise(ePKCS7Error, "must specify a boolean");
if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0))
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
return flag;
}
@@ -414,6 +520,8 @@ ossl_pkcs7_get_detached(VALUE self)
{
PKCS7 *p7;
GetPKCS7(self, p7);
+ if (!PKCS7_type_is_signed(p7))
+ return Qfalse;
return PKCS7_get_detached(p7) ? Qtrue : Qfalse;
}
@@ -429,11 +537,14 @@ static VALUE
ossl_pkcs7_set_cipher(VALUE self, VALUE cipher)
{
PKCS7 *pkcs7;
+ const EVP_CIPHER *ciph;
+ VALUE cipher_holder;
GetPKCS7(self, pkcs7);
- if (!PKCS7_set_cipher(pkcs7, GetCipherPtr(cipher))) {
- ossl_raise(ePKCS7Error, NULL);
- }
+ ciph = ossl_evp_cipher_fetch(cipher, &cipher_holder);
+ if (!PKCS7_set_cipher(pkcs7, ciph))
+ ossl_raise(ePKCS7Error, "PKCS7_set_cipher");
+ rb_ivar_set(self, id_cipher_holder, cipher_holder);
return cipher;
}
@@ -442,17 +553,18 @@ static VALUE
ossl_pkcs7_add_signer(VALUE self, VALUE signer)
{
PKCS7 *pkcs7;
- PKCS7_SIGNER_INFO *p7si;
+ PKCS7_SIGNER_INFO *si, *si_new;
- p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */
GetPKCS7(self, pkcs7);
- if (!PKCS7_add_signer(pkcs7, p7si)) {
- PKCS7_SIGNER_INFO_free(p7si);
- ossl_raise(ePKCS7Error, "Could not add signer.");
- }
- if (PKCS7_type_is_signed(pkcs7)){
- PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
- V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data));
+ GetPKCS7si(signer, si);
+
+ si_new = ossl_PKCS7_SIGNER_INFO_dup(si);
+ if (!si_new)
+ ossl_raise(ePKCS7Error, "PKCS7_SIGNER_INFO_dup");
+
+ if (PKCS7_add_signer(pkcs7, si_new) != 1) {
+ PKCS7_SIGNER_INFO_free(si_new);
+ ossl_raise(ePKCS7Error, "PKCS7_add_signer");
}
return self;
@@ -463,22 +575,17 @@ ossl_pkcs7_get_signer(VALUE self)
{
PKCS7 *pkcs7;
STACK_OF(PKCS7_SIGNER_INFO) *sk;
- PKCS7_SIGNER_INFO *si;
int num, i;
VALUE ary;
-
+
GetPKCS7(self, pkcs7);
- if (!(sk = PKCS7_get_signer_info(pkcs7))) {
- OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!");
- return rb_ary_new();
- }
- if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) {
- ossl_raise(ePKCS7Error, "Negative number of signers!");
- }
- ary = rb_ary_new2(num);
+ if (!(sk = PKCS7_get_signer_info(pkcs7)))
+ return rb_ary_new();
+ num = sk_PKCS7_SIGNER_INFO_num(sk);
+ ary = rb_ary_new_capa(num);
for (i=0; i<num; i++) {
- si = sk_PKCS7_SIGNER_INFO_value(sk, i);
- rb_ary_push(ary, ossl_pkcs7si_new(si));
+ PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(sk, i);
+ rb_ary_push(ary, ossl_pkcs7si_new(si));
}
return ary;
@@ -488,13 +595,18 @@ static VALUE
ossl_pkcs7_add_recipient(VALUE self, VALUE recip)
{
PKCS7 *pkcs7;
- PKCS7_RECIP_INFO *ri;
+ PKCS7_RECIP_INFO *ri, *ri_new;
- ri = DupPKCS7RecipientPtr(recip); /* NEED TO DUP */
GetPKCS7(self, pkcs7);
- if (!PKCS7_add_recipient_info(pkcs7, ri)) {
- PKCS7_RECIP_INFO_free(ri);
- ossl_raise(ePKCS7Error, "Could not add recipient.");
+ GetPKCS7ri(recip, ri);
+
+ ri_new = ossl_PKCS7_RECIP_INFO_dup(ri);
+ if (!ri_new)
+ ossl_raise(ePKCS7Error, "PKCS7_RECIP_INFO_dup");
+
+ if (PKCS7_add_recipient_info(pkcs7, ri_new) != 1) {
+ PKCS7_RECIP_INFO_free(ri_new);
+ ossl_raise(ePKCS7Error, "PKCS7_add_recipient_info");
}
return self;
@@ -505,24 +617,21 @@ ossl_pkcs7_get_recipient(VALUE self)
{
PKCS7 *pkcs7;
STACK_OF(PKCS7_RECIP_INFO) *sk;
- PKCS7_RECIP_INFO *si;
int num, i;
VALUE ary;
-
+
GetPKCS7(self, pkcs7);
if (PKCS7_type_is_enveloped(pkcs7))
- sk = pkcs7->d.enveloped->recipientinfo;
+ sk = pkcs7->d.enveloped->recipientinfo;
else if (PKCS7_type_is_signedAndEnveloped(pkcs7))
- sk = pkcs7->d.signed_and_enveloped->recipientinfo;
+ sk = pkcs7->d.signed_and_enveloped->recipientinfo;
else sk = NULL;
if (!sk) return rb_ary_new();
- if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) {
- ossl_raise(ePKCS7Error, "Negative number of recipient!");
- }
- ary = rb_ary_new2(num);
+ num = sk_PKCS7_RECIP_INFO_num(sk);
+ ary = rb_ary_new_capa(num);
for (i=0; i<num; i++) {
- si = sk_PKCS7_RECIP_INFO_value(sk, i);
- rb_ary_push(ary, ossl_pkcs7ri_new(si));
+ PKCS7_RECIP_INFO *ri = sk_PKCS7_RECIP_INFO_value(sk, i);
+ rb_ary_push(ary, ossl_pkcs7ri_new(ri));
}
return ary;
@@ -537,40 +646,60 @@ ossl_pkcs7_add_certificate(VALUE self, VALUE cert)
GetPKCS7(self, pkcs7);
x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
if (!PKCS7_add_certificate(pkcs7, x509)){
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
return self;
}
-static STACK *
-pkcs7_get_certs_or_crls(VALUE self, int want_certs)
+static STACK_OF(X509) *
+pkcs7_get_certs(VALUE self)
{
PKCS7 *pkcs7;
STACK_OF(X509) *certs;
- STACK_OF(X509_CRL) *crls;
int i;
GetPKCS7(self, pkcs7);
i = OBJ_obj2nid(pkcs7->type);
switch(i){
- case NID_pkcs7_signed:
+ case NID_pkcs7_signed:
certs = pkcs7->d.sign->cert;
- crls = pkcs7->d.sign->crl;
break;
- case NID_pkcs7_signedAndEnveloped:
+ case NID_pkcs7_signedAndEnveloped:
certs = pkcs7->d.signed_and_enveloped->cert;
+ break;
+ default:
+ certs = NULL;
+ }
+
+ return certs;
+}
+
+static STACK_OF(X509_CRL) *
+pkcs7_get_crls(VALUE self)
+{
+ PKCS7 *pkcs7;
+ STACK_OF(X509_CRL) *crls;
+ int i;
+
+ GetPKCS7(self, pkcs7);
+ i = OBJ_obj2nid(pkcs7->type);
+ switch(i){
+ case NID_pkcs7_signed:
+ crls = pkcs7->d.sign->crl;
+ break;
+ case NID_pkcs7_signedAndEnveloped:
crls = pkcs7->d.signed_and_enveloped->crl;
break;
- default:
- certs = crls = NULL;
+ default:
+ crls = NULL;
}
- return want_certs ? certs : crls;
+ return crls;
}
static VALUE
-ossl_pkcs7_set_certs_i(VALUE i, VALUE arg)
+ossl_pkcs7_set_certs_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
{
return ossl_pkcs7_add_certificate(arg, i);
}
@@ -581,9 +710,12 @@ ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
STACK_OF(X509) *certs;
X509 *cert;
- certs = pkcs7_get_certs_or_crls(self, 1);
- while((cert = sk_X509_pop(certs))) X509_free(cert);
- rb_iterate(rb_each, ary, ossl_pkcs7_set_certs_i, self);
+ certs = pkcs7_get_certs(self);
+ if (certs) {
+ while ((cert = sk_X509_pop(certs)))
+ X509_free(cert);
+ }
+ rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self);
return ary;
}
@@ -591,7 +723,10 @@ ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
static VALUE
ossl_pkcs7_get_certificates(VALUE self)
{
- return ossl_x509_sk2ary(pkcs7_get_certs_or_crls(self, 1));
+ STACK_OF(X509) *certs = pkcs7_get_certs(self);
+ if (!certs)
+ return Qnil;
+ return ossl_x509_sk2ary(certs);
}
static VALUE
@@ -603,14 +738,14 @@ ossl_pkcs7_add_crl(VALUE self, VALUE crl)
GetPKCS7(self, pkcs7); /* NO DUP needed! */
x509crl = GetX509CRLPtr(crl);
if (!PKCS7_add_crl(pkcs7, x509crl)) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
return self;
}
static VALUE
-ossl_pkcs7_set_crls_i(VALUE i, VALUE arg)
+ossl_pkcs7_set_crls_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
{
return ossl_pkcs7_add_crl(arg, i);
}
@@ -621,9 +756,12 @@ ossl_pkcs7_set_crls(VALUE self, VALUE ary)
STACK_OF(X509_CRL) *crls;
X509_CRL *crl;
- crls = pkcs7_get_certs_or_crls(self, 0);
- while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl);
- rb_iterate(rb_each, ary, ossl_pkcs7_set_crls_i, self);
+ crls = pkcs7_get_crls(self);
+ if (crls) {
+ while ((crl = sk_X509_CRL_pop(crls)))
+ X509_CRL_free(crl);
+ }
+ rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self);
return ary;
}
@@ -631,7 +769,10 @@ ossl_pkcs7_set_crls(VALUE self, VALUE ary)
static VALUE
ossl_pkcs7_get_crls(VALUE self)
{
- return ossl_x509crl_sk2ary(pkcs7_get_certs_or_crls(self, 0));
+ STACK_OF(X509_CRL) *crls = pkcs7_get_crls(self);
+ if (!crls)
+ return Qnil;
+ return ossl_x509crl_sk2ary(crls);
}
static VALUE
@@ -644,36 +785,39 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
BIO *in, *out;
PKCS7 *p7;
VALUE data;
- const char *msg;
+ GetPKCS7(self, p7);
rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags);
+ x509st = GetX509StorePtr(store);
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self);
- in = NIL_P(indata) ? NULL : ossl_obj2bio(indata);
+ in = NIL_P(indata) ? NULL : ossl_obj2bio(&indata);
if(NIL_P(certs)) x509s = NULL;
else{
- x509s = ossl_protect_x509_ary2sk(certs, &status);
- if(status){
- BIO_free(in);
- rb_jump_tag(status);
- }
+ x509s = ossl_protect_x509_ary2sk(certs, &status);
+ if(status){
+ BIO_free(in);
+ rb_jump_tag(status);
+ }
}
- x509st = GetX509StorePtr(store);
- GetPKCS7(self, p7);
if(!(out = BIO_new(BIO_s_mem()))){
- BIO_free(in);
- sk_X509_pop_free(x509s, X509_free);
- ossl_raise(ePKCS7Error, NULL);
+ BIO_free(in);
+ sk_X509_pop_free(x509s, X509_free);
+ ossl_raise(ePKCS7Error, NULL);
}
ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);
BIO_free(in);
- msg = ERR_reason_error_string(ERR_get_error());
- ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
+ sk_X509_pop_free(x509s, X509_free);
data = ossl_membio2str(out);
ossl_pkcs7_set_data(self, data);
- sk_X509_pop_free(x509s, X509_free);
-
- return (ok == 1) ? Qtrue : Qfalse;
+ if (ok != 1) {
+ const char *msg = ERR_reason_error_string(ERR_peek_error());
+ ossl_pkcs7_set_err_string(self, msg ? rb_str_new_cstr(msg) : Qnil);
+ ossl_clear_error();
+ return Qfalse;
+ }
+ ossl_pkcs7_set_err_string(self, Qnil);
+ return Qtrue;
}
static VALUE
@@ -687,16 +831,16 @@ ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self)
BIO *out;
VALUE str;
- rb_scan_args(argc, argv, "21", &pkey, &cert, &flags);
+ rb_scan_args(argc, argv, "12", &pkey, &cert, &flags);
key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */
- x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
+ x509 = NIL_P(cert) ? NULL : GetX509CertPtr(cert); /* NO NEED TO DUP */
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
GetPKCS7(self, p7);
if(!(out = BIO_new(BIO_s_mem())))
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
if(!PKCS7_decrypt(p7, key, x509, out, flg)){
- BIO_free(out);
- ossl_raise(ePKCS7Error, NULL);
+ BIO_free(out);
+ ossl_raise(ePKCS7Error, NULL);
}
str = ossl_membio2str(out); /* out will be free */
@@ -709,30 +853,38 @@ ossl_pkcs7_add_data(VALUE self, VALUE data)
PKCS7 *pkcs7;
BIO *out, *in;
char buf[4096];
- int len;
+ int len, ret;
- in = ossl_obj2bio(data);
GetPKCS7(self, pkcs7);
- if(PKCS7_type_is_signed(pkcs7)){
- if(!PKCS7_content_new(pkcs7, NID_pkcs7_data))
- ossl_raise(ePKCS7Error, NULL);
- }
- if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err;
- for(;;){
- if((len = BIO_read(in, buf, sizeof(buf))) <= 0)
- break;
- if(BIO_write(out, buf, len) != len)
- goto err;
- }
- if(!PKCS7_dataFinal(pkcs7, out)) goto err;
- ossl_pkcs7_set_data(self, Qnil);
-
- err:
- BIO_free(out);
- BIO_free(in);
- if(ERR_peek_error()){
- ossl_raise(ePKCS7Error, NULL);
+ if (PKCS7_type_is_signed(pkcs7)) {
+ if (!PKCS7_content_new(pkcs7, NID_pkcs7_data))
+ ossl_raise(ePKCS7Error, "PKCS7_content_new");
}
+ in = ossl_obj2bio(&data);
+ if (!(out = PKCS7_dataInit(pkcs7, NULL))) {
+ BIO_free(in);
+ ossl_raise(ePKCS7Error, "PKCS7_dataInit");
+ }
+ for (;;) {
+ if ((len = BIO_read(in, buf, sizeof(buf))) <= 0)
+ break;
+ if (BIO_write(out, buf, len) != len) {
+ BIO_free_all(out);
+ BIO_free(in);
+ ossl_raise(ePKCS7Error, "BIO_write");
+ }
+ }
+ if (BIO_flush(out) <= 0) {
+ BIO_free_all(out);
+ BIO_free(in);
+ ossl_raise(ePKCS7Error, "BIO_flush");
+ }
+ ret = PKCS7_dataFinal(pkcs7, out);
+ BIO_free_all(out);
+ BIO_free(in);
+ if (!ret)
+ ossl_raise(ePKCS7Error, "PKCS7_dataFinal");
+ ossl_pkcs7_set_data(self, Qnil);
return data;
}
@@ -747,30 +899,49 @@ ossl_pkcs7_to_der(VALUE self)
GetPKCS7(self, pkcs7);
if((len = i2d_PKCS7(pkcs7, NULL)) <= 0)
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = (unsigned char *)RSTRING_PTR(str);
if(i2d_PKCS7(pkcs7, &p) <= 0)
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
ossl_str_adjust(str, p);
return str;
}
static VALUE
+ossl_pkcs7_to_text(VALUE self)
+{
+ PKCS7 *pkcs7;
+ BIO *out;
+ VALUE str;
+
+ GetPKCS7(self, pkcs7);
+ if(!(out = BIO_new(BIO_s_mem())))
+ ossl_raise(ePKCS7Error, NULL);
+ if(!PKCS7_print_ctx(out, pkcs7, 0, NULL)) {
+ BIO_free(out);
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+static VALUE
ossl_pkcs7_to_pem(VALUE self)
{
PKCS7 *pkcs7;
BIO *out;
VALUE str;
-
+
GetPKCS7(self, pkcs7);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
if (!PEM_write_bio_PKCS7(out, pkcs7)) {
- BIO_free(out);
- ossl_raise(ePKCS7Error, NULL);
+ BIO_free(out);
+ ossl_raise(ePKCS7Error, NULL);
}
str = ossl_membio2str(out);
@@ -786,10 +957,11 @@ ossl_pkcs7si_alloc(VALUE klass)
PKCS7_SIGNER_INFO *p7si;
VALUE obj;
+ obj = NewPKCS7si(klass);
if (!(p7si = PKCS7_SIGNER_INFO_new())) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
- WrapPKCS7si(klass, obj, p7si);
+ SetPKCS7si(obj, p7si);
return obj;
}
@@ -801,14 +973,15 @@ ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest)
EVP_PKEY *pkey;
X509 *x509;
const EVP_MD *md;
+ VALUE md_holder;
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
- md = GetDigestPtr(digest);
+ md = ossl_evp_md_fetch(digest, &md_holder);
GetPKCS7si(self, p7si);
- if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) {
- ossl_raise(ePKCS7Error, NULL);
- }
+ if (PKCS7_SIGNER_INFO_set(p7si, x509, pkey, md) <= 0)
+ ossl_raise(ePKCS7Error, "PKCS7_SIGNER_INFO_set");
+ rb_ivar_set(self, id_md_holder, md_holder);
return self;
}
@@ -837,15 +1010,15 @@ static VALUE
ossl_pkcs7si_get_signed_time(VALUE self)
{
PKCS7_SIGNER_INFO *p7si;
- ASN1_TYPE *asn1obj;
-
+ const ASN1_TYPE *asn1obj;
+
GetPKCS7si(self, p7si);
-
+
if (!(asn1obj = PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime))) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
if (asn1obj->type == V_ASN1_UTCTIME) {
- return asn1time_to_time(asn1obj->value.utctime);
+ return asn1time_to_time(asn1obj->value.utctime);
}
/*
* OR
@@ -865,10 +1038,11 @@ ossl_pkcs7ri_alloc(VALUE klass)
PKCS7_RECIP_INFO *p7ri;
VALUE obj;
+ obj = NewPKCS7ri(klass);
if (!(p7ri = PKCS7_RECIP_INFO_new())) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
- WrapPKCS7ri(klass, obj, p7ri);
+ SetPKCS7ri(obj, p7ri);
return obj;
}
@@ -881,8 +1055,8 @@ ossl_pkcs7ri_initialize(VALUE self, VALUE cert)
x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
GetPKCS7ri(self, p7ri);
- if (!PKCS7_RECIP_INFO_set(p7ri, x509)) {
- ossl_raise(ePKCS7Error, NULL);
+ if (PKCS7_RECIP_INFO_set(p7ri, x509) <= 0) {
+ ossl_raise(ePKCS7Error, NULL);
}
return self;
@@ -922,21 +1096,19 @@ ossl_pkcs7ri_get_enc_key(VALUE self)
* INIT
*/
void
-Init_ossl_pkcs7()
+Init_ossl_pkcs7(void)
{
- mPKCS7 = rb_define_module_under(mOSSL, "PKCS7");
-
- ePKCS7Error = rb_define_class_under(mPKCS7, "PKCS7Error", eOSSLError);
-
- cPKCS7 = rb_define_class_under(mPKCS7, "PKCS7", rb_cObject);
- rb_define_singleton_method(mPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
- rb_define_singleton_method(mPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1);
- rb_define_singleton_method(mPKCS7, "sign", ossl_pkcs7_s_sign, -1);
- rb_define_singleton_method(mPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1);
+#undef rb_intern
+ cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject);
+ ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError);
+ rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
+ rb_define_singleton_method(cPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1);
+ rb_define_singleton_method(cPKCS7, "sign", ossl_pkcs7_s_sign, -1);
+ rb_define_singleton_method(cPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1);
rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse);
rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse);
rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc);
- rb_define_copy_func(cPKCS7, ossl_pkcs7_copy);
+ rb_define_method(cPKCS7, "initialize_copy", ossl_pkcs7_copy, 1);
rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1);
rb_define_method(cPKCS7, "type=", ossl_pkcs7_set_type, 1);
rb_define_method(cPKCS7, "type", ossl_pkcs7_get_type, 0);
@@ -961,24 +1133,24 @@ Init_ossl_pkcs7()
rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0);
rb_define_alias(cPKCS7, "to_s", "to_pem");
rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0);
+ rb_define_method(cPKCS7, "to_text", ossl_pkcs7_to_text, 0);
- cPKCS7Signer = rb_define_class_under(mPKCS7, "SignerInfo", rb_cObject);
- rb_define_const(mPKCS7, "Signer", cPKCS7Signer);
+ cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject);
+ rb_define_const(cPKCS7, "Signer", cPKCS7Signer);
rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc);
rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3);
rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0);
- rb_define_alias(cPKCS7Signer, "name", "issuer");
rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0);
rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0);
- cPKCS7Recipient = rb_define_class_under(mPKCS7,"RecipientInfo",rb_cObject);
+ cPKCS7Recipient = rb_define_class_under(cPKCS7,"RecipientInfo",rb_cObject);
rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc);
- rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1);
+ rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1);
rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0);
rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0);
- rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0);
+ rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0);
-#define DefPKCS7Const(x) rb_define_const(mPKCS7, #x, INT2NUM(PKCS7_##x))
+#define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x))
DefPKCS7Const(TEXT);
DefPKCS7Const(NOCERTS);
@@ -990,4 +1162,7 @@ Init_ossl_pkcs7()
DefPKCS7Const(BINARY);
DefPKCS7Const(NOATTR);
DefPKCS7Const(NOSMIMECAP);
+
+ id_md_holder = rb_intern_const("EVP_MD_holder");
+ id_cipher_holder = rb_intern_const("EVP_CIPHER_holder");
}
diff --git a/ext/openssl/ossl_pkcs7.h b/ext/openssl/ossl_pkcs7.h
index f5942d65db..140fda1835 100644
--- a/ext/openssl/ossl_pkcs7.h
+++ b/ext/openssl/ossl_pkcs7.h
@@ -1,23 +1,16 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_PKCS7_H_)
#define _OSSL_PKCS7_H_
-extern VALUE mPKCS7;
-extern VALUE cPKCS7;
-extern VALUE cPKCS7Signer;
-extern VALUE cPKCS7Recipient;
-extern VALUE ePKCS7Error;
-
+VALUE ossl_pkcs7_new(PKCS7 *p7);
void Init_ossl_pkcs7(void);
#endif /* _OSSL_PKCS7_H_ */
-
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index db70333047..a53332b17e 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -1,84 +1,552 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
+#ifdef OSSL_USE_ENGINE
+# include <openssl/engine.h>
+#endif
+
/*
* Classes
*/
VALUE mPKey;
VALUE cPKey;
VALUE ePKeyError;
-ID id_private_q;
+static ID id_private_q;
-/*
- * callback for generating keys
- */
-void
-ossl_generate_cb(int p, int n, void *arg)
+static void
+ossl_evp_pkey_free(void *ptr)
{
- VALUE ary;
-
- ary = rb_ary_new2(2);
- rb_ary_store(ary, 0, INT2NUM(p));
- rb_ary_store(ary, 1, INT2NUM(n));
-
- rb_yield(ary);
+ EVP_PKEY_free(ptr);
}
/*
* Public
*/
-VALUE
-ossl_pkey_new(EVP_PKEY *pkey)
+const rb_data_type_t ossl_evp_pkey_type = {
+ "OpenSSL/EVP_PKEY",
+ {
+ 0, ossl_evp_pkey_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static VALUE
+pkey_wrap0(VALUE arg)
{
- if (!pkey) {
- ossl_raise(ePKeyError, "Cannot make new key from NULL.");
- }
- switch (EVP_PKEY_type(pkey->type)) {
+ EVP_PKEY *pkey = (EVP_PKEY *)arg;
+ VALUE klass, obj;
+
+ switch (EVP_PKEY_base_id(pkey)) {
#if !defined(OPENSSL_NO_RSA)
- case EVP_PKEY_RSA:
- return ossl_rsa_new(pkey);
+ case EVP_PKEY_RSA: klass = cRSA; break;
#endif
#if !defined(OPENSSL_NO_DSA)
- case EVP_PKEY_DSA:
- return ossl_dsa_new(pkey);
+ case EVP_PKEY_DSA: klass = cDSA; break;
#endif
#if !defined(OPENSSL_NO_DH)
- case EVP_PKEY_DH:
- return ossl_dh_new(pkey);
+ case EVP_PKEY_DH: klass = cDH; break;
+#endif
+#if !defined(OPENSSL_NO_EC)
+ case EVP_PKEY_EC: klass = cEC; break;
#endif
- default:
- ossl_raise(ePKeyError, "unsupported key type");
+ default: klass = cPKey; break;
}
- return Qnil; /* not reached */
+ obj = rb_obj_alloc(klass);
+ RTYPEDDATA_DATA(obj) = pkey;
+ return obj;
}
VALUE
-ossl_pkey_new_from_file(VALUE filename)
+ossl_pkey_wrap(EVP_PKEY *pkey)
+{
+ VALUE obj;
+ int status;
+
+ obj = rb_protect(pkey_wrap0, (VALUE)pkey, &status);
+ if (status) {
+ EVP_PKEY_free(pkey);
+ rb_jump_tag(status);
+ }
+
+ return obj;
+}
+
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+# include <openssl/decoder.h>
+
+static EVP_PKEY *
+ossl_pkey_read(BIO *bio, const char *input_type, int selection, VALUE pass)
+{
+ void *ppass = (void *)pass;
+ OSSL_DECODER_CTX *dctx;
+ EVP_PKEY *pkey = NULL;
+ int pos = 0, pos2;
+
+ dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, input_type, NULL, NULL,
+ selection, NULL, NULL);
+ if (!dctx)
+ goto out;
+ if (selection == EVP_PKEY_KEYPAIR &&
+ OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb,
+ ppass) != 1)
+ goto out;
+ while (1) {
+ if (OSSL_DECODER_from_bio(dctx, bio) == 1)
+ goto out;
+ if (BIO_eof(bio))
+ break;
+ pos2 = BIO_tell(bio);
+ if (pos2 < 0 || pos2 <= pos)
+ break;
+ ossl_clear_error();
+ pos = pos2;
+ }
+ out:
+ OSSL_BIO_reset(bio);
+ OSSL_DECODER_CTX_free(dctx);
+ return pkey;
+}
+
+EVP_PKEY *
+ossl_pkey_read_generic(BIO *bio, VALUE pass)
+{
+ EVP_PKEY *pkey = NULL;
+ /* First check DER, then check PEM. */
+ const char *input_types[] = {"DER", "PEM"};
+ int input_type_num = (int)(sizeof(input_types) / sizeof(char *));
+ /*
+ * Non-zero selections to try to decode.
+ *
+ * See EVP_PKEY_fromdata(3) - Selections to see all the selections.
+ *
+ * This is a workaround for the decoder failing to decode or returning
+ * bogus keys with selection 0, if a key management provider is different
+ * from a decoder provider. The workaround is to avoid using selection 0.
+ *
+ * Affected OpenSSL versions: >= 3.1.0, <= 3.1.2, or >= 3.0.0, <= 3.0.10
+ * Fixed OpenSSL versions: 3.2, next release of the 3.1.z and 3.0.z
+ *
+ * See https://github.com/openssl/openssl/pull/21519 for details.
+ *
+ * First check for private key formats (EVP_PKEY_KEYPAIR). This is to keep
+ * compatibility with ruby/openssl < 3.0 which decoded the following as a
+ * private key.
+ *
+ * $ openssl ecparam -name prime256v1 -genkey -outform PEM
+ * -----BEGIN EC PARAMETERS-----
+ * BggqhkjOPQMBBw==
+ * -----END EC PARAMETERS-----
+ * -----BEGIN EC PRIVATE KEY-----
+ * MHcCAQEEIAG8ugBbA5MHkqnZ9ujQF93OyUfL9tk8sxqM5Wv5tKg5oAoGCCqGSM49
+ * AwEHoUQDQgAEVcjhJfkwqh5C7kGuhAf8XaAjVuG5ADwb5ayg/cJijCgs+GcXeedj
+ * 86avKpGH84DXUlB23C/kPt+6fXYlitUmXQ==
+ * -----END EC PRIVATE KEY-----
+ *
+ * While the first PEM block is a proper encoding of ECParameters, thus
+ * OSSL_DECODER_from_bio() would pick it up, ruby/openssl used to return
+ * the latter instead. Existing applications expect this behavior.
+ *
+ * Note that normally, the input is supposed to contain a single decodable
+ * PEM block only, so this special handling should not create a new problem.
+ *
+ * Note that we need to create the OSSL_DECODER_CTX variable each time when
+ * we use the different selection as a workaround.
+ * See https://github.com/openssl/openssl/issues/20657 for details.
+ */
+ int selections[] = {
+ EVP_PKEY_KEYPAIR,
+ EVP_PKEY_KEY_PARAMETERS,
+ EVP_PKEY_PUBLIC_KEY
+ };
+ int selection_num = (int)(sizeof(selections) / sizeof(int));
+ int i, j;
+
+ for (i = 0; i < input_type_num; i++) {
+ for (j = 0; j < selection_num; j++) {
+ pkey = ossl_pkey_read(bio, input_types[i], selections[j], pass);
+ if (pkey) {
+ goto out;
+ }
+ }
+ }
+ out:
+ return pkey;
+}
+#else
+EVP_PKEY *
+ossl_pkey_read_generic(BIO *bio, VALUE pass)
+{
+ void *ppass = (void *)pass;
+ EVP_PKEY *pkey;
+
+ if ((pkey = d2i_PrivateKey_bio(bio, NULL)))
+ goto out;
+ OSSL_BIO_reset(bio);
+ if ((pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, ossl_pem_passwd_cb, ppass)))
+ goto out;
+ OSSL_BIO_reset(bio);
+ if ((pkey = d2i_PUBKEY_bio(bio, NULL)))
+ goto out;
+ OSSL_BIO_reset(bio);
+ /* PEM_read_bio_PrivateKey() also parses PKCS #8 formats */
+ if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, ppass)))
+ goto out;
+ OSSL_BIO_reset(bio);
+ if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)))
+ goto out;
+ OSSL_BIO_reset(bio);
+ if ((pkey = PEM_read_bio_Parameters(bio, NULL)))
+ goto out;
+
+ out:
+ return pkey;
+}
+#endif
+
+/*
+ * call-seq:
+ * OpenSSL::PKey.read(string [, pwd ]) -> PKey
+ * OpenSSL::PKey.read(io [, pwd ]) -> PKey
+ *
+ * Reads a DER or PEM encoded string from _string_ or _io_ and returns an
+ * instance of the appropriate PKey class.
+ *
+ * === Parameters
+ * * _string_ is a DER- or PEM-encoded string containing an arbitrary private
+ * or public key.
+ * * _io_ is an instance of IO containing a DER- or PEM-encoded
+ * arbitrary private or public key.
+ * * _pwd_ is an optional password in case _string_ or _io_ is an encrypted
+ * PEM resource.
+ */
+static VALUE
+ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ BIO *bio;
+ VALUE data, pass;
+
+ rb_scan_args(argc, argv, "11", &data, &pass);
+ bio = ossl_obj2bio(&data);
+ pkey = ossl_pkey_read_generic(bio, ossl_pem_passwd_value(pass));
+ BIO_free(bio);
+ if (!pkey)
+ ossl_raise(ePKeyError, "Could not parse PKey");
+ return ossl_pkey_wrap(pkey);
+}
+
+static VALUE
+pkey_ctx_apply_options_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ctx_v))
{
- FILE *fp;
+ VALUE key = rb_ary_entry(i, 0), value = rb_ary_entry(i, 1);
+ EVP_PKEY_CTX *ctx = (EVP_PKEY_CTX *)ctx_v;
+
+ if (SYMBOL_P(key))
+ key = rb_sym2str(key);
+ value = rb_String(value);
+
+ if (EVP_PKEY_CTX_ctrl_str(ctx, StringValueCStr(key), StringValueCStr(value)) <= 0)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_ctrl_str(ctx, %+"PRIsVALUE", %+"PRIsVALUE")",
+ key, value);
+ return Qnil;
+}
+
+static VALUE
+pkey_ctx_apply_options0(VALUE args_v)
+{
+ VALUE *args = (VALUE *)args_v;
+ Check_Type(args[1], T_HASH);
+
+ rb_block_call(args[1], rb_intern("each"), 0, NULL,
+ pkey_ctx_apply_options_i, args[0]);
+ return Qnil;
+}
+
+static void
+pkey_ctx_apply_options(EVP_PKEY_CTX *ctx, VALUE options, int *state)
+{
+ VALUE args[2];
+ args[0] = (VALUE)ctx;
+ args[1] = options;
+
+ rb_protect(pkey_ctx_apply_options0, (VALUE)args, state);
+}
+
+struct pkey_blocking_generate_arg {
+ EVP_PKEY_CTX *ctx;
EVP_PKEY *pkey;
+ int state;
+ unsigned int yield: 1;
+ unsigned int genparam: 1;
+ unsigned int interrupted: 1;
+};
+
+static VALUE
+pkey_gen_cb_yield(VALUE ctx_v)
+{
+ EVP_PKEY_CTX *ctx = (void *)ctx_v;
+ int i, info_num;
+ VALUE *argv;
+
+ info_num = EVP_PKEY_CTX_get_keygen_info(ctx, -1);
+ argv = ALLOCA_N(VALUE, info_num);
+ for (i = 0; i < info_num; i++)
+ argv[i] = INT2NUM(EVP_PKEY_CTX_get_keygen_info(ctx, i));
+
+ return rb_yield_values2(info_num, argv);
+}
+
+static VALUE
+call_check_ints0(VALUE arg)
+{
+ rb_thread_check_ints();
+ return Qnil;
+}
+
+static void *
+call_check_ints(void *arg)
+{
+ int state;
+ rb_protect(call_check_ints0, Qnil, &state);
+ return (void *)(VALUE)state;
+}
+
+static int
+pkey_gen_cb(EVP_PKEY_CTX *ctx)
+{
+ struct pkey_blocking_generate_arg *arg = EVP_PKEY_CTX_get_app_data(ctx);
+ int state;
- SafeStringValue(filename);
- if (!(fp = fopen(RSTRING(filename)->ptr, "r"))) {
- ossl_raise(ePKeyError, "%s", strerror(errno));
+ if (arg->yield) {
+ rb_protect(pkey_gen_cb_yield, (VALUE)ctx, &state);
+ if (state) {
+ arg->state = state;
+ return 0;
+ }
}
+ if (arg->interrupted) {
+ arg->interrupted = 0;
+ state = (int)(VALUE)rb_thread_call_with_gvl(call_check_ints, NULL);
+ if (state) {
+ arg->state = state;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void
+pkey_blocking_gen_stop(void *ptr)
+{
+ struct pkey_blocking_generate_arg *arg = ptr;
+ arg->interrupted = 1;
+}
+
+static void *
+pkey_blocking_gen(void *ptr)
+{
+ struct pkey_blocking_generate_arg *arg = ptr;
- pkey = PEM_read_PrivateKey(fp, NULL, ossl_pem_passwd_cb, NULL);
- fclose(fp);
- if (!pkey) {
- ossl_raise(ePKeyError, NULL);
+ if (arg->genparam && EVP_PKEY_paramgen(arg->ctx, &arg->pkey) <= 0)
+ return NULL;
+ if (!arg->genparam && EVP_PKEY_keygen(arg->ctx, &arg->pkey) <= 0)
+ return NULL;
+ return arg->pkey;
+}
+
+static VALUE
+pkey_generate(int argc, VALUE *argv, VALUE self, int genparam)
+{
+ EVP_PKEY_CTX *ctx;
+ VALUE alg, options;
+ struct pkey_blocking_generate_arg gen_arg = { 0 };
+ int state;
+
+ rb_scan_args(argc, argv, "11", &alg, &options);
+ if (rb_obj_is_kind_of(alg, cPKey)) {
+ EVP_PKEY *base_pkey;
+
+ GetPKey(alg, base_pkey);
+ ctx = EVP_PKEY_CTX_new(base_pkey, NULL/* engine */);
+ if (!ctx)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
}
+ else {
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, StringValueCStr(alg), NULL);
+ if (!ctx)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_from_name");
+#else
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ ENGINE *tmpeng;
+ int pkey_id;
- return ossl_pkey_new(pkey);
+ StringValue(alg);
+ ameth = EVP_PKEY_asn1_find_str(&tmpeng, RSTRING_PTR(alg),
+ RSTRING_LENINT(alg));
+ if (!ameth)
+ ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", alg);
+ EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
+#if !defined(OPENSSL_NO_ENGINE)
+ if (tmpeng)
+ ENGINE_finish(tmpeng);
+#endif
+
+ ctx = EVP_PKEY_CTX_new_id(pkey_id, NULL/* engine */);
+ if (!ctx)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_id");
+#endif
+ }
+
+ if (genparam && EVP_PKEY_paramgen_init(ctx) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_paramgen_init");
+ }
+ if (!genparam && EVP_PKEY_keygen_init(ctx) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_keygen_init");
+ }
+
+ if (!NIL_P(options)) {
+ pkey_ctx_apply_options(ctx, options, &state);
+ if (state) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ }
+
+ gen_arg.genparam = genparam;
+ gen_arg.ctx = ctx;
+ gen_arg.yield = rb_block_given_p();
+ EVP_PKEY_CTX_set_app_data(ctx, &gen_arg);
+ EVP_PKEY_CTX_set_cb(ctx, pkey_gen_cb);
+ if (gen_arg.yield)
+ pkey_blocking_gen(&gen_arg);
+ else
+ rb_thread_call_without_gvl(pkey_blocking_gen, &gen_arg,
+ pkey_blocking_gen_stop, &gen_arg);
+ EVP_PKEY_CTX_free(ctx);
+ if (!gen_arg.pkey) {
+ if (gen_arg.state) {
+ ossl_clear_error();
+ rb_jump_tag(gen_arg.state);
+ }
+ else {
+ ossl_raise(ePKeyError, genparam ? "EVP_PKEY_paramgen" : "EVP_PKEY_keygen");
+ }
+ }
+
+ return ossl_pkey_wrap(gen_arg.pkey);
+}
+
+/*
+ * call-seq:
+ * OpenSSL::PKey.generate_parameters(algo_name [, options]) -> pkey
+ *
+ * Generates new parameters for the algorithm. _algo_name_ is a String that
+ * represents the algorithm. The optional argument _options_ is a Hash that
+ * specifies the options specific to the algorithm. The order of the options
+ * can be important.
+ *
+ * A block can be passed optionally. The meaning of the arguments passed to
+ * the block varies depending on the implementation of the algorithm. The block
+ * may be called once or multiple times, or may not even be called.
+ *
+ * For the supported options, see the documentation for the 'openssl genpkey'
+ * utility command.
+ *
+ * == Example
+ * pkey = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048)
+ * p pkey.p.num_bits #=> 2048
+ */
+static VALUE
+ossl_pkey_s_generate_parameters(int argc, VALUE *argv, VALUE self)
+{
+ return pkey_generate(argc, argv, self, 1);
+}
+
+/*
+ * call-seq:
+ * OpenSSL::PKey.generate_key(algo_name [, options]) -> pkey
+ * OpenSSL::PKey.generate_key(pkey [, options]) -> pkey
+ *
+ * Generates a new key (pair).
+ *
+ * If a String is given as the first argument, it generates a new random key
+ * for the algorithm specified by the name just as ::generate_parameters does.
+ * If an OpenSSL::PKey::PKey is given instead, it generates a new random key
+ * for the same algorithm as the key, using the parameters the key contains.
+ *
+ * See ::generate_parameters for the details of _options_ and the given block.
+ *
+ * == Example
+ * pkey_params = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048)
+ * pkey_params.priv_key #=> nil
+ * pkey = OpenSSL::PKey.generate_key(pkey_params)
+ * pkey.priv_key #=> #<OpenSSL::BN 6277...
+ */
+static VALUE
+ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self)
+{
+ return pkey_generate(argc, argv, self, 0);
+}
+
+/*
+ * TODO: There is no convenient way to check the presence of public key
+ * components on OpenSSL 3.0. But since keys are immutable on 3.0, pkeys without
+ * these should only be created by OpenSSL::PKey.generate_parameters or by
+ * parsing DER-/PEM-encoded string. We would need another flag for that.
+ */
+void
+ossl_pkey_check_public_key(const EVP_PKEY *pkey)
+{
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ if (EVP_PKEY_missing_parameters(pkey))
+ ossl_raise(ePKeyError, "parameters missing");
+#else
+ void *ptr;
+ const BIGNUM *n, *e, *pubkey;
+
+ if (EVP_PKEY_missing_parameters(pkey))
+ ossl_raise(ePKeyError, "parameters missing");
+
+ ptr = EVP_PKEY_get0(pkey);
+ switch (EVP_PKEY_base_id(pkey)) {
+ case EVP_PKEY_RSA:
+ RSA_get0_key(ptr, &n, &e, NULL);
+ if (n && e)
+ return;
+ break;
+ case EVP_PKEY_DSA:
+ DSA_get0_key(ptr, &pubkey, NULL);
+ if (pubkey)
+ return;
+ break;
+ case EVP_PKEY_DH:
+ DH_get0_key(ptr, &pubkey, NULL);
+ if (pubkey)
+ return;
+ break;
+#if !defined(OPENSSL_NO_EC)
+ case EVP_PKEY_EC:
+ if (EC_KEY_get0_public_key(ptr))
+ return;
+ break;
+#endif
+ default:
+ /* unsupported type; assuming ok */
+ return;
+ }
+ ossl_raise(ePKeyError, "public key missing");
+#endif
}
EVP_PKEY *
@@ -86,7 +554,7 @@ GetPKeyPtr(VALUE obj)
{
EVP_PKEY *pkey;
- SafeGetPKey(obj, pkey);
+ GetPKey(obj, pkey);
return pkey;
}
@@ -95,13 +563,20 @@ EVP_PKEY *
GetPrivPKeyPtr(VALUE obj)
{
EVP_PKEY *pkey;
-
- if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) {
- ossl_raise(rb_eArgError, "Private key is needed.");
- }
- SafeGetPKey(obj, pkey);
- return pkey;
+ GetPKey(obj, pkey);
+ if (OSSL_PKEY_IS_PRIVATE(obj))
+ return pkey;
+ /*
+ * The EVP API does not provide a way to check if the EVP_PKEY has private
+ * components. Assuming it does...
+ */
+ if (!rb_respond_to(obj, id_private_q))
+ return pkey;
+ if (RTEST(rb_funcallv(obj, id_private_q, 0, NULL)))
+ return pkey;
+
+ rb_raise(rb_eArgError, "private key is needed");
}
EVP_PKEY *
@@ -109,124 +584,1201 @@ DupPKeyPtr(VALUE obj)
{
EVP_PKEY *pkey;
- SafeGetPKey(obj, pkey);
- CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+ GetPKey(obj, pkey);
+ EVP_PKEY_up_ref(pkey);
return pkey;
}
-EVP_PKEY *
-DupPrivPKeyPtr(VALUE obj)
+/*
+ * Private
+ */
+static VALUE
+ossl_pkey_alloc(VALUE klass)
{
- EVP_PKEY *pkey;
-
- if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) {
- ossl_raise(rb_eArgError, "Private key is needed.");
+ return TypedData_Wrap_Struct(klass, &ossl_evp_pkey_type, NULL);
+}
+
+/*
+ * call-seq:
+ * PKeyClass.new -> self
+ *
+ * Because PKey is an abstract class, actually calling this method explicitly
+ * will raise a NotImplementedError.
+ */
+static VALUE
+ossl_pkey_initialize(VALUE self)
+{
+ if (rb_obj_is_instance_of(self, cPKey)) {
+ ossl_raise(rb_eTypeError, "OpenSSL::PKey::PKey can't be instantiated directly");
}
- SafeGetPKey(obj, pkey);
- CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+ return self;
+}
- return pkey;
+#ifdef HAVE_EVP_PKEY_DUP
+/* :nodoc: */
+static VALUE
+ossl_pkey_initialize_copy(VALUE self, VALUE other)
+{
+ EVP_PKEY *pkey, *pkey_other;
+
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ TypedData_Get_Struct(other, EVP_PKEY, &ossl_evp_pkey_type, pkey_other);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
+ if (pkey_other) {
+ pkey = EVP_PKEY_dup(pkey_other);
+ if (!pkey)
+ ossl_raise(ePKeyError, "EVP_PKEY_dup");
+ RTYPEDDATA_DATA(self) = pkey;
+ }
+ return self;
}
+#endif
+
+#ifndef OSSL_USE_PROVIDER
+static int
+lookup_pkey_type(VALUE type)
+{
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ int pkey_id;
+
+ StringValue(type);
+ /*
+ * XXX: EVP_PKEY_asn1_find_str() looks up a PEM type string. Should we use
+ * OBJ_txt2nid() instead (and then somehow check if the NID is an acceptable
+ * EVP_PKEY type)?
+ * It is probably fine, though, since it can handle all algorithms that
+ * support raw keys in 1.1.1: { X25519, X448, ED25519, ED448, HMAC }.
+ */
+ ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type));
+ if (!ameth)
+ ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type);
+ EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
+ return pkey_id;
+}
+#endif
/*
- * Private
+ * call-seq:
+ * OpenSSL::PKey.new_raw_private_key(algo, string) -> PKey
+ *
+ * See the OpenSSL documentation for EVP_PKEY_new_raw_private_key()
*/
+
static VALUE
-ossl_pkey_alloc(VALUE klass)
+ossl_pkey_new_raw_private_key(VALUE self, VALUE type, VALUE key)
{
EVP_PKEY *pkey;
- VALUE obj;
+ size_t keylen;
+
+ StringValue(key);
+ keylen = RSTRING_LEN(key);
+
+#ifdef OSSL_USE_PROVIDER
+ pkey = EVP_PKEY_new_raw_private_key_ex(NULL, StringValueCStr(type), NULL,
+ (unsigned char *)RSTRING_PTR(key),
+ keylen);
+ if (!pkey)
+ ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key_ex");
+#else
+ int pkey_id = lookup_pkey_type(type);
+ pkey = EVP_PKEY_new_raw_private_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
+ if (!pkey)
+ ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key");
+#endif
+
+ return ossl_pkey_wrap(pkey);
+}
+
+/*
+ * call-seq:
+ * OpenSSL::PKey.new_raw_public_key(algo, string) -> PKey
+ *
+ * See the OpenSSL documentation for EVP_PKEY_new_raw_public_key()
+ */
+
+static VALUE
+ossl_pkey_new_raw_public_key(VALUE self, VALUE type, VALUE key)
+{
+ EVP_PKEY *pkey;
+ size_t keylen;
+
+ StringValue(key);
+ keylen = RSTRING_LEN(key);
+
+#ifdef OSSL_USE_PROVIDER
+ pkey = EVP_PKEY_new_raw_public_key_ex(NULL, StringValueCStr(type), NULL,
+ (unsigned char *)RSTRING_PTR(key),
+ keylen);
+ if (!pkey)
+ ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key_ex");
+#else
+ int pkey_id = lookup_pkey_type(type);
+ pkey = EVP_PKEY_new_raw_public_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
+ if (!pkey)
+ ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key");
+#endif
+
+ return ossl_pkey_wrap(pkey);
+}
+
+/*
+ * call-seq:
+ * pkey.oid -> string
+ *
+ * Returns the short name of the OID associated with _pkey_.
+ */
+static VALUE
+ossl_pkey_oid(VALUE self)
+{
+ EVP_PKEY *pkey;
+ int nid;
+
+ GetPKey(self, pkey);
+ nid = EVP_PKEY_id(pkey);
+#ifdef OSSL_USE_PROVIDER
+ if (nid == EVP_PKEY_KEYMGMT)
+ ossl_raise(ePKeyError, "EVP_PKEY_id");
+#endif
+ return rb_str_new_cstr(OBJ_nid2sn(nid));
+}
+
+/*
+ * call-seq:
+ * pkey.inspect -> string
+ *
+ * Returns a string describing the PKey object.
+ */
+static VALUE
+ossl_pkey_inspect(VALUE self)
+{
+ EVP_PKEY *pkey;
+
+ GetPKey(self, pkey);
+ VALUE str = rb_sprintf("#<%"PRIsVALUE":%p",
+ rb_obj_class(self), (void *)self);
+ int nid = EVP_PKEY_id(pkey);
+#ifdef OSSL_USE_PROVIDER
+ if (nid != EVP_PKEY_KEYMGMT)
+#endif
+ rb_str_catf(str, " oid=%s", OBJ_nid2sn(nid));
+#ifdef OSSL_USE_PROVIDER
+ rb_str_catf(str, " type_name=%s", EVP_PKEY_get0_type_name(pkey));
+ const OSSL_PROVIDER *prov = EVP_PKEY_get0_provider(pkey);
+ if (prov)
+ rb_str_catf(str, " provider=%s", OSSL_PROVIDER_get0_name(prov));
+#endif
+ rb_str_catf(str, ">");
+ return str;
+}
+
+/*
+ * call-seq:
+ * pkey.to_text -> string
+ *
+ * Dumps key parameters, public key, and private key components contained in
+ * the key into a human-readable text.
+ *
+ * This is intended for debugging purpose.
+ *
+ * See also the man page EVP_PKEY_print_private(3).
+ */
+static VALUE
+ossl_pkey_to_text(VALUE self)
+{
+ EVP_PKEY *pkey;
+ BIO *bio;
+
+ GetPKey(self, pkey);
+ if (!(bio = BIO_new(BIO_s_mem())))
+ ossl_raise(ePKeyError, "BIO_new");
+
+ if (EVP_PKEY_print_private(bio, pkey, 0, NULL) == 1)
+ goto out;
+ OSSL_BIO_reset(bio);
+ if (EVP_PKEY_print_public(bio, pkey, 0, NULL) == 1)
+ goto out;
+ OSSL_BIO_reset(bio);
+ if (EVP_PKEY_print_params(bio, pkey, 0, NULL) == 1)
+ goto out;
- if (!(pkey = EVP_PKEY_new())) {
- ossl_raise(ePKeyError, NULL);
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "EVP_PKEY_print_params");
+
+ out:
+ return ossl_membio2str(bio);
+}
+
+VALUE
+ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der)
+{
+ EVP_PKEY *pkey;
+ VALUE cipher, pass, cipher_holder;
+ const EVP_CIPHER *enc = NULL;
+ BIO *bio;
+
+ GetPKey(self, pkey);
+ rb_scan_args(argc, argv, "02", &cipher, &pass);
+ if (!NIL_P(cipher)) {
+ enc = ossl_evp_cipher_fetch(cipher, &cipher_holder);
+ pass = ossl_pem_passwd_value(pass);
}
- WrapPKey(klass, obj, pkey);
- return obj;
+ bio = BIO_new(BIO_s_mem());
+ if (!bio)
+ ossl_raise(ePKeyError, "BIO_new");
+ if (to_der) {
+ if (!i2d_PrivateKey_bio(bio, pkey)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "i2d_PrivateKey_bio");
+ }
+ }
+ else {
+ if (!PEM_write_bio_PrivateKey_traditional(bio, pkey, enc, NULL, 0,
+ ossl_pem_passwd_cb,
+ (void *)pass)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "PEM_write_bio_PrivateKey_traditional");
+ }
+ }
+ return ossl_membio2str(bio);
}
static VALUE
-ossl_pkey_initialize(VALUE self)
+do_pkcs8_export(int argc, VALUE *argv, VALUE self, int to_der)
{
- if (rb_obj_is_instance_of(self, cPKey)) {
- ossl_raise(rb_eNotImpError, "OpenSSL::PKey::PKey is an abstract class.");
+ EVP_PKEY *pkey;
+ VALUE cipher, pass, cipher_holder;
+ const EVP_CIPHER *enc = NULL;
+ BIO *bio;
+
+ GetPKey(self, pkey);
+ rb_scan_args(argc, argv, "02", &cipher, &pass);
+ if (argc > 0) {
+ /*
+ * TODO: EncryptedPrivateKeyInfo actually has more options.
+ * Should they be exposed?
+ */
+ enc = ossl_evp_cipher_fetch(cipher, &cipher_holder);
+ pass = ossl_pem_passwd_value(pass);
}
- return self;
+
+ bio = BIO_new(BIO_s_mem());
+ if (!bio)
+ ossl_raise(ePKeyError, "BIO_new");
+ if (to_der) {
+ if (!i2d_PKCS8PrivateKey_bio(bio, pkey, enc, NULL, 0,
+ ossl_pem_passwd_cb, (void *)pass)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "i2d_PKCS8PrivateKey_bio");
+ }
+ }
+ else {
+ if (!PEM_write_bio_PKCS8PrivateKey(bio, pkey, enc, NULL, 0,
+ ossl_pem_passwd_cb, (void *)pass)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "PEM_write_bio_PKCS8PrivateKey");
+ }
+ }
+ return ossl_membio2str(bio);
+}
+
+/*
+ * call-seq:
+ * pkey.private_to_der -> string
+ * pkey.private_to_der(cipher, password) -> string
+ *
+ * Serializes the private key to DER-encoded PKCS #8 format. If called without
+ * arguments, unencrypted PKCS #8 PrivateKeyInfo format is used. If called with
+ * a cipher name and a password, PKCS #8 EncryptedPrivateKeyInfo format with
+ * PBES2 encryption scheme is used.
+ */
+static VALUE
+ossl_pkey_private_to_der(int argc, VALUE *argv, VALUE self)
+{
+ return do_pkcs8_export(argc, argv, self, 1);
}
+/*
+ * call-seq:
+ * pkey.private_to_pem -> string
+ * pkey.private_to_pem(cipher, password) -> string
+ *
+ * Serializes the private key to PEM-encoded PKCS #8 format. See #private_to_der
+ * for more details.
+ *
+ * An unencrypted PEM-encoded key will look like:
+ *
+ * -----BEGIN PRIVATE KEY-----
+ * [...]
+ * -----END PRIVATE KEY-----
+ *
+ * An encrypted PEM-encoded key will look like:
+ *
+ * -----BEGIN ENCRYPTED PRIVATE KEY-----
+ * [...]
+ * -----END ENCRYPTED PRIVATE KEY-----
+ */
static VALUE
-ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
+ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self)
+{
+ return do_pkcs8_export(argc, argv, self, 0);
+}
+
+/*
+ * call-seq:
+ * pkey.raw_private_key => string
+ *
+ * See the OpenSSL documentation for EVP_PKEY_get_raw_private_key()
+ */
+
+static VALUE
+ossl_pkey_raw_private_key(VALUE self)
{
EVP_PKEY *pkey;
- EVP_MD_CTX ctx;
- int buf_len;
VALUE str;
+ size_t len;
+
+ GetPKey(self, pkey);
+ if (EVP_PKEY_get_raw_private_key(pkey, NULL, &len) != 1)
+ ossl_raise(ePKeyError, "EVP_PKEY_get_raw_private_key");
+ str = rb_str_new(NULL, len);
+
+ if (EVP_PKEY_get_raw_private_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1)
+ ossl_raise(ePKeyError, "EVP_PKEY_get_raw_private_key");
+
+ rb_str_set_len(str, len);
+
+ return str;
+}
- if (rb_funcall(self, id_private_q, 0, NULL) != Qtrue) {
- ossl_raise(rb_eArgError, "Private key is needed.");
+VALUE
+ossl_pkey_export_spki(VALUE self, int to_der)
+{
+ EVP_PKEY *pkey;
+ BIO *bio;
+
+ GetPKey(self, pkey);
+ ossl_pkey_check_public_key(pkey);
+ bio = BIO_new(BIO_s_mem());
+ if (!bio)
+ ossl_raise(ePKeyError, "BIO_new");
+ if (to_der) {
+ if (!i2d_PUBKEY_bio(bio, pkey)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "i2d_PUBKEY_bio");
+ }
+ }
+ else {
+ if (!PEM_write_bio_PUBKEY(bio, pkey)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "PEM_write_bio_PUBKEY");
+ }
}
+ return ossl_membio2str(bio);
+}
+
+/*
+ * call-seq:
+ * pkey.public_to_der -> string
+ *
+ * Serializes the public key to DER-encoded X.509 SubjectPublicKeyInfo format.
+ */
+static VALUE
+ossl_pkey_public_to_der(VALUE self)
+{
+ return ossl_pkey_export_spki(self, 1);
+}
+
+/*
+ * call-seq:
+ * pkey.public_to_pem -> string
+ *
+ * Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format.
+ *
+ * A PEM-encoded key will look like:
+ *
+ * -----BEGIN PUBLIC KEY-----
+ * [...]
+ * -----END PUBLIC KEY-----
+ */
+static VALUE
+ossl_pkey_public_to_pem(VALUE self)
+{
+ return ossl_pkey_export_spki(self, 0);
+}
+
+/*
+ * call-seq:
+ * pkey.raw_public_key => string
+ *
+ * See the OpenSSL documentation for EVP_PKEY_get_raw_public_key()
+ */
+
+static VALUE
+ossl_pkey_raw_public_key(VALUE self)
+{
+ EVP_PKEY *pkey;
+ VALUE str;
+ size_t len;
+
GetPKey(self, pkey);
- EVP_SignInit(&ctx, GetDigestPtr(digest));
- StringValue(data);
- EVP_SignUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len);
- str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
- if (!EVP_SignFinal(&ctx, RSTRING(str)->ptr, &buf_len, pkey))
- ossl_raise(ePKeyError, NULL);
- assert(buf_len <= RSTRING(str)->len);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ if (EVP_PKEY_get_raw_public_key(pkey, NULL, &len) != 1)
+ ossl_raise(ePKeyError, "EVP_PKEY_get_raw_public_key");
+ str = rb_str_new(NULL, len);
+
+ if (EVP_PKEY_get_raw_public_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1)
+ ossl_raise(ePKeyError, "EVP_PKEY_get_raw_public_key");
+
+ rb_str_set_len(str, len);
return str;
}
+/*
+ * call-seq:
+ * pkey.compare?(another_pkey) -> true | false
+ *
+ * Used primarily to check if an OpenSSL::X509::Certificate#public_key compares to its private key.
+ *
+ * == Example
+ * x509 = OpenSSL::X509::Certificate.new(pem_encoded_certificate)
+ * rsa_key = OpenSSL::PKey::RSA.new(pem_encoded_private_key)
+ *
+ * rsa_key.compare?(x509.public_key) => true | false
+ */
static VALUE
-ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
+ossl_pkey_compare(VALUE self, VALUE other)
+{
+ int ret;
+ EVP_PKEY *selfPKey;
+ EVP_PKEY *otherPKey;
+
+ GetPKey(self, selfPKey);
+ GetPKey(other, otherPKey);
+
+ /* Explicitly check the key type given EVP_PKEY_ASN1_METHOD(3)
+ * docs param_cmp could return any negative number.
+ */
+ if (EVP_PKEY_id(selfPKey) != EVP_PKEY_id(otherPKey))
+ ossl_raise(rb_eTypeError, "cannot match different PKey types");
+
+ ret = EVP_PKEY_eq(selfPKey, otherPKey);
+
+ if (ret == 0)
+ return Qfalse;
+ else if (ret == 1)
+ return Qtrue;
+ else
+ ossl_raise(ePKeyError, "EVP_PKEY_eq");
+}
+
+/*
+ * call-seq:
+ * pkey.sign(digest, data [, options]) -> string
+ *
+ * Hashes and signs the +data+ using a message digest algorithm +digest+ and
+ * a private key +pkey+.
+ *
+ * See #verify for the verification operation.
+ *
+ * See also the man page EVP_DigestSign(3).
+ *
+ * +digest+::
+ * A String that represents the message digest algorithm name, or +nil+
+ * if the PKey type requires no digest algorithm.
+ * For backwards compatibility, this can be an instance of OpenSSL::Digest.
+ * Its state will not affect the signature.
+ * +data+::
+ * A String. The data to be hashed and signed.
+ * +options+::
+ * A Hash that contains algorithm specific control operations to \OpenSSL.
+ * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details.
+ * +options+ parameter was added in version 3.0.
+ *
+ * Example:
+ * data = "Sign me!"
+ * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048)
+ * signopts = { rsa_padding_mode: "pss" }
+ * signature = pkey.sign("SHA256", data, signopts)
+ *
+ * # Creates a copy of the RSA key pkey, but without the private components
+ * pub_key = pkey.public_key
+ * puts pub_key.verify("SHA256", signature, data, signopts) # => true
+ */
+static VALUE
+ossl_pkey_sign(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- EVP_MD_CTX ctx;
+ VALUE digest, data, options, sig, md_holder;
+ const EVP_MD *md = NULL;
+ EVP_MD_CTX *ctx;
+ EVP_PKEY_CTX *pctx;
+ size_t siglen;
+ int state;
+
+ pkey = GetPrivPKeyPtr(self);
+ rb_scan_args(argc, argv, "21", &digest, &data, &options);
+ if (!NIL_P(digest))
+ md = ossl_evp_md_fetch(digest, &md_holder);
+ StringValue(data);
+
+ ctx = EVP_MD_CTX_new();
+ if (!ctx)
+ ossl_raise(ePKeyError, "EVP_MD_CTX_new");
+ if (EVP_DigestSignInit(ctx, &pctx, md, /* engine */NULL, pkey) < 1) {
+ EVP_MD_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_DigestSignInit");
+ }
+ if (!NIL_P(options)) {
+ pkey_ctx_apply_options(pctx, options, &state);
+ if (state) {
+ EVP_MD_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ }
+ if (EVP_DigestSign(ctx, NULL, &siglen, (unsigned char *)RSTRING_PTR(data),
+ RSTRING_LEN(data)) < 1) {
+ EVP_MD_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_DigestSign");
+ }
+ if (siglen > LONG_MAX) {
+ EVP_MD_CTX_free(ctx);
+ rb_raise(ePKeyError, "signature would be too large");
+ }
+ sig = ossl_str_new(NULL, (long)siglen, &state);
+ if (state) {
+ EVP_MD_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ if (EVP_DigestSign(ctx, (unsigned char *)RSTRING_PTR(sig), &siglen,
+ (unsigned char *)RSTRING_PTR(data),
+ RSTRING_LEN(data)) < 1) {
+ EVP_MD_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_DigestSign");
+ }
+ EVP_MD_CTX_free(ctx);
+ rb_str_set_len(sig, siglen);
+ return sig;
+}
+
+/*
+ * call-seq:
+ * pkey.verify(digest, signature, data [, options]) -> true or false
+ *
+ * Verifies the +signature+ for the +data+ using a message digest algorithm
+ * +digest+ and a public key +pkey+.
+ *
+ * Returns +true+ if the signature is successfully verified, +false+ otherwise.
+ * The caller must check the return value.
+ *
+ * See #sign for the signing operation and an example.
+ *
+ * See also the man page EVP_DigestVerify(3).
+ *
+ * +digest+::
+ * See #sign.
+ * +signature+::
+ * A String containing the signature to be verified.
+ * +data+::
+ * See #sign.
+ * +options+::
+ * See #sign. +options+ parameter was added in version 3.0.
+ */
+static VALUE
+ossl_pkey_verify(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ VALUE digest, sig, data, options, md_holder;
+ const EVP_MD *md = NULL;
+ EVP_MD_CTX *ctx;
+ EVP_PKEY_CTX *pctx;
+ int state, ret;
GetPKey(self, pkey);
- EVP_VerifyInit(&ctx, GetDigestPtr(digest));
+ rb_scan_args(argc, argv, "31", &digest, &sig, &data, &options);
+ ossl_pkey_check_public_key(pkey);
+ if (!NIL_P(digest))
+ md = ossl_evp_md_fetch(digest, &md_holder);
StringValue(sig);
StringValue(data);
- EVP_VerifyUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len);
- switch (EVP_VerifyFinal(&ctx, RSTRING(sig)->ptr, RSTRING(sig)->len, pkey)) {
- case 0:
- return Qfalse;
- case 1:
- return Qtrue;
- default:
- ossl_raise(ePKeyError, NULL);
+
+ ctx = EVP_MD_CTX_new();
+ if (!ctx)
+ ossl_raise(ePKeyError, "EVP_MD_CTX_new");
+ if (EVP_DigestVerifyInit(ctx, &pctx, md, /* engine */NULL, pkey) < 1) {
+ EVP_MD_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_DigestVerifyInit");
+ }
+ if (!NIL_P(options)) {
+ pkey_ctx_apply_options(pctx, options, &state);
+ if (state) {
+ EVP_MD_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ }
+ ret = EVP_DigestVerify(ctx, (unsigned char *)RSTRING_PTR(sig),
+ RSTRING_LEN(sig), (unsigned char *)RSTRING_PTR(data),
+ RSTRING_LEN(data));
+ EVP_MD_CTX_free(ctx);
+ if (ret < 0)
+ ossl_raise(ePKeyError, "EVP_DigestVerify");
+ if (ret)
+ return Qtrue;
+ else {
+ ossl_clear_error();
+ return Qfalse;
}
- return Qnil; /* dummy */
+}
+
+/*
+ * call-seq:
+ * pkey.sign_raw(digest, data [, options]) -> string
+ *
+ * Signs +data+ using a private key +pkey+. Unlike #sign, +data+ will not be
+ * hashed by +digest+ automatically.
+ *
+ * See #verify_raw for the verification operation.
+ *
+ * Added in version 3.0. See also the man page EVP_PKEY_sign(3).
+ *
+ * +digest+::
+ * A String that represents the message digest algorithm name, or +nil+
+ * if the PKey type requires no digest algorithm.
+ * Although this method will not hash +data+ with it, this parameter may still
+ * be required depending on the signature algorithm.
+ * +data+::
+ * A String. The data to be signed.
+ * +options+::
+ * A Hash that contains algorithm specific control operations to \OpenSSL.
+ * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details.
+ *
+ * Example:
+ * data = "Sign me!"
+ * hash = OpenSSL::Digest.digest("SHA256", data)
+ * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048)
+ * signopts = { rsa_padding_mode: "pss" }
+ * signature = pkey.sign_raw("SHA256", hash, signopts)
+ *
+ * # Creates a copy of the RSA key pkey, but without the private components
+ * pub_key = pkey.public_key
+ * puts pub_key.verify_raw("SHA256", signature, hash, signopts) # => true
+ */
+static VALUE
+ossl_pkey_sign_raw(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ VALUE digest, data, options, sig, md_holder;
+ const EVP_MD *md = NULL;
+ EVP_PKEY_CTX *ctx;
+ size_t outlen;
+ int state;
+
+ GetPKey(self, pkey);
+ rb_scan_args(argc, argv, "21", &digest, &data, &options);
+ if (!NIL_P(digest))
+ md = ossl_evp_md_fetch(digest, &md_holder);
+ StringValue(data);
+
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
+ if (!ctx)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
+ if (EVP_PKEY_sign_init(ctx) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_sign_init");
+ }
+ if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md");
+ }
+ if (!NIL_P(options)) {
+ pkey_ctx_apply_options(ctx, options, &state);
+ if (state) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ }
+ if (EVP_PKEY_sign(ctx, NULL, &outlen, (unsigned char *)RSTRING_PTR(data),
+ RSTRING_LEN(data)) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_sign");
+ }
+ if (outlen > LONG_MAX) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_raise(ePKeyError, "signature would be too large");
+ }
+ sig = ossl_str_new(NULL, (long)outlen, &state);
+ if (state) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ if (EVP_PKEY_sign(ctx, (unsigned char *)RSTRING_PTR(sig), &outlen,
+ (unsigned char *)RSTRING_PTR(data),
+ RSTRING_LEN(data)) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_sign");
+ }
+ EVP_PKEY_CTX_free(ctx);
+ rb_str_set_len(sig, outlen);
+ return sig;
+}
+
+/*
+ * call-seq:
+ * pkey.verify_raw(digest, signature, data [, options]) -> true or false
+ *
+ * Verifies the +signature+ for the +data+ using a public key +pkey+. Unlike
+ * #verify, this method will not hash +data+ with +digest+ automatically.
+ *
+ * Returns +true+ if the signature is successfully verified, +false+ otherwise.
+ * The caller must check the return value.
+ *
+ * See #sign_raw for the signing operation and an example code.
+ *
+ * Added in version 3.0. See also the man page EVP_PKEY_verify(3).
+ *
+ * +signature+::
+ * A String containing the signature to be verified.
+ */
+static VALUE
+ossl_pkey_verify_raw(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ VALUE digest, sig, data, options, md_holder;
+ const EVP_MD *md = NULL;
+ EVP_PKEY_CTX *ctx;
+ int state, ret;
+
+ GetPKey(self, pkey);
+ rb_scan_args(argc, argv, "31", &digest, &sig, &data, &options);
+ ossl_pkey_check_public_key(pkey);
+ if (!NIL_P(digest))
+ md = ossl_evp_md_fetch(digest, &md_holder);
+ StringValue(sig);
+ StringValue(data);
+
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
+ if (!ctx)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
+ if (EVP_PKEY_verify_init(ctx) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_verify_init");
+ }
+ if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md");
+ }
+ if (!NIL_P(options)) {
+ pkey_ctx_apply_options(ctx, options, &state);
+ if (state) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ }
+ ret = EVP_PKEY_verify(ctx, (unsigned char *)RSTRING_PTR(sig),
+ RSTRING_LEN(sig),
+ (unsigned char *)RSTRING_PTR(data),
+ RSTRING_LEN(data));
+ EVP_PKEY_CTX_free(ctx);
+ if (ret < 0)
+ ossl_raise(ePKeyError, "EVP_PKEY_verify");
+
+ if (ret)
+ return Qtrue;
+ else {
+ ossl_clear_error();
+ return Qfalse;
+ }
+}
+
+/*
+ * call-seq:
+ * pkey.verify_recover(digest, signature [, options]) -> string
+ *
+ * Recovers the signed data from +signature+ using a public key +pkey+. Not all
+ * signature algorithms support this operation.
+ *
+ * Added in version 3.0. See also the man page EVP_PKEY_verify_recover(3).
+ *
+ * +signature+::
+ * A String containing the signature to be verified.
+ */
+static VALUE
+ossl_pkey_verify_recover(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ VALUE digest, sig, options, out, md_holder;
+ const EVP_MD *md = NULL;
+ EVP_PKEY_CTX *ctx;
+ int state;
+ size_t outlen;
+
+ GetPKey(self, pkey);
+ rb_scan_args(argc, argv, "21", &digest, &sig, &options);
+ ossl_pkey_check_public_key(pkey);
+ if (!NIL_P(digest))
+ md = ossl_evp_md_fetch(digest, &md_holder);
+ StringValue(sig);
+
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
+ if (!ctx)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
+ if (EVP_PKEY_verify_recover_init(ctx) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_verify_recover_init");
+ }
+ if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md");
+ }
+ if (!NIL_P(options)) {
+ pkey_ctx_apply_options(ctx, options, &state);
+ if (state) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ }
+ if (EVP_PKEY_verify_recover(ctx, NULL, &outlen,
+ (unsigned char *)RSTRING_PTR(sig),
+ RSTRING_LEN(sig)) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_verify_recover");
+ }
+ out = ossl_str_new(NULL, (long)outlen, &state);
+ if (state) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ if (EVP_PKEY_verify_recover(ctx, (unsigned char *)RSTRING_PTR(out), &outlen,
+ (unsigned char *)RSTRING_PTR(sig),
+ RSTRING_LEN(sig)) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_verify_recover");
+ }
+ EVP_PKEY_CTX_free(ctx);
+ rb_str_set_len(out, outlen);
+ return out;
+}
+
+/*
+ * call-seq:
+ * pkey.derive(peer_pkey) -> string
+ *
+ * Derives a shared secret from _pkey_ and _peer_pkey_. _pkey_ must contain
+ * the private components, _peer_pkey_ must contain the public components.
+ */
+static VALUE
+ossl_pkey_derive(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey, *peer_pkey;
+ EVP_PKEY_CTX *ctx;
+ VALUE peer_pkey_obj, str;
+ size_t keylen;
+ int state;
+
+ GetPKey(self, pkey);
+ rb_scan_args(argc, argv, "1", &peer_pkey_obj);
+ GetPKey(peer_pkey_obj, peer_pkey);
+
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
+ if (!ctx)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
+ if (EVP_PKEY_derive_init(ctx) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_derive_init");
+ }
+ if (EVP_PKEY_derive_set_peer(ctx, peer_pkey) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_derive_set_peer");
+ }
+ if (EVP_PKEY_derive(ctx, NULL, &keylen) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_derive");
+ }
+ if (keylen > LONG_MAX) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_raise(ePKeyError, "derived key would be too large");
+ }
+ str = ossl_str_new(NULL, (long)keylen, &state);
+ if (state) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ if (EVP_PKEY_derive(ctx, (unsigned char *)RSTRING_PTR(str), &keylen) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_derive");
+ }
+ EVP_PKEY_CTX_free(ctx);
+ rb_str_set_len(str, keylen);
+ return str;
+}
+
+/*
+ * call-seq:
+ * pkey.encrypt(data [, options]) -> string
+ *
+ * Performs a public key encryption operation using +pkey+.
+ *
+ * See #decrypt for the reverse operation.
+ *
+ * Added in version 3.0. See also the man page EVP_PKEY_encrypt(3).
+ *
+ * +data+::
+ * A String to be encrypted.
+ * +options+::
+ * A Hash that contains algorithm specific control operations to \OpenSSL.
+ * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details.
+ *
+ * Example:
+ * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048)
+ * data = "secret data"
+ * encrypted = pkey.encrypt(data, rsa_padding_mode: "oaep")
+ * decrypted = pkey.decrypt(data, rsa_padding_mode: "oaep")
+ * p decrypted #=> "secret data"
+ */
+static VALUE
+ossl_pkey_encrypt(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *ctx;
+ VALUE data, options, str;
+ size_t outlen;
+ int state;
+
+ GetPKey(self, pkey);
+ rb_scan_args(argc, argv, "11", &data, &options);
+ StringValue(data);
+
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
+ if (!ctx)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
+ if (EVP_PKEY_encrypt_init(ctx) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_encrypt_init");
+ }
+ if (!NIL_P(options)) {
+ pkey_ctx_apply_options(ctx, options, &state);
+ if (state) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ }
+ if (EVP_PKEY_encrypt(ctx, NULL, &outlen,
+ (unsigned char *)RSTRING_PTR(data),
+ RSTRING_LEN(data)) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_encrypt");
+ }
+ if (outlen > LONG_MAX) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_raise(ePKeyError, "encrypted data would be too large");
+ }
+ str = ossl_str_new(NULL, (long)outlen, &state);
+ if (state) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ if (EVP_PKEY_encrypt(ctx, (unsigned char *)RSTRING_PTR(str), &outlen,
+ (unsigned char *)RSTRING_PTR(data),
+ RSTRING_LEN(data)) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_encrypt");
+ }
+ EVP_PKEY_CTX_free(ctx);
+ rb_str_set_len(str, outlen);
+ return str;
+}
+
+/*
+ * call-seq:
+ * pkey.decrypt(data [, options]) -> string
+ *
+ * Performs a public key decryption operation using +pkey+.
+ *
+ * See #encrypt for a description of the parameters and an example.
+ *
+ * Added in version 3.0. See also the man page EVP_PKEY_decrypt(3).
+ */
+static VALUE
+ossl_pkey_decrypt(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *ctx;
+ VALUE data, options, str;
+ size_t outlen;
+ int state;
+
+ GetPKey(self, pkey);
+ rb_scan_args(argc, argv, "11", &data, &options);
+ StringValue(data);
+
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
+ if (!ctx)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
+ if (EVP_PKEY_decrypt_init(ctx) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_decrypt_init");
+ }
+ if (!NIL_P(options)) {
+ pkey_ctx_apply_options(ctx, options, &state);
+ if (state) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ }
+ if (EVP_PKEY_decrypt(ctx, NULL, &outlen,
+ (unsigned char *)RSTRING_PTR(data),
+ RSTRING_LEN(data)) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_decrypt");
+ }
+ if (outlen > LONG_MAX) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_raise(ePKeyError, "decrypted data would be too large");
+ }
+ str = ossl_str_new(NULL, (long)outlen, &state);
+ if (state) {
+ EVP_PKEY_CTX_free(ctx);
+ rb_jump_tag(state);
+ }
+ if (EVP_PKEY_decrypt(ctx, (unsigned char *)RSTRING_PTR(str), &outlen,
+ (unsigned char *)RSTRING_PTR(data),
+ RSTRING_LEN(data)) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_decrypt");
+ }
+ EVP_PKEY_CTX_free(ctx);
+ rb_str_set_len(str, outlen);
+ return str;
}
/*
* INIT
*/
void
-Init_ossl_pkey()
+Init_ossl_pkey(void)
{
+#undef rb_intern
+ /* Document-module: OpenSSL::PKey
+ *
+ * == Asymmetric Public Key Algorithms
+ *
+ * Asymmetric public key algorithms solve the problem of establishing and
+ * sharing secret keys to en-/decrypt messages. The key in such an
+ * algorithm consists of two parts: a public key that may be distributed
+ * to others and a private key that needs to remain secret.
+ *
+ * Messages encrypted with a public key can only be decrypted by
+ * recipients that are in possession of the associated private key.
+ * Since public key algorithms are considerably slower than symmetric
+ * key algorithms (cf. OpenSSL::Cipher) they are often used to establish
+ * a symmetric key shared between two parties that are in possession of
+ * each other's public key.
+ *
+ * Asymmetric algorithms offer a lot of nice features that are used in a
+ * lot of different areas. A very common application is the creation and
+ * validation of digital signatures. To sign a document, the signatory
+ * generally uses a message digest algorithm (cf. OpenSSL::Digest) to
+ * compute a digest of the document that is then encrypted (i.e. signed)
+ * using the private key. Anyone in possession of the public key may then
+ * verify the signature by computing the message digest of the original
+ * document on their own, decrypting the signature using the signatory's
+ * public key and comparing the result to the message digest they
+ * previously computed. The signature is valid if and only if the
+ * decrypted signature is equal to this message digest.
+ *
+ * The PKey module offers support for three popular public/private key
+ * algorithms:
+ * * RSA (OpenSSL::PKey::RSA)
+ * * DSA (OpenSSL::PKey::DSA)
+ * * Elliptic Curve Cryptography (OpenSSL::PKey::EC)
+ * Each of these implementations is in fact a sub-class of the abstract
+ * PKey class which offers the interface for supporting digital signatures
+ * in the form of PKey#sign and PKey#verify.
+ *
+ * == Diffie-Hellman Key Exchange
+ *
+ * Finally PKey also features OpenSSL::PKey::DH, an implementation of
+ * the Diffie-Hellman key exchange protocol based on discrete logarithms
+ * in finite fields, the same basis that DSA is built on.
+ * The Diffie-Hellman protocol can be used to exchange (symmetric) keys
+ * over insecure channels without needing any prior joint knowledge
+ * between the participating parties. As the security of DH demands
+ * relatively long "public keys" (i.e. the part that is overtly
+ * transmitted between participants) DH tends to be quite slow. If
+ * security or speed is your primary concern, OpenSSL::PKey::EC offers
+ * another implementation of the Diffie-Hellman protocol.
+ *
+ */
mPKey = rb_define_module_under(mOSSL, "PKey");
-
+
+ /* Document-class: OpenSSL::PKey::PKeyError
+ *
+ * Raised when errors occur during PKey#sign or PKey#verify.
+ *
+ * Before version 4.0.0, OpenSSL::PKey::PKeyError had the following
+ * subclasses. These subclasses have been removed and the constants are
+ * now defined as aliases of OpenSSL::PKey::PKeyError.
+ *
+ * * OpenSSL::PKey::DHError
+ * * OpenSSL::PKey::DSAError
+ * * OpenSSL::PKey::ECError
+ * * OpenSSL::PKey::RSAError
+ */
ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
+ /* Document-class: OpenSSL::PKey::PKey
+ *
+ * An abstract class that bundles signature creation (PKey#sign) and
+ * validation (PKey#verify) that is common to all implementations except
+ * OpenSSL::PKey::DH
+ * * OpenSSL::PKey::RSA
+ * * OpenSSL::PKey::DSA
+ * * OpenSSL::PKey::EC
+ */
cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
-
+
+ rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1);
+ rb_define_module_function(mPKey, "generate_parameters", ossl_pkey_s_generate_parameters, -1);
+ rb_define_module_function(mPKey, "generate_key", ossl_pkey_s_generate_key, -1);
+ rb_define_module_function(mPKey, "new_raw_private_key", ossl_pkey_new_raw_private_key, 2);
+ rb_define_module_function(mPKey, "new_raw_public_key", ossl_pkey_new_raw_public_key, 2);
+
rb_define_alloc_func(cPKey, ossl_pkey_alloc);
rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
+#ifdef HAVE_EVP_PKEY_DUP
+ rb_define_method(cPKey, "initialize_copy", ossl_pkey_initialize_copy, 1);
+#else
+ rb_undef_method(cPKey, "initialize_copy");
+#endif
+ rb_define_method(cPKey, "oid", ossl_pkey_oid, 0);
+ rb_define_method(cPKey, "inspect", ossl_pkey_inspect, 0);
+ rb_define_method(cPKey, "to_text", ossl_pkey_to_text, 0);
+ rb_define_method(cPKey, "private_to_der", ossl_pkey_private_to_der, -1);
+ rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1);
+ rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0);
+ rb_define_method(cPKey, "public_to_pem", ossl_pkey_public_to_pem, 0);
+ rb_define_method(cPKey, "raw_private_key", ossl_pkey_raw_private_key, 0);
+ rb_define_method(cPKey, "raw_public_key", ossl_pkey_raw_public_key, 0);
+ rb_define_method(cPKey, "compare?", ossl_pkey_compare, 1);
+
+ rb_define_method(cPKey, "sign", ossl_pkey_sign, -1);
+ rb_define_method(cPKey, "verify", ossl_pkey_verify, -1);
+ rb_define_method(cPKey, "sign_raw", ossl_pkey_sign_raw, -1);
+ rb_define_method(cPKey, "verify_raw", ossl_pkey_verify_raw, -1);
+ rb_define_method(cPKey, "verify_recover", ossl_pkey_verify_recover, -1);
+ rb_define_method(cPKey, "derive", ossl_pkey_derive, -1);
+ rb_define_method(cPKey, "encrypt", ossl_pkey_encrypt, -1);
+ rb_define_method(cPKey, "decrypt", ossl_pkey_decrypt, -1);
- rb_define_method(cPKey, "sign", ossl_pkey_sign, 2);
- rb_define_method(cPKey, "verify", ossl_pkey_verify, 3);
-
id_private_q = rb_intern("private?");
-
+
/*
- * INIT rsa, dsa
+ * INIT rsa, dsa, dh, ec
*/
Init_ossl_rsa();
Init_ossl_dsa();
Init_ossl_dh();
+ Init_ossl_ec();
}
-
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index 880a104675..efba33b752 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -1,120 +1,192 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
-#if !defined(_OSSL_PKEY_H_)
-#define _OSSL_PKEY_H_
+#if !defined(OSSL_PKEY_H)
+#define OSSL_PKEY_H
extern VALUE mPKey;
extern VALUE cPKey;
extern VALUE ePKeyError;
-extern ID id_private_q;
+extern const rb_data_type_t ossl_evp_pkey_type;
-#define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue)
-#define OSSL_PKEY_SET_PUBLIC(obj) rb_iv_set((obj), "private", Qfalse)
-#define OSSL_PKEY_IS_PRIVATE(obj) (rb_iv_get((obj), "private") == Qtrue)
+/* For ENGINE */
+#define OSSL_PKEY_SET_PRIVATE(obj) rb_ivar_set((obj), rb_intern("private"), Qtrue)
+#define OSSL_PKEY_IS_PRIVATE(obj) (rb_attr_get((obj), rb_intern("private")) == Qtrue)
-#define WrapPKey(klass, obj, pkey) do { \
- if (!pkey) { \
- rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!"); \
- } \
- obj = Data_Wrap_Struct(klass, 0, EVP_PKEY_free, pkey); \
- OSSL_PKEY_SET_PUBLIC(obj); \
-} while (0)
#define GetPKey(obj, pkey) do {\
- Data_Get_Struct(obj, EVP_PKEY, pkey);\
- if (!pkey) { \
- rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!");\
+ TypedData_Get_Struct((obj), EVP_PKEY, &ossl_evp_pkey_type, (pkey)); \
+ if (!(pkey)) { \
+ rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!");\
} \
} while (0)
-#define SafeGetPKey(obj, pkey) do { \
- OSSL_Check_Kind(obj, cPKey); \
- GetPKey(obj, pkey); \
-} while (0)
-
-void ossl_generate_cb(int, int, void *);
-VALUE ossl_pkey_new(EVP_PKEY *);
-VALUE ossl_pkey_new_from_file(VALUE);
+/* Takes ownership of the EVP_PKEY */
+VALUE ossl_pkey_wrap(EVP_PKEY *);
+void ossl_pkey_check_public_key(const EVP_PKEY *);
+EVP_PKEY *ossl_pkey_read_generic(BIO *, VALUE);
EVP_PKEY *GetPKeyPtr(VALUE);
EVP_PKEY *DupPKeyPtr(VALUE);
EVP_PKEY *GetPrivPKeyPtr(VALUE);
-EVP_PKEY *DupPrivPKeyPtr(VALUE);
+
+/*
+ * Serializes _self_ in X.509 SubjectPublicKeyInfo format and returns the
+ * resulting String. Sub-classes use this when overriding #to_der.
+ */
+VALUE ossl_pkey_export_spki(VALUE self, int to_der);
+/*
+ * Serializes the private key _self_ in the traditional private key format
+ * and returns the resulting String. Sub-classes use this when overriding
+ * #to_der.
+ */
+VALUE ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self,
+ int to_der);
+
void Init_ossl_pkey(void);
/*
* RSA
*/
extern VALUE cRSA;
-extern VALUE eRSAError;
-
-VALUE ossl_rsa_new(EVP_PKEY *);
void Init_ossl_rsa(void);
/*
* DSA
*/
extern VALUE cDSA;
-extern VALUE eDSAError;
-
-VALUE ossl_dsa_new(EVP_PKEY *);
void Init_ossl_dsa(void);
/*
* DH
*/
extern VALUE cDH;
-extern VALUE eDHError;
-extern DH *OSSL_DEFAULT_DH_512;
-extern DH *OSSL_DEFAULT_DH_1024;
-
-VALUE ossl_dh_new(EVP_PKEY *);
void Init_ossl_dh(void);
-#define OSSL_PKEY_BN(keytype, name) \
-static VALUE ossl_##keytype##_get_##name(VALUE self) \
-{ \
- EVP_PKEY *pkey; \
- BIGNUM *bn; \
- \
- GetPKey(self, pkey); \
- bn = pkey->pkey.keytype->name; \
- if (bn == NULL) \
- return Qnil; \
- return ossl_bn_new(bn); \
-} \
-static VALUE ossl_##keytype##_set_##name(VALUE self, VALUE bignum) \
-{ \
- EVP_PKEY *pkey; \
- BIGNUM *bn; \
- \
- GetPKey(self, pkey); \
- if (NIL_P(bignum)) { \
- BN_clear_free(pkey->pkey.keytype->name); \
- pkey->pkey.keytype->name = NULL; \
- return Qnil; \
- } \
- \
- bn = GetBNPtr(bignum); \
- if (pkey->pkey.keytype->name == NULL) \
- pkey->pkey.keytype->name = BN_new(); \
- if (pkey->pkey.keytype->name == NULL) \
- ossl_raise(eBNError, NULL); \
- if (BN_copy(pkey->pkey.keytype->name, bn) == NULL) \
- ossl_raise(eBNError, NULL); \
- return bignum; \
+/*
+ * EC
+ */
+extern VALUE cEC;
+void Init_ossl_ec(void);
+
+#define OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, _name, _get) \
+/* \
+ * call-seq: \
+ * _keytype##.##_name -> aBN \
+ */ \
+static VALUE ossl_##_keytype##_get_##_name(VALUE self) \
+{ \
+ const _type *obj; \
+ const BIGNUM *bn; \
+ \
+ Get##_type(self, obj); \
+ _get; \
+ if (bn == NULL) \
+ return Qnil; \
+ return ossl_bn_new(bn); \
}
-#define DEF_OSSL_PKEY_BN(class, keytype, name) \
-do { \
- rb_define_method(class, #name, ossl_##keytype##_get_##name, 0); \
- rb_define_method(class, #name "=", ossl_##keytype##_set_##name, 1);\
-} while (0)
+#define OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \
+ _type##_get0_##_group(obj, &bn, NULL, NULL)) \
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \
+ _type##_get0_##_group(obj, NULL, &bn, NULL)) \
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a3, \
+ _type##_get0_##_group(obj, NULL, NULL, &bn))
+
+#define OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \
+ _type##_get0_##_group(obj, &bn, NULL)) \
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \
+ _type##_get0_##_group(obj, NULL, &bn))
+
+#ifndef OSSL_HAVE_IMMUTABLE_PKEY
+#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \
+/* \
+ * call-seq: \
+ * _keytype##.set_##_group(a1, a2, a3) -> self \
+ */ \
+static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALUE v3) \
+{ \
+ _type *obj; \
+ BIGNUM *bn1 = NULL, *orig_bn1 = NIL_P(v1) ? NULL : GetBNPtr(v1);\
+ BIGNUM *bn2 = NULL, *orig_bn2 = NIL_P(v2) ? NULL : GetBNPtr(v2);\
+ BIGNUM *bn3 = NULL, *orig_bn3 = NIL_P(v3) ? NULL : GetBNPtr(v3);\
+ \
+ Get##_type(self, obj); \
+ if ((orig_bn1 && !(bn1 = BN_dup(orig_bn1))) || \
+ (orig_bn2 && !(bn2 = BN_dup(orig_bn2))) || \
+ (orig_bn3 && !(bn3 = BN_dup(orig_bn3)))) { \
+ BN_clear_free(bn1); \
+ BN_clear_free(bn2); \
+ BN_clear_free(bn3); \
+ ossl_raise(ePKeyError, "BN_dup"); \
+ } \
+ \
+ if (!_type##_set0_##_group(obj, bn1, bn2, bn3)) { \
+ BN_clear_free(bn1); \
+ BN_clear_free(bn2); \
+ BN_clear_free(bn3); \
+ ossl_raise(ePKeyError, #_type"_set0_"#_group); \
+ } \
+ return self; \
+}
+
+#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \
+/* \
+ * call-seq: \
+ * _keytype##.set_##_group(a1, a2) -> self \
+ */ \
+static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \
+{ \
+ _type *obj; \
+ BIGNUM *bn1 = NULL, *orig_bn1 = NIL_P(v1) ? NULL : GetBNPtr(v1);\
+ BIGNUM *bn2 = NULL, *orig_bn2 = NIL_P(v2) ? NULL : GetBNPtr(v2);\
+ \
+ Get##_type(self, obj); \
+ if ((orig_bn1 && !(bn1 = BN_dup(orig_bn1))) || \
+ (orig_bn2 && !(bn2 = BN_dup(orig_bn2)))) { \
+ BN_clear_free(bn1); \
+ BN_clear_free(bn2); \
+ ossl_raise(ePKeyError, "BN_dup"); \
+ } \
+ \
+ if (!_type##_set0_##_group(obj, bn1, bn2)) { \
+ BN_clear_free(bn1); \
+ BN_clear_free(bn2); \
+ ossl_raise(ePKeyError, #_type"_set0_"#_group); \
+ } \
+ return self; \
+}
+#else
+#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \
+static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALUE v3) \
+{ \
+ rb_raise(ePKeyError, \
+ #_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \
+}
+
+#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \
+static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \
+{ \
+ rb_raise(ePKeyError, \
+ #_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \
+}
+#endif
+
+#define OSSL_PKEY_BN_DEF3(_keytype, _type, _group, a1, a2, a3) \
+ OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \
+ OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3)
+
+#define OSSL_PKEY_BN_DEF2(_keytype, _type, _group, a1, a2) \
+ OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \
+ OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2)
+
+#define DEF_OSSL_PKEY_BN(class, keytype, name) \
+ rb_define_method((class), #name, ossl_##keytype##_get_##name, 0)
-#endif /* _OSSL_PKEY_H_ */
+#endif /* OSSL_PKEY_H */
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index 5b728ba353..3f2975c5a3 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -1,458 +1,420 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
-#if !defined(OPENSSL_NO_DH)
-
#include "ossl.h"
+#if !defined(OPENSSL_NO_DH)
+
#define GetPKeyDH(obj, pkey) do { \
- GetPKey(obj, pkey); \
- if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) { /* PARANOIA? */ \
- ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \
+ GetPKey((obj), (pkey)); \
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) { /* PARANOIA? */ \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \
} \
} while (0)
-
-#define DH_HAS_PRIVATE(dh) ((dh)->priv_key)
-
-#ifdef OSSL_ENGINE_ENABLED
-# define DH_PRIVATE(dh) (DH_HAS_PRIVATE(dh) || (dh)->engine)
-#else
-# define DH_PRIVATE(dh) DH_HAS_PRIVATE(dh)
-#endif
-
+#define GetDH(obj, dh) do { \
+ EVP_PKEY *_pkey; \
+ GetPKeyDH((obj), _pkey); \
+ (dh) = EVP_PKEY_get0_DH(_pkey); \
+ if ((dh) == NULL) \
+ ossl_raise(ePKeyError, "failed to get DH from EVP_PKEY"); \
+} while (0)
/*
* Classes
*/
VALUE cDH;
-VALUE eDHError;
/*
- * Public
+ * Private
*/
-static VALUE
-dh_instance(VALUE klass, DH *dh)
-{
- EVP_PKEY *pkey;
- VALUE obj;
-
- if (!dh) {
- return Qfalse;
- }
- if (!(pkey = EVP_PKEY_new())) {
- return Qfalse;
- }
- if (!EVP_PKEY_assign_DH(pkey, dh)) {
- EVP_PKEY_free(pkey);
- return Qfalse;
- }
- WrapPKey(klass, obj, pkey);
-
- return obj;
-}
-
-VALUE
-ossl_dh_new(EVP_PKEY *pkey)
-{
- VALUE obj;
-
- if (!pkey) {
- obj = dh_instance(cDH, DH_new());
- } else {
- if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) {
- ossl_raise(rb_eTypeError, "Not a DH key!");
- }
- WrapPKey(cDH, obj, pkey);
- }
- if (obj == Qfalse) {
- ossl_raise(eDHError, NULL);
- }
-
- return obj;
-}
-
/*
- * Private
+ * call-seq:
+ * DH.new -> dh
+ * DH.new(string) -> dh
+ * DH.new(size [, generator]) -> dh
+ *
+ * Creates a new instance of OpenSSL::PKey::DH.
+ *
+ * If called without arguments, an empty instance without any parameter or key
+ * components is created. Use #set_pqg to manually set the parameters afterwards
+ * (and optionally #set_key to set private and public key components).
+ * This form is not compatible with OpenSSL 3.0 or later.
+ *
+ * If a String is given, tries to parse it as a DER- or PEM- encoded parameters.
+ * See also OpenSSL::PKey.read which can parse keys of any kinds.
+ *
+ * The DH.new(size [, generator]) form is an alias of DH.generate.
+ *
+ * +string+::
+ * A String that contains the DER or PEM encoded key.
+ * +size+::
+ * See DH.generate.
+ * +generator+::
+ * See DH.generate.
+ *
+ * Examples:
+ * # Creating an instance from scratch
+ * # Note that this is deprecated and will result in ArgumentError when
+ * # using OpenSSL 3.0 or later.
+ * dh = OpenSSL::PKey::DH.new
+ * dh.set_pqg(bn_p, nil, bn_g)
+ *
+ * # Generating a parameters and a key pair
+ * dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048)
+ *
+ * # Reading DH parameters from a PEM-encoded string
+ * dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only
+ * dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair
*/
-static DH *
-dh_generate(int size, int gen)
+static VALUE
+ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
{
+ EVP_PKEY *pkey;
+ int type;
DH *dh;
-
- dh = DH_generate_parameters(size, gen,
- rb_block_given_p() ? ossl_generate_cb : NULL,
- NULL);
- if (!dh) return 0;
-
- if (!DH_generate_key(dh)) {
- DH_free(dh);
- return 0;
+ BIO *in = NULL;
+ VALUE arg;
+
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
+
+ /* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */
+ if (rb_scan_args(argc, argv, "01", &arg) == 0) {
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ rb_raise(rb_eArgError, "OpenSSL::PKey::DH.new cannot be called " \
+ "without arguments; pkeys are immutable with OpenSSL 3.0");
+#else
+ dh = DH_new();
+ if (!dh)
+ ossl_raise(ePKeyError, "DH_new");
+ goto legacy;
+#endif
}
- return dh;
-}
+ arg = ossl_to_der_if_possible(arg);
+ in = ossl_obj2bio(&arg);
-static VALUE
-ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
-{
- DH *dh ;
- int g = 2;
- VALUE size, gen, obj;
-
- if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
- g = FIX2INT(gen);
- }
- dh = dh_generate(FIX2INT(size), g);
- obj = dh_instance(klass, dh);
- if (obj == Qfalse) {
- DH_free(dh);
- ossl_raise(eDHError, NULL);
+ /*
+ * On OpenSSL <= 1.1.1 and current versions of LibreSSL, the generic
+ * routine does not support DER-encoded parameters
+ */
+ dh = d2i_DHparams_bio(in, NULL);
+ if (dh)
+ goto legacy;
+ OSSL_BIO_reset(in);
+
+ pkey = ossl_pkey_read_generic(in, Qnil);
+ BIO_free(in);
+ if (!pkey)
+ ossl_raise(ePKeyError, "could not parse pkey");
+
+ type = EVP_PKEY_base_id(pkey);
+ if (type != EVP_PKEY_DH) {
+ EVP_PKEY_free(pkey);
+ rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type));
}
+ RTYPEDDATA_DATA(self) = pkey;
+ return self;
- return obj;
+ legacy:
+ BIO_free(in);
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) {
+ EVP_PKEY_free(pkey);
+ DH_free(dh);
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_DH");
+ }
+ RTYPEDDATA_DATA(self) = pkey;
+ return self;
}
+#ifndef HAVE_EVP_PKEY_DUP
+/* :nodoc: */
static VALUE
-ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
+ossl_dh_initialize_copy(VALUE self, VALUE other)
{
EVP_PKEY *pkey;
- DH *dh;
- int g = 2;
- BIO *in;
- VALUE arg, gen;
-
- GetPKey(self, pkey);
- if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) {
- dh = DH_new();
- }
- else if (FIXNUM_P(arg)) {
- if (!NIL_P(gen)) {
- g = FIX2INT(gen);
- }
- if (!(dh = dh_generate(FIX2INT(arg), g))) {
- ossl_raise(eDHError, NULL);
- }
+ DH *dh, *dh_other;
+ const BIGNUM *pub, *priv;
+
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
+ GetDH(other, dh_other);
+
+ dh = DHparams_dup(dh_other);
+ if (!dh)
+ ossl_raise(ePKeyError, "DHparams_dup");
+
+ DH_get0_key(dh_other, &pub, &priv);
+ if (pub) {
+ BIGNUM *pub2 = BN_dup(pub);
+ BIGNUM *priv2 = BN_dup(priv);
+
+ if (!pub2 || (priv && !priv2)) {
+ BN_clear_free(pub2);
+ BN_clear_free(priv2);
+ ossl_raise(ePKeyError, "BN_dup");
+ }
+ DH_set0_key(dh, pub2, priv2);
}
- else {
- arg = ossl_to_der_if_possible(arg);
- in = ossl_obj2bio(arg);
- dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
- if (!dh){
- BIO_reset(in);
- dh = d2i_DHparams_bio(in, NULL);
- }
- BIO_free(in);
- if (!dh) ossl_raise(eDHError, NULL);
- }
- if (!EVP_PKEY_assign_DH(pkey, dh)) {
- DH_free(dh);
- ossl_raise(eDHError, NULL);
+
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) {
+ EVP_PKEY_free(pkey);
+ DH_free(dh);
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_DH");
}
+ RTYPEDDATA_DATA(self) = pkey;
return self;
}
+#endif
+/*
+ * call-seq:
+ * dh.public? -> true | false
+ *
+ * Indicates whether this DH instance has a public key associated with it or
+ * not. The public key may be retrieved with DH#pub_key.
+ */
static VALUE
ossl_dh_is_public(VALUE self)
{
- EVP_PKEY *pkey;
+ OSSL_3_const DH *dh;
+ const BIGNUM *bn;
- GetPKeyDH(self, pkey);
- /*
- * Do we need to check dhp->dh->public_pkey?
- * return Qtrue;
- */
- return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse;
+ GetDH(self, dh);
+ DH_get0_key(dh, &bn, NULL);
+
+ return bn ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * dh.private? -> true | false
+ *
+ * Indicates whether this DH instance has a private key associated with it or
+ * not. The private key may be retrieved with DH#priv_key.
+ */
static VALUE
ossl_dh_is_private(VALUE self)
{
- EVP_PKEY *pkey;
+ OSSL_3_const DH *dh;
+ const BIGNUM *bn;
- GetPKeyDH(self, pkey);
-
- return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse;
+ GetDH(self, dh);
+ DH_get0_key(dh, NULL, &bn);
+
+#if !defined(OPENSSL_NO_ENGINE)
+ return (bn || DH_get0_engine((DH *)dh)) ? Qtrue : Qfalse;
+#else
+ return bn ? Qtrue : Qfalse;
+#endif
}
+/*
+ * call-seq:
+ * dh.export -> aString
+ * dh.to_pem -> aString
+ * dh.to_s -> aString
+ *
+ * Serializes the DH parameters to a PEM-encoding.
+ *
+ * Note that any existing per-session public/private keys will *not* get
+ * encoded, just the Diffie-Hellman parameters will be encoded.
+ *
+ * PEM-encoded parameters will look like:
+ *
+ * -----BEGIN DH PARAMETERS-----
+ * [...]
+ * -----END DH PARAMETERS-----
+ *
+ * See also #public_to_pem (X.509 SubjectPublicKeyInfo) and
+ * #private_to_pem (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for
+ * serialization with the private or public key components.
+ */
static VALUE
ossl_dh_export(VALUE self)
{
- EVP_PKEY *pkey;
+ OSSL_3_const DH *dh;
BIO *out;
VALUE str;
- GetPKeyDH(self, pkey);
+ GetDH(self, dh);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eDHError, NULL);
+ ossl_raise(ePKeyError, NULL);
}
- if (!PEM_write_bio_DHparams(out, pkey->pkey.dh)) {
- BIO_free(out);
- ossl_raise(eDHError, NULL);
+ if (!PEM_write_bio_DHparams(out, dh)) {
+ BIO_free(out);
+ ossl_raise(ePKeyError, NULL);
}
str = ossl_membio2str(out);
return str;
}
+/*
+ * call-seq:
+ * dh.to_der -> aString
+ *
+ * Serializes the DH parameters to a DER-encoding
+ *
+ * Note that any existing per-session public/private keys will *not* get
+ * encoded, just the Diffie-Hellman parameters will be encoded.
+ *
+ * See also #public_to_der (X.509 SubjectPublicKeyInfo) and
+ * #private_to_der (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for
+ * serialization with the private or public key components.
+ */
static VALUE
ossl_dh_to_der(VALUE self)
-{
- EVP_PKEY *pkey;
+{
+ OSSL_3_const DH *dh;
unsigned char *p;
long len;
VALUE str;
- GetPKeyDH(self, pkey);
- if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0)
- ossl_raise(eDHError, NULL);
+ GetDH(self, dh);
+ if((len = i2d_DHparams(dh, NULL)) <= 0)
+ ossl_raise(ePKeyError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
- if(i2d_DHparams(pkey->pkey.dh, &p) < 0)
- ossl_raise(eDHError, NULL);
+ p = (unsigned char *)RSTRING_PTR(str);
+ if(i2d_DHparams(dh, &p) < 0)
+ ossl_raise(ePKeyError, NULL);
ossl_str_adjust(str, p);
return str;
}
/*
- * Stores all parameters of key to the hash
- * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
- * Don't use :-)) (I's up to you)
- */
-static VALUE
-ossl_dh_get_params(VALUE self)
-{
- EVP_PKEY *pkey;
- VALUE hash;
-
- GetPKeyDH(self, pkey);
-
- hash = rb_hash_new();
-
- rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dh->p));
- rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dh->g));
- rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dh->pub_key));
- rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dh->priv_key));
-
- return hash;
-}
-
-/*
- * Prints all parameters of key to buffer
- * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
- * Don't use :-)) (I's up to you)
- */
-static VALUE
-ossl_dh_to_text(VALUE self)
-{
- EVP_PKEY *pkey;
- BIO *out;
- VALUE str;
-
- GetPKeyDH(self, pkey);
- if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eDHError, NULL);
- }
- if (!DHparams_print(out, pkey->pkey.dh)) {
- BIO_free(out);
- ossl_raise(eDHError, NULL);
- }
- str = ossl_membio2str(out);
-
- return str;
-}
-
-/*
- * Makes new instance DH PUBLIC_KEY from PRIVATE_KEY
+ * call-seq:
+ * dh.params_ok? -> true | false
+ *
+ * Validates the Diffie-Hellman parameters associated with this instance.
+ * It checks whether a safe prime and a suitable generator are used. If this
+ * is not the case, +false+ is returned.
+ *
+ * See also the man page EVP_PKEY_param_check(3).
*/
static VALUE
-ossl_dh_to_public_key(VALUE self)
-{
- EVP_PKEY *pkey;
- DH *dh;
- VALUE obj;
-
- GetPKeyDH(self, pkey);
- dh = DHparams_dup(pkey->pkey.dh); /* err check perfomed by dh_instance */
- obj = dh_instance(CLASS_OF(self), dh);
- if (obj == Qfalse) {
- DH_free(dh);
- ossl_raise(eDHError, NULL);
- }
-
- return obj;
-}
-
-static VALUE
ossl_dh_check_params(VALUE self)
{
- DH *dh;
+ int ret;
+#ifdef HAVE_EVP_PKEY_CHECK
EVP_PKEY *pkey;
- int codes;
-
- GetPKeyDH(self, pkey);
- dh = pkey->pkey.dh;
-
- if (!DH_check(dh, &codes)) {
- return Qfalse;
- }
-
- return codes == 0 ? Qtrue : Qfalse;
-}
+ EVP_PKEY_CTX *pctx;
-static VALUE
-ossl_dh_generate_key(VALUE self)
-{
+ GetPKey(self, pkey);
+ pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
+ if (!pctx)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
+ ret = EVP_PKEY_param_check(pctx);
+ EVP_PKEY_CTX_free(pctx);
+#else
DH *dh;
- EVP_PKEY *pkey;
-
- GetPKeyDH(self, pkey);
- dh = pkey->pkey.dh;
-
- if (!DH_generate_key(dh))
- ossl_raise(eDHError, "Failed to generate key");
- return self;
-}
+ int codes;
-static VALUE
-ossl_dh_compute_key(VALUE self, VALUE pub)
-{
- DH *dh;
- EVP_PKEY *pkey;
- BIGNUM *pub_key;
- VALUE str;
- int len;
+ GetDH(self, dh);
+ ret = DH_check(dh, &codes) == 1 && codes == 0;
+#endif
- GetPKeyDH(self, pkey);
- dh = pkey->pkey.dh;
- pub_key = GetBNPtr(pub);
- len = DH_size(dh);
- str = rb_str_new(0, len);
- if ((len = DH_compute_key(RSTRING(str)->ptr, pub_key, dh)) < 0) {
- ossl_raise(eDHError, NULL);
+ if (ret == 1)
+ return Qtrue;
+ else {
+ /* DH_check_ex() will put error entry on failure */
+ ossl_clear_error();
+ return Qfalse;
}
- RSTRING(str)->len = len;
- RSTRING(str)->ptr[len] = 0;
-
- return str;
}
-OSSL_PKEY_BN(dh, p);
-OSSL_PKEY_BN(dh, g);
-OSSL_PKEY_BN(dh, pub_key);
-OSSL_PKEY_BN(dh, priv_key);
-
/*
- * -----BEGIN DH PARAMETERS-----
- * MEYCQQD0zXHljRg/mJ9PYLACLv58Cd8VxBxxY7oEuCeURMiTqEhMym16rhhKgZG2
- * zk2O9uUIBIxSj+NKMURHGaFKyIvLAgEC
- * -----END DH PARAMETERS-----
+ * Document-method: OpenSSL::PKey::DH#set_pqg
+ * call-seq:
+ * dh.set_pqg(p, q, g) -> self
+ *
+ * Sets _p_, _q_, _g_ to the DH instance.
*/
-static unsigned char DEFAULT_DH_512_PRIM[] = {
- 0xf4, 0xcd, 0x71, 0xe5, 0x8d, 0x18, 0x3f, 0x98,
- 0x9f, 0x4f, 0x60, 0xb0, 0x02, 0x2e, 0xfe, 0x7c,
- 0x09, 0xdf, 0x15, 0xc4, 0x1c, 0x71, 0x63, 0xba,
- 0x04, 0xb8, 0x27, 0x94, 0x44, 0xc8, 0x93, 0xa8,
- 0x48, 0x4c, 0xca, 0x6d, 0x7a, 0xae, 0x18, 0x4a,
- 0x81, 0x91, 0xb6, 0xce, 0x4d, 0x8e, 0xf6, 0xe5,
- 0x08, 0x04, 0x8c, 0x52, 0x8f, 0xe3, 0x4a, 0x31,
- 0x44, 0x47, 0x19, 0xa1, 0x4a, 0xc8, 0x8b, 0xcb,
-};
-static unsigned char DEFAULT_DH_512_GEN[] = { 0x02 };
-DH *OSSL_DEFAULT_DH_512 = NULL;
-
-/*
- * -----BEGIN DH PARAMETERS-----
- * MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ
- * AV/ZD2AWPbrTqV76mGRgJg4EddgT1zG0jq3rnFdMj2XzkBYx3BVvfR0Arnby0RHR
- * T4h7KZ/2zmjvV+eF8kBUHBJAojUlzxKj4QeO2x20FP9X5xmNUXeDAgEC
- * -----END DH PARAMETERS-----
+OSSL_PKEY_BN_DEF3(dh, DH, pqg, p, q, g)
+/*
+ * Document-method: OpenSSL::PKey::DH#set_key
+ * call-seq:
+ * dh.set_key(pub_key, priv_key) -> self
+ *
+ * Sets _pub_key_ and _priv_key_ for the DH instance. _priv_key_ may be +nil+.
*/
-static unsigned char DEFAULT_DH_1024_PRIM[] = {
- 0x9d, 0x25, 0x39, 0x5c, 0xb4, 0x54, 0x8a, 0xff,
- 0x25, 0xe6, 0xd6, 0x9f, 0x4c, 0xc3, 0xc1, 0x8d,
- 0xa1, 0xfa, 0xba, 0x88, 0x4c, 0x53, 0xa9, 0x74,
- 0xda, 0xfa, 0xba, 0x0b, 0x20, 0xbe, 0x40, 0xd7,
- 0xba, 0xe7, 0x1d, 0x70, 0x28, 0x61, 0x60, 0x4c,
- 0x49, 0x01, 0x5f, 0xd9, 0x0f, 0x60, 0x16, 0x3d,
- 0xba, 0xd3, 0xa9, 0x5e, 0xfa, 0x98, 0x64, 0x60,
- 0x26, 0x0e, 0x04, 0x75, 0xd8, 0x13, 0xd7, 0x31,
- 0xb4, 0x8e, 0xad, 0xeb, 0x9c, 0x57, 0x4c, 0x8f,
- 0x65, 0xf3, 0x90, 0x16, 0x31, 0xdc, 0x15, 0x6f,
- 0x7d, 0x1d, 0x00, 0xae, 0x76, 0xf2, 0xd1, 0x11,
- 0xd1, 0x4f, 0x88, 0x7b, 0x29, 0x9f, 0xf6, 0xce,
- 0x68, 0xef, 0x57, 0xe7, 0x85, 0xf2, 0x40, 0x54,
- 0x1c, 0x12, 0x40, 0xa2, 0x35, 0x25, 0xcf, 0x12,
- 0xa3, 0xe1, 0x07, 0x8e, 0xdb, 0x1d, 0xb4, 0x14,
- 0xff, 0x57, 0xe7, 0x19, 0x8d, 0x51, 0x77, 0x83
-};
-static unsigned char DEFAULT_DH_1024_GEN[] = { 0x02 };
-DH *OSSL_DEFAULT_DH_1024 = NULL;
-
-static DH*
-ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
-{
- DH *dh;
-
- if ((dh = DH_new()) == NULL) ossl_raise(eDHError, NULL);
- dh->p = BN_bin2bn(p, plen, NULL);
- dh->g = BN_bin2bn(g, glen, NULL);
- if (dh->p == NULL || dh->g == NULL){
- DH_free(dh);
- ossl_raise(eDHError, NULL);
- }
-
- return dh;
-}
+OSSL_PKEY_BN_DEF2(dh, DH, key, pub_key, priv_key)
/*
* INIT
*/
void
-Init_ossl_dh()
+Init_ossl_dh(void)
{
- eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError);
+ /* Document-class: OpenSSL::PKey::DH
+ *
+ * An implementation of the Diffie-Hellman key exchange protocol based on
+ * discrete logarithms in finite fields, the same basis that DSA is built
+ * on.
+ *
+ * === Accessor methods for the Diffie-Hellman parameters
+ * DH#p::
+ * The prime (an OpenSSL::BN) of the Diffie-Hellman parameters.
+ * DH#g::
+ * The generator (an OpenSSL::BN) g of the Diffie-Hellman parameters.
+ * DH#pub_key::
+ * The per-session public key (an OpenSSL::BN) matching the private key.
+ * This needs to be passed to DH#compute_key.
+ * DH#priv_key::
+ * The per-session private key, an OpenSSL::BN.
+ *
+ * === Example of a key exchange
+ * # you may send the parameters (der) and own public key (pub1) publicly
+ * # to the participating party
+ * dh1 = OpenSSL::PKey::DH.new(2048)
+ * der = dh1.to_der
+ * pub1 = dh1.pub_key
+ *
+ * # the other party generates its per-session key pair
+ * dhparams = OpenSSL::PKey::DH.new(der)
+ * dh2 = OpenSSL::PKey.generate_key(dhparams)
+ * pub2 = dh2.pub_key
+ *
+ * symm_key1 = dh1.compute_key(pub2)
+ * symm_key2 = dh2.compute_key(pub1)
+ * puts symm_key1 == symm_key2 # => true
+ */
cDH = rb_define_class_under(mPKey, "DH", cPKey);
- rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1);
rb_define_method(cDH, "initialize", ossl_dh_initialize, -1);
+#ifndef HAVE_EVP_PKEY_DUP
+ rb_define_method(cDH, "initialize_copy", ossl_dh_initialize_copy, 1);
+#endif
rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
rb_define_method(cDH, "private?", ossl_dh_is_private, 0);
- rb_define_method(cDH, "to_text", ossl_dh_to_text, 0);
rb_define_method(cDH, "export", ossl_dh_export, 0);
rb_define_alias(cDH, "to_pem", "export");
rb_define_alias(cDH, "to_s", "export");
rb_define_method(cDH, "to_der", ossl_dh_to_der, 0);
- rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0);
rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0);
- rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0);
- rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1);
+
DEF_OSSL_PKEY_BN(cDH, dh, p);
+ DEF_OSSL_PKEY_BN(cDH, dh, q);
DEF_OSSL_PKEY_BN(cDH, dh, g);
DEF_OSSL_PKEY_BN(cDH, dh, pub_key);
DEF_OSSL_PKEY_BN(cDH, dh, priv_key);
- rb_define_method(cDH, "params", ossl_dh_get_params, 0);
-
- OSSL_DEFAULT_DH_512 = ossl_create_dh(
- DEFAULT_DH_512_PRIM, sizeof(DEFAULT_DH_512_PRIM),
- DEFAULT_DH_512_GEN, sizeof(DEFAULT_DH_512_GEN));
- OSSL_DEFAULT_DH_1024 = ossl_create_dh(
- DEFAULT_DH_1024_PRIM, sizeof(DEFAULT_DH_1024_PRIM),
- DEFAULT_DH_1024_GEN, sizeof(DEFAULT_DH_1024_GEN));
+ rb_define_method(cDH, "set_pqg", ossl_dh_set_pqg, 3);
+ rb_define_method(cDH, "set_key", ossl_dh_set_key, 2);
}
#else /* defined NO_DH */
-# warning >>> OpenSSL is compiled without DH support <<<
void
-Init_ossl_dh()
+Init_ossl_dh(void)
{
- rb_warning("OpenSSL is compiled without DH support");
}
#endif /* NO_DH */
-
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 39b1902d57..041646a058 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -1,417 +1,371 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
-#if !defined(OPENSSL_NO_DSA)
-
#include "ossl.h"
+#if !defined(OPENSSL_NO_DSA)
+
#define GetPKeyDSA(obj, pkey) do { \
- GetPKey(obj, pkey); \
- if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) { /* PARANOIA? */ \
- ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \
+ GetPKey((obj), (pkey)); \
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DSA) { /* PARANOIA? */ \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \
} \
} while (0)
+#define GetDSA(obj, dsa) do { \
+ EVP_PKEY *_pkey; \
+ GetPKeyDSA((obj), _pkey); \
+ (dsa) = EVP_PKEY_get0_DSA(_pkey); \
+ if ((dsa) == NULL) \
+ ossl_raise(ePKeyError, "failed to get DSA from EVP_PKEY"); \
+} while (0)
+
+static inline int
+DSA_HAS_PRIVATE(OSSL_3_const DSA *dsa)
+{
+ const BIGNUM *bn;
+ DSA_get0_key(dsa, NULL, &bn);
+ return !!bn;
+}
-#define DSA_HAS_PRIVATE(dsa) ((dsa)->priv_key)
-#define DSA_PRIVATE(obj,dsa) (DSA_HAS_PRIVATE(dsa)||OSSL_PKEY_IS_PRIVATE(obj))
+static inline int
+DSA_PRIVATE(VALUE obj, OSSL_3_const DSA *dsa)
+{
+ return DSA_HAS_PRIVATE(dsa) || OSSL_PKEY_IS_PRIVATE(obj);
+}
/*
* Classes
*/
VALUE cDSA;
-VALUE eDSAError;
/*
- * Public
+ * Private
*/
-static VALUE
-dsa_instance(VALUE klass, DSA *dsa)
-{
- EVP_PKEY *pkey;
- VALUE obj;
-
- if (!dsa) {
- return Qfalse;
- }
- if (!(pkey = EVP_PKEY_new())) {
- return Qfalse;
- }
- if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
- EVP_PKEY_free(pkey);
- return Qfalse;
- }
- WrapPKey(klass, obj, pkey);
-
- return obj;
-}
-
-VALUE
-ossl_dsa_new(EVP_PKEY *pkey)
-{
- VALUE obj;
-
- if (!pkey) {
- obj = dsa_instance(cDSA, DSA_new());
- } else {
- if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) {
- ossl_raise(rb_eTypeError, "Not a DSA key!");
- }
- WrapPKey(cDSA, obj, pkey);
- }
- if (obj == Qfalse) {
- ossl_raise(eDSAError, NULL);
- }
-
- return obj;
-}
-
/*
- * Private
+ * call-seq:
+ * DSA.new -> dsa
+ * DSA.new(string [, pass]) -> dsa
+ * DSA.new(size) -> dsa
+ *
+ * Creates a new DSA instance by reading an existing key from _string_.
+ *
+ * If called without arguments, creates a new instance with no key components
+ * set. They can be set individually by #set_pqg and #set_key.
+ * This form is not compatible with OpenSSL 3.0 or later.
+ *
+ * If called with a String, tries to parse as DER or PEM encoding of a \DSA key.
+ * See also OpenSSL::PKey.read which can parse keys of any kinds.
+ *
+ * If called with a number, generates random parameters and a key pair. This
+ * form works as an alias of DSA.generate.
+ *
+ * +string+::
+ * A String that contains a DER or PEM encoded key.
+ * +pass+::
+ * A String that contains an optional password.
+ * +size+::
+ * See DSA.generate.
+ *
+ * Examples:
+ * p OpenSSL::PKey::DSA.new(1024)
+ * #=> #<OpenSSL::PKey::DSA:0x000055a8d6025bf0 oid=DSA>
+ *
+ * p OpenSSL::PKey::DSA.new(File.read('dsa.pem'))
+ * #=> #<OpenSSL::PKey::DSA:0x000055555d6b8110 oid=DSA>
+ *
+ * p OpenSSL::PKey::DSA.new(File.read('dsa.pem'), 'mypassword')
+ * #=> #<OpenSSL::PKey::DSA:0x0000556f973c40b8 oid=DSA>
*/
-static DSA *
-dsa_generate(int size)
-{
- DSA *dsa;
- unsigned char seed[20];
- int seed_len = 20, counter;
- unsigned long h;
-
- if (!RAND_bytes(seed, seed_len)) {
- return 0;
- }
- dsa = DSA_generate_parameters(size, seed, seed_len, &counter, &h,
- rb_block_given_p() ? ossl_generate_cb : NULL,
- NULL);
- if(!dsa) return 0;
-
- if (!DSA_generate_key(dsa)) {
- DSA_free(dsa);
- return 0;
- }
-
- return dsa;
-}
-
-static VALUE
-ossl_dsa_s_generate(VALUE klass, VALUE size)
-{
- DSA *dsa = dsa_generate(FIX2INT(size)); /* err handled by dsa_instance */
- VALUE obj = dsa_instance(klass, dsa);
-
- if (obj == Qfalse) {
- DSA_free(dsa);
- ossl_raise(eDSAError, NULL);
- }
-
- return obj;
-}
-
static VALUE
ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
DSA *dsa;
- BIO *in;
- char *passwd = NULL;
+ BIO *in = NULL;
VALUE arg, pass;
-
- GetPKey(self, pkey);
- if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
+ int type;
+
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
+
+ /* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
+ rb_scan_args(argc, argv, "02", &arg, &pass);
+ if (argc == 0) {
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ rb_raise(rb_eArgError, "OpenSSL::PKey::DSA.new cannot be called " \
+ "without arguments; pkeys are immutable with OpenSSL 3.0");
+#else
dsa = DSA_new();
- }
- else if (FIXNUM_P(arg)) {
- if (!(dsa = dsa_generate(FIX2INT(arg)))) {
- ossl_raise(eDSAError, NULL);
- }
- }
- else {
- if (!NIL_P(pass)) passwd = StringValuePtr(pass);
- arg = ossl_to_der_if_possible(arg);
- in = ossl_obj2bio(arg);
- dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
- if (!dsa) {
- BIO_reset(in);
- dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
- }
- if (!dsa) {
- BIO_reset(in);
- dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL);
- }
- if (!dsa) {
- BIO_reset(in);
- dsa = d2i_DSAPrivateKey_bio(in, NULL);
- }
- if (!dsa) {
- BIO_reset(in);
- dsa = d2i_DSA_PUBKEY_bio(in, NULL);
- }
- BIO_free(in);
- if (!dsa) ossl_raise(eDSAError, "Neither PUB key nor PRIV key:");
- }
- if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
- DSA_free(dsa);
- ossl_raise(eDSAError, NULL);
+ if (!dsa)
+ ossl_raise(ePKeyError, "DSA_new");
+ goto legacy;
+#endif
}
+ pass = ossl_pem_passwd_value(pass);
+ arg = ossl_to_der_if_possible(arg);
+ in = ossl_obj2bio(&arg);
+
+ /* DER-encoded DSAPublicKey format isn't supported by the generic routine */
+ dsa = (DSA *)PEM_ASN1_read_bio((d2i_of_void *)d2i_DSAPublicKey,
+ PEM_STRING_DSA_PUBLIC,
+ in, NULL, NULL, NULL);
+ if (dsa)
+ goto legacy;
+ OSSL_BIO_reset(in);
+
+ pkey = ossl_pkey_read_generic(in, pass);
+ BIO_free(in);
+ if (!pkey)
+ ossl_raise(ePKeyError, "Neither PUB key nor PRIV key");
+
+ type = EVP_PKEY_base_id(pkey);
+ if (type != EVP_PKEY_DSA) {
+ EVP_PKEY_free(pkey);
+ rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type));
+ }
+ RTYPEDDATA_DATA(self) = pkey;
return self;
-}
-
-static VALUE
-ossl_dsa_is_public(VALUE self)
-{
- EVP_PKEY *pkey;
-
- GetPKeyDSA(self, pkey);
-
- /*
- * Do we need to check dsap->dsa->public_pkey?
- * return Qtrue;
- */
- return (pkey->pkey.dsa->pub_key) ? Qtrue : Qfalse;
-}
-static VALUE
-ossl_dsa_is_private(VALUE self)
-{
- EVP_PKEY *pkey;
-
- GetPKeyDSA(self, pkey);
-
- return (DSA_PRIVATE(self, pkey->pkey.dsa)) ? Qtrue : Qfalse;
+ legacy:
+ BIO_free(in);
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa) != 1) {
+ EVP_PKEY_free(pkey);
+ DSA_free(dsa);
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_DSA");
+ }
+ RTYPEDDATA_DATA(self) = pkey;
+ return self;
}
+#ifndef HAVE_EVP_PKEY_DUP
+/* :nodoc: */
static VALUE
-ossl_dsa_export(int argc, VALUE *argv, VALUE self)
+ossl_dsa_initialize_copy(VALUE self, VALUE other)
{
EVP_PKEY *pkey;
- BIO *out;
- const EVP_CIPHER *ciph = NULL;
- char *passwd = NULL;
- VALUE cipher, pass, str;
-
- GetPKeyDSA(self, pkey);
- rb_scan_args(argc, argv, "02", &cipher, &pass);
- if (!NIL_P(cipher)) {
- ciph = GetCipherPtr(cipher);
- if (!NIL_P(pass)) {
- passwd = StringValuePtr(pass);
- }
+ DSA *dsa, *dsa_new;
+
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
+ GetDSA(other, dsa);
+
+ dsa_new = (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey,
+ (d2i_of_void *)d2i_DSAPrivateKey,
+ (char *)dsa);
+ if (!dsa_new)
+ ossl_raise(ePKeyError, "ASN1_dup");
+
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa_new) != 1) {
+ EVP_PKEY_free(pkey);
+ DSA_free(dsa_new);
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_DSA");
}
- if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eDSAError, NULL);
- }
- if (DSA_HAS_PRIVATE(pkey->pkey.dsa)) {
- if (!PEM_write_bio_DSAPrivateKey(out, pkey->pkey.dsa, ciph,
- NULL, 0, ossl_pem_passwd_cb, passwd)){
- BIO_free(out);
- ossl_raise(eDSAError, NULL);
- }
- } else {
- if (!PEM_write_bio_DSAPublicKey(out, pkey->pkey.dsa)) {
- BIO_free(out);
- ossl_raise(eDSAError, NULL);
- }
- }
- str = ossl_membio2str(out);
-
- return str;
-}
+ RTYPEDDATA_DATA(self) = pkey;
-static VALUE
-ossl_dsa_to_der(VALUE self)
-{
- EVP_PKEY *pkey;
- int (*i2d_func)_((DSA*, unsigned char**));
- unsigned char *p;
- long len;
- VALUE str;
-
- GetPKeyDSA(self, pkey);
- if(DSA_HAS_PRIVATE(pkey->pkey.dsa))
- i2d_func = (int(*)_((DSA*,unsigned char**)))i2d_DSAPrivateKey;
- else
- i2d_func = i2d_DSA_PUBKEY;
- if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0)
- ossl_raise(eDSAError, NULL);
- str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
- if(i2d_func(pkey->pkey.dsa, &p) < 0)
- ossl_raise(eDSAError, NULL);
- ossl_str_adjust(str, p);
-
- return str;
+ return self;
}
+#endif
/*
- * Stores all parameters of key to the hash
- * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
- * Don't use :-)) (I's up to you)
+ * call-seq:
+ * dsa.public? -> true | false
+ *
+ * Indicates whether this DSA instance has a public key associated with it or
+ * not. The public key may be retrieved with DSA#public_key.
*/
static VALUE
-ossl_dsa_get_params(VALUE self)
+ossl_dsa_is_public(VALUE self)
{
- EVP_PKEY *pkey;
- VALUE hash;
-
- GetPKeyDSA(self, pkey);
+ const DSA *dsa;
+ const BIGNUM *bn;
- hash = rb_hash_new();
+ GetDSA(self, dsa);
+ DSA_get0_key(dsa, &bn, NULL);
- rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dsa->p));
- rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.dsa->q));
- rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dsa->g));
- rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dsa->pub_key));
- rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dsa->priv_key));
-
- return hash;
+ return bn ? Qtrue : Qfalse;
}
/*
- * Prints all parameters of key to buffer
- * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
- * Don't use :-)) (I's up to you)
+ * call-seq:
+ * dsa.private? -> true | false
+ *
+ * Indicates whether this DSA instance has a private key associated with it or
+ * not. The private key may be retrieved with DSA#private_key.
*/
static VALUE
-ossl_dsa_to_text(VALUE self)
+ossl_dsa_is_private(VALUE self)
{
- EVP_PKEY *pkey;
- BIO *out;
- VALUE str;
+ OSSL_3_const DSA *dsa;
- GetPKeyDSA(self, pkey);
- if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eDSAError, NULL);
- }
- if (!DSA_print(out, pkey->pkey.dsa, 0)) { /* offset = 0 */
- BIO_free(out);
- ossl_raise(eDSAError, NULL);
- }
- str = ossl_membio2str(out);
+ GetDSA(self, dsa);
- return str;
+ return DSA_PRIVATE(self, dsa) ? Qtrue : Qfalse;
}
/*
- * Makes new instance DSA PUBLIC_KEY from PRIVATE_KEY
+ * call-seq:
+ * dsa.export([cipher, password]) -> aString
+ * dsa.to_pem([cipher, password]) -> aString
+ * dsa.to_s([cipher, password]) -> aString
+ *
+ * Serializes a private or public key to a PEM-encoding.
+ *
+ * [When the key contains public components only]
+ *
+ * Serializes it into an X.509 SubjectPublicKeyInfo.
+ * The parameters _cipher_ and _password_ are ignored.
+ *
+ * A PEM-encoded key will look like:
+ *
+ * -----BEGIN PUBLIC KEY-----
+ * [...]
+ * -----END PUBLIC KEY-----
+ *
+ * Consider using #public_to_pem instead. This serializes the key into an
+ * X.509 SubjectPublicKeyInfo regardless of whether it is a public key
+ * or a private key.
+ *
+ * [When the key contains private components, and no parameters are given]
+ *
+ * Serializes it into a traditional \OpenSSL DSAPrivateKey.
+ *
+ * A PEM-encoded key will look like:
+ *
+ * -----BEGIN DSA PRIVATE KEY-----
+ * [...]
+ * -----END DSA PRIVATE KEY-----
+ *
+ * [When the key contains private components, and _cipher_ and _password_ are given]
+ *
+ * Serializes it into a traditional \OpenSSL DSAPrivateKey and encrypts it in
+ * OpenSSL's traditional PEM encryption format.
+ * _cipher_ must be a cipher name understood by OpenSSL::Cipher.new or an
+ * instance of OpenSSL::Cipher.
+ *
+ * An encrypted PEM-encoded key will look like:
+ *
+ * -----BEGIN DSA PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0
+ *
+ * [...]
+ * -----END DSA PRIVATE KEY-----
+ *
+ * Note that this format uses MD5 to derive the encryption key, and hence
+ * will not be available on FIPS-compliant systems.
+ *
+ * <b>This method is kept for compatibility.</b>
+ * This should only be used when the traditional, non-standard \OpenSSL format
+ * is required.
+ *
+ * Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem
+ * (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead.
*/
static VALUE
-ossl_dsa_to_public_key(VALUE self)
-{
- EVP_PKEY *pkey;
- DSA *dsa;
- VALUE obj;
-
- GetPKeyDSA(self, pkey);
- /* err check performed by dsa_instance */
- dsa = DSAPublicKey_dup(pkey->pkey.dsa);
- obj = dsa_instance(CLASS_OF(self), dsa);
- if (obj == Qfalse) {
- DSA_free(dsa);
- ossl_raise(eDSAError, NULL);
- }
- return obj;
-}
-
-#define ossl_dsa_buf_size(pkey) (DSA_size((pkey)->pkey.dsa)+16)
-
-static VALUE
-ossl_dsa_sign(VALUE self, VALUE data)
+ossl_dsa_export(int argc, VALUE *argv, VALUE self)
{
- EVP_PKEY *pkey;
- int buf_len;
- VALUE str;
-
- GetPKeyDSA(self, pkey);
- StringValue(data);
- if (!DSA_PRIVATE(self, pkey->pkey.dsa)) {
- ossl_raise(eDSAError, "Private DSA key needed!");
- }
- str = rb_str_new(0, ossl_dsa_buf_size(pkey));
- if (!DSA_sign(0, RSTRING(data)->ptr, RSTRING(data)->len, RSTRING(str)->ptr,
- &buf_len, pkey->pkey.dsa)) { /* type is ignored (0) */
- ossl_raise(eDSAError, NULL);
- }
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ OSSL_3_const DSA *dsa;
- return str;
+ GetDSA(self, dsa);
+ if (DSA_HAS_PRIVATE(dsa))
+ return ossl_pkey_export_traditional(argc, argv, self, 0);
+ else
+ return ossl_pkey_export_spki(self, 0);
}
+/*
+ * call-seq:
+ * dsa.to_der -> aString
+ *
+ * Serializes a private or public key to a DER-encoding.
+ *
+ * See #to_pem for details.
+ *
+ * <b>This method is kept for compatibility.</b>
+ * This should only be used when the traditional, non-standard \OpenSSL format
+ * is required.
+ *
+ * Consider using #public_to_der or #private_to_der instead.
+ */
static VALUE
-ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
+ossl_dsa_to_der(VALUE self)
{
- EVP_PKEY *pkey;
- int ret;
-
- GetPKeyDSA(self, pkey);
- StringValue(digest);
- StringValue(sig);
- /* type is ignored (0) */
- ret = DSA_verify(0, RSTRING(digest)->ptr, RSTRING(digest)->len,
- RSTRING(sig)->ptr, RSTRING(sig)->len, pkey->pkey.dsa);
- if (ret < 0) {
- ossl_raise(eDSAError, NULL);
- }
- else if (ret == 1) {
- return Qtrue;
- }
+ OSSL_3_const DSA *dsa;
- return Qfalse;
+ GetDSA(self, dsa);
+ if (DSA_HAS_PRIVATE(dsa))
+ return ossl_pkey_export_traditional(0, NULL, self, 1);
+ else
+ return ossl_pkey_export_spki(self, 1);
}
-OSSL_PKEY_BN(dsa, p);
-OSSL_PKEY_BN(dsa, q);
-OSSL_PKEY_BN(dsa, g);
-OSSL_PKEY_BN(dsa, pub_key);
-OSSL_PKEY_BN(dsa, priv_key);
+
+/*
+ * Document-method: OpenSSL::PKey::DSA#set_pqg
+ * call-seq:
+ * dsa.set_pqg(p, q, g) -> self
+ *
+ * Sets _p_, _q_, _g_ to the DSA instance.
+ */
+OSSL_PKEY_BN_DEF3(dsa, DSA, pqg, p, q, g)
+/*
+ * Document-method: OpenSSL::PKey::DSA#set_key
+ * call-seq:
+ * dsa.set_key(pub_key, priv_key) -> self
+ *
+ * Sets _pub_key_ and _priv_key_ for the DSA instance. _priv_key_ may be +nil+.
+ */
+OSSL_PKEY_BN_DEF2(dsa, DSA, key, pub_key, priv_key)
/*
* INIT
*/
void
-Init_ossl_dsa()
+Init_ossl_dsa(void)
{
- eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError);
-
+ /* Document-class: OpenSSL::PKey::DSA
+ *
+ * DSA, the Digital Signature Algorithm, is specified in NIST's
+ * FIPS 186-3. It is an asymmetric public key algorithm that may be used
+ * similar to e.g. RSA.
+ */
cDSA = rb_define_class_under(mPKey, "DSA", cPKey);
-
- rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1);
+
rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1);
+#ifndef HAVE_EVP_PKEY_DUP
+ rb_define_method(cDSA, "initialize_copy", ossl_dsa_initialize_copy, 1);
+#endif
rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0);
rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0);
- rb_define_method(cDSA, "to_text", ossl_dsa_to_text, 0);
rb_define_method(cDSA, "export", ossl_dsa_export, -1);
rb_define_alias(cDSA, "to_pem", "export");
rb_define_alias(cDSA, "to_s", "export");
rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0);
- rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0);
- rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1);
- rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2);
DEF_OSSL_PKEY_BN(cDSA, dsa, p);
DEF_OSSL_PKEY_BN(cDSA, dsa, q);
DEF_OSSL_PKEY_BN(cDSA, dsa, g);
DEF_OSSL_PKEY_BN(cDSA, dsa, pub_key);
DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key);
-
- rb_define_method(cDSA, "params", ossl_dsa_get_params, 0);
+ rb_define_method(cDSA, "set_pqg", ossl_dsa_set_pqg, 3);
+ rb_define_method(cDSA, "set_key", ossl_dsa_set_key, 2);
}
#else /* defined NO_DSA */
-# warning >>> OpenSSL is compiled without DSA support <<<
-
void
-Init_ossl_dsa()
+Init_ossl_dsa(void)
{
- rb_warning("OpenSSL is compiled without DSA support");
}
-
#endif /* NO_DSA */
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
new file mode 100644
index 0000000000..35f031819d
--- /dev/null
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -0,0 +1,1655 @@
+/*
+ * Copyright (C) 2006-2007 Technorama Ltd. <oss-ruby@technorama.net>
+ */
+
+#include "ossl.h"
+
+#if !defined(OPENSSL_NO_EC)
+
+#define EXPORT_PEM 0
+#define EXPORT_DER 1
+
+static const rb_data_type_t ossl_ec_group_type;
+static const rb_data_type_t ossl_ec_point_type;
+
+#define GetPKeyEC(obj, pkey) do { \
+ GetPKey((obj), (pkey)); \
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \
+ } \
+} while (0)
+#define GetEC(obj, key) do { \
+ EVP_PKEY *_pkey; \
+ GetPKeyEC(obj, _pkey); \
+ (key) = EVP_PKEY_get0_EC_KEY(_pkey); \
+ if ((key) == NULL) \
+ ossl_raise(ePKeyError, "failed to get EC_KEY from EVP_PKEY"); \
+} while (0)
+
+#define GetECGroup(obj, group) do { \
+ TypedData_Get_Struct(obj, EC_GROUP, &ossl_ec_group_type, group); \
+ if ((group) == NULL) \
+ ossl_raise(eEC_GROUP, "EC_GROUP is not initialized"); \
+} while (0)
+
+#define GetECPoint(obj, point) do { \
+ TypedData_Get_Struct(obj, EC_POINT, &ossl_ec_point_type, point); \
+ if ((point) == NULL) \
+ ossl_raise(eEC_POINT, "EC_POINT is not initialized"); \
+} while (0)
+#define GetECPointGroup(obj, group) do { \
+ VALUE _group = rb_attr_get(obj, id_i_group); \
+ GetECGroup(_group, group); \
+} while (0)
+
+VALUE cEC;
+static VALUE cEC_GROUP;
+static VALUE eEC_GROUP;
+static VALUE cEC_POINT;
+static VALUE eEC_POINT;
+
+static VALUE sym_GFp, sym_GF2m;
+static VALUE sym_uncompressed, sym_compressed, sym_hybrid;
+
+static ID id_i_group;
+
+static VALUE ec_group_new(const EC_GROUP *group);
+static VALUE ec_point_new(const EC_POINT *point, const EC_GROUP *group);
+
+/*
+ * Creates a new EC_KEY on the EC group obj. arg can be an EC::Group or a String
+ * representing an OID.
+ */
+static EC_KEY *
+ec_key_new_from_group(VALUE arg)
+{
+ EC_KEY *ec;
+
+ if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
+ EC_GROUP *group;
+
+ GetECGroup(arg, group);
+ if (!(ec = EC_KEY_new()))
+ ossl_raise(ePKeyError, NULL);
+
+ if (!EC_KEY_set_group(ec, group)) {
+ EC_KEY_free(ec);
+ ossl_raise(ePKeyError, NULL);
+ }
+ } else {
+ int nid = OBJ_sn2nid(StringValueCStr(arg));
+
+ if (nid == NID_undef)
+ ossl_raise(ePKeyError, "invalid curve name");
+
+ if (!(ec = EC_KEY_new_by_curve_name(nid)))
+ ossl_raise(ePKeyError, NULL);
+
+ EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
+ EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
+ }
+
+ return ec;
+}
+
+/*
+ * call-seq:
+ * EC.generate(ec_group) -> ec
+ * EC.generate(string) -> ec
+ *
+ * Creates a new EC instance with a new random private and public key.
+ */
+static VALUE
+ossl_ec_key_s_generate(VALUE klass, VALUE arg)
+{
+ EVP_PKEY *pkey;
+ EC_KEY *ec;
+ VALUE obj;
+
+ obj = rb_obj_alloc(klass);
+
+ ec = ec_key_new_from_group(arg);
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) {
+ EVP_PKEY_free(pkey);
+ EC_KEY_free(ec);
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_EC_KEY");
+ }
+ RTYPEDDATA_DATA(obj) = pkey;
+
+ if (!EC_KEY_generate_key(ec))
+ ossl_raise(ePKeyError, "EC_KEY_generate_key");
+
+ return obj;
+}
+
+/*
+ * call-seq:
+ * OpenSSL::PKey::EC.new
+ * OpenSSL::PKey::EC.new(ec_key)
+ * OpenSSL::PKey::EC.new(ec_group)
+ * OpenSSL::PKey::EC.new("secp112r1")
+ * OpenSSL::PKey::EC.new(pem_string [, pwd])
+ * OpenSSL::PKey::EC.new(der_string)
+ *
+ * Creates a new EC object from given arguments.
+ */
+static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ EC_KEY *ec;
+ BIO *in;
+ VALUE arg, pass;
+ int type;
+
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
+
+ rb_scan_args(argc, argv, "02", &arg, &pass);
+ if (NIL_P(arg)) {
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ rb_raise(rb_eArgError, "OpenSSL::PKey::EC.new cannot be called " \
+ "without arguments; pkeys are immutable with OpenSSL 3.0");
+#else
+ if (!(ec = EC_KEY_new()))
+ ossl_raise(ePKeyError, "EC_KEY_new");
+ goto legacy;
+#endif
+ }
+ else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
+ ec = ec_key_new_from_group(arg);
+ goto legacy;
+ }
+
+ pass = ossl_pem_passwd_value(pass);
+ arg = ossl_to_der_if_possible(arg);
+ in = ossl_obj2bio(&arg);
+
+ pkey = ossl_pkey_read_generic(in, pass);
+ BIO_free(in);
+ if (!pkey) {
+ ossl_clear_error();
+ ec = ec_key_new_from_group(arg);
+ goto legacy;
+ }
+
+ type = EVP_PKEY_base_id(pkey);
+ if (type != EVP_PKEY_EC) {
+ EVP_PKEY_free(pkey);
+ rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type));
+ }
+ RTYPEDDATA_DATA(self) = pkey;
+ return self;
+
+ legacy:
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) {
+ EVP_PKEY_free(pkey);
+ EC_KEY_free(ec);
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_EC_KEY");
+ }
+ RTYPEDDATA_DATA(self) = pkey;
+ return self;
+}
+
+#ifndef HAVE_EVP_PKEY_DUP
+/* :nodoc: */
+static VALUE
+ossl_ec_key_initialize_copy(VALUE self, VALUE other)
+{
+ EVP_PKEY *pkey;
+ EC_KEY *ec, *ec_new;
+
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
+ GetEC(other, ec);
+
+ ec_new = EC_KEY_dup(ec);
+ if (!ec_new)
+ ossl_raise(ePKeyError, "EC_KEY_dup");
+
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec_new) != 1) {
+ EC_KEY_free(ec_new);
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_EC_KEY");
+ }
+ RTYPEDDATA_DATA(self) = pkey;
+
+ return self;
+}
+#endif
+
+/*
+ * call-seq:
+ * key.group => group
+ *
+ * Returns the EC::Group that the key is associated with. Modifying the returned
+ * group does not affect _key_.
+ */
+static VALUE
+ossl_ec_key_get_group(VALUE self)
+{
+ OSSL_3_const EC_KEY *ec;
+ const EC_GROUP *group;
+
+ GetEC(self, ec);
+ group = EC_KEY_get0_group(ec);
+ if (!group)
+ return Qnil;
+
+ return ec_group_new(group);
+}
+
+/*
+ * call-seq:
+ * key.group = group
+ *
+ * Sets the EC::Group for the key. The group structure is internally copied so
+ * modification to _group_ after assigning to a key has no effect on the key.
+ */
+static VALUE
+ossl_ec_key_set_group(VALUE self, VALUE group_v)
+{
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
+#else
+ EC_KEY *ec;
+ EC_GROUP *group;
+
+ GetEC(self, ec);
+ GetECGroup(group_v, group);
+
+ if (EC_KEY_set_group(ec, group) != 1)
+ ossl_raise(ePKeyError, "EC_KEY_set_group");
+
+ return group_v;
+#endif
+}
+
+/*
+ * call-seq:
+ * key.private_key => OpenSSL::BN
+ *
+ * See the OpenSSL documentation for EC_KEY_get0_private_key()
+ */
+static VALUE ossl_ec_key_get_private_key(VALUE self)
+{
+ OSSL_3_const EC_KEY *ec;
+ const BIGNUM *bn;
+
+ GetEC(self, ec);
+ if ((bn = EC_KEY_get0_private_key(ec)) == NULL)
+ return Qnil;
+
+ return ossl_bn_new(bn);
+}
+
+/*
+ * call-seq:
+ * key.private_key = openssl_bn
+ *
+ * See the OpenSSL documentation for EC_KEY_set_private_key()
+ */
+static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
+{
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
+#else
+ EC_KEY *ec;
+ BIGNUM *bn = NULL;
+
+ GetEC(self, ec);
+ if (!NIL_P(private_key))
+ bn = GetBNPtr(private_key);
+
+ switch (EC_KEY_set_private_key(ec, bn)) {
+ case 1:
+ break;
+ case 0:
+ if (bn == NULL)
+ break;
+ /* fallthrough */
+ default:
+ ossl_raise(ePKeyError, "EC_KEY_set_private_key");
+ }
+
+ return private_key;
+#endif
+}
+
+/*
+ * call-seq:
+ * key.public_key => OpenSSL::PKey::EC::Point
+ *
+ * See the OpenSSL documentation for EC_KEY_get0_public_key()
+ */
+static VALUE ossl_ec_key_get_public_key(VALUE self)
+{
+ OSSL_3_const EC_KEY *ec;
+ const EC_POINT *point;
+
+ GetEC(self, ec);
+ if ((point = EC_KEY_get0_public_key(ec)) == NULL)
+ return Qnil;
+
+ return ec_point_new(point, EC_KEY_get0_group(ec));
+}
+
+/*
+ * call-seq:
+ * key.public_key = ec_point
+ *
+ * See the OpenSSL documentation for EC_KEY_set_public_key()
+ */
+static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
+{
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
+#else
+ EC_KEY *ec;
+ EC_POINT *point = NULL;
+
+ GetEC(self, ec);
+ if (!NIL_P(public_key))
+ GetECPoint(public_key, point);
+
+ switch (EC_KEY_set_public_key(ec, point)) {
+ case 1:
+ break;
+ case 0:
+ if (point == NULL)
+ break;
+ /* fallthrough */
+ default:
+ ossl_raise(ePKeyError, "EC_KEY_set_public_key");
+ }
+
+ return public_key;
+#endif
+}
+
+/*
+ * call-seq:
+ * key.public? => true or false
+ *
+ * Returns whether this EC instance has a public key. The public key
+ * (EC::Point) can be retrieved with EC#public_key.
+ */
+static VALUE ossl_ec_key_is_public(VALUE self)
+{
+ OSSL_3_const EC_KEY *ec;
+
+ GetEC(self, ec);
+
+ return EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * key.private? => true or false
+ *
+ * Returns whether this EC instance has a private key. The private key (BN) can
+ * be retrieved with EC#private_key.
+ */
+static VALUE ossl_ec_key_is_private(VALUE self)
+{
+ OSSL_3_const EC_KEY *ec;
+
+ GetEC(self, ec);
+
+ return EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * key.export([cipher, password]) => String
+ * key.to_pem([cipher, password]) => String
+ *
+ * Serializes a private or public key to a PEM-encoding.
+ *
+ * [When the key contains public components only]
+ *
+ * Serializes it into an X.509 SubjectPublicKeyInfo.
+ * The parameters _cipher_ and _password_ are ignored.
+ *
+ * A PEM-encoded key will look like:
+ *
+ * -----BEGIN PUBLIC KEY-----
+ * [...]
+ * -----END PUBLIC KEY-----
+ *
+ * Consider using #public_to_pem instead. This serializes the key into an
+ * X.509 SubjectPublicKeyInfo regardless of whether it is a public key
+ * or a private key.
+ *
+ * [When the key contains private components, and no parameters are given]
+ *
+ * Serializes it into a SEC 1/RFC 5915 ECPrivateKey.
+ *
+ * A PEM-encoded key will look like:
+ *
+ * -----BEGIN EC PRIVATE KEY-----
+ * [...]
+ * -----END EC PRIVATE KEY-----
+ *
+ * [When the key contains private components, and _cipher_ and _password_ are given]
+ *
+ * Serializes it into a SEC 1/RFC 5915 ECPrivateKey
+ * and encrypts it in OpenSSL's traditional PEM encryption format.
+ * _cipher_ must be a cipher name understood by OpenSSL::Cipher.new or an
+ * instance of OpenSSL::Cipher.
+ *
+ * An encrypted PEM-encoded key will look like:
+ *
+ * -----BEGIN EC PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0
+ *
+ * [...]
+ * -----END EC PRIVATE KEY-----
+ *
+ * Note that this format uses MD5 to derive the encryption key, and hence
+ * will not be available on FIPS-compliant systems.
+ *
+ * <b>This method is kept for compatibility.</b>
+ * This should only be used when the SEC 1/RFC 5915 ECPrivateKey format is
+ * required.
+ *
+ * Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem
+ * (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead.
+ */
+static VALUE
+ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
+{
+ OSSL_3_const EC_KEY *ec;
+
+ GetEC(self, ec);
+ if (EC_KEY_get0_public_key(ec) == NULL)
+ ossl_raise(ePKeyError, "can't export - no public key set");
+ if (EC_KEY_get0_private_key(ec))
+ return ossl_pkey_export_traditional(argc, argv, self, 0);
+ else
+ return ossl_pkey_export_spki(self, 0);
+}
+
+/*
+ * call-seq:
+ * key.to_der => String
+ *
+ * Serializes a private or public key to a DER-encoding.
+ *
+ * See #to_pem for details.
+ *
+ * <b>This method is kept for compatibility.</b>
+ * This should only be used when the SEC 1/RFC 5915 ECPrivateKey format is
+ * required.
+ *
+ * Consider using #public_to_der or #private_to_der instead.
+ */
+static VALUE
+ossl_ec_key_to_der(VALUE self)
+{
+ OSSL_3_const EC_KEY *ec;
+
+ GetEC(self, ec);
+ if (EC_KEY_get0_public_key(ec) == NULL)
+ ossl_raise(ePKeyError, "can't export - no public key set");
+ if (EC_KEY_get0_private_key(ec))
+ return ossl_pkey_export_traditional(0, NULL, self, 1);
+ else
+ return ossl_pkey_export_spki(self, 1);
+}
+/*
+ * call-seq:
+ * key.generate_key! => self
+ *
+ * Generates a new random private and public key.
+ *
+ * See also the OpenSSL documentation for EC_KEY_generate_key()
+ *
+ * === Example
+ * ec = OpenSSL::PKey::EC.new("prime256v1")
+ * p ec.private_key # => nil
+ * ec.generate_key!
+ * p ec.private_key # => #<OpenSSL::BN XXXXXX>
+ */
+static VALUE ossl_ec_key_generate_key(VALUE self)
+{
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
+#else
+ EC_KEY *ec;
+
+ GetEC(self, ec);
+ if (EC_KEY_generate_key(ec) != 1)
+ ossl_raise(ePKeyError, "EC_KEY_generate_key");
+
+ return self;
+#endif
+}
+
+/*
+ * call-seq:
+ * key.check_key => true
+ *
+ * Raises an exception if the key is invalid.
+ *
+ * See also the man page EVP_PKEY_public_check(3).
+ */
+static VALUE ossl_ec_key_check_key(VALUE self)
+{
+#ifdef HAVE_EVP_PKEY_CHECK
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *pctx;
+ const EC_KEY *ec;
+
+ GetPKey(self, pkey);
+ GetEC(self, ec);
+ pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
+ if (!pctx)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
+
+ if (EC_KEY_get0_private_key(ec) != NULL) {
+ if (EVP_PKEY_check(pctx) != 1) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_check");
+ }
+ }
+ else {
+ if (EVP_PKEY_public_check(pctx) != 1) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(ePKeyError, "EVP_PKEY_public_check");
+ }
+ }
+
+ EVP_PKEY_CTX_free(pctx);
+#else
+ EC_KEY *ec;
+
+ GetEC(self, ec);
+ if (EC_KEY_check_key(ec) != 1)
+ ossl_raise(ePKeyError, "EC_KEY_check_key");
+#endif
+
+ return Qtrue;
+}
+
+/*
+ * OpenSSL::PKey::EC::Group
+ */
+static void
+ossl_ec_group_free(void *ptr)
+{
+ EC_GROUP_free(ptr);
+}
+
+static const rb_data_type_t ossl_ec_group_type = {
+ "OpenSSL/ec_group",
+ {
+ 0, ossl_ec_group_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static VALUE
+ossl_ec_group_alloc(VALUE klass)
+{
+ return TypedData_Wrap_Struct(klass, &ossl_ec_group_type, NULL);
+}
+
+static VALUE
+ec_group_new(const EC_GROUP *group)
+{
+ VALUE obj;
+ EC_GROUP *group_new;
+
+ obj = ossl_ec_group_alloc(cEC_GROUP);
+ group_new = EC_GROUP_dup(group);
+ if (!group_new)
+ ossl_raise(eEC_GROUP, "EC_GROUP_dup");
+ RTYPEDDATA_DATA(obj) = group_new;
+
+ return obj;
+}
+
+/*
+ * call-seq:
+ * OpenSSL::PKey::EC::Group.new(ec_group)
+ * OpenSSL::PKey::EC::Group.new(pem_or_der_encoded)
+ * OpenSSL::PKey::EC::Group.new(:GFp, bignum_p, bignum_a, bignum_b)
+ * OpenSSL::PKey::EC::Group.new(:GF2m, bignum_p, bignum_a, bignum_b)
+ *
+ * Creates a new EC::Group object.
+ *
+ * If the first argument is :GFp or :GF2m, creates a new curve with given
+ * parameters.
+ */
+static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE arg1, arg2, arg3, arg4;
+ EC_GROUP *group;
+
+ TypedData_Get_Struct(self, EC_GROUP, &ossl_ec_group_type, group);
+ if (group)
+ ossl_raise(rb_eRuntimeError, "EC_GROUP is already initialized");
+
+ switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) {
+ case 1:
+ if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
+ const EC_GROUP *arg1_group;
+
+ GetECGroup(arg1, arg1_group);
+ if ((group = EC_GROUP_dup(arg1_group)) == NULL)
+ ossl_raise(eEC_GROUP, "EC_GROUP_dup");
+ } else {
+ BIO *in = ossl_obj2bio(&arg1);
+
+ group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
+ if (!group) {
+ OSSL_BIO_reset(in);
+ group = d2i_ECPKParameters_bio(in, NULL);
+ }
+
+ BIO_free(in);
+
+ if (!group) {
+ const char *name = StringValueCStr(arg1);
+ int nid = OBJ_sn2nid(name);
+
+ ossl_clear_error(); /* ignore errors in d2i_ECPKParameters_bio() */
+ if (nid == NID_undef)
+ ossl_raise(eEC_GROUP, "unknown curve name (%"PRIsVALUE")", arg1);
+#if !defined(OPENSSL_IS_AWSLC)
+ group = EC_GROUP_new_by_curve_name(nid);
+#else /* EC_GROUPs are static and immutable by default in AWS-LC. */
+ group = EC_GROUP_new_by_curve_name_mutable(nid);
+#endif
+ if (group == NULL)
+ ossl_raise(eEC_GROUP, "unable to create curve (%"PRIsVALUE")", arg1);
+
+ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+ EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
+ }
+ }
+
+ break;
+ case 4:
+ if (SYMBOL_P(arg1)) {
+ EC_GROUP *(*new_curve)(const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *) = NULL;
+ const BIGNUM *p = GetBNPtr(arg2);
+ const BIGNUM *a = GetBNPtr(arg3);
+ const BIGNUM *b = GetBNPtr(arg4);
+
+ if (arg1 == sym_GFp) {
+ new_curve = EC_GROUP_new_curve_GFp;
+ }
+#if !defined(OPENSSL_NO_EC2M)
+ else if (arg1 == sym_GF2m) {
+ new_curve = EC_GROUP_new_curve_GF2m;
+ }
+#endif
+ else {
+ ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
+ }
+
+ if ((group = new_curve(p, a, b, ossl_bn_ctx)) == NULL)
+ ossl_raise(eEC_GROUP, "EC_GROUP_new_by_GF*");
+ } else {
+ ossl_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
+ }
+
+ break;
+ default:
+ ossl_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1 or 4)", argc);
+ }
+
+ ASSUME(group);
+ RTYPEDDATA_DATA(self) = group;
+
+ return self;
+}
+
+/* :nodoc: */
+static VALUE
+ossl_ec_group_initialize_copy(VALUE self, VALUE other)
+{
+ EC_GROUP *group, *group_new;
+
+ TypedData_Get_Struct(self, EC_GROUP, &ossl_ec_group_type, group_new);
+ if (group_new)
+ ossl_raise(eEC_GROUP, "EC::Group already initialized");
+ GetECGroup(other, group);
+
+ group_new = EC_GROUP_dup(group);
+ if (!group_new)
+ ossl_raise(eEC_GROUP, "EC_GROUP_dup");
+ RTYPEDDATA_DATA(self) = group_new;
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * group1.eql?(group2) => true | false
+ * group1 == group2 => true | false
+ *
+ * Returns +true+ if the two groups use the same curve and have the same
+ * parameters, +false+ otherwise.
+ */
+static VALUE ossl_ec_group_eql(VALUE a, VALUE b)
+{
+ EC_GROUP *group1 = NULL, *group2 = NULL;
+
+ GetECGroup(a, group1);
+ GetECGroup(b, group2);
+
+ switch (EC_GROUP_cmp(group1, group2, ossl_bn_ctx)) {
+ case 0: return Qtrue;
+ case 1: return Qfalse;
+ default: ossl_raise(eEC_GROUP, "EC_GROUP_cmp");
+ }
+}
+
+/*
+ * call-seq:
+ * group.generator => ec_point
+ *
+ * Returns the generator of the group.
+ *
+ * See the OpenSSL documentation for EC_GROUP_get0_generator()
+ */
+static VALUE ossl_ec_group_get_generator(VALUE self)
+{
+ EC_GROUP *group;
+ const EC_POINT *generator;
+
+ GetECGroup(self, group);
+ generator = EC_GROUP_get0_generator(group);
+ if (!generator)
+ return Qnil;
+
+ return ec_point_new(generator, group);
+}
+
+/*
+ * call-seq:
+ * group.set_generator(generator, order, cofactor) => self
+ *
+ * Sets the curve parameters. _generator_ must be an instance of EC::Point that
+ * is on the curve. _order_ and _cofactor_ are integers.
+ *
+ * See the OpenSSL documentation for EC_GROUP_set_generator()
+ */
+static VALUE ossl_ec_group_set_generator(VALUE self, VALUE generator, VALUE order, VALUE cofactor)
+{
+ EC_GROUP *group = NULL;
+ const EC_POINT *point;
+ const BIGNUM *o, *co;
+
+ GetECGroup(self, group);
+ GetECPoint(generator, point);
+ o = GetBNPtr(order);
+ co = GetBNPtr(cofactor);
+
+ if (EC_GROUP_set_generator(group, point, o, co) != 1)
+ ossl_raise(eEC_GROUP, "EC_GROUP_set_generator");
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * group.get_order => order_bn
+ *
+ * Returns the order of the group.
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_order()
+ */
+static VALUE ossl_ec_group_get_order(VALUE self)
+{
+ VALUE bn_obj;
+ BIGNUM *bn;
+ EC_GROUP *group;
+
+ GetECGroup(self, group);
+ bn_obj = ossl_bn_new(BN_value_one());
+ bn = GetBNPtr(bn_obj);
+
+ if (EC_GROUP_get_order(group, bn, ossl_bn_ctx) != 1)
+ ossl_raise(eEC_GROUP, "EC_GROUP_get_order");
+
+ return bn_obj;
+}
+
+/*
+ * call-seq:
+ * group.get_cofactor => cofactor_bn
+ *
+ * Returns the cofactor of the group.
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_cofactor()
+ */
+static VALUE ossl_ec_group_get_cofactor(VALUE self)
+{
+ VALUE bn_obj;
+ BIGNUM *bn;
+ EC_GROUP *group;
+
+ GetECGroup(self, group);
+ bn_obj = ossl_bn_new(BN_value_one());
+ bn = GetBNPtr(bn_obj);
+
+ if (EC_GROUP_get_cofactor(group, bn, ossl_bn_ctx) != 1)
+ ossl_raise(eEC_GROUP, "EC_GROUP_get_cofactor");
+
+ return bn_obj;
+}
+
+/*
+ * call-seq:
+ * group.curve_name -> string or nil
+ *
+ * Returns the curve name (short name) corresponding to this group, or +nil+
+ * if \OpenSSL does not have an OID associated with the group.
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_curve_name()
+ */
+static VALUE ossl_ec_group_get_curve_name(VALUE self)
+{
+ EC_GROUP *group;
+ int nid;
+
+ GetECGroup(self, group);
+ nid = EC_GROUP_get_curve_name(group);
+ if (nid == NID_undef)
+ return Qnil;
+ return rb_str_new_cstr(OBJ_nid2sn(nid));
+}
+
+/*
+ * call-seq:
+ * EC.builtin_curves => [[sn, comment], ...]
+ *
+ * Obtains a list of all predefined curves by the OpenSSL. Curve names are
+ * returned as sn.
+ *
+ * See the OpenSSL documentation for EC_get_builtin_curves().
+ */
+static VALUE ossl_s_builtin_curves(VALUE self)
+{
+ EC_builtin_curve *curves = NULL;
+ int n;
+ int crv_len = rb_long2int(EC_get_builtin_curves(NULL, 0));
+ VALUE ary, ret;
+
+ curves = ALLOCA_N(EC_builtin_curve, crv_len);
+ if (curves == NULL)
+ return Qnil;
+ if (!EC_get_builtin_curves(curves, crv_len))
+ ossl_raise(rb_eRuntimeError, "EC_get_builtin_curves");
+
+ ret = rb_ary_new2(crv_len);
+
+ for (n = 0; n < crv_len; n++) {
+ const char *sname = OBJ_nid2sn(curves[n].nid);
+ const char *comment = curves[n].comment;
+
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, rb_str_new2(sname));
+ rb_ary_push(ary, comment ? rb_str_new2(comment) : Qnil);
+ rb_ary_push(ret, ary);
+ }
+
+ return ret;
+}
+
+/*
+ * call-seq:
+ * group.asn1_flag -> Integer
+ *
+ * Returns the flags set on the group.
+ *
+ * See also #asn1_flag=.
+ */
+static VALUE ossl_ec_group_get_asn1_flag(VALUE self)
+{
+ EC_GROUP *group = NULL;
+ int flag;
+
+ GetECGroup(self, group);
+ flag = EC_GROUP_get_asn1_flag(group);
+
+ return INT2NUM(flag);
+}
+
+/*
+ * call-seq:
+ * group.asn1_flag = flags
+ *
+ * Sets flags on the group. The flag value is used to determine how to encode
+ * the group: encode explicit parameters or named curve using an OID.
+ *
+ * The flag value can be either of:
+ *
+ * * EC::NAMED_CURVE
+ * * EC::EXPLICIT_CURVE
+ *
+ * See the OpenSSL documentation for EC_GROUP_set_asn1_flag().
+ */
+static VALUE ossl_ec_group_set_asn1_flag(VALUE self, VALUE flag_v)
+{
+ EC_GROUP *group = NULL;
+
+ GetECGroup(self, group);
+ EC_GROUP_set_asn1_flag(group, NUM2INT(flag_v));
+
+ return flag_v;
+}
+
+/*
+ * call-seq:
+ * group.point_conversion_form -> Symbol
+ *
+ * Returns the form how EC::Point data is encoded as ASN.1.
+ *
+ * See also #point_conversion_form=.
+ */
+static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
+{
+ EC_GROUP *group;
+ point_conversion_form_t form;
+
+ GetECGroup(self, group);
+ form = EC_GROUP_get_point_conversion_form(group);
+
+ switch (form) {
+ case POINT_CONVERSION_UNCOMPRESSED:
+ return sym_uncompressed;
+ case POINT_CONVERSION_COMPRESSED:
+ return sym_compressed;
+ case POINT_CONVERSION_HYBRID:
+ return sym_hybrid;
+ default:
+ ossl_raise(eEC_GROUP, "unsupported point conversion form: %d, " \
+ "this module should be updated", form);
+ }
+}
+
+static point_conversion_form_t
+parse_point_conversion_form_symbol(VALUE sym)
+{
+ if (sym == sym_uncompressed)
+ return POINT_CONVERSION_UNCOMPRESSED;
+ if (sym == sym_compressed)
+ return POINT_CONVERSION_COMPRESSED;
+ if (sym == sym_hybrid)
+ return POINT_CONVERSION_HYBRID;
+ ossl_raise(rb_eArgError, "unsupported point conversion form %+"PRIsVALUE
+ " (expected :compressed, :uncompressed, or :hybrid)", sym);
+}
+
+/*
+ * call-seq:
+ * group.point_conversion_form = form
+ *
+ * Sets the form how EC::Point data is encoded as ASN.1 as defined in X9.62.
+ *
+ * _format_ can be one of these:
+ *
+ * +:compressed+::
+ * Encoded as z||x, where z is an octet indicating which solution of the
+ * equation y is. z will be 0x02 or 0x03.
+ * +:uncompressed+::
+ * Encoded as z||x||y, where z is an octet 0x04.
+ * +:hybrid+::
+ * Encodes as z||x||y, where z is an octet indicating which solution of the
+ * equation y is. z will be 0x06 or 0x07.
+ *
+ * See the OpenSSL documentation for EC_GROUP_set_point_conversion_form()
+ */
+static VALUE
+ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
+{
+ EC_GROUP *group;
+ point_conversion_form_t form;
+
+ GetECGroup(self, group);
+ form = parse_point_conversion_form_symbol(form_v);
+
+ EC_GROUP_set_point_conversion_form(group, form);
+
+ return form_v;
+}
+
+/*
+ * call-seq:
+ * group.seed => String or nil
+ *
+ * See the OpenSSL documentation for EC_GROUP_get0_seed()
+ */
+static VALUE ossl_ec_group_get_seed(VALUE self)
+{
+ EC_GROUP *group = NULL;
+ size_t seed_len;
+
+ GetECGroup(self, group);
+ seed_len = EC_GROUP_get_seed_len(group);
+
+ if (seed_len == 0)
+ return Qnil;
+
+ return rb_str_new((const char *)EC_GROUP_get0_seed(group), seed_len);
+}
+
+/*
+ * call-seq:
+ * group.seed = seed => seed
+ *
+ * See the OpenSSL documentation for EC_GROUP_set_seed()
+ */
+static VALUE ossl_ec_group_set_seed(VALUE self, VALUE seed)
+{
+ EC_GROUP *group = NULL;
+
+ GetECGroup(self, group);
+ StringValue(seed);
+
+ if (EC_GROUP_set_seed(group, (unsigned char *)RSTRING_PTR(seed), RSTRING_LEN(seed)) != (size_t)RSTRING_LEN(seed))
+ ossl_raise(eEC_GROUP, "EC_GROUP_set_seed");
+
+ return seed;
+}
+
+/* get/set curve GFp, GF2m */
+
+/*
+ * call-seq:
+ * group.degree => integer
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_degree()
+ */
+static VALUE ossl_ec_group_get_degree(VALUE self)
+{
+ EC_GROUP *group = NULL;
+
+ GetECGroup(self, group);
+
+ return INT2NUM(EC_GROUP_get_degree(group));
+}
+
+static VALUE ossl_ec_group_to_string(VALUE self, int format)
+{
+ EC_GROUP *group;
+ BIO *out;
+ int i = -1;
+ VALUE str;
+
+ GetECGroup(self, group);
+
+ if (!(out = BIO_new(BIO_s_mem())))
+ ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
+
+ switch(format) {
+ case EXPORT_PEM:
+ i = PEM_write_bio_ECPKParameters(out, group);
+ break;
+ case EXPORT_DER:
+ i = i2d_ECPKParameters_bio(out, group);
+ break;
+ default:
+ BIO_free(out);
+ ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
+ }
+
+ if (i != 1) {
+ BIO_free(out);
+ ossl_raise(ePKeyError, NULL);
+ }
+
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * group.to_pem => String
+ *
+ * See the OpenSSL documentation for PEM_write_bio_ECPKParameters()
+ */
+static VALUE ossl_ec_group_to_pem(VALUE self)
+{
+ return ossl_ec_group_to_string(self, EXPORT_PEM);
+}
+
+/*
+ * call-seq:
+ * group.to_der => String
+ *
+ * See the OpenSSL documentation for i2d_ECPKParameters_bio()
+ */
+static VALUE ossl_ec_group_to_der(VALUE self)
+{
+ return ossl_ec_group_to_string(self, EXPORT_DER);
+}
+
+/*
+ * call-seq:
+ * group.to_text => String
+ *
+ * See the OpenSSL documentation for ECPKParameters_print()
+ */
+static VALUE ossl_ec_group_to_text(VALUE self)
+{
+ EC_GROUP *group;
+ BIO *out;
+ VALUE str;
+
+ GetECGroup(self, group);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
+ }
+ if (!ECPKParameters_print(out, group, 0)) {
+ BIO_free(out);
+ ossl_raise(eEC_GROUP, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+
+/*
+ * OpenSSL::PKey::EC::Point
+ */
+static void
+ossl_ec_point_free(void *ptr)
+{
+ EC_POINT_clear_free(ptr);
+}
+
+static const rb_data_type_t ossl_ec_point_type = {
+ "OpenSSL/EC_POINT",
+ {
+ 0, ossl_ec_point_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static VALUE
+ossl_ec_point_alloc(VALUE klass)
+{
+ return TypedData_Wrap_Struct(klass, &ossl_ec_point_type, NULL);
+}
+
+static VALUE
+ec_point_new(const EC_POINT *point, const EC_GROUP *group)
+{
+ EC_POINT *point_new;
+ VALUE obj;
+
+ obj = ossl_ec_point_alloc(cEC_POINT);
+ point_new = EC_POINT_dup(point, group);
+ if (!point_new)
+ ossl_raise(eEC_POINT, "EC_POINT_dup");
+ RTYPEDDATA_DATA(obj) = point_new;
+ rb_ivar_set(obj, id_i_group, ec_group_new(group));
+
+ return obj;
+}
+
+static VALUE ossl_ec_point_initialize_copy(VALUE, VALUE);
+/*
+ * call-seq:
+ * OpenSSL::PKey::EC::Point.new(point)
+ * OpenSSL::PKey::EC::Point.new(group [, encoded_point])
+ *
+ * Creates a new instance of OpenSSL::PKey::EC::Point. If the only argument is
+ * an instance of EC::Point, a copy is returned. Otherwise, creates a point
+ * that belongs to _group_.
+ *
+ * _encoded_point_ is the octet string representation of the point. This
+ * must be either a String or an OpenSSL::BN.
+ */
+static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
+{
+ EC_POINT *point;
+ VALUE group_v, arg2;
+ const EC_GROUP *group;
+
+ TypedData_Get_Struct(self, EC_POINT, &ossl_ec_point_type, point);
+ if (point)
+ rb_raise(eEC_POINT, "EC_POINT already initialized");
+
+ rb_scan_args(argc, argv, "11", &group_v, &arg2);
+ if (rb_obj_is_kind_of(group_v, cEC_POINT)) {
+ if (argc != 1)
+ rb_raise(rb_eArgError, "invalid second argument");
+ return ossl_ec_point_initialize_copy(self, group_v);
+ }
+
+ GetECGroup(group_v, group);
+ if (argc == 1) {
+ point = EC_POINT_new(group);
+ if (!point)
+ ossl_raise(eEC_POINT, "EC_POINT_new");
+ }
+ else {
+ if (rb_obj_is_kind_of(arg2, cBN)) {
+ point = EC_POINT_bn2point(group, GetBNPtr(arg2), NULL, ossl_bn_ctx);
+ if (!point)
+ ossl_raise(eEC_POINT, "EC_POINT_bn2point");
+ }
+ else {
+ StringValue(arg2);
+ point = EC_POINT_new(group);
+ if (!point)
+ ossl_raise(eEC_POINT, "EC_POINT_new");
+ if (!EC_POINT_oct2point(group, point,
+ (unsigned char *)RSTRING_PTR(arg2),
+ RSTRING_LEN(arg2), ossl_bn_ctx)) {
+ EC_POINT_free(point);
+ ossl_raise(eEC_POINT, "EC_POINT_oct2point");
+ }
+ }
+ }
+
+ RTYPEDDATA_DATA(self) = point;
+ rb_ivar_set(self, id_i_group, group_v);
+
+ return self;
+}
+
+/* :nodoc: */
+static VALUE
+ossl_ec_point_initialize_copy(VALUE self, VALUE other)
+{
+ EC_POINT *point, *point_new;
+ EC_GROUP *group;
+ VALUE group_v;
+
+ TypedData_Get_Struct(self, EC_POINT, &ossl_ec_point_type, point_new);
+ if (point_new)
+ ossl_raise(eEC_POINT, "EC::Point already initialized");
+ GetECPoint(other, point);
+
+ group_v = rb_obj_dup(rb_attr_get(other, id_i_group));
+ GetECGroup(group_v, group);
+
+ point_new = EC_POINT_dup(point, group);
+ if (!point_new)
+ ossl_raise(eEC_POINT, "EC_POINT_dup");
+ RTYPEDDATA_DATA(self) = point_new;
+ rb_ivar_set(self, id_i_group, group_v);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * point1.eql?(point2) => true | false
+ * point1 == point2 => true | false
+ */
+static VALUE ossl_ec_point_eql(VALUE a, VALUE b)
+{
+ EC_POINT *point1, *point2;
+ VALUE group_v1 = rb_attr_get(a, id_i_group);
+ VALUE group_v2 = rb_attr_get(b, id_i_group);
+ const EC_GROUP *group;
+
+ if (ossl_ec_group_eql(group_v1, group_v2) == Qfalse)
+ return Qfalse;
+
+ GetECPoint(a, point1);
+ GetECPoint(b, point2);
+ GetECGroup(group_v1, group);
+
+ switch (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx)) {
+ case 0: return Qtrue;
+ case 1: return Qfalse;
+ default: ossl_raise(eEC_POINT, "EC_POINT_cmp");
+ }
+
+ UNREACHABLE;
+}
+
+/*
+ * call-seq:
+ * point.infinity? => true | false
+ */
+static VALUE ossl_ec_point_is_at_infinity(VALUE self)
+{
+ EC_POINT *point;
+ const EC_GROUP *group;
+
+ GetECPoint(self, point);
+ GetECPointGroup(self, group);
+
+ switch (EC_POINT_is_at_infinity(group, point)) {
+ case 1: return Qtrue;
+ case 0: return Qfalse;
+ default: ossl_raise(eEC_POINT, "EC_POINT_is_at_infinity");
+ }
+
+ UNREACHABLE;
+}
+
+/*
+ * call-seq:
+ * point.on_curve? => true | false
+ */
+static VALUE ossl_ec_point_is_on_curve(VALUE self)
+{
+ EC_POINT *point;
+ const EC_GROUP *group;
+
+ GetECPoint(self, point);
+ GetECPointGroup(self, group);
+
+ switch (EC_POINT_is_on_curve(group, point, ossl_bn_ctx)) {
+ case 1: return Qtrue;
+ case 0: return Qfalse;
+ default: ossl_raise(eEC_POINT, "EC_POINT_is_on_curve");
+ }
+
+ UNREACHABLE;
+}
+
+/*
+ * call-seq:
+ * point.make_affine! => self
+ *
+ * This method is deprecated and should not be used. This is a no-op.
+ */
+static VALUE ossl_ec_point_make_affine(VALUE self)
+{
+ EC_POINT *point;
+ const EC_GROUP *group;
+
+ GetECPoint(self, point);
+ GetECPointGroup(self, group);
+
+ rb_warn("OpenSSL::PKey::EC::Point#make_affine! is deprecated");
+#if !defined(OSSL_HAVE_IMMUTABLE_PKEY) && !defined(OPENSSL_IS_AWSLC)
+ if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
+ ossl_raise(eEC_POINT, "EC_POINT_make_affine");
+#endif
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * point.invert! => self
+ */
+static VALUE ossl_ec_point_invert(VALUE self)
+{
+ EC_POINT *point;
+ const EC_GROUP *group;
+
+ GetECPoint(self, point);
+ GetECPointGroup(self, group);
+
+ if (EC_POINT_invert(group, point, ossl_bn_ctx) != 1)
+ ossl_raise(eEC_POINT, "EC_POINT_invert");
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * point.set_to_infinity! => self
+ */
+static VALUE ossl_ec_point_set_to_infinity(VALUE self)
+{
+ EC_POINT *point;
+ const EC_GROUP *group;
+
+ GetECPoint(self, point);
+ GetECPointGroup(self, group);
+
+ if (EC_POINT_set_to_infinity(group, point) != 1)
+ ossl_raise(eEC_POINT, "EC_POINT_set_to_infinity");
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * point.to_octet_string(conversion_form) -> String
+ *
+ * Returns the octet string representation of the elliptic curve point.
+ *
+ * _conversion_form_ specifies how the point is converted. Possible values are:
+ *
+ * - +:compressed+
+ * - +:uncompressed+
+ * - +:hybrid+
+ */
+static VALUE
+ossl_ec_point_to_octet_string(VALUE self, VALUE conversion_form)
+{
+ EC_POINT *point;
+ const EC_GROUP *group;
+ point_conversion_form_t form;
+ VALUE str;
+ size_t len;
+
+ GetECPoint(self, point);
+ GetECPointGroup(self, group);
+ form = parse_point_conversion_form_symbol(conversion_form);
+
+ len = EC_POINT_point2oct(group, point, form, NULL, 0, ossl_bn_ctx);
+ if (!len)
+ ossl_raise(eEC_POINT, "EC_POINT_point2oct");
+ str = rb_str_new(NULL, (long)len);
+ if (!EC_POINT_point2oct(group, point, form,
+ (unsigned char *)RSTRING_PTR(str), len,
+ ossl_bn_ctx))
+ ossl_raise(eEC_POINT, "EC_POINT_point2oct");
+ return str;
+}
+
+/*
+ * call-seq:
+ * point.add(point) => point
+ *
+ * Performs elliptic curve point addition.
+ */
+static VALUE ossl_ec_point_add(VALUE self, VALUE other)
+{
+ EC_POINT *point_self, *point_other, *point_result;
+ const EC_GROUP *group;
+ VALUE group_v = rb_attr_get(self, id_i_group);
+ VALUE result;
+
+ GetECPoint(self, point_self);
+ GetECPoint(other, point_other);
+ GetECGroup(group_v, group);
+
+ result = rb_obj_alloc(cEC_POINT);
+ ossl_ec_point_initialize(1, &group_v, result);
+ GetECPoint(result, point_result);
+
+ if (EC_POINT_add(group, point_result, point_self, point_other, ossl_bn_ctx) != 1) {
+ ossl_raise(eEC_POINT, "EC_POINT_add");
+ }
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * point.mul(bn1 [, bn2]) => point
+ *
+ * Performs elliptic curve point multiplication.
+ *
+ * The first form calculates <tt>bn1 * point + bn2 * G</tt>, where +G+ is the
+ * generator of the group of _point_. _bn2_ may be omitted, and in that case,
+ * the result is just <tt>bn1 * point</tt>.
+ *
+ * Before version 4.0.0, and when compiled with OpenSSL 1.1.1 or older, this
+ * method allowed another form:
+ * point.mul(bns, points [, bn2]) => point
+ */
+static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
+{
+ EC_POINT *point_self, *point_result;
+ const EC_GROUP *group;
+ VALUE group_v = rb_attr_get(self, id_i_group);
+ VALUE arg1, arg2, arg3, result;
+ const BIGNUM *bn_g = NULL;
+
+ GetECPoint(self, point_self);
+ GetECGroup(group_v, group);
+
+ result = rb_obj_alloc(cEC_POINT);
+ ossl_ec_point_initialize(1, &group_v, result);
+ GetECPoint(result, point_result);
+
+ rb_scan_args(argc, argv, "12", &arg1, &arg2, &arg3);
+ if (RB_TYPE_P(arg1, T_ARRAY) || argc > 2)
+ rb_raise(rb_eNotImpError, "OpenSSL::PKey::EC::Point#mul with arrays " \
+ "is no longer supported");
+
+ BIGNUM *bn = GetBNPtr(arg1);
+ if (!NIL_P(arg2))
+ bn_g = GetBNPtr(arg2);
+ if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1)
+ ossl_raise(eEC_POINT, NULL);
+
+ return result;
+}
+
+void Init_ossl_ec(void)
+{
+#undef rb_intern
+ /*
+ * Document-class: OpenSSL::PKey::EC
+ *
+ * OpenSSL::PKey::EC provides access to Elliptic Curve Digital Signature
+ * Algorithm (ECDSA) and Elliptic Curve Diffie-Hellman (ECDH).
+ *
+ * === Key exchange
+ * ec1 = OpenSSL::PKey::EC.generate("prime256v1")
+ * ec2 = OpenSSL::PKey::EC.generate("prime256v1")
+ * # ec1 and ec2 have own private key respectively
+ * shared_key1 = ec1.dh_compute_key(ec2.public_key)
+ * shared_key2 = ec2.dh_compute_key(ec1.public_key)
+ *
+ * p shared_key1 == shared_key2 #=> true
+ */
+ cEC = rb_define_class_under(mPKey, "EC", cPKey);
+ cEC_GROUP = rb_define_class_under(cEC, "Group", rb_cObject);
+ cEC_POINT = rb_define_class_under(cEC, "Point", rb_cObject);
+ eEC_GROUP = rb_define_class_under(cEC_GROUP, "Error", eOSSLError);
+ eEC_POINT = rb_define_class_under(cEC_POINT, "Error", eOSSLError);
+
+ sym_GFp = ID2SYM(rb_intern_const("GFp"));
+ sym_GF2m = ID2SYM(rb_intern_const("GF2m"));
+
+ sym_uncompressed = ID2SYM(rb_intern_const("uncompressed"));
+ sym_compressed = ID2SYM(rb_intern_const("compressed"));
+ sym_hybrid = ID2SYM(rb_intern_const("hybrid"));
+
+ rb_define_const(cEC, "NAMED_CURVE", INT2NUM(OPENSSL_EC_NAMED_CURVE));
+ rb_define_const(cEC, "EXPLICIT_CURVE", INT2NUM(OPENSSL_EC_EXPLICIT_CURVE));
+
+ rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0);
+
+ rb_define_singleton_method(cEC, "generate", ossl_ec_key_s_generate, 1);
+ rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1);
+#ifndef HAVE_EVP_PKEY_DUP
+ rb_define_method(cEC, "initialize_copy", ossl_ec_key_initialize_copy, 1);
+#endif
+
+ rb_define_method(cEC, "group", ossl_ec_key_get_group, 0);
+ rb_define_method(cEC, "group=", ossl_ec_key_set_group, 1);
+ rb_define_method(cEC, "private_key", ossl_ec_key_get_private_key, 0);
+ rb_define_method(cEC, "private_key=", ossl_ec_key_set_private_key, 1);
+ rb_define_method(cEC, "public_key", ossl_ec_key_get_public_key, 0);
+ rb_define_method(cEC, "public_key=", ossl_ec_key_set_public_key, 1);
+ rb_define_method(cEC, "private?", ossl_ec_key_is_private, 0);
+ rb_define_method(cEC, "public?", ossl_ec_key_is_public, 0);
+ rb_define_alias(cEC, "private_key?", "private?");
+ rb_define_alias(cEC, "public_key?", "public?");
+/* rb_define_method(cEC, "", ossl_ec_key_get_, 0);
+ rb_define_method(cEC, "=", ossl_ec_key_set_ 1);
+ set/get enc_flags
+ set/get _conv_from
+ set/get asn1_flag (can use ruby to call self.group.asn1_flag)
+ set/get precompute_mult
+*/
+ rb_define_method(cEC, "generate_key!", ossl_ec_key_generate_key, 0);
+ rb_define_alias(cEC, "generate_key", "generate_key!");
+ rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0);
+
+ rb_define_method(cEC, "export", ossl_ec_key_export, -1);
+ rb_define_alias(cEC, "to_pem", "export");
+ rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
+
+
+ rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc);
+ rb_define_method(cEC_GROUP, "initialize", ossl_ec_group_initialize, -1);
+ rb_define_method(cEC_GROUP, "initialize_copy", ossl_ec_group_initialize_copy, 1);
+ rb_define_method(cEC_GROUP, "eql?", ossl_ec_group_eql, 1);
+ rb_define_alias(cEC_GROUP, "==", "eql?");
+/* copy/dup/cmp */
+
+ rb_define_method(cEC_GROUP, "generator", ossl_ec_group_get_generator, 0);
+ rb_define_method(cEC_GROUP, "set_generator", ossl_ec_group_set_generator, 3);
+ rb_define_method(cEC_GROUP, "order", ossl_ec_group_get_order, 0);
+ rb_define_method(cEC_GROUP, "cofactor", ossl_ec_group_get_cofactor, 0);
+
+ rb_define_method(cEC_GROUP, "curve_name", ossl_ec_group_get_curve_name, 0);
+/* rb_define_method(cEC_GROUP, "curve_name=", ossl_ec_group_set_curve_name, 1); */
+
+ rb_define_method(cEC_GROUP, "asn1_flag", ossl_ec_group_get_asn1_flag, 0);
+ rb_define_method(cEC_GROUP, "asn1_flag=", ossl_ec_group_set_asn1_flag, 1);
+
+ rb_define_method(cEC_GROUP, "point_conversion_form", ossl_ec_group_get_point_conversion_form, 0);
+ rb_define_method(cEC_GROUP, "point_conversion_form=", ossl_ec_group_set_point_conversion_form, 1);
+
+ rb_define_method(cEC_GROUP, "seed", ossl_ec_group_get_seed, 0);
+ rb_define_method(cEC_GROUP, "seed=", ossl_ec_group_set_seed, 1);
+
+/* get/set GFp, GF2m */
+
+ rb_define_method(cEC_GROUP, "degree", ossl_ec_group_get_degree, 0);
+
+/* check* */
+
+
+ rb_define_method(cEC_GROUP, "to_pem", ossl_ec_group_to_pem, 0);
+ rb_define_method(cEC_GROUP, "to_der", ossl_ec_group_to_der, 0);
+ rb_define_method(cEC_GROUP, "to_text", ossl_ec_group_to_text, 0);
+
+
+ rb_define_alloc_func(cEC_POINT, ossl_ec_point_alloc);
+ rb_define_method(cEC_POINT, "initialize", ossl_ec_point_initialize, -1);
+ rb_define_method(cEC_POINT, "initialize_copy", ossl_ec_point_initialize_copy, 1);
+ rb_attr(cEC_POINT, rb_intern("group"), 1, 0, 0);
+ rb_define_method(cEC_POINT, "eql?", ossl_ec_point_eql, 1);
+ rb_define_alias(cEC_POINT, "==", "eql?");
+
+ rb_define_method(cEC_POINT, "infinity?", ossl_ec_point_is_at_infinity, 0);
+ rb_define_method(cEC_POINT, "on_curve?", ossl_ec_point_is_on_curve, 0);
+ rb_define_method(cEC_POINT, "make_affine!", ossl_ec_point_make_affine, 0);
+ rb_define_method(cEC_POINT, "invert!", ossl_ec_point_invert, 0);
+ rb_define_method(cEC_POINT, "set_to_infinity!", ossl_ec_point_set_to_infinity, 0);
+/* all the other methods */
+
+ rb_define_method(cEC_POINT, "to_octet_string", ossl_ec_point_to_octet_string, 1);
+ rb_define_method(cEC_POINT, "add", ossl_ec_point_add, 1);
+ rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);
+
+ id_i_group = rb_intern("@group");
+}
+
+#else /* defined NO_EC */
+void Init_ossl_ec(void)
+{
+}
+#endif /* NO_EC */
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 17bec2b7bb..039b2c6a34 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -1,483 +1,566 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
-#if !defined(OPENSSL_NO_RSA)
-
#include "ossl.h"
+#if !defined(OPENSSL_NO_RSA)
+
#define GetPKeyRSA(obj, pkey) do { \
- GetPKey(obj, pkey); \
- if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) { /* PARANOIA? */ \
- ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \
+ GetPKey((obj), (pkey)); \
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { /* PARANOIA? */ \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \
} \
} while (0)
+#define GetRSA(obj, rsa) do { \
+ EVP_PKEY *_pkey; \
+ GetPKeyRSA((obj), _pkey); \
+ (rsa) = EVP_PKEY_get0_RSA(_pkey); \
+ if ((rsa) == NULL) \
+ ossl_raise(ePKeyError, "failed to get RSA from EVP_PKEY"); \
+} while (0)
-#define RSA_HAS_PRIVATE(rsa) ((rsa)->p && (rsa)->q)
-#define RSA_PRIVATE(obj,rsa) (RSA_HAS_PRIVATE(rsa)||OSSL_PKEY_IS_PRIVATE(obj))
+static inline int
+RSA_HAS_PRIVATE(OSSL_3_const RSA *rsa)
+{
+ const BIGNUM *e, *d;
+
+ RSA_get0_key(rsa, NULL, &e, &d);
+ return e && d;
+}
+
+static inline int
+RSA_PRIVATE(VALUE obj, OSSL_3_const RSA *rsa)
+{
+ return RSA_HAS_PRIVATE(rsa) || OSSL_PKEY_IS_PRIVATE(obj);
+}
/*
* Classes
*/
VALUE cRSA;
-VALUE eRSAError;
/*
- * Public
+ * Private
*/
-static VALUE
-rsa_instance(VALUE klass, RSA *rsa)
-{
- EVP_PKEY *pkey;
- VALUE obj;
-
- if (!rsa) {
- return Qfalse;
- }
- if (!(pkey = EVP_PKEY_new())) {
- return Qfalse;
- }
- if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
- EVP_PKEY_free(pkey);
- return Qfalse;
- }
- WrapPKey(klass, obj, pkey);
-
- return obj;
-}
-
-VALUE
-ossl_rsa_new(EVP_PKEY *pkey)
-{
- VALUE obj;
-
- if (!pkey) {
- obj = rsa_instance(cRSA, RSA_new());
- }
- else {
- if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) {
- ossl_raise(rb_eTypeError, "Not a RSA key!");
- }
- WrapPKey(cRSA, obj, pkey);
- }
- if (obj == Qfalse) {
- ossl_raise(eRSAError, NULL);
- }
-
- return obj;
-}
-
/*
- * Private
+ * call-seq:
+ * RSA.new -> rsa
+ * RSA.new(encoded_key [, password ]) -> rsa
+ * RSA.new(encoded_key) { password } -> rsa
+ * RSA.new(size [, exponent]) -> rsa
+ *
+ * Generates or loads an \RSA keypair.
+ *
+ * If called without arguments, creates a new instance with no key components
+ * set. They can be set individually by #set_key, #set_factors, and
+ * #set_crt_params.
+ * This form is not compatible with OpenSSL 3.0 or later.
+ *
+ * If called with a String, tries to parse as DER or PEM encoding of an \RSA key.
+ * Note that if _password_ is not specified, but the key is encrypted with a
+ * password, \OpenSSL will prompt for it.
+ * See also OpenSSL::PKey.read which can parse keys of any kind.
+ *
+ * If called with a number, generates a new key pair. This form works as an
+ * alias of RSA.generate.
+ *
+ * Examples:
+ * OpenSSL::PKey::RSA.new 2048
+ * OpenSSL::PKey::RSA.new File.read 'rsa.pem'
+ * OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my password'
*/
-static RSA *
-rsa_generate(int size, int exp)
-{
- return RSA_generate_key(size, exp,
- rb_block_given_p() ? ossl_generate_cb : NULL,
- NULL);
-}
-
static VALUE
-ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
+ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
{
+ EVP_PKEY *pkey;
RSA *rsa;
- VALUE size, exp;
- VALUE obj;
-
- rb_scan_args(argc, argv, "11", &size, &exp);
-
- rsa = rsa_generate(NUM2INT(size), NIL_P(exp) ? RSA_F4 : NUM2INT(exp)); /* err handled by rsa_instance */
- obj = rsa_instance(klass, rsa);
+ BIO *in = NULL;
+ VALUE arg, pass;
+ int type;
+
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
+
+ /* The RSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
+ rb_scan_args(argc, argv, "02", &arg, &pass);
+ if (argc == 0) {
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ rb_raise(rb_eArgError, "OpenSSL::PKey::RSA.new cannot be called " \
+ "without arguments; pkeys are immutable with OpenSSL 3.0");
+#else
+ rsa = RSA_new();
+ if (!rsa)
+ ossl_raise(ePKeyError, "RSA_new");
+ goto legacy;
+#endif
+ }
- if (obj == Qfalse) {
- RSA_free(rsa);
- ossl_raise(eRSAError, NULL);
+ pass = ossl_pem_passwd_value(pass);
+ arg = ossl_to_der_if_possible(arg);
+ in = ossl_obj2bio(&arg);
+
+ /* First try RSAPublicKey format */
+ rsa = d2i_RSAPublicKey_bio(in, NULL);
+ if (rsa)
+ goto legacy;
+ OSSL_BIO_reset(in);
+ rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
+ if (rsa)
+ goto legacy;
+ OSSL_BIO_reset(in);
+
+ /* Use the generic routine */
+ pkey = ossl_pkey_read_generic(in, pass);
+ BIO_free(in);
+ if (!pkey)
+ ossl_raise(ePKeyError, "Neither PUB key nor PRIV key");
+
+ type = EVP_PKEY_base_id(pkey);
+ if (type != EVP_PKEY_RSA) {
+ EVP_PKEY_free(pkey);
+ rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type));
}
+ RTYPEDDATA_DATA(self) = pkey;
+ return self;
- return obj;
+ legacy:
+ BIO_free(in);
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa) != 1) {
+ EVP_PKEY_free(pkey);
+ RSA_free(rsa);
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_RSA");
+ }
+ RTYPEDDATA_DATA(self) = pkey;
+ return self;
}
+#ifndef HAVE_EVP_PKEY_DUP
+/* :nodoc: */
static VALUE
-ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
+ossl_rsa_initialize_copy(VALUE self, VALUE other)
{
EVP_PKEY *pkey;
- RSA *rsa;
- BIO *in;
- char *passwd = NULL;
- VALUE arg, pass;
-
- GetPKey(self, pkey);
- if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
- rsa = RSA_new();
- }
- else if (FIXNUM_P(arg)) {
- rsa = rsa_generate(FIX2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2INT(pass));
- if (!rsa) ossl_raise(eRSAError, NULL);
- }
- else {
- if (!NIL_P(pass)) passwd = StringValuePtr(pass);
- arg = ossl_to_der_if_possible(arg);
- in = ossl_obj2bio(arg);
- rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
- if (!rsa) {
- BIO_reset(in);
- rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
- }
- if (!rsa) {
- BIO_reset(in);
- rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL);
- }
- if (!rsa) {
- BIO_reset(in);
- rsa = d2i_RSAPrivateKey_bio(in, NULL);
- }
- if (!rsa) {
- BIO_reset(in);
- rsa = d2i_RSAPublicKey_bio(in, NULL);
- }
- if (!rsa) {
- BIO_reset(in);
- rsa = d2i_RSA_PUBKEY_bio(in, NULL);
- }
- BIO_free(in);
- if (!rsa) ossl_raise(eRSAError, "Neither PUB key nor PRIV key:");
- }
- if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
- RSA_free(rsa);
- ossl_raise(eRSAError, NULL);
+ RSA *rsa, *rsa_new;
+
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
+ GetRSA(other, rsa);
+
+ rsa_new = (RSA *)ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey,
+ (d2i_of_void *)d2i_RSAPrivateKey,
+ (char *)rsa);
+ if (!rsa_new)
+ ossl_raise(ePKeyError, "ASN1_dup");
+
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa_new) != 1) {
+ RSA_free(rsa_new);
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_RSA");
}
+ RTYPEDDATA_DATA(self) = pkey;
return self;
}
+#endif
+/*
+ * call-seq:
+ * rsa.public? => true
+ *
+ * The return value is always +true+ since every private key is also a public
+ * key.
+ */
static VALUE
ossl_rsa_is_public(VALUE self)
{
- EVP_PKEY *pkey;
+ OSSL_3_const RSA *rsa;
- GetPKeyRSA(self, pkey);
+ GetRSA(self, rsa);
/*
- * SURPRISE! :-))
- * Every key is public at the same time!
+ * This method should check for n and e. BUG.
*/
+ (void)rsa;
return Qtrue;
}
+/*
+ * call-seq:
+ * rsa.private? => true | false
+ *
+ * Does this keypair contain a private key?
+ */
static VALUE
ossl_rsa_is_private(VALUE self)
{
- EVP_PKEY *pkey;
-
- GetPKeyRSA(self, pkey);
-
- return (RSA_PRIVATE(self, pkey->pkey.rsa)) ? Qtrue : Qfalse;
-}
-
-static VALUE
-ossl_rsa_export(int argc, VALUE *argv, VALUE self)
-{
- EVP_PKEY *pkey;
- BIO *out;
- const EVP_CIPHER *ciph = NULL;
- char *passwd = NULL;
- VALUE cipher, pass, str;
-
- GetPKeyRSA(self, pkey);
+ OSSL_3_const RSA *rsa;
- rb_scan_args(argc, argv, "02", &cipher, &pass);
+ GetRSA(self, rsa);
- if (!NIL_P(cipher)) {
- ciph = GetCipherPtr(cipher);
- if (!NIL_P(pass)) {
- passwd = StringValuePtr(pass);
- }
- }
- if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eRSAError, NULL);
- }
- if (RSA_HAS_PRIVATE(pkey->pkey.rsa)) {
- if (!PEM_write_bio_RSAPrivateKey(out, pkey->pkey.rsa, ciph,
- NULL, 0, ossl_pem_passwd_cb, passwd)) {
- BIO_free(out);
- ossl_raise(eRSAError, NULL);
- }
- } else {
- if (!PEM_write_bio_RSAPublicKey(out, pkey->pkey.rsa)) {
- BIO_free(out);
- ossl_raise(eRSAError, NULL);
- }
- }
- str = ossl_membio2str(out);
-
- return str;
+ return RSA_PRIVATE(self, rsa) ? Qtrue : Qfalse;
}
-static VALUE
-ossl_rsa_to_der(VALUE self)
+static int
+can_export_rsaprivatekey(VALUE self)
{
- EVP_PKEY *pkey;
- int (*i2d_func)_((const RSA*, unsigned char**));
- unsigned char *p;
- long len;
- VALUE str;
-
- GetPKeyRSA(self, pkey);
- if(RSA_HAS_PRIVATE(pkey->pkey.rsa))
- i2d_func = i2d_RSAPrivateKey;
- else
- i2d_func = i2d_RSAPublicKey;
- if((len = i2d_func(pkey->pkey.rsa, NULL)) <= 0)
- ossl_raise(eRSAError, NULL);
- str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
- if(i2d_func(pkey->pkey.rsa, &p) < 0)
- ossl_raise(eRSAError, NULL);
- ossl_str_adjust(str, p);
-
- return str;
-}
+ OSSL_3_const RSA *rsa;
+ const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
-#define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16)
+ GetRSA(self, rsa);
-static VALUE
-ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
-{
- EVP_PKEY *pkey;
- int buf_len, pad;
- VALUE str, buffer, padding;
-
- GetPKeyRSA(self, pkey);
- rb_scan_args(argc, argv, "11", &buffer, &padding);
- pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
- StringValue(buffer);
- str = rb_str_new(0, ossl_rsa_buf_size(pkey));
- buf_len = RSA_public_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
- RSTRING(str)->ptr, pkey->pkey.rsa,
- pad);
- if (buf_len < 0) ossl_raise(eRSAError, NULL);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
-
- return str;
-}
+ RSA_get0_key(rsa, &n, &e, &d);
+ RSA_get0_factors(rsa, &p, &q);
+ RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
-static VALUE
-ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
-{
- EVP_PKEY *pkey;
- int buf_len, pad;
- VALUE str, buffer, padding;
-
- GetPKeyRSA(self, pkey);
- rb_scan_args(argc, argv, "11", &buffer, &padding);
- pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
- StringValue(buffer);
- str = rb_str_new(0, ossl_rsa_buf_size(pkey));
- buf_len = RSA_public_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
- RSTRING(str)->ptr, pkey->pkey.rsa,
- pad);
- if (buf_len < 0) ossl_raise(eRSAError, NULL);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
-
- return str;
-}
-
-static VALUE
-ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
-{
- EVP_PKEY *pkey;
- int buf_len, pad;
- VALUE str, buffer, padding;
-
- GetPKeyRSA(self, pkey);
- if (!RSA_PRIVATE(self, pkey->pkey.rsa)) {
- ossl_raise(eRSAError, "private key needed.");
- }
- rb_scan_args(argc, argv, "11", &buffer, &padding);
- pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
- StringValue(buffer);
- str = rb_str_new(0, ossl_rsa_buf_size(pkey));
- buf_len = RSA_private_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
- RSTRING(str)->ptr, pkey->pkey.rsa,
- pad);
- if (buf_len < 0) ossl_raise(eRSAError, NULL);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
-
- return str;
+ return n && e && d && p && q && dmp1 && dmq1 && iqmp;
}
+/*
+ * call-seq:
+ * rsa.export([cipher, password]) => PEM-format String
+ * rsa.to_pem([cipher, password]) => PEM-format String
+ * rsa.to_s([cipher, password]) => PEM-format String
+ *
+ * Serializes a private or public key to a PEM-encoding.
+ *
+ * [When the key contains public components only]
+ *
+ * Serializes it into an X.509 SubjectPublicKeyInfo.
+ * The parameters _cipher_ and _password_ are ignored.
+ *
+ * A PEM-encoded key will look like:
+ *
+ * -----BEGIN PUBLIC KEY-----
+ * [...]
+ * -----END PUBLIC KEY-----
+ *
+ * Consider using #public_to_pem instead. This serializes the key into an
+ * X.509 SubjectPublicKeyInfo regardless of whether the key is a public key
+ * or a private key.
+ *
+ * [When the key contains private components, and no parameters are given]
+ *
+ * Serializes it into a PKCS #1 RSAPrivateKey.
+ *
+ * A PEM-encoded key will look like:
+ *
+ * -----BEGIN RSA PRIVATE KEY-----
+ * [...]
+ * -----END RSA PRIVATE KEY-----
+ *
+ * [When the key contains private components, and _cipher_ and _password_ are given]
+ *
+ * Serializes it into a PKCS #1 RSAPrivateKey
+ * and encrypts it in OpenSSL's traditional PEM encryption format.
+ * _cipher_ must be a cipher name understood by OpenSSL::Cipher.new or an
+ * instance of OpenSSL::Cipher.
+ *
+ * An encrypted PEM-encoded key will look like:
+ *
+ * -----BEGIN RSA PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0
+ *
+ * [...]
+ * -----END RSA PRIVATE KEY-----
+ *
+ * Note that this format uses MD5 to derive the encryption key, and hence
+ * will not be available on FIPS-compliant systems.
+ *
+ * <b>This method is kept for compatibility.</b>
+ * This should only be used when the PKCS #1 RSAPrivateKey format is required.
+ *
+ * Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem
+ * (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead.
+ */
static VALUE
-ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
+ossl_rsa_export(int argc, VALUE *argv, VALUE self)
{
- EVP_PKEY *pkey;
- int buf_len, pad;
- VALUE str, buffer, padding;
-
- GetPKeyRSA(self, pkey);
- if (!RSA_PRIVATE(self, pkey->pkey.rsa)) {
- ossl_raise(eRSAError, "private key needed.");
- }
- rb_scan_args(argc, argv, "11", &buffer, &padding);
- pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
- StringValue(buffer);
- str = rb_str_new(0, ossl_rsa_buf_size(pkey));
- buf_len = RSA_private_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
- RSTRING(str)->ptr, pkey->pkey.rsa,
- pad);
- if (buf_len < 0) ossl_raise(eRSAError, NULL);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
-
- return str;
+ if (can_export_rsaprivatekey(self))
+ return ossl_pkey_export_traditional(argc, argv, self, 0);
+ else
+ return ossl_pkey_export_spki(self, 0);
}
/*
- * Stores all parameters of key to the hash
- * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
- * Don't use :-)) (I's up to you)
+ * call-seq:
+ * rsa.to_der => DER-format String
+ *
+ * Serializes a private or public key to a DER-encoding.
+ *
+ * See #to_pem for details.
+ *
+ * <b>This method is kept for compatibility.</b>
+ * This should only be used when the PKCS #1 RSAPrivateKey format is required.
+ *
+ * Consider using #public_to_der or #private_to_der instead.
*/
static VALUE
-ossl_rsa_get_params(VALUE self)
+ossl_rsa_to_der(VALUE self)
{
- EVP_PKEY *pkey;
- VALUE hash;
-
- GetPKeyRSA(self, pkey);
-
- hash = rb_hash_new();
-
- rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(pkey->pkey.rsa->n));
- rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(pkey->pkey.rsa->e));
- rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(pkey->pkey.rsa->d));
- rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.rsa->p));
- rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.rsa->q));
- rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(pkey->pkey.rsa->dmp1));
- rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(pkey->pkey.rsa->dmq1));
- rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(pkey->pkey.rsa->iqmp));
-
- return hash;
+ if (can_export_rsaprivatekey(self))
+ return ossl_pkey_export_traditional(0, NULL, self, 1);
+ else
+ return ossl_pkey_export_spki(self, 1);
}
/*
- * Prints all parameters of key to buffer
- * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
- * Don't use :-)) (It's up to you)
+ * call-seq:
+ * rsa.sign_pss(digest, data, salt_length:, mgf1_hash:) -> String
+ *
+ * Signs _data_ using the Probabilistic Signature Scheme (RSA-PSS) and returns
+ * the calculated signature.
+ *
+ * PKeyError will be raised if an error occurs.
+ *
+ * See #verify_pss for the verification operation.
+ *
+ * === Parameters
+ * _digest_::
+ * A String containing the message digest algorithm name.
+ * _data_::
+ * A String. The data to be signed.
+ * _salt_length_::
+ * The length in octets of the salt. Two special values are reserved:
+ * +:digest+ means the digest length, and +:max+ means the maximum possible
+ * length for the combination of the private key and the selected message
+ * digest algorithm.
+ * _mgf1_hash_::
+ * The hash algorithm used in MGF1 (the currently supported mask generation
+ * function (MGF)).
+ *
+ * === Example
+ * data = "Sign me!"
+ * pkey = OpenSSL::PKey::RSA.new(2048)
+ * signature = pkey.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA256")
+ * pub_key = OpenSSL::PKey.read(pkey.public_to_der)
+ * puts pub_key.verify_pss("SHA256", signature, data,
+ * salt_length: :auto, mgf1_hash: "SHA256") # => true
*/
static VALUE
-ossl_rsa_to_text(VALUE self)
+ossl_rsa_sign_pss(int argc, VALUE *argv, VALUE self)
{
+ VALUE digest, data, options, kwargs[2], signature, mgf1md_holder, md_holder;
+ static ID kwargs_ids[2];
EVP_PKEY *pkey;
- BIO *out;
- VALUE str;
-
- GetPKeyRSA(self, pkey);
- if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eRSAError, NULL);
- }
- if (!RSA_print(out, pkey->pkey.rsa, 0)) { /* offset = 0 */
- BIO_free(out);
- ossl_raise(eRSAError, NULL);
+ EVP_PKEY_CTX *pkey_ctx;
+ const EVP_MD *md, *mgf1md;
+ EVP_MD_CTX *md_ctx;
+ size_t buf_len;
+ int salt_len;
+
+ if (!kwargs_ids[0]) {
+ kwargs_ids[0] = rb_intern_const("salt_length");
+ kwargs_ids[1] = rb_intern_const("mgf1_hash");
}
- str = ossl_membio2str(out);
+ rb_scan_args(argc, argv, "2:", &digest, &data, &options);
+ rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs);
+ if (kwargs[0] == ID2SYM(rb_intern("max")))
+ salt_len = -2; /* RSA_PSS_SALTLEN_MAX_SIGN */
+ else if (kwargs[0] == ID2SYM(rb_intern("digest")))
+ salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */
+ else
+ salt_len = NUM2INT(kwargs[0]);
+ mgf1md = ossl_evp_md_fetch(kwargs[1], &mgf1md_holder);
+
+ pkey = GetPrivPKeyPtr(self);
+ buf_len = EVP_PKEY_size(pkey);
+ md = ossl_evp_md_fetch(digest, &md_holder);
+ StringValue(data);
+ signature = rb_str_new(NULL, (long)buf_len);
+
+ md_ctx = EVP_MD_CTX_new();
+ if (!md_ctx)
+ goto err;
+
+ if (EVP_DigestSignInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1)
+ goto err;
+
+ if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1)
+ goto err;
+
+ if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1)
+ goto err;
+
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1)
+ goto err;
+
+ if (EVP_DigestSignUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
+ goto err;
- return str;
+ if (EVP_DigestSignFinal(md_ctx, (unsigned char *)RSTRING_PTR(signature), &buf_len) != 1)
+ goto err;
+
+ rb_str_set_len(signature, (long)buf_len);
+
+ EVP_MD_CTX_free(md_ctx);
+ return signature;
+
+ err:
+ EVP_MD_CTX_free(md_ctx);
+ ossl_raise(ePKeyError, NULL);
}
/*
- * Makes new instance RSA PUBLIC_KEY from PRIVATE_KEY
+ * call-seq:
+ * rsa.verify_pss(digest, signature, data, salt_length:, mgf1_hash:) -> true | false
+ *
+ * Verifies _data_ using the Probabilistic Signature Scheme (RSA-PSS).
+ *
+ * The return value is +true+ if the signature is valid, +false+ otherwise.
+ * PKeyError will be raised if an error occurs.
+ *
+ * See #sign_pss for the signing operation and an example code.
+ *
+ * === Parameters
+ * _digest_::
+ * A String containing the message digest algorithm name.
+ * _data_::
+ * A String. The data to be signed.
+ * _salt_length_::
+ * The length in octets of the salt. Two special values are reserved:
+ * +:digest+ means the digest length, and +:auto+ means automatically
+ * determining the length based on the signature.
+ * _mgf1_hash_::
+ * The hash algorithm used in MGF1.
*/
static VALUE
-ossl_rsa_to_public_key(VALUE self)
+ossl_rsa_verify_pss(int argc, VALUE *argv, VALUE self)
{
+ VALUE digest, signature, data, options, kwargs[2], mgf1md_holder, md_holder;
+ static ID kwargs_ids[2];
EVP_PKEY *pkey;
- RSA *rsa;
- VALUE obj;
-
- GetPKeyRSA(self, pkey);
- /* err check performed by rsa_instance */
- rsa = RSAPublicKey_dup(pkey->pkey.rsa);
- obj = rsa_instance(CLASS_OF(self), rsa);
- if (obj == Qfalse) {
- RSA_free(rsa);
- ossl_raise(eRSAError, NULL);
+ EVP_PKEY_CTX *pkey_ctx;
+ const EVP_MD *md, *mgf1md;
+ EVP_MD_CTX *md_ctx;
+ int result, salt_len;
+
+ if (!kwargs_ids[0]) {
+ kwargs_ids[0] = rb_intern_const("salt_length");
+ kwargs_ids[1] = rb_intern_const("mgf1_hash");
}
- return obj;
-}
-
-/*
- * TODO: Test me
-extern BN_CTX *ossl_bn_ctx;
-
-static VALUE
-ossl_rsa_blinding_on(VALUE self)
-{
- EVP_PKEY *pkey;
-
- GetPKeyRSA(self, pkey);
+ rb_scan_args(argc, argv, "3:", &digest, &signature, &data, &options);
+ rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs);
+ if (kwargs[0] == ID2SYM(rb_intern("auto")))
+ salt_len = -2; /* RSA_PSS_SALTLEN_AUTO */
+ else if (kwargs[0] == ID2SYM(rb_intern("digest")))
+ salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */
+ else
+ salt_len = NUM2INT(kwargs[0]);
+ mgf1md = ossl_evp_md_fetch(kwargs[1], &mgf1md_holder);
- if (RSA_blinding_on(pkey->pkey.rsa, ossl_bn_ctx) != 1) {
- ossl_raise(eRSAError, NULL);
+ GetPKey(self, pkey);
+ md = ossl_evp_md_fetch(digest, &md_holder);
+ StringValue(signature);
+ StringValue(data);
+
+ md_ctx = EVP_MD_CTX_new();
+ if (!md_ctx)
+ goto err;
+
+ if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1)
+ goto err;
+
+ if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1)
+ goto err;
+
+ if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1)
+ goto err;
+
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1)
+ goto err;
+
+ if (EVP_DigestVerifyUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
+ goto err;
+
+ result = EVP_DigestVerifyFinal(md_ctx,
+ (unsigned char *)RSTRING_PTR(signature),
+ RSTRING_LEN(signature));
+ EVP_MD_CTX_free(md_ctx);
+
+ switch (result) {
+ case 0:
+ ossl_clear_error();
+ return Qfalse;
+ case 1:
+ return Qtrue;
+ default:
+ ossl_raise(ePKeyError, "EVP_DigestVerifyFinal");
}
- return self;
-}
-static VALUE
-ossl_rsa_blinding_off(VALUE self)
-{
- EVP_PKEY *pkey;
-
- GetPKeyRSA(self, pkey);
- RSA_blinding_off(pkey->pkey.rsa);
-
- return self;
+ err:
+ EVP_MD_CTX_free(md_ctx);
+ ossl_raise(ePKeyError, NULL);
}
- */
-OSSL_PKEY_BN(rsa, n);
-OSSL_PKEY_BN(rsa, e);
-OSSL_PKEY_BN(rsa, d);
-OSSL_PKEY_BN(rsa, p);
-OSSL_PKEY_BN(rsa, q);
-OSSL_PKEY_BN(rsa, dmp1);
-OSSL_PKEY_BN(rsa, dmq1);
-OSSL_PKEY_BN(rsa, iqmp);
+/*
+ * Document-method: OpenSSL::PKey::RSA#set_key
+ * call-seq:
+ * rsa.set_key(n, e, d) -> self
+ *
+ * Sets _n_, _e_, _d_ for the RSA instance.
+ */
+OSSL_PKEY_BN_DEF3(rsa, RSA, key, n, e, d)
+/*
+ * Document-method: OpenSSL::PKey::RSA#set_factors
+ * call-seq:
+ * rsa.set_factors(p, q) -> self
+ *
+ * Sets _p_, _q_ for the RSA instance.
+ */
+OSSL_PKEY_BN_DEF2(rsa, RSA, factors, p, q)
+/*
+ * Document-method: OpenSSL::PKey::RSA#set_crt_params
+ * call-seq:
+ * rsa.set_crt_params(dmp1, dmq1, iqmp) -> self
+ *
+ * Sets _dmp1_, _dmq1_, _iqmp_ for the RSA instance. They are calculated by
+ * <tt>d mod (p - 1)</tt>, <tt>d mod (q - 1)</tt> and <tt>q^(-1) mod p</tt>
+ * respectively.
+ */
+OSSL_PKEY_BN_DEF3(rsa, RSA, crt_params, dmp1, dmq1, iqmp)
/*
* INIT
*/
-#define DefRSAConst(x) rb_define_const(cRSA, #x,INT2FIX(RSA_##x))
+#define DefRSAConst(x) rb_define_const(cRSA, #x, INT2NUM(RSA_##x))
void
-Init_ossl_rsa()
+Init_ossl_rsa(void)
{
- eRSAError = rb_define_class_under(mPKey, "RSAError", ePKeyError);
-
+ /* Document-class: OpenSSL::PKey::RSA
+ *
+ * RSA is an asymmetric public key algorithm that has been formalized in
+ * RFC 3447. It is in widespread use in public key infrastructures (PKI)
+ * where certificates (cf. OpenSSL::X509::Certificate) often are issued
+ * on the basis of a public/private RSA key pair. RSA is used in a wide
+ * field of applications such as secure (symmetric) key exchange, e.g.
+ * when establishing a secure TLS/SSL connection. It is also used in
+ * various digital signature schemes.
+ */
cRSA = rb_define_class_under(mPKey, "RSA", cPKey);
- rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, -1);
rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1);
-
+#ifndef HAVE_EVP_PKEY_DUP
+ rb_define_method(cRSA, "initialize_copy", ossl_rsa_initialize_copy, 1);
+#endif
+
rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0);
rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0);
- rb_define_method(cRSA, "to_text", ossl_rsa_to_text, 0);
rb_define_method(cRSA, "export", ossl_rsa_export, -1);
rb_define_alias(cRSA, "to_pem", "export");
rb_define_alias(cRSA, "to_s", "export");
rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0);
- rb_define_method(cRSA, "public_key", ossl_rsa_to_public_key, 0);
- rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1);
- rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1);
- rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1);
- rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1);
+ rb_define_method(cRSA, "sign_pss", ossl_rsa_sign_pss, -1);
+ rb_define_method(cRSA, "verify_pss", ossl_rsa_verify_pss, -1);
DEF_OSSL_PKEY_BN(cRSA, rsa, n);
DEF_OSSL_PKEY_BN(cRSA, rsa, e);
@@ -487,13 +570,9 @@ Init_ossl_rsa()
DEF_OSSL_PKEY_BN(cRSA, rsa, dmp1);
DEF_OSSL_PKEY_BN(cRSA, rsa, dmq1);
DEF_OSSL_PKEY_BN(cRSA, rsa, iqmp);
-
- rb_define_method(cRSA, "params", ossl_rsa_get_params, 0);
-
- DefRSAConst(PKCS1_PADDING);
- DefRSAConst(SSLV23_PADDING);
- DefRSAConst(NO_PADDING);
- DefRSAConst(PKCS1_OAEP_PADDING);
+ rb_define_method(cRSA, "set_key", ossl_rsa_set_key, 3);
+ rb_define_method(cRSA, "set_factors", ossl_rsa_set_factors, 2);
+ rb_define_method(cRSA, "set_crt_params", ossl_rsa_set_crt_params, 3);
/*
* TODO: Test it
@@ -503,11 +582,8 @@ Init_ossl_rsa()
}
#else /* defined NO_RSA */
-# warning >>> OpenSSL is compiled without RSA support <<<
void
-Init_ossl_rsa()
+Init_ossl_rsa(void)
{
- rb_warning("OpenSSL is compiled without RSA support");
}
#endif /* NO_RSA */
-
diff --git a/ext/openssl/ossl_provider.c b/ext/openssl/ossl_provider.c
new file mode 100644
index 0000000000..ea5abb8e48
--- /dev/null
+++ b/ext/openssl/ossl_provider.c
@@ -0,0 +1,204 @@
+/*
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
+ */
+#include "ossl.h"
+
+#ifdef OSSL_USE_PROVIDER
+#define NewProvider(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_provider_type, 0)
+#define SetProvider(obj, provider) do { \
+ if (!(provider)) { \
+ ossl_raise(rb_eRuntimeError, "Provider wasn't initialized."); \
+ } \
+ RTYPEDDATA_DATA(obj) = (provider); \
+} while(0)
+#define GetProvider(obj, provider) do { \
+ TypedData_Get_Struct((obj), OSSL_PROVIDER, &ossl_provider_type, (provider)); \
+ if (!(provider)) { \
+ ossl_raise(rb_eRuntimeError, "PROVIDER wasn't initialized."); \
+ } \
+} while (0)
+
+static const rb_data_type_t ossl_provider_type = {
+ "OpenSSL/Provider",
+ {
+ 0,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+/*
+ * Classes
+ */
+/* Document-class: OpenSSL::Provider
+ *
+ * This class is the access to openssl's Provider
+ * See also, https://www.openssl.org/docs/manmaster/man7/provider.html
+ */
+static VALUE cProvider;
+/* Document-class: OpenSSL::Provider::ProviderError
+ *
+ * This is the generic exception for OpenSSL::Provider related errors
+ */
+static VALUE eProviderError;
+
+/*
+ * call-seq:
+ * OpenSSL::Provider.load(name) -> provider
+ *
+ * This method loads and initializes a provider
+ */
+static VALUE
+ossl_provider_s_load(VALUE klass, VALUE name)
+{
+ OSSL_PROVIDER *provider = NULL;
+ VALUE obj;
+
+ const char *provider_name_ptr = StringValueCStr(name);
+
+ provider = OSSL_PROVIDER_load(NULL, provider_name_ptr);
+ if (provider == NULL) {
+ ossl_raise(eProviderError, "Failed to load %s provider", provider_name_ptr);
+ }
+ obj = NewProvider(klass);
+ SetProvider(obj, provider);
+
+ return obj;
+}
+
+struct ary_with_state { VALUE ary; int state; };
+struct rb_push_provider_name_args { OSSL_PROVIDER *prov; VALUE ary; };
+
+static VALUE
+rb_push_provider_name(VALUE rb_push_provider_name_args)
+{
+ struct rb_push_provider_name_args *args = (struct rb_push_provider_name_args *)rb_push_provider_name_args;
+
+ VALUE name = rb_str_new2(OSSL_PROVIDER_get0_name(args->prov));
+ return rb_ary_push(args->ary, name);
+}
+
+static int
+push_provider(OSSL_PROVIDER *prov, void *cbdata)
+{
+ struct ary_with_state *ary_with_state = (struct ary_with_state *)cbdata;
+ struct rb_push_provider_name_args args = { prov, ary_with_state->ary };
+
+ rb_protect(rb_push_provider_name, (VALUE)&args, &ary_with_state->state);
+ if (ary_with_state->state) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+/*
+ * call-seq:
+ * OpenSSL::Provider.provider_names -> [provider_name, ...]
+ *
+ * Returns an array of currently loaded provider names.
+ */
+static VALUE
+ossl_provider_s_provider_names(VALUE klass)
+{
+ VALUE ary = rb_ary_new();
+ struct ary_with_state cbdata = { ary, 0 };
+
+ int result = OSSL_PROVIDER_do_all(NULL, &push_provider, (void*)&cbdata);
+ if (result != 1 ) {
+ if (cbdata.state) {
+ rb_jump_tag(cbdata.state);
+ } else {
+ ossl_raise(eProviderError, "Failed to load provider names");
+ }
+ }
+
+ return ary;
+}
+
+/*
+ * call-seq:
+ * provider.unload -> true
+ *
+ * This method unloads this provider.
+ *
+ * if provider unload fails or already unloaded, it raises OpenSSL::Provider::ProviderError
+ */
+static VALUE
+ossl_provider_unload(VALUE self)
+{
+ OSSL_PROVIDER *prov;
+ if (RTYPEDDATA_DATA(self) == NULL) {
+ ossl_raise(eProviderError, "Provider already unloaded.");
+ }
+ GetProvider(self, prov);
+
+ int result = OSSL_PROVIDER_unload(prov);
+
+ if (result != 1) {
+ ossl_raise(eProviderError, "Failed to unload provider");
+ }
+ RTYPEDDATA_DATA(self) = NULL;
+ return Qtrue;
+}
+
+/*
+ * call-seq:
+ * provider.name -> string
+ *
+ * Get the name of this provider.
+ *
+ * if this provider is already unloaded, it raises OpenSSL::Provider::ProviderError
+ */
+static VALUE
+ossl_provider_get_name(VALUE self)
+{
+ OSSL_PROVIDER *prov;
+ if (RTYPEDDATA_DATA(self) == NULL) {
+ ossl_raise(eProviderError, "Provider already unloaded.");
+ }
+ GetProvider(self, prov);
+
+ return rb_str_new2(OSSL_PROVIDER_get0_name(prov));
+}
+
+/*
+ * call-seq:
+ * provider.inspect -> string
+ *
+ * Pretty prints this provider.
+ */
+static VALUE
+ossl_provider_inspect(VALUE self)
+{
+ OSSL_PROVIDER *prov;
+ if (RTYPEDDATA_DATA(self) == NULL ) {
+ return rb_sprintf("#<%"PRIsVALUE" unloaded provider>", rb_obj_class(self));
+ }
+ GetProvider(self, prov);
+
+ return rb_sprintf("#<%"PRIsVALUE" name=\"%s\">",
+ rb_obj_class(self), OSSL_PROVIDER_get0_name(prov));
+}
+
+void
+Init_ossl_provider(void)
+{
+ cProvider = rb_define_class_under(mOSSL, "Provider", rb_cObject);
+ eProviderError = rb_define_class_under(cProvider, "ProviderError", eOSSLError);
+
+ rb_undef_alloc_func(cProvider);
+ rb_define_singleton_method(cProvider, "load", ossl_provider_s_load, 1);
+ rb_define_singleton_method(cProvider, "provider_names", ossl_provider_s_provider_names, 0);
+
+ rb_define_method(cProvider, "unload", ossl_provider_unload, 0);
+ rb_define_method(cProvider, "name", ossl_provider_get_name, 0);
+ rb_define_method(cProvider, "inspect", ossl_provider_inspect, 0);
+}
+#else
+void
+Init_ossl_provider(void)
+{
+}
+#endif
diff --git a/ext/openssl/ossl_provider.h b/ext/openssl/ossl_provider.h
new file mode 100644
index 0000000000..1d69cb1e44
--- /dev/null
+++ b/ext/openssl/ossl_provider.h
@@ -0,0 +1,5 @@
+#if !defined(OSSL_PROVIDER_H)
+#define OSSL_PROVIDER_H
+
+void Init_ossl_provider(void);
+#endif
diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c
index ec9883d70a..753f8b25f7 100644
--- a/ext/openssl/ossl_rand.c
+++ b/ext/openssl/ossl_rand.c
@@ -1,130 +1,193 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ *
* All rights reserved.
- */
-/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ *
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-/*
- * Classes
- */
-VALUE mRandom;
-VALUE eRandomError;
+static VALUE mRandom;
+static VALUE eRandomError;
/*
- * Struct
+ * call-seq:
+ * seed(str) -> str
+ *
+ * ::seed is equivalent to ::add where _entropy_ is length of _str_.
*/
+static VALUE
+ossl_rand_seed(VALUE self, VALUE str)
+{
+ StringValue(str);
+ RAND_seed(RSTRING_PTR(str), RSTRING_LENINT(str));
-/*
- * Public
- */
+ return str;
+}
/*
- * Private
+ * call-seq:
+ * add(str, entropy) -> self
+ *
+ * Mixes the bytes from _str_ into the Pseudo Random Number Generator(PRNG)
+ * state.
+ *
+ * Thus, if the data from _str_ are unpredictable to an adversary, this
+ * increases the uncertainty about the state and makes the PRNG output less
+ * predictable.
+ *
+ * The _entropy_ argument is (the lower bound of) an estimate of how much
+ * randomness is contained in _str_, measured in bytes.
+ *
+ * === Example
+ *
+ * pid = $$
+ * now = Time.now
+ * ary = [now.to_i, now.nsec, 1000, pid]
+ * OpenSSL::Random.add(ary.join, 0.0)
+ * OpenSSL::Random.seed(ary.join)
*/
static VALUE
-ossl_rand_seed(VALUE self, VALUE str)
+ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
{
StringValue(str);
- RAND_seed(RSTRING(str)->ptr, RSTRING(str)->len);
+ RAND_add(RSTRING_PTR(str), RSTRING_LENINT(str), NUM2DBL(entropy));
- return str;
+ return self;
}
+/*
+ * call-seq:
+ * load_random_file(filename) -> true
+ *
+ * Reads bytes from _filename_ and adds them to the PRNG.
+ */
static VALUE
ossl_rand_load_file(VALUE self, VALUE filename)
{
- SafeStringValue(filename);
-
- if(!RAND_load_file(RSTRING(filename)->ptr, -1)) {
- ossl_raise(eRandomError, NULL);
+ if(!RAND_load_file(StringValueCStr(filename), -1)) {
+ ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
+/*
+ * call-seq:
+ * write_random_file(filename) -> true
+ *
+ * Writes a number of random generated bytes (currently 1024) to _filename_
+ * which can be used to initialize the PRNG by calling ::load_random_file in a
+ * later session.
+ */
static VALUE
ossl_rand_write_file(VALUE self, VALUE filename)
{
- SafeStringValue(filename);
- if (RAND_write_file(RSTRING(filename)->ptr) == -1) {
- ossl_raise(eRandomError, NULL);
+ if (RAND_write_file(StringValueCStr(filename)) == -1) {
+ ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
+/*
+ * call-seq:
+ * random_bytes(length) -> string
+ *
+ * Generates a String with _length_ number of cryptographically strong
+ * pseudo-random bytes.
+ *
+ * === Example
+ *
+ * OpenSSL::Random.random_bytes(12)
+ * #=> "..."
+ */
static VALUE
ossl_rand_bytes(VALUE self, VALUE len)
{
VALUE str;
-
- str = rb_str_new(0, FIX2INT(len));
- if (!RAND_bytes(RSTRING(str)->ptr, FIX2INT(len))) {
- ossl_raise(eRandomError, NULL);
- }
-
- return str;
-}
-
-static VALUE
-ossl_rand_pseudo_bytes(VALUE self, VALUE len)
-{
- VALUE str;
-
- str = rb_str_new(0, FIX2INT(len));
- if (!RAND_pseudo_bytes(RSTRING(str)->ptr, FIX2INT(len))) {
- ossl_raise(eRandomError, NULL);
+ int n = NUM2INT(len);
+ int ret;
+
+ str = rb_str_new(0, n);
+ ret = RAND_bytes((unsigned char *)RSTRING_PTR(str), n);
+ if (ret == 0) {
+ ossl_raise(eRandomError, "RAND_bytes");
+ } else if (ret == -1) {
+ ossl_raise(eRandomError, "RAND_bytes is not supported");
}
return str;
}
+#ifdef HAVE_RAND_EGD
+/*
+ * call-seq:
+ * egd(filename) -> true
+ *
+ * Same as ::egd_bytes but queries 255 bytes by default.
+ */
static VALUE
ossl_rand_egd(VALUE self, VALUE filename)
{
- SafeStringValue(filename);
-
- if(!RAND_egd(RSTRING(filename)->ptr)) {
- ossl_raise(eRandomError, NULL);
+ if (RAND_egd(StringValueCStr(filename)) == -1) {
+ ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
+/*
+ * call-seq:
+ * egd_bytes(filename, length) -> true
+ *
+ * Queries the entropy gathering daemon EGD on socket path given by _filename_.
+ *
+ * Fetches _length_ number of bytes and uses ::add to seed the OpenSSL built-in
+ * PRNG.
+ */
static VALUE
ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
{
- SafeStringValue(filename);
+ int n = NUM2INT(len);
- if (!RAND_egd_bytes(RSTRING(filename)->ptr, FIX2INT(len))) {
- ossl_raise(eRandomError, NULL);
+ if (RAND_egd_bytes(StringValueCStr(filename), n) == -1) {
+ ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
+#endif /* HAVE_RAND_EGD */
-#define DEFMETH(class, name, func, argc) \
- rb_define_method(class, name, func, argc); \
- rb_define_singleton_method(class, name, func, argc);
+/*
+ * call-seq:
+ * status? => true | false
+ *
+ * Return +true+ if the PRNG has been seeded with enough data, +false+ otherwise.
+ */
+static VALUE
+ossl_rand_status(VALUE self)
+{
+ return RAND_status() ? Qtrue : Qfalse;
+}
/*
* INIT
*/
void
-Init_ossl_rand()
+Init_ossl_rand(void)
{
mRandom = rb_define_module_under(mOSSL, "Random");
-
+
eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError);
-
- DEFMETH(mRandom, "seed", ossl_rand_seed, 1);
- DEFMETH(mRandom, "load_random_file", ossl_rand_load_file, 1);
- DEFMETH(mRandom, "write_random_file", ossl_rand_write_file, 1);
- DEFMETH(mRandom, "random_bytes", ossl_rand_bytes, 1);
- DEFMETH(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
- DEFMETH(mRandom, "egd", ossl_rand_egd, 1);
- DEFMETH(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
-}
+ rb_define_module_function(mRandom, "seed", ossl_rand_seed, 1);
+ rb_define_module_function(mRandom, "random_add", ossl_rand_add, 2);
+ rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1);
+ rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1);
+ rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1);
+ rb_define_alias(rb_singleton_class(mRandom), "pseudo_bytes", "random_bytes");
+#ifdef HAVE_RAND_EGD
+ rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1);
+ rb_define_module_function(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
+#endif /* HAVE_RAND_EGD */
+ rb_define_module_function(mRandom, "status?", ossl_rand_status, 0);
+}
diff --git a/ext/openssl/ossl_rand.h b/ext/openssl/ossl_rand.h
index ce2ae0d129..294986d017 100644
--- a/ext/openssl/ossl_rand.h
+++ b/ext/openssl/ossl_rand.h
@@ -1,20 +1,15 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_RAND_H_)
#define _OSSL_RAND_H_
-extern VALUE mRandom;
-extern VALUE eRandomError;
-
void Init_ossl_rand(void);
#endif /* _OSSL_RAND_H_ */
-
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 92384f1b1a..3d913a3968 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -1,413 +1,947 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2000-2002 GOTOU Yuuzou <gotoyuzo@notwork.org>
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ * Copyright (C) 2001-2007 Technorama Ltd. <oss-ruby@technorama.net>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#include <rubysig.h>
-#include <rubyio.h>
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h> /* for read(), and write() */
-#endif
+#ifndef OPENSSL_NO_SOCK
+#define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
-#define numberof(ary) (sizeof(ary)/sizeof(ary[0]))
+#if !defined(OPENSSL_NO_NEXTPROTONEG) && !OSSL_IS_LIBRESSL
+# define OSSL_USE_NEXTPROTONEG
+#endif
#ifdef _WIN32
# define TO_SOCKET(s) _get_osfhandle(s)
#else
-# define TO_SOCKET(s) s
+# define TO_SOCKET(s) (s)
#endif
+#define GetSSLCTX(obj, ctx) do { \
+ TypedData_Get_Struct((obj), SSL_CTX, &ossl_sslctx_type, (ctx)); \
+} while (0)
+
VALUE mSSL;
-VALUE eSSLError;
-VALUE cSSLContext;
+static VALUE eSSLError;
+static VALUE cSSLContext;
VALUE cSSLSocket;
-/*
- * SSLContext class
- */
-#define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v))
-#define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v))
-#define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v))
-#define ossl_sslctx_set_ca_file(o,v) rb_iv_set((o),"@ca_file",(v))
-#define ossl_sslctx_set_ca_path(o,v) rb_iv_set((o),"@ca_path",(v))
-#define ossl_sslctx_set_timeout(o,v) rb_iv_set((o),"@timeout",(v))
-#define ossl_sslctx_set_verify_mode(o,v) rb_iv_set((o),"@verify_mode",(v))
-#define ossl_sslctx_set_verify_dep(o,v) rb_iv_set((o),"@verify_depth",(v))
-#define ossl_sslctx_set_verify_cb(o,v) rb_iv_set((o),"@verify_callback",(v))
-#define ossl_sslctx_set_options(o,v) rb_iv_set((o),"@options",(v))
-#define ossl_sslctx_set_cert_store(o,v) rb_iv_set((o),"@cert_store",(v))
-#define ossl_sslctx_set_extra_cert(o,v) rb_iv_set((o),"@extra_chain_cert",(v))
-#define ossl_sslctx_set_client_cert_cb(o,v) rb_iv_set((o),"@client_cert_cb",(v))
-#define ossl_sslctx_set_tmp_dh_cb(o,v) rb_iv_set((o),"@tmp_dh_callback",(v))
-#define ossl_sslctx_set_sess_id_ctx(o, v) rb_iv_get((o),"@session_id_context"(v))
-
-#define ossl_sslctx_get_cert(o) rb_iv_get((o),"@cert")
-#define ossl_sslctx_get_key(o) rb_iv_get((o),"@key")
-#define ossl_sslctx_get_client_ca(o) rb_iv_get((o),"@client_ca")
-#define ossl_sslctx_get_ca_file(o) rb_iv_get((o),"@ca_file")
-#define ossl_sslctx_get_ca_path(o) rb_iv_get((o),"@ca_path")
-#define ossl_sslctx_get_timeout(o) rb_iv_get((o),"@timeout")
-#define ossl_sslctx_get_verify_mode(o) rb_iv_get((o),"@verify_mode")
-#define ossl_sslctx_get_verify_dep(o) rb_iv_get((o),"@verify_depth")
-#define ossl_sslctx_get_verify_cb(o) rb_iv_get((o),"@verify_callback")
-#define ossl_sslctx_get_options(o) rb_iv_get((o),"@options")
-#define ossl_sslctx_get_cert_store(o) rb_iv_get((o),"@cert_store")
-#define ossl_sslctx_get_extra_cert(o) rb_iv_get((o),"@extra_chain_cert")
-#define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb")
-#define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback")
-#define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context")
-
-static char *ossl_sslctx_attrs[] = {
- "cert", "key", "client_ca", "ca_file", "ca_path",
- "timeout", "verify_mode", "verify_depth",
- "verify_callback", "options", "cert_store", "extra_chain_cert",
- "client_cert_cb", "tmp_dh_callback", "session_id_context",
-};
-
-#define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
-#define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context")
-#define ossl_ssl_get_sync_close(o) rb_iv_get((o),"@sync_close")
-#define ossl_ssl_get_x509(o) rb_iv_get((o),"@x509")
-#define ossl_ssl_get_key(o) rb_iv_get((o),"@key")
-#define ossl_ssl_get_tmp_dh(o) rb_iv_get((o),"@tmp_dh")
+static VALUE eSSLErrorWaitReadable;
+static VALUE eSSLErrorWaitWritable;
-#define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v))
-#define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v))
-#define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v))
-#define ossl_ssl_set_x509(o,v) rb_iv_set((o),"@x509",(v))
-#define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v))
-#define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
+static ID id_call, ID_callback_state, id_npn_protocols_encoded, id_each;
+static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
-static char *ossl_ssl_attr_readers[] = { "io", "context", };
-static char *ossl_ssl_attrs[] = { "sync_close", };
+static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
+ id_i_verify_depth, id_i_verify_callback, id_i_client_ca,
+ id_i_renegotiation_cb, id_i_cert, id_i_key, id_i_extra_chain_cert,
+ id_i_client_cert_cb, id_i_timeout,
+ id_i_session_id_context, id_i_session_get_cb, id_i_session_new_cb,
+ id_i_session_remove_cb, id_i_npn_select_cb, id_i_npn_protocols,
+ id_i_alpn_select_cb, id_i_alpn_protocols, id_i_servername_cb,
+ id_i_verify_hostname, id_i_keylog_cb, id_i_tmp_dh_callback;
+static ID id_i_io, id_i_context, id_i_hostname, id_i_sync_close;
-/*
- * SSLContext class
- */
-struct {
- const char *name;
- SSL_METHOD *(*func)(void);
-} ossl_ssl_method_tab[] = {
-#define OSSL_SSL_METHOD_ENTRY(name) { #name, name##_method }
- OSSL_SSL_METHOD_ENTRY(TLSv1),
- OSSL_SSL_METHOD_ENTRY(TLSv1_server),
- OSSL_SSL_METHOD_ENTRY(TLSv1_client),
- OSSL_SSL_METHOD_ENTRY(SSLv2),
- OSSL_SSL_METHOD_ENTRY(SSLv2_server),
- OSSL_SSL_METHOD_ENTRY(SSLv2_client),
- OSSL_SSL_METHOD_ENTRY(SSLv3),
- OSSL_SSL_METHOD_ENTRY(SSLv3_server),
- OSSL_SSL_METHOD_ENTRY(SSLv3_client),
- OSSL_SSL_METHOD_ENTRY(SSLv23),
- OSSL_SSL_METHOD_ENTRY(SSLv23_server),
- OSSL_SSL_METHOD_ENTRY(SSLv23_client),
-#undef OSSL_SSL_METHOD_ENTRY
-};
+static int ossl_ssl_ex_ptr_idx;
+static int ossl_sslctx_ex_ptr_idx;
-int ossl_ssl_ex_vcb_idx;
-int ossl_ssl_ex_store_p;
-int ossl_ssl_ex_ptr_idx;
-int ossl_ssl_ex_client_cert_cb_idx;
-int ossl_ssl_ex_tmp_dh_callback_idx;
+static void
+ossl_sslctx_mark(void *ptr)
+{
+ SSL_CTX *ctx = ptr;
+ rb_gc_mark((VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx));
+}
static void
-ossl_sslctx_free(SSL_CTX *ctx)
+ossl_sslctx_free(void *ptr)
{
- if(ctx && SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_store_p)== (void*)1)
- ctx->cert_store = NULL;
- SSL_CTX_free(ctx);
+ SSL_CTX_free(ptr);
}
+static const rb_data_type_t ossl_sslctx_type = {
+ "OpenSSL/SSL/CTX",
+ {
+ ossl_sslctx_mark, ossl_sslctx_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
static VALUE
ossl_sslctx_s_alloc(VALUE klass)
{
SSL_CTX *ctx;
+ long mode = 0 |
+ SSL_MODE_ENABLE_PARTIAL_WRITE |
+ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
+ SSL_MODE_RELEASE_BUFFERS;
+ VALUE obj;
- ctx = SSL_CTX_new(SSLv23_method());
+ obj = TypedData_Wrap_Struct(klass, &ossl_sslctx_type, 0);
+ ctx = SSL_CTX_new(TLS_method());
if (!ctx) {
- ossl_raise(eSSLError, "SSL_CTX_new:");
+ ossl_raise(eSSLError, "SSL_CTX_new");
}
- SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
- SSL_CTX_set_options(ctx, SSL_OP_ALL);
- return Data_Wrap_Struct(klass, 0, ossl_sslctx_free, ctx);
+ SSL_CTX_set_mode(ctx, mode);
+ SSL_CTX_set_dh_auto(ctx, 1);
+ RTYPEDDATA_DATA(obj) = ctx;
+ if (!SSL_CTX_set_ex_data(ctx, ossl_sslctx_ex_ptr_idx, (void *)obj))
+ ossl_raise(eSSLError, "SSL_CTX_set_ex_data");
+
+ return obj;
}
static VALUE
-ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
+ossl_call_client_cert_cb(VALUE obj)
{
- VALUE ssl_method;
- SSL_METHOD *method = NULL;
- SSL_CTX *ctx;
- int i;
- char *s;
+ VALUE ctx_obj, cb, ary, cert, key;
+
+ ctx_obj = rb_attr_get(obj, id_i_context);
+ cb = rb_attr_get(ctx_obj, id_i_client_cert_cb);
+ if (NIL_P(cb))
+ return Qnil;
+
+ ary = rb_funcallv(cb, id_call, 1, &obj);
+ Check_Type(ary, T_ARRAY);
+ GetX509CertPtr(cert = rb_ary_entry(ary, 0));
+ GetPrivPKeyPtr(key = rb_ary_entry(ary, 1));
+
+ return rb_ary_new3(2, cert, key);
+}
+
+static int
+ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
+{
+ VALUE obj, ret;
- for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
- char buf[32];
- snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]);
- rb_iv_set(self, buf, Qnil);
+ obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ ret = rb_protect(ossl_call_client_cert_cb, obj, NULL);
+ if (NIL_P(ret))
+ return 0;
+
+ *x509 = DupX509CertPtr(RARRAY_AREF(ret, 0));
+ *pkey = DupPKeyPtr(RARRAY_AREF(ret, 1));
+
+ return 1;
+}
+
+#if !defined(OPENSSL_NO_DH)
+struct tmp_dh_callback_args {
+ VALUE ssl_obj;
+ int is_export;
+ int keylength;
+};
+
+static VALUE
+ossl_call_tmp_dh_callback(VALUE arg)
+{
+ struct tmp_dh_callback_args *args = (struct tmp_dh_callback_args *)arg;
+ VALUE ctx_obj, cb, obj;
+ const DH *dh;
+
+ ctx_obj = rb_attr_get(args->ssl_obj, id_i_context);
+ cb = rb_attr_get(ctx_obj, id_i_tmp_dh_callback);
+ if (NIL_P(cb))
+ return (VALUE)NULL;
+
+ obj = rb_funcall(cb, id_call, 3, args->ssl_obj, INT2NUM(args->is_export),
+ INT2NUM(args->keylength));
+ // TODO: We should riase if obj is not DH
+ dh = EVP_PKEY_get0_DH(GetPKeyPtr(obj));
+ if (!dh)
+ ossl_clear_error();
+
+ return (VALUE)dh;
+}
+
+static DH *
+ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
+{
+ int state;
+ VALUE rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ struct tmp_dh_callback_args args = {rb_ssl, is_export, keylength};
+ VALUE ret = rb_protect(ossl_call_tmp_dh_callback, (VALUE)&args, &state);
+ if (state) {
+ rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state));
+ return NULL;
}
- if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){
- return self;
+ return (DH *)ret;
+}
+#endif /* OPENSSL_NO_DH */
+
+static VALUE
+call_verify_certificate_identity(VALUE ctx_v)
+{
+ X509_STORE_CTX *ctx = (X509_STORE_CTX *)ctx_v;
+ SSL *ssl;
+ VALUE ssl_obj, hostname, cert_obj;
+
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ hostname = rb_attr_get(ssl_obj, id_i_hostname);
+
+ if (!RTEST(hostname)) {
+ rb_warning("verify_hostname requires hostname to be set");
+ return Qtrue;
}
- if(TYPE(ssl_method) == T_SYMBOL)
- s = rb_id2name(SYM2ID(ssl_method));
- else
- s = StringValuePtr(ssl_method);
- for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
- if (strcmp(ossl_ssl_method_tab[i].name, s) == 0) {
- method = ossl_ssl_method_tab[i].func();
- break;
+
+ cert_obj = ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
+ return rb_funcall(mSSL, rb_intern("verify_certificate_identity"), 2,
+ cert_obj, hostname);
+}
+
+static int
+ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
+{
+ VALUE cb, ssl_obj, sslctx_obj, verify_hostname, ret;
+ SSL *ssl;
+ int status;
+
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ sslctx_obj = rb_attr_get(ssl_obj, id_i_context);
+ cb = rb_attr_get(sslctx_obj, id_i_verify_callback);
+ verify_hostname = rb_attr_get(sslctx_obj, id_i_verify_hostname);
+
+ if (preverify_ok && RTEST(verify_hostname) && !SSL_is_server(ssl) &&
+ !X509_STORE_CTX_get_error_depth(ctx)) {
+ ret = rb_protect(call_verify_certificate_identity, (VALUE)ctx, &status);
+ if (status) {
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
+ return 0;
+ }
+ if (ret != Qtrue) {
+ preverify_ok = 0;
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH);
}
}
- if (!method) {
- ossl_raise(rb_eArgError, "unknown SSL method `%s'.", s);
- }
- Data_Get_Struct(self, SSL_CTX, ctx);
- if (SSL_CTX_set_ssl_version(ctx, method) != 1) {
- ossl_raise(eSSLError, "SSL_CTX_set_ssl_version:");
+
+ return ossl_verify_cb_call(cb, preverify_ok, ctx);
+}
+
+static VALUE
+ossl_call_session_get_cb(VALUE ary)
+{
+ VALUE ssl_obj, cb;
+
+ Check_Type(ary, T_ARRAY);
+ ssl_obj = rb_ary_entry(ary, 0);
+
+ cb = rb_funcall(ssl_obj, rb_intern("session_get_cb"), 0);
+ if (NIL_P(cb)) return Qnil;
+
+ return rb_funcallv(cb, id_call, 1, &ary);
+}
+
+static SSL_SESSION *
+ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy)
+{
+ VALUE ary, ssl_obj, ret_obj;
+ SSL_SESSION *sess;
+ int state = 0;
+
+ OSSL_Debug("SSL SESSION get callback entered");
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, ssl_obj);
+ rb_ary_push(ary, rb_str_new((const char *)buf, len));
+
+ ret_obj = rb_protect(ossl_call_session_get_cb, ary, &state);
+ if (state) {
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
+ return NULL;
}
+ if (!rb_obj_is_instance_of(ret_obj, cSSLSession))
+ return NULL;
- return self;
+ GetSSLSession(ret_obj, sess);
+ *copy = 1;
+
+ return sess;
}
static VALUE
-ossl_call_client_cert_cb(VALUE obj)
+ossl_call_session_new_cb(VALUE ary)
{
- VALUE cb, ary, cert, key;
- SSL *ssl;
+ VALUE ssl_obj, cb;
- Data_Get_Struct(obj, SSL, ssl);
- cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx);
- if (NIL_P(cb)) return Qfalse;
- ary = rb_funcall(cb, rb_intern("call"), 1, obj);
Check_Type(ary, T_ARRAY);
- GetX509CertPtr(cert = rb_ary_entry(ary, 0));
- GetPKeyPtr(key = rb_ary_entry(ary, 1));
- ossl_ssl_set_x509(obj, cert);
- ossl_ssl_set_key(obj, key);
+ ssl_obj = rb_ary_entry(ary, 0);
- return Qtrue;
+ cb = rb_funcall(ssl_obj, rb_intern("session_new_cb"), 0);
+ if (NIL_P(cb)) return Qnil;
+
+ return rb_funcallv(cb, id_call, 1, &ary);
}
+/* return 1 normal. return 0 removes the session */
static int
-ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
+ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
{
- VALUE obj;
- int status, success;
+ VALUE ary, ssl_obj, sess_obj;
+ int state = 0;
- obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
- success = rb_protect((VALUE(*)_((VALUE)))ossl_call_client_cert_cb,
- obj, &status);
- if (status || !success) return 0;
- *x509 = DupX509CertPtr(ossl_ssl_get_x509(obj));
- *pkey = DupPKeyPtr(ossl_ssl_get_key(obj));
+ OSSL_Debug("SSL SESSION new callback entered");
- return 1;
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ sess_obj = rb_obj_alloc(cSSLSession);
+ SSL_SESSION_up_ref(sess);
+ DATA_PTR(sess_obj) = sess;
+
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, ssl_obj);
+ rb_ary_push(ary, sess_obj);
+
+ rb_protect(ossl_call_session_new_cb, ary, &state);
+ if (state) {
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
+ }
+
+ /*
+ * return 0 which means to OpenSSL that the session is still
+ * valid (since we created Ruby Session object) and was not freed by us
+ * with SSL_SESSION_free(). Call SSLContext#remove_session(sess) in
+ * session_get_cb block if you don't want OpenSSL to cache the session
+ * internally.
+ */
+ return 0;
}
-#if !defined(OPENSSL_NO_DH)
+#if !OSSL_IS_LIBRESSL
+/*
+ * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
+ * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
+ * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
+ */
+
+struct ossl_call_keylog_cb_args {
+ VALUE ssl_obj;
+ const char * line;
+};
+
static VALUE
-ossl_call_tmp_dh_callback(VALUE *args)
+ossl_call_keylog_cb(VALUE args_v)
{
- SSL *ssl;
- VALUE cb, dh;
- EVP_PKEY *pkey;
+ VALUE sslctx_obj, cb, line_v;
+ struct ossl_call_keylog_cb_args *args = (struct ossl_call_keylog_cb_args *) args_v;
- Data_Get_Struct(args[0], SSL, ssl);
- cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx);
- if (NIL_P(cb)) return Qfalse;
- dh = rb_funcall(cb, rb_intern("call"), 3, args[0], args[1], args[2]);
- pkey = GetPKeyPtr(dh);
- if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) return Qfalse;
- ossl_ssl_set_tmp_dh(args[0], dh);
+ sslctx_obj = rb_attr_get(args->ssl_obj, id_i_context);
- return Qtrue;
+ cb = rb_attr_get(sslctx_obj, id_i_keylog_cb);
+ if (NIL_P(cb)) return Qnil;
+
+ line_v = rb_str_new_cstr(args->line);
+
+ return rb_funcall(cb, id_call, 2, args->ssl_obj, line_v);
}
-static DH*
-ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
+static void
+ossl_sslctx_keylog_cb(const SSL *ssl, const char *line)
{
- VALUE args[3];
- int status, success;
+ VALUE ssl_obj;
+ struct ossl_call_keylog_cb_args args;
+ int state = 0;
+
+ OSSL_Debug("SSL keylog callback entered");
- args[0] = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
- args[1] = INT2FIX(is_export);
- args[2] = INT2FIX(keylength);
- success = rb_protect((VALUE(*)_((VALUE)))ossl_call_tmp_dh_callback,
- (VALUE)args, &status);
- if (status || !success) return NULL;
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ args.ssl_obj = ssl_obj;
+ args.line = line;
- return GetPKeyPtr(ossl_ssl_get_tmp_dh(args[0]))->pkey.dh;
+ rb_protect(ossl_call_keylog_cb, (VALUE)&args, &state);
+ if (state) {
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
+ }
}
+#endif
-static DH*
-ossl_default_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
+static VALUE
+ossl_call_session_remove_cb(VALUE ary)
{
- switch(keylength){
- case 512:
- return OSSL_DEFAULT_DH_512;
- case 1024:
- return OSSL_DEFAULT_DH_1024;
- }
- return NULL;
+ VALUE sslctx_obj, cb;
+
+ Check_Type(ary, T_ARRAY);
+ sslctx_obj = rb_ary_entry(ary, 0);
+
+ cb = rb_attr_get(sslctx_obj, id_i_session_remove_cb);
+ if (NIL_P(cb)) return Qnil;
+
+ return rb_funcallv(cb, id_call, 1, &ary);
}
-#endif /* OPENSSL_NO_DH */
-static int
-ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
+static void
+ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
{
- VALUE cb;
- SSL *ssl;
+ VALUE ary, sslctx_obj, sess_obj;
+ int state = 0;
- ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
- cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx);
- X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, (void*)cb);
- return ossl_verify_cb(preverify_ok, ctx);
+ /*
+ * This callback is also called for all sessions in the internal store
+ * when SSL_CTX_free() is called.
+ */
+ if (rb_during_gc())
+ return;
+
+ OSSL_Debug("SSL SESSION remove callback entered");
+
+ sslctx_obj = (VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx);
+ sess_obj = rb_obj_alloc(cSSLSession);
+ SSL_SESSION_up_ref(sess);
+ DATA_PTR(sess_obj) = sess;
+
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, sslctx_obj);
+ rb_ary_push(ary, sess_obj);
+
+ rb_protect(ossl_call_session_remove_cb, ary, &state);
+ if (state) {
+/*
+ the SSL_CTX is frozen, nowhere to save state.
+ there is no common accessor method to check it either.
+ rb_ivar_set(sslctx_obj, ID_callback_state, INT2NUM(state));
+*/
+ }
}
static VALUE
-ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg)
+ossl_sslctx_add_extra_chain_cert_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
{
X509 *x509;
SSL_CTX *ctx;
- Data_Get_Struct(arg, SSL_CTX, ctx);
+ GetSSLCTX(arg, ctx);
x509 = DupX509CertPtr(i);
- if(!SSL_CTX_add_extra_chain_cert(ctx, x509)){
- ossl_raise(eSSLError, NULL);
+ if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) {
+ X509_free(x509);
+ ossl_raise(eSSLError, "SSL_CTX_add_extra_chain_cert");
}
return i;
}
+static VALUE ossl_sslctx_setup(VALUE self);
+
+static VALUE
+ossl_call_servername_cb(VALUE arg)
+{
+ SSL *ssl = (void *)arg;
+ const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+ if (!servername)
+ return Qnil;
+
+ VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ VALUE sslctx_obj = rb_attr_get(ssl_obj, id_i_context);
+ VALUE cb = rb_attr_get(sslctx_obj, id_i_servername_cb);
+ VALUE ary = rb_assoc_new(ssl_obj, rb_str_new_cstr(servername));
+
+ VALUE ret_obj = rb_funcallv(cb, id_call, 1, &ary);
+ if (rb_obj_is_kind_of(ret_obj, cSSLContext)) {
+ SSL_CTX *ctx2;
+ ossl_sslctx_setup(ret_obj);
+ GetSSLCTX(ret_obj, ctx2);
+ if (!SSL_set_SSL_CTX(ssl, ctx2))
+ ossl_raise(eSSLError, "SSL_set_SSL_CTX");
+ rb_ivar_set(ssl_obj, id_i_context, ret_obj);
+ } else if (!NIL_P(ret_obj)) {
+ ossl_raise(rb_eArgError, "servername_cb must return an "
+ "OpenSSL::SSL::SSLContext object or nil");
+ }
+
+ return Qnil;
+}
+
+static int
+ssl_servername_cb(SSL *ssl, int *ad, void *arg)
+{
+ int state;
+
+ rb_protect(ossl_call_servername_cb, (VALUE)ssl, &state);
+ if (state) {
+ VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+ }
+
+ return SSL_TLSEXT_ERR_OK;
+}
+
+static void
+ssl_renegotiation_cb(const SSL *ssl)
+{
+ VALUE ssl_obj, sslctx_obj, cb;
+
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ sslctx_obj = rb_attr_get(ssl_obj, id_i_context);
+ cb = rb_attr_get(sslctx_obj, id_i_renegotiation_cb);
+ if (NIL_P(cb)) return;
+
+ rb_funcallv(cb, id_call, 1, &ssl_obj);
+}
+
+static VALUE
+ssl_npn_encode_protocol_i(RB_BLOCK_CALL_FUNC_ARGLIST(cur, encoded))
+{
+ int len = RSTRING_LENINT(cur);
+ char len_byte;
+ if (len < 1 || len > 255)
+ ossl_raise(eSSLError, "Advertised protocol must have length 1..255");
+ /* Encode the length byte */
+ len_byte = len;
+ rb_str_buf_cat(encoded, &len_byte, 1);
+ rb_str_buf_cat(encoded, RSTRING_PTR(cur), len);
+ return Qnil;
+}
+
+static VALUE
+ssl_encode_npn_protocols(VALUE protocols)
+{
+ VALUE encoded = rb_str_new(NULL, 0);
+ rb_block_call(protocols, id_each, 0, 0, ssl_npn_encode_protocol_i, encoded);
+ return encoded;
+}
+
+struct npn_select_cb_common_args {
+ VALUE cb;
+ const unsigned char *in;
+ unsigned inlen;
+};
+
+static VALUE
+npn_select_cb_common_i(VALUE tmp)
+{
+ struct npn_select_cb_common_args *args = (void *)tmp;
+ const unsigned char *in = args->in, *in_end = in + args->inlen;
+ unsigned char l;
+ long len;
+ VALUE selected, protocols = rb_ary_new();
+
+ /* assume OpenSSL verifies this format */
+ /* The format is len_1|proto_1|...|len_n|proto_n */
+ while (in < in_end) {
+ l = *in++;
+ rb_ary_push(protocols, rb_str_new((const char *)in, l));
+ in += l;
+ }
+
+ selected = rb_funcallv(args->cb, id_call, 1, &protocols);
+ StringValue(selected);
+ len = RSTRING_LEN(selected);
+ if (len < 1 || len >= 256) {
+ ossl_raise(eSSLError, "Selected protocol name must have length 1..255");
+ }
+
+ return selected;
+}
+
+static int
+ssl_npn_select_cb_common(SSL *ssl, VALUE cb, const unsigned char **out,
+ unsigned char *outlen, const unsigned char *in,
+ unsigned int inlen)
+{
+ VALUE selected;
+ int status;
+ struct npn_select_cb_common_args args;
+
+ args.cb = cb;
+ args.in = in;
+ args.inlen = inlen;
+
+ selected = rb_protect(npn_select_cb_common_i, (VALUE)&args, &status);
+ if (status) {
+ VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+ }
+
+ *out = (unsigned char *)RSTRING_PTR(selected);
+ *outlen = (unsigned char)RSTRING_LEN(selected);
+
+ return SSL_TLSEXT_ERR_OK;
+}
+
+#ifdef OSSL_USE_NEXTPROTONEG
+static int
+ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
+ void *arg)
+{
+ VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded);
+
+ *out = (const unsigned char *) RSTRING_PTR(protocols);
+ *outlen = RSTRING_LENINT(protocols);
+
+ return SSL_TLSEXT_ERR_OK;
+}
+
+static int
+ssl_npn_select_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen, void *arg)
+{
+ VALUE sslctx_obj, cb;
+
+ sslctx_obj = (VALUE) arg;
+ cb = rb_attr_get(sslctx_obj, id_i_npn_select_cb);
+
+ return ssl_npn_select_cb_common(ssl, cb, (const unsigned char **)out,
+ outlen, in, inlen);
+}
+#endif
+
+static int
+ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen, void *arg)
+{
+ VALUE sslctx_obj, cb;
+
+ sslctx_obj = (VALUE) arg;
+ cb = rb_attr_get(sslctx_obj, id_i_alpn_select_cb);
+
+ return ssl_npn_select_cb_common(ssl, cb, out, outlen, in, inlen);
+}
+
+/* This function may serve as the entry point to support further callbacks. */
+static void
+ssl_info_cb(const SSL *ssl, int where, int val)
+{
+ int is_server = SSL_is_server((SSL *)ssl);
+
+ if (is_server && where & SSL_CB_HANDSHAKE_START) {
+ ssl_renegotiation_cb(ssl);
+ }
+}
+
+/*
+ * call-seq:
+ * ctx.options -> integer
+ *
+ * Gets various \OpenSSL options.
+ */
+static VALUE
+ossl_sslctx_get_options(VALUE self)
+{
+ SSL_CTX *ctx;
+ GetSSLCTX(self, ctx);
+ /*
+ * Do explicit cast because SSL_CTX_get_options() returned (signed) long in
+ * OpenSSL before 1.1.0.
+ */
+ return ULONG2NUM((unsigned long)SSL_CTX_get_options(ctx));
+}
+
+/*
+ * call-seq:
+ * ctx.options = integer
+ *
+ * Sets various \OpenSSL options. The options are a bit field and can be
+ * combined with the bitwise OR operator (<tt>|</tt>). Available options are
+ * defined as constants in OpenSSL::SSL that begin with +OP_+.
+ *
+ * For backwards compatibility, passing +nil+ has the same effect as passing
+ * OpenSSL::SSL::OP_ALL.
+ *
+ * See also man page SSL_CTX_set_options(3).
+ */
+static VALUE
+ossl_sslctx_set_options(VALUE self, VALUE options)
+{
+ SSL_CTX *ctx;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+
+ SSL_CTX_clear_options(ctx, SSL_CTX_get_options(ctx));
+
+ if (NIL_P(options)) {
+ SSL_CTX_set_options(ctx, SSL_OP_ALL);
+ } else {
+ SSL_CTX_set_options(ctx, NUM2ULONG(options));
+ }
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * ctx.setup => Qtrue # first time
+ * ctx.setup => nil # thereafter
+ *
+ * This method is called automatically when a new SSLSocket is created.
+ * However, it is not thread-safe and must be called before creating
+ * SSLSocket objects in a multi-threaded program.
+ */
static VALUE
ossl_sslctx_setup(VALUE self)
{
SSL_CTX *ctx;
X509 *cert = NULL, *client_ca = NULL;
- X509_STORE *store;
EVP_PKEY *key = NULL;
char *ca_path = NULL, *ca_file = NULL;
- int i, verify_mode;
+ int verify_mode;
+ long i;
VALUE val;
if(OBJ_FROZEN(self)) return Qnil;
- Data_Get_Struct(self, SSL_CTX, ctx);
+ GetSSLCTX(self, ctx);
#if !defined(OPENSSL_NO_DH)
- if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){
- SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
- }
- else{
- rb_warning("using default DH parameters.");
- SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback);
+ if (!NIL_P(rb_attr_get(self, id_i_tmp_dh_callback))) {
+ SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
+ SSL_CTX_set_dh_auto(ctx, 0);
}
#endif
- val = ossl_sslctx_get_cert_store(self);
- if(!NIL_P(val)){
- /*
- * WORKAROUND:
- * X509_STORE can count references, but
- * X509_STORE_free() doesn't care it.
- * So we won't increment it but mark it by ex_data.
- */
- store = GetX509StorePtr(val); /* NO NEED TO DUP */
+#if !defined(OPENSSL_IS_AWSLC) /* AWS-LC has no support for TLS 1.3 PHA. */
+ SSL_CTX_set_post_handshake_auth(ctx, 1);
+#endif
+
+ val = rb_attr_get(self, id_i_cert_store);
+ if (!NIL_P(val)) {
+ X509_STORE *store = GetX509StorePtr(val); /* NO NEED TO DUP */
SSL_CTX_set_cert_store(ctx, store);
- SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1);
+ X509_STORE_up_ref(store);
}
- val = ossl_sslctx_get_extra_cert(self);
+ val = rb_attr_get(self, id_i_extra_chain_cert);
if(!NIL_P(val)){
- rb_iterate(rb_each, val, ossl_sslctx_add_extra_chain_cert_i, self);
+ rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
}
/* private key may be bundled in certificate file. */
- val = ossl_sslctx_get_cert(self);
+ val = rb_attr_get(self, id_i_cert);
cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */
- val = ossl_sslctx_get_key(self);
- key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */
+ val = rb_attr_get(self, id_i_key);
+ key = NIL_P(val) ? NULL : GetPrivPKeyPtr(val); /* NO DUP NEEDED */
if (cert && key) {
if (!SSL_CTX_use_certificate(ctx, cert)) {
/* Adds a ref => Safe to FREE */
- ossl_raise(eSSLError, "SSL_CTX_use_certificate:");
+ ossl_raise(eSSLError, "SSL_CTX_use_certificate");
}
if (!SSL_CTX_use_PrivateKey(ctx, key)) {
/* Adds a ref => Safe to FREE */
- ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey:");
+ ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
}
if (!SSL_CTX_check_private_key(ctx)) {
- ossl_raise(eSSLError, "SSL_CTX_check_private_key:");
+ ossl_raise(eSSLError, "SSL_CTX_check_private_key");
}
}
- val = ossl_sslctx_get_client_ca(self);
+ val = rb_attr_get(self, id_i_client_ca);
if(!NIL_P(val)){
- if(TYPE(val) == T_ARRAY){
- for(i = 0; i < RARRAY(val)->len; i++){
- client_ca = GetX509CertPtr(RARRAY(val)->ptr[i]);
- if (!SSL_CTX_add_client_CA(ctx, client_ca)){
- /* Copies X509_NAME => FREE it. */
- ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
- }
- }
+ if (RB_TYPE_P(val, T_ARRAY)) {
+ for(i = 0; i < RARRAY_LEN(val); i++){
+ client_ca = GetX509CertPtr(RARRAY_AREF(val, i));
+ if (!SSL_CTX_add_client_CA(ctx, client_ca)){
+ /* Copies X509_NAME => FREE it. */
+ ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
+ }
+ }
}
- else{
- client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */
+ else{
+ client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */
if (!SSL_CTX_add_client_CA(ctx, client_ca)){
- /* Copies X509_NAME => FREE it. */
- ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
+ /* Copies X509_NAME => FREE it. */
+ ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
}
- }
+ }
}
- val = ossl_sslctx_get_ca_file(self);
- ca_file = NIL_P(val) ? NULL : StringValuePtr(val);
- val = ossl_sslctx_get_ca_path(self);
- ca_path = NIL_P(val) ? NULL : StringValuePtr(val);
- if(ca_file || ca_path){
- if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
- rb_warning("can't set verify locations");
+ val = rb_attr_get(self, id_i_ca_file);
+ ca_file = NIL_P(val) ? NULL : StringValueCStr(val);
+ val = rb_attr_get(self, id_i_ca_path);
+ ca_path = NIL_P(val) ? NULL : StringValueCStr(val);
+#ifdef HAVE_SSL_CTX_LOAD_VERIFY_FILE
+ if (ca_file && !SSL_CTX_load_verify_file(ctx, ca_file))
+ ossl_raise(eSSLError, "SSL_CTX_load_verify_file");
+ if (ca_path && !SSL_CTX_load_verify_dir(ctx, ca_path))
+ ossl_raise(eSSLError, "SSL_CTX_load_verify_dir");
+#else
+ if (ca_file || ca_path) {
+ if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
+ ossl_raise(eSSLError, "SSL_CTX_load_verify_locations");
}
+#endif
- val = ossl_sslctx_get_verify_mode(self);
+ val = rb_attr_get(self, id_i_verify_mode);
verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
- if (RTEST(ossl_sslctx_get_client_cert_cb(self)))
- SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);
+ if (RTEST(rb_attr_get(self, id_i_client_cert_cb)))
+ SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);
- val = ossl_sslctx_get_timeout(self);
+ val = rb_attr_get(self, id_i_timeout);
if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));
- val = ossl_sslctx_get_verify_dep(self);
- if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2LONG(val));
+ val = rb_attr_get(self, id_i_verify_depth);
+ if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val));
+
+#ifdef OSSL_USE_NEXTPROTONEG
+ val = rb_attr_get(self, id_i_npn_protocols);
+ if (!NIL_P(val)) {
+ VALUE encoded = ssl_encode_npn_protocols(val);
+ rb_ivar_set(self, id_npn_protocols_encoded, encoded);
+ SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self);
+ OSSL_Debug("SSL NPN advertise callback added");
+ }
+ if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
+ SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self);
+ OSSL_Debug("SSL NPN select callback added");
+ }
+#endif
+
+ val = rb_attr_get(self, id_i_alpn_protocols);
+ if (!NIL_P(val)) {
+ VALUE rprotos = ssl_encode_npn_protocols(val);
+
+ /* returns 0 on success */
+ if (SSL_CTX_set_alpn_protos(ctx, (unsigned char *)RSTRING_PTR(rprotos),
+ RSTRING_LENINT(rprotos)))
+ ossl_raise(eSSLError, "SSL_CTX_set_alpn_protos");
+ OSSL_Debug("SSL ALPN values added");
+ }
+ if (RTEST(rb_attr_get(self, id_i_alpn_select_cb))) {
+ SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self);
+ OSSL_Debug("SSL ALPN select callback added");
+ }
- val = ossl_sslctx_get_options(self);
- if(!NIL_P(val)) SSL_CTX_set_options(ctx, NUM2LONG(val));
rb_obj_freeze(self);
- val = ossl_sslctx_get_sess_id_ctx(self);
+ val = rb_attr_get(self, id_i_session_id_context);
if (!NIL_P(val)){
- StringValue(val);
- if (!SSL_CTX_set_session_id_context(ctx, RSTRING(val)->ptr,
- RSTRING(val)->len)){
- ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:");
- }
+ StringValue(val);
+ if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val),
+ RSTRING_LENINT(val))){
+ ossl_raise(eSSLError, "SSL_CTX_set_session_id_context");
+ }
+ }
+
+ if (RTEST(rb_attr_get(self, id_i_session_get_cb))) {
+ SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
+ OSSL_Debug("SSL SESSION get callback added");
+ }
+ if (RTEST(rb_attr_get(self, id_i_session_new_cb))) {
+ SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
+ OSSL_Debug("SSL SESSION new callback added");
+ }
+ if (RTEST(rb_attr_get(self, id_i_session_remove_cb))) {
+ SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
+ OSSL_Debug("SSL SESSION remove callback added");
+ }
+
+ val = rb_attr_get(self, id_i_servername_cb);
+ if (!NIL_P(val)) {
+ SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
+ OSSL_Debug("SSL TLSEXT servername callback added");
+ }
+
+#if !OSSL_IS_LIBRESSL
+ /*
+ * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
+ * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
+ * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
+ */
+ if (RTEST(rb_attr_get(self, id_i_keylog_cb))) {
+ SSL_CTX_set_keylog_callback(ctx, ossl_sslctx_keylog_cb);
+ OSSL_Debug("SSL keylog callback added");
}
+#endif
return Qtrue;
}
+static int
+parse_proto_version(VALUE str)
+{
+ int i;
+ static const struct {
+ const char *name;
+ int version;
+ } map[] = {
+ { "SSL2", SSL2_VERSION },
+ { "SSL3", SSL3_VERSION },
+ { "TLS1", TLS1_VERSION },
+ { "TLS1_1", TLS1_1_VERSION },
+ { "TLS1_2", TLS1_2_VERSION },
+ { "TLS1_3", TLS1_3_VERSION },
+ };
+
+ if (NIL_P(str))
+ return 0;
+ if (RB_INTEGER_TYPE_P(str))
+ return NUM2INT(str);
+
+ if (SYMBOL_P(str))
+ str = rb_sym2str(str);
+ StringValue(str);
+ for (i = 0; i < numberof(map); i++)
+ if (!strncmp(map[i].name, RSTRING_PTR(str), RSTRING_LEN(str)))
+ return map[i].version;
+ rb_raise(rb_eArgError, "unrecognized version %+"PRIsVALUE, str);
+}
+
+/*
+ * call-seq:
+ * ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION
+ * ctx.min_version = :TLS1_2
+ * ctx.min_version = nil
+ *
+ * Sets the lower bound on the supported SSL/TLS protocol version. The
+ * version may be specified by an integer constant named
+ * OpenSSL::SSL::*_VERSION, a Symbol, or +nil+ which means "any version".
+ *
+ * === Example
+ * ctx = OpenSSL::SSL::SSLContext.new
+ * ctx.min_version = OpenSSL::SSL::TLS1_1_VERSION
+ * ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
+ *
+ * sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx)
+ * sock.connect # Initiates a connection using either TLS 1.1 or TLS 1.2
+ */
+static VALUE
+ossl_sslctx_set_min_version(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+ int version;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+ version = parse_proto_version(v);
+
+ if (!SSL_CTX_set_min_proto_version(ctx, version))
+ ossl_raise(eSSLError, "SSL_CTX_set_min_proto_version");
+ return v;
+}
+
+/*
+ * call-seq:
+ * ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
+ * ctx.max_version = :TLS1_2
+ * ctx.max_version = nil
+ *
+ * Sets the upper bound of the supported SSL/TLS protocol version. See
+ * #min_version= for the possible values.
+ */
+static VALUE
+ossl_sslctx_set_max_version(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+ int version;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+ version = parse_proto_version(v);
+
+ if (!SSL_CTX_set_max_proto_version(ctx, version))
+ ossl_raise(eSSLError, "SSL_CTX_set_max_proto_version");
+ return v;
+}
+
static VALUE
-ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
+ossl_ssl_cipher_to_ary(const SSL_CIPHER *cipher)
{
VALUE ary;
int bits, alg_bits;
@@ -416,327 +950,1314 @@ ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_name(cipher)));
rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_version(cipher)));
bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
- rb_ary_push(ary, INT2FIX(bits));
- rb_ary_push(ary, INT2FIX(alg_bits));
+ rb_ary_push(ary, INT2NUM(bits));
+ rb_ary_push(ary, INT2NUM(alg_bits));
return ary;
}
+/*
+ * call-seq:
+ * ctx.ciphers => [[name, version, bits, alg_bits], ...]
+ *
+ * The list of cipher suites configured for this context.
+ */
static VALUE
ossl_sslctx_get_ciphers(VALUE self)
{
SSL_CTX *ctx;
STACK_OF(SSL_CIPHER) *ciphers;
- SSL_CIPHER *cipher;
+ const SSL_CIPHER *cipher;
VALUE ary;
int i, num;
- Data_Get_Struct(self, SSL_CTX, ctx);
- if(!ctx){
- rb_warning("SSL_CTX is not initialized.");
- return Qnil;
- }
- ciphers = ctx->cipher_list;
-
+ GetSSLCTX(self, ctx);
+ ciphers = SSL_CTX_get_ciphers(ctx);
if (!ciphers)
return rb_ary_new();
- num = sk_num((STACK*)ciphers);
+ num = sk_SSL_CIPHER_num(ciphers);
ary = rb_ary_new2(num);
for(i = 0; i < num; i++){
- cipher = (SSL_CIPHER*)sk_value((STACK*)ciphers, i);
+ cipher = sk_SSL_CIPHER_value(ciphers, i);
rb_ary_push(ary, ossl_ssl_cipher_to_ary(cipher));
}
return ary;
}
static VALUE
-ossl_sslctx_set_ciphers(VALUE self, VALUE v)
+build_cipher_string(VALUE v)
{
- SSL_CTX *ctx;
VALUE str, elem;
- int i;
- rb_check_frozen(self);
- if (NIL_P(v))
- return v;
- else if (TYPE(v) == T_ARRAY) {
+ if (RB_TYPE_P(v, T_ARRAY)) {
str = rb_str_new(0, 0);
- for (i = 0; i < RARRAY(v)->len; i++) {
+ for (long i = 0; i < RARRAY_LEN(v); i++) {
elem = rb_ary_entry(v, i);
- if (TYPE(elem) == T_ARRAY) elem = rb_ary_entry(elem, 0);
+ if (RB_TYPE_P(elem, T_ARRAY)) elem = rb_ary_entry(elem, 0);
elem = rb_String(elem);
rb_str_append(str, elem);
- if (i < RARRAY(v)->len-1) rb_str_cat2(str, ":");
+ if (i < RARRAY_LEN(v)-1) rb_str_cat2(str, ":");
}
} else {
str = v;
StringValue(str);
}
- Data_Get_Struct(self, SSL_CTX, ctx);
- if(!ctx){
- ossl_raise(eSSLError, "SSL_CTX is not initialized.");
- return Qnil;
+ return str;
+}
+
+/*
+ * call-seq:
+ * ctx.ciphers = "cipher1:cipher2:..."
+ * ctx.ciphers = [name, ...]
+ * ctx.ciphers = [[name, version, bits, alg_bits], ...]
+ *
+ * Sets the list of available cipher suites for TLS 1.2 and below for this
+ * context.
+ *
+ * Note in a server context some ciphers require the appropriate certificates.
+ * For example, an RSA cipher suite can only be chosen when an RSA certificate
+ * is available.
+ *
+ * This method does not affect TLS 1.3 connections. See also #ciphersuites=.
+ */
+static VALUE
+ossl_sslctx_set_ciphers(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+ VALUE str;
+
+ rb_check_frozen(self);
+ // Assigning nil is a no-op for compatibility
+ if (NIL_P(v))
+ return v;
+
+ str = build_cipher_string(v);
+
+ GetSSLCTX(self, ctx);
+ if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str)))
+ ossl_raise(eSSLError, "SSL_CTX_set_cipher_list");
+
+ return v;
+}
+
+/*
+ * call-seq:
+ * ctx.ciphersuites = "cipher1:cipher2:..."
+ * ctx.ciphersuites = [name, ...]
+ *
+ * Sets the list of available TLS 1.3 cipher suites for this context.
+ */
+static VALUE
+ossl_sslctx_set_ciphersuites(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+ VALUE str;
+
+ rb_check_frozen(self);
+ // Assigning nil is a no-op for compatibility
+ if (NIL_P(v))
+ return v;
+
+ str = build_cipher_string(v);
+
+ GetSSLCTX(self, ctx);
+ if (!SSL_CTX_set_ciphersuites(ctx, StringValueCStr(str)))
+ ossl_raise(eSSLError, "SSL_CTX_set_ciphersuites");
+
+ return v;
+}
+
+#ifdef HAVE_SSL_CTX_SET1_SIGALGS_LIST
+/*
+ * call-seq:
+ * ctx.sigalgs = "sigalg1:sigalg2:..."
+ *
+ * Sets the list of "supported signature algorithms" for this context.
+ *
+ * For a TLS client, the list is used in the "signature_algorithms" extension
+ * in the ClientHello message. For a server, the list is used by OpenSSL to
+ * determine the set of shared signature algorithms. OpenSSL will pick the most
+ * appropriate one from it.
+ *
+ * See also #client_sigalgs= for the client authentication equivalent.
+ */
+static VALUE
+ossl_sslctx_set_sigalgs(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+
+ if (!SSL_CTX_set1_sigalgs_list(ctx, StringValueCStr(v)))
+ ossl_raise(eSSLError, "SSL_CTX_set1_sigalgs_list");
+
+ return v;
+}
+#endif
+
+#ifdef HAVE_SSL_CTX_SET1_CLIENT_SIGALGS_LIST
+/*
+ * call-seq:
+ * ctx.client_sigalgs = "sigalg1:sigalg2:..."
+ *
+ * Sets the list of "supported signature algorithms" for client authentication
+ * for this context.
+ *
+ * For a TLS server, the list is sent to the client as part of the
+ * CertificateRequest message.
+ *
+ * See also #sigalgs= for the server authentication equivalent.
+ */
+static VALUE
+ossl_sslctx_set_client_sigalgs(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+
+ if (!SSL_CTX_set1_client_sigalgs_list(ctx, StringValueCStr(v)))
+ ossl_raise(eSSLError, "SSL_CTX_set1_client_sigalgs_list");
+
+ return v;
+}
+#endif
+
+#ifndef OPENSSL_NO_DH
+/*
+ * call-seq:
+ * ctx.tmp_dh = pkey
+ *
+ * Sets DH parameters used for ephemeral DH key exchange. This is relevant for
+ * servers only.
+ *
+ * +pkey+ is an instance of OpenSSL::PKey::DH. Note that key components
+ * contained in the key object, if any, are ignored. The server will always
+ * generate a new key pair for each handshake.
+ *
+ * Added in version 3.0. See also the man page SSL_CTX_set0_tmp_dh_pkey(3).
+ *
+ * Example:
+ * ctx = OpenSSL::SSL::SSLContext.new
+ * ctx.tmp_dh = OpenSSL::DH.generate(2048)
+ * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx)
+ * Thread.new { svr.accept }
+ */
+static VALUE
+ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+ EVP_PKEY *pkey;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+ pkey = GetPKeyPtr(arg);
+
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH)
+ rb_raise(eSSLError, "invalid pkey type %s (expected DH)",
+ OBJ_nid2sn(EVP_PKEY_base_id(pkey)));
+#ifdef HAVE_SSL_CTX_SET0_TMP_DH_PKEY
+ if (!SSL_CTX_set0_tmp_dh_pkey(ctx, pkey))
+ ossl_raise(eSSLError, "SSL_CTX_set0_tmp_dh_pkey");
+ EVP_PKEY_up_ref(pkey);
+#else
+ if (!SSL_CTX_set_tmp_dh(ctx, EVP_PKEY_get0_DH(pkey)))
+ ossl_raise(eSSLError, "SSL_CTX_set_tmp_dh");
+#endif
+
+ // Turn off the "auto" DH parameters set by ossl_sslctx_s_alloc()
+ SSL_CTX_set_dh_auto(ctx, 0);
+
+ return arg;
+}
+#endif
+
+/*
+ * call-seq:
+ * ctx.groups = groups_list
+ * ctx.ecdh_curves = groups_list
+ *
+ * Sets the list of supported groups for key agreement for this context.
+ *
+ * For a TLS client, the list is directly used in the "supported_groups"
+ * extension. For a server, the list is used by OpenSSL to determine the set of
+ * shared supported groups. OpenSSL will pick the most appropriate one from it.
+ *
+ * #ecdh_curves= is a deprecated alias for #groups=.
+ *
+ * See also the man page SSL_CTX_set1_groups_list(3).
+ *
+ * === Example
+ * ctx1 = OpenSSL::SSL::SSLContext.new
+ * ctx1.groups = "X25519:P-256:P-224"
+ * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx1)
+ * Thread.new { svr.accept }
+ *
+ * ctx2 = OpenSSL::SSL::SSLContext.new
+ * ctx2.groups = "P-256"
+ * cli = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx2)
+ * cli.connect
+ *
+ * p cli.tmp_key.group.curve_name
+ * # => "prime256v1" (is an alias for NIST P-256)
+ */
+static VALUE
+ossl_sslctx_set_groups(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+ StringValueCStr(arg);
+
+ if (!SSL_CTX_set1_groups_list(ctx, RSTRING_PTR(arg)))
+ ossl_raise(eSSLError, "SSL_CTX_set1_groups_list");
+ return arg;
+}
+
+/*
+ * call-seq:
+ * ctx.security_level -> Integer
+ *
+ * Returns the security level for the context.
+ *
+ * See also OpenSSL::SSL::SSLContext#security_level=.
+ */
+static VALUE
+ossl_sslctx_get_security_level(VALUE self)
+{
+ SSL_CTX *ctx;
+
+ GetSSLCTX(self, ctx);
+
+ return INT2NUM(SSL_CTX_get_security_level(ctx));
+}
+
+/*
+ * call-seq:
+ * ctx.security_level = integer
+ *
+ * Sets the security level for the context. OpenSSL limits parameters according
+ * to the level. The "parameters" include: ciphersuites, curves, key sizes,
+ * certificate signature algorithms, protocol version and so on. For example,
+ * level 1 rejects parameters offering below 80 bits of security, such as
+ * ciphersuites using MD5 for the MAC or RSA keys shorter than 1024 bits.
+ *
+ * Note that attempts to set such parameters with insufficient security are
+ * also blocked. You need to lower the level first.
+ *
+ * This feature is not supported in OpenSSL < 1.1.0, and setting the level to
+ * other than 0 will raise NotImplementedError. Level 0 means everything is
+ * permitted, the same behavior as previous versions of OpenSSL.
+ *
+ * See the manpage of SSL_CTX_set_security_level(3) for details.
+ */
+static VALUE
+ossl_sslctx_set_security_level(VALUE self, VALUE value)
+{
+ SSL_CTX *ctx;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+
+ SSL_CTX_set_security_level(ctx, NUM2INT(value));
+
+ return value;
+}
+
+#ifdef SSL_MODE_SEND_FALLBACK_SCSV
+/*
+ * call-seq:
+ * ctx.enable_fallback_scsv() => nil
+ *
+ * Activate TLS_FALLBACK_SCSV for this context.
+ * See RFC 7507.
+ */
+static VALUE
+ossl_sslctx_enable_fallback_scsv(VALUE self)
+{
+ SSL_CTX *ctx;
+
+ GetSSLCTX(self, ctx);
+ SSL_CTX_set_mode(ctx, SSL_MODE_SEND_FALLBACK_SCSV);
+
+ return Qnil;
+}
+#endif
+
+/*
+ * call-seq:
+ * ctx.add_certificate(certificate, pkey [, extra_certs]) -> self
+ *
+ * Adds a certificate to the context. _pkey_ must be a corresponding private
+ * key with _certificate_.
+ *
+ * Multiple certificates with different public key type can be added by
+ * repeated calls of this method, and OpenSSL will choose the most appropriate
+ * certificate during the handshake.
+ *
+ * #cert=, #key=, and #extra_chain_cert= are old accessor methods for setting
+ * certificate and internally call this method.
+ *
+ * === Parameters
+ * _certificate_::
+ * A certificate. An instance of OpenSSL::X509::Certificate.
+ * _pkey_::
+ * The private key for _certificate_. An instance of OpenSSL::PKey::PKey.
+ * _extra_certs_::
+ * Optional. An array of OpenSSL::X509::Certificate. When sending a
+ * certificate chain, the certificates specified by this are sent following
+ * _certificate_, in the order in the array.
+ *
+ * === Example
+ * rsa_cert = OpenSSL::X509::Certificate.new(...)
+ * rsa_pkey = OpenSSL::PKey.read(...)
+ * ca_intermediate_cert = OpenSSL::X509::Certificate.new(...)
+ * ctx.add_certificate(rsa_cert, rsa_pkey, [ca_intermediate_cert])
+ *
+ * ecdsa_cert = ...
+ * ecdsa_pkey = ...
+ * another_ca_cert = ...
+ * ctx.add_certificate(ecdsa_cert, ecdsa_pkey, [another_ca_cert])
+ */
+static VALUE
+ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self)
+{
+ VALUE cert, key, extra_chain_ary;
+ SSL_CTX *ctx;
+ X509 *x509;
+ STACK_OF(X509) *extra_chain = NULL;
+ EVP_PKEY *pkey, *pub_pkey;
+
+ GetSSLCTX(self, ctx);
+ rb_scan_args(argc, argv, "21", &cert, &key, &extra_chain_ary);
+ rb_check_frozen(self);
+ x509 = GetX509CertPtr(cert);
+ pkey = GetPrivPKeyPtr(key);
+
+ /*
+ * The reference counter is bumped, and decremented immediately.
+ * X509_get0_pubkey() is only available in OpenSSL >= 1.1.0.
+ */
+ pub_pkey = X509_get_pubkey(x509);
+ EVP_PKEY_free(pub_pkey);
+ if (!pub_pkey)
+ rb_raise(rb_eArgError, "certificate does not contain public key");
+ if (EVP_PKEY_eq(pub_pkey, pkey) != 1)
+ rb_raise(rb_eArgError, "public key mismatch");
+
+ if (argc >= 3)
+ extra_chain = ossl_x509_ary2sk(extra_chain_ary);
+
+ if (!SSL_CTX_use_certificate(ctx, x509)) {
+ sk_X509_pop_free(extra_chain, X509_free);
+ ossl_raise(eSSLError, "SSL_CTX_use_certificate");
+ }
+ if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
+ sk_X509_pop_free(extra_chain, X509_free);
+ ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
}
- if (!SSL_CTX_set_cipher_list(ctx, RSTRING(str)->ptr)) {
- ossl_raise(eSSLError, "SSL_CTX_set_cipher_list:");
+ if (extra_chain && !SSL_CTX_set0_chain(ctx, extra_chain)) {
+ sk_X509_pop_free(extra_chain, X509_free);
+ ossl_raise(eSSLError, "SSL_CTX_set0_chain");
}
+ return self;
+}
- return v;
+/*
+ * call-seq:
+ * ctx.session_add(session) -> true | false
+ *
+ * Adds _session_ to the session cache.
+ */
+static VALUE
+ossl_sslctx_session_add(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+ SSL_SESSION *sess;
+
+ GetSSLCTX(self, ctx);
+ GetSSLSession(arg, sess);
+
+ return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * ctx.session_remove(session) -> true | false
+ *
+ * Removes _session_ from the session cache.
+ */
+static VALUE
+ossl_sslctx_session_remove(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+ SSL_SESSION *sess;
+
+ GetSSLCTX(self, ctx);
+ GetSSLSession(arg, sess);
+
+ return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_mode -> Integer
+ *
+ * The current session cache mode.
+ */
+static VALUE
+ossl_sslctx_get_session_cache_mode(VALUE self)
+{
+ SSL_CTX *ctx;
+
+ GetSSLCTX(self, ctx);
+
+ return LONG2NUM(SSL_CTX_get_session_cache_mode(ctx));
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_mode=(integer) -> Integer
+ *
+ * Sets the SSL session cache mode. Bitwise-or together the desired
+ * SESSION_CACHE_* constants to set. See SSL_CTX_set_session_cache_mode(3) for
+ * details.
+ */
+static VALUE
+ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+
+ GetSSLCTX(self, ctx);
+
+ SSL_CTX_set_session_cache_mode(ctx, NUM2LONG(arg));
+
+ return arg;
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_size -> Integer
+ *
+ * Returns the current session cache size. Zero is used to represent an
+ * unlimited cache size.
+ */
+static VALUE
+ossl_sslctx_get_session_cache_size(VALUE self)
+{
+ SSL_CTX *ctx;
+
+ GetSSLCTX(self, ctx);
+
+ return LONG2NUM(SSL_CTX_sess_get_cache_size(ctx));
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_size=(integer) -> Integer
+ *
+ * Sets the session cache size. Returns the previously valid session cache
+ * size. Zero is used to represent an unlimited session cache size.
+ */
+static VALUE
+ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+
+ GetSSLCTX(self, ctx);
+
+ SSL_CTX_sess_set_cache_size(ctx, NUM2LONG(arg));
+
+ return arg;
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_stats -> Hash
+ *
+ * Returns a Hash containing the following keys:
+ *
+ * :accept:: Number of started SSL/TLS handshakes in server mode
+ * :accept_good:: Number of established SSL/TLS sessions in server mode
+ * :accept_renegotiate:: Number of start renegotiations in server mode
+ * :cache_full:: Number of sessions that were removed due to cache overflow
+ * :cache_hits:: Number of successfully reused connections
+ * :cache_misses:: Number of sessions proposed by clients that were not found
+ * in the cache
+ * :cache_num:: Number of sessions in the internal session cache
+ * :cb_hits:: Number of sessions retrieved from the external cache in server
+ * mode
+ * :connect:: Number of started SSL/TLS handshakes in client mode
+ * :connect_good:: Number of established SSL/TLS sessions in client mode
+ * :connect_renegotiate:: Number of start renegotiations in client mode
+ * :timeouts:: Number of sessions proposed by clients that were found in the
+ * cache but had expired due to timeouts
+ */
+static VALUE
+ossl_sslctx_get_session_cache_stats(VALUE self)
+{
+ SSL_CTX *ctx;
+ VALUE hash;
+
+ GetSSLCTX(self, ctx);
+
+ hash = rb_hash_new();
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_num")), LONG2NUM(SSL_CTX_sess_number(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect")), LONG2NUM(SSL_CTX_sess_connect(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect_good")), LONG2NUM(SSL_CTX_sess_connect_good(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect_renegotiate")), LONG2NUM(SSL_CTX_sess_connect_renegotiate(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept")), LONG2NUM(SSL_CTX_sess_accept(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept_good")), LONG2NUM(SSL_CTX_sess_accept_good(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept_renegotiate")), LONG2NUM(SSL_CTX_sess_accept_renegotiate(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_hits")), LONG2NUM(SSL_CTX_sess_hits(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cb_hits")), LONG2NUM(SSL_CTX_sess_cb_hits(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_misses")), LONG2NUM(SSL_CTX_sess_misses(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_full")), LONG2NUM(SSL_CTX_sess_cache_full(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("timeouts")), LONG2NUM(SSL_CTX_sess_timeouts(ctx)));
+
+ return hash;
+}
+
+
+/*
+ * call-seq:
+ * ctx.flush_sessions(time) -> self
+ *
+ * Removes sessions in the internal cache that have expired at _time_.
+ */
+static VALUE
+ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
+{
+ VALUE arg1;
+ SSL_CTX *ctx;
+ time_t tm = 0;
+
+ rb_scan_args(argc, argv, "01", &arg1);
+
+ GetSSLCTX(self, ctx);
+
+ if (NIL_P(arg1)) {
+ tm = time(0);
+ } else if (rb_obj_is_instance_of(arg1, rb_cTime)) {
+ tm = NUM2LONG(rb_funcall(arg1, rb_intern("to_i"), 0));
+ } else {
+ ossl_raise(rb_eArgError, "arg must be Time or nil");
+ }
+
+ SSL_CTX_flush_sessions(ctx, (long)tm);
+
+ return self;
}
/*
* SSLSocket class
*/
+static inline int
+ssl_started(SSL *ssl)
+{
+ /* BIO is created through ossl_ssl_setup(), called by #connect or #accept */
+ return SSL_get_rbio(ssl) != NULL;
+}
+
static void
-ossl_ssl_shutdown(SSL *ssl)
+ossl_ssl_mark(void *ptr)
{
- if (ssl) {
- SSL_shutdown(ssl);
- SSL_clear(ssl);
- }
+ SSL *ssl = ptr;
+ rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx));
}
static void
-ossl_ssl_free(SSL *ssl)
+ossl_ssl_free(void *ssl)
{
- ossl_ssl_shutdown(ssl);
SSL_free(ssl);
}
+const rb_data_type_t ossl_ssl_type = {
+ "OpenSSL/SSL",
+ {
+ ossl_ssl_mark, ossl_ssl_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
static VALUE
ossl_ssl_s_alloc(VALUE klass)
{
- return Data_Wrap_Struct(klass, 0, ossl_ssl_free, NULL);
+ return TypedData_Wrap_Struct(klass, &ossl_ssl_type, NULL);
+}
+
+static VALUE
+peer_ip_address(VALUE io)
+{
+ VALUE remote_address = rb_funcall(io, rb_intern("remote_address"), 0);
+
+ return rb_funcall(remote_address, rb_intern("inspect_sockaddr"), 0);
+}
+
+static VALUE
+fallback_peer_ip_address(VALUE self, VALUE exc)
+{
+ return rb_str_new_cstr("(null)");
+}
+
+static VALUE
+peeraddr_ip_str(VALUE io)
+{
+ return rb_rescue2(peer_ip_address, io, fallback_peer_ip_address, Qnil,
+ rb_eSystemCallError, (VALUE)0);
}
+/*
+ * call-seq:
+ * SSLSocket.new(io) => aSSLSocket
+ * SSLSocket.new(io, ctx) => aSSLSocket
+ * SSLSocket.new(io, ctx, sync_close:) => aSSLSocket
+ *
+ * Creates a new SSL socket from _io_ which must be a real IO object (not an
+ * IO-like object that responds to read/write).
+ *
+ * If _ctx_ is provided the SSL Sockets initial params will be taken from
+ * the context.
+ *
+ * The optional _sync_close_ keyword parameter sets the _sync_close_ instance
+ * variable. Setting this to +true+ will cause the underlying socket to be
+ * closed when the SSL/TLS connection is shut down.
+ *
+ * The OpenSSL::Buffering module provides additional IO methods.
+ *
+ * This method will freeze the SSLContext if one is provided;
+ * however, session management is still allowed in the frozen SSLContext.
+ */
static VALUE
ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
{
- VALUE io, ctx;
+ static ID kw_ids[1];
+ VALUE kw_args[1];
+ VALUE opts;
- if (rb_scan_args(argc, argv, "11", &io, &ctx) == 1) {
- ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
+ VALUE io, v_ctx;
+ SSL *ssl;
+ SSL_CTX *ctx;
+
+ TypedData_Get_Struct(self, SSL, &ossl_ssl_type, ssl);
+ if (ssl)
+ ossl_raise(eSSLError, "SSL already initialized");
+
+ if (rb_scan_args(argc, argv, "11:", &io, &v_ctx, &opts) == 1)
+ v_ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
+
+ if (!kw_ids[0]) {
+ kw_ids[0] = rb_intern_const("sync_close");
+ }
+
+ rb_get_kwargs(opts, kw_ids, 0, 1, kw_args);
+ if (kw_args[0] != Qundef) {
+ rb_ivar_set(self, id_i_sync_close, kw_args[0]);
}
- OSSL_Check_Kind(ctx, cSSLContext);
+
+ GetSSLCTX(v_ctx, ctx);
+ rb_ivar_set(self, id_i_context, v_ctx);
+ ossl_sslctx_setup(v_ctx);
+
+ if (rb_respond_to(io, rb_intern("nonblock=")))
+ rb_funcall(io, rb_intern("nonblock="), 1, Qtrue);
Check_Type(io, T_FILE);
- ossl_ssl_set_io(self, io);
- ossl_ssl_set_ctx(self, ctx);
- ossl_ssl_set_sync_close(self, Qfalse);
- ossl_sslctx_setup(ctx);
- rb_call_super(0, 0);
+ rb_ivar_set(self, id_i_io, io);
+
+ ssl = SSL_new(ctx);
+ if (!ssl)
+ ossl_raise(eSSLError, NULL);
+ RTYPEDDATA_DATA(self) = ssl;
+
+ if (!SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void *)self))
+ ossl_raise(eSSLError, "SSL_set_ex_data");
+ SSL_set_info_callback(ssl, ssl_info_cb);
+
+ rb_call_super(0, NULL);
return self;
}
+#ifndef HAVE_RB_IO_DESCRIPTOR
+static int
+io_descriptor_fallback(VALUE io)
+{
+ rb_io_t *fptr;
+ GetOpenFile(io, fptr);
+ return fptr->fd;
+}
+#define rb_io_descriptor io_descriptor_fallback
+#endif
+
static VALUE
ossl_ssl_setup(VALUE self)
{
- VALUE io, v_ctx, cb;
- SSL_CTX *ctx;
+ VALUE io;
SSL *ssl;
- OpenFile *fptr;
+ rb_io_t *fptr;
- Data_Get_Struct(self, SSL, ssl);
- if(!ssl){
- v_ctx = ossl_ssl_get_ctx(self);
- Data_Get_Struct(v_ctx, SSL_CTX, ctx);
+ GetSSL(self, ssl);
+ if (ssl_started(ssl))
+ return Qtrue;
- ssl = SSL_new(ctx);
- if (!ssl) {
- ossl_raise(eSSLError, "SSL_new:");
- }
- DATA_PTR(self) = ssl;
-
- io = ossl_ssl_get_io(self);
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
- rb_io_check_writable(fptr);
- SSL_set_fd(ssl, TO_SOCKET(fileno(fptr->f)));
- SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self);
- cb = ossl_sslctx_get_verify_cb(v_ctx);
- SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb);
- cb = ossl_sslctx_get_client_cert_cb(v_ctx);
- SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb);
- cb = ossl_sslctx_get_tmp_dh_cb(v_ctx);
- SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb);
- }
+ io = rb_attr_get(self, id_i_io);
+ GetOpenFile(io, fptr);
+ rb_io_check_readable(fptr);
+ rb_io_check_writable(fptr);
+ if (!SSL_set_fd(ssl, TO_SOCKET(rb_io_descriptor(io))))
+ ossl_raise(eSSLError, "SSL_set_fd");
return Qtrue;
}
+static int
+errno_mapped(void)
+{
#ifdef _WIN32
-#define ssl_get_error(ssl, ret) \
- (errno = WSAGetLastError(), SSL_get_error(ssl, ret))
+ return rb_w32_map_errno(WSAGetLastError());
+#else
+ return errno;
+#endif
+}
+
+static void
+write_would_block(int nonblock)
+{
+ if (nonblock)
+ ossl_raise(eSSLErrorWaitWritable, "write would block");
+}
+
+static void
+read_would_block(int nonblock)
+{
+ if (nonblock)
+ ossl_raise(eSSLErrorWaitReadable, "read would block");
+}
+
+static int
+no_exception_p(VALUE opts)
+{
+ if (RB_TYPE_P(opts, T_HASH) &&
+ rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse)
+ return 1;
+ return 0;
+}
+
+// Provided by Ruby 3.2.0 and later in order to support the default IO#timeout.
+#ifndef RUBY_IO_TIMEOUT_DEFAULT
+#define RUBY_IO_TIMEOUT_DEFAULT Qnil
+#endif
+
+#ifdef HAVE_RB_IO_TIMEOUT
+#define IO_TIMEOUT_ERROR rb_eIOTimeoutError
#else
-#define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret)
+#define IO_TIMEOUT_ERROR rb_eIOError
#endif
+
+static void
+io_wait_writable(VALUE io)
+{
+#ifdef HAVE_RB_IO_MAYBE_WAIT
+ if (!rb_io_wait(io, INT2NUM(RUBY_IO_WRITABLE), RUBY_IO_TIMEOUT_DEFAULT)) {
+ rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become writable!");
+ }
+#else
+ rb_io_t *fptr;
+ GetOpenFile(io, fptr);
+ rb_thread_fd_writable(fptr->fd);
+#endif
+}
+
+static void
+io_wait_readable(VALUE io)
+{
+#ifdef HAVE_RB_IO_MAYBE_WAIT
+ if (!rb_io_wait(io, INT2NUM(RUBY_IO_READABLE), RUBY_IO_TIMEOUT_DEFAULT)) {
+ rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become readable!");
+ }
+#else
+ rb_io_t *fptr;
+ GetOpenFile(io, fptr);
+ rb_thread_wait_fd(fptr->fd);
+#endif
+}
+
static VALUE
-ossl_start_ssl(VALUE self, int (*func)())
+ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts)
{
SSL *ssl;
- OpenFile *fptr;
- int ret;
+ VALUE cb_state;
+ int nonblock = opts != Qfalse;
- Data_Get_Struct(self, SSL, ssl);
- GetOpenFile(ossl_ssl_get_io(self), fptr);
- for(;;){
- if((ret = func(ssl)) > 0) break;
- switch(ssl_get_error(ssl, ret)){
- case SSL_ERROR_WANT_WRITE:
- rb_io_wait_writable(fileno(fptr->f));
+ rb_ivar_set(self, ID_callback_state, Qnil);
+
+ GetSSL(self, ssl);
+
+ VALUE io = rb_attr_get(self, id_i_io);
+ for (;;) {
+ int ret = func(ssl);
+ int saved_errno = errno_mapped();
+
+ cb_state = rb_attr_get(self, ID_callback_state);
+ if (!NIL_P(cb_state)) {
+ /* must cleanup OpenSSL error stack before re-raising */
+ ossl_clear_error();
+ rb_jump_tag(NUM2INT(cb_state));
+ }
+
+ if (ret > 0)
+ break;
+
+ int code = SSL_get_error(ssl, ret);
+ switch (code) {
+ case SSL_ERROR_WANT_WRITE:
+ if (no_exception_p(opts)) { return sym_wait_writable; }
+ write_would_block(nonblock);
+ io_wait_writable(io);
continue;
- case SSL_ERROR_WANT_READ:
- rb_io_wait_readable(fileno(fptr->f));
+ case SSL_ERROR_WANT_READ:
+ if (no_exception_p(opts)) { return sym_wait_readable; }
+ read_would_block(nonblock);
+ io_wait_readable(io);
continue;
- case SSL_ERROR_SYSCALL:
- if (errno) rb_sys_fail(0);
- default:
- ossl_raise(eSSLError, NULL);
- }
+ case SSL_ERROR_SYSCALL:
+#ifdef __APPLE__
+ /* See ossl_ssl_write_internal() */
+ if (saved_errno == EPROTOTYPE)
+ continue;
+#endif
+ if (saved_errno)
+ rb_exc_raise(rb_syserr_new(saved_errno, funcname));
+ /* fallthrough */
+ default: {
+ VALUE error_append = Qnil;
+#if defined(SSL_R_CERTIFICATE_VERIFY_FAILED)
+ unsigned long err = ERR_peek_last_error();
+ if (ERR_GET_LIB(err) == ERR_LIB_SSL &&
+ ERR_GET_REASON(err) == SSL_R_CERTIFICATE_VERIFY_FAILED) {
+ const char *err_msg = ERR_reason_error_string(err),
+ *verify_msg = X509_verify_cert_error_string(SSL_get_verify_result(ssl));
+ if (!err_msg)
+ err_msg = "(null)";
+ if (!verify_msg)
+ verify_msg = "(null)";
+ ossl_clear_error(); /* let ossl_raise() not append message */
+ error_append = rb_sprintf(": %s (%s)", err_msg, verify_msg);
+ }
+#endif
+ ossl_raise(eSSLError,
+ "%s%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s%"PRIsVALUE,
+ funcname,
+ code == SSL_ERROR_SYSCALL ? " SYSCALL" : "",
+ code,
+ saved_errno,
+ peeraddr_ip_str(io),
+ SSL_state_string_long(ssl),
+ error_append);
+ }
+ }
}
return self;
}
+/*
+ * call-seq:
+ * ssl.connect => self
+ *
+ * Initiates an SSL/TLS handshake with a server.
+ */
static VALUE
ossl_ssl_connect(VALUE self)
{
ossl_ssl_setup(self);
- return ossl_start_ssl(self, SSL_connect);
+
+ return ossl_start_ssl(self, SSL_connect, "SSL_connect", Qfalse);
+}
+
+/*
+ * call-seq:
+ * ssl.connect_nonblock([options]) => self
+ *
+ * Initiates the SSL/TLS handshake as a client in non-blocking manner.
+ *
+ * # emulates blocking connect
+ * begin
+ * ssl.connect_nonblock
+ * rescue IO::WaitReadable
+ * IO.select([s2])
+ * retry
+ * rescue IO::WaitWritable
+ * IO.select(nil, [s2])
+ * retry
+ * end
+ *
+ * By specifying a keyword argument _exception_ to +false+, you can indicate
+ * that connect_nonblock should not raise an IO::WaitReadable or
+ * IO::WaitWritable exception, but return the symbol +:wait_readable+ or
+ * +:wait_writable+ instead.
+ */
+static VALUE
+ossl_ssl_connect_nonblock(int argc, VALUE *argv, VALUE self)
+{
+ VALUE opts;
+ rb_scan_args(argc, argv, "0:", &opts);
+
+ ossl_ssl_setup(self);
+
+ return ossl_start_ssl(self, SSL_connect, "SSL_connect", opts);
}
+/*
+ * call-seq:
+ * ssl.accept => self
+ *
+ * Waits for a SSL/TLS client to initiate a handshake.
+ */
static VALUE
ossl_ssl_accept(VALUE self)
{
ossl_ssl_setup(self);
- return ossl_start_ssl(self, SSL_accept);
+
+ return ossl_start_ssl(self, SSL_accept, "SSL_accept", Qfalse);
}
+/*
+ * call-seq:
+ * ssl.accept_nonblock([options]) => self
+ *
+ * Initiates the SSL/TLS handshake as a server in non-blocking manner.
+ *
+ * # emulates blocking accept
+ * begin
+ * ssl.accept_nonblock
+ * rescue IO::WaitReadable
+ * IO.select([s2])
+ * retry
+ * rescue IO::WaitWritable
+ * IO.select(nil, [s2])
+ * retry
+ * end
+ *
+ * By specifying a keyword argument _exception_ to +false+, you can indicate
+ * that accept_nonblock should not raise an IO::WaitReadable or
+ * IO::WaitWritable exception, but return the symbol +:wait_readable+ or
+ * +:wait_writable+ instead.
+ */
static VALUE
-ossl_ssl_read(int argc, VALUE *argv, VALUE self)
+ossl_ssl_accept_nonblock(int argc, VALUE *argv, VALUE self)
+{
+ VALUE opts;
+
+ rb_scan_args(argc, argv, "0:", &opts);
+ ossl_ssl_setup(self);
+
+ return ossl_start_ssl(self, SSL_accept, "SSL_accept", opts);
+}
+
+static VALUE
+ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
{
SSL *ssl;
- int ilen, nread = 0;
- VALUE len, str;
- OpenFile *fptr;
+ int ilen;
+ VALUE len, str, cb_state;
+ VALUE opts = Qnil;
+
+ if (nonblock) {
+ rb_scan_args(argc, argv, "11:", &len, &str, &opts);
+ } else {
+ rb_scan_args(argc, argv, "11", &len, &str);
+ }
+ GetSSL(self, ssl);
+ if (!ssl_started(ssl))
+ rb_raise(eSSLError, "SSL session is not started yet");
- rb_scan_args(argc, argv, "11", &len, &str);
ilen = NUM2INT(len);
- if(NIL_P(str)) str = rb_str_new(0, ilen);
- else{
+ if (NIL_P(str))
+ str = rb_str_new(0, ilen);
+ else {
StringValue(str);
- rb_str_modify(str);
- rb_str_resize(str, ilen);
- }
- if(ilen == 0) return str;
-
- Data_Get_Struct(self, SSL, ssl);
- GetOpenFile(ossl_ssl_get_io(self), fptr);
- if (ssl) {
- if(SSL_pending(ssl) <= 0)
- rb_thread_wait_fd(fileno(fptr->f));
- for (;;){
- nread = SSL_read(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
- switch(ssl_get_error(ssl, nread)){
- case SSL_ERROR_NONE:
- goto end;
- case SSL_ERROR_ZERO_RETURN:
- rb_eof_error();
- case SSL_ERROR_WANT_WRITE:
- rb_io_wait_writable(fileno(fptr->f));
- continue;
- case SSL_ERROR_WANT_READ:
- rb_io_wait_readable(fileno(fptr->f));
- continue;
- case SSL_ERROR_SYSCALL:
- if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
- rb_sys_fail(0);
- default:
- ossl_raise(eSSLError, "SSL_read:");
- }
- }
+ if (RSTRING_LEN(str) >= ilen)
+ rb_str_modify(str);
+ else
+ rb_str_modify_expand(str, ilen - RSTRING_LEN(str));
}
- else {
- ID id_sysread = rb_intern("sysread");
- rb_warning("SSL session is not started yet.");
- return rb_funcall(ossl_ssl_get_io(self), id_sysread, 2, len, str);
+
+ if (ilen == 0) {
+ rb_str_set_len(str, 0);
+ return str;
}
- end:
- RSTRING(str)->len = nread;
- RSTRING(str)->ptr[nread] = 0;
- OBJ_TAINT(str);
+ VALUE io = rb_attr_get(self, id_i_io);
- return str;
+ for (;;) {
+ rb_str_locktmp(str);
+ int nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
+ int saved_errno = errno_mapped();
+ rb_str_unlocktmp(str);
+
+ cb_state = rb_attr_get(self, ID_callback_state);
+ if (!NIL_P(cb_state)) {
+ rb_ivar_set(self, ID_callback_state, Qnil);
+ ossl_clear_error();
+ rb_jump_tag(NUM2INT(cb_state));
+ }
+
+ switch (SSL_get_error(ssl, nread)) {
+ case SSL_ERROR_NONE:
+ rb_str_set_len(str, nread);
+ return str;
+ case SSL_ERROR_ZERO_RETURN:
+ if (no_exception_p(opts)) { return Qnil; }
+ rb_eof_error();
+ case SSL_ERROR_WANT_WRITE:
+ if (nonblock) {
+ if (no_exception_p(opts)) { return sym_wait_writable; }
+ write_would_block(nonblock);
+ }
+ io_wait_writable(io);
+ break;
+ case SSL_ERROR_WANT_READ:
+ if (nonblock) {
+ if (no_exception_p(opts)) { return sym_wait_readable; }
+ read_would_block(nonblock);
+ }
+ io_wait_readable(io);
+ break;
+ case SSL_ERROR_SYSCALL:
+ if (!ERR_peek_error()) {
+ if (saved_errno)
+ rb_exc_raise(rb_syserr_new(saved_errno, "SSL_read"));
+ else {
+ /*
+ * The underlying BIO returned 0. This is actually a
+ * protocol error. But unfortunately, not all
+ * implementations cleanly shutdown the TLS connection
+ * but just shutdown/close the TCP connection. So report
+ * EOF for now...
+ */
+ if (no_exception_p(opts)) { return Qnil; }
+ rb_eof_error();
+ }
+ }
+ /* fall through */
+ default:
+ ossl_raise(eSSLError, "SSL_read");
+ }
+
+ // Ensure the buffer is not modified during io_wait_*able()
+ rb_str_modify(str);
+ if (rb_str_capacity(str) < (size_t)ilen)
+ rb_raise(eSSLError, "read buffer was modified");
+ }
}
+/*
+ * call-seq:
+ * ssl.sysread(length) => string
+ * ssl.sysread(length, buffer) => buffer
+ *
+ * Reads _length_ bytes from the SSL connection. If a pre-allocated _buffer_
+ * is provided the data will be written into it.
+ */
static VALUE
-ossl_ssl_write(VALUE self, VALUE str)
+ossl_ssl_read(int argc, VALUE *argv, VALUE self)
+{
+ return ossl_ssl_read_internal(argc, argv, self, 0);
+}
+
+/*
+ * call-seq:
+ * ssl.sysread_nonblock(length) => string
+ * ssl.sysread_nonblock(length, buffer) => buffer
+ * ssl.sysread_nonblock(length[, buffer [, opts]) => buffer
+ *
+ * A non-blocking version of #sysread. Raises an SSLError if reading would
+ * block. If "exception: false" is passed, this method returns a symbol of
+ * :wait_readable, :wait_writable, or nil, rather than raising an exception.
+ *
+ * Reads _length_ bytes from the SSL connection. If a pre-allocated _buffer_
+ * is provided the data will be written into it.
+ */
+static VALUE
+ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
+{
+ return ossl_ssl_read_internal(argc, argv, self, 1);
+}
+
+static VALUE
+ossl_ssl_write_internal_safe(VALUE _args)
{
+ VALUE *args = (VALUE*)_args;
+ VALUE self = args[0];
+ VALUE str = args[1];
+ VALUE opts = args[2];
+
SSL *ssl;
- int nwrite = 0;
- OpenFile *fptr;
+ rb_io_t *fptr;
+ int num, nonblock = opts != Qfalse;
+ VALUE cb_state;
+
+ GetSSL(self, ssl);
+ if (!ssl_started(ssl))
+ rb_raise(eSSLError, "SSL session is not started yet");
+
+ VALUE io = rb_attr_get(self, id_i_io);
+ GetOpenFile(io, fptr);
+
+ /* SSL_write(3ssl) manpage states num == 0 is undefined */
+ num = RSTRING_LENINT(str);
+ if (num == 0)
+ return INT2FIX(0);
+
+ for (;;) {
+ int nwritten = SSL_write(ssl, RSTRING_PTR(str), num);
+ int saved_errno = errno_mapped();
+
+ cb_state = rb_attr_get(self, ID_callback_state);
+ if (!NIL_P(cb_state)) {
+ rb_ivar_set(self, ID_callback_state, Qnil);
+ ossl_clear_error();
+ rb_jump_tag(NUM2INT(cb_state));
+ }
- StringValue(str);
- Data_Get_Struct(self, SSL, ssl);
- GetOpenFile(ossl_ssl_get_io(self), fptr);
-
- if (ssl) {
- for (;;){
- nwrite = SSL_write(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
- switch(ssl_get_error(ssl, nwrite)){
- case SSL_ERROR_NONE:
- goto end;
- case SSL_ERROR_WANT_WRITE:
- rb_io_wait_writable(fileno(fptr->f));
- continue;
- case SSL_ERROR_WANT_READ:
- rb_io_wait_readable(fileno(fptr->f));
+ switch (SSL_get_error(ssl, nwritten)) {
+ case SSL_ERROR_NONE:
+ return INT2NUM(nwritten);
+ case SSL_ERROR_WANT_WRITE:
+ if (no_exception_p(opts)) { return sym_wait_writable; }
+ write_would_block(nonblock);
+ io_wait_writable(io);
+ continue;
+ case SSL_ERROR_WANT_READ:
+ if (no_exception_p(opts)) { return sym_wait_readable; }
+ read_would_block(nonblock);
+ io_wait_readable(io);
+ continue;
+ case SSL_ERROR_SYSCALL:
+#ifdef __APPLE__
+ /*
+ * It appears that send syscall can return EPROTOTYPE if the
+ * socket is being torn down. Retry to get a proper errno to
+ * make the error handling in line with the socket library.
+ * [Bug #14713] https://bugs.ruby-lang.org/issues/14713
+ */
+ if (saved_errno == EPROTOTYPE)
continue;
- case SSL_ERROR_SYSCALL:
- if (errno) rb_sys_fail(0);
- default:
- ossl_raise(eSSLError, "SSL_write:");
- }
+#endif
+ if (saved_errno)
+ rb_exc_raise(rb_syserr_new(saved_errno, "SSL_write"));
+ /* fallthrough */
+ default:
+ ossl_raise(eSSLError, "SSL_write");
}
}
- else {
- ID id_syswrite = rb_intern("syswrite");
- rb_warning("SSL session is not started yet.");
- return rb_funcall(ossl_ssl_get_io(self), id_syswrite, 1, str);
+}
+
+
+static VALUE
+ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
+{
+ StringValue(str);
+ int frozen = RB_OBJ_FROZEN(str);
+ if (!frozen) {
+ rb_str_locktmp(str);
+ }
+ int state;
+ VALUE args[3] = {self, str, opts};
+ VALUE result = rb_protect(ossl_ssl_write_internal_safe, (VALUE)args, &state);
+ if (!frozen) {
+ rb_str_unlocktmp(str);
+ }
+
+ if (state) {
+ rb_jump_tag(state);
}
+ return result;
+}
+
+/*
+ * call-seq:
+ * ssl.syswrite(string) => Integer
+ *
+ * Writes _string_ to the SSL connection.
+ */
+static VALUE
+ossl_ssl_write(VALUE self, VALUE str)
+{
+ return ossl_ssl_write_internal(self, str, Qfalse);
+}
+
+/*
+ * call-seq:
+ * ssl.syswrite_nonblock(string) => Integer
+ * ssl.syswrite_nonblock(string, opts) => Integer
+ *
+ * Writes _string_ to the SSL connection in a non-blocking manner. Raises an
+ * SSLError if writing would block. If "exception: false" is passed, this
+ * method returns a symbol of :wait_readable or :wait_writable, rather than
+ * raising an exception.
+ */
+static VALUE
+ossl_ssl_write_nonblock(int argc, VALUE *argv, VALUE self)
+{
+ VALUE str, opts;
- end:
- return INT2NUM(nwrite);
+ rb_scan_args(argc, argv, "1:", &str, &opts);
+
+ return ossl_ssl_write_internal(self, str, opts);
}
+/*
+ * call-seq:
+ * ssl.stop => nil
+ *
+ * Sends "close notify" to the peer and tries to shut down the SSL connection
+ * gracefully.
+ */
static VALUE
-ossl_ssl_close(VALUE self)
+ossl_ssl_stop(VALUE self)
{
SSL *ssl;
+ int ret;
- Data_Get_Struct(self, SSL, ssl);
- ossl_ssl_shutdown(ssl);
- if (RTEST(ossl_ssl_get_sync_close(self)))
- rb_funcall(ossl_ssl_get_io(self), rb_intern("close"), 0);
+ GetSSL(self, ssl);
+ if (!ssl_started(ssl))
+ return Qnil;
+ ret = SSL_shutdown(ssl);
+ if (ret == 1) /* Have already received close_notify */
+ return Qnil;
+ if (ret == 0) /* Sent close_notify, but we don't wait for reply */
+ return Qnil;
+ /*
+ * XXX: Something happened. Possibly it failed because the underlying socket
+ * is not writable/readable, since it is in non-blocking mode. We should do
+ * some proper error handling using SSL_get_error() and maybe retry, but we
+ * can't block here. Give up for now.
+ */
+ ossl_clear_error();
return Qnil;
}
+/*
+ * call-seq:
+ * ssl.cert => cert or nil
+ *
+ * The X509 certificate for this socket endpoint.
+ */
static VALUE
ossl_ssl_get_cert(VALUE self)
{
SSL *ssl;
X509 *cert = NULL;
- Data_Get_Struct(self, SSL, ssl);
- if (ssl) {
- rb_warning("SSL session is not started yet.");
- return Qnil;
- }
+ GetSSL(self, ssl);
/*
* Is this OpenSSL bug? Should add a ref?
@@ -750,6 +2271,12 @@ ossl_ssl_get_cert(VALUE self)
return ossl_x509_new(cert);
}
+/*
+ * call-seq:
+ * ssl.peer_cert => cert or nil
+ *
+ * The X509 certificate for this socket's peer.
+ */
static VALUE
ossl_ssl_get_peer_cert(VALUE self)
{
@@ -757,12 +2284,7 @@ ossl_ssl_get_peer_cert(VALUE self)
X509 *cert = NULL;
VALUE obj;
- Data_Get_Struct(self, SSL, ssl);
-
- if (!ssl){
- rb_warning("SSL session is not started yet.");
- return Qnil;
- }
+ GetSSL(self, ssl);
cert = SSL_get_peer_certificate(ssl); /* Adds a ref => Safe to FREE. */
@@ -775,6 +2297,12 @@ ossl_ssl_get_peer_cert(VALUE self)
return obj;
}
+/*
+ * call-seq:
+ * ssl.peer_cert_chain => [cert, ...] or nil
+ *
+ * The X509 certificate chain for this socket's peer.
+ */
static VALUE
ossl_ssl_get_peer_cert_chain(VALUE self)
{
@@ -784,50 +2312,70 @@ ossl_ssl_get_peer_cert_chain(VALUE self)
VALUE ary;
int i, num;
- Data_Get_Struct(self, SSL, ssl);
- if(!ssl){
- rb_warning("SSL session is not started yet.");
- return Qnil;
- }
+ GetSSL(self, ssl);
+
chain = SSL_get_peer_cert_chain(ssl);
if(!chain) return Qnil;
- num = sk_num(chain);
+ num = sk_X509_num(chain);
ary = rb_ary_new2(num);
for (i = 0; i < num; i++){
- cert = (X509*)sk_value(chain, i);
- rb_ary_push(ary, ossl_x509_new(cert));
+ cert = sk_X509_value(chain, i);
+ rb_ary_push(ary, ossl_x509_new(cert));
}
return ary;
}
+/*
+ * call-seq:
+ * ssl.ssl_version => String
+ *
+ * Returns a String representing the SSL/TLS version that was negotiated
+ * for the connection, for example "TLSv1.2".
+ */
+static VALUE
+ossl_ssl_get_version(VALUE self)
+{
+ SSL *ssl;
+
+ GetSSL(self, ssl);
+
+ return rb_str_new2(SSL_get_version(ssl));
+}
+
+/*
+ * call-seq:
+ * ssl.cipher -> nil or [name, version, bits, alg_bits]
+ *
+ * Returns the cipher suite actually used in the current session, or nil if
+ * no session has been established.
+ */
static VALUE
ossl_ssl_get_cipher(VALUE self)
{
SSL *ssl;
- SSL_CIPHER *cipher;
+ const SSL_CIPHER *cipher;
- Data_Get_Struct(self, SSL, ssl);
- if (!ssl) {
- rb_warning("SSL session is not started yet.");
- return Qnil;
- }
+ GetSSL(self, ssl);
cipher = SSL_get_current_cipher(ssl);
-
- return ossl_ssl_cipher_to_ary(cipher);
+ return cipher ? ossl_ssl_cipher_to_ary(cipher) : Qnil;
}
+/*
+ * call-seq:
+ * ssl.state => string
+ *
+ * A description of the current connection state. This is for diagnostic
+ * purposes only.
+ */
static VALUE
ossl_ssl_get_state(VALUE self)
{
SSL *ssl;
VALUE ret;
- Data_Get_Struct(self, SSL, ssl);
- if (!ssl) {
- rb_warning("SSL session is not started yet.");
- return Qnil;
- }
+ GetSSL(self, ssl);
+
ret = rb_str_new2(SSL_state_string(ssl));
if (ruby_verbose) {
rb_str_cat2(ret, ": ");
@@ -836,102 +2384,951 @@ ossl_ssl_get_state(VALUE self)
return ret;
}
+/*
+ * call-seq:
+ * ssl.pending => Integer
+ *
+ * The number of bytes that are immediately available for reading.
+ */
static VALUE
ossl_ssl_pending(VALUE self)
{
SSL *ssl;
- Data_Get_Struct(self, SSL, ssl);
- if (!ssl) {
- rb_warning("SSL session is not started yet.");
+ GetSSL(self, ssl);
+
+ return INT2NUM(SSL_pending(ssl));
+}
+
+/*
+ * call-seq:
+ * ssl.session_reused? -> true | false
+ *
+ * Returns +true+ if a reused session was negotiated during the handshake.
+ */
+static VALUE
+ossl_ssl_session_reused(VALUE self)
+{
+ SSL *ssl;
+
+ GetSSL(self, ssl);
+
+ return SSL_session_reused(ssl) ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * ssl.session = session -> session
+ *
+ * Sets the Session to be used when the connection is established.
+ */
+static VALUE
+ossl_ssl_set_session(VALUE self, VALUE arg1)
+{
+ SSL *ssl;
+ SSL_SESSION *sess;
+
+ GetSSL(self, ssl);
+ GetSSLSession(arg1, sess);
+
+ if (SSL_set_session(ssl, sess) != 1)
+ ossl_raise(eSSLError, "SSL_set_session");
+
+ return arg1;
+}
+
+/*
+ * call-seq:
+ * ssl.hostname = hostname -> hostname
+ *
+ * Sets the server hostname used for SNI. This needs to be set before
+ * SSLSocket#connect.
+ */
+static VALUE
+ossl_ssl_set_hostname(VALUE self, VALUE arg)
+{
+ SSL *ssl;
+ char *hostname = NULL;
+
+ GetSSL(self, ssl);
+
+ if (!NIL_P(arg))
+ hostname = StringValueCStr(arg);
+
+ if (!SSL_set_tlsext_host_name(ssl, hostname))
+ ossl_raise(eSSLError, NULL);
+
+ /* for SSLSocket#hostname */
+ rb_ivar_set(self, id_i_hostname, arg);
+
+ return arg;
+}
+
+/*
+ * call-seq:
+ * ssl.verify_result => Integer
+ *
+ * Returns the result of the peer certificates verification. See verify(1)
+ * for error values and descriptions.
+ *
+ * If no peer certificate was presented X509_V_OK is returned.
+ */
+static VALUE
+ossl_ssl_get_verify_result(VALUE self)
+{
+ SSL *ssl;
+
+ GetSSL(self, ssl);
+
+ return LONG2NUM(SSL_get_verify_result(ssl));
+}
+
+/*
+ * call-seq:
+ * ssl.finished_message -> string or nil
+ *
+ * Returns the contents of the last +Finished+ message sent to the peer.
+ */
+static VALUE
+ossl_ssl_get_finished(VALUE self)
+{
+ SSL *ssl;
+ char sizer[1];
+ size_t len;
+
+ GetSSL(self, ssl);
+
+ len = SSL_get_finished(ssl, sizer, 0);
+ if (len == 0)
+ return Qnil;
+
+ VALUE str = rb_str_new(NULL, len);
+ SSL_get_finished(ssl, RSTRING_PTR(str), len);
+ return str;
+}
+
+/*
+ * call-seq:
+ * ssl.peer_finished_message -> string or nil
+ *
+ * Returns the contents of the last +Finished+ message expected to be sent
+ * by the peer.
+ */
+static VALUE
+ossl_ssl_get_peer_finished(VALUE self)
+{
+ SSL *ssl;
+ char sizer[1];
+ size_t len;
+
+ GetSSL(self, ssl);
+
+ len = SSL_get_peer_finished(ssl, sizer, 0);
+ if (len == 0)
+ return Qnil;
+
+ VALUE str = rb_str_new(NULL, len);
+ SSL_get_peer_finished(ssl, RSTRING_PTR(str), len);
+ return str;
+}
+
+/*
+ * call-seq:
+ * ssl.client_ca => [x509name, ...] or nil
+ *
+ * Returns the list of client CAs. Please note that in contrast to
+ * SSLContext#client_ca= no array of X509::Certificate is returned but
+ * X509::Name instances of the CA's subject distinguished name.
+ *
+ * In server mode, returns the list set by SSLContext#client_ca=.
+ * In client mode, returns the list of client CAs sent from the server.
+ */
+static VALUE
+ossl_ssl_get_client_ca_list(VALUE self)
+{
+ SSL *ssl;
+ STACK_OF(X509_NAME) *ca;
+
+ GetSSL(self, ssl);
+
+ ca = SSL_get_client_CA_list(ssl);
+ if (!ca)
+ return Qnil;
+ return ossl_x509name_sk2ary(ca);
+}
+
+# ifdef OSSL_USE_NEXTPROTONEG
+/*
+ * call-seq:
+ * ssl.npn_protocol => String | nil
+ *
+ * Returns the protocol string that was finally selected by the client
+ * during the handshake.
+ */
+static VALUE
+ossl_ssl_npn_protocol(VALUE self)
+{
+ SSL *ssl;
+ const unsigned char *out;
+ unsigned int outlen;
+
+ GetSSL(self, ssl);
+
+ SSL_get0_next_proto_negotiated(ssl, &out, &outlen);
+ if (!outlen)
return Qnil;
+ else
+ return rb_str_new((const char *) out, outlen);
+}
+# endif
+
+/*
+ * call-seq:
+ * ssl.alpn_protocol => String | nil
+ *
+ * Returns the ALPN protocol string that was finally selected by the server
+ * during the handshake.
+ */
+static VALUE
+ossl_ssl_alpn_protocol(VALUE self)
+{
+ SSL *ssl;
+ const unsigned char *out;
+ unsigned int outlen;
+
+ GetSSL(self, ssl);
+
+ SSL_get0_alpn_selected(ssl, &out, &outlen);
+ if (!outlen)
+ return Qnil;
+ else
+ return rb_str_new((const char *) out, outlen);
+}
+
+/*
+ * call-seq:
+ * session.export_keying_material(label, length) -> String
+ *
+ * Enables use of shared session key material in accordance with RFC 5705.
+ */
+static VALUE
+ossl_ssl_export_keying_material(int argc, VALUE *argv, VALUE self)
+{
+ SSL *ssl;
+ VALUE str;
+ VALUE label;
+ VALUE length;
+ VALUE context;
+ unsigned char *p;
+ size_t len;
+ int use_ctx = 0;
+ unsigned char *ctx = NULL;
+ size_t ctx_len = 0;
+ int ret;
+
+ rb_scan_args(argc, argv, "21", &label, &length, &context);
+ StringValue(label);
+
+ GetSSL(self, ssl);
+
+ len = (size_t)NUM2LONG(length);
+ str = rb_str_new(0, len);
+ p = (unsigned char *)RSTRING_PTR(str);
+ if (!NIL_P(context)) {
+ use_ctx = 1;
+ StringValue(context);
+ ctx = (unsigned char *)RSTRING_PTR(context);
+ ctx_len = RSTRING_LEN(context);
}
+ ret = SSL_export_keying_material(ssl, p, len, (char *)RSTRING_PTR(label),
+ RSTRING_LENINT(label), ctx, ctx_len, use_ctx);
+ if (ret == 0 || ret == -1) {
+ ossl_raise(eSSLError, "SSL_export_keying_material");
+ }
+ return str;
+}
- return INT2NUM(SSL_pending(ssl));
+/*
+ * call-seq:
+ * ssl.tmp_key => PKey or nil
+ *
+ * Returns the ephemeral key used in case of forward secrecy cipher.
+ */
+static VALUE
+ossl_ssl_tmp_key(VALUE self)
+{
+ SSL *ssl;
+ EVP_PKEY *key;
+
+ GetSSL(self, ssl);
+ if (!SSL_get_server_tmp_key(ssl, &key))
+ return Qnil;
+ return ossl_pkey_wrap(key);
}
-void
-Init_ossl_ssl()
+#ifdef HAVE_SSL_GET0_PEER_SIGNATURE_NAME
+/*
+ * call-seq:
+ * ssl.sigalg => String or nil
+ *
+ * Returns the signature algorithm name, the IANA name of the signature scheme
+ * used by the local to sign the TLS handshake.
+ */
+static VALUE
+ossl_ssl_get_sigalg(VALUE self)
{
- int i;
+ SSL *ssl;
+ const char *name;
- ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_vcb_idx",0,0,0);
- ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,"ossl_ssl_ex_store_p",0,0,0);
- ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_ptr_idx",0,0,0);
- ossl_ssl_ex_client_cert_cb_idx =
- SSL_get_ex_new_index(0,"ossl_ssl_ex_client_cert_cb_idx",0,0,0);
- ossl_ssl_ex_tmp_dh_callback_idx =
- SSL_get_ex_new_index(0,"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0);
+ GetSSL(self, ssl);
+ if (!SSL_get0_signature_name(ssl, &name))
+ return Qnil;
+ return rb_str_new_cstr(name);
+}
+
+/*
+ * call-seq:
+ * ssl.peer_sigalg => String or nil
+ *
+ * Returns the signature algorithm name, the IANA name of the signature scheme
+ * used by the peer to sign the TLS handshake.
+ */
+static VALUE
+ossl_ssl_get_peer_sigalg(VALUE self)
+{
+ SSL *ssl;
+ const char *name;
+
+ GetSSL(self, ssl);
+ if (!SSL_get0_peer_signature_name(ssl, &name))
+ return Qnil;
+ return rb_str_new_cstr(name);
+}
+#endif
+#ifdef HAVE_SSL_GET0_GROUP_NAME
+/*
+ * call-seq:
+ * ssl.group => String or nil
+ *
+ * Returns the name of the group that was used for the key agreement of the
+ * current TLS session establishment.
+ */
+static VALUE
+ossl_ssl_get_group(VALUE self)
+{
+ SSL *ssl;
+ const char *name;
+
+ GetSSL(self, ssl);
+ if (!(name = SSL_get0_group_name(ssl)))
+ return Qnil;
+ return rb_str_new_cstr(name);
+}
+#endif
+
+#endif /* !defined(OPENSSL_NO_SOCK) */
+
+void
+Init_ossl_ssl(void)
+{
+#if 0
+ rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
+ rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
+#endif
+
+#ifndef OPENSSL_NO_SOCK
+ id_call = rb_intern_const("call");
+ ID_callback_state = rb_intern_const("callback_state");
+
+ ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_ptr_idx", 0, 0, 0);
+ if (ossl_ssl_ex_ptr_idx < 0)
+ ossl_raise(rb_eRuntimeError, "SSL_get_ex_new_index");
+ ossl_sslctx_ex_ptr_idx = SSL_CTX_get_ex_new_index(0, (void *)"ossl_sslctx_ex_ptr_idx", 0, 0, 0);
+ if (ossl_sslctx_ex_ptr_idx < 0)
+ ossl_raise(rb_eRuntimeError, "SSL_CTX_get_ex_new_index");
+
+ /* Document-module: OpenSSL::SSL
+ *
+ * Use SSLContext to set up the parameters for a TLS (former SSL)
+ * connection. Both client and server TLS connections are supported,
+ * SSLSocket and SSLServer may be used in conjunction with an instance
+ * of SSLContext to set up connections.
+ */
mSSL = rb_define_module_under(mOSSL, "SSL");
- eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError);
- /* class SSLContext */
+ /* Document-class: OpenSSL::SSL::SSLError
+ *
+ * Generic error class raised by SSLSocket and SSLContext.
+ */
+ eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError);
+ eSSLErrorWaitReadable = rb_define_class_under(mSSL, "SSLErrorWaitReadable", eSSLError);
+ rb_include_module(eSSLErrorWaitReadable, rb_mWaitReadable);
+ eSSLErrorWaitWritable = rb_define_class_under(mSSL, "SSLErrorWaitWritable", eSSLError);
+ rb_include_module(eSSLErrorWaitWritable, rb_mWaitWritable);
+
+ Init_ossl_ssl_session();
+
+ /* Document-class: OpenSSL::SSL::SSLContext
+ *
+ * An SSLContext is used to set various options regarding certificates,
+ * algorithms, verification, session caching, etc. The SSLContext is
+ * used to create an SSLSocket.
+ *
+ * All attributes must be set before creating an SSLSocket as the
+ * SSLContext will be frozen afterward.
+ */
cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
- for(i = 0; i < numberof(ossl_sslctx_attrs); i++)
- rb_attr(cSSLContext, rb_intern(ossl_sslctx_attrs[i]), 1, 1, Qfalse);
- rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1);
+ rb_undef_method(cSSLContext, "initialize_copy");
+
+ /*
+ * Context certificate
+ *
+ * The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
+ * It is recommended to use #add_certificate instead.
+ */
+ rb_attr(cSSLContext, rb_intern_const("cert"), 1, 1, Qfalse);
+
+ /*
+ * Context private key
+ *
+ * The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
+ * It is recommended to use #add_certificate instead.
+ */
+ rb_attr(cSSLContext, rb_intern_const("key"), 1, 1, Qfalse);
+
+ /*
+ * A certificate or Array of certificates that will be sent to the client.
+ */
+ rb_attr(cSSLContext, rb_intern_const("client_ca"), 1, 1, Qfalse);
+
+ /*
+ * The path to a file containing a PEM-format CA certificate
+ */
+ rb_attr(cSSLContext, rb_intern_const("ca_file"), 1, 1, Qfalse);
+
+ /*
+ * The path to a directory containing CA certificates in PEM format.
+ *
+ * Files are looked up by subject's X509 name's hash value.
+ */
+ rb_attr(cSSLContext, rb_intern_const("ca_path"), 1, 1, Qfalse);
+
+ /*
+ * Maximum session lifetime in seconds.
+ */
+ rb_attr(cSSLContext, rb_intern_const("timeout"), 1, 1, Qfalse);
+
+ /*
+ * Session verification mode.
+ *
+ * Valid modes are VERIFY_NONE, VERIFY_PEER, VERIFY_CLIENT_ONCE,
+ * VERIFY_FAIL_IF_NO_PEER_CERT and defined on OpenSSL::SSL
+ *
+ * The default mode is VERIFY_NONE, which does not perform any verification
+ * at all.
+ *
+ * See SSL_CTX_set_verify(3) for details.
+ */
+ rb_attr(cSSLContext, rb_intern_const("verify_mode"), 1, 1, Qfalse);
+
+ /*
+ * Number of CA certificates to walk when verifying a certificate chain.
+ */
+ rb_attr(cSSLContext, rb_intern_const("verify_depth"), 1, 1, Qfalse);
+
+ /*
+ * A callback for additional certificate verification. The callback is
+ * invoked for each certificate in the chain.
+ *
+ * The callback is invoked with two values. _preverify_ok_ indicates
+ * indicates if the verification was passed (+true+) or not (+false+).
+ * _store_context_ is an OpenSSL::X509::StoreContext containing the
+ * context used for certificate verification.
+ *
+ * If the callback returns +false+, the chain verification is immediately
+ * stopped and a bad_certificate alert is then sent.
+ */
+ rb_attr(cSSLContext, rb_intern_const("verify_callback"), 1, 1, Qfalse);
+
+ /*
+ * Whether to check the server certificate is valid for the hostname.
+ *
+ * In order to make this work, verify_mode must be set to VERIFY_PEER and
+ * the server hostname must be given by OpenSSL::SSL::SSLSocket#hostname=.
+ */
+ rb_attr(cSSLContext, rb_intern_const("verify_hostname"), 1, 1, Qfalse);
+
+ /*
+ * An OpenSSL::X509::Store used for certificate verification.
+ */
+ rb_attr(cSSLContext, rb_intern_const("cert_store"), 1, 1, Qfalse);
+
+ /*
+ * An Array of extra X509 certificates to be added to the certificate
+ * chain.
+ *
+ * The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
+ * It is recommended to use #add_certificate instead.
+ */
+ rb_attr(cSSLContext, rb_intern_const("extra_chain_cert"), 1, 1, Qfalse);
+
+ /*
+ * A callback invoked when a client certificate is requested by a server
+ * and no certificate has been set.
+ *
+ * The callback is invoked with a Session and must return an Array
+ * containing an OpenSSL::X509::Certificate and an OpenSSL::PKey. If any
+ * other value is returned the handshake is suspended.
+ */
+ rb_attr(cSSLContext, rb_intern_const("client_cert_cb"), 1, 1, Qfalse);
+
+#ifndef OPENSSL_NO_DH
+ /*
+ * A callback invoked when DH parameters are required for ephemeral DH key
+ * exchange.
+ *
+ * The callback is invoked with the SSLSocket, a
+ * flag indicating the use of an export cipher and the keylength
+ * required.
+ *
+ * The callback must return an OpenSSL::PKey::DH instance of the correct
+ * key length.
+ *
+ * <b>Deprecated in version 3.0.</b> Use #tmp_dh= instead.
+ */
+ rb_attr(cSSLContext, rb_intern_const("tmp_dh_callback"), 1, 1, Qfalse);
+#endif
+
+ /*
+ * Sets the context in which a session can be reused. This allows
+ * sessions for multiple applications to be distinguished, for example, by
+ * name.
+ */
+ rb_attr(cSSLContext, rb_intern_const("session_id_context"), 1, 1, Qfalse);
+
+ /*
+ * A callback invoked on a server when a session is proposed by the client
+ * but the session could not be found in the server's internal cache.
+ *
+ * The callback is invoked with the SSLSocket and session id. The
+ * callback may return a Session from an external cache.
+ */
+ rb_attr(cSSLContext, rb_intern_const("session_get_cb"), 1, 1, Qfalse);
+
+ /*
+ * A callback invoked when a new session was negotiated.
+ *
+ * The callback is invoked with an SSLSocket. If +false+ is returned the
+ * session will be removed from the internal cache.
+ */
+ rb_attr(cSSLContext, rb_intern_const("session_new_cb"), 1, 1, Qfalse);
+
+ /*
+ * A callback invoked when a session is removed from the internal cache.
+ *
+ * The callback is invoked with an SSLContext and a Session.
+ *
+ * IMPORTANT NOTE: It is currently not possible to use this safely in a
+ * multi-threaded application. The callback is called inside a global lock
+ * and it can randomly cause deadlock on Ruby thread switching.
+ */
+ rb_attr(cSSLContext, rb_intern_const("session_remove_cb"), 1, 1, Qfalse);
+
+ /*
+ * A callback invoked whenever a new handshake is initiated on an
+ * established connection. May be used to disable renegotiation entirely.
+ *
+ * The callback is invoked with the active SSLSocket. The callback's
+ * return value is ignored. A normal return indicates "approval" of the
+ * renegotiation and will continue the process. To forbid renegotiation
+ * and to cancel the process, raise an exception within the callback.
+ *
+ * === Disable client renegotiation
+ *
+ * When running a server, it is often desirable to disable client
+ * renegotiation entirely. You may use a callback as follows to implement
+ * this feature:
+ *
+ * ctx.renegotiation_cb = lambda do |ssl|
+ * raise RuntimeError, "Client renegotiation disabled"
+ * end
+ */
+ rb_attr(cSSLContext, rb_intern_const("renegotiation_cb"), 1, 1, Qfalse);
+#ifdef OSSL_USE_NEXTPROTONEG
+ /*
+ * An Enumerable of Strings. Each String represents a protocol to be
+ * advertised as the list of supported protocols for Next Protocol
+ * Negotiation. Supported in OpenSSL 1.0.1 and higher. Has no effect
+ * on the client side. If not set explicitly, the NPN extension will
+ * not be sent by the server in the handshake.
+ *
+ * === Example
+ *
+ * ctx.npn_protocols = ["http/1.1", "spdy/2"]
+ */
+ rb_attr(cSSLContext, rb_intern_const("npn_protocols"), 1, 1, Qfalse);
+ /*
+ * A callback invoked on the client side when the client needs to select
+ * a protocol from the list sent by the server. Supported in OpenSSL 1.0.1
+ * and higher. The client MUST select a protocol of those advertised by
+ * the server. If none is acceptable, raising an error in the callback
+ * will cause the handshake to fail. Not setting this callback explicitly
+ * means not supporting the NPN extension on the client - any protocols
+ * advertised by the server will be ignored.
+ *
+ * === Example
+ *
+ * ctx.npn_select_cb = lambda do |protocols|
+ * # inspect the protocols and select one
+ * protocols.first
+ * end
+ */
+ rb_attr(cSSLContext, rb_intern_const("npn_select_cb"), 1, 1, Qfalse);
+#endif
+
+ /*
+ * An Enumerable of Strings. Each String represents a protocol to be
+ * advertised as the list of supported protocols for Application-Layer
+ * Protocol Negotiation. Supported in OpenSSL 1.0.2 and higher. Has no
+ * effect on the server side. If not set explicitly, the ALPN extension will
+ * not be included in the handshake.
+ *
+ * === Example
+ *
+ * ctx.alpn_protocols = ["http/1.1", "spdy/2", "h2"]
+ */
+ rb_attr(cSSLContext, rb_intern_const("alpn_protocols"), 1, 1, Qfalse);
+ /*
+ * A callback invoked on the server side when the server needs to select
+ * a protocol from the list sent by the client. Supported in OpenSSL 1.0.2
+ * and higher. The callback must return a protocol of those advertised by
+ * the client. If none is acceptable, raising an error in the callback
+ * will cause the handshake to fail. Not setting this callback explicitly
+ * means not supporting the ALPN extension on the server - any protocols
+ * advertised by the client will be ignored.
+ *
+ * === Example
+ *
+ * ctx.alpn_select_cb = lambda do |protocols|
+ * # inspect the protocols and select one
+ * protocols.first
+ * end
+ */
+ rb_attr(cSSLContext, rb_intern_const("alpn_select_cb"), 1, 1, Qfalse);
+
+ /*
+ * A callback invoked when TLS key material is generated or received, in
+ * order to allow applications to store this keying material for debugging
+ * purposes.
+ *
+ * The callback is invoked with an SSLSocket and a string containing the
+ * key material in the format used by NSS for its SSLKEYLOGFILE debugging
+ * output.
+ *
+ * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
+ * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
+ * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
+ *
+ * === Example
+ *
+ * context.keylog_cb = proc do |_sock, line|
+ * File.open('ssl_keylog_file', "a") do |f|
+ * f.write("#{line}\n")
+ * end
+ * end
+ */
+ rb_attr(cSSLContext, rb_intern_const("keylog_cb"), 1, 1, Qfalse);
+
+ rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
+ rb_define_alias(cSSLContext, "ssl_timeout=", "timeout=");
+ rb_define_method(cSSLContext, "min_version=", ossl_sslctx_set_min_version, 1);
+ rb_define_method(cSSLContext, "max_version=", ossl_sslctx_set_max_version, 1);
rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
+ rb_define_method(cSSLContext, "ciphersuites=", ossl_sslctx_set_ciphersuites, 1);
+#ifdef HAVE_SSL_CTX_SET1_SIGALGS_LIST // Not in LibreSSL yet
+ rb_define_method(cSSLContext, "sigalgs=", ossl_sslctx_set_sigalgs, 1);
+#endif
+#ifdef HAVE_SSL_CTX_SET1_CLIENT_SIGALGS_LIST // Not in LibreSSL or AWS-LC yet
+ rb_define_method(cSSLContext, "client_sigalgs=", ossl_sslctx_set_client_sigalgs, 1);
+#endif
+#ifndef OPENSSL_NO_DH
+ rb_define_method(cSSLContext, "tmp_dh=", ossl_sslctx_set_tmp_dh, 1);
+#endif
+ rb_define_method(cSSLContext, "groups=", ossl_sslctx_set_groups, 1);
+ rb_define_alias(cSSLContext, "ecdh_curves=", "groups=");
+ rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0);
+ rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1);
+#ifdef SSL_MODE_SEND_FALLBACK_SCSV
+ rb_define_method(cSSLContext, "enable_fallback_scsv", ossl_sslctx_enable_fallback_scsv, 0);
+#endif
+ rb_define_method(cSSLContext, "add_certificate", ossl_sslctx_add_certificate, -1);
+
+ rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
+ rb_define_alias(cSSLContext, "freeze", "setup");
- /* class SSLSocket */
+ /*
+ * No session caching for client or server
+ */
+ rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2NUM(SSL_SESS_CACHE_OFF));
+
+ /*
+ * Client sessions are added to the session cache
+ */
+ rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2NUM(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */
+
+ /*
+ * Server sessions are added to the session cache
+ */
+ rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2NUM(SSL_SESS_CACHE_SERVER));
+
+ /*
+ * Both client and server sessions are added to the session cache
+ */
+ rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2NUM(SSL_SESS_CACHE_BOTH)); /* no different than CACHE_SERVER in 0.9.8e */
+
+ /*
+ * Normally the session cache is checked for expired sessions every 255
+ * connections. Since this may lead to a delay that cannot be controlled,
+ * the automatic flushing may be disabled and #flush_sessions can be
+ * called explicitly.
+ */
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2NUM(SSL_SESS_CACHE_NO_AUTO_CLEAR));
+
+ /*
+ * Always perform external lookups of sessions even if they are in the
+ * internal cache.
+ *
+ * This flag has no effect on clients
+ */
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP));
+
+ /*
+ * Never automatically store sessions in the internal store.
+ */
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL_STORE));
+
+ /*
+ * Enables both SESSION_CACHE_NO_INTERNAL_LOOKUP and
+ * SESSION_CACHE_NO_INTERNAL_STORE.
+ */
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL));
+
+ rb_define_method(cSSLContext, "session_add", ossl_sslctx_session_add, 1);
+ rb_define_method(cSSLContext, "session_remove", ossl_sslctx_session_remove, 1);
+ rb_define_method(cSSLContext, "session_cache_mode", ossl_sslctx_get_session_cache_mode, 0);
+ rb_define_method(cSSLContext, "session_cache_mode=", ossl_sslctx_set_session_cache_mode, 1);
+ rb_define_method(cSSLContext, "session_cache_size", ossl_sslctx_get_session_cache_size, 0);
+ rb_define_method(cSSLContext, "session_cache_size=", ossl_sslctx_set_session_cache_size, 1);
+ rb_define_method(cSSLContext, "session_cache_stats", ossl_sslctx_get_session_cache_stats, 0);
+ rb_define_method(cSSLContext, "flush_sessions", ossl_sslctx_flush_sessions, -1);
+ rb_define_method(cSSLContext, "options", ossl_sslctx_get_options, 0);
+ rb_define_method(cSSLContext, "options=", ossl_sslctx_set_options, 1);
+
+ /*
+ * Document-class: OpenSSL::SSL::SSLSocket
+ */
cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
- for(i = 0; i < numberof(ossl_ssl_attr_readers); i++)
- rb_attr(cSSLSocket, rb_intern(ossl_ssl_attr_readers[i]), 1, 0, Qfalse);
- for(i = 0; i < numberof(ossl_ssl_attrs); i++)
- rb_attr(cSSLSocket, rb_intern(ossl_ssl_attrs[i]), 1, 1, Qfalse);
- rb_define_alias(cSSLSocket, "to_io", "io");
rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
+ rb_undef_method(cSSLSocket, "initialize_copy");
rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
+ rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, -1);
rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
+ rb_define_method(cSSLSocket, "accept_nonblock", ossl_ssl_accept_nonblock, -1);
rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1);
+ rb_define_private_method(cSSLSocket, "sysread_nonblock", ossl_ssl_read_nonblock, -1);
rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1);
- rb_define_method(cSSLSocket, "sysclose", ossl_ssl_close, 0);
+ rb_define_private_method(cSSLSocket, "syswrite_nonblock", ossl_ssl_write_nonblock, -1);
+ rb_define_private_method(cSSLSocket, "stop", ossl_ssl_stop, 0);
rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0);
rb_define_method(cSSLSocket, "peer_cert", ossl_ssl_get_peer_cert, 0);
rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0);
+ rb_define_method(cSSLSocket, "ssl_version", ossl_ssl_get_version, 0);
rb_define_method(cSSLSocket, "cipher", ossl_ssl_get_cipher, 0);
rb_define_method(cSSLSocket, "state", ossl_ssl_get_state, 0);
rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0);
+ rb_define_method(cSSLSocket, "session_reused?", ossl_ssl_session_reused, 0);
+ /* implementation of OpenSSL::SSL::SSLSocket#session is in lib/openssl/ssl.rb */
+ rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
+ rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0);
+ rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0);
+ /* #hostname is defined in lib/openssl/ssl.rb */
+ rb_define_method(cSSLSocket, "hostname=", ossl_ssl_set_hostname, 1);
+ rb_define_method(cSSLSocket, "finished_message", ossl_ssl_get_finished, 0);
+ rb_define_method(cSSLSocket, "peer_finished_message", ossl_ssl_get_peer_finished, 0);
+ rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0);
+ rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0);
+ rb_define_method(cSSLSocket, "export_keying_material", ossl_ssl_export_keying_material, -1);
+# ifdef OSSL_USE_NEXTPROTONEG
+ rb_define_method(cSSLSocket, "npn_protocol", ossl_ssl_npn_protocol, 0);
+# endif
+#ifdef HAVE_SSL_GET0_PEER_SIGNATURE_NAME
+ rb_define_method(cSSLSocket, "sigalg", ossl_ssl_get_sigalg, 0);
+ rb_define_method(cSSLSocket, "peer_sigalg", ossl_ssl_get_peer_sigalg, 0);
+#endif
+#ifdef HAVE_SSL_GET0_GROUP_NAME
+ rb_define_method(cSSLSocket, "group", ossl_ssl_get_group, 0);
+#endif
-#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2FIX(SSL_##x))
-
- ossl_ssl_def_const(VERIFY_NONE);
- ossl_ssl_def_const(VERIFY_PEER);
- ossl_ssl_def_const(VERIFY_FAIL_IF_NO_PEER_CERT);
- ossl_ssl_def_const(VERIFY_CLIENT_ONCE);
- /* Not introduce constants included in OP_ALL such as...
- * ossl_ssl_def_const(OP_MICROSOFT_SESS_ID_BUG);
- * ossl_ssl_def_const(OP_NETSCAPE_CHALLENGE_BUG);
- * ossl_ssl_def_const(OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
- * ossl_ssl_def_const(OP_SSLREF2_REUSE_CERT_TYPE_BUG);
- * ossl_ssl_def_const(OP_MICROSOFT_BIG_SSLV3_BUFFER);
- * ossl_ssl_def_const(OP_MSIE_SSLV2_RSA_PADDING);
- * ossl_ssl_def_const(OP_SSLEAY_080_CLIENT_DH_BUG);
- * ossl_ssl_def_const(OP_TLS_D5_BUG);
- * ossl_ssl_def_const(OP_TLS_BLOCK_PADDING_BUG);
- * ossl_ssl_def_const(OP_DONT_INSERT_EMPTY_FRAGMENTS);
- */
- ossl_ssl_def_const(OP_ALL);
-#if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
- ossl_ssl_def_const(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
-#endif
-#if defined(SSL_OP_SINGLE_ECDH_USE)
- ossl_ssl_def_const(OP_SINGLE_ECDH_USE);
-#endif
- ossl_ssl_def_const(OP_SINGLE_DH_USE);
- ossl_ssl_def_const(OP_EPHEMERAL_RSA);
-#if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
- ossl_ssl_def_const(OP_CIPHER_SERVER_PREFERENCE);
-#endif
- ossl_ssl_def_const(OP_TLS_ROLLBACK_BUG);
- ossl_ssl_def_const(OP_NO_SSLv2);
- ossl_ssl_def_const(OP_NO_SSLv3);
- ossl_ssl_def_const(OP_NO_TLSv1);
- ossl_ssl_def_const(OP_PKCS1_CHECK_1);
- ossl_ssl_def_const(OP_PKCS1_CHECK_2);
- ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG);
- ossl_ssl_def_const(OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
+ rb_define_const(mSSL, "VERIFY_NONE", INT2NUM(SSL_VERIFY_NONE));
+ rb_define_const(mSSL, "VERIFY_PEER", INT2NUM(SSL_VERIFY_PEER));
+ rb_define_const(mSSL, "VERIFY_FAIL_IF_NO_PEER_CERT", INT2NUM(SSL_VERIFY_FAIL_IF_NO_PEER_CERT));
+ rb_define_const(mSSL, "VERIFY_CLIENT_ONCE", INT2NUM(SSL_VERIFY_CLIENT_ONCE));
+
+ rb_define_const(mSSL, "OP_ALL", ULONG2NUM(SSL_OP_ALL));
+#ifdef SSL_OP_CLEANSE_PLAINTEXT /* OpenSSL 3.0 */
+ rb_define_const(mSSL, "OP_CLEANSE_PLAINTEXT", ULONG2NUM(SSL_OP_CLEANSE_PLAINTEXT));
+#endif
+ rb_define_const(mSSL, "OP_LEGACY_SERVER_CONNECT", ULONG2NUM(SSL_OP_LEGACY_SERVER_CONNECT));
+#ifdef SSL_OP_ENABLE_KTLS /* OpenSSL 3.0 */
+ rb_define_const(mSSL, "OP_ENABLE_KTLS", ULONG2NUM(SSL_OP_ENABLE_KTLS));
+#endif
+ rb_define_const(mSSL, "OP_TLSEXT_PADDING", ULONG2NUM(SSL_OP_TLSEXT_PADDING));
+ rb_define_const(mSSL, "OP_SAFARI_ECDHE_ECDSA_BUG", ULONG2NUM(SSL_OP_SAFARI_ECDHE_ECDSA_BUG));
+#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF /* OpenSSL 3.0 */
+ rb_define_const(mSSL, "OP_IGNORE_UNEXPECTED_EOF", ULONG2NUM(SSL_OP_IGNORE_UNEXPECTED_EOF));
+#endif
+#ifdef SSL_OP_ALLOW_CLIENT_RENEGOTIATION /* OpenSSL 3.0 */
+ rb_define_const(mSSL, "OP_ALLOW_CLIENT_RENEGOTIATION", ULONG2NUM(SSL_OP_ALLOW_CLIENT_RENEGOTIATION));
+#endif
+#ifdef SSL_OP_DISABLE_TLSEXT_CA_NAMES /* OpenSSL 3.0 */
+ rb_define_const(mSSL, "OP_DISABLE_TLSEXT_CA_NAMES", ULONG2NUM(SSL_OP_DISABLE_TLSEXT_CA_NAMES));
+#endif
+#ifdef SSL_OP_ALLOW_NO_DHE_KEX /* OpenSSL 1.1.1, missing in LibreSSL */
+ rb_define_const(mSSL, "OP_ALLOW_NO_DHE_KEX", ULONG2NUM(SSL_OP_ALLOW_NO_DHE_KEX));
+#endif
+ rb_define_const(mSSL, "OP_DONT_INSERT_EMPTY_FRAGMENTS", ULONG2NUM(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS));
+ rb_define_const(mSSL, "OP_NO_TICKET", ULONG2NUM(SSL_OP_NO_TICKET));
+ rb_define_const(mSSL, "OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION));
+ rb_define_const(mSSL, "OP_NO_COMPRESSION", ULONG2NUM(SSL_OP_NO_COMPRESSION));
+ rb_define_const(mSSL, "OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION", ULONG2NUM(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
+#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC /* OpenSSL 1.1.1, missing in LibreSSL */
+ rb_define_const(mSSL, "OP_NO_ENCRYPT_THEN_MAC", ULONG2NUM(SSL_OP_NO_ENCRYPT_THEN_MAC));
+#endif
+#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT /* OpenSSL 1.1.1, missing in LibreSSL */
+ rb_define_const(mSSL, "OP_ENABLE_MIDDLEBOX_COMPAT", ULONG2NUM(SSL_OP_ENABLE_MIDDLEBOX_COMPAT));
+#endif
+#ifdef SSL_OP_PRIORITIZE_CHACHA /* OpenSSL 1.1.1, missing in LibreSSL */
+ rb_define_const(mSSL, "OP_PRIORITIZE_CHACHA", ULONG2NUM(SSL_OP_PRIORITIZE_CHACHA));
+#endif
+#ifdef SSL_OP_NO_ANTI_REPLAY /* OpenSSL 1.1.1, missing in LibreSSL */
+ rb_define_const(mSSL, "OP_NO_ANTI_REPLAY", ULONG2NUM(SSL_OP_NO_ANTI_REPLAY));
+#endif
+ rb_define_const(mSSL, "OP_NO_SSLv3", ULONG2NUM(SSL_OP_NO_SSLv3));
+ rb_define_const(mSSL, "OP_NO_TLSv1", ULONG2NUM(SSL_OP_NO_TLSv1));
+ rb_define_const(mSSL, "OP_NO_TLSv1_1", ULONG2NUM(SSL_OP_NO_TLSv1_1));
+ rb_define_const(mSSL, "OP_NO_TLSv1_2", ULONG2NUM(SSL_OP_NO_TLSv1_2));
+ rb_define_const(mSSL, "OP_NO_TLSv1_3", ULONG2NUM(SSL_OP_NO_TLSv1_3));
+ rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE));
+ rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG));
+#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1, missing in LibreSSL */
+ rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION));
+#endif
+ rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG));
+
+ /* SSL_OP_* flags for DTLS */
+#if 0
+ rb_define_const(mSSL, "OP_NO_QUERY_MTU", ULONG2NUM(SSL_OP_NO_QUERY_MTU));
+ rb_define_const(mSSL, "OP_COOKIE_EXCHANGE", ULONG2NUM(SSL_OP_COOKIE_EXCHANGE));
+ rb_define_const(mSSL, "OP_CISCO_ANYCONNECT", ULONG2NUM(SSL_OP_CISCO_ANYCONNECT));
+#endif
+
+ /* Deprecated in OpenSSL 1.1.0. */
+ rb_define_const(mSSL, "OP_MICROSOFT_SESS_ID_BUG", ULONG2NUM(SSL_OP_MICROSOFT_SESS_ID_BUG));
+ /* Deprecated in OpenSSL 1.1.0. */
+ rb_define_const(mSSL, "OP_NETSCAPE_CHALLENGE_BUG", ULONG2NUM(SSL_OP_NETSCAPE_CHALLENGE_BUG));
+ /* Deprecated in OpenSSL 0.9.8q and 1.0.0c. */
+ rb_define_const(mSSL, "OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG", ULONG2NUM(SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG));
+ /* Deprecated in OpenSSL 1.0.1h and 1.0.2. */
+ rb_define_const(mSSL, "OP_SSLREF2_REUSE_CERT_TYPE_BUG", ULONG2NUM(SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG));
+ /* Deprecated in OpenSSL 1.1.0. */
+ rb_define_const(mSSL, "OP_MICROSOFT_BIG_SSLV3_BUFFER", ULONG2NUM(SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER));
+ /* Deprecated in OpenSSL 0.9.7h and 0.9.8b. */
+ rb_define_const(mSSL, "OP_MSIE_SSLV2_RSA_PADDING", ULONG2NUM(SSL_OP_MSIE_SSLV2_RSA_PADDING));
+ /* Deprecated in OpenSSL 1.1.0. */
+ rb_define_const(mSSL, "OP_SSLEAY_080_CLIENT_DH_BUG", ULONG2NUM(SSL_OP_SSLEAY_080_CLIENT_DH_BUG));
+ /* Deprecated in OpenSSL 1.1.0. */
+ rb_define_const(mSSL, "OP_TLS_D5_BUG", ULONG2NUM(SSL_OP_TLS_D5_BUG));
+ /* Deprecated in OpenSSL 1.1.0. */
+ rb_define_const(mSSL, "OP_TLS_BLOCK_PADDING_BUG", ULONG2NUM(SSL_OP_TLS_BLOCK_PADDING_BUG));
+ /* Deprecated in OpenSSL 1.1.0. */
+ rb_define_const(mSSL, "OP_SINGLE_ECDH_USE", ULONG2NUM(SSL_OP_SINGLE_ECDH_USE));
+ /* Deprecated in OpenSSL 1.1.0. */
+ rb_define_const(mSSL, "OP_SINGLE_DH_USE", ULONG2NUM(SSL_OP_SINGLE_DH_USE));
+ /* Deprecated in OpenSSL 1.0.1k and 1.0.2. */
+ rb_define_const(mSSL, "OP_EPHEMERAL_RSA", ULONG2NUM(SSL_OP_EPHEMERAL_RSA));
+ /* Deprecated in OpenSSL 1.1.0. */
+ rb_define_const(mSSL, "OP_NO_SSLv2", ULONG2NUM(SSL_OP_NO_SSLv2));
+ /* Deprecated in OpenSSL 1.0.1. */
+ rb_define_const(mSSL, "OP_PKCS1_CHECK_1", ULONG2NUM(SSL_OP_PKCS1_CHECK_1));
+ /* Deprecated in OpenSSL 1.0.1. */
+ rb_define_const(mSSL, "OP_PKCS1_CHECK_2", ULONG2NUM(SSL_OP_PKCS1_CHECK_2));
+ /* Deprecated in OpenSSL 1.1.0. */
+ rb_define_const(mSSL, "OP_NETSCAPE_CA_DN_BUG", ULONG2NUM(SSL_OP_NETSCAPE_CA_DN_BUG));
+ /* Deprecated in OpenSSL 1.1.0. */
+ rb_define_const(mSSL, "OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG", ULONG2NUM(SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG));
+
+
+ /*
+ * SSL/TLS version constants. Used by SSLContext#min_version= and
+ * #max_version=
+ */
+ /* SSL 2.0 */
+ rb_define_const(mSSL, "SSL2_VERSION", INT2NUM(SSL2_VERSION));
+ /* SSL 3.0 */
+ rb_define_const(mSSL, "SSL3_VERSION", INT2NUM(SSL3_VERSION));
+ /* TLS 1.0 */
+ rb_define_const(mSSL, "TLS1_VERSION", INT2NUM(TLS1_VERSION));
+ /* TLS 1.1 */
+ rb_define_const(mSSL, "TLS1_1_VERSION", INT2NUM(TLS1_1_VERSION));
+ /* TLS 1.2 */
+ rb_define_const(mSSL, "TLS1_2_VERSION", INT2NUM(TLS1_2_VERSION));
+ /* TLS 1.3 */
+ rb_define_const(mSSL, "TLS1_3_VERSION", INT2NUM(TLS1_3_VERSION));
+
+
+ sym_exception = ID2SYM(rb_intern_const("exception"));
+ sym_wait_readable = ID2SYM(rb_intern_const("wait_readable"));
+ sym_wait_writable = ID2SYM(rb_intern_const("wait_writable"));
+
+ id_npn_protocols_encoded = rb_intern_const("npn_protocols_encoded");
+ id_each = rb_intern_const("each");
+
+#define DefIVarID(name) do \
+ id_i_##name = rb_intern_const("@"#name); while (0)
+
+ DefIVarID(cert_store);
+ DefIVarID(ca_file);
+ DefIVarID(ca_path);
+ DefIVarID(verify_mode);
+ DefIVarID(verify_depth);
+ DefIVarID(verify_callback);
+ DefIVarID(client_ca);
+ DefIVarID(renegotiation_cb);
+ DefIVarID(cert);
+ DefIVarID(key);
+ DefIVarID(extra_chain_cert);
+ DefIVarID(client_cert_cb);
+ DefIVarID(timeout);
+ DefIVarID(session_id_context);
+ DefIVarID(session_get_cb);
+ DefIVarID(session_new_cb);
+ DefIVarID(session_remove_cb);
+ DefIVarID(npn_select_cb);
+ DefIVarID(npn_protocols);
+ DefIVarID(alpn_protocols);
+ DefIVarID(alpn_select_cb);
+ DefIVarID(servername_cb);
+ DefIVarID(verify_hostname);
+ DefIVarID(keylog_cb);
+ DefIVarID(tmp_dh_callback);
+
+ DefIVarID(io);
+ DefIVarID(context);
+ DefIVarID(hostname);
+ DefIVarID(sync_close);
+#endif /* !defined(OPENSSL_NO_SOCK) */
}
diff --git a/ext/openssl/ossl_ssl.h b/ext/openssl/ossl_ssl.h
index 5929eef856..a87e62d450 100644
--- a/ext/openssl/ossl_ssl.h
+++ b/ext/openssl/ossl_ssl.h
@@ -1,21 +1,36 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_SSL_H_)
#define _OSSL_SSL_H_
+#define GetSSL(obj, ssl) do { \
+ TypedData_Get_Struct((obj), SSL, &ossl_ssl_type, (ssl)); \
+ if (!(ssl)) { \
+ ossl_raise(rb_eRuntimeError, "SSL is not initialized"); \
+ } \
+} while (0)
+
+#define GetSSLSession(obj, sess) do { \
+ TypedData_Get_Struct((obj), SSL_SESSION, &ossl_ssl_session_type, (sess)); \
+ if (!(sess)) { \
+ ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
+ } \
+} while (0)
+
+extern const rb_data_type_t ossl_ssl_type;
+extern const rb_data_type_t ossl_ssl_session_type;
extern VALUE mSSL;
-extern VALUE eSSLError;
extern VALUE cSSLSocket;
-extern VALUE cSSLContext;
+extern VALUE cSSLSession;
void Init_ossl_ssl(void);
+void Init_ossl_ssl_session(void);
#endif /* _OSSL_SSL_H_ */
diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c
new file mode 100644
index 0000000000..8a2fbf4100
--- /dev/null
+++ b/ext/openssl/ossl_ssl_session.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2004-2007 Technorama Ltd. <oss-ruby@technorama.net>
+ */
+
+#include "ossl.h"
+
+#ifndef OPENSSL_NO_SOCK
+VALUE cSSLSession;
+static VALUE eSSLSession;
+
+static void
+ossl_ssl_session_free(void *ptr)
+{
+ SSL_SESSION_free(ptr);
+}
+
+const rb_data_type_t ossl_ssl_session_type = {
+ "OpenSSL/SSL/Session",
+ {
+ 0, ossl_ssl_session_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static VALUE ossl_ssl_session_alloc(VALUE klass)
+{
+ return TypedData_Wrap_Struct(klass, &ossl_ssl_session_type, NULL);
+}
+
+/*
+ * call-seq:
+ * Session.new(ssl_socket) -> Session
+ * Session.new(string) -> Session
+ *
+ * Creates a new Session object from an instance of SSLSocket or DER/PEM encoded
+ * String.
+ */
+static VALUE
+ossl_ssl_session_initialize(VALUE self, VALUE arg1)
+{
+ SSL_SESSION *ctx;
+
+ if (RTYPEDDATA_DATA(self))
+ ossl_raise(eSSLSession, "SSL Session already initialized");
+
+ if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
+ SSL *ssl;
+
+ GetSSL(arg1, ssl);
+
+ if ((ctx = SSL_get1_session(ssl)) == NULL)
+ ossl_raise(eSSLSession, "no session available");
+ }
+ else {
+ BIO *in = ossl_obj2bio(&arg1);
+
+ ctx = d2i_SSL_SESSION_bio(in, NULL);
+ if (!ctx) {
+ OSSL_BIO_reset(in);
+ ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
+ }
+ BIO_free(in);
+ if (!ctx)
+ ossl_raise(rb_eArgError, "unknown type");
+ }
+
+ RTYPEDDATA_DATA(self) = ctx;
+
+ return self;
+}
+
+/* :nodoc: */
+static VALUE
+ossl_ssl_session_initialize_copy(VALUE self, VALUE other)
+{
+ SSL_SESSION *sess, *sess_other, *sess_new;
+
+ rb_check_frozen(self);
+ sess = RTYPEDDATA_DATA(self); /* XXX */
+ GetSSLSession(other, sess_other);
+
+ sess_new = ASN1_dup((i2d_of_void *)i2d_SSL_SESSION, (d2i_of_void *)d2i_SSL_SESSION,
+ (char *)sess_other);
+ if (!sess_new)
+ ossl_raise(eSSLSession, "ASN1_dup");
+
+ RTYPEDDATA_DATA(self) = sess_new;
+ SSL_SESSION_free(sess);
+
+ return self;
+}
+
+static int
+ossl_SSL_SESSION_cmp(const SSL_SESSION *a, const SSL_SESSION *b)
+{
+ unsigned int a_len;
+ const unsigned char *a_sid = SSL_SESSION_get_id(a, &a_len);
+ unsigned int b_len;
+ const unsigned char *b_sid = SSL_SESSION_get_id(b, &b_len);
+
+ if (SSL_SESSION_get_protocol_version(a) != SSL_SESSION_get_protocol_version(b))
+ return 1;
+ if (a_len != b_len)
+ return 1;
+
+ return CRYPTO_memcmp(a_sid, b_sid, a_len);
+}
+
+/*
+ * call-seq:
+ * session1 == session2 -> boolean
+ *
+ * Returns +true+ if the two Session is the same, +false+ if not.
+ */
+static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
+{
+ SSL_SESSION *ctx1, *ctx2;
+
+ GetSSLSession(val1, ctx1);
+ GetSSLSession(val2, ctx2);
+
+ switch (ossl_SSL_SESSION_cmp(ctx1, ctx2)) {
+ case 0: return Qtrue;
+ default: return Qfalse;
+ }
+}
+
+/*
+ * call-seq:
+ * session.time -> Time
+ *
+ * Returns the time at which the session was established.
+ */
+static VALUE
+ossl_ssl_session_get_time(VALUE self)
+{
+ SSL_SESSION *ctx;
+ long t;
+
+ GetSSLSession(self, ctx);
+ t = SSL_SESSION_get_time(ctx);
+ if (t == 0)
+ return Qnil;
+
+ return rb_funcall(rb_cTime, rb_intern("at"), 1, LONG2NUM(t));
+}
+
+/*
+ * call-seq:
+ * session.timeout -> Integer
+ *
+ * Returns the timeout value set for the session, in seconds from the
+ * established time.
+ *
+ */
+static VALUE
+ossl_ssl_session_get_timeout(VALUE self)
+{
+ SSL_SESSION *ctx;
+ long t;
+
+ GetSSLSession(self, ctx);
+ t = SSL_SESSION_get_timeout(ctx);
+
+ return LONG2NUM(t);
+}
+
+/*
+ * call-seq:
+ * session.time = time
+ * session.time = integer
+ *
+ * Sets start time of the session. Time resolution is in seconds.
+ *
+ */
+static VALUE ossl_ssl_session_set_time(VALUE self, VALUE time_v)
+{
+ SSL_SESSION *ctx;
+ long t;
+
+ GetSSLSession(self, ctx);
+ if (rb_obj_is_instance_of(time_v, rb_cTime)) {
+ time_v = rb_funcall(time_v, rb_intern("to_i"), 0);
+ }
+ t = NUM2LONG(time_v);
+ SSL_SESSION_set_time(ctx, t);
+ return ossl_ssl_session_get_time(self);
+}
+
+/*
+ * call-seq:
+ * session.timeout = integer
+ *
+ * Sets how long until the session expires in seconds.
+ */
+static VALUE ossl_ssl_session_set_timeout(VALUE self, VALUE time_v)
+{
+ SSL_SESSION *ctx;
+ long t;
+
+ GetSSLSession(self, ctx);
+ t = NUM2LONG(time_v);
+ SSL_SESSION_set_timeout(ctx, t);
+ return ossl_ssl_session_get_timeout(self);
+}
+
+/*
+ * call-seq:
+ * session.id -> String
+ *
+ * Returns the Session ID.
+ */
+static VALUE ossl_ssl_session_get_id(VALUE self)
+{
+ SSL_SESSION *ctx;
+ const unsigned char *p = NULL;
+ unsigned int i = 0;
+
+ GetSSLSession(self, ctx);
+
+ p = SSL_SESSION_get_id(ctx, &i);
+
+ return rb_str_new((const char *) p, i);
+}
+
+/*
+ * call-seq:
+ * session.to_der -> String
+ *
+ * Returns an ASN1 encoded String that contains the Session object.
+ */
+static VALUE ossl_ssl_session_to_der(VALUE self)
+{
+ SSL_SESSION *ctx;
+ unsigned char *p;
+ int len;
+ VALUE str;
+
+ GetSSLSession(self, ctx);
+ len = i2d_SSL_SESSION(ctx, NULL);
+ if (len <= 0) {
+ ossl_raise(eSSLSession, "i2d_SSL_SESSION");
+ }
+
+ str = rb_str_new(0, len);
+ p = (unsigned char *)RSTRING_PTR(str);
+ i2d_SSL_SESSION(ctx, &p);
+ ossl_str_adjust(str, p);
+ return str;
+}
+
+/*
+ * call-seq:
+ * session.to_pem -> String
+ *
+ * Returns a PEM encoded String that contains the Session object.
+ */
+static VALUE ossl_ssl_session_to_pem(VALUE self)
+{
+ SSL_SESSION *ctx;
+ BIO *out;
+
+ GetSSLSession(self, ctx);
+
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eSSLSession, "BIO_s_mem()");
+ }
+
+ if (!PEM_write_bio_SSL_SESSION(out, ctx)) {
+ BIO_free(out);
+ ossl_raise(eSSLSession, "SSL_SESSION_print()");
+ }
+
+
+ return ossl_membio2str(out);
+}
+
+
+/*
+ * call-seq:
+ * session.to_text -> String
+ *
+ * Shows everything in the Session object. This is for diagnostic purposes.
+ */
+static VALUE ossl_ssl_session_to_text(VALUE self)
+{
+ SSL_SESSION *ctx;
+ BIO *out;
+
+ GetSSLSession(self, ctx);
+
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eSSLSession, "BIO_s_mem()");
+ }
+
+ if (!SSL_SESSION_print(out, ctx)) {
+ BIO_free(out);
+ ossl_raise(eSSLSession, "SSL_SESSION_print()");
+ }
+
+ return ossl_membio2str(out);
+}
+
+#endif /* !defined(OPENSSL_NO_SOCK) */
+
+void Init_ossl_ssl_session(void)
+{
+#ifndef OPENSSL_NO_SOCK
+ cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
+ eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
+
+ rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
+ rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
+ rb_define_method(cSSLSession, "initialize_copy", ossl_ssl_session_initialize_copy, 1);
+
+ rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
+
+ rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0);
+ rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
+ rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
+ rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
+ rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
+ rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
+ rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
+ rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
+#endif /* !defined(OPENSSL_NO_SOCK) */
+}
diff --git a/ext/openssl/ossl_ts.c b/ext/openssl/ossl_ts.c
new file mode 100644
index 0000000000..317f7786aa
--- /dev/null
+++ b/ext/openssl/ossl_ts.c
@@ -0,0 +1,1554 @@
+/*
+ *
+ * Copyright (C) 2010 Martin Bosslet <Martin.Bosslet@googlemail.com>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'COPYING'.)
+ */
+#include "ossl.h"
+
+#ifndef OPENSSL_NO_TS
+
+#define NewTSRequest(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_ts_req_type, 0)
+#define SetTSRequest(obj, req) do { \
+ if (!(req)) { \
+ ossl_raise(rb_eRuntimeError, "TS_REQ wasn't initialized."); \
+ } \
+ RTYPEDDATA_DATA(obj) = (req); \
+} while (0)
+#define GetTSRequest(obj, req) do { \
+ TypedData_Get_Struct((obj), TS_REQ, &ossl_ts_req_type, (req)); \
+ if (!(req)) { \
+ ossl_raise(rb_eRuntimeError, "TS_REQ wasn't initialized."); \
+ } \
+} while (0)
+
+#define NewTSResponse(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_ts_resp_type, 0)
+#define SetTSResponse(obj, resp) do { \
+ if (!(resp)) { \
+ ossl_raise(rb_eRuntimeError, "TS_RESP wasn't initialized."); \
+ } \
+ RTYPEDDATA_DATA(obj) = (resp); \
+} while (0)
+#define GetTSResponse(obj, resp) do { \
+ TypedData_Get_Struct((obj), TS_RESP, &ossl_ts_resp_type, (resp)); \
+ if (!(resp)) { \
+ ossl_raise(rb_eRuntimeError, "TS_RESP wasn't initialized."); \
+ } \
+} while (0)
+
+#define NewTSTokenInfo(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_ts_token_info_type, 0)
+#define SetTSTokenInfo(obj, info) do { \
+ if (!(info)) { \
+ ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \
+ } \
+ RTYPEDDATA_DATA(obj) = (info); \
+} while (0)
+#define GetTSTokenInfo(obj, info) do { \
+ TypedData_Get_Struct((obj), TS_TST_INFO, &ossl_ts_token_info_type, (info)); \
+ if (!(info)) { \
+ ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \
+ } \
+} while (0)
+
+#define ossl_tsfac_get_default_policy_id(o) rb_attr_get((o),rb_intern("@default_policy_id"))
+#define ossl_tsfac_get_serial_number(o) rb_attr_get((o),rb_intern("@serial_number"))
+#define ossl_tsfac_get_gen_time(o) rb_attr_get((o),rb_intern("@gen_time"))
+#define ossl_tsfac_get_additional_certs(o) rb_attr_get((o),rb_intern("@additional_certs"))
+#define ossl_tsfac_get_allowed_digests(o) rb_attr_get((o),rb_intern("@allowed_digests"))
+
+static VALUE mTimestamp;
+static VALUE eTimestampError;
+static VALUE cTimestampRequest;
+static VALUE cTimestampResponse;
+static VALUE cTimestampTokenInfo;
+static VALUE cTimestampFactory;
+static VALUE sBAD_ALG, sBAD_REQUEST, sBAD_DATA_FORMAT, sTIME_NOT_AVAILABLE;
+static VALUE sUNACCEPTED_POLICY, sUNACCEPTED_EXTENSION, sADD_INFO_NOT_AVAILABLE;
+static VALUE sSYSTEM_FAILURE;
+
+static void
+ossl_ts_req_free(void *ptr)
+{
+ TS_REQ_free(ptr);
+}
+
+static const rb_data_type_t ossl_ts_req_type = {
+ "OpenSSL/Timestamp/Request",
+ {
+ 0, ossl_ts_req_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static void
+ossl_ts_resp_free(void *ptr)
+{
+ TS_RESP_free(ptr);
+}
+
+static const rb_data_type_t ossl_ts_resp_type = {
+ "OpenSSL/Timestamp/Response",
+ {
+ 0, ossl_ts_resp_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static void
+ossl_ts_token_info_free(void *ptr)
+{
+ TS_TST_INFO_free(ptr);
+}
+
+static const rb_data_type_t ossl_ts_token_info_type = {
+ "OpenSSL/Timestamp/TokenInfo",
+ {
+ 0, ossl_ts_token_info_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static VALUE
+asn1_to_der(void *template, int (*i2d)(void *template, unsigned char **pp))
+{
+ VALUE str;
+ int len;
+ unsigned char *p;
+
+ if((len = i2d(template, NULL)) <= 0)
+ ossl_raise(eTimestampError, "Error when encoding to DER");
+ str = rb_str_new(0, len);
+ p = (unsigned char *)RSTRING_PTR(str);
+ if(i2d(template, &p) <= 0)
+ ossl_raise(eTimestampError, "Error when encoding to DER");
+ rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str));
+
+ return str;
+}
+
+static VALUE
+obj_to_asn1obj_i(VALUE obj)
+{
+ return (VALUE)ossl_to_asn1obj(obj);
+}
+
+static VALUE
+ossl_ts_req_alloc(VALUE klass)
+{
+ TS_REQ *req;
+ VALUE obj;
+
+ obj = NewTSRequest(klass);
+ if (!(req = TS_REQ_new()))
+ ossl_raise(eTimestampError, NULL);
+ SetTSRequest(obj, req);
+
+ /* Defaults */
+ TS_REQ_set_version(req, 1);
+ TS_REQ_set_cert_req(req, 1);
+
+ return obj;
+}
+
+/*
+ * When creating a Request with the +File+ or +string+ parameter, the
+ * corresponding +File+ or +string+ must be DER-encoded.
+ *
+ * call-seq:
+ * OpenSSL::Timestamp::Request.new(file) -> request
+ * OpenSSL::Timestamp::Request.new(string) -> request
+ * OpenSSL::Timestamp::Request.new -> empty request
+ */
+static VALUE
+ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self)
+{
+ TS_REQ *req, *req_orig = DATA_PTR(self);
+ BIO *in;
+ VALUE arg;
+
+ if(rb_scan_args(argc, argv, "01", &arg) == 0) {
+ return self;
+ }
+
+ arg = ossl_to_der_if_possible(arg);
+ in = ossl_obj2bio(&arg);
+ req = d2i_TS_REQ_bio(in, NULL);
+ BIO_free(in);
+ if (!req) {
+ ossl_raise(eTimestampError,
+ "Error when decoding the timestamp request");
+ }
+ TS_REQ_free(req_orig);
+ RTYPEDDATA_DATA(self) = req;
+
+ return self;
+}
+
+/*
+ * Returns the 'short name' of the object identifier that represents the
+ * algorithm that was used to create the message imprint digest.
+ *
+ * call-seq:
+ * request.algorithm -> string
+ */
+static VALUE
+ossl_ts_req_get_algorithm(VALUE self)
+{
+ TS_REQ *req;
+ TS_MSG_IMPRINT *mi;
+ X509_ALGOR *algor;
+ const ASN1_OBJECT *obj;
+
+ GetTSRequest(self, req);
+ mi = TS_REQ_get_msg_imprint(req);
+ algor = TS_MSG_IMPRINT_get_algo(mi);
+ X509_ALGOR_get0(&obj, NULL, NULL, algor);
+ return ossl_asn1obj_to_string(obj);
+}
+
+/*
+ * Allows to set the object identifier or the 'short name' of the
+ * algorithm that was used to create the message imprint digest.
+ *
+ * ===Example:
+ * request.algorithm = "SHA1"
+ *
+ * call-seq:
+ * request.algorithm = "string" -> string
+ */
+static VALUE
+ossl_ts_req_set_algorithm(VALUE self, VALUE algo)
+{
+ TS_REQ *req;
+ TS_MSG_IMPRINT *mi;
+ ASN1_OBJECT *obj;
+ X509_ALGOR *algor;
+
+ GetTSRequest(self, req);
+ obj = ossl_to_asn1obj(algo);
+ mi = TS_REQ_get_msg_imprint(req);
+ algor = TS_MSG_IMPRINT_get_algo(mi);
+ if (!X509_ALGOR_set0(algor, obj, V_ASN1_NULL, NULL)) {
+ ASN1_OBJECT_free(obj);
+ ossl_raise(eTimestampError, "X509_ALGOR_set0");
+ }
+
+ return algo;
+}
+
+/*
+ * Returns the message imprint (digest) of the data to be timestamped.
+ *
+ * call-seq:
+ * request.message_imprint -> string or nil
+ */
+static VALUE
+ossl_ts_req_get_msg_imprint(VALUE self)
+{
+ TS_REQ *req;
+ TS_MSG_IMPRINT *mi;
+ ASN1_OCTET_STRING *hashed_msg;
+ VALUE ret;
+
+ GetTSRequest(self, req);
+ mi = TS_REQ_get_msg_imprint(req);
+ hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
+
+ ret = asn1str_to_str(hashed_msg);
+
+ return ret;
+}
+
+/*
+ * Set the message imprint digest.
+ *
+ * call-seq:
+ * request.message_imprint = "string" -> string
+ */
+static VALUE
+ossl_ts_req_set_msg_imprint(VALUE self, VALUE hash)
+{
+ TS_REQ *req;
+ TS_MSG_IMPRINT *mi;
+ StringValue(hash);
+
+ GetTSRequest(self, req);
+ mi = TS_REQ_get_msg_imprint(req);
+ if (!TS_MSG_IMPRINT_set_msg(mi, (unsigned char *)RSTRING_PTR(hash), RSTRING_LENINT(hash)))
+ ossl_raise(eTimestampError, "TS_MSG_IMPRINT_set_msg");
+
+ return hash;
+}
+
+/*
+ * Returns the version of this request. +1+ is the default value.
+ *
+ * call-seq:
+ * request.version -> Integer
+ */
+static VALUE
+ossl_ts_req_get_version(VALUE self)
+{
+ TS_REQ *req;
+
+ GetTSRequest(self, req);
+ return LONG2NUM(TS_REQ_get_version(req));
+}
+
+/*
+ * Sets the version number for this Request. This should be +1+ for compliant
+ * servers.
+ *
+ * call-seq:
+ * request.version = number -> Integer
+ */
+static VALUE
+ossl_ts_req_set_version(VALUE self, VALUE version)
+{
+ TS_REQ *req;
+ long ver;
+
+ if ((ver = NUM2LONG(version)) < 0)
+ ossl_raise(eTimestampError, "version must be >= 0!");
+ GetTSRequest(self, req);
+ if (!TS_REQ_set_version(req, ver))
+ ossl_raise(eTimestampError, "TS_REQ_set_version");
+
+ return version;
+}
+
+/*
+ * Returns the 'short name' of the object identifier that represents the
+ * timestamp policy under which the server shall create the timestamp.
+ *
+ * call-seq:
+ * request.policy_id -> string or nil
+ */
+static VALUE
+ossl_ts_req_get_policy_id(VALUE self)
+{
+ TS_REQ *req;
+
+ GetTSRequest(self, req);
+ if (!TS_REQ_get_policy_id(req))
+ return Qnil;
+ return ossl_asn1obj_to_string(TS_REQ_get_policy_id(req));
+}
+
+/*
+ * Allows to set the object identifier that represents the
+ * timestamp policy under which the server shall create the timestamp. This
+ * may be left +nil+, implying that the timestamp server will issue the
+ * timestamp using some default policy.
+ *
+ * ===Example:
+ * request.policy_id = "1.2.3.4.5"
+ *
+ * call-seq:
+ * request.policy_id = "string" -> string
+ */
+static VALUE
+ossl_ts_req_set_policy_id(VALUE self, VALUE oid)
+{
+ TS_REQ *req;
+ ASN1_OBJECT *obj;
+ int ok;
+
+ GetTSRequest(self, req);
+ obj = ossl_to_asn1obj(oid);
+ ok = TS_REQ_set_policy_id(req, obj);
+ ASN1_OBJECT_free(obj);
+ if (!ok)
+ ossl_raise(eTimestampError, "TS_REQ_set_policy_id");
+
+ return oid;
+}
+
+/*
+ * Returns the nonce (number used once) that the server shall include in its
+ * response.
+ *
+ * call-seq:
+ * request.nonce -> BN or nil
+ */
+static VALUE
+ossl_ts_req_get_nonce(VALUE self)
+{
+ TS_REQ *req;
+ const ASN1_INTEGER * nonce;
+
+ GetTSRequest(self, req);
+ if (!(nonce = TS_REQ_get_nonce(req)))
+ return Qnil;
+ return asn1integer_to_num(nonce);
+}
+
+/*
+ * Sets the nonce (number used once) that the server shall include in its
+ * response. If the nonce is set, the server must return the same nonce value in
+ * a valid Response.
+ *
+ * call-seq:
+ * request.nonce = number -> BN
+ */
+static VALUE
+ossl_ts_req_set_nonce(VALUE self, VALUE num)
+{
+ TS_REQ *req;
+ ASN1_INTEGER *nonce;
+ int ok;
+
+ GetTSRequest(self, req);
+ nonce = num_to_asn1integer(num, NULL);
+ ok = TS_REQ_set_nonce(req, nonce);
+ ASN1_INTEGER_free(nonce);
+ if (!ok)
+ ossl_raise(eTimestampError, NULL);
+ return num;
+}
+
+/*
+ * Indicates whether the response shall contain the timestamp authority's
+ * certificate or not.
+ *
+ * call-seq:
+ * request.cert_requested? -> true or false
+ */
+static VALUE
+ossl_ts_req_get_cert_requested(VALUE self)
+{
+ TS_REQ *req;
+
+ GetTSRequest(self, req);
+ return TS_REQ_get_cert_req(req) ? Qtrue: Qfalse;
+}
+
+/*
+ * Specify whether the response shall contain the timestamp authority's
+ * certificate or not. The default value is +true+.
+ *
+ * call-seq:
+ * request.cert_requested = boolean -> true or false
+ */
+static VALUE
+ossl_ts_req_set_cert_requested(VALUE self, VALUE requested)
+{
+ TS_REQ *req;
+
+ GetTSRequest(self, req);
+ TS_REQ_set_cert_req(req, RTEST(requested));
+
+ return requested;
+}
+
+/*
+ * DER-encodes this Request.
+ *
+ * call-seq:
+ * request.to_der -> DER-encoded string
+ */
+static VALUE
+ossl_ts_req_to_der(VALUE self)
+{
+ TS_REQ *req;
+ TS_MSG_IMPRINT *mi;
+ X509_ALGOR *algo;
+ const ASN1_OBJECT *obj;
+ ASN1_OCTET_STRING *hashed_msg;
+
+ GetTSRequest(self, req);
+ mi = TS_REQ_get_msg_imprint(req);
+
+ algo = TS_MSG_IMPRINT_get_algo(mi);
+ X509_ALGOR_get0(&obj, NULL, NULL, algo);
+ if (OBJ_obj2nid(obj) == NID_undef)
+ ossl_raise(eTimestampError, "Message imprint missing algorithm");
+
+ hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
+ if (!ASN1_STRING_length(hashed_msg))
+ ossl_raise(eTimestampError, "Message imprint missing hashed message");
+
+ return asn1_to_der((void *)req, (int (*)(void *, unsigned char **))i2d_TS_REQ);
+}
+
+static VALUE
+ossl_ts_req_to_text(VALUE self)
+{
+ TS_REQ *req;
+ BIO *out;
+
+ GetTSRequest(self, req);
+
+ out = BIO_new(BIO_s_mem());
+ if (!out) ossl_raise(eTimestampError, NULL);
+
+ if (!TS_REQ_print_bio(out, req)) {
+ BIO_free(out);
+ ossl_raise(eTimestampError, NULL);
+ }
+
+ return ossl_membio2str(out);
+}
+
+static VALUE
+ossl_ts_resp_alloc(VALUE klass)
+{
+ TS_RESP *resp;
+ VALUE obj;
+
+ obj = NewTSResponse(klass);
+ if (!(resp = TS_RESP_new()))
+ ossl_raise(eTimestampError, NULL);
+ SetTSResponse(obj, resp);
+
+ return obj;
+}
+
+/*
+ * Creates a Response from a +File+ or +string+ parameter, the
+ * corresponding +File+ or +string+ must be DER-encoded. Please note
+ * that Response is an immutable read-only class. If you'd like to create
+ * timestamps please refer to Factory instead.
+ *
+ * call-seq:
+ * OpenSSL::Timestamp::Response.new(file) -> response
+ * OpenSSL::Timestamp::Response.new(string) -> response
+ */
+static VALUE
+ossl_ts_resp_initialize(VALUE self, VALUE der)
+{
+ TS_RESP *resp, *resp_orig = DATA_PTR(self);
+ BIO *in;
+
+ der = ossl_to_der_if_possible(der);
+ in = ossl_obj2bio(&der);
+ resp = d2i_TS_RESP_bio(in, NULL);
+ BIO_free(in);
+ if (!resp) {
+ ossl_raise(eTimestampError,
+ "Error when decoding the timestamp response");
+ }
+ TS_RESP_free(resp_orig);
+ RTYPEDDATA_DATA(self) = resp;
+
+ return self;
+}
+
+/*
+ * Returns one of GRANTED, GRANTED_WITH_MODS, REJECTION, WAITING,
+ * REVOCATION_WARNING or REVOCATION_NOTIFICATION. A timestamp token has
+ * been created only in case +status+ is equal to GRANTED or GRANTED_WITH_MODS.
+ *
+ * call-seq:
+ * response.status -> BN (never nil)
+ */
+static VALUE
+ossl_ts_resp_get_status(VALUE self)
+{
+ TS_RESP *resp;
+ TS_STATUS_INFO *si;
+ const ASN1_INTEGER *st;
+
+ GetTSResponse(self, resp);
+ si = TS_RESP_get_status_info(resp);
+ st = TS_STATUS_INFO_get0_status(si);
+
+ return asn1integer_to_num(st);
+}
+
+/*
+ * In cases no timestamp token has been created, this field contains further
+ * info about the reason why response creation failed. The method returns either
+ * nil (the request was successful and a timestamp token was created) or one of
+ * the following:
+ * * :BAD_ALG - Indicates that the timestamp server rejects the message
+ * imprint algorithm used in the Request
+ * * :BAD_REQUEST - Indicates that the timestamp server was not able to process
+ * the Request properly
+ * * :BAD_DATA_FORMAT - Indicates that the timestamp server was not able to
+ * parse certain data in the Request
+ * * :TIME_NOT_AVAILABLE - Indicates that the server could not access its time
+ * source
+ * * :UNACCEPTED_POLICY - Indicates that the requested policy identifier is not
+ * recognized or supported by the timestamp server
+ * * :UNACCEPTED_EXTENSIION - Indicates that an extension in the Request is
+ * not supported by the timestamp server
+ * * :ADD_INFO_NOT_AVAILABLE -Indicates that additional information requested
+ * is either not understood or currently not available
+ * * :SYSTEM_FAILURE - Timestamp creation failed due to an internal error that
+ * occurred on the timestamp server
+ *
+ * call-seq:
+ * response.failure_info -> nil or symbol
+ */
+static VALUE
+ossl_ts_resp_get_failure_info(VALUE self)
+{
+ TS_RESP *resp;
+ TS_STATUS_INFO *si;
+ const ASN1_BIT_STRING *fi;
+
+ GetTSResponse(self, resp);
+ si = TS_RESP_get_status_info(resp);
+ fi = TS_STATUS_INFO_get0_failure_info(si);
+ if (!fi)
+ return Qnil;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_ALG))
+ return sBAD_ALG;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_REQUEST))
+ return sBAD_REQUEST;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_DATA_FORMAT))
+ return sBAD_DATA_FORMAT;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_TIME_NOT_AVAILABLE))
+ return sTIME_NOT_AVAILABLE;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_POLICY))
+ return sUNACCEPTED_POLICY;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_EXTENSION))
+ return sUNACCEPTED_EXTENSION;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_ADD_INFO_NOT_AVAILABLE))
+ return sADD_INFO_NOT_AVAILABLE;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_SYSTEM_FAILURE))
+ return sSYSTEM_FAILURE;
+
+ ossl_raise(eTimestampError, "Unrecognized failure info.");
+}
+
+/*
+ * In cases of failure this field may contain an array of strings further
+ * describing the origin of the failure.
+ *
+ * call-seq:
+ * response.status_text -> Array of strings or nil
+ */
+static VALUE
+ossl_ts_resp_get_status_text(VALUE self)
+{
+ TS_RESP *resp;
+ TS_STATUS_INFO *si;
+ const STACK_OF(ASN1_UTF8STRING) *text;
+ ASN1_UTF8STRING *current;
+ int i;
+ VALUE ret = rb_ary_new();
+
+ GetTSResponse(self, resp);
+ si = TS_RESP_get_status_info(resp);
+ if ((text = TS_STATUS_INFO_get0_text(si))) {
+ for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
+ current = sk_ASN1_UTF8STRING_value(text, i);
+ rb_ary_push(ret, asn1str_to_str(current));
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * If a timestamp token is present, this returns it in the form of a
+ * OpenSSL::PKCS7.
+ *
+ * call-seq:
+ * response.token -> nil or OpenSSL::PKCS7
+ */
+static VALUE
+ossl_ts_resp_get_token(VALUE self)
+{
+ TS_RESP *resp;
+ PKCS7 *p7;
+
+ GetTSResponse(self, resp);
+ if (!(p7 = TS_RESP_get_token(resp)))
+ return Qnil;
+ return ossl_pkcs7_new(p7);
+}
+
+/*
+ * Get the response's token info if present.
+ *
+ * call-seq:
+ * response.token_info -> nil or OpenSSL::Timestamp::TokenInfo
+ */
+static VALUE
+ossl_ts_resp_get_token_info(VALUE self)
+{
+ TS_RESP *resp;
+ TS_TST_INFO *info, *copy;
+ VALUE obj;
+
+ GetTSResponse(self, resp);
+ if (!(info = TS_RESP_get_tst_info(resp)))
+ return Qnil;
+
+ obj = NewTSTokenInfo(cTimestampTokenInfo);
+
+ if (!(copy = TS_TST_INFO_dup(info)))
+ ossl_raise(eTimestampError, NULL);
+
+ SetTSTokenInfo(obj, copy);
+
+ return obj;
+}
+
+/*
+ * If the Request specified to request the TSA certificate
+ * (Request#cert_requested = true), then this field contains the
+ * certificate of the timestamp authority.
+ *
+ * call-seq:
+ * response.tsa_certificate -> OpenSSL::X509::Certificate or nil
+ */
+static VALUE
+ossl_ts_resp_get_tsa_certificate(VALUE self)
+{
+ TS_RESP *resp;
+ PKCS7 *p7;
+ PKCS7_SIGNER_INFO *ts_info;
+ const X509 *cert;
+
+ GetTSResponse(self, resp);
+ if (!(p7 = TS_RESP_get_token(resp)))
+ return Qnil;
+ ts_info = sk_PKCS7_SIGNER_INFO_value(p7->d.sign->signer_info, 0);
+ cert = PKCS7_cert_from_signer_info(p7, ts_info);
+ if (!cert)
+ return Qnil;
+ return ossl_x509_new(cert);
+}
+
+/*
+ * Returns the Response in DER-encoded form.
+ *
+ * call-seq:
+ * response.to_der -> string
+ */
+static VALUE
+ossl_ts_resp_to_der(VALUE self)
+{
+ TS_RESP *resp;
+
+ GetTSResponse(self, resp);
+ return asn1_to_der((void *)resp, (int (*)(void *, unsigned char **))i2d_TS_RESP);
+}
+
+static VALUE
+ossl_ts_resp_to_text(VALUE self)
+{
+ TS_RESP *resp;
+ BIO *out;
+
+ GetTSResponse(self, resp);
+
+ out = BIO_new(BIO_s_mem());
+ if (!out) ossl_raise(eTimestampError, NULL);
+
+ if (!TS_RESP_print_bio(out, resp)) {
+ BIO_free(out);
+ ossl_raise(eTimestampError, NULL);
+ }
+
+ return ossl_membio2str(out);
+}
+
+/*
+ * Verifies a timestamp token by checking the signature, validating the
+ * certificate chain implied by tsa_certificate and by checking conformance to
+ * a given Request. Mandatory parameters are the Request associated to this
+ * Response, and an OpenSSL::X509::Store of trusted roots.
+ *
+ * Intermediate certificates can optionally be supplied for creating the
+ * certificate chain. These intermediate certificates must all be
+ * instances of OpenSSL::X509::Certificate.
+ *
+ * If validation fails, several kinds of exceptions can be raised:
+ * * TypeError if types don't fit
+ * * TimestampError if something is wrong with the timestamp token itself, if
+ * it is not conformant to the Request, or if validation of the timestamp
+ * certificate chain fails.
+ *
+ * call-seq:
+ * response.verify(Request, root_store) -> Response
+ * response.verify(Request, root_store, [intermediate_cert]) -> Response
+ */
+static VALUE
+ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self)
+{
+ VALUE ts_req, store, intermediates;
+ TS_RESP *resp;
+ TS_REQ *req;
+ X509_STORE *x509st;
+ TS_VERIFY_CTX *ctx;
+ STACK_OF(X509) *x509inter = NULL;
+ PKCS7* p7;
+ X509 *cert;
+ int status, i, ok;
+
+ rb_scan_args(argc, argv, "21", &ts_req, &store, &intermediates);
+
+ GetTSResponse(self, resp);
+ GetTSRequest(ts_req, req);
+ x509st = GetX509StorePtr(store);
+
+ if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(req, NULL))) {
+ ossl_raise(eTimestampError, "Error when creating the verification context.");
+ }
+
+ if (!NIL_P(intermediates)) {
+ x509inter = ossl_protect_x509_ary2sk(intermediates, &status);
+ if (status) {
+ TS_VERIFY_CTX_free(ctx);
+ rb_jump_tag(status);
+ }
+ } else if (!(x509inter = sk_X509_new_null())) {
+ TS_VERIFY_CTX_free(ctx);
+ ossl_raise(eTimestampError, "sk_X509_new_null");
+ }
+
+ if (!(p7 = TS_RESP_get_token(resp))) {
+ TS_VERIFY_CTX_free(ctx);
+ sk_X509_pop_free(x509inter, X509_free);
+ ossl_raise(eTimestampError, "TS_RESP_get_token");
+ }
+ for (i=0; i < sk_X509_num(p7->d.sign->cert); i++) {
+ cert = sk_X509_value(p7->d.sign->cert, i);
+ if (!sk_X509_push(x509inter, cert)) {
+ sk_X509_pop_free(x509inter, X509_free);
+ TS_VERIFY_CTX_free(ctx);
+ ossl_raise(eTimestampError, "sk_X509_push");
+ }
+ X509_up_ref(cert);
+ }
+
+ if (!X509_STORE_up_ref(x509st)) {
+ sk_X509_pop_free(x509inter, X509_free);
+ TS_VERIFY_CTX_free(ctx);
+ ossl_raise(eTimestampError, "X509_STORE_up_ref");
+ }
+
+#ifdef HAVE_TS_VERIFY_CTX_SET0_CERTS
+ TS_VERIFY_CTX_set0_certs(ctx, x509inter);
+ TS_VERIFY_CTX_set0_store(ctx, x509st);
+#else
+# if OSSL_OPENSSL_PREREQ(3, 0, 0) || OSSL_IS_LIBRESSL
+ TS_VERIFY_CTX_set_certs(ctx, x509inter);
+# else
+ TS_VERIFY_CTS_set_certs(ctx, x509inter);
+# endif
+ TS_VERIFY_CTX_set_store(ctx, x509st);
+#endif
+ TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE);
+
+ ok = TS_RESP_verify_response(ctx, resp);
+ TS_VERIFY_CTX_free(ctx);
+
+ if (!ok)
+ ossl_raise(eTimestampError, "TS_RESP_verify_response");
+
+ return self;
+}
+
+static VALUE
+ossl_ts_token_info_alloc(VALUE klass)
+{
+ TS_TST_INFO *info;
+ VALUE obj;
+
+ obj = NewTSTokenInfo(klass);
+ if (!(info = TS_TST_INFO_new()))
+ ossl_raise(eTimestampError, NULL);
+ SetTSTokenInfo(obj, info);
+
+ return obj;
+}
+
+/*
+ * Creates a TokenInfo from a +File+ or +string+ parameter, the
+ * corresponding +File+ or +string+ must be DER-encoded. Please note
+ * that TokenInfo is an immutable read-only class. If you'd like to create
+ * timestamps please refer to Factory instead.
+ *
+ * call-seq:
+ * OpenSSL::Timestamp::TokenInfo.new(file) -> token-info
+ * OpenSSL::Timestamp::TokenInfo.new(string) -> token-info
+ */
+static VALUE
+ossl_ts_token_info_initialize(VALUE self, VALUE der)
+{
+ TS_TST_INFO *info, *info_orig = DATA_PTR(self);
+ BIO *in;
+
+ der = ossl_to_der_if_possible(der);
+ in = ossl_obj2bio(&der);
+ info = d2i_TS_TST_INFO_bio(in, NULL);
+ BIO_free(in);
+ if (!info) {
+ ossl_raise(eTimestampError,
+ "Error when decoding the timestamp token info");
+ }
+ TS_TST_INFO_free(info_orig);
+ RTYPEDDATA_DATA(self) = info;
+
+ return self;
+}
+
+/*
+ * Returns the version number of the token info. With compliant servers,
+ * this value should be +1+ if present. If status is GRANTED or
+ * GRANTED_WITH_MODS.
+ *
+ * call-seq:
+ * token_info.version -> Integer or nil
+ */
+static VALUE
+ossl_ts_token_info_get_version(VALUE self)
+{
+ TS_TST_INFO *info;
+
+ GetTSTokenInfo(self, info);
+ return LONG2NUM(TS_TST_INFO_get_version(info));
+}
+
+/*
+ * Returns the timestamp policy object identifier of the policy this timestamp
+ * was created under. If status is GRANTED or GRANTED_WITH_MODS, this is never
+ * +nil+.
+ *
+ * ===Example:
+ * id = token_info.policy_id
+ * puts id -> "1.2.3.4.5"
+ *
+ * call-seq:
+ * token_info.policy_id -> string or nil
+ */
+static VALUE
+ossl_ts_token_info_get_policy_id(VALUE self)
+{
+ TS_TST_INFO *info;
+
+ GetTSTokenInfo(self, info);
+ return ossl_asn1obj_to_string(TS_TST_INFO_get_policy_id(info));
+}
+
+/*
+ * Returns the 'short name' of the object identifier representing the algorithm
+ * that was used to derive the message imprint digest. For valid timestamps,
+ * this is the same value that was already given in the Request. If status is
+ * GRANTED or GRANTED_WITH_MODS, this is never +nil+.
+ *
+ * ===Example:
+ * algo = token_info.algorithm
+ * puts algo -> "SHA1"
+ *
+ * call-seq:
+ * token_info.algorithm -> string or nil
+ */
+static VALUE
+ossl_ts_token_info_get_algorithm(VALUE self)
+{
+ TS_TST_INFO *info;
+ TS_MSG_IMPRINT *mi;
+ X509_ALGOR *algo;
+ const ASN1_OBJECT *obj;
+
+ GetTSTokenInfo(self, info);
+ mi = TS_TST_INFO_get_msg_imprint(info);
+ algo = TS_MSG_IMPRINT_get_algo(mi);
+ X509_ALGOR_get0(&obj, NULL, NULL, algo);
+ return ossl_asn1obj_to_string(obj);
+}
+
+/*
+ * Returns the message imprint digest. For valid timestamps,
+ * this is the same value that was already given in the Request.
+ * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+.
+ *
+ * ===Example:
+ * mi = token_info.msg_imprint
+ * puts mi -> "DEADBEEF"
+ *
+ * call-seq:
+ * token_info.msg_imprint -> string.
+ */
+static VALUE
+ossl_ts_token_info_get_msg_imprint(VALUE self)
+{
+ TS_TST_INFO *info;
+ TS_MSG_IMPRINT *mi;
+ ASN1_OCTET_STRING *hashed_msg;
+ VALUE ret;
+
+ GetTSTokenInfo(self, info);
+ mi = TS_TST_INFO_get_msg_imprint(info);
+ hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
+ ret = asn1str_to_str(hashed_msg);
+
+ return ret;
+}
+
+/*
+ * Returns serial number of the timestamp token. This value shall never be the
+ * same for two timestamp tokens issued by a dedicated timestamp authority.
+ * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+.
+ *
+ * call-seq:
+ * token_info.serial_number -> BN or nil
+ */
+static VALUE
+ossl_ts_token_info_get_serial_number(VALUE self)
+{
+ TS_TST_INFO *info;
+
+ GetTSTokenInfo(self, info);
+ return asn1integer_to_num(TS_TST_INFO_get_serial(info));
+}
+
+/*
+ * Returns time when this timestamp token was created. If status is GRANTED or
+ * GRANTED_WITH_MODS, this is never +nil+.
+ *
+ * call-seq:
+ * token_info.gen_time -> Time
+ */
+static VALUE
+ossl_ts_token_info_get_gen_time(VALUE self)
+{
+ TS_TST_INFO *info;
+
+ GetTSTokenInfo(self, info);
+ return asn1time_to_time(TS_TST_INFO_get_time(info));
+}
+
+/*
+ * If the ordering field is missing, or if the ordering field is present
+ * and set to false, then the genTime field only indicates the time at
+ * which the time-stamp token has been created by the TSA. In such a
+ * case, the ordering of time-stamp tokens issued by the same TSA or
+ * different TSAs is only possible when the difference between the
+ * genTime of the first time-stamp token and the genTime of the second
+ * time-stamp token is greater than the sum of the accuracies of the
+ * genTime for each time-stamp token.
+ *
+ * If the ordering field is present and set to true, every time-stamp
+ * token from the same TSA can always be ordered based on the genTime
+ * field, regardless of the genTime accuracy.
+ *
+ * call-seq:
+ * token_info.ordering -> true, falses or nil
+ */
+static VALUE
+ossl_ts_token_info_get_ordering(VALUE self)
+{
+ TS_TST_INFO *info;
+
+ GetTSTokenInfo(self, info);
+ return TS_TST_INFO_get_ordering(info) ? Qtrue : Qfalse;
+}
+
+/*
+ * If the timestamp token is valid then this field contains the same nonce that
+ * was passed to the timestamp server in the initial Request.
+ *
+ * call-seq:
+ * token_info.nonce -> BN or nil
+ */
+static VALUE
+ossl_ts_token_info_get_nonce(VALUE self)
+{
+ TS_TST_INFO *info;
+ const ASN1_INTEGER *nonce;
+
+ GetTSTokenInfo(self, info);
+ if (!(nonce = TS_TST_INFO_get_nonce(info)))
+ return Qnil;
+
+ return asn1integer_to_num(nonce);
+}
+
+/*
+ * Returns the TokenInfo in DER-encoded form.
+ *
+ * call-seq:
+ * token_info.to_der -> string
+ */
+static VALUE
+ossl_ts_token_info_to_der(VALUE self)
+{
+ TS_TST_INFO *info;
+
+ GetTSTokenInfo(self, info);
+ return asn1_to_der((void *)info, (int (*)(void *, unsigned char **))i2d_TS_TST_INFO);
+}
+
+static VALUE
+ossl_ts_token_info_to_text(VALUE self)
+{
+ TS_TST_INFO *info;
+ BIO *out;
+
+ GetTSTokenInfo(self, info);
+
+ out = BIO_new(BIO_s_mem());
+ if (!out) ossl_raise(eTimestampError, NULL);
+
+ if (!TS_TST_INFO_print_bio(out, info)) {
+ BIO_free(out);
+ ossl_raise(eTimestampError, NULL);
+ }
+
+ return ossl_membio2str(out);
+}
+
+static ASN1_INTEGER *
+ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data)
+{
+ ASN1_INTEGER **snptr = (ASN1_INTEGER **)data;
+ ASN1_INTEGER *sn = *snptr;
+ *snptr = NULL;
+ return sn;
+}
+
+static int
+#if !defined(LIBRESSL_VERSION_NUMBER)
+ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec)
+#else
+ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, time_t *sec, long *usec)
+#endif
+{
+ *sec = *((long *)data);
+ *usec = 0;
+ return 1;
+}
+
+static VALUE
+ossl_evp_md_fetch_i(VALUE args_)
+{
+ VALUE *args = (VALUE *)args_, md_holder;
+ const EVP_MD *md;
+
+ md = ossl_evp_md_fetch(args[1], &md_holder);
+ rb_ary_push(args[0], md_holder);
+ return (VALUE)md;
+}
+
+static VALUE
+ossl_obj2bio_i(VALUE arg)
+{
+ return (VALUE)ossl_obj2bio((VALUE *)arg);
+}
+
+/*
+ * Creates a Response with the help of an OpenSSL::PKey, an
+ * OpenSSL::X509::Certificate and a Request.
+ *
+ * Mandatory parameters for timestamp creation that need to be set in the
+ * Request:
+ *
+ * * Request#algorithm
+ * * Request#message_imprint
+ *
+ * Mandatory parameters that need to be set in the Factory:
+ * * Factory#serial_number
+ * * Factory#gen_time
+ * * Factory#allowed_digests
+ *
+ * In addition one of either Request#policy_id or Factory#default_policy_id
+ * must be set.
+ *
+ * Raises a TimestampError if creation fails, though successfully created error
+ * responses may be returned.
+ *
+ * call-seq:
+ * factory.create_timestamp(key, certificate, request) -> Response
+ */
+static VALUE
+ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
+{
+ VALUE serial_number, def_policy_id, gen_time, additional_certs,
+ allowed_digests, allowed_digests_tmp = Qnil;
+ VALUE str;
+ STACK_OF(X509) *inter_certs;
+ VALUE tsresp, ret = Qnil;
+ EVP_PKEY *sign_key;
+ X509 *tsa_cert;
+ TS_REQ *req;
+ TS_RESP *response = NULL;
+ TS_RESP_CTX *ctx = NULL;
+ BIO *req_bio;
+ ASN1_INTEGER *asn1_serial = NULL;
+ ASN1_OBJECT *def_policy_id_obj = NULL;
+ long lgen_time;
+ const char * err_msg = NULL;
+ int status = 0;
+
+ tsresp = NewTSResponse(cTimestampResponse);
+ tsa_cert = GetX509CertPtr(certificate);
+ sign_key = GetPrivPKeyPtr(key);
+ GetTSRequest(request, req);
+
+ gen_time = ossl_tsfac_get_gen_time(self);
+ if (!rb_obj_is_instance_of(gen_time, rb_cTime)) {
+ err_msg = "@gen_time must be a Time.";
+ goto end;
+ }
+ lgen_time = NUM2LONG(rb_funcall(gen_time, rb_intern("to_i"), 0));
+
+ serial_number = ossl_tsfac_get_serial_number(self);
+ if (NIL_P(serial_number)) {
+ err_msg = "@serial_number must be set.";
+ goto end;
+ }
+ asn1_serial = num_to_asn1integer(serial_number, NULL);
+
+ def_policy_id = ossl_tsfac_get_default_policy_id(self);
+ if (NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
+ err_msg = "No policy id in the request and no default policy set";
+ goto end;
+ }
+ if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
+ def_policy_id_obj = (ASN1_OBJECT*)rb_protect(obj_to_asn1obj_i, (VALUE)def_policy_id, &status);
+ if (status)
+ goto end;
+ }
+
+ if (!(ctx = TS_RESP_CTX_new())) {
+ err_msg = "Memory allocation failed.";
+ goto end;
+ }
+
+ TS_RESP_CTX_set_serial_cb(ctx, ossl_tsfac_serial_cb, &asn1_serial);
+ if (!TS_RESP_CTX_set_signer_cert(ctx, tsa_cert)) {
+ err_msg = "Certificate does not contain the timestamping extension";
+ goto end;
+ }
+
+ additional_certs = ossl_tsfac_get_additional_certs(self);
+ if (rb_obj_is_kind_of(additional_certs, rb_cArray)) {
+ inter_certs = ossl_protect_x509_ary2sk(additional_certs, &status);
+ if (status)
+ goto end;
+
+ /* this dups the sk_X509 and ups each cert's ref count */
+ TS_RESP_CTX_set_certs(ctx, inter_certs);
+ sk_X509_pop_free(inter_certs, X509_free);
+ }
+
+ TS_RESP_CTX_set_signer_key(ctx, sign_key);
+ if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req))
+ TS_RESP_CTX_set_def_policy(ctx, def_policy_id_obj);
+ if (TS_REQ_get_policy_id(req))
+ TS_RESP_CTX_set_def_policy(ctx, TS_REQ_get_policy_id(req));
+ TS_RESP_CTX_set_time_cb(ctx, ossl_tsfac_time_cb, &lgen_time);
+
+ allowed_digests = ossl_tsfac_get_allowed_digests(self);
+ if (rb_obj_is_kind_of(allowed_digests, rb_cArray)) {
+ allowed_digests_tmp = rb_ary_new_capa(RARRAY_LEN(allowed_digests));
+ for (long i = 0; i < RARRAY_LEN(allowed_digests); i++) {
+ VALUE args[] = {
+ allowed_digests_tmp,
+ rb_ary_entry(allowed_digests, i),
+ };
+ const EVP_MD *md = (const EVP_MD *)rb_protect(ossl_evp_md_fetch_i,
+ (VALUE)args, &status);
+ if (status)
+ goto end;
+ if (!TS_RESP_CTX_add_md(ctx, md))
+ goto end;
+ }
+ }
+
+ str = rb_protect(ossl_to_der, request, &status);
+ if (status)
+ goto end;
+
+ req_bio = (BIO*)rb_protect(ossl_obj2bio_i, (VALUE)&str, &status);
+ if (status)
+ goto end;
+
+ response = TS_RESP_create_response(ctx, req_bio);
+ BIO_free(req_bio);
+ RB_GC_GUARD(allowed_digests_tmp);
+
+ if (!response) {
+ err_msg = "Error during response generation";
+ goto end;
+ }
+
+ /* bad responses aren't exceptional, but openssl still sets error
+ * information. */
+ ossl_clear_error();
+
+ SetTSResponse(tsresp, response);
+ ret = tsresp;
+
+ end:
+ ASN1_INTEGER_free(asn1_serial);
+ ASN1_OBJECT_free(def_policy_id_obj);
+ TS_RESP_CTX_free(ctx);
+ if (err_msg)
+ rb_exc_raise(ossl_make_error(eTimestampError, rb_str_new_cstr(err_msg)));
+ if (status)
+ rb_jump_tag(status);
+ return ret;
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_ts(void)
+{
+ /*
+ * Possible return value for +Response#failure_info+. Indicates that the
+ * timestamp server rejects the message imprint algorithm used in the
+ * +Request+
+ */
+ sBAD_ALG = ID2SYM(rb_intern_const("BAD_ALG"));
+
+ /*
+ * Possible return value for +Response#failure_info+. Indicates that the
+ * timestamp server was not able to process the +Request+ properly.
+ */
+ sBAD_REQUEST = ID2SYM(rb_intern_const("BAD_REQUEST"));
+ /*
+ * Possible return value for +Response#failure_info+. Indicates that the
+ * timestamp server was not able to parse certain data in the +Request+.
+ */
+ sBAD_DATA_FORMAT = ID2SYM(rb_intern_const("BAD_DATA_FORMAT"));
+
+ sTIME_NOT_AVAILABLE = ID2SYM(rb_intern_const("TIME_NOT_AVAILABLE"));
+ sUNACCEPTED_POLICY = ID2SYM(rb_intern_const("UNACCEPTED_POLICY"));
+ sUNACCEPTED_EXTENSION = ID2SYM(rb_intern_const("UNACCEPTED_EXTENSION"));
+ sADD_INFO_NOT_AVAILABLE = ID2SYM(rb_intern_const("ADD_INFO_NOT_AVAILABLE"));
+ sSYSTEM_FAILURE = ID2SYM(rb_intern_const("SYSTEM_FAILURE"));
+
+ /* Document-class: OpenSSL::Timestamp
+ * Provides classes and methods to request, create and validate
+ * {RFC3161-compliant}[http://www.ietf.org/rfc/rfc3161.txt] timestamps.
+ * Request may be used to either create requests from scratch or to parse
+ * existing requests that again can be used to request timestamps from a
+ * timestamp server, e.g. via the net/http. The resulting timestamp
+ * response may be parsed using Response.
+ *
+ * Please note that Response is read-only and immutable. To create a
+ * Response, an instance of Factory as well as a valid Request are needed.
+ *
+ * ===Create a Response:
+ * #Assumes ts.p12 is a PKCS#12-compatible file with a private key
+ * #and a certificate that has an extended key usage of 'timeStamping'
+ * p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd')
+ * md = OpenSSL::Digest.new('SHA1')
+ * hash = md.digest(data) #some binary data to be timestamped
+ * req = OpenSSL::Timestamp::Request.new
+ * req.algorithm = 'SHA1'
+ * req.message_imprint = hash
+ * req.policy_id = "1.2.3.4.5"
+ * req.nonce = 42
+ * fac = OpenSSL::Timestamp::Factory.new
+ * fac.gen_time = Time.now
+ * fac.serial_number = 1
+ * timestamp = fac.create_timestamp(p12.key, p12.certificate, req)
+ *
+ * ===Verify a timestamp response:
+ * #Assume we have a timestamp token in a file called ts.der
+ * ts = OpenSSL::Timestamp::Response.new(File.binread('ts.der'))
+ * #Assume we have the Request for this token in a file called req.der
+ * req = OpenSSL::Timestamp::Request.new(File.binread('req.der'))
+ * # Assume the associated root CA certificate is contained in a
+ * # DER-encoded file named root.cer
+ * root = OpenSSL::X509::Certificate.new(File.binread('root.cer'))
+ * # get the necessary intermediate certificates, available in
+ * # DER-encoded form in inter1.cer and inter2.cer
+ * inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer'))
+ * inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer'))
+ * ts.verify(req, root, inter1, inter2) -> ts or raises an exception if validation fails
+ *
+ */
+ mTimestamp = rb_define_module_under(mOSSL, "Timestamp");
+
+ /* Document-class: OpenSSL::Timestamp::TimestampError
+ * Generic exception class of the Timestamp module.
+ */
+ eTimestampError = rb_define_class_under(mTimestamp, "TimestampError", eOSSLError);
+
+ /* Document-class: OpenSSL::Timestamp::Response
+ * Immutable and read-only representation of a timestamp response returned
+ * from a timestamp server after receiving an associated Request. Allows
+ * access to specific information about the response but also allows to
+ * verify the Response.
+ */
+ cTimestampResponse = rb_define_class_under(mTimestamp, "Response", rb_cObject);
+ rb_define_alloc_func(cTimestampResponse, ossl_ts_resp_alloc);
+ rb_define_method(cTimestampResponse, "initialize", ossl_ts_resp_initialize, 1);
+ rb_define_method(cTimestampResponse, "status", ossl_ts_resp_get_status, 0);
+ rb_define_method(cTimestampResponse, "failure_info", ossl_ts_resp_get_failure_info, 0);
+ rb_define_method(cTimestampResponse, "status_text", ossl_ts_resp_get_status_text, 0);
+ rb_define_method(cTimestampResponse, "token", ossl_ts_resp_get_token, 0);
+ rb_define_method(cTimestampResponse, "token_info", ossl_ts_resp_get_token_info, 0);
+ rb_define_method(cTimestampResponse, "tsa_certificate", ossl_ts_resp_get_tsa_certificate, 0);
+ rb_define_method(cTimestampResponse, "to_der", ossl_ts_resp_to_der, 0);
+ rb_define_method(cTimestampResponse, "to_text", ossl_ts_resp_to_text, 0);
+ rb_define_method(cTimestampResponse, "verify", ossl_ts_resp_verify, -1);
+
+ /* Document-class: OpenSSL::Timestamp::TokenInfo
+ * Immutable and read-only representation of a timestamp token info from a
+ * Response.
+ */
+ cTimestampTokenInfo = rb_define_class_under(mTimestamp, "TokenInfo", rb_cObject);
+ rb_define_alloc_func(cTimestampTokenInfo, ossl_ts_token_info_alloc);
+ rb_define_method(cTimestampTokenInfo, "initialize", ossl_ts_token_info_initialize, 1);
+ rb_define_method(cTimestampTokenInfo, "version", ossl_ts_token_info_get_version, 0);
+ rb_define_method(cTimestampTokenInfo, "policy_id", ossl_ts_token_info_get_policy_id, 0);
+ rb_define_method(cTimestampTokenInfo, "algorithm", ossl_ts_token_info_get_algorithm, 0);
+ rb_define_method(cTimestampTokenInfo, "message_imprint", ossl_ts_token_info_get_msg_imprint, 0);
+ rb_define_method(cTimestampTokenInfo, "serial_number", ossl_ts_token_info_get_serial_number, 0);
+ rb_define_method(cTimestampTokenInfo, "gen_time", ossl_ts_token_info_get_gen_time, 0);
+ rb_define_method(cTimestampTokenInfo, "ordering", ossl_ts_token_info_get_ordering, 0);
+ rb_define_method(cTimestampTokenInfo, "nonce", ossl_ts_token_info_get_nonce, 0);
+ rb_define_method(cTimestampTokenInfo, "to_der", ossl_ts_token_info_to_der, 0);
+ rb_define_method(cTimestampTokenInfo, "to_text", ossl_ts_token_info_to_text, 0);
+
+ /* Document-class: OpenSSL::Timestamp::Request
+ * Allows to create timestamp requests or parse existing ones. A Request is
+ * also needed for creating timestamps from scratch with Factory. When
+ * created from scratch, some default values are set:
+ * * version is set to +1+
+ * * cert_requested is set to +true+
+ * * algorithm, message_imprint, policy_id, and nonce are set to +false+
+ */
+ cTimestampRequest = rb_define_class_under(mTimestamp, "Request", rb_cObject);
+ rb_define_alloc_func(cTimestampRequest, ossl_ts_req_alloc);
+ rb_define_method(cTimestampRequest, "initialize", ossl_ts_req_initialize, -1);
+ rb_define_method(cTimestampRequest, "version=", ossl_ts_req_set_version, 1);
+ rb_define_method(cTimestampRequest, "version", ossl_ts_req_get_version, 0);
+ rb_define_method(cTimestampRequest, "algorithm=", ossl_ts_req_set_algorithm, 1);
+ rb_define_method(cTimestampRequest, "algorithm", ossl_ts_req_get_algorithm, 0);
+ rb_define_method(cTimestampRequest, "message_imprint=", ossl_ts_req_set_msg_imprint, 1);
+ rb_define_method(cTimestampRequest, "message_imprint", ossl_ts_req_get_msg_imprint, 0);
+ rb_define_method(cTimestampRequest, "policy_id=", ossl_ts_req_set_policy_id, 1);
+ rb_define_method(cTimestampRequest, "policy_id", ossl_ts_req_get_policy_id, 0);
+ rb_define_method(cTimestampRequest, "nonce=", ossl_ts_req_set_nonce, 1);
+ rb_define_method(cTimestampRequest, "nonce", ossl_ts_req_get_nonce, 0);
+ rb_define_method(cTimestampRequest, "cert_requested=", ossl_ts_req_set_cert_requested, 1);
+ rb_define_method(cTimestampRequest, "cert_requested?", ossl_ts_req_get_cert_requested, 0);
+ rb_define_method(cTimestampRequest, "to_der", ossl_ts_req_to_der, 0);
+ rb_define_method(cTimestampRequest, "to_text", ossl_ts_req_to_text, 0);
+
+ /*
+ * Indicates a successful response. Equal to +0+.
+ */
+ rb_define_const(cTimestampResponse, "GRANTED", INT2NUM(TS_STATUS_GRANTED));
+ /*
+ * Indicates a successful response that probably contains modifications
+ * from the initial request. Equal to +1+.
+ */
+ rb_define_const(cTimestampResponse, "GRANTED_WITH_MODS", INT2NUM(TS_STATUS_GRANTED_WITH_MODS));
+ /*
+ * Indicates a failure. No timestamp token was created. Equal to +2+.
+ */
+ rb_define_const(cTimestampResponse, "REJECTION", INT2NUM(TS_STATUS_REJECTION));
+ /*
+ * Indicates a failure. No timestamp token was created. Equal to +3+.
+ */
+ rb_define_const(cTimestampResponse, "WAITING", INT2NUM(TS_STATUS_WAITING));
+ /*
+ * Indicates a failure. No timestamp token was created. Revocation of a
+ * certificate is imminent. Equal to +4+.
+ */
+ rb_define_const(cTimestampResponse, "REVOCATION_WARNING", INT2NUM(TS_STATUS_REVOCATION_WARNING));
+ /*
+ * Indicates a failure. No timestamp token was created. A certificate
+ * has been revoked. Equal to +5+.
+ */
+ rb_define_const(cTimestampResponse, "REVOCATION_NOTIFICATION", INT2NUM(TS_STATUS_REVOCATION_NOTIFICATION));
+
+ /* Document-class: OpenSSL::Timestamp::Factory
+ *
+ * Used to generate a Response from scratch.
+ *
+ * Please bear in mind that the implementation will always apply and prefer
+ * the policy object identifier given in the request over the default policy
+ * id specified in the Factory. As a consequence, +default_policy_id+ will
+ * only be applied if no Request#policy_id was given. But this also means
+ * that one needs to check the policy identifier in the request manually
+ * before creating the Response, e.g. to check whether it complies to a
+ * specific set of acceptable policies.
+ *
+ * There exists also the possibility to add certificates (instances of
+ * OpenSSL::X509::Certificate) besides the timestamping certificate
+ * that will be included in the resulting timestamp token if
+ * Request#cert_requested? is +true+. Ideally, one would also include any
+ * intermediate certificates (the root certificate can be left out - in
+ * order to trust it any verifying party will have to be in its possession
+ * anyway). This simplifies validation of the timestamp since these
+ * intermediate certificates are "already there" and need not be passed as
+ * external parameters to Response#verify anymore, thus minimizing external
+ * resources needed for verification.
+ *
+ * ===Example: Inclusion of (untrusted) intermediate certificates
+ *
+ * Assume we received a timestamp request that has set Request#policy_id to
+ * +nil+ and Request#cert_requested? to true. The raw request bytes are
+ * stored in a variable called +req_raw+. We'd still like to integrate
+ * the necessary intermediate certificates (in +inter1.cer+ and
+ * +inter2.cer+) to simplify validation of the resulting Response. +ts.p12+
+ * is a PKCS#12-compatible file including the private key and the
+ * timestamping certificate.
+ *
+ * req = OpenSSL::Timestamp::Request.new(raw_bytes)
+ * p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd')
+ * inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer'))
+ * inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer'))
+ * fac = OpenSSL::Timestamp::Factory.new
+ * fac.gen_time = Time.now
+ * fac.serial_number = 1
+ * fac.allowed_digests = ["sha256", "sha384", "sha512"]
+ * #needed because the Request contained no policy identifier
+ * fac.default_policy_id = '1.2.3.4.5'
+ * fac.additional_certificates = [ inter1, inter2 ]
+ * timestamp = fac.create_timestamp(p12.key, p12.certificate, req)
+ */
+ cTimestampFactory = rb_define_class_under(mTimestamp, "Factory", rb_cObject);
+ /*
+ * The list of digest algorithms that the factory is allowed
+ * create timestamps for. Known vulnerable or weak algorithms should not be
+ * allowed where possible. Must be an Array of String or OpenSSL::Digest
+ * subclass instances.
+ */
+ rb_attr(cTimestampFactory, rb_intern_const("allowed_digests"), 1, 1, 0);
+ /*
+ * A String representing the default policy object identifier, or +nil+.
+ *
+ * Request#policy_id will always be preferred over this if present in the
+ * Request, only if Request#policy_id is +nil+ default_policy will be used.
+ * If none of both is present, a TimestampError will be raised when trying
+ * to create a Response.
+ */
+ rb_attr(cTimestampFactory, rb_intern_const("default_policy_id"), 1, 1, 0);
+ /*
+ * The serial number to be used for timestamp creation. Must be present for
+ * timestamp creation. Must be an instance of OpenSSL::BN or Integer.
+ */
+ rb_attr(cTimestampFactory, rb_intern_const("serial_number"), 1, 1, 0);
+ /*
+ * The Time value to be used in the Response. Must be present for timestamp
+ * creation.
+ */
+ rb_attr(cTimestampFactory, rb_intern_const("gen_time"), 1, 1, 0);
+ /*
+ * Additional certificates apart from the timestamp certificate (e.g.
+ * intermediate certificates) to be added to the Response.
+ * Must be an Array of OpenSSL::X509::Certificate, or +nil+.
+ */
+ rb_attr(cTimestampFactory, rb_intern_const("additional_certs"), 1, 1, 0);
+ rb_define_method(cTimestampFactory, "create_timestamp", ossl_tsfac_create_ts, 3);
+}
+#else /* OPENSSL_NO_TS */
+void
+Init_ossl_ts(void)
+{
+}
+#endif
diff --git a/ext/openssl/ossl_ts.h b/ext/openssl/ossl_ts.h
new file mode 100644
index 0000000000..eeca3046eb
--- /dev/null
+++ b/ext/openssl/ossl_ts.h
@@ -0,0 +1,16 @@
+/*
+ *
+ * Copyright (C) 2010 Martin Bosslet <Martin.Bosslet@googlemail.com>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'COPYING'.)
+ */
+
+#if !defined(_OSSL_TS_H_)
+#define _OSSL_TS_H_
+
+void Init_ossl_ts(void);
+
+#endif
diff --git a/ext/openssl/ossl_version.h b/ext/openssl/ossl_version.h
deleted file mode 100644
index 63878e0d8e..0000000000
--- a/ext/openssl/ossl_version.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * $Id$
- * 'OpenSSL for Ruby' project
- * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
- * All rights reserved.
- */
-/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
- */
-#if !defined(_OSSL_VERSION_H_)
-#define _OSSL_VERSION_H_
-
-#define OSSL_VERSION "1.0.0"
-
-#endif /* _OSSL_VERSION_H_ */
diff --git a/ext/openssl/ossl_x509.c b/ext/openssl/ossl_x509.c
index fd1d9b6c7e..bc3914fda2 100644
--- a/ext/openssl/ossl_x509.c
+++ b/ext/openssl/ossl_x509.c
@@ -1,23 +1,34 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
VALUE mX509;
-#define DefX509Const(x) rb_define_const(mX509, #x,INT2FIX(X509_##x))
+#define DefX509Const(x) rb_define_const(mX509, #x, INT2NUM(X509_##x))
#define DefX509Default(x,i) \
- rb_define_const(mX509, "DEFAULT_" #x, rb_str_new2(X509_get_default_##i()))
+ rb_define_const(mX509, "DEFAULT_" #x, \
+ rb_obj_freeze(rb_str_new_cstr(X509_get_default_##i())))
+
+ASN1_TIME *
+ossl_x509_time_adjust(ASN1_TIME *s, VALUE time)
+{
+ time_t sec;
+
+ int off_days;
+
+ ossl_time_split(time, &sec, &off_days);
+ return X509_time_adj_ex(s, off_days, 0, &sec);
+}
void
-Init_ossl_x509()
+Init_ossl_x509(void)
{
mX509 = rb_define_module_under(mOSSL, "X509");
@@ -30,7 +41,11 @@ Init_ossl_x509()
Init_ossl_x509revoked();
Init_ossl_x509store();
+ /* Constants are up-to-date with 1.1.1. */
+
+ /* Certificate verification error code */
DefX509Const(V_OK);
+ DefX509Const(V_ERR_UNSPECIFIED);
DefX509Const(V_ERR_UNABLE_TO_GET_ISSUER_CERT);
DefX509Const(V_ERR_UNABLE_TO_GET_CRL);
DefX509Const(V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE);
@@ -62,37 +77,156 @@ Init_ossl_x509()
DefX509Const(V_ERR_AKID_SKID_MISMATCH);
DefX509Const(V_ERR_AKID_ISSUER_SERIAL_MISMATCH);
DefX509Const(V_ERR_KEYUSAGE_NO_CERTSIGN);
+ DefX509Const(V_ERR_UNABLE_TO_GET_CRL_ISSUER);
+ DefX509Const(V_ERR_UNHANDLED_CRITICAL_EXTENSION);
+ DefX509Const(V_ERR_KEYUSAGE_NO_CRL_SIGN);
+ DefX509Const(V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION);
+ DefX509Const(V_ERR_INVALID_NON_CA);
+ DefX509Const(V_ERR_PROXY_PATH_LENGTH_EXCEEDED);
+ DefX509Const(V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE);
+ DefX509Const(V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED);
+ DefX509Const(V_ERR_INVALID_EXTENSION);
+ DefX509Const(V_ERR_INVALID_POLICY_EXTENSION);
+ DefX509Const(V_ERR_NO_EXPLICIT_POLICY);
+ DefX509Const(V_ERR_DIFFERENT_CRL_SCOPE);
+ DefX509Const(V_ERR_UNSUPPORTED_EXTENSION_FEATURE);
+ DefX509Const(V_ERR_UNNESTED_RESOURCE);
+ DefX509Const(V_ERR_PERMITTED_VIOLATION);
+ DefX509Const(V_ERR_EXCLUDED_VIOLATION);
+ DefX509Const(V_ERR_SUBTREE_MINMAX);
DefX509Const(V_ERR_APPLICATION_VERIFICATION);
+ DefX509Const(V_ERR_UNSUPPORTED_CONSTRAINT_TYPE);
+ DefX509Const(V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX);
+ DefX509Const(V_ERR_UNSUPPORTED_NAME_SYNTAX);
+ DefX509Const(V_ERR_CRL_PATH_VALIDATION_ERROR);
+#if defined(X509_V_ERR_PATH_LOOP) /* OpenSSL 1.1.0, missing in LibreSSL */
+ DefX509Const(V_ERR_PATH_LOOP);
+#endif
+#if defined(X509_V_ERR_SUITE_B_INVALID_VERSION) /* OpenSSL 1.1.0, missing in LibreSSL */
+ DefX509Const(V_ERR_SUITE_B_INVALID_VERSION);
+ DefX509Const(V_ERR_SUITE_B_INVALID_ALGORITHM);
+ DefX509Const(V_ERR_SUITE_B_INVALID_CURVE);
+ DefX509Const(V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM);
+ DefX509Const(V_ERR_SUITE_B_LOS_NOT_ALLOWED);
+ DefX509Const(V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256);
+#endif
+ DefX509Const(V_ERR_HOSTNAME_MISMATCH);
+ DefX509Const(V_ERR_EMAIL_MISMATCH);
+ DefX509Const(V_ERR_IP_ADDRESS_MISMATCH);
+#if defined(X509_V_ERR_DANE_NO_MATCH) /* OpenSSL 1.1.0, missing in LibreSSL */
+ DefX509Const(V_ERR_DANE_NO_MATCH);
+#endif
+ DefX509Const(V_ERR_EE_KEY_TOO_SMALL);
+ DefX509Const(V_ERR_CA_KEY_TOO_SMALL);
+ DefX509Const(V_ERR_CA_MD_TOO_WEAK);
+ DefX509Const(V_ERR_INVALID_CALL);
+ DefX509Const(V_ERR_STORE_LOOKUP);
+#if defined(X509_V_ERR_NO_VALID_SCTS) /* OpenSSL 1.1.0, missing in LibreSSL */
+ DefX509Const(V_ERR_NO_VALID_SCTS);
+#endif
+#if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION) /* OpenSSL 1.1.0, missing in LibreSSL */
+ DefX509Const(V_ERR_PROXY_SUBJECT_NAME_VIOLATION);
+#endif
+#if defined(X509_V_ERR_OCSP_VERIFY_NEEDED) /* OpenSSL 1.1.1, missing in LibreSSL */
+ DefX509Const(V_ERR_OCSP_VERIFY_NEEDED);
+ DefX509Const(V_ERR_OCSP_VERIFY_FAILED);
+ DefX509Const(V_ERR_OCSP_CERT_UNKNOWN);
+#endif
-#if defined(X509_V_FLAG_CRL_CHECK)
+ /* Certificate verify flags */
+ /* Set by Store#flags= and StoreContext#flags=. */
+ DefX509Const(V_FLAG_USE_CHECK_TIME);
+ /* Set by Store#flags= and StoreContext#flags=. Enables CRL checking for the
+ * certificate chain leaf. */
DefX509Const(V_FLAG_CRL_CHECK);
-#endif
-#if defined(X509_V_FLAG_CRL_CHECK_ALL)
+ /* Set by Store#flags= and StoreContext#flags=. Enables CRL checking for all
+ * certificates in the certificate chain */
DefX509Const(V_FLAG_CRL_CHECK_ALL);
+ /* Set by Store#flags= and StoreContext#flags=. Disables critical extension
+ * checking. */
+ DefX509Const(V_FLAG_IGNORE_CRITICAL);
+ /* Set by Store#flags= and StoreContext#flags=. Disables workarounds for
+ * broken certificates. */
+ DefX509Const(V_FLAG_X509_STRICT);
+ /* Set by Store#flags= and StoreContext#flags=. Enables proxy certificate
+ * verification. */
+ DefX509Const(V_FLAG_ALLOW_PROXY_CERTS);
+ /* Set by Store#flags= and StoreContext#flags=. Enables certificate policy
+ * constraints checking. */
+ DefX509Const(V_FLAG_POLICY_CHECK);
+ /* Set by Store#flags= and StoreContext#flags=.
+ * Implies V_FLAG_POLICY_CHECK */
+ DefX509Const(V_FLAG_EXPLICIT_POLICY);
+ /* Set by Store#flags= and StoreContext#flags=.
+ * Implies V_FLAG_POLICY_CHECK */
+ DefX509Const(V_FLAG_INHIBIT_ANY);
+ /* Set by Store#flags= and StoreContext#flags=.
+ * Implies V_FLAG_POLICY_CHECK */
+ DefX509Const(V_FLAG_INHIBIT_MAP);
+ /* Set by Store#flags= and StoreContext#flags=. */
+ DefX509Const(V_FLAG_NOTIFY_POLICY);
+ /* Set by Store#flags= and StoreContext#flags=. Enables some additional
+ * features including support for indirect signed CRLs. */
+ DefX509Const(V_FLAG_EXTENDED_CRL_SUPPORT);
+ /* Set by Store#flags= and StoreContext#flags=. Uses delta CRLs. If not
+ * specified, deltas are ignored. */
+ DefX509Const(V_FLAG_USE_DELTAS);
+ /* Set by Store#flags= and StoreContext#flags=. Enables checking of the
+ * signature of the root self-signed CA. */
+ DefX509Const(V_FLAG_CHECK_SS_SIGNATURE);
+ /* Set by Store#flags= and StoreContext#flags=. When constructing a
+ * certificate chain, search the Store first for the issuer certificate.
+ * Enabled by default in OpenSSL >= 1.1.0. */
+ DefX509Const(V_FLAG_TRUSTED_FIRST);
+#if defined(X509_V_FLAG_SUITEB_128_LOS_ONLY) /* OpenSSL 1.1.0, missing in LibreSSL */
+ /* Set by Store#flags= and StoreContext#flags=.
+ * Enables Suite B 128 bit only mode. */
+ DefX509Const(V_FLAG_SUITEB_128_LOS_ONLY);
+ /* Set by Store#flags= and StoreContext#flags=.
+ * Enables Suite B 192 bit only mode. */
+ DefX509Const(V_FLAG_SUITEB_192_LOS);
+ /* Set by Store#flags= and StoreContext#flags=.
+ * Enables Suite B 128 bit mode allowing 192 bit algorithms. */
+ DefX509Const(V_FLAG_SUITEB_128_LOS);
#endif
+ /* Set by Store#flags= and StoreContext#flags=.
+ * Allows partial chains if at least one certificate is in trusted store. */
+ DefX509Const(V_FLAG_PARTIAL_CHAIN);
+ /* Set by Store#flags= and StoreContext#flags=. Suppresses searching for
+ * a alternative chain. No effect in OpenSSL >= 1.1.0. */
+ DefX509Const(V_FLAG_NO_ALT_CHAINS);
+ /* Set by Store#flags= and StoreContext#flags=. Suppresses checking the
+ * validity period of certificates and CRLs. No effect when the current
+ * time is explicitly set by Store#time= or StoreContext#time=. */
+ DefX509Const(V_FLAG_NO_CHECK_TIME);
+ /* Set by Store#purpose=. SSL/TLS client. */
DefX509Const(PURPOSE_SSL_CLIENT);
+ /* Set by Store#purpose=. SSL/TLS server. */
DefX509Const(PURPOSE_SSL_SERVER);
+ /* Set by Store#purpose=. Netscape SSL server. */
DefX509Const(PURPOSE_NS_SSL_SERVER);
+ /* Set by Store#purpose=. S/MIME signing. */
DefX509Const(PURPOSE_SMIME_SIGN);
+ /* Set by Store#purpose=. S/MIME encryption. */
DefX509Const(PURPOSE_SMIME_ENCRYPT);
+ /* Set by Store#purpose=. CRL signing */
DefX509Const(PURPOSE_CRL_SIGN);
+ /* Set by Store#purpose=. No checks. */
DefX509Const(PURPOSE_ANY);
-#if defined(X509_PURPOSE_OCSP_HELPER)
+ /* Set by Store#purpose=. OCSP helper. */
DefX509Const(PURPOSE_OCSP_HELPER);
-#endif
+ /* Set by Store#purpose=. Time stamps signer. */
+ DefX509Const(PURPOSE_TIMESTAMP_SIGN);
DefX509Const(TRUST_COMPAT);
DefX509Const(TRUST_SSL_CLIENT);
DefX509Const(TRUST_SSL_SERVER);
DefX509Const(TRUST_EMAIL);
DefX509Const(TRUST_OBJECT_SIGN);
-#if defined(X509_TRUST_OCSP_SIGN)
DefX509Const(TRUST_OCSP_SIGN);
-#endif
-#if defined(X509_TRUST_OCSP_REQUEST)
DefX509Const(TRUST_OCSP_REQUEST);
-#endif
+ DefX509Const(TRUST_TSA);
DefX509Default(CERT_AREA, cert_area);
DefX509Default(CERT_DIR, cert_dir);
@@ -101,4 +235,3 @@ Init_ossl_x509()
DefX509Default(CERT_FILE_ENV, cert_file_env);
DefX509Default(PRIVATE_DIR, private_dir);
}
-
diff --git a/ext/openssl/ossl_x509.h b/ext/openssl/ossl_x509.h
index 1a43569073..71932ef1a9 100644
--- a/ext/openssl/ossl_x509.h
+++ b/ext/openssl/ossl_x509.h
@@ -1,12 +1,11 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_X509_H_)
#define _OSSL_X509_H_
@@ -16,26 +15,30 @@
*/
extern VALUE mX509;
+/*
+ * Converts the VALUE into Integer and set it to the ASN1_TIME. This is a
+ * wrapper for X509_time_adj_ex() so passing NULL creates a new ASN1_TIME.
+ * Note that the caller must check the NULL return.
+ */
+ASN1_TIME *ossl_x509_time_adjust(ASN1_TIME *, VALUE);
+
void Init_ossl_x509(void);
/*
* X509Attr
*/
extern VALUE cX509Attr;
-extern VALUE eX509AttrError;
-VALUE ossl_x509attr_new(X509_ATTRIBUTE *);
-X509_ATTRIBUTE *DupX509AttrPtr(VALUE);
+VALUE ossl_x509attr_new(const X509_ATTRIBUTE *);
+X509_ATTRIBUTE *GetX509AttrPtr(VALUE);
void Init_ossl_x509attr(void);
/*
* X509Cert
*/
extern VALUE cX509Cert;
-extern VALUE eX509CertError;
-VALUE ossl_x509_new(X509 *);
-VALUE ossl_x509_new_from_file(VALUE);
+VALUE ossl_x509_new(const X509 *);
X509 *GetX509CertPtr(VALUE);
X509 *DupX509CertPtr(VALUE);
void Init_ossl_x509cert(void);
@@ -43,72 +46,51 @@ void Init_ossl_x509cert(void);
/*
* X509CRL
*/
-extern VALUE cX509CRL;
-extern VALUE eX509CRLError;
-
-VALUE ossl_x509crl_new(X509_CRL *);
+VALUE ossl_x509crl_new(const X509_CRL *);
X509_CRL *GetX509CRLPtr(VALUE);
-X509_CRL *DupX509CRLPtr(VALUE);
void Init_ossl_x509crl(void);
/*
* X509Extension
*/
extern VALUE cX509Ext;
-extern VALUE cX509ExtFactory;
-extern VALUE eX509ExtError;
-VALUE ossl_x509ext_new(X509_EXTENSION *);
+VALUE ossl_x509ext_new(const X509_EXTENSION *);
X509_EXTENSION *GetX509ExtPtr(VALUE);
-X509_EXTENSION *DupX509ExtPtr(VALUE);
void Init_ossl_x509ext(void);
/*
* X509Name
*/
-extern VALUE cX509Name;
-extern VALUE eX509NameError;
-
-VALUE ossl_x509name_new(X509_NAME *);
+VALUE ossl_x509name_new(const X509_NAME *);
X509_NAME *GetX509NamePtr(VALUE);
void Init_ossl_x509name(void);
/*
* X509Request
*/
-extern VALUE cX509Req;
-extern VALUE eX509ReqError;
-
-VALUE ossl_x509req_new(X509_REQ *);
X509_REQ *GetX509ReqPtr(VALUE);
-X509_REQ *DupX509ReqPtr(VALUE);
void Init_ossl_x509req(void);
/*
* X509Revoked
*/
extern VALUE cX509Rev;
-extern VALUE eX509RevError;
-VALUE ossl_x509revoked_new(X509_REVOKED *);
+VALUE ossl_x509revoked_new(const X509_REVOKED *);
X509_REVOKED *DupX509RevokedPtr(VALUE);
void Init_ossl_x509revoked(void);
/*
* X509Store and X509StoreContext
*/
-extern VALUE cX509Store;
-extern VALUE cX509StoreContext;
-extern VALUE eX509StoreError;
-
-VALUE ossl_x509store_new(X509_STORE *);
X509_STORE *GetX509StorePtr(VALUE);
-X509_STORE *DupX509StorePtr(VALUE);
-
-VALUE ossl_x509stctx_new(X509_STORE_CTX *);
-VALUE ossl_x509stctx_clear_ptr(VALUE);
-X509_STORE_CTX *GetX509StCtxtPtr(VALUE);
-
void Init_ossl_x509store(void);
+/*
+ * Calls the verify callback Proc (the first parameter) with given pre-verify
+ * result and the X509_STORE_CTX.
+ */
+int ossl_verify_cb_call(VALUE, int, X509_STORE_CTX *);
+
#endif /* _OSSL_X509_H_ */
diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c
index 7b88e294a9..38600b9b00 100644
--- a/ext/openssl/ossl_x509attr.c
+++ b/ext/openssl/ossl_x509attr.c
@@ -1,71 +1,76 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#define WrapX509Attr(klass, obj, attr) do { \
- if (!attr) { \
- ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
+#define NewX509Attr(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_x509attr_type, 0)
+#define SetX509Attr(obj, attr) do { \
+ if (!(attr)) { \
+ ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
} \
- obj = Data_Wrap_Struct(klass, 0, X509_ATTRIBUTE_free, attr); \
+ RTYPEDDATA_DATA(obj) = (attr); \
} while (0)
#define GetX509Attr(obj, attr) do { \
- Data_Get_Struct(obj, X509_ATTRIBUTE, attr); \
- if (!attr) { \
- ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
+ TypedData_Get_Struct((obj), X509_ATTRIBUTE, &ossl_x509attr_type, (attr)); \
+ if (!(attr)) { \
+ ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
} \
} while (0)
-#define SafeGetX509Attr(obj, attr) do { \
- OSSL_Check_Kind(obj, cX509Attr); \
- GetX509Attr(obj, attr); \
-} while (0)
/*
* Classes
*/
VALUE cX509Attr;
-VALUE eX509AttrError;
+static VALUE eX509AttrError;
+
+static void
+ossl_x509attr_free(void *ptr)
+{
+ X509_ATTRIBUTE_free(ptr);
+}
+
+static const rb_data_type_t ossl_x509attr_type = {
+ "OpenSSL/X509/ATTRIBUTE",
+ {
+ 0, ossl_x509attr_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
/*
* Public
*/
VALUE
-ossl_x509attr_new(X509_ATTRIBUTE *attr)
+ossl_x509attr_new(const X509_ATTRIBUTE *attr)
{
X509_ATTRIBUTE *new;
VALUE obj;
-
- if (!attr) {
- new = X509_ATTRIBUTE_new();
- } else {
- new = X509_ATTRIBUTE_dup(attr);
- }
- if (!new) {
- ossl_raise(eX509AttrError, NULL);
- }
- WrapX509Attr(cX509Attr, obj, new);
+
+ obj = NewX509Attr(cX509Attr);
+ /* OpenSSL 1.1.1 takes a non-const pointer */
+ new = X509_ATTRIBUTE_dup((X509_ATTRIBUTE *)attr);
+ if (!new)
+ ossl_raise(eX509AttrError, "X509_ATTRIBUTE_dup");
+ SetX509Attr(obj, new);
return obj;
}
X509_ATTRIBUTE *
-DupX509AttrPtr(VALUE obj)
+GetX509AttrPtr(VALUE obj)
{
- X509_ATTRIBUTE *attr, *new;
+ X509_ATTRIBUTE *attr;
- SafeGetX509Attr(obj, attr);
- if (!(new = X509_ATTRIBUTE_dup(attr))) {
- ossl_raise(eX509AttrError, NULL);
- }
+ GetX509Attr(obj, attr);
- return new;
+ return attr;
}
/*
@@ -77,30 +82,36 @@ ossl_x509attr_alloc(VALUE klass)
X509_ATTRIBUTE *attr;
VALUE obj;
- if (!(attr = X509_ATTRIBUTE_new()))
- ossl_raise(eX509AttrError, NULL);
- WrapX509Attr(klass, obj, attr);
+ obj = NewX509Attr(klass);
+ if (!(attr = X509_ATTRIBUTE_new()))
+ ossl_raise(eX509AttrError, NULL);
+ SetX509Attr(obj, attr);
return obj;
}
+/*
+ * call-seq:
+ * Attribute.new(oid [, value]) => attr
+ */
static VALUE
ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE oid, value;
- X509_ATTRIBUTE *attr;
- unsigned char *p;
+ X509_ATTRIBUTE *attr, *x;
+ const unsigned char *p;
GetX509Attr(self, attr);
if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){
- oid = ossl_to_der_if_possible(oid);
- StringValue(oid);
- p = RSTRING(oid)->ptr;
- if(!d2i_X509_ATTRIBUTE((X509_ATTRIBUTE**)&DATA_PTR(self),
- &p, RSTRING(oid)->len)){
- ossl_raise(eX509AttrError, NULL);
- }
- return self;
+ oid = ossl_to_der_if_possible(oid);
+ StringValue(oid);
+ p = (unsigned char *)RSTRING_PTR(oid);
+ x = d2i_X509_ATTRIBUTE(&attr, &p, RSTRING_LEN(oid));
+ DATA_PTR(self) = attr;
+ if(!x){
+ ossl_raise(eX509AttrError, NULL);
+ }
+ return self;
}
rb_funcall(self, rb_intern("oid="), 1, oid);
rb_funcall(self, rb_intern("value="), 1, value);
@@ -108,108 +119,159 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/* :nodoc: */
+static VALUE
+ossl_x509attr_initialize_copy(VALUE self, VALUE other)
+{
+ X509_ATTRIBUTE *attr, *attr_other, *attr_new;
+
+ rb_check_frozen(self);
+ GetX509Attr(self, attr);
+ GetX509Attr(other, attr_other);
+
+ attr_new = X509_ATTRIBUTE_dup(attr_other);
+ if (!attr_new)
+ ossl_raise(eX509AttrError, "X509_ATTRIBUTE_dup");
+
+ SetX509Attr(self, attr_new);
+ X509_ATTRIBUTE_free(attr);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * attr.oid = string => string
+ */
static VALUE
ossl_x509attr_set_oid(VALUE self, VALUE oid)
{
X509_ATTRIBUTE *attr;
ASN1_OBJECT *obj;
char *s;
-
- s = StringValuePtr(oid);
+
+ GetX509Attr(self, attr);
+ s = StringValueCStr(oid);
obj = OBJ_txt2obj(s, 0);
- if(!obj) obj = OBJ_txt2obj(s, 1);
if(!obj) ossl_raise(eX509AttrError, NULL);
- GetX509Attr(self, attr);
- X509_ATTRIBUTE_set1_object(attr, obj);
-
+ if (!X509_ATTRIBUTE_set1_object(attr, obj)) {
+ ASN1_OBJECT_free(obj);
+ ossl_raise(eX509AttrError, "X509_ATTRIBUTE_set1_object");
+ }
+ ASN1_OBJECT_free(obj);
+
return oid;
}
+/*
+ * call-seq:
+ * attr.oid -> string
+ *
+ * Returns the OID of the attribute. Returns the short name or the dotted
+ * decimal notation.
+ */
static VALUE
ossl_x509attr_get_oid(VALUE self)
{
X509_ATTRIBUTE *attr;
- ASN1_OBJECT *oid;
- BIO *out;
- VALUE ret;
- int nid;
GetX509Attr(self, attr);
- oid = X509_ATTRIBUTE_get0_object(attr);
- if ((nid = OBJ_obj2nid(oid)) != NID_undef)
- ret = rb_str_new2(OBJ_nid2sn(nid));
- else{
- if (!(out = BIO_new(BIO_s_mem())))
- ossl_raise(eX509AttrError, NULL);
- i2a_ASN1_OBJECT(out, oid);
- ret = ossl_membio2str(out);
- }
-
- return ret;
+ return ossl_asn1obj_to_string(X509_ATTRIBUTE_get0_object(attr));
}
-#if defined(HAVE_ST_X509_ATTRIBUTE_SINGLE) || defined(HAVE_ST_SINGLE)
-# define OSSL_X509ATTR_IS_SINGLE(attr) ((attr)->single)
-# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->single = 1)
-#else
-# define OSSL_X509ATTR_IS_SINGLE(attr) (!(attr)->set)
-# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->set = 0)
-#endif
-
+/*
+ * call-seq:
+ * attr.value = asn1 => asn1
+ */
static VALUE
ossl_x509attr_set_value(VALUE self, VALUE value)
{
X509_ATTRIBUTE *attr;
- ASN1_TYPE *a1type;
+ GetX509Attr(self, attr);
+
+ OSSL_Check_Kind(value, cASN1Data);
+ VALUE der = ossl_to_der(value);
+ const unsigned char *p = (const unsigned char *)RSTRING_PTR(der);
+ STACK_OF(ASN1_TYPE) *sk = d2i_ASN1_SET_ANY(NULL, &p, RSTRING_LEN(der));
+ if (!sk)
+ ossl_raise(eX509AttrError, "attribute value must be ASN1::Set");
- if(!(a1type = ossl_asn1_get_asn1type(value)))
- ossl_raise(eASN1Error, "could not get ASN1_TYPE");
- if(ASN1_TYPE_get(a1type) == V_ASN1_SEQUENCE){
- ASN1_TYPE_free(a1type);
- ossl_raise(eASN1Error, "couldn't set SEQUENCE for attribute value.");
+ if (X509_ATTRIBUTE_count(attr)) { /* populated, reset first */
+ const ASN1_OBJECT *obj = X509_ATTRIBUTE_get0_object(attr);
+ X509_ATTRIBUTE *new_attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, 0, NULL, -1);
+ if (!new_attr) {
+ sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
+ ossl_raise(eX509AttrError, "X509_ATTRIBUTE_create_by_OBJ");
+ }
+ SetX509Attr(self, new_attr);
+ X509_ATTRIBUTE_free(attr);
+ attr = new_attr;
}
- GetX509Attr(self, attr);
- if(attr->value.set){
- if(OSSL_X509ATTR_IS_SINGLE(attr)) ASN1_TYPE_free(attr->value.single);
- else sk_ASN1_TYPE_free(attr->value.set);
+
+ for (int i = 0; i < sk_ASN1_TYPE_num(sk); i++) {
+ ASN1_TYPE *a1type = sk_ASN1_TYPE_value(sk, i);
+ if (!X509_ATTRIBUTE_set1_data(attr, ASN1_TYPE_get(a1type),
+ a1type->value.ptr, -1)) {
+ sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
+ ossl_raise(eX509AttrError, "X509_ATTRIBUTE_set1_data");
+ }
}
- OSSL_X509ATTR_SET_SINGLE(attr);
- attr->value.single = a1type;
+ sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
return value;
}
+/*
+ * call-seq:
+ * attr.value => asn1
+ */
static VALUE
ossl_x509attr_get_value(VALUE self)
{
X509_ATTRIBUTE *attr;
- VALUE str, asn1;
- long length;
+ STACK_OF(ASN1_TYPE) *sk;
+ VALUE str;
+ int i, count, len;
unsigned char *p;
GetX509Attr(self, attr);
- if(attr->value.ptr == NULL) return Qnil;
- if(OSSL_X509ATTR_IS_SINGLE(attr)){
- length = i2d_ASN1_TYPE(attr->value.single, NULL);
- str = rb_str_new(0, length);
- p = RSTRING(str)->ptr;
- i2d_ASN1_TYPE(attr->value.single, &p);
- ossl_str_adjust(str, p);
+ count = X509_ATTRIBUTE_count(attr);
+ /* there is no X509_ATTRIBUTE_get0_set() :( */
+#ifdef HAVE_OPENSSL_SK_NEW_RESERVE
+ if (!(sk = sk_ASN1_TYPE_new_reserve(NULL, count)))
+ ossl_raise(eX509AttrError, "sk_new_reserve");
+#else
+ if (!(sk = sk_ASN1_TYPE_new_null()))
+ ossl_raise(eX509AttrError, "sk_new");
+#endif
+
+ for (i = 0; i < count; i++) {
+ if (!sk_ASN1_TYPE_push(sk, (ASN1_TYPE *)X509_ATTRIBUTE_get0_type(attr, i))) {
+ sk_ASN1_TYPE_free(sk);
+ ossl_raise(eX509AttrError, NULL);
+ }
+ }
+
+ if ((len = i2d_ASN1_SET_ANY(sk, NULL)) <= 0) {
+ sk_ASN1_TYPE_free(sk);
+ ossl_raise(eX509AttrError, NULL);
}
- else{
- length = i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, NULL,
- i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0);
- str = rb_str_new(0, length);
- p = RSTRING(str)->ptr;
- i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, &p,
- i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0);
- ossl_str_adjust(str, p);
+ str = rb_str_new(0, len);
+ p = (unsigned char *)RSTRING_PTR(str);
+ if (i2d_ASN1_SET_ANY(sk, &p) <= 0) {
+ sk_ASN1_TYPE_free(sk);
+ ossl_raise(eX509AttrError, NULL);
}
- asn1 = rb_funcall(mASN1, rb_intern("decode"), 1, str);
+ ossl_str_adjust(str, p);
+ sk_ASN1_TYPE_free(sk);
- return asn1;
+ return rb_funcall(mASN1, rb_intern("decode"), 1, str);
}
+/*
+ * call-seq:
+ * attr.to_der => string
+ */
static VALUE
ossl_x509attr_to_der(VALUE self)
{
@@ -220,12 +282,12 @@ ossl_x509attr_to_der(VALUE self)
GetX509Attr(self, attr);
if((len = i2d_X509_ATTRIBUTE(attr, NULL)) <= 0)
- ossl_raise(eX509AttrError, NULL);
+ ossl_raise(eX509AttrError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = (unsigned char *)RSTRING_PTR(str);
if(i2d_X509_ATTRIBUTE(attr, &p) <= 0)
- ossl_raise(eX509AttrError, NULL);
- RSTRING(str)->len = p - (unsigned char*)RSTRING(str)->ptr;
+ ossl_raise(eX509AttrError, NULL);
+ ossl_str_adjust(str, p);
return str;
}
@@ -234,13 +296,14 @@ ossl_x509attr_to_der(VALUE self)
* X509_ATTRIBUTE init
*/
void
-Init_ossl_x509attr()
+Init_ossl_x509attr(void)
{
eX509AttrError = rb_define_class_under(mX509, "AttributeError", eOSSLError);
cX509Attr = rb_define_class_under(mX509, "Attribute", rb_cObject);
rb_define_alloc_func(cX509Attr, ossl_x509attr_alloc);
rb_define_method(cX509Attr, "initialize", ossl_x509attr_initialize, -1);
+ rb_define_method(cX509Attr, "initialize_copy", ossl_x509attr_initialize_copy, 1);
rb_define_method(cX509Attr, "oid=", ossl_x509attr_set_oid, 1);
rb_define_method(cX509Attr, "oid", ossl_x509attr_get_oid, 0);
rb_define_method(cX509Attr, "value=", ossl_x509attr_set_value, 1);
diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c
index fc587a31f3..08dd184a0c 100644
--- a/ext/openssl/ossl_x509cert.c
+++ b/ext/openssl/ossl_x509cert.c
@@ -1,87 +1,64 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#define WrapX509(klass, obj, x509) do { \
- if (!x509) { \
- ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
+#define NewX509(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_x509_type, 0)
+#define SetX509(obj, x509) do { \
+ if (!(x509)) { \
+ ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
} \
- obj = Data_Wrap_Struct(klass, 0, X509_free, x509); \
+ RTYPEDDATA_DATA(obj) = (x509); \
} while (0)
#define GetX509(obj, x509) do { \
- Data_Get_Struct(obj, X509, x509); \
- if (!x509) { \
- ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
+ TypedData_Get_Struct((obj), X509, &ossl_x509_type, (x509)); \
+ if (!(x509)) { \
+ ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
} \
} while (0)
-#define SafeGetX509(obj, x509) do { \
- OSSL_Check_Kind(obj, cX509Cert); \
- GetX509(obj, x509); \
-} while (0)
/*
* Classes
*/
VALUE cX509Cert;
-VALUE eX509CertError;
+static VALUE eX509CertError;
+
+static void
+ossl_x509_free(void *ptr)
+{
+ X509_free(ptr);
+}
+
+static const rb_data_type_t ossl_x509_type = {
+ "OpenSSL/X509",
+ {
+ 0, ossl_x509_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
/*
* Public
*/
VALUE
-ossl_x509_new(X509 *x509)
+ossl_x509_new(const X509 *x509)
{
X509 *new;
VALUE obj;
- if (!x509) {
- new = X509_new();
- } else {
- new = X509_dup(x509);
- }
- if (!new) {
- ossl_raise(eX509CertError, NULL);
- }
- WrapX509(cX509Cert, obj, new);
-
- return obj;
-}
-
-VALUE
-ossl_x509_new_from_file(VALUE filename)
-{
- X509 *x509;
- FILE *fp;
- VALUE obj;
-
- SafeStringValue(filename);
- if (!(fp = fopen(RSTRING(filename)->ptr, "r"))) {
- ossl_raise(eX509CertError, "%s", strerror(errno));
- }
- x509 = PEM_read_X509(fp, NULL, NULL, NULL);
- /*
- * prepare for DER...
-#if !defined(OPENSSL_NO_FP_API)
- if (!x509) {
- rewind(fp);
-
- x509 = d2i_X509_fp(fp, NULL);
- }
-#endif
- */
- fclose(fp);
- if (!x509) {
- ossl_raise(eX509CertError, NULL);
- }
- WrapX509(cX509Cert, obj, x509);
+ obj = NewX509(cX509Cert);
+ /* OpenSSL 1.1.1 takes a non-const pointer */
+ new = X509_dup((X509 *)x509);
+ if (!new)
+ ossl_raise(eX509CertError, "X509_dup");
+ SetX509(obj, new);
return obj;
}
@@ -90,9 +67,9 @@ X509 *
GetX509CertPtr(VALUE obj)
{
X509 *x509;
-
- SafeGetX509(obj, x509);
-
+
+ GetX509(obj, x509);
+
return x509;
}
@@ -100,76 +77,91 @@ X509 *
DupX509CertPtr(VALUE obj)
{
X509 *x509;
-
- SafeGetX509(obj, x509);
-
- CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
-
+
+ GetX509(obj, x509);
+
+ X509_up_ref(x509);
+
return x509;
}
/*
* Private
*/
-static VALUE
+static VALUE
ossl_x509_alloc(VALUE klass)
{
X509 *x509;
VALUE obj;
+ obj = NewX509(klass);
x509 = X509_new();
if (!x509) ossl_raise(eX509CertError, NULL);
-
- WrapX509(klass, obj, x509);
+ SetX509(obj, x509);
return obj;
}
-static VALUE
+/*
+ * call-seq:
+ * Certificate.new => cert
+ * Certificate.new(string) => cert
+ */
+static VALUE
ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
{
BIO *in;
- X509 *x509;
+ X509 *x509, *x509_orig = RTYPEDDATA_DATA(self);
VALUE arg;
+ rb_check_frozen(self);
if (rb_scan_args(argc, argv, "01", &arg) == 0) {
- /* create just empty X509Cert */
- return self;
+ /* create just empty X509Cert */
+ return self;
}
arg = ossl_to_der_if_possible(arg);
- in = ossl_obj2bio(arg);
- x509 = PEM_read_bio_X509(in, (X509 **)&DATA_PTR(self), NULL, NULL);
+ in = ossl_obj2bio(&arg);
+ x509 = d2i_X509_bio(in, NULL);
if (!x509) {
- BIO_reset(in);
- x509 = d2i_X509_bio(in, (X509 **)&DATA_PTR(self));
+ OSSL_BIO_reset(in);
+ x509 = PEM_read_bio_X509(in, NULL, NULL, NULL);
}
BIO_free(in);
- if (!x509) ossl_raise(eX509CertError, NULL);
-
+ if (!x509)
+ ossl_raise(eX509CertError, "PEM_read_bio_X509");
+
+ RTYPEDDATA_DATA(self) = x509;
+ X509_free(x509_orig);
+
return self;
}
+/* :nodoc: */
static VALUE
ossl_x509_copy(VALUE self, VALUE other)
{
X509 *a, *b, *x509;
-
+
rb_check_frozen(self);
if (self == other) return self;
GetX509(self, a);
- SafeGetX509(other, b);
+ GetX509(other, b);
x509 = X509_dup(b);
if (!x509) ossl_raise(eX509CertError, NULL);
-
+
DATA_PTR(self) = x509;
X509_free(a);
return self;
}
-static VALUE
+/*
+ * call-seq:
+ * cert.to_der => string
+ */
+static VALUE
ossl_x509_to_der(VALUE self)
{
X509 *x509;
@@ -179,51 +171,59 @@ ossl_x509_to_der(VALUE self)
GetX509(self, x509);
if ((len = i2d_X509(x509, NULL)) <= 0)
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = (unsigned char *)RSTRING_PTR(str);
if (i2d_X509(x509, &p) <= 0)
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
ossl_str_adjust(str, p);
-
+
return str;
}
-static VALUE
+/*
+ * call-seq:
+ * cert.to_pem => string
+ */
+static VALUE
ossl_x509_to_pem(VALUE self)
{
X509 *x509;
BIO *out;
VALUE str;
-
+
GetX509(self, x509);
out = BIO_new(BIO_s_mem());
if (!out) ossl_raise(eX509CertError, NULL);
if (!PEM_write_bio_X509(out, x509)) {
- BIO_free(out);
- ossl_raise(eX509CertError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509CertError, NULL);
}
str = ossl_membio2str(out);
return str;
}
+/*
+ * call-seq:
+ * cert.to_text => string
+ */
static VALUE
ossl_x509_to_text(VALUE self)
{
X509 *x509;
BIO *out;
VALUE str;
-
+
GetX509(self, x509);
out = BIO_new(BIO_s_mem());
if (!out) ossl_raise(eX509CertError, NULL);
if (!X509_print(out, x509)) {
- BIO_free(out);
- ossl_raise(eX509CertError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509CertError, NULL);
}
str = ossl_membio2str(out);
@@ -234,7 +234,7 @@ ossl_x509_to_text(VALUE self)
/*
* Makes from X509 X509_REQuest
*/
-static VALUE
+static VALUE
ossl_x509_to_req(VALUE self)
{
X509 *x509;
@@ -243,7 +243,7 @@ ossl_x509_to_req(VALUE self)
GetX509(self, x509);
if (!(req = X509_to_X509_REQ(x509, NULL, EVP_md5()))) {
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
obj = ossl_x509req_new(req);
X509_REQ_free(req);
@@ -252,189 +252,247 @@ ossl_x509_to_req(VALUE self)
}
#endif
-static VALUE
+/*
+ * call-seq:
+ * cert.version => integer
+ */
+static VALUE
ossl_x509_get_version(VALUE self)
{
X509 *x509;
GetX509(self, x509);
-
+
return LONG2NUM(X509_get_version(x509));
}
-static VALUE
+/*
+ * call-seq:
+ * cert.version = integer => integer
+ */
+static VALUE
ossl_x509_set_version(VALUE self, VALUE version)
{
X509 *x509;
long ver;
if ((ver = NUM2LONG(version)) < 0) {
- ossl_raise(eX509CertError, "version must be >= 0!");
+ ossl_raise(eX509CertError, "version must be >= 0!");
}
GetX509(self, x509);
if (!X509_set_version(x509, ver)) {
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return version;
}
-static VALUE
+/*
+ * call-seq:
+ * cert.serial => integer
+ */
+static VALUE
ossl_x509_get_serial(VALUE self)
{
X509 *x509;
GetX509(self, x509);
-
+
return asn1integer_to_num(X509_get_serialNumber(x509));
}
-static VALUE
+/*
+ * call-seq:
+ * cert.serial = integer => integer
+ */
+static VALUE
ossl_x509_set_serial(VALUE self, VALUE num)
{
X509 *x509;
GetX509(self, x509);
+ if (!X509_set_serialNumber(x509, num_to_asn1integer(num, X509_get_serialNumber(x509)))) {
+ ossl_raise(eX509CertError, NULL);
+ }
- x509->cert_info->serialNumber =
- num_to_asn1integer(num, X509_get_serialNumber(x509));
-
return num;
}
-static VALUE
+/*
+ * call-seq:
+ * cert.signature_algorithm => string
+ *
+ * Returns the signature algorithm used to sign this certificate. This returns
+ * the algorithm name found in the TBSCertificate structure, not the outer
+ * \Certificate structure.
+ *
+ * Returns the long name of the signature algorithm, or the dotted decimal
+ * notation if \OpenSSL does not define a long name for it.
+ */
+static VALUE
ossl_x509_get_signature_algorithm(VALUE self)
{
X509 *x509;
- BIO *out;
- VALUE str;
+ const ASN1_OBJECT *obj;
GetX509(self, x509);
- out = BIO_new(BIO_s_mem());
- if (!out) ossl_raise(eX509CertError, NULL);
-
- if (!i2a_ASN1_OBJECT(out, x509->cert_info->signature->algorithm)) {
- BIO_free(out);
- ossl_raise(eX509CertError, NULL);
- }
- str = ossl_membio2str(out);
-
- return str;
+ X509_ALGOR_get0(&obj, NULL, NULL, X509_get0_tbs_sigalg(x509));
+ return ossl_asn1obj_to_string_long_name(obj);
}
-static VALUE
+/*
+ * call-seq:
+ * cert.subject => name
+ */
+static VALUE
ossl_x509_get_subject(VALUE self)
{
X509 *x509;
- X509_NAME *name;
-
+ const X509_NAME *name;
+
GetX509(self, x509);
if (!(name = X509_get_subject_name(x509))) { /* NO DUP - don't free! */
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return ossl_x509name_new(name);
}
-static VALUE
+/*
+ * call-seq:
+ * cert.subject = name => name
+ */
+static VALUE
ossl_x509_set_subject(VALUE self, VALUE subject)
{
X509 *x509;
-
+
GetX509(self, x509);
if (!X509_set_subject_name(x509, GetX509NamePtr(subject))) { /* DUPs name */
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return subject;
}
-static VALUE
+/*
+ * call-seq:
+ * cert.issuer => name
+ */
+static VALUE
ossl_x509_get_issuer(VALUE self)
{
X509 *x509;
- X509_NAME *name;
+ const X509_NAME *name;
GetX509(self, x509);
if(!(name = X509_get_issuer_name(x509))) { /* NO DUP - don't free! */
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return ossl_x509name_new(name);
}
-static VALUE
+/*
+ * call-seq:
+ * cert.issuer = name => name
+ */
+static VALUE
ossl_x509_set_issuer(VALUE self, VALUE issuer)
{
X509 *x509;
GetX509(self, x509);
if (!X509_set_issuer_name(x509, GetX509NamePtr(issuer))) { /* DUPs name */
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return issuer;
}
-static VALUE
+/*
+ * call-seq:
+ * cert.not_before => time
+ */
+static VALUE
ossl_x509_get_not_before(VALUE self)
{
X509 *x509;
- ASN1_UTCTIME *asn1time;
+ const ASN1_TIME *asn1time;
GetX509(self, x509);
- if (!(asn1time = X509_get_notBefore(x509))) { /* NO DUP - don't free! */
- ossl_raise(eX509CertError, NULL);
+ if (!(asn1time = X509_get0_notBefore(x509))) {
+ ossl_raise(eX509CertError, NULL);
}
return asn1time_to_time(asn1time);
}
-static VALUE
+/*
+ * call-seq:
+ * cert.not_before = time => time
+ */
+static VALUE
ossl_x509_set_not_before(VALUE self, VALUE time)
{
X509 *x509;
- time_t sec;
-
- sec = time_to_time_t(time);
+ ASN1_TIME *asn1time;
+
GetX509(self, x509);
- if (!X509_time_adj(X509_get_notBefore(x509), 0, &sec)) {
- ossl_raise(eX509CertError, NULL);
+ asn1time = ossl_x509_time_adjust(NULL, time);
+ if (!X509_set1_notBefore(x509, asn1time)) {
+ ASN1_TIME_free(asn1time);
+ ossl_raise(eX509CertError, "X509_set_notBefore");
}
+ ASN1_TIME_free(asn1time);
return time;
}
-static VALUE
+/*
+ * call-seq:
+ * cert.not_after => time
+ */
+static VALUE
ossl_x509_get_not_after(VALUE self)
{
X509 *x509;
- ASN1_TIME *asn1time;
+ const ASN1_TIME *asn1time;
GetX509(self, x509);
- if (!(asn1time = X509_get_notAfter(x509))) { /* NO DUP - don't free! */
- ossl_raise(eX509CertError, NULL);
+ if (!(asn1time = X509_get0_notAfter(x509))) {
+ ossl_raise(eX509CertError, NULL);
}
return asn1time_to_time(asn1time);
}
-static VALUE
+/*
+ * call-seq:
+ * cert.not_after = time => time
+ */
+static VALUE
ossl_x509_set_not_after(VALUE self, VALUE time)
{
X509 *x509;
- time_t sec;
-
- sec = time_to_time_t(time);
+ ASN1_TIME *asn1time;
+
GetX509(self, x509);
- if (!X509_time_adj(X509_get_notAfter(x509), 0, &sec)) {
- ossl_raise(eX509CertError, NULL);
+ asn1time = ossl_x509_time_adjust(NULL, time);
+ if (!X509_set1_notAfter(x509, asn1time)) {
+ ASN1_TIME_free(asn1time);
+ ossl_raise(eX509CertError, "X509_set_notAfter");
}
+ ASN1_TIME_free(asn1time);
return time;
}
-static VALUE
+/*
+ * call-seq:
+ * cert.public_key => key
+ */
+static VALUE
ossl_x509_get_public_key(VALUE self)
{
X509 *x509;
@@ -442,205 +500,488 @@ ossl_x509_get_public_key(VALUE self)
GetX509(self, x509);
if (!(pkey = X509_get_pubkey(x509))) { /* adds an reference */
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
- return ossl_pkey_new(pkey); /* NO DUP - OK */
+ return ossl_pkey_wrap(pkey);
}
-static VALUE
+/*
+ * call-seq:
+ * cert.public_key = key
+ */
+static VALUE
ossl_x509_set_public_key(VALUE self, VALUE key)
{
X509 *x509;
+ EVP_PKEY *pkey;
GetX509(self, x509);
- if (!X509_set_pubkey(x509, GetPKeyPtr(key))) { /* DUPs pkey */
- ossl_raise(eX509CertError, NULL);
- }
-
+ pkey = GetPKeyPtr(key);
+ ossl_pkey_check_public_key(pkey);
+ if (!X509_set_pubkey(x509, pkey))
+ ossl_raise(eX509CertError, "X509_set_pubkey");
return key;
}
-static VALUE
+/*
+ * call-seq:
+ * cert.sign(key, digest) => self
+ */
+static VALUE
ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
{
X509 *x509;
EVP_PKEY *pkey;
const EVP_MD *md;
+ VALUE md_holder;
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
- md = GetDigestPtr(digest);
+ /* NULL needed for some key types, e.g. Ed25519 */
+ md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder);
GetX509(self, x509);
- if (!X509_sign(x509, pkey, md)) {
- ossl_raise(eX509CertError, NULL);
- }
+ if (!X509_sign(x509, pkey, md))
+ ossl_raise(eX509CertError, "X509_sign");
return self;
}
/*
- * Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
+ * call-seq:
+ * cert.verify(key) => true | false
+ *
+ * Verifies the signature of the certificate, with the public key _key_. _key_
+ * must be an instance of OpenSSL::PKey.
*/
-static VALUE
+static VALUE
ossl_x509_verify(VALUE self, VALUE key)
{
X509 *x509;
EVP_PKEY *pkey;
- int i;
- pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
GetX509(self, x509);
- if ((i = X509_verify(x509, pkey)) < 0) {
- ossl_raise(eX509CertError, NULL);
- }
- if (i > 0) {
- return Qtrue;
+ pkey = GetPKeyPtr(key);
+ ossl_pkey_check_public_key(pkey);
+ switch (X509_verify(x509, pkey)) {
+ case 1:
+ return Qtrue;
+ case 0:
+ ossl_clear_error();
+ return Qfalse;
+ default:
+ ossl_raise(eX509CertError, NULL);
}
-
- return Qfalse;
}
/*
- * Checks if 'key' is PRIV key for this cert
+ * call-seq:
+ * cert.check_private_key(key) -> true | false
+ *
+ * Returns +true+ if _key_ is the corresponding private key to the Subject
+ * Public Key Information, +false+ otherwise.
*/
-static VALUE
+static VALUE
ossl_x509_check_private_key(VALUE self, VALUE key)
{
X509 *x509;
EVP_PKEY *pkey;
-
+
/* not needed private key, but should be */
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
GetX509(self, x509);
if (!X509_check_private_key(x509, pkey)) {
- OSSL_Warning("Check private key:%s", OSSL_ErrMsg());
- return Qfalse;
+ ossl_clear_error();
+ return Qfalse;
}
return Qtrue;
}
/*
- * Gets X509v3 extensions as array of X509Ext objects
+ * call-seq:
+ * cert.extensions => [extension...]
*/
-static VALUE
+static VALUE
ossl_x509_get_extensions(VALUE self)
{
X509 *x509;
int count, i;
- X509_EXTENSION *ext;
VALUE ary;
GetX509(self, x509);
count = X509_get_ext_count(x509);
- if (count < 0) {
- return rb_ary_new();
- }
- ary = rb_ary_new2(count);
+ ary = rb_ary_new_capa(count);
for (i=0; i<count; i++) {
- ext = X509_get_ext(x509, i); /* NO DUP - don't free! */
- rb_ary_push(ary, ossl_x509ext_new(ext));
+ const X509_EXTENSION *ext = X509_get_ext(x509, i);
+ rb_ary_push(ary, ossl_x509ext_new(ext));
}
return ary;
}
/*
- * Sets X509_EXTENSIONs
+ * call-seq:
+ * cert.extensions = [ext...] => [ext...]
*/
-static VALUE
+static VALUE
ossl_x509_set_extensions(VALUE self, VALUE ary)
{
X509 *x509;
X509_EXTENSION *ext;
- int i;
-
+ long i;
+
Check_Type(ary, T_ARRAY);
/* All ary's members should be X509Extension */
- for (i=0; i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
}
GetX509(self, x509);
- sk_X509_EXTENSION_pop_free(x509->cert_info->extensions, X509_EXTENSION_free);
- x509->cert_info->extensions = NULL;
- for (i=0; i<RARRAY(ary)->len; i++) {
- ext = DupX509ExtPtr(RARRAY(ary)->ptr[i]);
-
- if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
- X509_EXTENSION_free(ext);
- ossl_raise(eX509CertError, NULL);
- }
- X509_EXTENSION_free(ext);
+ for (i = X509_get_ext_count(x509); i > 0; i--)
+ X509_EXTENSION_free(X509_delete_ext(x509, 0));
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ ext = GetX509ExtPtr(RARRAY_AREF(ary, i));
+ if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */
+ ossl_raise(eX509CertError, "X509_add_ext");
+ }
}
return ary;
}
-static VALUE
+/*
+ * call-seq:
+ * cert.add_extension(extension) => extension
+ */
+static VALUE
ossl_x509_add_extension(VALUE self, VALUE extension)
{
X509 *x509;
X509_EXTENSION *ext;
-
+
GetX509(self, x509);
- ext = DupX509ExtPtr(extension);
+ ext = GetX509ExtPtr(extension);
if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
- X509_EXTENSION_free(ext);
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
- X509_EXTENSION_free(ext);
return extension;
}
+/*
+ * call-seq:
+ * cert1 == cert2 -> true | false
+ *
+ * Compares the two certificates. Note that this takes into account all fields,
+ * not just the issuer name and the serial number.
+ *
+ * This method uses X509_cmp() from OpenSSL, which compares certificates based
+ * on their cached DER encodings. The comparison can be unreliable if a
+ * certificate is incomplete.
+ *
+ * See also the man page X509_cmp(3).
+ */
+static VALUE
+ossl_x509_eq(VALUE self, VALUE other)
+{
+ X509 *a, *b;
+
+ GetX509(self, a);
+ if (!rb_obj_is_kind_of(other, cX509Cert))
+ return Qfalse;
+ GetX509(other, b);
+
+ return !X509_cmp(a, b) ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * cert.tbs_bytes => string
+ *
+ * Returns the DER-encoded bytes of the certificate's to be signed certificate.
+ * This is mainly useful for validating embedded certificate transparency signatures.
+ */
static VALUE
-ossl_x509_inspect(VALUE self)
+ossl_x509_tbs_bytes(VALUE self)
{
+ X509 *x509;
+ int len;
+ unsigned char *p0;
VALUE str;
- char *cname = rb_class2name(rb_obj_class(self));
- str = rb_str_new2("#<");
- rb_str_cat2(str, cname);
- rb_str_cat2(str, " ");
+ GetX509(self, x509);
+ len = i2d_re_X509_tbs(x509, NULL);
+ if (len <= 0) {
+ ossl_raise(eX509CertError, "i2d_re_X509_tbs");
+ }
+ str = rb_str_new(NULL, len);
+ p0 = (unsigned char *)RSTRING_PTR(str);
+ if (i2d_re_X509_tbs(x509, &p0) <= 0) {
+ ossl_raise(eX509CertError, "i2d_re_X509_tbs");
+ }
+ ossl_str_adjust(str, p0);
- rb_str_cat2(str, "subject=");
- rb_str_append(str, rb_inspect(ossl_x509_get_subject(self)));
- rb_str_cat2(str, ", ");
+ return str;
+}
- rb_str_cat2(str, "issuer=");
- rb_str_append(str, rb_inspect(ossl_x509_get_issuer(self)));
- rb_str_cat2(str, ", ");
+struct load_chained_certificates_arguments {
+ VALUE certificates;
+ X509 *certificate;
+};
- rb_str_cat2(str, "serial=");
- rb_str_append(str, rb_inspect(ossl_x509_get_serial(self)));
- rb_str_cat2(str, ", ");
+static VALUE
+load_chained_certificates_append_push(VALUE _arguments) {
+ struct load_chained_certificates_arguments *arguments = (struct load_chained_certificates_arguments*)_arguments;
- rb_str_cat2(str, "not_before=");
- rb_str_append(str, rb_inspect(ossl_x509_get_not_before(self)));
- rb_str_cat2(str, ", ");
+ if (arguments->certificates == Qnil) {
+ arguments->certificates = rb_ary_new();
+ }
- rb_str_cat2(str, "not_after=");
- rb_str_append(str, rb_inspect(ossl_x509_get_not_after(self)));
+ rb_ary_push(arguments->certificates, ossl_x509_new(arguments->certificate));
- str = rb_str_cat2(str, ">");
+ return Qnil;
+}
- return str;
+static VALUE
+load_chained_certificate_append_ensure(VALUE _arguments) {
+ struct load_chained_certificates_arguments *arguments = (struct load_chained_certificates_arguments*)_arguments;
+
+ X509_free(arguments->certificate);
+
+ return Qnil;
+}
+
+inline static VALUE
+load_chained_certificates_append(VALUE certificates, X509 *certificate) {
+ struct load_chained_certificates_arguments arguments;
+ arguments.certificates = certificates;
+ arguments.certificate = certificate;
+
+ rb_ensure(load_chained_certificates_append_push, (VALUE)&arguments, load_chained_certificate_append_ensure, (VALUE)&arguments);
+
+ return arguments.certificates;
+}
+
+static VALUE
+load_chained_certificates_PEM(BIO *in) {
+ VALUE certificates = Qnil;
+ X509 *certificate = PEM_read_bio_X509(in, NULL, NULL, NULL);
+
+ /* If we cannot read even one certificate: */
+ if (certificate == NULL) {
+ /* If we cannot read one certificate because we could not read the PEM encoding: */
+ if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
+ ossl_clear_error();
+ }
+
+ if (ERR_peek_last_error())
+ ossl_raise(eX509CertError, NULL);
+ else
+ return Qnil;
+ }
+
+ certificates = load_chained_certificates_append(Qnil, certificate);
+
+ while ((certificate = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
+ load_chained_certificates_append(certificates, certificate);
+ }
+
+ /* We tried to read one more certificate but could not read start line: */
+ if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
+ /* This is not an error, it means we are finished: */
+ ossl_clear_error();
+
+ return certificates;
+ }
+
+ /* Alternatively, if we reached the end of the file and there was no error: */
+ if (BIO_eof(in) && !ERR_peek_last_error()) {
+ return certificates;
+ } else {
+ /* Otherwise, we tried to read a certificate but failed somewhere: */
+ ossl_raise(eX509CertError, NULL);
+ }
+}
+
+static VALUE
+load_chained_certificates_DER(BIO *in) {
+ X509 *certificate = d2i_X509_bio(in, NULL);
+
+ /* If we cannot read one certificate: */
+ if (certificate == NULL) {
+ /* Ignore error. We could not load. */
+ ossl_clear_error();
+
+ return Qnil;
+ }
+
+ return load_chained_certificates_append(Qnil, certificate);
+}
+
+static VALUE
+load_chained_certificates(VALUE _io) {
+ BIO *in = (BIO*)_io;
+ VALUE certificates = Qnil;
+
+ /*
+ DER is a binary format and it may contain octets within it that look like
+ PEM encoded certificates. So we need to check DER first.
+ */
+ certificates = load_chained_certificates_DER(in);
+
+ if (certificates != Qnil)
+ return certificates;
+
+ OSSL_BIO_reset(in);
+
+ certificates = load_chained_certificates_PEM(in);
+
+ if (certificates != Qnil)
+ return certificates;
+
+ /* Otherwise we couldn't read the output correctly so fail: */
+ ossl_raise(eX509CertError, "Could not detect format of certificate data!");
+}
+
+static VALUE
+load_chained_certificates_ensure(VALUE _io) {
+ BIO *in = (BIO*)_io;
+
+ BIO_free(in);
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * OpenSSL::X509::Certificate.load(string) -> [certs...]
+ * OpenSSL::X509::Certificate.load(file) -> [certs...]
+ *
+ * Read the chained certificates from the given input. Supports both PEM
+ * and DER encoded certificates.
+ *
+ * PEM is a text format and supports more than one certificate.
+ *
+ * DER is a binary format and only supports one certificate.
+ *
+ * If the file is empty, or contains only unrelated data, an
+ * +OpenSSL::X509::CertificateError+ exception will be raised.
+ */
+static VALUE
+ossl_x509_load(VALUE klass, VALUE buffer)
+{
+ BIO *in = ossl_obj2bio(&buffer);
+
+ return rb_ensure(load_chained_certificates, (VALUE)in, load_chained_certificates_ensure, (VALUE)in);
}
/*
* INIT
*/
-void
-Init_ossl_x509cert()
+void
+Init_ossl_x509cert(void)
{
eX509CertError = rb_define_class_under(mX509, "CertificateError", eOSSLError);
-
+
+ /* Document-class: OpenSSL::X509::Certificate
+ *
+ * Implementation of an X.509 certificate as specified in RFC 5280.
+ * Provides access to a certificate's attributes and allows certificates
+ * to be read from a string, but also supports the creation of new
+ * certificates from scratch.
+ *
+ * === Reading a certificate from a file
+ *
+ * Certificate is capable of handling DER-encoded certificates and
+ * certificates encoded in OpenSSL's PEM format.
+ *
+ * raw = File.binread "cert.cer" # DER- or PEM-encoded
+ * certificate = OpenSSL::X509::Certificate.new raw
+ *
+ * === Saving a certificate to a file
+ *
+ * A certificate may be encoded in DER format
+ *
+ * cert = ...
+ * File.open("cert.cer", "wb") { |f| f.print cert.to_der }
+ *
+ * or in PEM format
+ *
+ * cert = ...
+ * File.open("cert.pem", "wb") { |f| f.print cert.to_pem }
+ *
+ * X.509 certificates are associated with a private/public key pair,
+ * typically a RSA, DSA or ECC key (see also OpenSSL::PKey::RSA,
+ * OpenSSL::PKey::DSA and OpenSSL::PKey::EC), the public key itself is
+ * stored within the certificate and can be accessed in form of an
+ * OpenSSL::PKey. Certificates are typically used to be able to associate
+ * some form of identity with a key pair, for example web servers serving
+ * pages over HTTPs use certificates to authenticate themselves to the user.
+ *
+ * The public key infrastructure (PKI) model relies on trusted certificate
+ * authorities ("root CAs") that issue these certificates, so that end
+ * users need to base their trust just on a selected few authorities
+ * that themselves again vouch for subordinate CAs issuing their
+ * certificates to end users.
+ *
+ * The OpenSSL::X509 module provides the tools to set up an independent
+ * PKI, similar to scenarios where the 'openssl' command line tool is
+ * used for issuing certificates in a private PKI.
+ *
+ * === Creating a root CA certificate and an end-entity certificate
+ *
+ * First, we need to create a "self-signed" root certificate. To do so,
+ * we need to generate a key first. Please note that the choice of "1"
+ * as a serial number is considered a security flaw for real certificates.
+ * Secure choices are integers in the two-digit byte range and ideally
+ * not sequential but secure random numbers, steps omitted here to keep
+ * the example concise.
+ *
+ * root_key = OpenSSL::PKey::RSA.new 2048 # the CA's public/private key
+ * root_ca = OpenSSL::X509::Certificate.new
+ * root_ca.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
+ * root_ca.serial = 1
+ * root_ca.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby CA"
+ * root_ca.issuer = root_ca.subject # root CA's are "self-signed"
+ * root_ca.public_key = root_key.public_key
+ * root_ca.not_before = Time.now
+ * root_ca.not_after = root_ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity
+ * ef = OpenSSL::X509::ExtensionFactory.new
+ * ef.subject_certificate = root_ca
+ * ef.issuer_certificate = root_ca
+ * root_ca.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
+ * root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
+ * root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
+ * root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
+ * root_ca.sign(root_key, OpenSSL::Digest.new('SHA256'))
+ *
+ * The next step is to create the end-entity certificate using the root CA
+ * certificate.
+ *
+ * key = OpenSSL::PKey::RSA.new 2048
+ * cert = OpenSSL::X509::Certificate.new
+ * cert.version = 2
+ * cert.serial = 2
+ * cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby certificate"
+ * cert.issuer = root_ca.subject # root CA is the issuer
+ * cert.public_key = key.public_key
+ * cert.not_before = Time.now
+ * cert.not_after = cert.not_before + 1 * 365 * 24 * 60 * 60 # 1 years validity
+ * ef = OpenSSL::X509::ExtensionFactory.new
+ * ef.subject_certificate = cert
+ * ef.issuer_certificate = root_ca
+ * cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true))
+ * cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
+ * cert.sign(root_key, OpenSSL::Digest.new('SHA256'))
+ *
+ */
cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject);
-
+
+ rb_define_singleton_method(cX509Cert, "load", ossl_x509_load, 1);
+
rb_define_alloc_func(cX509Cert, ossl_x509_alloc);
rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1);
- rb_define_copy_func(cX509Cert, ossl_x509_copy);
-
+ rb_define_method(cX509Cert, "initialize_copy", ossl_x509_copy, 1);
+
rb_define_method(cX509Cert, "to_der", ossl_x509_to_der, 0);
rb_define_method(cX509Cert, "to_pem", ossl_x509_to_pem, 0);
rb_define_alias(cX509Cert, "to_s", "to_pem");
@@ -666,6 +1007,6 @@ Init_ossl_x509cert()
rb_define_method(cX509Cert, "extensions", ossl_x509_get_extensions, 0);
rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1);
rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1);
- rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
+ rb_define_method(cX509Cert, "==", ossl_x509_eq, 1);
+ rb_define_method(cX509Cert, "tbs_bytes", ossl_x509_tbs_bytes, 0);
}
-
diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c
index 0dc22416e7..9b59bda9e2 100644
--- a/ext/openssl/ossl_x509crl.c
+++ b/ext/openssl/ossl_x509crl.c
@@ -1,37 +1,48 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#define WrapX509CRL(klass, obj, crl) do { \
- if (!crl) { \
- ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
+#define NewX509CRL(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_x509crl_type, 0)
+#define SetX509CRL(obj, crl) do { \
+ if (!(crl)) { \
+ ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
} \
- obj = Data_Wrap_Struct(klass, 0, X509_CRL_free, crl); \
+ RTYPEDDATA_DATA(obj) = (crl); \
} while (0)
#define GetX509CRL(obj, crl) do { \
- Data_Get_Struct(obj, X509_CRL, crl); \
- if (!crl) { \
- ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
+ TypedData_Get_Struct((obj), X509_CRL, &ossl_x509crl_type, (crl)); \
+ if (!(crl)) { \
+ ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
} \
} while (0)
-#define SafeGetX509CRL(obj, crl) do { \
- OSSL_Check_Kind(obj, cX509CRL); \
- GetX509CRL(obj, crl); \
-} while (0)
/*
* Classes
*/
-VALUE cX509CRL;
-VALUE eX509CRLError;
+static VALUE cX509CRL;
+static VALUE eX509CRLError;
+
+static void
+ossl_x509crl_free(void *ptr)
+{
+ X509_CRL_free(ptr);
+}
+
+static const rb_data_type_t ossl_x509crl_type = {
+ "OpenSSL/X509/CRL",
+ {
+ 0, ossl_x509crl_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
/*
* PUBLIC
@@ -41,86 +52,85 @@ GetX509CRLPtr(VALUE obj)
{
X509_CRL *crl;
- SafeGetX509CRL(obj, crl);
-
- return crl;
-}
-
-X509_CRL *
-DupX509CRLPtr(VALUE obj)
-{
- X509_CRL *crl;
-
- SafeGetX509CRL(obj, crl);
- CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL);
+ GetX509CRL(obj, crl);
return crl;
}
VALUE
-ossl_x509crl_new(X509_CRL *crl)
+ossl_x509crl_new(const X509_CRL *crl)
{
X509_CRL *tmp;
VALUE obj;
- tmp = crl ? X509_CRL_dup(crl) : X509_CRL_new();
- if(!tmp) ossl_raise(eX509CRLError, NULL);
- WrapX509CRL(cX509CRL, obj, tmp);
-
+ obj = NewX509CRL(cX509CRL);
+ /* OpenSSL 1.1.1 takes a non-const pointer */
+ tmp = X509_CRL_dup((X509_CRL *)crl);
+ if (!tmp)
+ ossl_raise(eX509CRLError, "X509_CRL_dup");
+ SetX509CRL(obj, tmp);
+
return obj;
}
/*
* PRIVATE
*/
-static VALUE
+static VALUE
ossl_x509crl_alloc(VALUE klass)
{
X509_CRL *crl;
VALUE obj;
+ obj = NewX509CRL(klass);
if (!(crl = X509_CRL_new())) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
- WrapX509CRL(klass, obj, crl);
+ SetX509CRL(obj, crl);
return obj;
}
-static VALUE
+static VALUE
ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self)
{
BIO *in;
- X509_CRL *crl;
+ X509_CRL *crl, *crl_orig = RTYPEDDATA_DATA(self);
VALUE arg;
+ rb_check_frozen(self);
if (rb_scan_args(argc, argv, "01", &arg) == 0) {
- return self;
+ return self;
}
arg = ossl_to_der_if_possible(arg);
- in = ossl_obj2bio(arg);
- crl = PEM_read_bio_X509_CRL(in, (X509_CRL **)&DATA_PTR(self), NULL, NULL);
+ in = ossl_obj2bio(&arg);
+ crl = d2i_X509_CRL_bio(in, NULL);
if (!crl) {
- BIO_reset(in);
- crl = d2i_X509_CRL_bio(in, (X509_CRL **)&DATA_PTR(self));
+ OSSL_BIO_reset(in);
+ crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
}
BIO_free(in);
- if (!crl) ossl_raise(eX509CRLError, NULL);
+ if (!crl)
+ ossl_raise(eX509CRLError, "PEM_read_bio_X509_CRL");
+
+ RTYPEDDATA_DATA(self) = crl;
+ X509_CRL_free(crl_orig);
return self;
}
+/* :nodoc: */
static VALUE
ossl_x509crl_copy(VALUE self, VALUE other)
{
X509_CRL *a, *b, *crl;
-
+
rb_check_frozen(self);
if (self == other) return self;
GetX509CRL(self, a);
- SafeGetX509CRL(other, b);
+ GetX509CRL(other, b);
if (!(crl = X509_CRL_dup(b))) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
X509_CRL_free(a);
DATA_PTR(self) = crl;
@@ -128,7 +138,7 @@ ossl_x509crl_copy(VALUE self, VALUE other)
return self;
}
-static VALUE
+static VALUE
ossl_x509crl_get_version(VALUE self)
{
X509_CRL *crl;
@@ -140,46 +150,46 @@ ossl_x509crl_get_version(VALUE self)
return LONG2NUM(ver);
}
-static VALUE
+static VALUE
ossl_x509crl_set_version(VALUE self, VALUE version)
{
X509_CRL *crl;
long ver;
if ((ver = NUM2LONG(version)) < 0) {
- ossl_raise(eX509CRLError, "version must be >= 0!");
+ ossl_raise(eX509CRLError, "version must be >= 0!");
}
GetX509CRL(self, crl);
if (!X509_CRL_set_version(crl, ver)) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
return version;
}
-static VALUE
+/*
+ * call-seq:
+ * crl.signature_algorithm -> string
+ *
+ * Returns the signature algorithm used to sign this CRL.
+ *
+ * Returns the long name of the signature algorithm, or the dotted decimal
+ * notation if \OpenSSL does not define a long name for it.
+ */
+static VALUE
ossl_x509crl_get_signature_algorithm(VALUE self)
{
X509_CRL *crl;
- BIO *out;
- BUF_MEM *buf;
- VALUE str;
+ const X509_ALGOR *alg;
+ const ASN1_OBJECT *obj;
GetX509CRL(self, crl);
- if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509CRLError, NULL);
- }
- if (!i2a_ASN1_OBJECT(out, crl->sig_alg->algorithm)) {
- BIO_free(out);
- ossl_raise(eX509CRLError, NULL);
- }
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ X509_CRL_get0_signature(crl, NULL, &alg);
+ X509_ALGOR_get0(&obj, NULL, NULL, alg);
+ return ossl_asn1obj_to_string_long_name(obj);
}
-static VALUE
+static VALUE
ossl_x509crl_get_issuer(VALUE self)
{
X509_CRL *crl;
@@ -189,7 +199,7 @@ ossl_x509crl_get_issuer(VALUE self)
return ossl_x509name_new(X509_CRL_get_issuer(crl)); /* NO DUP - don't free */
}
-static VALUE
+static VALUE
ossl_x509crl_set_issuer(VALUE self, VALUE issuer)
{
X509_CRL *crl;
@@ -197,58 +207,69 @@ ossl_x509crl_set_issuer(VALUE self, VALUE issuer)
GetX509CRL(self, crl);
if (!X509_CRL_set_issuer_name(crl, GetX509NamePtr(issuer))) { /* DUPs name */
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
return issuer;
}
-static VALUE
+static VALUE
ossl_x509crl_get_last_update(VALUE self)
{
X509_CRL *crl;
+ const ASN1_TIME *time;
GetX509CRL(self, crl);
+ time = X509_CRL_get0_lastUpdate(crl);
+ if (!time)
+ return Qnil;
- return asn1time_to_time(X509_CRL_get_lastUpdate(crl));
+ return asn1time_to_time(time);
}
-static VALUE
+static VALUE
ossl_x509crl_set_last_update(VALUE self, VALUE time)
{
X509_CRL *crl;
- time_t sec;
+ ASN1_TIME *asn1time;
- sec = time_to_time_t(time);
GetX509CRL(self, crl);
- if (!X509_time_adj(crl->crl->lastUpdate, 0, &sec)) {
- ossl_raise(eX509CRLError, NULL);
+ asn1time = ossl_x509_time_adjust(NULL, time);
+ if (!X509_CRL_set1_lastUpdate(crl, asn1time)) {
+ ASN1_TIME_free(asn1time);
+ ossl_raise(eX509CRLError, "X509_CRL_set_lastUpdate");
}
+ ASN1_TIME_free(asn1time);
return time;
}
-static VALUE
+static VALUE
ossl_x509crl_get_next_update(VALUE self)
{
X509_CRL *crl;
+ const ASN1_TIME *time;
GetX509CRL(self, crl);
+ time = X509_CRL_get0_nextUpdate(crl);
+ if (!time)
+ return Qnil;
- return asn1time_to_time(X509_CRL_get_nextUpdate(crl));
+ return asn1time_to_time(time);
}
-static VALUE
+static VALUE
ossl_x509crl_set_next_update(VALUE self, VALUE time)
{
X509_CRL *crl;
- time_t sec;
+ ASN1_TIME *asn1time;
- sec = time_to_time_t(time);
GetX509CRL(self, crl);
- /* This must be some thinko in OpenSSL */
- if (!(crl->crl->nextUpdate = X509_time_adj(crl->crl->nextUpdate, 0, &sec))){
- ossl_raise(eX509CRLError, NULL);
+ asn1time = ossl_x509_time_adjust(NULL, time);
+ if (!X509_CRL_set1_nextUpdate(crl, asn1time)) {
+ ASN1_TIME_free(asn1time);
+ ossl_raise(eX509CRLError, "X509_CRL_set_nextUpdate");
}
+ ASN1_TIME_free(asn1time);
return time;
}
@@ -258,53 +279,55 @@ ossl_x509crl_get_revoked(VALUE self)
{
X509_CRL *crl;
int i, num;
- X509_REVOKED *rev;
- VALUE ary, revoked;
+ STACK_OF(X509_REVOKED) *sk;
+ VALUE ary;
GetX509CRL(self, crl);
- num = sk_X509_CRL_num(X509_CRL_get_REVOKED(crl));
- if (num < 0) {
- OSSL_Debug("num < 0???");
- return rb_ary_new();
- }
- ary = rb_ary_new2(num);
+ sk = X509_CRL_get_REVOKED(crl);
+ if (!sk)
+ return rb_ary_new();
+
+ num = sk_X509_REVOKED_num(sk);
+ ary = rb_ary_new_capa(num);
for(i=0; i<num; i++) {
- /* NO DUP - don't free! */
- rev = (X509_REVOKED *)sk_X509_CRL_value(X509_CRL_get_REVOKED(crl), i);
- revoked = ossl_x509revoked_new(rev);
- rb_ary_push(ary, revoked);
+ const X509_REVOKED *rev = sk_X509_REVOKED_value(sk, i);
+ rb_ary_push(ary, ossl_x509revoked_new(rev));
}
return ary;
}
-static VALUE
+static VALUE
ossl_x509crl_set_revoked(VALUE self, VALUE ary)
{
X509_CRL *crl;
X509_REVOKED *rev;
- int i;
+ STACK_OF(X509_REVOKED) *sk;
+ long i;
Check_Type(ary, T_ARRAY);
/* All ary members should be X509 Revoked */
- for (i=0; i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Rev);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Rev);
}
GetX509CRL(self, crl);
- sk_X509_REVOKED_pop_free(crl->crl->revoked, X509_REVOKED_free);
- crl->crl->revoked = NULL;
- for (i=0; i<RARRAY(ary)->len; i++) {
- rev = DupX509RevokedPtr(RARRAY(ary)->ptr[i]);
- if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
- ossl_raise(eX509CRLError, NULL);
- }
+ if ((sk = X509_CRL_get_REVOKED(crl))) {
+ while ((rev = sk_X509_REVOKED_pop(sk)))
+ X509_REVOKED_free(rev);
+ }
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ rev = DupX509RevokedPtr(RARRAY_AREF(ary, i));
+ if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
+ X509_REVOKED_free(rev);
+ ossl_raise(eX509CRLError, "X509_CRL_add0_revoked");
+ }
}
X509_CRL_sort(crl);
return ary;
}
-static VALUE
+static VALUE
ossl_x509crl_add_revoked(VALUE self, VALUE revoked)
{
X509_CRL *crl;
@@ -313,137 +336,122 @@ ossl_x509crl_add_revoked(VALUE self, VALUE revoked)
GetX509CRL(self, crl);
rev = DupX509RevokedPtr(revoked);
if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
- ossl_raise(eX509CRLError, NULL);
+ X509_REVOKED_free(rev);
+ ossl_raise(eX509CRLError, "X509_CRL_add0_revoked");
}
X509_CRL_sort(crl);
return revoked;
}
-static VALUE
+static VALUE
ossl_x509crl_sign(VALUE self, VALUE key, VALUE digest)
{
X509_CRL *crl;
EVP_PKEY *pkey;
const EVP_MD *md;
+ VALUE md_holder;
GetX509CRL(self, crl);
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
- md = GetDigestPtr(digest);
- if (!X509_CRL_sign(crl, pkey, md)) {
- ossl_raise(eX509CRLError, NULL);
- }
+ /* NULL needed for some key types, e.g. Ed25519 */
+ md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder);
+ if (!X509_CRL_sign(crl, pkey, md))
+ ossl_raise(eX509CRLError, "X509_CRL_sign");
return self;
}
-static VALUE
+static VALUE
ossl_x509crl_verify(VALUE self, VALUE key)
{
X509_CRL *crl;
- int ret;
+ EVP_PKEY *pkey;
GetX509CRL(self, crl);
- if ((ret = X509_CRL_verify(crl, GetPKeyPtr(key))) < 0) {
- ossl_raise(eX509CRLError, NULL);
+ pkey = GetPKeyPtr(key);
+ ossl_pkey_check_public_key(pkey);
+ switch (X509_CRL_verify(crl, pkey)) {
+ case 1:
+ return Qtrue;
+ case 0:
+ ossl_clear_error();
+ return Qfalse;
+ default:
+ ossl_raise(eX509CRLError, NULL);
}
- if (ret == 1) {
- return Qtrue;
- }
-
- return Qfalse;
}
-static VALUE
+static VALUE
ossl_x509crl_to_der(VALUE self)
{
X509_CRL *crl;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
if (!i2d_X509_CRL_bio(out, crl)) {
- BIO_free(out);
- ossl_raise(eX509CRLError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509CRLError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
-static VALUE
+static VALUE
ossl_x509crl_to_pem(VALUE self)
{
X509_CRL *crl;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
if (!PEM_write_bio_X509_CRL(out, crl)) {
- BIO_free(out);
- ossl_raise(eX509CRLError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509CRLError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
-static VALUE
+static VALUE
ossl_x509crl_to_text(VALUE self)
{
X509_CRL *crl;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
if (!X509_CRL_print(out, crl)) {
- BIO_free(out);
- ossl_raise(eX509CRLError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509CRLError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
-
- return str;
+
+ return ossl_membio2str(out);
}
/*
* Gets X509v3 extensions as array of X509Ext objects
*/
-static VALUE
+static VALUE
ossl_x509crl_get_extensions(VALUE self)
{
X509_CRL *crl;
int count, i;
- X509_EXTENSION *ext;
VALUE ary;
GetX509CRL(self, crl);
count = X509_CRL_get_ext_count(crl);
- if (count < 0) {
- OSSL_Debug("count < 0???");
- return rb_ary_new();
- }
- ary = rb_ary_new2(count);
+ ary = rb_ary_new_capa(count);
for (i=0; i<count; i++) {
- ext = X509_CRL_get_ext(crl, i); /* NO DUP - don't free! */
- rb_ary_push(ary, ossl_x509ext_new(ext));
+ const X509_EXTENSION *ext = X509_CRL_get_ext(crl, i);
+ rb_ary_push(ary, ossl_x509ext_new(ext));
}
return ary;
@@ -452,46 +460,42 @@ ossl_x509crl_get_extensions(VALUE self)
/*
* Sets X509_EXTENSIONs
*/
-static VALUE
+static VALUE
ossl_x509crl_set_extensions(VALUE self, VALUE ary)
{
X509_CRL *crl;
X509_EXTENSION *ext;
- int i;
-
+ long i;
+
Check_Type(ary, T_ARRAY);
/* All ary members should be X509 Extensions */
- for (i=0; i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
}
GetX509CRL(self, crl);
- sk_X509_EXTENSION_pop_free(crl->crl->extensions, X509_EXTENSION_free);
- crl->crl->extensions = NULL;
- for (i=0; i<RARRAY(ary)->len; i++) {
- ext = DupX509ExtPtr(RARRAY(ary)->ptr[i]);
- if(!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */
- X509_EXTENSION_free(ext);
- ossl_raise(eX509CRLError, NULL);
- }
- X509_EXTENSION_free(ext);
+ for (i = X509_CRL_get_ext_count(crl); i > 0; i--)
+ X509_EXTENSION_free(X509_CRL_delete_ext(crl, 0));
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ ext = GetX509ExtPtr(RARRAY_AREF(ary, i)); /* NO NEED TO DUP */
+ if (!X509_CRL_add_ext(crl, ext, -1)) {
+ ossl_raise(eX509CRLError, "X509_CRL_add_ext");
+ }
}
return ary;
}
-static VALUE
+static VALUE
ossl_x509crl_add_extension(VALUE self, VALUE extension)
{
X509_CRL *crl;
X509_EXTENSION *ext;
GetX509CRL(self, crl);
- ext = DupX509ExtPtr(extension);
- if (!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */
- X509_EXTENSION_free(ext);
- ossl_raise(eX509CRLError, NULL);
+ ext = GetX509ExtPtr(extension);
+ if (!X509_CRL_add_ext(crl, ext, -1)) {
+ ossl_raise(eX509CRLError, NULL);
}
- X509_EXTENSION_free(ext);
return extension;
}
@@ -499,17 +503,17 @@ ossl_x509crl_add_extension(VALUE self, VALUE extension)
/*
* INIT
*/
-void
-Init_ossl_x509crl()
+void
+Init_ossl_x509crl(void)
{
eX509CRLError = rb_define_class_under(mX509, "CRLError", eOSSLError);
cX509CRL = rb_define_class_under(mX509, "CRL", rb_cObject);
-
+
rb_define_alloc_func(cX509CRL, ossl_x509crl_alloc);
rb_define_method(cX509CRL, "initialize", ossl_x509crl_initialize, -1);
- rb_define_copy_func(cX509CRL, ossl_x509crl_copy);
-
+ rb_define_method(cX509CRL, "initialize_copy", ossl_x509crl_copy, 1);
+
rb_define_method(cX509CRL, "version", ossl_x509crl_get_version, 0);
rb_define_method(cX509CRL, "version=", ossl_x509crl_set_version, 1);
rb_define_method(cX509CRL, "signature_algorithm", ossl_x509crl_get_signature_algorithm, 0);
@@ -532,4 +536,3 @@ Init_ossl_x509crl()
rb_define_method(cX509CRL, "extensions=", ossl_x509crl_set_extensions, 1);
rb_define_method(cX509CRL, "add_extension", ossl_x509crl_add_extension, 1);
}
-
diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c
index 31ffec48fa..1fe727d3f1 100644
--- a/ext/openssl/ossl_x509ext.c
+++ b/ext/openssl/ossl_x509ext.c
@@ -1,41 +1,39 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#define WrapX509Ext(klass, obj, ext) do { \
- if (!ext) { \
- ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
+#define NewX509Ext(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_x509ext_type, 0)
+#define SetX509Ext(obj, ext) do { \
+ if (!(ext)) { \
+ ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
} \
- obj = Data_Wrap_Struct(klass, 0, X509_EXTENSION_free, ext); \
+ RTYPEDDATA_DATA(obj) = (ext); \
} while (0)
#define GetX509Ext(obj, ext) do { \
- Data_Get_Struct(obj, X509_EXTENSION, ext); \
- if (!ext) { \
- ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
+ TypedData_Get_Struct((obj), X509_EXTENSION, &ossl_x509ext_type, (ext)); \
+ if (!(ext)) { \
+ ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
} \
} while (0)
-#define SafeGetX509Ext(obj, ext) do { \
- OSSL_Check_Kind(obj, cX509Ext); \
- GetX509Ext(obj, ext); \
-} while (0)
#define MakeX509ExtFactory(klass, obj, ctx) do { \
- if (!(ctx = OPENSSL_malloc(sizeof(X509V3_CTX)))) \
+ (obj) = TypedData_Wrap_Struct((klass), &ossl_x509extfactory_type, 0); \
+ if (!((ctx) = OPENSSL_malloc(sizeof(X509V3_CTX)))) \
ossl_raise(rb_eRuntimeError, "CTX wasn't allocated!"); \
- X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, 0); \
- obj = Data_Wrap_Struct(klass, 0, ossl_x509extfactory_free, ctx); \
+ X509V3_set_ctx((ctx), NULL, NULL, NULL, NULL, 0); \
+ RTYPEDDATA_DATA(obj) = (ctx); \
} while (0)
#define GetX509ExtFactory(obj, ctx) do { \
- Data_Get_Struct(obj, X509V3_CTX, ctx); \
- if (!ctx) { \
- ossl_raise(rb_eRuntimeError, "CTX wasn't initialized!"); \
+ TypedData_Get_Struct((obj), X509V3_CTX, &ossl_x509extfactory_type, (ctx)); \
+ if (!(ctx)) { \
+ ossl_raise(rb_eRuntimeError, "CTX wasn't initialized!"); \
} \
} while (0)
@@ -43,28 +41,39 @@
* Classes
*/
VALUE cX509Ext;
-VALUE cX509ExtFactory;
-VALUE eX509ExtError;
+static VALUE cX509ExtFactory;
+static VALUE eX509ExtError;
+
+static void
+ossl_x509ext_free(void *ptr)
+{
+ X509_EXTENSION_free(ptr);
+}
+
+static const rb_data_type_t ossl_x509ext_type = {
+ "OpenSSL/X509/EXTENSION",
+ {
+ 0, ossl_x509ext_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
/*
* Public
*/
-VALUE
-ossl_x509ext_new(X509_EXTENSION *ext)
+VALUE
+ossl_x509ext_new(const X509_EXTENSION *ext)
{
X509_EXTENSION *new;
VALUE obj;
- if (!ext) {
- new = X509_EXTENSION_new();
- } else {
- new = X509_EXTENSION_dup(ext);
- }
- if (!new) {
- ossl_raise(eX509ExtError, NULL);
- }
- WrapX509Ext(cX509Ext, obj, new);
-
+ obj = NewX509Ext(cX509Ext);
+ /* OpenSSL 1.1.1 takes a non-const pointer */
+ new = X509_EXTENSION_dup((X509_EXTENSION *)ext);
+ if (!new)
+ ossl_raise(eX509ExtError, "X509_EXTENSION_dup");
+ SetX509Ext(obj, new);
+
return obj;
}
@@ -73,24 +82,11 @@ GetX509ExtPtr(VALUE obj)
{
X509_EXTENSION *ext;
- SafeGetX509Ext(obj, ext);
+ GetX509Ext(obj, ext);
return ext;
}
-X509_EXTENSION *
-DupX509ExtPtr(VALUE obj)
-{
- X509_EXTENSION *ext, *new;
-
- SafeGetX509Ext(obj, ext);
- if (!(new = X509_EXTENSION_dup(ext))) {
- ossl_raise(eX509ExtError, NULL);
- }
-
- return new;
-}
-
/*
* Private
*/
@@ -98,23 +94,32 @@ DupX509ExtPtr(VALUE obj)
* Ext factory
*/
static void
-ossl_x509extfactory_free(X509V3_CTX *ctx)
+ossl_x509extfactory_free(void *ctx)
{
OPENSSL_free(ctx);
}
-static VALUE
+static const rb_data_type_t ossl_x509extfactory_type = {
+ "OpenSSL/X509/EXTENSION/Factory",
+ {
+ 0, ossl_x509extfactory_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static VALUE
ossl_x509extfactory_alloc(VALUE klass)
{
X509V3_CTX *ctx;
VALUE obj;
MakeX509ExtFactory(klass, obj, ctx);
+ rb_iv_set(obj, "@config", Qnil);
return obj;
}
-static VALUE
+static VALUE
ossl_x509extfactory_set_issuer_cert(VALUE self, VALUE cert)
{
X509V3_CTX *ctx;
@@ -126,7 +131,7 @@ ossl_x509extfactory_set_issuer_cert(VALUE self, VALUE cert)
return cert;
}
-static VALUE
+static VALUE
ossl_x509extfactory_set_subject_cert(VALUE self, VALUE cert)
{
X509V3_CTX *ctx;
@@ -138,7 +143,7 @@ ossl_x509extfactory_set_subject_cert(VALUE self, VALUE cert)
return cert;
}
-static VALUE
+static VALUE
ossl_x509extfactory_set_subject_req(VALUE self, VALUE req)
{
X509V3_CTX *ctx;
@@ -150,7 +155,7 @@ ossl_x509extfactory_set_subject_req(VALUE self, VALUE req)
return req;
}
-static VALUE
+static VALUE
ossl_x509extfactory_set_crl(VALUE self, VALUE crl)
{
X509V3_CTX *ctx;
@@ -163,91 +168,70 @@ ossl_x509extfactory_set_crl(VALUE self, VALUE crl)
}
static VALUE
-ossl_x509extfactory_set_config(VALUE self, VALUE config)
-{
-#ifdef HAVE_X509V3_SET_NCONF
- X509V3_CTX *ctx;
- CONF *conf;
-
- GetX509ExtFactory(self, ctx);
- rb_iv_set(self, "@config", config);
- conf = GetConfigPtr(config); /* NO DUP NEEDED */
- X509V3_set_nconf(ctx, conf);
-
- return config;
-#else
- rb_notimplement();
-#endif
-}
-
-static VALUE
ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self)
{
/*X509V3_CTX *ctx;*/
VALUE issuer_cert, subject_cert, subject_req, crl;
-
+
/*GetX509ExtFactory(self, ctx);*/
rb_scan_args(argc, argv, "04",
- &issuer_cert, &subject_cert, &subject_req, &crl);
+ &issuer_cert, &subject_cert, &subject_req, &crl);
if (!NIL_P(issuer_cert))
- ossl_x509extfactory_set_issuer_cert(self, issuer_cert);
+ ossl_x509extfactory_set_issuer_cert(self, issuer_cert);
if (!NIL_P(subject_cert))
- ossl_x509extfactory_set_subject_cert(self, subject_cert);
+ ossl_x509extfactory_set_subject_cert(self, subject_cert);
if (!NIL_P(subject_req))
- ossl_x509extfactory_set_subject_req(self, subject_req);
+ ossl_x509extfactory_set_subject_req(self, subject_req);
if (!NIL_P(crl))
- ossl_x509extfactory_set_crl(self, crl);
+ ossl_x509extfactory_set_crl(self, crl);
return self;
}
/*
- * Array to X509_EXTENSION
- * Structure:
- * ["ln", "value", bool_critical] or
- * ["sn", "value", bool_critical] or
- * ["ln", "critical,value"] or the same for sn
- * ["ln", "value"] => not critical
+ * call-seq:
+ * ef.create_ext(ln_or_sn, "value", critical = false) -> X509::Extension
+ * ef.create_ext(ln_or_sn, "critical,value") -> X509::Extension
+ *
+ * Creates a new X509::Extension with passed values. See also x509v3_config(5).
*/
-static VALUE
+static VALUE
ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
{
X509V3_CTX *ctx;
X509_EXTENSION *ext;
VALUE oid, value, critical, valstr, obj;
int nid;
-#ifdef HAVE_X509V3_EXT_NCONF_NID
VALUE rconf;
CONF *conf;
-#else
- static LHASH *empty_lhash;
-#endif
+ const char *oid_cstr = NULL;
rb_scan_args(argc, argv, "21", &oid, &value, &critical);
- StringValue(oid);
StringValue(value);
if(NIL_P(critical)) critical = Qfalse;
- nid = OBJ_ln2nid(RSTRING(oid)->ptr);
- if(!nid) nid = OBJ_sn2nid(RSTRING(oid)->ptr);
- if(!nid) ossl_raise(eX509ExtError, "unknown OID `%s'", RSTRING(oid)->ptr);
+ oid_cstr = StringValueCStr(oid);
+ nid = OBJ_ln2nid(oid_cstr);
+ if (nid != NID_undef)
+ oid_cstr = OBJ_nid2sn(nid);
+
valstr = rb_str_new2(RTEST(critical) ? "critical," : "");
rb_str_append(valstr, value);
+ StringValueCStr(valstr);
+
GetX509ExtFactory(self, ctx);
-#ifdef HAVE_X509V3_EXT_NCONF_NID
+ obj = NewX509Ext(cX509Ext);
rconf = rb_iv_get(self, "@config");
- conf = NIL_P(rconf) ? NULL : GetConfigPtr(rconf);
- ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING(valstr)->ptr);
-#else
- if (!empty_lhash) empty_lhash = lh_new(NULL, NULL);
- ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING(valstr)->ptr);
-#endif
+ conf = NIL_P(rconf) ? NULL : GetConfig(rconf);
+ X509V3_set_nconf(ctx, conf);
+
+ ext = X509V3_EXT_nconf(conf, ctx, oid_cstr, RSTRING_PTR(valstr));
+ X509V3_set_ctx_nodb(ctx);
if (!ext){
- ossl_raise(eX509ExtError, "%s = %s",
- RSTRING(oid)->ptr, RSTRING(value)->ptr);
+ ossl_raise(eX509ExtError, "%"PRIsVALUE" = %"PRIsVALUE, oid, valstr);
}
- WrapX509Ext(cX509Ext, obj, ext);
+ SetX509Ext(obj, ext);
return obj;
}
@@ -261,30 +245,44 @@ ossl_x509ext_alloc(VALUE klass)
X509_EXTENSION *ext;
VALUE obj;
+ obj = NewX509Ext(klass);
if(!(ext = X509_EXTENSION_new())){
- ossl_raise(eX509ExtError, NULL);
+ ossl_raise(eX509ExtError, NULL);
}
- WrapX509Ext(klass, obj, ext);
+ SetX509Ext(obj, ext);
return obj;
}
+/*
+ * call-seq:
+ * OpenSSL::X509::Extension.new(der)
+ * OpenSSL::X509::Extension.new(oid, value)
+ * OpenSSL::X509::Extension.new(oid, value, critical)
+ *
+ * Creates an X509 extension.
+ *
+ * The extension may be created from _der_ data or from an extension _oid_
+ * and _value_. The _oid_ may be either an OID or an extension name. If
+ * _critical_ is +true+ the extension is marked critical.
+ */
static VALUE
ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE oid, value, critical;
- unsigned char *p;
- X509_EXTENSION *ext;
+ const unsigned char *p;
+ X509_EXTENSION *ext, *x;
GetX509Ext(self, ext);
if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){
- oid = ossl_to_der_if_possible(oid);
- StringValue(oid);
- p = RSTRING(oid)->ptr;
- if(!d2i_X509_EXTENSION((X509_EXTENSION**)&DATA_PTR(self),
- &p, RSTRING(oid)->len))
- ossl_raise(eX509ExtError, NULL);
- return self;
+ oid = ossl_to_der_if_possible(oid);
+ StringValue(oid);
+ p = (unsigned char *)RSTRING_PTR(oid);
+ x = d2i_X509_EXTENSION(&ext, &p, RSTRING_LEN(oid));
+ DATA_PTR(self) = ext;
+ if(!x)
+ ossl_raise(eX509ExtError, NULL);
+ return self;
}
rb_funcall(self, rb_intern("oid="), 1, oid);
rb_funcall(self, rb_intern("value="), 1, value);
@@ -293,19 +291,41 @@ ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/* :nodoc: */
+static VALUE
+ossl_x509ext_initialize_copy(VALUE self, VALUE other)
+{
+ X509_EXTENSION *ext, *ext_other, *ext_new;
+
+ rb_check_frozen(self);
+ GetX509Ext(self, ext);
+ GetX509Ext(other, ext_other);
+
+ ext_new = X509_EXTENSION_dup(ext_other);
+ if (!ext_new)
+ ossl_raise(eX509ExtError, "X509_EXTENSION_dup");
+
+ SetX509Ext(self, ext_new);
+ X509_EXTENSION_free(ext);
+
+ return self;
+}
+
static VALUE
ossl_x509ext_set_oid(VALUE self, VALUE oid)
{
X509_EXTENSION *ext;
ASN1_OBJECT *obj;
- char *s;
- s = StringValuePtr(oid);
- obj = OBJ_txt2obj(s, 0);
- if(!obj) obj = OBJ_txt2obj(s, 1);
- if(!obj) ossl_raise(eX509ExtError, NULL);
GetX509Ext(self, ext);
- X509_EXTENSION_set_object(ext, obj);
+ obj = OBJ_txt2obj(StringValueCStr(oid), 0);
+ if (!obj)
+ ossl_raise(eX509ExtError, "OBJ_txt2obj");
+ if (!X509_EXTENSION_set_object(ext, obj)) {
+ ASN1_OBJECT_free(obj);
+ ossl_raise(eX509ExtError, "X509_EXTENSION_set_object");
+ }
+ ASN1_OBJECT_free(obj);
return oid;
}
@@ -315,24 +335,24 @@ ossl_x509ext_set_value(VALUE self, VALUE data)
{
X509_EXTENSION *ext;
ASN1_OCTET_STRING *asn1s;
- char *s;
+ GetX509Ext(self, ext);
data = ossl_to_der_if_possible(data);
StringValue(data);
- if(!(s = OPENSSL_malloc(RSTRING(data)->len)))
- ossl_raise(eX509ExtError, "malloc error");
- memcpy(s, RSTRING(data)->ptr, RSTRING(data)->len);
- if(!(asn1s = ASN1_OCTET_STRING_new())){
- free(s);
- ossl_raise(eX509ExtError, NULL);
+
+ asn1s = ASN1_OCTET_STRING_new();
+ if (!asn1s)
+ ossl_raise(eX509ExtError, "ASN1_OCTET_STRING_new");
+ if (!ASN1_OCTET_STRING_set(asn1s, (unsigned char *)RSTRING_PTR(data),
+ RSTRING_LENINT(data))) {
+ ASN1_OCTET_STRING_free(asn1s);
+ ossl_raise(eX509ExtError, "ASN1_OCTET_STRING_set");
}
- if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING(data)->len)){
- free(s);
- ASN1_OCTET_STRING_free(asn1s);
- ossl_raise(eX509ExtError, NULL);
+ if (!X509_EXTENSION_set_data(ext, asn1s)) {
+ ASN1_OCTET_STRING_free(asn1s);
+ ossl_raise(eX509ExtError, "X509_EXTENSION_set_data");
}
- GetX509Ext(self, ext);
- X509_EXTENSION_set_data(ext, asn1s);
+ ASN1_OCTET_STRING_free(asn1s);
return data;
}
@@ -348,27 +368,20 @@ ossl_x509ext_set_critical(VALUE self, VALUE flag)
return flag;
}
-static VALUE
+/*
+ * call-seq:
+ * ext.oid -> string
+ *
+ * Returns the OID of the extension. Returns the short name or the dotted
+ * decimal notation.
+ */
+static VALUE
ossl_x509ext_get_oid(VALUE obj)
{
X509_EXTENSION *ext;
- ASN1_OBJECT *extobj;
- BIO *out;
- VALUE ret;
- int nid;
GetX509Ext(obj, ext);
- extobj = X509_EXTENSION_get_object(ext);
- if ((nid = OBJ_obj2nid(extobj)) != NID_undef)
- ret = rb_str_new2(OBJ_nid2sn(nid));
- else{
- if (!(out = BIO_new(BIO_s_mem())))
- ossl_raise(eX509ExtError, NULL);
- i2a_ASN1_OBJECT(out, extobj);
- ret = ossl_membio2str(out);
- }
-
- return ret;
+ return ossl_asn1obj_to_string(X509_EXTENSION_get_object(ext));
}
static VALUE
@@ -380,15 +393,28 @@ ossl_x509ext_get_value(VALUE obj)
GetX509Ext(obj, ext);
if (!(out = BIO_new(BIO_s_mem())))
- ossl_raise(eX509ExtError, NULL);
+ ossl_raise(eX509ExtError, NULL);
if (!X509V3_EXT_print(out, ext, 0, 0))
- M_ASN1_OCTET_STRING_print(out, ext->value);
+ ASN1_STRING_print(out, X509_EXTENSION_get_data(ext));
ret = ossl_membio2str(out);
return ret;
}
static VALUE
+ossl_x509ext_get_value_der(VALUE obj)
+{
+ X509_EXTENSION *ext;
+ const ASN1_OCTET_STRING *value;
+
+ GetX509Ext(obj, ext);
+ if ((value = X509_EXTENSION_get_data(ext)) == NULL)
+ ossl_raise(eX509ExtError, NULL);
+
+ return asn1str_to_str(value);
+}
+
+static VALUE
ossl_x509ext_get_critical(VALUE obj)
{
X509_EXTENSION *ext;
@@ -407,11 +433,11 @@ ossl_x509ext_to_der(VALUE obj)
GetX509Ext(obj, ext);
if((len = i2d_X509_EXTENSION(ext, NULL)) <= 0)
- ossl_raise(eX509ExtError, NULL);
+ ossl_raise(eX509ExtError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = (unsigned char *)RSTRING_PTR(str);
if(i2d_X509_EXTENSION(ext, &p) < 0)
- ossl_raise(eX509ExtError, NULL);
+ ossl_raise(eX509ExtError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -421,36 +447,38 @@ ossl_x509ext_to_der(VALUE obj)
* INIT
*/
void
-Init_ossl_x509ext()
+Init_ossl_x509ext(void)
{
+#undef rb_intern
eX509ExtError = rb_define_class_under(mX509, "ExtensionError", eOSSLError);
-
+
cX509ExtFactory = rb_define_class_under(mX509, "ExtensionFactory", rb_cObject);
-
+
rb_define_alloc_func(cX509ExtFactory, ossl_x509extfactory_alloc);
rb_define_method(cX509ExtFactory, "initialize", ossl_x509extfactory_initialize, -1);
-
+
rb_attr(cX509ExtFactory, rb_intern("issuer_certificate"), 1, 0, Qfalse);
rb_attr(cX509ExtFactory, rb_intern("subject_certificate"), 1, 0, Qfalse);
rb_attr(cX509ExtFactory, rb_intern("subject_request"), 1, 0, Qfalse);
rb_attr(cX509ExtFactory, rb_intern("crl"), 1, 0, Qfalse);
- rb_attr(cX509ExtFactory, rb_intern("config"), 1, 0, Qfalse);
+ rb_attr(cX509ExtFactory, rb_intern("config"), 1, 1, Qfalse);
rb_define_method(cX509ExtFactory, "issuer_certificate=", ossl_x509extfactory_set_issuer_cert, 1);
rb_define_method(cX509ExtFactory, "subject_certificate=", ossl_x509extfactory_set_subject_cert, 1);
rb_define_method(cX509ExtFactory, "subject_request=", ossl_x509extfactory_set_subject_req, 1);
rb_define_method(cX509ExtFactory, "crl=", ossl_x509extfactory_set_crl, 1);
- rb_define_method(cX509ExtFactory, "config=", ossl_x509extfactory_set_config, 1);
rb_define_method(cX509ExtFactory, "create_ext", ossl_x509extfactory_create_ext, -1);
-
+
cX509Ext = rb_define_class_under(mX509, "Extension", rb_cObject);
rb_define_alloc_func(cX509Ext, ossl_x509ext_alloc);
rb_define_method(cX509Ext, "initialize", ossl_x509ext_initialize, -1);
+ rb_define_method(cX509Ext, "initialize_copy", ossl_x509ext_initialize_copy, 1);
rb_define_method(cX509Ext, "oid=", ossl_x509ext_set_oid, 1);
rb_define_method(cX509Ext, "value=", ossl_x509ext_set_value, 1);
rb_define_method(cX509Ext, "critical=", ossl_x509ext_set_critical, 1);
rb_define_method(cX509Ext, "oid", ossl_x509ext_get_oid, 0);
rb_define_method(cX509Ext, "value", ossl_x509ext_get_value, 0);
+ rb_define_method(cX509Ext, "value_der", ossl_x509ext_get_value_der, 0);
rb_define_method(cX509Ext, "critical?", ossl_x509ext_get_critical, 0);
rb_define_method(cX509Ext, "to_der", ossl_x509ext_to_der, 0);
}
diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c
index c5ed8b5457..eb97b23c02 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -1,62 +1,70 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#define WrapX509Name(klass, obj, name) do { \
- if (!name) { \
- ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
+#define NewX509Name(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_x509name_type, 0)
+#define SetX509Name(obj, name) do { \
+ if (!(name)) { \
+ ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
} \
- obj = Data_Wrap_Struct(klass, 0, X509_NAME_free, name); \
+ RTYPEDDATA_DATA(obj) = (name); \
} while (0)
#define GetX509Name(obj, name) do { \
- Data_Get_Struct(obj, X509_NAME, name); \
- if (!name) { \
- ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
+ TypedData_Get_Struct((obj), X509_NAME, &ossl_x509name_type, (name)); \
+ if (!(name)) { \
+ ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
} \
} while (0)
-#define SafeGetX509Name(obj, name) do { \
- OSSL_Check_Kind(obj, cX509Name); \
- GetX509Name(obj, name); \
-} while (0)
#define OBJECT_TYPE_TEMPLATE \
- rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE"))
+ rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE"))
#define DEFAULT_OBJECT_TYPE \
- rb_const_get(cX509Name, rb_intern("DEFAULT_OBJECT_TYPE"))
+ rb_const_get(cX509Name, rb_intern("DEFAULT_OBJECT_TYPE"))
/*
* Classes
*/
-VALUE cX509Name;
-VALUE eX509NameError;
+static VALUE cX509Name;
+static VALUE eX509NameError;
+
+static void
+ossl_x509name_free(void *ptr)
+{
+ X509_NAME_free(ptr);
+}
+
+static const rb_data_type_t ossl_x509name_type = {
+ "OpenSSL/X509/NAME",
+ {
+ 0, ossl_x509name_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
/*
* Public
*/
-VALUE
-ossl_x509name_new(X509_NAME *name)
+VALUE
+ossl_x509name_new(const X509_NAME *name)
{
X509_NAME *new;
VALUE obj;
- if (!name) {
- new = X509_NAME_new();
- } else {
- new = X509_NAME_dup(name);
- }
- if (!new) {
- ossl_raise(eX509NameError, NULL);
- }
- WrapX509Name(cX509Name, obj, new);
-
+ obj = NewX509Name(cX509Name);
+ /* OpenSSL 1.1.1 takes a non-const pointer */
+ new = X509_NAME_dup((X509_NAME *)name);
+ if (!new)
+ ossl_raise(eX509NameError, "X509_NAME_dup");
+ SetX509Name(obj, new);
+
return obj;
}
@@ -65,7 +73,7 @@ GetX509NamePtr(VALUE obj)
{
X509_NAME *name;
- SafeGetX509Name(obj, name);
+ GetX509Name(obj, name);
return name;
}
@@ -78,21 +86,22 @@ ossl_x509name_alloc(VALUE klass)
{
X509_NAME *name;
VALUE obj;
-
+
+ obj = NewX509Name(klass);
if (!(name = X509_NAME_new())) {
- ossl_raise(eX509NameError, NULL);
+ ossl_raise(eX509NameError, NULL);
}
- WrapX509Name(klass, obj, name);
+ SetX509Name(obj, name);
return obj;
}
-static int id_aref;
+static ID id_aref;
static VALUE ossl_x509name_add_entry(int, VALUE*, VALUE);
-#define rb_aref(obj, key) rb_funcall(obj, id_aref, 1, key)
+#define rb_aref(obj, key) rb_funcall((obj), id_aref, 1, (key))
static VALUE
-ossl_x509name_init_i(VALUE i, VALUE args)
+ossl_x509name_init_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
{
VALUE self = rb_ary_entry(args, 0);
VALUE template = rb_ary_entry(args, 1);
@@ -109,6 +118,26 @@ ossl_x509name_init_i(VALUE i, VALUE args)
return Qnil;
}
+/*
+ * call-seq:
+ * X509::Name.new => name
+ * X509::Name.new(der) => name
+ * X509::Name.new(distinguished_name) => name
+ * X509::Name.new(distinguished_name, template) => name
+ *
+ * Creates a new Name.
+ *
+ * A name may be created from a DER encoded string _der_, an Array
+ * representing a _distinguished_name_ or a _distinguished_name_ along with a
+ * _template_.
+ *
+ * name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']]
+ *
+ * name = OpenSSL::X509::Name.new name.to_der
+ *
+ * See add_entry for a description of the _distinguished_name_ Array's
+ * contents
+ */
static VALUE
ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -117,46 +146,99 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
GetX509Name(self, name);
if (rb_scan_args(argc, argv, "02", &arg, &template) == 0) {
- return self;
+ return self;
}
else {
- VALUE tmp = rb_check_array_type(arg);
- if (!NIL_P(tmp)) {
- VALUE args;
- if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
- args = rb_ary_new3(2, self, template);
- rb_iterate(rb_each, tmp, ossl_x509name_init_i, args);
- }
- else{
- unsigned char *p;
- VALUE str = ossl_to_der_if_possible(arg);
- StringValue(str);
- p = RSTRING(str)->ptr;
- if(!d2i_X509_NAME((X509_NAME**)&DATA_PTR(self), &p, RSTRING(str)->len)){
- ossl_raise(eX509NameError, NULL);
- }
- }
+ VALUE tmp = rb_check_array_type(arg);
+ if (!NIL_P(tmp)) {
+ VALUE args;
+ if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
+ args = rb_ary_new3(2, self, template);
+ rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args);
+ }
+ else{
+ const unsigned char *p;
+ VALUE str = ossl_to_der_if_possible(arg);
+ X509_NAME *x;
+ StringValue(str);
+ p = (unsigned char *)RSTRING_PTR(str);
+ x = d2i_X509_NAME(&name, &p, RSTRING_LEN(str));
+ DATA_PTR(self) = name;
+ if(!x){
+ ossl_raise(eX509NameError, NULL);
+ }
+ }
}
return self;
}
+/* :nodoc: */
+static VALUE
+ossl_x509name_initialize_copy(VALUE self, VALUE other)
+{
+ X509_NAME *name, *name_other, *name_new;
+
+ rb_check_frozen(self);
+ GetX509Name(self, name);
+ GetX509Name(other, name_other);
+
+ name_new = X509_NAME_dup(name_other);
+ if (!name_new)
+ ossl_raise(eX509NameError, "X509_NAME_dup");
+
+ SetX509Name(self, name_new);
+ X509_NAME_free(name);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * name.add_entry(oid, value [, type], loc: -1, set: 0) => self
+ *
+ * Adds a new entry with the given _oid_ and _value_ to this name. The _oid_
+ * is an object identifier defined in ASN.1. Some common OIDs are:
+ *
+ * C:: Country Name
+ * CN:: Common Name
+ * DC:: Domain Component
+ * O:: Organization Name
+ * OU:: Organizational Unit Name
+ * ST:: State or Province Name
+ *
+ * The optional keyword parameters _loc_ and _set_ specify where to insert the
+ * new attribute. Refer to the manpage of X509_NAME_add_entry(3) for details.
+ * _loc_ defaults to -1 and _set_ defaults to 0. This appends a single-valued
+ * RDN to the end.
+ */
static
VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
{
X509_NAME *name;
- VALUE oid, value, type;
-
- rb_scan_args(argc, argv, "21", &oid, &value, &type);
- StringValue(oid);
+ VALUE oid, value, type, opts, kwargs[2];
+ static ID kwargs_ids[2];
+ const char *oid_name;
+ int loc = -1, set = 0;
+
+ if (!kwargs_ids[0]) {
+ kwargs_ids[0] = rb_intern_const("loc");
+ kwargs_ids[1] = rb_intern_const("set");
+ }
+ rb_scan_args(argc, argv, "21:", &oid, &value, &type, &opts);
+ rb_get_kwargs(opts, kwargs_ids, 0, 2, kwargs);
+ oid_name = StringValueCStr(oid);
StringValue(value);
if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
+ if (kwargs[0] != Qundef)
+ loc = NUM2INT(kwargs[0]);
+ if (kwargs[1] != Qundef)
+ set = NUM2INT(kwargs[1]);
GetX509Name(self, name);
- if (!X509_NAME_add_entry_by_txt(name, RSTRING(oid)->ptr, NUM2INT(type),
- RSTRING(value)->ptr, RSTRING(value)->len, -1, 0)) {
- ossl_raise(eX509NameError, NULL);
- }
-
+ if (!X509_NAME_add_entry_by_txt(name, oid_name, NUM2INT(type),
+ (unsigned char *)RSTRING_PTR(value),
+ RSTRING_LENINT(value), loc, set))
+ ossl_raise(eX509NameError, "X509_NAME_add_entry_by_txt");
return self;
}
@@ -165,69 +247,117 @@ ossl_x509name_to_s_old(VALUE self)
{
X509_NAME *name;
char *buf;
- VALUE str;
GetX509Name(self, name);
buf = X509_NAME_oneline(name, NULL, 0);
- str = rb_str_new2(buf);
- OPENSSL_free(buf);
-
- return str;
+ if (!buf)
+ ossl_raise(eX509NameError, "X509_NAME_oneline");
+ return ossl_buf2str(buf, rb_long2int(strlen(buf)));
}
static VALUE
-ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
-{
+x509name_print(VALUE self, unsigned long iflag)
+{
X509_NAME *name;
- VALUE flag, str;
BIO *out;
- unsigned long iflag;
-
- rb_scan_args(argc, argv, "01", &flag);
- if (NIL_P(flag))
- return ossl_x509name_to_s_old(self);
- else iflag = NUM2ULONG(flag);
- if (!(out = BIO_new(BIO_s_mem())))
- rb_raise(eX509NameError, NULL);
+ int ret;
+
GetX509Name(self, name);
- if (!X509_NAME_print_ex(out, name, 0, iflag)){
- BIO_free(out);
- rb_raise(eX509NameError, NULL);
+ out = BIO_new(BIO_s_mem());
+ if (!out)
+ ossl_raise(eX509NameError, NULL);
+ ret = X509_NAME_print_ex(out, name, 0, iflag);
+ if (ret < 0 || (iflag == XN_FLAG_COMPAT && ret == 0)) {
+ BIO_free(out);
+ ossl_raise(eX509NameError, "X509_NAME_print_ex");
}
- str = ossl_membio2str(out);
+ return ossl_membio2str(out);
+}
+/*
+ * call-seq:
+ * name.to_s -> string
+ * name.to_s(format) -> string
+ *
+ * Returns a String representation of the Distinguished Name. _format_ is
+ * one of:
+ *
+ * * OpenSSL::X509::Name::COMPAT
+ * * OpenSSL::X509::Name::RFC2253
+ * * OpenSSL::X509::Name::ONELINE
+ * * OpenSSL::X509::Name::MULTILINE
+ *
+ * If _format_ is omitted, the largely broken and traditional OpenSSL format
+ * (<tt>X509_NAME_oneline()</tt> format) is chosen.
+ *
+ * <b>Use of this method is discouraged.</b> None of the formats other than
+ * OpenSSL::X509::Name::RFC2253 is standardized and may show an inconsistent
+ * behavior through \OpenSSL versions.
+ *
+ * It is recommended to use #to_utf8 instead, which is equivalent to calling
+ * <tt>name.to_s(OpenSSL::X509::Name::RFC2253).force_encoding("UTF-8")</tt>.
+ */
+static VALUE
+ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 0, 1);
+ /* name.to_s(nil) was allowed */
+ if (!argc || NIL_P(argv[0]))
+ return ossl_x509name_to_s_old(self);
+ else
+ return x509name_print(self, NUM2ULONG(argv[0]));
+}
+
+/*
+ * call-seq:
+ * name.to_utf8 -> string
+ *
+ * Returns an UTF-8 representation of the distinguished name, as specified
+ * in {RFC 2253}[https://www.ietf.org/rfc/rfc2253.txt].
+ */
+static VALUE
+ossl_x509name_to_utf8(VALUE self)
+{
+ VALUE str = x509name_print(self, XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB);
+ rb_enc_associate_index(str, rb_utf8_encindex());
return str;
}
-static VALUE
+/* :nodoc: */
+static VALUE
+ossl_x509name_inspect(VALUE self)
+{
+ return rb_enc_sprintf(rb_utf8_encoding(), "#<%"PRIsVALUE" %"PRIsVALUE">",
+ rb_obj_class(self), ossl_x509name_to_utf8(self));
+}
+
+/*
+ * call-seq:
+ * name.to_a => [[name, data, type], ...]
+ *
+ * Returns an Array representation of the distinguished name suitable for
+ * passing to ::new
+ */
+static VALUE
ossl_x509name_to_a(VALUE self)
{
X509_NAME *name;
- X509_NAME_ENTRY *entry;
- int i,entries;
- char long_name[512];
- const char *short_name;
- VALUE ary, ret;
-
+ int entries;
+ VALUE ret;
+
GetX509Name(self, name);
entries = X509_NAME_entry_count(name);
- if (entries < 0) {
- OSSL_Debug("name entries < 0!");
- return rb_ary_new();
- }
- ret = rb_ary_new2(entries);
- for (i=0; i<entries; i++) {
- if (!(entry = X509_NAME_get_entry(name, i))) {
- ossl_raise(eX509NameError, NULL);
- }
- if (!i2t_ASN1_OBJECT(long_name, sizeof(long_name), entry->object)) {
- ossl_raise(eX509NameError, NULL);
- }
- short_name = OBJ_nid2sn(OBJ_ln2nid(long_name));
- ary = rb_ary_new3(3, rb_str_new2(short_name),
- rb_str_new(entry->value->data, entry->value->length),
- INT2FIX(entry->value->type));
- rb_ary_push(ret, ary);
+ ret = rb_ary_new_capa(entries);
+ for (int i = 0; i < entries; i++) {
+ const X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i);
+ if (!entry)
+ ossl_raise(eX509NameError, "X509_NAME_get_entry");
+ const ASN1_OBJECT *obj = X509_NAME_ENTRY_get_object(entry);
+ VALUE vname = ossl_asn1obj_to_string(obj);
+ const ASN1_STRING *data = X509_NAME_ENTRY_get_data(entry);
+ VALUE vdata = asn1str_to_str(data);
+ VALUE type = INT2NUM(ASN1_STRING_type(data));
+ rb_ary_push(ret, rb_ary_new_from_args(3, vname, vdata, type));
}
return ret;
}
@@ -236,36 +366,65 @@ static int
ossl_x509name_cmp0(VALUE self, VALUE other)
{
X509_NAME *name1, *name2;
+ int result;
GetX509Name(self, name1);
- SafeGetX509Name(other, name2);
+ GetX509Name(other, name2);
+
+ result = X509_NAME_cmp(name1, name2);
+ if (result == -2) {
+ ossl_raise(eX509NameError, NULL);
+ }
- return X509_NAME_cmp(name1, name2);
+ return result;
}
+/*
+ * call-seq:
+ * name.cmp(other) -> -1 | 0 | 1 | nil
+ * name <=> other -> -1 | 0 | 1 | nil
+ *
+ * Compares this Name with _other_ and returns +0+ if they are the same and +-1+
+ * or ++1+ if they are greater or less than each other respectively.
+ * Returns +nil+ if they are not comparable (i.e. different types).
+ */
static VALUE
ossl_x509name_cmp(VALUE self, VALUE other)
{
int result;
+ if (!rb_obj_is_kind_of(other, cX509Name))
+ return Qnil;
+
result = ossl_x509name_cmp0(self, other);
if (result < 0) return INT2FIX(-1);
- if (result > 1) return INT2FIX(1);
+ if (result > 0) return INT2FIX(1);
return INT2FIX(0);
}
+/*
+ * call-seq:
+ * name.eql?(other) -> true | false
+ *
+ * Returns true if _name_ and _other_ refer to the same hash key.
+ */
static VALUE
ossl_x509name_eql(VALUE self, VALUE other)
{
- int result;
-
- if(CLASS_OF(other) != cX509Name) return Qfalse;
- result = ossl_x509name_cmp0(self, other);
+ if (!rb_obj_is_kind_of(other, cX509Name))
+ return Qfalse;
- return (result == 0) ? Qtrue : Qfalse;
+ return ossl_x509name_cmp0(self, other) == 0 ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * name.hash => integer
+ *
+ * The hash value returned is suitable for use as a certificate's filename in
+ * a CA path.
+ */
static VALUE
ossl_x509name_hash(VALUE self)
{
@@ -279,6 +438,31 @@ ossl_x509name_hash(VALUE self)
return ULONG2NUM(hash);
}
+/*
+ * call-seq:
+ * name.hash_old => integer
+ *
+ * Returns an MD5 based hash used in OpenSSL 0.9.X.
+ */
+static VALUE
+ossl_x509name_hash_old(VALUE self)
+{
+ X509_NAME *name;
+ unsigned long hash;
+
+ GetX509Name(self, name);
+
+ hash = X509_NAME_hash_old(name);
+
+ return ULONG2NUM(hash);
+}
+
+/*
+ * call-seq:
+ * name.to_der => string
+ *
+ * Converts the name to DER encoding
+ */
static VALUE
ossl_x509name_to_der(VALUE self)
{
@@ -289,45 +473,67 @@ ossl_x509name_to_der(VALUE self)
GetX509Name(self, name);
if((len = i2d_X509_NAME(name, NULL)) <= 0)
- ossl_raise(eX509NameError, NULL);
+ ossl_raise(eX509NameError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = (unsigned char *)RSTRING_PTR(str);
if(i2d_X509_NAME(name, &p) <= 0)
- ossl_raise(eX509NameError, NULL);
+ ossl_raise(eX509NameError, NULL);
ossl_str_adjust(str, p);
return str;
}
/*
- * INIT
+ * Document-class: OpenSSL::X509::Name
+ *
+ * An X.509 name represents a hostname, email address or other entity
+ * associated with a public key.
+ *
+ * You can create a Name by parsing a distinguished name String or by
+ * supplying the distinguished name as an Array.
+ *
+ * name = OpenSSL::X509::Name.parse_rfc2253 'DC=example,CN=nobody'
+ *
+ * name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']]
*/
-void
-Init_ossl_x509name()
+
+void
+Init_ossl_x509name(void)
{
+#undef rb_intern
VALUE utf8str, ptrstr, ia5str, hash;
id_aref = rb_intern("[]");
eX509NameError = rb_define_class_under(mX509, "NameError", eOSSLError);
cX509Name = rb_define_class_under(mX509, "Name", rb_cObject);
+ rb_include_module(cX509Name, rb_mComparable);
+
rb_define_alloc_func(cX509Name, ossl_x509name_alloc);
rb_define_method(cX509Name, "initialize", ossl_x509name_initialize, -1);
+ rb_define_method(cX509Name, "initialize_copy", ossl_x509name_initialize_copy, 1);
rb_define_method(cX509Name, "add_entry", ossl_x509name_add_entry, -1);
rb_define_method(cX509Name, "to_s", ossl_x509name_to_s, -1);
+ rb_define_method(cX509Name, "to_utf8", ossl_x509name_to_utf8, 0);
+ rb_define_method(cX509Name, "inspect", ossl_x509name_inspect, 0);
rb_define_method(cX509Name, "to_a", ossl_x509name_to_a, 0);
rb_define_method(cX509Name, "cmp", ossl_x509name_cmp, 1);
rb_define_alias(cX509Name, "<=>", "cmp");
rb_define_method(cX509Name, "eql?", ossl_x509name_eql, 1);
rb_define_method(cX509Name, "hash", ossl_x509name_hash, 0);
+ rb_define_method(cX509Name, "hash_old", ossl_x509name_hash_old, 0);
rb_define_method(cX509Name, "to_der", ossl_x509name_to_der, 0);
utf8str = INT2NUM(V_ASN1_UTF8STRING);
ptrstr = INT2NUM(V_ASN1_PRINTABLESTRING);
ia5str = INT2NUM(V_ASN1_IA5STRING);
+
+ /*
+ * The default object type for name entries.
+ */
rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str);
hash = rb_hash_new();
- RHASH(hash)->ifnone = utf8str;
+ RHASH_SET_IFNONE(hash, utf8str);
rb_hash_aset(hash, rb_str_new2("C"), ptrstr);
rb_hash_aset(hash, rb_str_new2("countryName"), ptrstr);
rb_hash_aset(hash, rb_str_new2("serialNumber"), ptrstr);
@@ -335,10 +541,39 @@ Init_ossl_x509name()
rb_hash_aset(hash, rb_str_new2("DC"), ia5str);
rb_hash_aset(hash, rb_str_new2("domainComponent"), ia5str);
rb_hash_aset(hash, rb_str_new2("emailAddress"), ia5str);
+ rb_obj_freeze(hash);
+
+ /*
+ * The default object type template for name entries.
+ */
rb_define_const(cX509Name, "OBJECT_TYPE_TEMPLATE", hash);
+ /*
+ * A flag for #to_s.
+ *
+ * Breaks the name returned into multiple lines if longer than 80
+ * characters.
+ */
rb_define_const(cX509Name, "COMPAT", ULONG2NUM(XN_FLAG_COMPAT));
+
+ /*
+ * A flag for #to_s.
+ *
+ * Returns an RFC2253 format name.
+ */
rb_define_const(cX509Name, "RFC2253", ULONG2NUM(XN_FLAG_RFC2253));
+
+ /*
+ * A flag for #to_s.
+ *
+ * Returns a more readable format than RFC2253.
+ */
rb_define_const(cX509Name, "ONELINE", ULONG2NUM(XN_FLAG_ONELINE));
+
+ /*
+ * A flag for #to_s.
+ *
+ * Returns a multiline format.
+ */
rb_define_const(cX509Name, "MULTILINE", ULONG2NUM(XN_FLAG_MULTILINE));
}
diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c
index d644250433..ad5dd08033 100644
--- a/ext/openssl/ossl_x509req.c
+++ b/ext/openssl/ossl_x509req.c
@@ -1,134 +1,120 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#define WrapX509Req(klass, obj, req) do { \
- if (!req) { \
- ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
+#define NewX509Req(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_x509req_type, 0)
+#define SetX509Req(obj, req) do { \
+ if (!(req)) { \
+ ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
} \
- obj = Data_Wrap_Struct(klass, 0, X509_REQ_free, req); \
+ RTYPEDDATA_DATA(obj) = (req); \
} while (0)
#define GetX509Req(obj, req) do { \
- Data_Get_Struct(obj, X509_REQ, req); \
- if (!req) { \
- ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
+ TypedData_Get_Struct((obj), X509_REQ, &ossl_x509req_type, (req)); \
+ if (!(req)) { \
+ ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
} \
} while (0)
-#define SafeGetX509Req(obj, req) do { \
- OSSL_Check_Kind(obj, cX509Req); \
- GetX509Req(obj, req); \
-} while (0)
/*
* Classes
*/
-VALUE cX509Req;
-VALUE eX509ReqError;
+static VALUE cX509Req;
+static VALUE eX509ReqError;
-/*
- * Public functions
- */
-VALUE
-ossl_x509req_new(X509_REQ *req)
+static void
+ossl_x509req_free(void *ptr)
{
- X509_REQ *new;
- VALUE obj;
-
- if (!req) {
- new = X509_REQ_new();
- } else {
- new = X509_REQ_dup(req);
- }
- if (!new) {
- ossl_raise(eX509ReqError, NULL);
- }
- WrapX509Req(cX509Req, obj, new);
-
- return obj;
+ X509_REQ_free(ptr);
}
+static const rb_data_type_t ossl_x509req_type = {
+ "OpenSSL/X509/REQ",
+ {
+ 0, ossl_x509req_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+/*
+ * Public functions
+ */
X509_REQ *
GetX509ReqPtr(VALUE obj)
{
X509_REQ *req;
- SafeGetX509Req(obj, req);
+ GetX509Req(obj, req);
return req;
}
-X509_REQ *
-DupX509ReqPtr(VALUE obj)
-{
- X509_REQ *req, *new;
-
- SafeGetX509Req(obj, req);
- if (!(new = X509_REQ_dup(req))) {
- ossl_raise(eX509ReqError, NULL);
- }
-
- return new;
-}
-
/*
* Private functions
*/
-static VALUE
+static VALUE
ossl_x509req_alloc(VALUE klass)
{
X509_REQ *req;
VALUE obj;
+ obj = NewX509Req(klass);
if (!(req = X509_REQ_new())) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
- WrapX509Req(klass, obj, req);
+ SetX509Req(obj, req);
return obj;
}
-static VALUE
+static VALUE
ossl_x509req_initialize(int argc, VALUE *argv, VALUE self)
{
BIO *in;
- X509_REQ *req;
+ X509_REQ *req, *req_orig = RTYPEDDATA_DATA(self);
VALUE arg;
+ rb_check_frozen(self);
if (rb_scan_args(argc, argv, "01", &arg) == 0) {
- return self;
+ return self;
}
arg = ossl_to_der_if_possible(arg);
- in = ossl_obj2bio(arg);
- req = PEM_read_bio_X509_REQ(in, (X509_REQ **)&DATA_PTR(self), NULL, NULL);
+ in = ossl_obj2bio(&arg);
+ req = d2i_X509_REQ_bio(in, NULL);
if (!req) {
- BIO_reset(in);
- req = d2i_X509_REQ_bio(in, (X509_REQ **)&DATA_PTR(self));
+ OSSL_BIO_reset(in);
+ req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
}
BIO_free(in);
- if (!req) ossl_raise(eX509ReqError, NULL);
+ if (!req)
+ ossl_raise(eX509ReqError, "PEM_read_bio_X509_REQ");
+
+ RTYPEDDATA_DATA(self) = req;
+ X509_REQ_free(req_orig);
return self;
}
+/* :nodoc: */
static VALUE
ossl_x509req_copy(VALUE self, VALUE other)
{
X509_REQ *a, *b, *req;
-
+
rb_check_frozen(self);
if (self == other) return self;
GetX509Req(self, a);
- SafeGetX509Req(other, b);
+ GetX509Req(other, b);
if (!(req = X509_REQ_dup(b))) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
X509_REQ_free(a);
DATA_PTR(self) = req;
@@ -136,27 +122,22 @@ ossl_x509req_copy(VALUE self, VALUE other)
return self;
}
-static VALUE
+static VALUE
ossl_x509req_to_pem(VALUE self)
{
X509_REQ *req;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
-
+
GetX509Req(self, req);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
if (!PEM_write_bio_X509_REQ(out, req)) {
- BIO_free(out);
- ossl_raise(eX509ReqError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509ReqError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
static VALUE
@@ -169,60 +150,55 @@ ossl_x509req_to_der(VALUE self)
GetX509Req(self, req);
if ((len = i2d_X509_REQ(req, NULL)) <= 0)
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509ReqError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = (unsigned char *)RSTRING_PTR(str);
if (i2d_X509_REQ(req, &p) <= 0)
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
ossl_str_adjust(str, p);
return str;
}
-static VALUE
+static VALUE
ossl_x509req_to_text(VALUE self)
{
X509_REQ *req;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509Req(self, req);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
if (!X509_REQ_print(out, req)) {
- BIO_free(out);
- ossl_raise(eX509ReqError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509ReqError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
#if 0
/*
* Makes X509 from X509_REQuest
*/
-static VALUE
+static VALUE
ossl_x509req_to_x509(VALUE self, VALUE days, VALUE key)
{
X509_REQ *req;
X509 *x509;
-
+
GetX509Req(self, req);
...
if (!(x509 = X509_REQ_to_X509(req, d, pkey))) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
return ossl_x509_new(x509);
}
#endif
-static VALUE
+static VALUE
ossl_x509req_get_version(VALUE self)
{
X509_REQ *req;
@@ -231,78 +207,77 @@ ossl_x509req_get_version(VALUE self)
GetX509Req(self, req);
version = X509_REQ_get_version(req);
- return LONG2FIX(version);
+ return LONG2NUM(version);
}
-static VALUE
+static VALUE
ossl_x509req_set_version(VALUE self, VALUE version)
{
X509_REQ *req;
long ver;
- if ((ver = FIX2LONG(version)) < 0) {
- ossl_raise(eX509ReqError, "version must be >= 0!");
+ if ((ver = NUM2LONG(version)) < 0) {
+ ossl_raise(eX509ReqError, "version must be >= 0!");
}
GetX509Req(self, req);
if (!X509_REQ_set_version(req, ver)) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, "X509_REQ_set_version");
}
return version;
}
-static VALUE
+static VALUE
ossl_x509req_get_subject(VALUE self)
{
X509_REQ *req;
- X509_NAME *name;
+ const X509_NAME *name;
GetX509Req(self, req);
if (!(name = X509_REQ_get_subject_name(req))) { /* NO DUP - don't free */
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
return ossl_x509name_new(name);
}
-static VALUE
+static VALUE
ossl_x509req_set_subject(VALUE self, VALUE subject)
{
X509_REQ *req;
-
+
GetX509Req(self, req);
/* DUPs name */
if (!X509_REQ_set_subject_name(req, GetX509NamePtr(subject))) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
return subject;
}
-static VALUE
+/*
+ * call-seq:
+ * req.signature_algorithm -> string
+ *
+ * Returns the signature algorithm used to sign this request.
+ *
+ * Returns the long name of the signature algorithm, or the dotted decimal
+ * notation if \OpenSSL does not define a long name for it.
+ */
+static VALUE
ossl_x509req_get_signature_algorithm(VALUE self)
{
X509_REQ *req;
- BIO *out;
- BUF_MEM *buf;
- VALUE str;
+ const X509_ALGOR *alg;
+ const ASN1_OBJECT *obj;
GetX509Req(self, req);
-
- if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509ReqError, NULL);
- }
- if (!i2a_ASN1_OBJECT(out, req->sig_alg->algorithm)) {
- BIO_free(out);
- ossl_raise(eX509ReqError, NULL);
- }
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ X509_REQ_get0_signature(req, NULL, &alg);
+ X509_ALGOR_get0(&obj, NULL, NULL, alg);
+ return ossl_asn1obj_to_string_long_name(obj);
}
-static VALUE
+static VALUE
ossl_x509req_get_public_key(VALUE self)
{
X509_REQ *req;
@@ -310,40 +285,40 @@ ossl_x509req_get_public_key(VALUE self)
GetX509Req(self, req);
if (!(pkey = X509_REQ_get_pubkey(req))) { /* adds reference */
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
- return ossl_pkey_new(pkey); /* NO DUP - OK */
+ return ossl_pkey_wrap(pkey);
}
-static VALUE
+static VALUE
ossl_x509req_set_public_key(VALUE self, VALUE key)
{
X509_REQ *req;
EVP_PKEY *pkey;
GetX509Req(self, req);
- pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
- if (!X509_REQ_set_pubkey(req, pkey)) {
- ossl_raise(eX509ReqError, NULL);
- }
-
+ pkey = GetPKeyPtr(key);
+ ossl_pkey_check_public_key(pkey);
+ if (!X509_REQ_set_pubkey(req, pkey))
+ ossl_raise(eX509ReqError, "X509_REQ_set_pubkey");
return key;
}
-static VALUE
+static VALUE
ossl_x509req_sign(VALUE self, VALUE key, VALUE digest)
{
X509_REQ *req;
EVP_PKEY *pkey;
const EVP_MD *md;
+ VALUE md_holder;
GetX509Req(self, req);
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
- md = GetDigestPtr(digest);
- if (!X509_REQ_sign(req, pkey, md)) {
- ossl_raise(eX509ReqError, NULL);
- }
+ /* NULL needed for some key types, e.g. Ed25519 */
+ md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder);
+ if (!X509_REQ_sign(req, pkey, md))
+ ossl_raise(eX509ReqError, "X509_REQ_sign");
return self;
}
@@ -351,82 +326,83 @@ ossl_x509req_sign(VALUE self, VALUE key, VALUE digest)
/*
* Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
*/
-static VALUE
+static VALUE
ossl_x509req_verify(VALUE self, VALUE key)
{
X509_REQ *req;
EVP_PKEY *pkey;
- int i;
GetX509Req(self, req);
- pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
- if ((i = X509_REQ_verify(req, pkey)) < 0) {
- ossl_raise(eX509ReqError, NULL);
- }
- if (i > 0) {
- return Qtrue;
+ pkey = GetPKeyPtr(key);
+ ossl_pkey_check_public_key(pkey);
+ switch (X509_REQ_verify(req, pkey)) {
+ case 1:
+ return Qtrue;
+ case 0:
+ ossl_clear_error();
+ return Qfalse;
+ default:
+ ossl_raise(eX509ReqError, NULL);
}
-
- return Qfalse;
}
-static VALUE
+static VALUE
ossl_x509req_get_attributes(VALUE self)
{
X509_REQ *req;
int count, i;
- X509_ATTRIBUTE *attr;
+ const X509_ATTRIBUTE *attr;
VALUE ary;
-
+
GetX509Req(self, req);
count = X509_REQ_get_attr_count(req);
if (count < 0) {
- OSSL_Debug("count < 0???");
- return rb_ary_new();
+ OSSL_Debug("count < 0???");
+ return rb_ary_new();
}
ary = rb_ary_new2(count);
for (i=0; i<count; i++) {
- attr = X509_REQ_get_attr(req, i);
- rb_ary_push(ary, ossl_x509attr_new(attr));
+ attr = X509_REQ_get_attr(req, i);
+ rb_ary_push(ary, ossl_x509attr_new(attr));
}
return ary;
}
-static VALUE
+static VALUE
ossl_x509req_set_attributes(VALUE self, VALUE ary)
{
X509_REQ *req;
X509_ATTRIBUTE *attr;
- int i;
+ long i;
VALUE item;
Check_Type(ary, T_ARRAY);
- for (i=0;i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Attr);
+ for (i=0;i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Attr);
}
GetX509Req(self, req);
- sk_X509_ATTRIBUTE_pop_free(req->req_info->attributes, X509_ATTRIBUTE_free);
- req->req_info->attributes = NULL;
- for (i=0;i<RARRAY(ary)->len; i++) {
- item = RARRAY(ary)->ptr[i];
- attr = DupX509AttrPtr(item);
- if (!X509_REQ_add1_attr(req, attr)) {
- ossl_raise(eX509ReqError, NULL);
- }
+ for (i = X509_REQ_get_attr_count(req); i > 0; i--)
+ X509_ATTRIBUTE_free(X509_REQ_delete_attr(req, 0));
+ for (i=0;i<RARRAY_LEN(ary); i++) {
+ item = RARRAY_AREF(ary, i);
+ attr = GetX509AttrPtr(item);
+ if (!X509_REQ_add1_attr(req, attr)) {
+ ossl_raise(eX509ReqError, "X509_REQ_add1_attr");
+ }
}
return ary;
}
-static VALUE
+static VALUE
ossl_x509req_add_attribute(VALUE self, VALUE attr)
{
X509_REQ *req;
GetX509Req(self, req);
- if (!X509_REQ_add1_attr(req, DupX509AttrPtr(attr))) {
- ossl_raise(eX509ReqError, NULL);
+ if (!X509_REQ_add1_attr(req, GetX509AttrPtr(attr))) {
+ ossl_raise(eX509ReqError, NULL);
}
return attr;
@@ -435,17 +411,17 @@ ossl_x509req_add_attribute(VALUE self, VALUE attr)
/*
* X509_REQUEST init
*/
-void
-Init_ossl_x509req()
+void
+Init_ossl_x509req(void)
{
eX509ReqError = rb_define_class_under(mX509, "RequestError", eOSSLError);
-
+
cX509Req = rb_define_class_under(mX509, "Request", rb_cObject);
-
+
rb_define_alloc_func(cX509Req, ossl_x509req_alloc);
rb_define_method(cX509Req, "initialize", ossl_x509req_initialize, -1);
- rb_define_copy_func(cX509Req, ossl_x509req_copy);
-
+ rb_define_method(cX509Req, "initialize_copy", ossl_x509req_copy, 1);
+
rb_define_method(cX509Req, "to_pem", ossl_x509req_to_pem, 0);
rb_define_method(cX509Req, "to_der", ossl_x509req_to_der, 0);
rb_define_alias(cX509Req, "to_s", "to_pem");
@@ -463,4 +439,3 @@ Init_ossl_x509req()
rb_define_method(cX509Req, "attributes=", ossl_x509req_set_attributes, 1);
rb_define_method(cX509Req, "add_attribute", ossl_x509req_add_attribute, 1);
}
-
diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c
index 3ccac8d26a..0151961e9f 100644
--- a/ext/openssl/ossl_x509revoked.c
+++ b/ext/openssl/ossl_x509revoked.c
@@ -1,56 +1,64 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#define WrapX509Rev(klass, obj, rev) do { \
- if (!rev) { \
- ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
+#define NewX509Rev(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_x509rev_type, 0)
+#define SetX509Rev(obj, rev) do { \
+ if (!(rev)) { \
+ ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
} \
- obj = Data_Wrap_Struct(klass, 0, X509_REVOKED_free, rev); \
+ RTYPEDDATA_DATA(obj) = (rev); \
} while (0)
#define GetX509Rev(obj, rev) do { \
- Data_Get_Struct(obj, X509_REVOKED, rev); \
- if (!rev) { \
- ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
+ TypedData_Get_Struct((obj), X509_REVOKED, &ossl_x509rev_type, (rev)); \
+ if (!(rev)) { \
+ ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
} \
} while (0)
-#define SafeGetX509Rev(obj, rev) do { \
- OSSL_Check_Kind(obj, cX509Rev); \
- GetX509Rev(obj, rev); \
-} while (0)
/*
* Classes
*/
VALUE cX509Rev;
-VALUE eX509RevError;
+static VALUE eX509RevError;
+
+static void
+ossl_x509rev_free(void *ptr)
+{
+ X509_REVOKED_free(ptr);
+}
+
+static const rb_data_type_t ossl_x509rev_type = {
+ "OpenSSL/X509/REV",
+ {
+ 0, ossl_x509rev_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
/*
* PUBLIC
*/
-VALUE
-ossl_x509revoked_new(X509_REVOKED *rev)
+VALUE
+ossl_x509revoked_new(const X509_REVOKED *rev)
{
X509_REVOKED *new;
VALUE obj;
- if (!rev) {
- new = X509_REVOKED_new();
- } else {
- new = X509_REVOKED_dup(rev);
- }
- if (!new) {
- ossl_raise(eX509RevError, NULL);
- }
- WrapX509Rev(cX509Rev, obj, new);
+ obj = NewX509Rev(cX509Rev);
+ /* OpenSSL 1.1.1 takes a non-const pointer */
+ new = X509_REVOKED_dup((X509_REVOKED *)rev);
+ if (!new)
+ ossl_raise(eX509RevError, "X509_REVOKED_dup");
+ SetX509Rev(obj, new);
return obj;
}
@@ -60,9 +68,9 @@ DupX509RevokedPtr(VALUE obj)
{
X509_REVOKED *rev, *new;
- SafeGetX509Rev(obj, rev);
+ GetX509Rev(obj, rev);
if (!(new = X509_REVOKED_dup(rev))) {
- ossl_raise(eX509RevError, NULL);
+ ossl_raise(eX509RevError, NULL);
}
return new;
@@ -71,93 +79,122 @@ DupX509RevokedPtr(VALUE obj)
/*
* PRIVATE
*/
-static VALUE
+static VALUE
ossl_x509revoked_alloc(VALUE klass)
{
X509_REVOKED *rev;
VALUE obj;
+ obj = NewX509Rev(klass);
if (!(rev = X509_REVOKED_new())) {
- ossl_raise(eX509RevError, NULL);
+ ossl_raise(eX509RevError, NULL);
}
- WrapX509Rev(klass, obj, rev);
+ SetX509Rev(obj, rev);
return obj;
}
-static VALUE
+static VALUE
ossl_x509revoked_initialize(int argc, VALUE *argv, VALUE self)
{
/* EMPTY */
return self;
}
-static VALUE
+/* :nodoc: */
+static VALUE
+ossl_x509revoked_initialize_copy(VALUE self, VALUE other)
+{
+ X509_REVOKED *rev, *rev_other, *rev_new;
+
+ rb_check_frozen(self);
+ GetX509Rev(self, rev);
+ GetX509Rev(other, rev_other);
+
+ rev_new = X509_REVOKED_dup(rev_other);
+ if (!rev_new)
+ ossl_raise(eX509RevError, "X509_REVOKED_dup");
+
+ SetX509Rev(self, rev_new);
+ X509_REVOKED_free(rev);
+
+ return self;
+}
+
+static VALUE
ossl_x509revoked_get_serial(VALUE self)
{
X509_REVOKED *rev;
GetX509Rev(self, rev);
- return asn1integer_to_num(rev->serialNumber);
+ return asn1integer_to_num(X509_REVOKED_get0_serialNumber(rev));
}
-static VALUE
+static VALUE
ossl_x509revoked_set_serial(VALUE self, VALUE num)
{
X509_REVOKED *rev;
+ ASN1_INTEGER *asn1int;
GetX509Rev(self, rev);
- rev->serialNumber = num_to_asn1integer(num, rev->serialNumber);
+ asn1int = num_to_asn1integer(num, NULL);
+ if (!X509_REVOKED_set_serialNumber(rev, asn1int)) {
+ ASN1_INTEGER_free(asn1int);
+ ossl_raise(eX509RevError, "X509_REVOKED_set_serialNumber");
+ }
+ ASN1_INTEGER_free(asn1int);
return num;
}
-static VALUE
+static VALUE
ossl_x509revoked_get_time(VALUE self)
{
X509_REVOKED *rev;
-
+ const ASN1_TIME *time;
+
GetX509Rev(self, rev);
+ time = X509_REVOKED_get0_revocationDate(rev);
+ if (!time)
+ return Qnil;
- return asn1time_to_time(rev->revocationDate);
+ return asn1time_to_time(time);
}
-static VALUE
+static VALUE
ossl_x509revoked_set_time(VALUE self, VALUE time)
{
X509_REVOKED *rev;
- time_t sec;
+ ASN1_TIME *asn1time;
- sec = time_to_time_t(time);
GetX509Rev(self, rev);
- if (!X509_time_adj(rev->revocationDate, 0, &sec)) {
- ossl_raise(eX509RevError, NULL);
+ asn1time = ossl_x509_time_adjust(NULL, time);
+ if (!X509_REVOKED_set_revocationDate(rev, asn1time)) {
+ ASN1_TIME_free(asn1time);
+ ossl_raise(eX509RevError, "X509_REVOKED_set_revocationDate");
}
+ ASN1_TIME_free(asn1time);
return time;
}
/*
* Gets X509v3 extensions as array of X509Ext objects
*/
-static VALUE
+static VALUE
ossl_x509revoked_get_extensions(VALUE self)
{
X509_REVOKED *rev;
int count, i;
- X509_EXTENSION *ext;
+ const X509_EXTENSION *ext;
VALUE ary;
GetX509Rev(self, rev);
count = X509_REVOKED_get_ext_count(rev);
- if (count < 0) {
- OSSL_Debug("count < 0???");
- return rb_ary_new();
- }
- ary = rb_ary_new2(count);
+ ary = rb_ary_new_capa(count);
for (i=0; i<count; i++) {
- ext = X509_REVOKED_get_ext(rev, i);
- rb_ary_push(ary, ossl_x509ext_new(ext));
+ ext = X509_REVOKED_get_ext(rev, i);
+ rb_ary_push(ary, ossl_x509ext_new(ext));
}
return ary;
@@ -166,27 +203,27 @@ ossl_x509revoked_get_extensions(VALUE self)
/*
* Sets X509_EXTENSIONs
*/
-static VALUE
+static VALUE
ossl_x509revoked_set_extensions(VALUE self, VALUE ary)
{
X509_REVOKED *rev;
X509_EXTENSION *ext;
- int i;
+ long i;
VALUE item;
Check_Type(ary, T_ARRAY);
- for (i=0; i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
}
GetX509Rev(self, rev);
- sk_X509_EXTENSION_pop_free(rev->extensions, X509_EXTENSION_free);
- rev->extensions = NULL;
- for (i=0; i<RARRAY(ary)->len; i++) {
- item = RARRAY(ary)->ptr[i];
- ext = DupX509ExtPtr(item);
- if(!X509_REVOKED_add_ext(rev, ext, -1)) {
- ossl_raise(eX509RevError, NULL);
- }
+ for (i = X509_REVOKED_get_ext_count(rev); i > 0; i--)
+ X509_EXTENSION_free(X509_REVOKED_delete_ext(rev, 0));
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ item = RARRAY_AREF(ary, i);
+ ext = GetX509ExtPtr(item);
+ if(!X509_REVOKED_add_ext(rev, ext, -1)) {
+ ossl_raise(eX509RevError, "X509_REVOKED_add_ext");
+ }
}
return ary;
@@ -196,28 +233,49 @@ static VALUE
ossl_x509revoked_add_extension(VALUE self, VALUE ext)
{
X509_REVOKED *rev;
-
+
GetX509Rev(self, rev);
- if(!X509_REVOKED_add_ext(rev, DupX509ExtPtr(ext), -1)) {
- ossl_raise(eX509RevError, NULL);
+ if (!X509_REVOKED_add_ext(rev, GetX509ExtPtr(ext), -1)) {
+ ossl_raise(eX509RevError, NULL);
}
return ext;
}
+static VALUE
+ossl_x509revoked_to_der(VALUE self)
+{
+ X509_REVOKED *rev;
+ VALUE str;
+ int len;
+ unsigned char *p;
+
+ GetX509Rev(self, rev);
+ len = i2d_X509_REVOKED(rev, NULL);
+ if (len <= 0)
+ ossl_raise(eX509RevError, "i2d_X509_REVOKED");
+ str = rb_str_new(NULL, len);
+ p = (unsigned char *)RSTRING_PTR(str);
+ if (i2d_X509_REVOKED(rev, &p) <= 0)
+ ossl_raise(eX509RevError, "i2d_X509_REVOKED");
+ ossl_str_adjust(str, p);
+ return str;
+}
+
/*
* INIT
*/
void
-Init_ossl_x509revoked()
+Init_ossl_x509revoked(void)
{
eX509RevError = rb_define_class_under(mX509, "RevokedError", eOSSLError);
cX509Rev = rb_define_class_under(mX509, "Revoked", rb_cObject);
-
+
rb_define_alloc_func(cX509Rev, ossl_x509revoked_alloc);
rb_define_method(cX509Rev, "initialize", ossl_x509revoked_initialize, -1);
-
+ rb_define_method(cX509Rev, "initialize_copy", ossl_x509revoked_initialize_copy, 1);
+
rb_define_method(cX509Rev, "serial", ossl_x509revoked_get_serial, 0);
rb_define_method(cX509Rev, "serial=", ossl_x509revoked_set_serial, 1);
rb_define_method(cX509Rev, "time", ossl_x509revoked_get_time, 0);
@@ -225,5 +283,5 @@ Init_ossl_x509revoked()
rb_define_method(cX509Rev, "extensions", ossl_x509revoked_get_extensions, 0);
rb_define_method(cX509Rev, "extensions=", ossl_x509revoked_set_extensions, 1);
rb_define_method(cX509Rev, "add_extension", ossl_x509revoked_add_extension, 1);
+ rb_define_method(cX509Rev, "to_der", ossl_x509revoked_to_der, 0);
}
-
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c
index cea845a1cc..9e43336c44 100644
--- a/ext/openssl/ossl_x509store.c
+++ b/ext/openssl/ossl_x509store.c
@@ -1,104 +1,182 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * This program is licensed under the same licence as Ruby.
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-#include <rubysig.h>
-#define WrapX509Store(klass, obj, st) do { \
- if (!st) { \
- ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
+#define NewX509Store(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_x509store_type, 0)
+#define SetX509Store(obj, st) do { \
+ if (!(st)) { \
+ ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
} \
- obj = Data_Wrap_Struct(klass, 0, X509_STORE_free, st); \
+ RTYPEDDATA_DATA(obj) = (st); \
} while (0)
#define GetX509Store(obj, st) do { \
- Data_Get_Struct(obj, X509_STORE, st); \
- if (!st) { \
- ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
+ TypedData_Get_Struct((obj), X509_STORE, &ossl_x509store_type, (st)); \
+ if (!(st)) { \
+ ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
} \
} while (0)
-#define SafeGetX509Store(obj, st) do { \
- OSSL_Check_Kind(obj, cX509Store); \
- GetX509Store(obj, st); \
-} while (0)
-#define WrapX509StCtx(klass, obj, ctx) do { \
- if (!ctx) { \
- ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
+#define NewX509StCtx(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_x509stctx_type, 0)
+#define SetX509StCtx(obj, ctx) do { \
+ if (!(ctx)) { \
+ ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
} \
- obj = Data_Wrap_Struct(klass, 0, ossl_x509stctx_free, ctx); \
+ RTYPEDDATA_DATA(obj) = (ctx); \
} while (0)
#define GetX509StCtx(obj, ctx) do { \
- Data_Get_Struct(obj, X509_STORE_CTX, ctx); \
- if (!ctx) { \
- ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
+ TypedData_Get_Struct((obj), X509_STORE_CTX, &ossl_x509stctx_type, (ctx)); \
+ if (!(ctx)) { \
+ ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
} \
} while (0)
-#define SafeGetX509StCtx(obj, storep) do { \
- OSSL_Check_Kind(obj, cX509StoreContext); \
- GetX509Store(obj, ctx); \
-} while (0)
/*
- * Classes
+ * Verify callback stuff
*/
-VALUE cX509Store;
-VALUE cX509StoreContext;
-VALUE eX509StoreError;
+static int stctx_ex_verify_cb_idx, store_ex_verify_cb_idx;
+static VALUE ossl_x509stctx_new(X509_STORE_CTX *);
-/*
- * Public functions
- */
-VALUE
-ossl_x509store_new(X509_STORE *store)
-{
- VALUE obj;
+struct ossl_verify_cb_args {
+ VALUE proc;
+ VALUE preverify_ok;
+ VALUE store_ctx;
+};
- WrapX509Store(cX509Store, obj, store);
+static VALUE
+ossl_x509stctx_new_i(VALUE arg)
+{
+ return ossl_x509stctx_new((X509_STORE_CTX *)arg);
+}
- return obj;
+static VALUE
+call_verify_cb_proc(VALUE arg)
+{
+ struct ossl_verify_cb_args *args = (struct ossl_verify_cb_args *)arg;
+ return rb_funcall(args->proc, rb_intern("call"), 2,
+ args->preverify_ok, args->store_ctx);
}
-X509_STORE *
-GetX509StorePtr(VALUE obj)
+int
+ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
{
- X509_STORE *store;
+ VALUE rctx, ret;
+ struct ossl_verify_cb_args args;
+ int state;
- SafeGetX509Store(obj, store);
+ if (NIL_P(proc))
+ return ok;
- return store;
+ ret = Qfalse;
+ rctx = rb_protect(ossl_x509stctx_new_i, (VALUE)ctx, &state);
+ if (state) {
+ rb_set_errinfo(Qnil);
+ rb_warn("StoreContext initialization failure");
+ }
+ else {
+ args.proc = proc;
+ args.preverify_ok = ok ? Qtrue : Qfalse;
+ args.store_ctx = rctx;
+ ret = rb_protect(call_verify_cb_proc, (VALUE)&args, &state);
+ if (state) {
+ rb_set_errinfo(Qnil);
+ rb_warn("exception in verify_callback is ignored");
+ }
+ RTYPEDDATA_DATA(rctx) = NULL;
+ }
+ if (ret == Qtrue) {
+ X509_STORE_CTX_set_error(ctx, X509_V_OK);
+ ok = 1;
+ }
+ else {
+ if (X509_STORE_CTX_get_error(ctx) == X509_V_OK)
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
+ ok = 0;
+ }
+
+ return ok;
}
+/*
+ * Classes
+ */
+static VALUE cX509Store;
+static VALUE cX509StoreContext;
+static VALUE eX509StoreError;
+
+static void
+ossl_x509store_mark(void *ptr)
+{
+ X509_STORE *store = ptr;
+ // Note: this reference is stored as @verify_callback so we don't need to mark it.
+ // However we do need to ensure GC compaction won't move it, hence why
+ // we call rb_gc_mark here.
+ rb_gc_mark((VALUE)X509_STORE_get_ex_data(store, store_ex_verify_cb_idx));
+}
+
+static void
+ossl_x509store_free(void *ptr)
+{
+ X509_STORE_free(ptr);
+}
+
+static const rb_data_type_t ossl_x509store_type = {
+ "OpenSSL/X509/STORE",
+ {
+ ossl_x509store_mark, ossl_x509store_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+/*
+ * Public functions
+ */
X509_STORE *
-DupX509StorePtr(VALUE obj)
-{
+GetX509StorePtr(VALUE obj)
+{
X509_STORE *store;
- SafeGetX509Store(obj, store);
- CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
-
+ GetX509Store(obj, store);
+
return store;
}
/*
* Private functions
*/
-static VALUE
+static int
+x509store_verify_cb(int ok, X509_STORE_CTX *ctx)
+{
+ VALUE proc;
+
+ proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx);
+ if (!proc)
+ proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx),
+ store_ex_verify_cb_idx);
+ if (!proc)
+ return ok;
+
+ return ossl_verify_cb_call(proc, ok, ctx);
+}
+
+static VALUE
ossl_x509store_alloc(VALUE klass)
{
X509_STORE *store;
VALUE obj;
- if((store = X509_STORE_new()) == NULL){
- ossl_raise(eX509StoreError, NULL);
- }
- WrapX509Store(klass, obj, store);
+ obj = NewX509Store(klass);
+ if ((store = X509_STORE_new()) == NULL)
+ ossl_raise(eX509StoreError, "X509_STORE_new");
+ SetX509Store(obj, store);
return obj;
}
@@ -112,146 +190,237 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
X509_STORE *store;
GetX509Store(self, store);
- X509_STORE_set_ex_data(store, ossl_verify_cb_idx, (void*)cb);
+ if (!X509_STORE_set_ex_data(store, store_ex_verify_cb_idx, (void *)cb))
+ ossl_raise(eX509StoreError, "X509_STORE_set_ex_data");
rb_iv_set(self, "@verify_callback", cb);
+ RB_OBJ_WRITTEN(self, Qundef, cb);
return cb;
}
+
+/*
+ * call-seq:
+ * X509::Store.new => store
+ *
+ * Creates a new X509::Store.
+ */
static VALUE
ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
{
X509_STORE *store;
GetX509Store(self, store);
- X509_STORE_set_verify_cb_func(store, ossl_verify_cb);
+ if (argc != 0)
+ rb_warn("OpenSSL::X509::Store.new does not take any arguments");
+ X509_STORE_set_verify_cb(store, x509store_verify_cb);
ossl_x509store_set_vfy_cb(self, Qnil);
-#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
- rb_iv_set(self, "@flags", INT2NUM(0));
- rb_iv_set(self, "@purpose", INT2NUM(0));
- rb_iv_set(self, "@trust", INT2NUM(0));
-#endif
-
/* last verification status */
rb_iv_set(self, "@error", Qnil);
rb_iv_set(self, "@error_string", Qnil);
rb_iv_set(self, "@chain", Qnil);
- rb_iv_set(self, "@time", Qnil);
return self;
}
+/*
+ * call-seq:
+ * store.flags = flags
+ *
+ * Sets the default flags used by certificate chain verification performed with
+ * the Store.
+ *
+ * _flags_ consists of zero or more of the constants defined in OpenSSL::X509
+ * with name V_FLAG_* or'ed together.
+ *
+ * OpenSSL::X509::StoreContext#flags= can be used to change the flags for a
+ * single verification operation.
+ *
+ * See also the man page X509_VERIFY_PARAM_set_flags(3).
+ */
static VALUE
ossl_x509store_set_flags(VALUE self, VALUE flags)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
X509_STORE *store;
long f = NUM2LONG(flags);
GetX509Store(self, store);
X509_STORE_set_flags(store, f);
-#else
- rb_iv_set(self, "@flags", flags);
-#endif
return flags;
}
+/*
+ * call-seq:
+ * store.purpose = purpose
+ *
+ * Sets the store's default verification purpose. If specified,
+ * the verifications on the store will check every certificate's extensions are
+ * consistent with the purpose. The purpose is specified by constants:
+ *
+ * * X509::PURPOSE_SSL_CLIENT
+ * * X509::PURPOSE_SSL_SERVER
+ * * X509::PURPOSE_NS_SSL_SERVER
+ * * X509::PURPOSE_SMIME_SIGN
+ * * X509::PURPOSE_SMIME_ENCRYPT
+ * * X509::PURPOSE_CRL_SIGN
+ * * X509::PURPOSE_ANY
+ * * X509::PURPOSE_OCSP_HELPER
+ * * X509::PURPOSE_TIMESTAMP_SIGN
+ *
+ * OpenSSL::X509::StoreContext#purpose= can be used to change the value for a
+ * single verification operation.
+ *
+ * See also the man page X509_VERIFY_PARAM_set_purpose(3).
+ */
static VALUE
ossl_x509store_set_purpose(VALUE self, VALUE purpose)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
X509_STORE *store;
- long p = NUM2LONG(purpose);
-
+ int p = NUM2INT(purpose);
+
GetX509Store(self, store);
X509_STORE_set_purpose(store, p);
-#else
- rb_iv_set(self, "@purpose", purpose);
-#endif
return purpose;
}
+/*
+ * call-seq:
+ * store.trust = trust
+ *
+ * Sets the default trust settings used by the certificate verification with
+ * the store.
+ *
+ * OpenSSL::X509::StoreContext#trust= can be used to change the value for a
+ * single verification operation.
+ *
+ * See also the man page X509_VERIFY_PARAM_set_trust(3).
+ */
static VALUE
ossl_x509store_set_trust(VALUE self, VALUE trust)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
X509_STORE *store;
- long t = NUM2LONG(trust);
+ int t = NUM2INT(trust);
GetX509Store(self, store);
X509_STORE_set_trust(store, t);
-#else
- rb_iv_set(self, "@trust", trust);
-#endif
return trust;
}
-static VALUE
+/*
+ * call-seq:
+ * store.time = time
+ *
+ * Sets the time to be used in the certificate verifications with the store.
+ * By default, if not specified, the current system time is used.
+ *
+ * OpenSSL::X509::StoreContext#time= can be used to change the value for a
+ * single verification operation.
+ *
+ * See also the man page X509_VERIFY_PARAM_set_time(3).
+ */
+static VALUE
ossl_x509store_set_time(VALUE self, VALUE time)
{
- rb_iv_set(self, "@time", time);
+ X509_STORE *store;
+ X509_VERIFY_PARAM *param;
+
+ GetX509Store(self, store);
+ param = X509_STORE_get0_param(store);
+ X509_VERIFY_PARAM_set_time(param, NUM2LONG(rb_Integer(time)));
return time;
}
-static VALUE
+/*
+ * call-seq:
+ * store.add_file(file) -> self
+ *
+ * Adds the certificates in _file_ to the certificate store. _file_ is the path
+ * to the file, and the file contains one or more certificates in PEM format
+ * concatenated together.
+ *
+ * See also the man page X509_LOOKUP_file(3).
+ */
+static VALUE
ossl_x509store_add_file(VALUE self, VALUE file)
{
X509_STORE *store;
X509_LOOKUP *lookup;
- char *path = NULL;
+ const char *path;
- if(file != Qnil){
- Check_SafeStr(file);
- path = RSTRING(file)->ptr;
- }
GetX509Store(self, store);
+ path = StringValueCStr(file);
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
- if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
- if(X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1){
- ossl_raise(eX509StoreError, NULL);
- }
+ if (!lookup)
+ ossl_raise(eX509StoreError, "X509_STORE_add_lookup");
+ if (X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1)
+ ossl_raise(eX509StoreError, "X509_LOOKUP_load_file");
return self;
}
-static VALUE
+/*
+ * call-seq:
+ * store.add_path(path) -> self
+ *
+ * Adds _path_ as the hash dir to be looked up by the store.
+ *
+ * See also the man page X509_LOOKUP_hash_dir(3).
+ */
+static VALUE
ossl_x509store_add_path(VALUE self, VALUE dir)
{
X509_STORE *store;
X509_LOOKUP *lookup;
- char *path = NULL;
+ const char *path;
- if(dir != Qnil){
- Check_SafeStr(dir);
- path = RSTRING(dir)->ptr;
- }
GetX509Store(self, store);
+ path = StringValueCStr(dir);
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
- if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
- if(X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1){
- ossl_raise(eX509StoreError, NULL);
- }
+ if (!lookup)
+ ossl_raise(eX509StoreError, "X509_STORE_add_lookup");
+ if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1)
+ ossl_raise(eX509StoreError, "X509_LOOKUP_add_dir");
return self;
}
+/*
+ * call-seq:
+ * store.set_default_paths
+ *
+ * Configures _store_ to look up CA certificates from the system default
+ * certificate store as needed basis. The location of the store can usually be
+ * determined by:
+ *
+ * * OpenSSL::X509::DEFAULT_CERT_FILE
+ * * OpenSSL::X509::DEFAULT_CERT_DIR
+ *
+ * See also the man page X509_STORE_set_default_paths(3).
+ */
static VALUE
ossl_x509store_set_default_paths(VALUE self)
{
X509_STORE *store;
GetX509Store(self, store);
- if (X509_STORE_set_default_paths(store) != 1){
- ossl_raise(eX509StoreError, NULL);
- }
+ if (X509_STORE_set_default_paths(store) != 1)
+ ossl_raise(eX509StoreError, "X509_STORE_set_default_paths");
return Qnil;
}
+/*
+ * call-seq:
+ * store.add_cert(cert) -> self
+ *
+ * Adds the OpenSSL::X509::Certificate _cert_ to the certificate store.
+ *
+ * See also the man page X509_STORE_add_cert(3).
+ */
static VALUE
ossl_x509store_add_cert(VALUE self, VALUE arg)
{
@@ -260,13 +429,20 @@ ossl_x509store_add_cert(VALUE self, VALUE arg)
cert = GetX509CertPtr(arg); /* NO NEED TO DUP */
GetX509Store(self, store);
- if (X509_STORE_add_cert(store, cert) != 1){
- ossl_raise(eX509StoreError, NULL);
- }
+ if (X509_STORE_add_cert(store, cert) != 1)
+ ossl_raise(eX509StoreError, "X509_STORE_add_cert");
return self;
}
+/*
+ * call-seq:
+ * store.add_crl(crl) -> self
+ *
+ * Adds the OpenSSL::X509::CRL _crl_ to the store.
+ *
+ * See also the man page X509_STORE_add_crl(3).
+ */
static VALUE
ossl_x509store_add_crl(VALUE self, VALUE arg)
{
@@ -275,9 +451,8 @@ ossl_x509store_add_crl(VALUE self, VALUE arg)
crl = GetX509CRLPtr(arg); /* NO NEED TO DUP */
GetX509Store(self, store);
- if (X509_STORE_add_crl(store, crl) != 1){
- ossl_raise(eX509StoreError, NULL);
- }
+ if (X509_STORE_add_crl(store, crl) != 1)
+ ossl_raise(eX509StoreError, "X509_STORE_add_crl");
return self;
}
@@ -286,7 +461,22 @@ static VALUE ossl_x509stctx_get_err(VALUE);
static VALUE ossl_x509stctx_get_err_string(VALUE);
static VALUE ossl_x509stctx_get_chain(VALUE);
-static VALUE
+/*
+ * call-seq:
+ * store.verify(cert, chain = nil) -> true | false
+ *
+ * Performs a certificate verification on the OpenSSL::X509::Certificate _cert_.
+ *
+ * _chain_ can be an array of OpenSSL::X509::Certificate that is used to
+ * construct the certificate chain.
+ *
+ * If a block is given, it overrides the callback set by #verify_callback=.
+ *
+ * After finishing the verification, the error information can be retrieved by
+ * #error, #error_string, and the resulting complete certificate chain can be
+ * retrieved by #chain.
+ */
+static VALUE
ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
{
VALUE cert, chain;
@@ -295,7 +485,7 @@ ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &cert, &chain);
ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain);
proc = rb_block_given_p() ? rb_block_proc() :
- rb_iv_get(self, "@verify_callback");
+ rb_iv_get(self, "@verify_callback");
rb_iv_set(ctx, "@verify_callback", proc);
result = rb_funcall(ctx, rb_intern("verify"), 0);
@@ -307,52 +497,56 @@ ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
}
/*
- * Public Functions
+ * Private functions
*/
-static void ossl_x509stctx_free(X509_STORE_CTX*);
-
-VALUE
-ossl_x509stctx_new(X509_STORE_CTX *ctx)
-{
- VALUE obj;
-
- WrapX509StCtx(cX509StoreContext, obj, ctx);
-
- return obj;
-}
-
-VALUE
-ossl_x509stctx_clear_ptr(VALUE obj)
+static void
+ossl_x509stctx_mark(void *ptr)
{
- OSSL_Check_Kind(obj, cX509StoreContext);
- RDATA(obj)->data = NULL;
-
- return obj;
+ X509_STORE_CTX *ctx = ptr;
+ // Note: this reference is stored as @verify_callback so we don't need to mark it.
+ // However we do need to ensure GC compaction won't move it, hence why
+ // we call rb_gc_mark here.
+ rb_gc_mark((VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx));
}
-/*
- * Private functions
- */
static void
-ossl_x509stctx_free(X509_STORE_CTX *ctx)
+ossl_x509stctx_free(void *ptr)
{
- if(ctx->untrusted)
- sk_X509_pop_free(ctx->untrusted, X509_free);
- if(ctx->cert)
- X509_free(ctx->cert);
+ X509_STORE_CTX *ctx = ptr;
+ sk_X509_pop_free(X509_STORE_CTX_get0_untrusted(ctx), X509_free);
+ X509_free((X509 *)X509_STORE_CTX_get0_cert(ctx));
X509_STORE_CTX_free(ctx);
}
-static VALUE
+static const rb_data_type_t ossl_x509stctx_type = {
+ "OpenSSL/X509/STORE_CTX",
+ {
+ ossl_x509stctx_mark, ossl_x509stctx_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static VALUE
ossl_x509stctx_alloc(VALUE klass)
{
X509_STORE_CTX *ctx;
VALUE obj;
- if((ctx = X509_STORE_CTX_new()) == NULL){
- ossl_raise(eX509StoreError, NULL);
- }
- WrapX509StCtx(klass, obj, ctx);
+ obj = NewX509StCtx(klass);
+ if ((ctx = X509_STORE_CTX_new()) == NULL)
+ ossl_raise(eX509StoreError, "X509_STORE_CTX_new");
+ SetX509StCtx(obj, ctx);
+
+ return obj;
+}
+
+static VALUE
+ossl_x509stctx_new(X509_STORE_CTX *ctx)
+{
+ VALUE obj;
+
+ obj = NewX509StCtx(cX509StoreContext);
+ SetX509StCtx(obj, ctx);
return obj;
}
@@ -360,103 +554,147 @@ ossl_x509stctx_alloc(VALUE klass)
static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
-static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
+/*
+ * call-seq:
+ * StoreContext.new(store, cert = nil, untrusted = nil)
+ *
+ * Sets up a StoreContext for a verification of the X.509 certificate _cert_.
+ */
static VALUE
ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
{
- VALUE store, cert, chain, t;
+ VALUE store, cert, chain;
X509_STORE_CTX *ctx;
X509_STORE *x509st;
X509 *x509 = NULL;
STACK_OF(X509) *x509s = NULL;
+ int state;
rb_scan_args(argc, argv, "12", &store, &cert, &chain);
GetX509StCtx(self, ctx);
- SafeGetX509Store(store, x509st);
- if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */
- if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
-#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
- if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
+ GetX509Store(store, x509st);
+ if (!NIL_P(cert))
+ x509 = DupX509CertPtr(cert); /* NEED TO DUP */
+ if (!NIL_P(chain)) {
+ x509s = ossl_protect_x509_ary2sk(chain, &state);
+ if (state) {
+ X509_free(x509);
+ rb_jump_tag(state);
+ }
+ }
+ if (X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
+ X509_free(x509);
sk_X509_pop_free(x509s, X509_free);
- ossl_raise(eX509StoreError, NULL);
+ ossl_raise(eX509StoreError, "X509_STORE_CTX_init");
}
-#else
- X509_STORE_CTX_init(ctx, x509st, x509, x509s);
- ossl_x509stctx_set_flags(self, rb_iv_get(store, "@flags"));
- ossl_x509stctx_set_purpose(self, rb_iv_get(store, "@purpose"));
- ossl_x509stctx_set_trust(self, rb_iv_get(store, "@trust"));
-#endif
- if (!NIL_P(t = rb_iv_get(store, "@time")))
- ossl_x509stctx_set_time(self, t);
rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback"));
rb_iv_set(self, "@cert", cert);
return self;
}
+/*
+ * call-seq:
+ * stctx.verify -> true | false
+ *
+ * Performs the certificate verification using the parameters set to _stctx_.
+ *
+ * See also the man page X509_verify_cert(3).
+ */
static VALUE
ossl_x509stctx_verify(VALUE self)
{
X509_STORE_CTX *ctx;
- int result;
GetX509StCtx(self, ctx);
- X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx,
- (void*)rb_iv_get(self, "@verify_callback"));
- result = X509_verify_cert(ctx);
-
- return result ? Qtrue : Qfalse;
+ VALUE cb = rb_iv_get(self, "@verify_callback");
+ if (!X509_STORE_CTX_set_ex_data(ctx, stctx_ex_verify_cb_idx, (void *)cb))
+ ossl_raise(eX509StoreError, "X509_STORE_CTX_set_ex_data");
+ RB_OBJ_WRITTEN(self, Qundef, cb);
+
+ switch (X509_verify_cert(ctx)) {
+ case 1:
+ return Qtrue;
+ case 0:
+ ossl_clear_error();
+ return Qfalse;
+ default:
+ ossl_raise(eX509StoreError, "X509_verify_cert");
+ }
}
+/*
+ * call-seq:
+ * stctx.chain -> nil | Array of X509::Certificate
+ *
+ * Returns the verified chain.
+ *
+ * See also the man page X509_STORE_CTX_set0_verified_chain(3).
+ */
static VALUE
ossl_x509stctx_get_chain(VALUE self)
{
X509_STORE_CTX *ctx;
- STACK_OF(X509) *chain;
- X509 *x509;
- int i, num;
- VALUE ary;
+ const STACK_OF(X509) *chain;
GetX509StCtx(self, ctx);
- if((chain = X509_STORE_CTX_get_chain(ctx)) == NULL){
- return Qnil;
- }
- if((num = sk_X509_num(chain)) < 0){
- OSSL_Debug("certs in chain < 0???");
- return rb_ary_new();
- }
- ary = rb_ary_new2(num);
- for(i = 0; i < num; i++) {
- x509 = sk_X509_value(chain, i);
- rb_ary_push(ary, ossl_x509_new(x509));
- }
-
- return ary;
+ chain = X509_STORE_CTX_get0_chain(ctx);
+ if (!chain)
+ return Qnil; /* Could be an empty array instead? */
+ return ossl_x509_sk2ary(chain);
}
-static VALUE
+/*
+ * call-seq:
+ * stctx.error -> Integer
+ *
+ * Returns the error code of _stctx_. This is typically called after #verify
+ * is done, or from the verification callback set to
+ * OpenSSL::X509::Store#verify_callback=.
+ *
+ * See also the man page X509_STORE_CTX_get_error(3).
+ */
+static VALUE
ossl_x509stctx_get_err(VALUE self)
{
X509_STORE_CTX *ctx;
GetX509StCtx(self, ctx);
- return INT2FIX(X509_STORE_CTX_get_error(ctx));
+ return INT2NUM(X509_STORE_CTX_get_error(ctx));
}
+/*
+ * call-seq:
+ * stctx.error = error_code
+ *
+ * Sets the error code of _stctx_. This is used by the verification callback
+ * set to OpenSSL::X509::Store#verify_callback=.
+ *
+ * See also the man page X509_STORE_CTX_set_error(3).
+ */
static VALUE
ossl_x509stctx_set_error(VALUE self, VALUE err)
{
X509_STORE_CTX *ctx;
GetX509StCtx(self, ctx);
- X509_STORE_CTX_set_error(ctx, FIX2INT(err));
+ X509_STORE_CTX_set_error(ctx, NUM2INT(err));
return err;
}
-static VALUE
+/*
+ * call-seq:
+ * stctx.error_string -> String
+ *
+ * Returns the human readable error string corresponding to the error code
+ * retrieved by #error.
+ *
+ * See also the man page X509_verify_cert_error_string(3).
+ */
+static VALUE
ossl_x509stctx_get_err_string(VALUE self)
{
X509_STORE_CTX *ctx;
@@ -468,52 +706,77 @@ ossl_x509stctx_get_err_string(VALUE self)
return rb_str_new2(X509_verify_cert_error_string(err));
}
-static VALUE
+/*
+ * call-seq:
+ * stctx.error_depth -> Integer
+ *
+ * Returns the depth of the chain. This is used in combination with #error.
+ *
+ * See also the man page X509_STORE_CTX_get_error_depth(3).
+ */
+static VALUE
ossl_x509stctx_get_err_depth(VALUE self)
{
X509_STORE_CTX *ctx;
GetX509StCtx(self, ctx);
- return INT2FIX(X509_STORE_CTX_get_error_depth(ctx));
+ return INT2NUM(X509_STORE_CTX_get_error_depth(ctx));
}
-static VALUE
+/*
+ * call-seq:
+ * stctx.current_cert -> X509::Certificate
+ *
+ * Returns the certificate which caused the error.
+ *
+ * See also the man page X509_STORE_CTX_get_current_cert(3).
+ */
+static VALUE
ossl_x509stctx_get_curr_cert(VALUE self)
{
X509_STORE_CTX *ctx;
+ const X509 *x509;
GetX509StCtx(self, ctx);
+ x509 = X509_STORE_CTX_get_current_cert(ctx);
+ if (!x509)
+ return Qnil;
- return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
+ return ossl_x509_new(x509);
}
+/*
+ * call-seq:
+ * stctx.current_crl -> X509::CRL
+ *
+ * Returns the CRL which caused the error.
+ *
+ * See also the man page X509_STORE_CTX_get_current_crl(3).
+ */
static VALUE
ossl_x509stctx_get_curr_crl(VALUE self)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
- X509_STORE_CTX *ctx;
-
- GetX509StCtx(self, ctx);
- if(!ctx->current_crl) return Qnil;
-
- return ossl_x509crl_new(ctx->current_crl);
-#else
- return Qnil;
-#endif
-}
-
-static VALUE
-ossl_x509stctx_cleanup(VALUE self)
-{
X509_STORE_CTX *ctx;
+ const X509_CRL *crl;
GetX509StCtx(self, ctx);
- X509_STORE_CTX_cleanup(ctx);
+ crl = X509_STORE_CTX_get0_current_crl(ctx);
+ if (!crl)
+ return Qnil;
- return self;
+ return ossl_x509crl_new(crl);
}
+/*
+ * call-seq:
+ * stctx.flags = flags
+ *
+ * Sets the verification flags to the context. This overrides the default value
+ * set by Store#flags=.
+ *
+ * See also the man page X509_VERIFY_PARAM_set_flags(3).
+ */
static VALUE
ossl_x509stctx_set_flags(VALUE self, VALUE flags)
{
@@ -526,11 +789,20 @@ ossl_x509stctx_set_flags(VALUE self, VALUE flags)
return flags;
}
+/*
+ * call-seq:
+ * stctx.purpose = purpose
+ *
+ * Sets the purpose of the context. This overrides the default value set by
+ * Store#purpose=.
+ *
+ * See also the man page X509_VERIFY_PARAM_set_purpose(3).
+ */
static VALUE
ossl_x509stctx_set_purpose(VALUE self, VALUE purpose)
{
X509_STORE_CTX *store;
- long p = NUM2LONG(purpose);
+ int p = NUM2INT(purpose);
GetX509StCtx(self, store);
X509_STORE_CTX_set_purpose(store, p);
@@ -538,11 +810,20 @@ ossl_x509stctx_set_purpose(VALUE self, VALUE purpose)
return purpose;
}
+/*
+ * call-seq:
+ * stctx.trust = trust
+ *
+ * Sets the trust settings of the context. This overrides the default value set
+ * by Store#trust=.
+ *
+ * See also the man page X509_VERIFY_PARAM_set_trust(3).
+ */
static VALUE
ossl_x509stctx_set_trust(VALUE self, VALUE trust)
{
X509_STORE_CTX *store;
- long t = NUM2LONG(trust);
+ int t = NUM2INT(trust);
GetX509StCtx(self, store);
X509_STORE_CTX_set_trust(store, t);
@@ -550,6 +831,14 @@ ossl_x509stctx_set_trust(VALUE self, VALUE trust)
return trust;
}
+/*
+ * call-seq:
+ * stctx.time = time
+ *
+ * Sets the time used in the verification. If not set, the current time is used.
+ *
+ * See also the man page X509_VERIFY_PARAM_set_time(3).
+ */
static VALUE
ossl_x509stctx_set_time(VALUE self, VALUE time)
{
@@ -566,20 +855,94 @@ ossl_x509stctx_set_time(VALUE self, VALUE time)
/*
* INIT
*/
-void
-Init_ossl_x509store()
-{
- VALUE x509stctx;
+void
+Init_ossl_x509store(void)
+{
+#undef rb_intern
+ /* Register ext_data slot for verify callback Proc */
+ stctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"stctx_ex_verify_cb_idx", 0, 0, 0);
+ if (stctx_ex_verify_cb_idx < 0)
+ ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
+ store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"store_ex_verify_cb_idx", 0, 0, 0);
+ if (store_ex_verify_cb_idx < 0)
+ ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index");
eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError);
+ /* Document-class: OpenSSL::X509::Store
+ *
+ * The X509 certificate store holds trusted CA certificates used to verify
+ * peer certificates.
+ *
+ * The easiest way to create a useful certificate store is:
+ *
+ * cert_store = OpenSSL::X509::Store.new
+ * cert_store.set_default_paths
+ *
+ * This will use your system's built-in certificates.
+ *
+ * If your system does not have a default set of certificates you can obtain
+ * a set extracted from Mozilla CA certificate store by cURL maintainers
+ * here: https://curl.haxx.se/docs/caextract.html (You may wish to use the
+ * firefox-db2pem.sh script to extract the certificates from a local install
+ * to avoid man-in-the-middle attacks.)
+ *
+ * After downloading or generating a cacert.pem from the above link you
+ * can create a certificate store from the pem file like this:
+ *
+ * cert_store = OpenSSL::X509::Store.new
+ * cert_store.add_file 'cacert.pem'
+ *
+ * The certificate store can be used with an SSLSocket like this:
+ *
+ * ssl_context = OpenSSL::SSL::SSLContext.new
+ * ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
+ * ssl_context.cert_store = cert_store
+ *
+ * tcp_socket = TCPSocket.open 'example.com', 443
+ *
+ * ssl_socket = OpenSSL::SSL::SSLSocket.new tcp_socket, ssl_context
+ */
+
cX509Store = rb_define_class_under(mX509, "Store", rb_cObject);
+ /*
+ * The callback for additional certificate verification. It is invoked for
+ * each certificate in the chain and can be used to implement custom
+ * certificate verification conditions.
+ *
+ * The callback is invoked with two values, a boolean that indicates if the
+ * pre-verification by OpenSSL has succeeded or not, and the StoreContext in
+ * use.
+ *
+ * The callback can use StoreContext#error= to change the error code as
+ * needed. The callback must return either true or false.
+ *
+ * NOTE: any exception raised within the callback will be ignored.
+ *
+ * See also the man page X509_STORE_CTX_set_verify_cb(3).
+ */
rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse);
+ /*
+ * The error code set by the last call of #verify.
+ *
+ * See also StoreContext#error.
+ */
rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse);
+ /*
+ * The description for the error code set by the last call of #verify.
+ *
+ * See also StoreContext#error_string.
+ */
rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse);
+ /*
+ * The certificate chain constructed by the last call of #verify.
+ *
+ * See also StoreContext#chain.
+ */
rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse);
rb_define_alloc_func(cX509Store, ossl_x509store_alloc);
rb_define_method(cX509Store, "initialize", ossl_x509store_initialize, -1);
+ rb_undef_method(cX509Store, "initialize_copy");
rb_define_method(cX509Store, "verify_callback=", ossl_x509store_set_vfy_cb, 1);
rb_define_method(cX509Store, "flags=", ossl_x509store_set_flags, 1);
rb_define_method(cX509Store, "purpose=", ossl_x509store_set_purpose, 1);
@@ -592,22 +955,26 @@ Init_ossl_x509store()
rb_define_method(cX509Store, "add_crl", ossl_x509store_add_crl, 1);
rb_define_method(cX509Store, "verify", ossl_x509store_verify, -1);
- cX509StoreContext = rb_define_class_under(mX509,"StoreContext",rb_cObject);
- x509stctx = cX509StoreContext;
+ /*
+ * Document-class: OpenSSL::X509::StoreContext
+ *
+ * A StoreContext is used while validating a single certificate and holds
+ * the status involved.
+ */
+ cX509StoreContext = rb_define_class_under(mX509,"StoreContext", rb_cObject);
rb_define_alloc_func(cX509StoreContext, ossl_x509stctx_alloc);
- rb_define_method(x509stctx,"initialize", ossl_x509stctx_initialize, -1);
- rb_define_method(x509stctx,"verify", ossl_x509stctx_verify, 0);
- rb_define_method(x509stctx,"chain", ossl_x509stctx_get_chain,0);
- rb_define_method(x509stctx,"error", ossl_x509stctx_get_err, 0);
- rb_define_method(x509stctx,"error=", ossl_x509stctx_set_error, 1);
- rb_define_method(x509stctx,"error_string",ossl_x509stctx_get_err_string,0);
- rb_define_method(x509stctx,"error_depth", ossl_x509stctx_get_err_depth, 0);
- rb_define_method(x509stctx,"current_cert",ossl_x509stctx_get_curr_cert, 0);
- rb_define_method(x509stctx,"current_crl", ossl_x509stctx_get_curr_crl, 0);
- rb_define_method(x509stctx,"cleanup", ossl_x509stctx_cleanup, 0);
- rb_define_method(x509stctx,"flags=", ossl_x509stctx_set_flags, 1);
- rb_define_method(x509stctx,"purpose=", ossl_x509stctx_set_purpose, 1);
- rb_define_method(x509stctx,"trust=", ossl_x509stctx_set_trust, 1);
- rb_define_method(x509stctx,"time=", ossl_x509stctx_set_time, 1);
-
+ rb_define_method(cX509StoreContext, "initialize", ossl_x509stctx_initialize, -1);
+ rb_undef_method(cX509StoreContext, "initialize_copy");
+ rb_define_method(cX509StoreContext, "verify", ossl_x509stctx_verify, 0);
+ rb_define_method(cX509StoreContext, "chain", ossl_x509stctx_get_chain,0);
+ rb_define_method(cX509StoreContext, "error", ossl_x509stctx_get_err, 0);
+ rb_define_method(cX509StoreContext, "error=", ossl_x509stctx_set_error, 1);
+ rb_define_method(cX509StoreContext, "error_string", ossl_x509stctx_get_err_string,0);
+ rb_define_method(cX509StoreContext, "error_depth", ossl_x509stctx_get_err_depth, 0);
+ rb_define_method(cX509StoreContext, "current_cert", ossl_x509stctx_get_curr_cert, 0);
+ rb_define_method(cX509StoreContext, "current_crl", ossl_x509stctx_get_curr_crl, 0);
+ rb_define_method(cX509StoreContext, "flags=", ossl_x509stctx_set_flags, 1);
+ rb_define_method(cX509StoreContext, "purpose=", ossl_x509stctx_set_purpose, 1);
+ rb_define_method(cX509StoreContext, "trust=", ossl_x509stctx_set_trust, 1);
+ rb_define_method(cX509StoreContext, "time=", ossl_x509stctx_set_time, 1);
}
diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h
deleted file mode 100644
index 4bd08890f8..0000000000
--- a/ext/openssl/ruby_missing.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * $Id$
- * 'OpenSSL for Ruby' project
- * Copyright (C) 2001-2003 Michal Rokos <m.rokos@sh.cvut.cz>
- * All rights reserved.
- */
-/*
- * This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
- */
-#if !defined(_OSSL_RUBY_MISSING_H_)
-#define _OSS_RUBY_MISSING_H_
-
-#define rb_define_copy_func(klass, func) \
- rb_define_method(klass, "initialize_copy", func, 1)
-
-#endif /* _OSS_RUBY_MISSING_H_ */
-
diff --git a/ext/psych/.gitignore b/ext/psych/.gitignore
new file mode 100644
index 0000000000..92946455b0
--- /dev/null
+++ b/ext/psych/.gitignore
@@ -0,0 +1 @@
+/yaml-[0-9]*.*.*
diff --git a/ext/psych/depend b/ext/psych/depend
new file mode 100644
index 0000000000..95175841a2
--- /dev/null
+++ b/ext/psych/depend
@@ -0,0 +1,906 @@
+$(TARGET_SO): $(LIBYAML)
+
+libyaml $(LIBYAML):
+ cd libyaml && $(MAKE)
+ $(AR) $(ARFLAGS) $(LIBYAML) $(LIBYAML_OBJDIR)/*.$(OBJEXT)
+ $(RANLIB) $(LIBYAML)
+
+clean-so::
+ -cd libyaml && $(MAKE) clean
+
+distclean-so::
+ -cd libyaml && $(MAKE) distclean
+ -$(Q)$(RMDIRS) libyaml/* libyaml
+
+# AUTOGENERATED DEPENDENCIES START
+psych.o: $(RUBY_EXTCONF_H)
+psych.o: $(arch_hdrdir)/ruby/config.h
+psych.o: $(hdrdir)/ruby.h
+psych.o: $(hdrdir)/ruby/assert.h
+psych.o: $(hdrdir)/ruby/backward.h
+psych.o: $(hdrdir)/ruby/backward/2/assume.h
+psych.o: $(hdrdir)/ruby/backward/2/attributes.h
+psych.o: $(hdrdir)/ruby/backward/2/bool.h
+psych.o: $(hdrdir)/ruby/backward/2/inttypes.h
+psych.o: $(hdrdir)/ruby/backward/2/limits.h
+psych.o: $(hdrdir)/ruby/backward/2/long_long.h
+psych.o: $(hdrdir)/ruby/backward/2/stdalign.h
+psych.o: $(hdrdir)/ruby/backward/2/stdarg.h
+psych.o: $(hdrdir)/ruby/defines.h
+psych.o: $(hdrdir)/ruby/encoding.h
+psych.o: $(hdrdir)/ruby/intern.h
+psych.o: $(hdrdir)/ruby/internal/abi.h
+psych.o: $(hdrdir)/ruby/internal/anyargs.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+psych.o: $(hdrdir)/ruby/internal/assume.h
+psych.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+psych.o: $(hdrdir)/ruby/internal/attr/artificial.h
+psych.o: $(hdrdir)/ruby/internal/attr/cold.h
+psych.o: $(hdrdir)/ruby/internal/attr/const.h
+psych.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+psych.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+psych.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+psych.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+psych.o: $(hdrdir)/ruby/internal/attr/error.h
+psych.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+psych.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+psych.o: $(hdrdir)/ruby/internal/attr/format.h
+psych.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+psych.o: $(hdrdir)/ruby/internal/attr/noalias.h
+psych.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+psych.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+psych.o: $(hdrdir)/ruby/internal/attr/noinline.h
+psych.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+psych.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+psych.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+psych.o: $(hdrdir)/ruby/internal/attr/pure.h
+psych.o: $(hdrdir)/ruby/internal/attr/restrict.h
+psych.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+psych.o: $(hdrdir)/ruby/internal/attr/warning.h
+psych.o: $(hdrdir)/ruby/internal/attr/weakref.h
+psych.o: $(hdrdir)/ruby/internal/cast.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+psych.o: $(hdrdir)/ruby/internal/compiler_since.h
+psych.o: $(hdrdir)/ruby/internal/config.h
+psych.o: $(hdrdir)/ruby/internal/constant_p.h
+psych.o: $(hdrdir)/ruby/internal/core.h
+psych.o: $(hdrdir)/ruby/internal/core/rarray.h
+psych.o: $(hdrdir)/ruby/internal/core/rbasic.h
+psych.o: $(hdrdir)/ruby/internal/core/rbignum.h
+psych.o: $(hdrdir)/ruby/internal/core/rclass.h
+psych.o: $(hdrdir)/ruby/internal/core/rdata.h
+psych.o: $(hdrdir)/ruby/internal/core/rfile.h
+psych.o: $(hdrdir)/ruby/internal/core/rhash.h
+psych.o: $(hdrdir)/ruby/internal/core/robject.h
+psych.o: $(hdrdir)/ruby/internal/core/rregexp.h
+psych.o: $(hdrdir)/ruby/internal/core/rstring.h
+psych.o: $(hdrdir)/ruby/internal/core/rstruct.h
+psych.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+psych.o: $(hdrdir)/ruby/internal/ctype.h
+psych.o: $(hdrdir)/ruby/internal/dllexport.h
+psych.o: $(hdrdir)/ruby/internal/dosish.h
+psych.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+psych.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+psych.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+psych.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+psych.o: $(hdrdir)/ruby/internal/encoding/re.h
+psych.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+psych.o: $(hdrdir)/ruby/internal/encoding/string.h
+psych.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+psych.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+psych.o: $(hdrdir)/ruby/internal/error.h
+psych.o: $(hdrdir)/ruby/internal/eval.h
+psych.o: $(hdrdir)/ruby/internal/event.h
+psych.o: $(hdrdir)/ruby/internal/fl_type.h
+psych.o: $(hdrdir)/ruby/internal/gc.h
+psych.o: $(hdrdir)/ruby/internal/glob.h
+psych.o: $(hdrdir)/ruby/internal/globals.h
+psych.o: $(hdrdir)/ruby/internal/has/attribute.h
+psych.o: $(hdrdir)/ruby/internal/has/builtin.h
+psych.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+psych.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+psych.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+psych.o: $(hdrdir)/ruby/internal/has/extension.h
+psych.o: $(hdrdir)/ruby/internal/has/feature.h
+psych.o: $(hdrdir)/ruby/internal/has/warning.h
+psych.o: $(hdrdir)/ruby/internal/intern/array.h
+psych.o: $(hdrdir)/ruby/internal/intern/bignum.h
+psych.o: $(hdrdir)/ruby/internal/intern/class.h
+psych.o: $(hdrdir)/ruby/internal/intern/compar.h
+psych.o: $(hdrdir)/ruby/internal/intern/complex.h
+psych.o: $(hdrdir)/ruby/internal/intern/cont.h
+psych.o: $(hdrdir)/ruby/internal/intern/dir.h
+psych.o: $(hdrdir)/ruby/internal/intern/enum.h
+psych.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+psych.o: $(hdrdir)/ruby/internal/intern/error.h
+psych.o: $(hdrdir)/ruby/internal/intern/eval.h
+psych.o: $(hdrdir)/ruby/internal/intern/file.h
+psych.o: $(hdrdir)/ruby/internal/intern/hash.h
+psych.o: $(hdrdir)/ruby/internal/intern/io.h
+psych.o: $(hdrdir)/ruby/internal/intern/load.h
+psych.o: $(hdrdir)/ruby/internal/intern/marshal.h
+psych.o: $(hdrdir)/ruby/internal/intern/numeric.h
+psych.o: $(hdrdir)/ruby/internal/intern/object.h
+psych.o: $(hdrdir)/ruby/internal/intern/parse.h
+psych.o: $(hdrdir)/ruby/internal/intern/proc.h
+psych.o: $(hdrdir)/ruby/internal/intern/process.h
+psych.o: $(hdrdir)/ruby/internal/intern/random.h
+psych.o: $(hdrdir)/ruby/internal/intern/range.h
+psych.o: $(hdrdir)/ruby/internal/intern/rational.h
+psych.o: $(hdrdir)/ruby/internal/intern/re.h
+psych.o: $(hdrdir)/ruby/internal/intern/ruby.h
+psych.o: $(hdrdir)/ruby/internal/intern/select.h
+psych.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych.o: $(hdrdir)/ruby/internal/intern/set.h
+psych.o: $(hdrdir)/ruby/internal/intern/signal.h
+psych.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+psych.o: $(hdrdir)/ruby/internal/intern/string.h
+psych.o: $(hdrdir)/ruby/internal/intern/struct.h
+psych.o: $(hdrdir)/ruby/internal/intern/thread.h
+psych.o: $(hdrdir)/ruby/internal/intern/time.h
+psych.o: $(hdrdir)/ruby/internal/intern/variable.h
+psych.o: $(hdrdir)/ruby/internal/intern/vm.h
+psych.o: $(hdrdir)/ruby/internal/interpreter.h
+psych.o: $(hdrdir)/ruby/internal/iterator.h
+psych.o: $(hdrdir)/ruby/internal/memory.h
+psych.o: $(hdrdir)/ruby/internal/method.h
+psych.o: $(hdrdir)/ruby/internal/module.h
+psych.o: $(hdrdir)/ruby/internal/newobj.h
+psych.o: $(hdrdir)/ruby/internal/scan_args.h
+psych.o: $(hdrdir)/ruby/internal/special_consts.h
+psych.o: $(hdrdir)/ruby/internal/static_assert.h
+psych.o: $(hdrdir)/ruby/internal/stdalign.h
+psych.o: $(hdrdir)/ruby/internal/stdbool.h
+psych.o: $(hdrdir)/ruby/internal/stdckdint.h
+psych.o: $(hdrdir)/ruby/internal/symbol.h
+psych.o: $(hdrdir)/ruby/internal/value.h
+psych.o: $(hdrdir)/ruby/internal/value_type.h
+psych.o: $(hdrdir)/ruby/internal/variable.h
+psych.o: $(hdrdir)/ruby/internal/warning_push.h
+psych.o: $(hdrdir)/ruby/internal/xmalloc.h
+psych.o: $(hdrdir)/ruby/missing.h
+psych.o: $(hdrdir)/ruby/onigmo.h
+psych.o: $(hdrdir)/ruby/oniguruma.h
+psych.o: $(hdrdir)/ruby/ruby.h
+psych.o: $(hdrdir)/ruby/st.h
+psych.o: $(hdrdir)/ruby/subst.h
+psych.o: psych.c
+psych.o: psych.h
+psych.o: psych_emitter.h
+psych.o: psych_parser.h
+psych.o: psych_to_ruby.h
+psych.o: psych_yaml_tree.h
+psych_emitter.o: $(RUBY_EXTCONF_H)
+psych_emitter.o: $(arch_hdrdir)/ruby/config.h
+psych_emitter.o: $(hdrdir)/ruby.h
+psych_emitter.o: $(hdrdir)/ruby/assert.h
+psych_emitter.o: $(hdrdir)/ruby/backward.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/assume.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/attributes.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/bool.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/inttypes.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/limits.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/long_long.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/stdalign.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/stdarg.h
+psych_emitter.o: $(hdrdir)/ruby/defines.h
+psych_emitter.o: $(hdrdir)/ruby/encoding.h
+psych_emitter.o: $(hdrdir)/ruby/intern.h
+psych_emitter.o: $(hdrdir)/ruby/internal/abi.h
+psych_emitter.o: $(hdrdir)/ruby/internal/anyargs.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/assume.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/artificial.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/cold.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/const.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/error.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/format.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/noalias.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/noinline.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/pure.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/restrict.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/warning.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/weakref.h
+psych_emitter.o: $(hdrdir)/ruby/internal/cast.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_since.h
+psych_emitter.o: $(hdrdir)/ruby/internal/config.h
+psych_emitter.o: $(hdrdir)/ruby/internal/constant_p.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rarray.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rbasic.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rbignum.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rclass.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rdata.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rfile.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rhash.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/robject.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rregexp.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rstring.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rstruct.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+psych_emitter.o: $(hdrdir)/ruby/internal/ctype.h
+psych_emitter.o: $(hdrdir)/ruby/internal/dllexport.h
+psych_emitter.o: $(hdrdir)/ruby/internal/dosish.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/re.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/string.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+psych_emitter.o: $(hdrdir)/ruby/internal/error.h
+psych_emitter.o: $(hdrdir)/ruby/internal/eval.h
+psych_emitter.o: $(hdrdir)/ruby/internal/event.h
+psych_emitter.o: $(hdrdir)/ruby/internal/fl_type.h
+psych_emitter.o: $(hdrdir)/ruby/internal/gc.h
+psych_emitter.o: $(hdrdir)/ruby/internal/glob.h
+psych_emitter.o: $(hdrdir)/ruby/internal/globals.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/attribute.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/builtin.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/extension.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/feature.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/warning.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/array.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/bignum.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/class.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/compar.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/complex.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/cont.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/dir.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/enum.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/error.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/eval.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/file.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/hash.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/io.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/load.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/marshal.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/numeric.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/object.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/parse.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/proc.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/process.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/random.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/range.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/rational.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/re.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/ruby.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/select.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/set.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/signal.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/string.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/struct.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/thread.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/time.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/variable.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/vm.h
+psych_emitter.o: $(hdrdir)/ruby/internal/interpreter.h
+psych_emitter.o: $(hdrdir)/ruby/internal/iterator.h
+psych_emitter.o: $(hdrdir)/ruby/internal/memory.h
+psych_emitter.o: $(hdrdir)/ruby/internal/method.h
+psych_emitter.o: $(hdrdir)/ruby/internal/module.h
+psych_emitter.o: $(hdrdir)/ruby/internal/newobj.h
+psych_emitter.o: $(hdrdir)/ruby/internal/scan_args.h
+psych_emitter.o: $(hdrdir)/ruby/internal/special_consts.h
+psych_emitter.o: $(hdrdir)/ruby/internal/static_assert.h
+psych_emitter.o: $(hdrdir)/ruby/internal/stdalign.h
+psych_emitter.o: $(hdrdir)/ruby/internal/stdbool.h
+psych_emitter.o: $(hdrdir)/ruby/internal/stdckdint.h
+psych_emitter.o: $(hdrdir)/ruby/internal/symbol.h
+psych_emitter.o: $(hdrdir)/ruby/internal/value.h
+psych_emitter.o: $(hdrdir)/ruby/internal/value_type.h
+psych_emitter.o: $(hdrdir)/ruby/internal/variable.h
+psych_emitter.o: $(hdrdir)/ruby/internal/warning_push.h
+psych_emitter.o: $(hdrdir)/ruby/internal/xmalloc.h
+psych_emitter.o: $(hdrdir)/ruby/missing.h
+psych_emitter.o: $(hdrdir)/ruby/onigmo.h
+psych_emitter.o: $(hdrdir)/ruby/oniguruma.h
+psych_emitter.o: $(hdrdir)/ruby/ruby.h
+psych_emitter.o: $(hdrdir)/ruby/st.h
+psych_emitter.o: $(hdrdir)/ruby/subst.h
+psych_emitter.o: psych.h
+psych_emitter.o: psych_emitter.c
+psych_emitter.o: psych_emitter.h
+psych_emitter.o: psych_parser.h
+psych_emitter.o: psych_to_ruby.h
+psych_emitter.o: psych_yaml_tree.h
+psych_parser.o: $(RUBY_EXTCONF_H)
+psych_parser.o: $(arch_hdrdir)/ruby/config.h
+psych_parser.o: $(hdrdir)/ruby.h
+psych_parser.o: $(hdrdir)/ruby/assert.h
+psych_parser.o: $(hdrdir)/ruby/backward.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/assume.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/attributes.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/bool.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/inttypes.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/limits.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/long_long.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/stdalign.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/stdarg.h
+psych_parser.o: $(hdrdir)/ruby/defines.h
+psych_parser.o: $(hdrdir)/ruby/encoding.h
+psych_parser.o: $(hdrdir)/ruby/intern.h
+psych_parser.o: $(hdrdir)/ruby/internal/abi.h
+psych_parser.o: $(hdrdir)/ruby/internal/anyargs.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/assume.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/artificial.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/cold.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/const.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/error.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/format.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/noalias.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/noinline.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/pure.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/restrict.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/warning.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/weakref.h
+psych_parser.o: $(hdrdir)/ruby/internal/cast.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_since.h
+psych_parser.o: $(hdrdir)/ruby/internal/config.h
+psych_parser.o: $(hdrdir)/ruby/internal/constant_p.h
+psych_parser.o: $(hdrdir)/ruby/internal/core.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rarray.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rbasic.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rbignum.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rclass.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rdata.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rfile.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rhash.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/robject.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rregexp.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rstring.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rstruct.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+psych_parser.o: $(hdrdir)/ruby/internal/ctype.h
+psych_parser.o: $(hdrdir)/ruby/internal/dllexport.h
+psych_parser.o: $(hdrdir)/ruby/internal/dosish.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/re.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/string.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+psych_parser.o: $(hdrdir)/ruby/internal/error.h
+psych_parser.o: $(hdrdir)/ruby/internal/eval.h
+psych_parser.o: $(hdrdir)/ruby/internal/event.h
+psych_parser.o: $(hdrdir)/ruby/internal/fl_type.h
+psych_parser.o: $(hdrdir)/ruby/internal/gc.h
+psych_parser.o: $(hdrdir)/ruby/internal/glob.h
+psych_parser.o: $(hdrdir)/ruby/internal/globals.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/attribute.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/builtin.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/extension.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/feature.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/warning.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/array.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/bignum.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/class.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/compar.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/complex.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/cont.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/dir.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/enum.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/error.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/eval.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/file.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/hash.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/io.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/load.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/marshal.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/numeric.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/object.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/parse.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/proc.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/process.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/random.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/range.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/rational.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/re.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/ruby.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/select.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/set.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/signal.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/string.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/struct.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/thread.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/time.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/variable.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/vm.h
+psych_parser.o: $(hdrdir)/ruby/internal/interpreter.h
+psych_parser.o: $(hdrdir)/ruby/internal/iterator.h
+psych_parser.o: $(hdrdir)/ruby/internal/memory.h
+psych_parser.o: $(hdrdir)/ruby/internal/method.h
+psych_parser.o: $(hdrdir)/ruby/internal/module.h
+psych_parser.o: $(hdrdir)/ruby/internal/newobj.h
+psych_parser.o: $(hdrdir)/ruby/internal/scan_args.h
+psych_parser.o: $(hdrdir)/ruby/internal/special_consts.h
+psych_parser.o: $(hdrdir)/ruby/internal/static_assert.h
+psych_parser.o: $(hdrdir)/ruby/internal/stdalign.h
+psych_parser.o: $(hdrdir)/ruby/internal/stdbool.h
+psych_parser.o: $(hdrdir)/ruby/internal/stdckdint.h
+psych_parser.o: $(hdrdir)/ruby/internal/symbol.h
+psych_parser.o: $(hdrdir)/ruby/internal/value.h
+psych_parser.o: $(hdrdir)/ruby/internal/value_type.h
+psych_parser.o: $(hdrdir)/ruby/internal/variable.h
+psych_parser.o: $(hdrdir)/ruby/internal/warning_push.h
+psych_parser.o: $(hdrdir)/ruby/internal/xmalloc.h
+psych_parser.o: $(hdrdir)/ruby/missing.h
+psych_parser.o: $(hdrdir)/ruby/onigmo.h
+psych_parser.o: $(hdrdir)/ruby/oniguruma.h
+psych_parser.o: $(hdrdir)/ruby/ruby.h
+psych_parser.o: $(hdrdir)/ruby/st.h
+psych_parser.o: $(hdrdir)/ruby/subst.h
+psych_parser.o: psych.h
+psych_parser.o: psych_emitter.h
+psych_parser.o: psych_parser.c
+psych_parser.o: psych_parser.h
+psych_parser.o: psych_to_ruby.h
+psych_parser.o: psych_yaml_tree.h
+psych_to_ruby.o: $(RUBY_EXTCONF_H)
+psych_to_ruby.o: $(arch_hdrdir)/ruby/config.h
+psych_to_ruby.o: $(hdrdir)/ruby.h
+psych_to_ruby.o: $(hdrdir)/ruby/assert.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/assume.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/attributes.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/bool.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/inttypes.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/limits.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/long_long.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/stdalign.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/stdarg.h
+psych_to_ruby.o: $(hdrdir)/ruby/defines.h
+psych_to_ruby.o: $(hdrdir)/ruby/encoding.h
+psych_to_ruby.o: $(hdrdir)/ruby/intern.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/abi.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/anyargs.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/assume.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/artificial.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/cold.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/const.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/error.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/format.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noalias.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noinline.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/pure.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/restrict.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/warning.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/weakref.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/cast.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_since.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/config.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/constant_p.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rarray.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rbasic.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rbignum.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rclass.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rdata.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rfile.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rhash.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/robject.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rregexp.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rstring.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rstruct.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/ctype.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/dllexport.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/dosish.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/re.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/string.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/error.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/eval.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/event.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/fl_type.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/gc.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/glob.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/globals.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/attribute.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/builtin.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/extension.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/feature.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/warning.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/array.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/bignum.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/class.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/compar.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/complex.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/cont.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/dir.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/enum.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/error.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/eval.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/file.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/hash.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/io.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/load.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/marshal.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/numeric.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/object.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/parse.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/proc.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/process.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/random.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/range.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/rational.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/re.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/ruby.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/select.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/set.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/signal.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/string.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/struct.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/thread.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/time.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/variable.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/vm.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/interpreter.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/iterator.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/memory.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/method.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/module.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/newobj.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/scan_args.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/special_consts.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/static_assert.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/stdalign.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/stdbool.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/stdckdint.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/symbol.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/value.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/value_type.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/variable.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/warning_push.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/xmalloc.h
+psych_to_ruby.o: $(hdrdir)/ruby/missing.h
+psych_to_ruby.o: $(hdrdir)/ruby/onigmo.h
+psych_to_ruby.o: $(hdrdir)/ruby/oniguruma.h
+psych_to_ruby.o: $(hdrdir)/ruby/ruby.h
+psych_to_ruby.o: $(hdrdir)/ruby/st.h
+psych_to_ruby.o: $(hdrdir)/ruby/subst.h
+psych_to_ruby.o: psych.h
+psych_to_ruby.o: psych_emitter.h
+psych_to_ruby.o: psych_parser.h
+psych_to_ruby.o: psych_to_ruby.c
+psych_to_ruby.o: psych_to_ruby.h
+psych_to_ruby.o: psych_yaml_tree.h
+psych_yaml_tree.o: $(RUBY_EXTCONF_H)
+psych_yaml_tree.o: $(arch_hdrdir)/ruby/config.h
+psych_yaml_tree.o: $(hdrdir)/ruby.h
+psych_yaml_tree.o: $(hdrdir)/ruby/assert.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/assume.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/attributes.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/bool.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/inttypes.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/limits.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/long_long.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/stdalign.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/stdarg.h
+psych_yaml_tree.o: $(hdrdir)/ruby/defines.h
+psych_yaml_tree.o: $(hdrdir)/ruby/encoding.h
+psych_yaml_tree.o: $(hdrdir)/ruby/intern.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/abi.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/anyargs.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/assume.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/artificial.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/cold.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/const.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/error.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/format.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noalias.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noinline.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/pure.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/restrict.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/warning.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/weakref.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/cast.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_since.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/config.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/constant_p.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rarray.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rbasic.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rbignum.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rclass.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rdata.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rfile.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rhash.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/robject.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rregexp.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rstring.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rstruct.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/ctype.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/dllexport.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/dosish.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/re.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/string.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/error.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/eval.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/event.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/fl_type.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/gc.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/glob.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/globals.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/attribute.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/builtin.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/extension.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/feature.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/warning.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/array.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/bignum.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/class.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/compar.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/complex.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/cont.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/dir.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/enum.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/error.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/eval.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/file.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/hash.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/io.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/load.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/marshal.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/numeric.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/object.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/parse.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/proc.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/process.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/random.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/range.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/rational.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/re.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/ruby.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/select.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/set.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/signal.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/string.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/struct.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/thread.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/time.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/variable.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/vm.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/interpreter.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/iterator.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/memory.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/method.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/module.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/newobj.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/scan_args.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/special_consts.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/static_assert.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdalign.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdbool.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdckdint.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/symbol.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/value.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/value_type.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/variable.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/warning_push.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/xmalloc.h
+psych_yaml_tree.o: $(hdrdir)/ruby/missing.h
+psych_yaml_tree.o: $(hdrdir)/ruby/onigmo.h
+psych_yaml_tree.o: $(hdrdir)/ruby/oniguruma.h
+psych_yaml_tree.o: $(hdrdir)/ruby/ruby.h
+psych_yaml_tree.o: $(hdrdir)/ruby/st.h
+psych_yaml_tree.o: $(hdrdir)/ruby/subst.h
+psych_yaml_tree.o: psych.h
+psych_yaml_tree.o: psych_emitter.h
+psych_yaml_tree.o: psych_parser.h
+psych_yaml_tree.o: psych_to_ruby.h
+psych_yaml_tree.o: psych_yaml_tree.c
+psych_yaml_tree.o: psych_yaml_tree.h
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/psych/extconf.rb b/ext/psych/extconf.rb
new file mode 100644
index 0000000000..589e201c1c
--- /dev/null
+++ b/ext/psych/extconf.rb
@@ -0,0 +1,56 @@
+# -*- coding: us-ascii -*-
+# frozen_string_literal: true
+require 'mkmf'
+
+if $mswin or $mingw or $cygwin
+ $CPPFLAGS << " -DYAML_DECLARE_STATIC"
+end
+
+yaml_source = with_config("libyaml-source-dir")
+if yaml_source
+ yaml_source = yaml_source.gsub(/\$\((\w+)\)|\$\{(\w+)\}/) {ENV[$1||$2]}
+ yaml_source = yaml_source.chomp("/")
+ yaml_configure = "#{File.expand_path(yaml_source)}/configure"
+ unless File.exist?(yaml_configure)
+ raise "Configure script not found in #{yaml_source.quote}"
+ end
+
+ puts("Configuring libyaml source in #{yaml_source.quote}")
+ yaml = "libyaml"
+ Dir.mkdir(yaml) unless File.directory?(yaml)
+ shared = $enable_shared || !$static
+ args = [
+ yaml_configure,
+ "--enable-#{shared ? 'shared' : 'static'}",
+ "--host=#{RbConfig::CONFIG['host'].sub(/-unknown-/, '-').sub(/arm64/, 'arm')}",
+ "CC=#{RbConfig::CONFIG['CC']}",
+ *(["CFLAGS=-w"] if RbConfig::CONFIG["GCC"] == "yes"),
+ ]
+ puts(args.quote.join(' '))
+ unless system(*args, chdir: yaml)
+ raise "failed to configure libyaml"
+ end
+ inc = yaml_source.start_with?("#$srcdir/") ? "$(srcdir)#{yaml_source[$srcdir.size..-1]}" : yaml_source
+ $INCFLAGS << " -I#{yaml}/include -I#{inc}/include"
+ puts("INCFLAGS=#$INCFLAGS")
+ libyaml = "libyaml.#$LIBEXT"
+ $cleanfiles << libyaml
+ $LOCAL_LIBS.prepend("$(LIBYAML) ")
+
+ # default to pre-installed libyaml
+elsif pkg_config('yaml-0.1')
+ # found with pkg-config
+else
+ dir_config('libyaml')
+ find_header('yaml.h') or abort "yaml.h not found"
+ find_library('yaml', 'yaml_get_version') or abort "libyaml not found"
+end
+
+create_makefile 'psych' do |mk|
+ mk << "LIBYAML = #{libyaml}".strip << "\n"
+ mk << "LIBYAML_OBJDIR = libyaml/src#{shared ? '/.libs' : ''}\n"
+ mk << "OBJEXT = #$OBJEXT"
+ mk << "RANLIB = #{config_string('RANLIB') || config_string('NULLCMD')}\n"
+end
+
+# :startdoc:
diff --git a/ext/psych/lib/psych.rb b/ext/psych/lib/psych.rb
new file mode 100644
index 0000000000..850a6d1937
--- /dev/null
+++ b/ext/psych/lib/psych.rb
@@ -0,0 +1,794 @@
+# frozen_string_literal: true
+require 'date'
+
+require_relative 'psych/versions'
+case RUBY_ENGINE
+when 'jruby'
+ require_relative 'psych_jars'
+ if JRuby::Util.respond_to?(:load_ext)
+ JRuby::Util.load_ext('org.jruby.ext.psych.PsychLibrary')
+ else
+ require 'java'; require 'jruby'
+ org.jruby.ext.psych.PsychLibrary.new.load(JRuby.runtime, false)
+ end
+else
+ require 'psych.so'
+end
+require_relative 'psych/nodes'
+require_relative 'psych/streaming'
+require_relative 'psych/visitors'
+require_relative 'psych/handler'
+require_relative 'psych/tree_builder'
+require_relative 'psych/parser'
+require_relative 'psych/omap'
+require_relative 'psych/set'
+require_relative 'psych/coder'
+require_relative 'psych/stream'
+require_relative 'psych/json/tree_builder'
+require_relative 'psych/json/stream'
+require_relative 'psych/handlers/document_stream'
+require_relative 'psych/class_loader'
+
+###
+# = Overview
+#
+# Psych is a YAML parser and emitter.
+# Psych leverages libyaml [Home page: https://pyyaml.org/wiki/LibYAML]
+# or [git repo: https://github.com/yaml/libyaml] for its YAML parsing
+# and emitting capabilities. In addition to wrapping libyaml, Psych also
+# knows how to serialize and de-serialize most Ruby objects to and from
+# the YAML format.
+#
+# = I NEED TO PARSE OR EMIT YAML RIGHT NOW!
+#
+# # Parse some YAML
+# Psych.load("--- foo") # => "foo"
+#
+# # Emit some YAML
+# Psych.dump("foo") # => "--- foo\n...\n"
+# { :a => 'b'}.to_yaml # => "---\n:a: b\n"
+#
+# Got more time on your hands? Keep on reading!
+#
+# == YAML Parsing
+#
+# Psych provides a range of interfaces for parsing a YAML document ranging from
+# low level to high level, depending on your parsing needs. At the lowest
+# level, is an event based parser. Mid level is access to the raw YAML AST,
+# and at the highest level is the ability to unmarshal YAML to Ruby objects.
+#
+# == YAML Emitting
+#
+# Psych provides a range of interfaces ranging from low to high level for
+# producing YAML documents. Very similar to the YAML parsing interfaces, Psych
+# provides at the lowest level, an event based system, mid-level is building
+# a YAML AST, and the highest level is converting a Ruby object straight to
+# a YAML document.
+#
+# == High-level API
+#
+# === Parsing
+#
+# The high level YAML parser provided by Psych simply takes YAML as input and
+# returns a Ruby data structure. For information on using the high level parser
+# see Psych.load
+#
+# ==== Reading from a string
+#
+# Psych.safe_load("--- a") # => 'a'
+# Psych.safe_load("---\n - a\n - b") # => ['a', 'b']
+# # From a trusted string:
+# Psych.load("--- !ruby/range\nbegin: 0\nend: 42\nexcl: false\n") # => 0..42
+#
+# ==== Reading from a file
+#
+# Psych.safe_load_file("data.yml", permitted_classes: [Date])
+# Psych.load_file("trusted_database.yml")
+#
+# ==== \Exception handling
+#
+# begin
+# # The second argument changes only the exception contents
+# Psych.parse("--- `", "file.txt")
+# rescue Psych::SyntaxError => ex
+# ex.file # => 'file.txt'
+# ex.message # => "(file.txt): found character that cannot start any token"
+# end
+#
+# === Emitting
+#
+# The high level emitter has the easiest interface. Psych simply takes a Ruby
+# data structure and converts it to a YAML document. See Psych.dump for more
+# information on dumping a Ruby data structure.
+#
+# ==== Writing to a string
+#
+# # Dump an array, get back a YAML string
+# Psych.dump(['a', 'b']) # => "---\n- a\n- b\n"
+#
+# # Dump an array to an IO object
+# Psych.dump(['a', 'b'], StringIO.new) # => #<StringIO:0x000001009d0890>
+#
+# # Dump an array with indentation set
+# Psych.dump(['a', ['b']], :indentation => 3) # => "---\n- a\n- - b\n"
+#
+# # Dump an array to an IO with indentation set
+# Psych.dump(['a', ['b']], StringIO.new, :indentation => 3)
+#
+# ==== Writing to a file
+#
+# Currently there is no direct API for dumping Ruby structure to file:
+#
+# File.open('database.yml', 'w') do |file|
+# file.write(Psych.dump(['a', 'b']))
+# end
+#
+# == Mid-level API
+#
+# === Parsing
+#
+# Psych provides access to an AST produced from parsing a YAML document. This
+# tree is built using the Psych::Parser and Psych::TreeBuilder. The AST can
+# be examined and manipulated freely. Please see Psych::parse_stream,
+# Psych::Nodes, and Psych::Nodes::Node for more information on dealing with
+# YAML syntax trees.
+#
+# ==== Reading from a string
+#
+# # Returns Psych::Nodes::Stream
+# Psych.parse_stream("---\n - a\n - b")
+#
+# # Returns Psych::Nodes::Document
+# Psych.parse("---\n - a\n - b")
+#
+# ==== Reading from a file
+#
+# # Returns Psych::Nodes::Stream
+# Psych.parse_stream(File.read('database.yml'))
+#
+# # Returns Psych::Nodes::Document
+# Psych.parse_file('database.yml')
+#
+# ==== \Exception handling
+#
+# begin
+# # The second argument changes only the exception contents
+# Psych.parse("--- `", "file.txt")
+# rescue Psych::SyntaxError => ex
+# ex.file # => 'file.txt'
+# ex.message # => "(file.txt): found character that cannot start any token"
+# end
+#
+# === Emitting
+#
+# At the mid level is building an AST. This AST is exactly the same as the AST
+# used when parsing a YAML document. Users can build an AST by hand and the
+# AST knows how to emit itself as a YAML document. See Psych::Nodes,
+# Psych::Nodes::Node, and Psych::TreeBuilder for more information on building
+# a YAML AST.
+#
+# ==== Writing to a string
+#
+# # We need Psych::Nodes::Stream (not Psych::Nodes::Document)
+# stream = Psych.parse_stream("---\n - a\n - b")
+#
+# stream.to_yaml # => "---\n- a\n- b\n"
+#
+# ==== Writing to a file
+#
+# # We need Psych::Nodes::Stream (not Psych::Nodes::Document)
+# stream = Psych.parse_stream(File.read('database.yml'))
+#
+# File.open('database.yml', 'w') do |file|
+# file.write(stream.to_yaml)
+# end
+#
+# == Low-level API
+#
+# === Parsing
+#
+# The lowest level parser should be used when the YAML input is already known,
+# and the developer does not want to pay the price of building an AST or
+# automatic detection and conversion to Ruby objects. See Psych::Parser for
+# more information on using the event based parser.
+#
+# ==== Reading to Psych::Nodes::Stream structure
+#
+# parser = Psych::Parser.new(TreeBuilder.new) # => #<Psych::Parser>
+# parser = Psych.parser # it's an alias for the above
+#
+# parser.parse("---\n - a\n - b") # => #<Psych::Parser>
+# parser.handler # => #<Psych::TreeBuilder>
+# parser.handler.root # => #<Psych::Nodes::Stream>
+#
+# ==== Receiving an events stream
+#
+# recorder = Psych::Handlers::Recorder.new
+# parser = Psych::Parser.new(recorder)
+#
+# parser.parse("---\n - a\n - b")
+# recorder.events # => [list of [event, args] lists]
+# # event is one of: Psych::Handler::EVENTS
+# # args are the arguments passed to the event
+#
+# === Emitting
+#
+# The lowest level emitter is an event based system. Events are sent to a
+# Psych::Emitter object. That object knows how to convert the events to a YAML
+# document. This interface should be used when document format is known in
+# advance or speed is a concern. See Psych::Emitter for more information.
+#
+# ==== Writing to a Ruby structure
+#
+# Psych.parser.parse("--- a") # => #<Psych::Parser>
+#
+# parser.handler.first # => #<Psych::Nodes::Stream>
+# parser.handler.first.to_ruby # => ["a"]
+#
+# parser.handler.root.first # => #<Psych::Nodes::Document>
+# parser.handler.root.first.to_ruby # => "a"
+#
+# # You can instantiate an Emitter manually
+# Psych::Visitors::ToRuby.new.accept(parser.handler.root.first)
+# # => "a"
+
+module Psych
+ # The version of libyaml Psych is using
+ LIBYAML_VERSION = Psych.libyaml_version.join('.').freeze
+
+ ###
+ # Load +yaml+ in to a Ruby data structure. If multiple documents are
+ # provided, the object contained in the first document will be returned.
+ # +filename+ will be used in the exception message if any exception
+ # is raised while parsing. If +yaml+ is empty, it returns
+ # the specified +fallback+ return value, which defaults to +false+.
+ #
+ # Raises a Psych::SyntaxError when a YAML syntax error is detected.
+ #
+ # Example:
+ #
+ # Psych.unsafe_load("--- a") # => 'a'
+ # Psych.unsafe_load("---\n - a\n - b") # => ['a', 'b']
+ #
+ # begin
+ # Psych.unsafe_load("--- `", filename: "file.txt")
+ # rescue Psych::SyntaxError => ex
+ # ex.file # => 'file.txt'
+ # ex.message # => "(file.txt): found character that cannot start any token"
+ # end
+ #
+ # When the optional +symbolize_names+ keyword argument is set to a
+ # true value, returns symbols for keys in Hash objects (default: strings).
+ #
+ # Psych.unsafe_load("---\n foo: bar") # => {"foo"=>"bar"}
+ # Psych.unsafe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
+ #
+ # Raises a TypeError when `yaml` parameter is NilClass
+ #
+ # NOTE: This method *should not* be used to parse untrusted documents, such as
+ # YAML documents that are supplied via user input. Instead, please use the
+ # load method or the safe_load method.
+ #
+ def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true
+ result = parse(yaml, filename: filename)
+ return fallback unless result
+ result.to_ruby(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer, parse_symbols: parse_symbols)
+ end
+
+ ###
+ # Safely load the yaml string in +yaml+. By default, only the following
+ # classes are allowed to be deserialized:
+ #
+ # * TrueClass
+ # * FalseClass
+ # * NilClass
+ # * Integer
+ # * Float
+ # * String
+ # * Array
+ # * Hash
+ #
+ # Recursive data structures are not allowed by default. Arbitrary classes
+ # can be allowed by adding those classes to the +permitted_classes+ keyword argument. They are
+ # additive. For example, to allow Date deserialization:
+ #
+ # Psych.safe_load(yaml, permitted_classes: [Date])
+ #
+ # Now the Date class can be loaded in addition to the classes listed above.
+ #
+ # Aliases can be explicitly allowed by changing the +aliases+ keyword argument.
+ # For example:
+ #
+ # x = []
+ # x << x
+ # yaml = Psych.dump x
+ # Psych.safe_load yaml # => raises an exception
+ # Psych.safe_load yaml, aliases: true # => loads the aliases
+ #
+ # A Psych::DisallowedClass exception will be raised if the yaml contains a
+ # class that isn't in the +permitted_classes+ list.
+ #
+ # A Psych::AliasesNotEnabled exception will be raised if the yaml contains aliases
+ # but the +aliases+ keyword argument is set to false.
+ #
+ # +filename+ will be used in the exception message if any exception is raised
+ # while parsing.
+ #
+ # When the optional +symbolize_names+ keyword argument is set to a
+ # true value, returns symbols for keys in Hash objects (default: strings).
+ #
+ # Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"}
+ # Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
+ #
+ def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true
+ result = parse(yaml, filename: filename)
+ return fallback unless result
+
+ class_loader = ClassLoader::Restricted.new(permitted_classes.map(&:to_s),
+ permitted_symbols.map(&:to_s))
+ scanner = ScalarScanner.new class_loader, strict_integer: strict_integer, parse_symbols: parse_symbols
+ visitor = if aliases
+ Visitors::ToRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
+ else
+ Visitors::NoAliasRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
+ end
+ result = visitor.accept result
+ result
+ end
+
+ ###
+ # Load +yaml+ in to a Ruby data structure. If multiple documents are
+ # provided, the object contained in the first document will be returned.
+ # +filename+ will be used in the exception message if any exception
+ # is raised while parsing. If +yaml+ is empty, it returns
+ # the specified +fallback+ return value, which defaults to +nil+.
+ #
+ # Raises a Psych::SyntaxError when a YAML syntax error is detected.
+ #
+ # Example:
+ #
+ # Psych.load("--- a") # => 'a'
+ # Psych.load("---\n - a\n - b") # => ['a', 'b']
+ #
+ # begin
+ # Psych.load("--- `", filename: "file.txt")
+ # rescue Psych::SyntaxError => ex
+ # ex.file # => 'file.txt'
+ # ex.message # => "(file.txt): found character that cannot start any token"
+ # end
+ #
+ # When the optional +symbolize_names+ keyword argument is set to a
+ # true value, returns symbols for keys in Hash objects (default: strings).
+ #
+ # Psych.load("---\n foo: bar") # => {"foo"=>"bar"}
+ # Psych.load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
+ #
+ # Raises a TypeError when `yaml` parameter is NilClass. This method is
+ # similar to `safe_load` except that `Symbol` objects are allowed by default.
+ #
+ def self.load yaml, permitted_classes: [Symbol], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true
+ safe_load yaml, permitted_classes: permitted_classes,
+ permitted_symbols: permitted_symbols,
+ aliases: aliases,
+ filename: filename,
+ fallback: fallback,
+ symbolize_names: symbolize_names,
+ freeze: freeze,
+ strict_integer: strict_integer,
+ parse_symbols: parse_symbols
+ end
+
+ ###
+ # Parse a YAML string in +yaml+. Returns the Psych::Nodes::Document.
+ # +filename+ is used in the exception message if a Psych::SyntaxError is
+ # raised.
+ #
+ # Raises a Psych::SyntaxError when a YAML syntax error is detected.
+ #
+ # Example:
+ #
+ # Psych.parse("---\n - a\n - b") # => #<Psych::Nodes::Document:0x00>
+ #
+ # begin
+ # Psych.parse("--- `", filename: "file.txt")
+ # rescue Psych::SyntaxError => ex
+ # ex.file # => 'file.txt'
+ # ex.message # => "(file.txt): found character that cannot start any token"
+ # end
+ #
+ # See Psych::Nodes for more information about YAML AST.
+ def self.parse yaml, filename: nil
+ parse_stream(yaml, filename: filename) do |node|
+ return node
+ end
+
+ false
+ end
+
+ ###
+ # Parse a file at +filename+. Returns the Psych::Nodes::Document.
+ #
+ # Raises a Psych::SyntaxError when a YAML syntax error is detected.
+ def self.parse_file filename, fallback: false
+ result = File.open filename, 'r:bom|utf-8' do |f|
+ parse f, filename: filename
+ end
+ result || fallback
+ end
+
+ ###
+ # Returns a default parser
+ def self.parser
+ Psych::Parser.new(TreeBuilder.new)
+ end
+
+ ###
+ # Parse a YAML string in +yaml+. Returns the Psych::Nodes::Stream.
+ # This method can handle multiple YAML documents contained in +yaml+.
+ # +filename+ is used in the exception message if a Psych::SyntaxError is
+ # raised.
+ #
+ # If a block is given, a Psych::Nodes::Document node will be yielded to the
+ # block as it's being parsed.
+ #
+ # Raises a Psych::SyntaxError when a YAML syntax error is detected.
+ #
+ # Example:
+ #
+ # Psych.parse_stream("---\n - a\n - b") # => #<Psych::Nodes::Stream:0x00>
+ #
+ # Psych.parse_stream("--- a\n--- b") do |node|
+ # node # => #<Psych::Nodes::Document:0x00>
+ # end
+ #
+ # begin
+ # Psych.parse_stream("--- `", filename: "file.txt")
+ # rescue Psych::SyntaxError => ex
+ # ex.file # => 'file.txt'
+ # ex.message # => "(file.txt): found character that cannot start any token"
+ # end
+ #
+ # Raises a TypeError when NilClass is passed.
+ #
+ # See Psych::Nodes for more information about YAML AST.
+ def self.parse_stream yaml, filename: nil, &block
+ if block_given?
+ parser = Psych::Parser.new(Handlers::DocumentStream.new(&block))
+ parser.parse yaml, filename
+ else
+ parser = self.parser
+ parser.parse yaml, filename
+ parser.handler.root
+ end
+ end
+
+ ###
+ # call-seq:
+ # Psych.dump(o) -> string of yaml
+ # Psych.dump(o, options) -> string of yaml
+ # Psych.dump(o, io) -> io object passed in
+ # Psych.dump(o, io, options) -> io object passed in
+ #
+ # Dump Ruby object +o+ to a YAML string. Optional +options+ may be passed in
+ # to control the output format. If an IO object is passed in, the YAML will
+ # be dumped to that IO object.
+ #
+ # Currently supported options are:
+ #
+ # [<tt>:indentation</tt>] Number of space characters used to indent.
+ # Acceptable value should be in <tt>0..9</tt> range,
+ # otherwise option is ignored.
+ #
+ # Default: <tt>2</tt>.
+ # [<tt>:line_width</tt>] Max character to wrap line at.
+ # For unlimited line width use <tt>-1</tt>.
+ #
+ # Default: <tt>0</tt> (meaning "wrap at 81").
+ # [<tt>:canonical</tt>] Write "canonical" YAML form (very verbose, yet
+ # strictly formal).
+ #
+ # Default: <tt>false</tt>.
+ # [<tt>:header</tt>] Write <tt>%YAML [version]</tt> at the beginning of document.
+ #
+ # Default: <tt>false</tt>.
+ #
+ # [<tt>:stringify_names</tt>] Dump symbol keys in Hash objects as string.
+ #
+ # Default: <tt>false</tt>.
+ #
+ # Example:
+ #
+ # # Dump an array, get back a YAML string
+ # Psych.dump(['a', 'b']) # => "---\n- a\n- b\n"
+ #
+ # # Dump an array to an IO object
+ # Psych.dump(['a', 'b'], StringIO.new) # => #<StringIO:0x000001009d0890>
+ #
+ # # Dump an array with indentation set
+ # Psych.dump(['a', ['b']], indentation: 3) # => "---\n- a\n- - b\n"
+ #
+ # # Dump an array to an IO with indentation set
+ # Psych.dump(['a', ['b']], StringIO.new, indentation: 3)
+ #
+ # # Dump hash with symbol keys as string
+ # Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n"
+ def self.dump o, io = nil, options = {}
+ if Hash === io
+ options = io
+ io = nil
+ end
+
+ visitor = Psych::Visitors::YAMLTree.create options
+ visitor << o
+ visitor.tree.yaml io, options
+ end
+
+ ###
+ # call-seq:
+ # Psych.safe_dump(o) -> string of yaml
+ # Psych.safe_dump(o, options) -> string of yaml
+ # Psych.safe_dump(o, io) -> io object passed in
+ # Psych.safe_dump(o, io, options) -> io object passed in
+ #
+ # Safely dump Ruby object +o+ to a YAML string. Optional +options+ may be passed in
+ # to control the output format. If an IO object is passed in, the YAML will
+ # be dumped to that IO object. By default, only the following
+ # classes are allowed to be serialized:
+ #
+ # * TrueClass
+ # * FalseClass
+ # * NilClass
+ # * Integer
+ # * Float
+ # * String
+ # * Array
+ # * Hash
+ #
+ # Arbitrary classes can be allowed by adding those classes to the +permitted_classes+
+ # keyword argument. They are additive. For example, to allow Date serialization:
+ #
+ # Psych.safe_dump(yaml, permitted_classes: [Date])
+ #
+ # Now the Date class can be dumped in addition to the classes listed above.
+ #
+ # A Psych::DisallowedClass exception will be raised if the object contains a
+ # class that isn't in the +permitted_classes+ list.
+ #
+ # Currently supported options are:
+ #
+ # [<tt>:indentation</tt>] Number of space characters used to indent.
+ # Acceptable value should be in <tt>0..9</tt> range,
+ # otherwise option is ignored.
+ #
+ # Default: <tt>2</tt>.
+ # [<tt>:line_width</tt>] Max character to wrap line at.
+ # For unlimited line width use <tt>-1</tt>.
+ #
+ # Default: <tt>0</tt> (meaning "wrap at 81").
+ # [<tt>:canonical</tt>] Write "canonical" YAML form (very verbose, yet
+ # strictly formal).
+ #
+ # Default: <tt>false</tt>.
+ # [<tt>:header</tt>] Write <tt>%YAML [version]</tt> at the beginning of document.
+ #
+ # Default: <tt>false</tt>.
+ #
+ # [<tt>:stringify_names</tt>] Dump symbol keys in Hash objects as string.
+ #
+ # Default: <tt>false</tt>.
+ #
+ # Example:
+ #
+ # # Dump an array, get back a YAML string
+ # Psych.safe_dump(['a', 'b']) # => "---\n- a\n- b\n"
+ #
+ # # Dump an array to an IO object
+ # Psych.safe_dump(['a', 'b'], StringIO.new) # => #<StringIO:0x000001009d0890>
+ #
+ # # Dump an array with indentation set
+ # Psych.safe_dump(['a', ['b']], indentation: 3) # => "---\n- a\n- - b\n"
+ #
+ # # Dump an array to an IO with indentation set
+ # Psych.safe_dump(['a', ['b']], StringIO.new, indentation: 3)
+ #
+ # # Dump hash with symbol keys as string
+ # Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n"
+ def self.safe_dump o, io = nil, options = {}
+ if Hash === io
+ options = io
+ io = nil
+ end
+
+ visitor = Psych::Visitors::RestrictedYAMLTree.create options
+ visitor << o
+ visitor.tree.yaml io, options
+ end
+
+ ###
+ # Dump a list of objects as separate documents to a document stream.
+ #
+ # Example:
+ #
+ # Psych.dump_stream("foo\n ", {}) # => "--- ! \"foo\\n \"\n--- {}\n"
+ def self.dump_stream *objects
+ visitor = Psych::Visitors::YAMLTree.create({})
+ objects.each do |o|
+ visitor << o
+ end
+ visitor.tree.yaml
+ end
+
+ ###
+ # Dump Ruby +object+ to a JSON string.
+ def self.to_json object
+ visitor = Psych::Visitors::JSONTree.create
+ visitor << object
+ visitor.tree.yaml
+ end
+
+ ###
+ # Load multiple documents given in +yaml+. Returns the parsed documents
+ # as a list. If a block is given, each document will be converted to Ruby
+ # and passed to the block during parsing
+ #
+ # Example:
+ #
+ # Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
+ #
+ # list = []
+ # Psych.load_stream("--- foo\n...\n--- bar\n...") do |ruby|
+ # list << ruby
+ # end
+ # list # => ['foo', 'bar']
+ #
+ def self.load_stream yaml, filename: nil, fallback: [], **kwargs
+ result = if block_given?
+ parse_stream(yaml, filename: filename) do |node|
+ yield node.to_ruby(**kwargs)
+ end
+ else
+ parse_stream(yaml, filename: filename).children.map { |node| node.to_ruby(**kwargs) }
+ end
+
+ return fallback if result.is_a?(Array) && result.empty?
+ result
+ end
+
+ ###
+ # Load multiple documents given in +yaml+. Returns the parsed documents
+ # as a list.
+ #
+ # Example:
+ #
+ # Psych.safe_load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
+ #
+ # list = []
+ # Psych.safe_load_stream("--- foo\n...\n--- bar\n...") do |ruby|
+ # list << ruby
+ # end
+ # list # => ['foo', 'bar']
+ #
+ def self.safe_load_stream yaml, filename: nil, permitted_classes: [], aliases: false
+ documents = parse_stream(yaml, filename: filename).children.map do |child|
+ stream = Psych::Nodes::Stream.new
+ stream.children << child
+ safe_load(stream.to_yaml, permitted_classes: permitted_classes, aliases: aliases)
+ end
+
+ if block_given?
+ documents.each { |doc| yield doc }
+ nil
+ else
+ documents
+ end
+ end
+
+ ###
+ # Load the document contained in +filename+. Returns the yaml contained in
+ # +filename+ as a Ruby object, or if the file is empty, it returns
+ # the specified +fallback+ return value, which defaults to +false+.
+ #
+ # NOTE: This method *should not* be used to parse untrusted documents, such as
+ # YAML documents that are supplied via user input. Instead, please use the
+ # safe_load_file method.
+ def self.unsafe_load_file filename, **kwargs
+ File.open(filename, 'r:bom|utf-8') { |f|
+ self.unsafe_load f, filename: filename, **kwargs
+ }
+ end
+
+ ###
+ # Safely loads the document contained in +filename+. Returns the yaml contained in
+ # +filename+ as a Ruby object, or if the file is empty, it returns
+ # the specified +fallback+ return value, which defaults to +nil+.
+ # See safe_load for options.
+ def self.safe_load_file filename, **kwargs
+ File.open(filename, 'r:bom|utf-8') { |f|
+ self.safe_load f, filename: filename, **kwargs
+ }
+ end
+
+ ###
+ # Loads the document contained in +filename+. Returns the yaml contained in
+ # +filename+ as a Ruby object, or if the file is empty, it returns
+ # the specified +fallback+ return value, which defaults to +nil+.
+ # See load for options.
+ def self.load_file filename, **kwargs
+ File.open(filename, 'r:bom|utf-8') { |f|
+ self.load f, filename: filename, **kwargs
+ }
+ end
+
+ # :stopdoc:
+ def self.add_domain_type domain, type_tag, &block
+ key = ['tag', domain, type_tag].join ':'
+ domain_types[key] = [key, block]
+ domain_types["tag:#{type_tag}"] = [key, block]
+ end
+
+ def self.add_builtin_type type_tag, &block
+ domain = 'yaml.org,2002'
+ key = ['tag', domain, type_tag].join ':'
+ domain_types[key] = [key, block]
+ end
+
+ def self.remove_type type_tag
+ domain_types.delete type_tag
+ end
+
+ def self.add_tag tag, klass
+ load_tags[tag] = klass.name
+ dump_tags[klass] = tag
+ end
+
+ class << self
+ if defined?(Ractor)
+ class Config
+ attr_accessor :load_tags, :dump_tags, :domain_types
+ def initialize
+ @load_tags = {}
+ @dump_tags = {}
+ @domain_types = {}
+ end
+ end
+
+ def config
+ Ractor.current[:PsychConfig] ||= Config.new
+ end
+
+ def load_tags
+ config.load_tags
+ end
+
+ def dump_tags
+ config.dump_tags
+ end
+
+ def domain_types
+ config.domain_types
+ end
+
+ def load_tags=(value)
+ config.load_tags = value
+ end
+
+ def dump_tags=(value)
+ config.dump_tags = value
+ end
+
+ def domain_types=(value)
+ config.domain_types = value
+ end
+ else
+ attr_accessor :load_tags
+ attr_accessor :dump_tags
+ attr_accessor :domain_types
+ end
+ end
+ self.load_tags = {}
+ self.dump_tags = {}
+ self.domain_types = {}
+ # :startdoc:
+end
+
+require_relative 'psych/core_ext'
diff --git a/ext/psych/lib/psych/class_loader.rb b/ext/psych/lib/psych/class_loader.rb
new file mode 100644
index 0000000000..c8f509720a
--- /dev/null
+++ b/ext/psych/lib/psych/class_loader.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+require_relative 'omap'
+require_relative 'set'
+
+module Psych
+ class ClassLoader # :nodoc:
+ BIG_DECIMAL = 'BigDecimal'
+ COMPLEX = 'Complex'
+ DATA = 'Data' unless RUBY_VERSION < "3.2"
+ DATE = 'Date'
+ DATE_TIME = 'DateTime'
+ EXCEPTION = 'Exception'
+ OBJECT = 'Object'
+ PSYCH_OMAP = 'Psych::Omap'
+ PSYCH_SET = 'Psych::Set'
+ RANGE = 'Range'
+ RATIONAL = 'Rational'
+ REGEXP = 'Regexp'
+ STRUCT = 'Struct'
+ SYMBOL = 'Symbol'
+
+ def initialize
+ @cache = CACHE.dup
+ end
+
+ def load klassname
+ return nil if !klassname || klassname.empty?
+
+ find klassname
+ end
+
+ def symbolize sym
+ symbol
+ sym.to_sym
+ end
+
+ constants.each do |const|
+ konst = const_get const
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
+ def #{const.to_s.downcase}
+ load #{konst.inspect}
+ end
+ RUBY
+ end
+
+ private
+
+ def find klassname
+ @cache[klassname] ||= resolve(klassname)
+ end
+
+ def resolve klassname
+ name = klassname
+ retried = false
+
+ begin
+ path2class(name)
+ rescue ArgumentError, NameError => ex
+ unless retried
+ name = "Struct::#{name}"
+ retried = ex
+ retry
+ end
+ raise retried
+ end
+ end
+
+ CACHE = Hash[constants.map { |const|
+ val = const_get const
+ begin
+ [val, ::Object.const_get(val)]
+ rescue
+ nil
+ end
+ }.compact].freeze
+
+ class Restricted < ClassLoader
+ def initialize classes, symbols
+ @classes = classes
+ @symbols = symbols
+ super()
+ end
+
+ def symbolize sym
+ return super if @symbols.empty?
+
+ if @symbols.include? sym
+ super
+ else
+ raise DisallowedClass.new('load', 'Symbol')
+ end
+ end
+
+ private
+
+ def find klassname
+ if @classes.include? klassname
+ super
+ else
+ raise DisallowedClass.new('load', klassname)
+ end
+ end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/coder.rb b/ext/psych/lib/psych/coder.rb
new file mode 100644
index 0000000000..96a9c3fbad
--- /dev/null
+++ b/ext/psych/lib/psych/coder.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+module Psych
+ ###
+ # If an object defines +encode_with+, then an instance of Psych::Coder will
+ # be passed to the method when the object is being serialized. The Coder
+ # automatically assumes a Psych::Nodes::Mapping is being emitted. Other
+ # objects like Sequence and Scalar may be emitted if +seq=+ or +scalar=+ are
+ # called, respectively.
+ class Coder
+ attr_accessor :tag, :style, :implicit, :object
+ attr_reader :type, :seq
+
+ def initialize tag
+ @map = {}
+ @seq = []
+ @implicit = false
+ @type = :map
+ @tag = tag
+ @style = Psych::Nodes::Mapping::BLOCK
+ @scalar = nil
+ @object = nil
+ end
+
+ def scalar *args
+ if args.length > 0
+ warn "#{caller[0]}: Coder#scalar(a,b,c) is deprecated" if $VERBOSE
+ @tag, @scalar, _ = args
+ @type = :scalar
+ end
+ @scalar
+ end
+
+ # Emit a map. The coder will be yielded to the block.
+ def map tag = @tag, style = @style
+ @tag = tag
+ @style = style
+ yield self if block_given?
+ @map
+ end
+
+ # Emit a scalar with +value+ and +tag+
+ def represent_scalar tag, value
+ self.tag = tag
+ self.scalar = value
+ end
+
+ # Emit a sequence with +list+ and +tag+
+ def represent_seq tag, list
+ @tag = tag
+ self.seq = list
+ end
+
+ # Emit a sequence with +map+ and +tag+
+ def represent_map tag, map
+ @tag = tag
+ self.map = map
+ end
+
+ # Emit an arbitrary object +obj+ and +tag+
+ def represent_object tag, obj
+ @tag = tag
+ @type = :object
+ @object = obj
+ end
+
+ # Emit a scalar with +value+
+ def scalar= value
+ @type = :scalar
+ @scalar = value
+ end
+
+ # Emit a map with +value+
+ def map= map
+ @type = :map
+ @map = map
+ end
+
+ def []= k, v
+ @type = :map
+ @map[k] = v
+ end
+ alias :add :[]=
+
+ def [] k
+ @type = :map
+ @map[k]
+ end
+
+ # Emit a sequence of +list+
+ def seq= list
+ @type = :seq
+ @seq = list
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/core_ext.rb b/ext/psych/lib/psych/core_ext.rb
new file mode 100644
index 0000000000..6dfd0f1696
--- /dev/null
+++ b/ext/psych/lib/psych/core_ext.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+class Object
+ def self.yaml_tag url
+ Psych.add_tag(url, self)
+ end
+
+ ###
+ # call-seq: to_yaml(options = {})
+ #
+ # Convert an object to YAML. See Psych.dump for more information on the
+ # available +options+.
+ def to_yaml options = {}
+ Psych.dump self, options
+ end
+end
+
+# Up to Ruby 3.4, Set was a regular object and was dumped as such
+# by Pysch.
+# Starting from Ruby 4.0 it's a core class written in C, so we have to implement
+# #encode_with / #init_with to preserve backward compatibility.
+if defined?(::Set) && Set.new.instance_variables.empty?
+ class Set
+ def encode_with(coder)
+ hash = {}
+ each do |m|
+ hash[m] = true
+ end
+ coder["hash"] = hash
+ coder
+ end
+
+ def init_with(coder)
+ replace(coder["hash"].keys)
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/exception.rb b/ext/psych/lib/psych/exception.rb
new file mode 100644
index 0000000000..d7469a4b30
--- /dev/null
+++ b/ext/psych/lib/psych/exception.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+module Psych
+ class Exception < RuntimeError
+ end
+
+ class BadAlias < Exception
+ end
+
+ # Subclasses `BadAlias` for backwards compatibility
+ class AliasesNotEnabled < BadAlias
+ def initialize
+ super "Alias parsing was not enabled. To enable it, pass `aliases: true` to `Psych::load` or `Psych::safe_load`."
+ end
+ end
+
+ # Subclasses `BadAlias` for backwards compatibility
+ class AnchorNotDefined < BadAlias
+ def initialize anchor_name
+ super "An alias referenced an unknown anchor: #{anchor_name}"
+ end
+ end
+
+ class DisallowedClass < Exception
+ def initialize action, klass_name
+ super "Tried to #{action} unspecified class: #{klass_name}"
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/handler.rb b/ext/psych/lib/psych/handler.rb
new file mode 100644
index 0000000000..ad7249ff77
--- /dev/null
+++ b/ext/psych/lib/psych/handler.rb
@@ -0,0 +1,255 @@
+# frozen_string_literal: true
+module Psych
+ ###
+ # Psych::Handler is an abstract base class that defines the events used
+ # when dealing with Psych::Parser. Clients who want to use Psych::Parser
+ # should implement a class that inherits from Psych::Handler and define
+ # events that they can handle.
+ #
+ # Psych::Handler defines all events that Psych::Parser can possibly send to
+ # event handlers.
+ #
+ # See Psych::Parser for more details
+ class Handler
+ ###
+ # Configuration options for dumping YAML.
+ class DumperOptions
+ attr_accessor :line_width, :indentation, :canonical
+
+ def initialize
+ @line_width = 0
+ @indentation = 2
+ @canonical = false
+ end
+ end
+
+ # Default dumping options
+ OPTIONS = DumperOptions.new
+
+ # Events that a Handler should respond to.
+ EVENTS = [ :alias,
+ :empty,
+ :end_document,
+ :end_mapping,
+ :end_sequence,
+ :end_stream,
+ :scalar,
+ :start_document,
+ :start_mapping,
+ :start_sequence,
+ :start_stream ]
+
+ ###
+ # Called with +encoding+ when the YAML stream starts. This method is
+ # called once per stream. A stream may contain multiple documents.
+ #
+ # See the constants in Psych::Parser for the possible values of +encoding+.
+ def start_stream encoding
+ end
+
+ ###
+ # Called when the document starts with the declared +version+,
+ # +tag_directives+, if the document is +implicit+.
+ #
+ # +version+ will be an array of integers indicating the YAML version being
+ # dealt with, +tag_directives+ is a list of tuples indicating the prefix
+ # and suffix of each tag, and +implicit+ is a boolean indicating whether
+ # the document is started implicitly.
+ #
+ # === Example
+ #
+ # Given the following YAML:
+ #
+ # %YAML 1.1
+ # %TAG ! tag:tenderlovemaking.com,2009:
+ # --- !squee
+ #
+ # The parameters for start_document must be this:
+ #
+ # version # => [1, 1]
+ # tag_directives # => [["!", "tag:tenderlovemaking.com,2009:"]]
+ # implicit # => false
+ def start_document version, tag_directives, implicit
+ end
+
+ ###
+ # Called with the document ends. +implicit+ is a boolean value indicating
+ # whether or not the document has an implicit ending.
+ #
+ # === Example
+ #
+ # Given the following YAML:
+ #
+ # ---
+ # hello world
+ #
+ # +implicit+ will be true. Given this YAML:
+ #
+ # ---
+ # hello world
+ # ...
+ #
+ # +implicit+ will be false.
+ def end_document implicit
+ end
+
+ ###
+ # Called when an alias is found to +anchor+. +anchor+ will be the name
+ # of the anchor found.
+ #
+ # === Example
+ #
+ # Here we have an example of an array that references itself in YAML:
+ #
+ # --- &ponies
+ # - first element
+ # - *ponies
+ #
+ # &ponies is the anchor, *ponies is the alias. In this case, alias is
+ # called with "ponies".
+ def alias anchor
+ end
+
+ ###
+ # Called when a scalar +value+ is found. The scalar may have an
+ # +anchor+, a +tag+, be implicitly +plain+ or implicitly +quoted+
+ #
+ # +value+ is the string value of the scalar
+ # +anchor+ is an associated anchor or nil
+ # +tag+ is an associated tag or nil
+ # +plain+ is a boolean value
+ # +quoted+ is a boolean value
+ # +style+ is an integer indicating the string style
+ #
+ # See the constants in Psych::Nodes::Scalar for the possible values of
+ # +style+
+ #
+ # === Example
+ #
+ # Here is a YAML document that exercises most of the possible ways this
+ # method can be called:
+ #
+ # ---
+ # - !str "foo"
+ # - &anchor fun
+ # - many
+ # lines
+ # - |
+ # many
+ # newlines
+ #
+ # The above YAML document contains a list with four strings. Here are
+ # the parameters sent to this method in the same order:
+ #
+ # # value anchor tag plain quoted style
+ # ["foo", nil, "!str", false, false, 3 ]
+ # ["fun", "anchor", nil, true, false, 1 ]
+ # ["many lines", nil, nil, true, false, 1 ]
+ # ["many\nnewlines\n", nil, nil, false, true, 4 ]
+ #
+ def scalar value, anchor, tag, plain, quoted, style
+ end
+
+ ###
+ # Called when a sequence is started.
+ #
+ # +anchor+ is the anchor associated with the sequence or nil.
+ # +tag+ is the tag associated with the sequence or nil.
+ # +implicit+ a boolean indicating whether or not the sequence was implicitly
+ # started.
+ # +style+ is an integer indicating the list style.
+ #
+ # See the constants in Psych::Nodes::Sequence for the possible values of
+ # +style+.
+ #
+ # === Example
+ #
+ # Here is a YAML document that exercises most of the possible ways this
+ # method can be called:
+ #
+ # ---
+ # - !!seq [
+ # a
+ # ]
+ # - &pewpew
+ # - b
+ #
+ # The above YAML document consists of three lists, an outer list that
+ # contains two inner lists. Here is a matrix of the parameters sent
+ # to represent these lists:
+ #
+ # # anchor tag implicit style
+ # [nil, nil, true, 1 ]
+ # [nil, "tag:yaml.org,2002:seq", false, 2 ]
+ # ["pewpew", nil, true, 1 ]
+
+ def start_sequence anchor, tag, implicit, style
+ end
+
+ ###
+ # Called when a sequence ends.
+ def end_sequence
+ end
+
+ ###
+ # Called when a map starts.
+ #
+ # +anchor+ is the anchor associated with the map or +nil+.
+ # +tag+ is the tag associated with the map or +nil+.
+ # +implicit+ is a boolean indicating whether or not the map was implicitly
+ # started.
+ # +style+ is an integer indicating the mapping style.
+ #
+ # See the constants in Psych::Nodes::Mapping for the possible values of
+ # +style+.
+ #
+ # === Example
+ #
+ # Here is a YAML document that exercises most of the possible ways this
+ # method can be called:
+ #
+ # ---
+ # k: !!map { hello: world }
+ # v: &pewpew
+ # hello: world
+ #
+ # The above YAML document consists of three maps, an outer map that contains
+ # two inner maps. Below is a matrix of the parameters sent in order to
+ # represent these three maps:
+ #
+ # # anchor tag implicit style
+ # [nil, nil, true, 1 ]
+ # [nil, "tag:yaml.org,2002:map", false, 2 ]
+ # ["pewpew", nil, true, 1 ]
+
+ def start_mapping anchor, tag, implicit, style
+ end
+
+ ###
+ # Called when a map ends
+ def end_mapping
+ end
+
+ ###
+ # Called when an empty event happens. (Which, as far as I can tell, is
+ # never).
+ def empty
+ end
+
+ ###
+ # Called when the YAML stream ends
+ def end_stream
+ end
+
+ ###
+ # Called before each event with line/column information.
+ def event_location(start_line, start_column, end_line, end_column)
+ end
+
+ ###
+ # Is this handler a streaming handler?
+ def streaming?
+ false
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/handlers/document_stream.rb b/ext/psych/lib/psych/handlers/document_stream.rb
new file mode 100644
index 0000000000..b77115d074
--- /dev/null
+++ b/ext/psych/lib/psych/handlers/document_stream.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+require_relative '../tree_builder'
+
+module Psych
+ module Handlers
+ class DocumentStream < Psych::TreeBuilder # :nodoc:
+ def initialize &block
+ super
+ @block = block
+ end
+
+ def start_document version, tag_directives, implicit
+ n = Nodes::Document.new version, tag_directives, implicit
+ push n
+ end
+
+ def end_document implicit_end = !streaming?
+ @last.implicit_end = implicit_end
+ @block.call pop
+ end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/handlers/recorder.rb b/ext/psych/lib/psych/handlers/recorder.rb
new file mode 100644
index 0000000000..c98724cb76
--- /dev/null
+++ b/ext/psych/lib/psych/handlers/recorder.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+require_relative '../handler'
+
+module Psych
+ module Handlers
+ ###
+ # This handler will capture an event and record the event. Recorder events
+ # are available vial Psych::Handlers::Recorder#events.
+ #
+ # For example:
+ #
+ # recorder = Psych::Handlers::Recorder.new
+ # parser = Psych::Parser.new recorder
+ # parser.parse '--- foo'
+ #
+ # recorder.events # => [list of events]
+ #
+ # # Replay the events
+ #
+ # emitter = Psych::Emitter.new $stdout
+ # recorder.events.each do |m, args|
+ # emitter.send m, *args
+ # end
+
+ class Recorder < Psych::Handler
+ attr_reader :events
+
+ def initialize
+ @events = []
+ super
+ end
+
+ EVENTS.each do |event|
+ define_method event do |*args|
+ @events << [event, args]
+ end
+ end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/json/ruby_events.rb b/ext/psych/lib/psych/json/ruby_events.rb
new file mode 100644
index 0000000000..17b7ddc386
--- /dev/null
+++ b/ext/psych/lib/psych/json/ruby_events.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+module Psych
+ module JSON
+ module RubyEvents # :nodoc:
+ def visit_Time o
+ formatted = format_time o
+ @emitter.scalar formatted, nil, nil, false, true, Nodes::Scalar::DOUBLE_QUOTED
+ end
+
+ def visit_DateTime o
+ visit_Time o.to_time
+ end
+
+ def visit_String o
+ @emitter.scalar o.to_s, nil, nil, false, true, Nodes::Scalar::DOUBLE_QUOTED
+ end
+ alias :visit_Symbol :visit_String
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/json/stream.rb b/ext/psych/lib/psych/json/stream.rb
new file mode 100644
index 0000000000..24dd4b9baf
--- /dev/null
+++ b/ext/psych/lib/psych/json/stream.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+require_relative 'ruby_events'
+require_relative 'yaml_events'
+
+module Psych
+ module JSON
+ class Stream < Psych::Visitors::JSONTree
+ include Psych::JSON::RubyEvents
+ include Psych::Streaming
+ extend Psych::Streaming::ClassMethods
+
+ class Emitter < Psych::Stream::Emitter # :nodoc:
+ include Psych::JSON::YAMLEvents
+ end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/json/tree_builder.rb b/ext/psych/lib/psych/json/tree_builder.rb
new file mode 100644
index 0000000000..9a45f6b94c
--- /dev/null
+++ b/ext/psych/lib/psych/json/tree_builder.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+require_relative 'yaml_events'
+
+module Psych
+ module JSON
+ ###
+ # Psych::JSON::TreeBuilder is an event based AST builder. Events are sent
+ # to an instance of Psych::JSON::TreeBuilder and a JSON AST is constructed.
+ class TreeBuilder < Psych::TreeBuilder
+ include Psych::JSON::YAMLEvents
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/json/yaml_events.rb b/ext/psych/lib/psych/json/yaml_events.rb
new file mode 100644
index 0000000000..eb973f5361
--- /dev/null
+++ b/ext/psych/lib/psych/json/yaml_events.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+module Psych
+ module JSON
+ module YAMLEvents # :nodoc:
+ def start_document version, tag_directives, implicit
+ super(version, tag_directives, !streaming?)
+ end
+
+ def end_document implicit_end = !streaming?
+ super(implicit_end)
+ end
+
+ def start_mapping anchor, tag, implicit, style
+ super(anchor, nil, true, Nodes::Mapping::FLOW)
+ end
+
+ def start_sequence anchor, tag, implicit, style
+ super(anchor, nil, true, Nodes::Sequence::FLOW)
+ end
+
+ def scalar value, anchor, tag, plain, quoted, style
+ if "tag:yaml.org,2002:null" == tag
+ super('null', nil, nil, true, false, Nodes::Scalar::PLAIN)
+ else
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/nodes.rb b/ext/psych/lib/psych/nodes.rb
new file mode 100644
index 0000000000..2fa52e0055
--- /dev/null
+++ b/ext/psych/lib/psych/nodes.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+require_relative 'nodes/node'
+require_relative 'nodes/stream'
+require_relative 'nodes/document'
+require_relative 'nodes/sequence'
+require_relative 'nodes/scalar'
+require_relative 'nodes/mapping'
+require_relative 'nodes/alias'
+
+module Psych
+ ###
+ # = Overview
+ #
+ # When using Psych.load to deserialize a YAML document, the document is
+ # translated to an intermediary AST. That intermediary AST is then
+ # translated in to a Ruby object graph.
+ #
+ # In the opposite direction, when using Psych.dump, the Ruby object graph is
+ # translated to an intermediary AST which is then converted to a YAML
+ # document.
+ #
+ # Psych::Nodes contains all of the classes that make up the nodes of a YAML
+ # AST. You can manually build an AST and use one of the visitors (see
+ # Psych::Visitors) to convert that AST to either a YAML document or to a
+ # Ruby object graph.
+ #
+ # Here is an example of building an AST that represents a list with one
+ # scalar:
+ #
+ # # Create our nodes
+ # stream = Psych::Nodes::Stream.new
+ # doc = Psych::Nodes::Document.new
+ # seq = Psych::Nodes::Sequence.new
+ # scalar = Psych::Nodes::Scalar.new('foo')
+ #
+ # # Build up our tree
+ # stream.children << doc
+ # doc.children << seq
+ # seq.children << scalar
+ #
+ # The stream is the root of the tree. We can then convert the tree to YAML:
+ #
+ # stream.to_yaml => "---\n- foo\n"
+ #
+ # Or convert it to Ruby:
+ #
+ # stream.to_ruby => [["foo"]]
+ #
+ # == YAML AST Requirements
+ #
+ # A valid YAML AST *must* have one Psych::Nodes::Stream at the root. A
+ # Psych::Nodes::Stream node must have 1 or more Psych::Nodes::Document nodes
+ # as children.
+ #
+ # Psych::Nodes::Document nodes must have one and *only* one child. That child
+ # may be one of:
+ #
+ # * Psych::Nodes::Sequence
+ # * Psych::Nodes::Mapping
+ # * Psych::Nodes::Scalar
+ #
+ # Psych::Nodes::Sequence and Psych::Nodes::Mapping nodes may have many
+ # children, but Psych::Nodes::Mapping nodes should have an even number of
+ # children.
+ #
+ # All of these are valid children for Psych::Nodes::Sequence and
+ # Psych::Nodes::Mapping nodes:
+ #
+ # * Psych::Nodes::Sequence
+ # * Psych::Nodes::Mapping
+ # * Psych::Nodes::Scalar
+ # * Psych::Nodes::Alias
+ #
+ # Psych::Nodes::Scalar and Psych::Nodes::Alias are both terminal nodes and
+ # should not have any children.
+ module Nodes
+ end
+end
diff --git a/ext/psych/lib/psych/nodes/alias.rb b/ext/psych/lib/psych/nodes/alias.rb
new file mode 100644
index 0000000000..6da655f0fd
--- /dev/null
+++ b/ext/psych/lib/psych/nodes/alias.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+module Psych
+ module Nodes
+ ###
+ # This class represents a {YAML Alias}[http://yaml.org/spec/1.1/#alias].
+ # It points to an +anchor+.
+ #
+ # A Psych::Nodes::Alias is a terminal node and may have no children.
+ class Alias < Psych::Nodes::Node
+ # The anchor this alias links to
+ attr_accessor :anchor
+
+ # Create a new Alias that points to an +anchor+
+ def initialize anchor
+ @anchor = anchor
+ end
+
+ def alias?; true; end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/nodes/document.rb b/ext/psych/lib/psych/nodes/document.rb
new file mode 100644
index 0000000000..f57410d636
--- /dev/null
+++ b/ext/psych/lib/psych/nodes/document.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+module Psych
+ module Nodes
+ ###
+ # This represents a YAML Document. This node must be a child of
+ # Psych::Nodes::Stream. A Psych::Nodes::Document must have one child,
+ # and that child may be one of the following:
+ #
+ # * Psych::Nodes::Sequence
+ # * Psych::Nodes::Mapping
+ # * Psych::Nodes::Scalar
+ class Document < Psych::Nodes::Node
+ # The version of the YAML document
+ attr_accessor :version
+
+ # A list of tag directives for this document
+ attr_accessor :tag_directives
+
+ # Was this document implicitly created?
+ attr_accessor :implicit
+
+ # Is the end of the document implicit?
+ attr_accessor :implicit_end
+
+ ###
+ # Create a new Psych::Nodes::Document object.
+ #
+ # +version+ is a list indicating the YAML version.
+ # +tags_directives+ is a list of tag directive declarations
+ # +implicit+ is a flag indicating whether the document will be implicitly
+ # started.
+ #
+ # == Example:
+ # This creates a YAML document object that represents a YAML 1.1 document
+ # with one tag directive, and has an implicit start:
+ #
+ # Psych::Nodes::Document.new(
+ # [1,1],
+ # [["!", "tag:tenderlovemaking.com,2009:"]],
+ # true
+ # )
+ #
+ # == See Also
+ # See also Psych::Handler#start_document
+ def initialize version = [], tag_directives = [], implicit = false
+ super()
+ @version = version
+ @tag_directives = tag_directives
+ @implicit = implicit
+ @implicit_end = true
+ end
+
+ ###
+ # Returns the root node. A Document may only have one root node:
+ # http://yaml.org/spec/1.1/#id898031
+ def root
+ children.first
+ end
+
+ def document?; true; end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/nodes/mapping.rb b/ext/psych/lib/psych/nodes/mapping.rb
new file mode 100644
index 0000000000..d49678cb0e
--- /dev/null
+++ b/ext/psych/lib/psych/nodes/mapping.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+module Psych
+ module Nodes
+ ###
+ # This class represents a {YAML Mapping}[http://yaml.org/spec/1.1/#mapping].
+ #
+ # A Psych::Nodes::Mapping node may have 0 or more children, but must have
+ # an even number of children. Here are the valid children a
+ # Psych::Nodes::Mapping node may have:
+ #
+ # * Psych::Nodes::Sequence
+ # * Psych::Nodes::Mapping
+ # * Psych::Nodes::Scalar
+ # * Psych::Nodes::Alias
+ class Mapping < Psych::Nodes::Node
+ # Any Map Style
+ ANY = 0
+
+ # Block Map Style
+ BLOCK = 1
+
+ # Flow Map Style
+ FLOW = 2
+
+ # The optional anchor for this mapping
+ attr_accessor :anchor
+
+ # The optional tag for this mapping
+ attr_accessor :tag
+
+ # Is this an implicit mapping?
+ attr_accessor :implicit
+
+ # The style of this mapping
+ attr_accessor :style
+
+ ###
+ # Create a new Psych::Nodes::Mapping object.
+ #
+ # +anchor+ is the anchor associated with the map or +nil+.
+ # +tag+ is the tag associated with the map or +nil+.
+ # +implicit+ is a boolean indicating whether or not the map was implicitly
+ # started.
+ # +style+ is an integer indicating the mapping style.
+ #
+ # == See Also
+ # See also Psych::Handler#start_mapping
+ def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK
+ super()
+ @anchor = anchor
+ @tag = tag
+ @implicit = implicit
+ @style = style
+ end
+
+ def mapping?; true; end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/nodes/node.rb b/ext/psych/lib/psych/nodes/node.rb
new file mode 100644
index 0000000000..fc27448f2e
--- /dev/null
+++ b/ext/psych/lib/psych/nodes/node.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+require_relative '../class_loader'
+require_relative '../scalar_scanner'
+
+module Psych
+ module Nodes
+ ###
+ # The base class for any Node in a YAML parse tree. This class should
+ # never be instantiated.
+ class Node
+ include Enumerable
+
+ # The children of this node
+ attr_reader :children
+
+ # An associated tag
+ attr_reader :tag
+
+ # The line number where this node start
+ attr_accessor :start_line
+
+ # The column number where this node start
+ attr_accessor :start_column
+
+ # The line number where this node ends
+ attr_accessor :end_line
+
+ # The column number where this node ends
+ attr_accessor :end_column
+
+ # Create a new Psych::Nodes::Node
+ def initialize
+ @children = []
+ end
+
+ ###
+ # Iterate over each node in the tree. Yields each node to +block+ depth
+ # first.
+ def each &block
+ return enum_for :each unless block_given?
+ Visitors::DepthFirst.new(block).accept self
+ end
+
+ ###
+ # Convert this node to Ruby.
+ #
+ # See also Psych::Visitors::ToRuby
+ def to_ruby(symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true)
+ Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer, parse_symbols: parse_symbols).accept(self)
+ end
+ alias :transform :to_ruby
+
+ ###
+ # Convert this node to YAML.
+ #
+ # See also Psych::Visitors::Emitter
+ def yaml io = nil, options = {}
+ require "stringio" unless defined?(StringIO)
+
+ real_io = io || StringIO.new(''.encode('utf-8'))
+
+ Visitors::Emitter.new(real_io, options).accept self
+ return real_io.string unless io
+ io
+ end
+ alias :to_yaml :yaml
+
+ def alias?; false; end
+ def document?; false; end
+ def mapping?; false; end
+ def scalar?; false; end
+ def sequence?; false; end
+ def stream?; false; end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/nodes/scalar.rb b/ext/psych/lib/psych/nodes/scalar.rb
new file mode 100644
index 0000000000..5550b616a3
--- /dev/null
+++ b/ext/psych/lib/psych/nodes/scalar.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+module Psych
+ module Nodes
+ ###
+ # This class represents a {YAML Scalar}[http://yaml.org/spec/1.1/#id858081].
+ #
+ # This node type is a terminal node and should not have any children.
+ class Scalar < Psych::Nodes::Node
+ # Any style scalar, the emitter chooses
+ ANY = 0
+
+ # Plain scalar style
+ PLAIN = 1
+
+ # Single quoted style
+ SINGLE_QUOTED = 2
+
+ # Double quoted style
+ DOUBLE_QUOTED = 3
+
+ # Literal style
+ LITERAL = 4
+
+ # Folded style
+ FOLDED = 5
+
+ # The scalar value
+ attr_accessor :value
+
+ # The anchor value (if there is one)
+ attr_accessor :anchor
+
+ # The tag value (if there is one)
+ attr_accessor :tag
+
+ # Is this a plain scalar?
+ attr_accessor :plain
+
+ # Is this scalar quoted?
+ attr_accessor :quoted
+
+ # The style of this scalar
+ attr_accessor :style
+
+ ###
+ # Create a new Psych::Nodes::Scalar object.
+ #
+ # +value+ is the string value of the scalar
+ # +anchor+ is an associated anchor or nil
+ # +tag+ is an associated tag or nil
+ # +plain+ is a boolean value
+ # +quoted+ is a boolean value
+ # +style+ is an integer indicating the string style
+ #
+ # == See Also
+ #
+ # See also Psych::Handler#scalar
+ def initialize value, anchor = nil, tag = nil, plain = true, quoted = false, style = ANY
+ @value = value
+ @anchor = anchor
+ @tag = tag
+ @plain = plain
+ @quoted = quoted
+ @style = style
+ end
+
+ def scalar?; true; end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/nodes/sequence.rb b/ext/psych/lib/psych/nodes/sequence.rb
new file mode 100644
index 0000000000..740f1938a4
--- /dev/null
+++ b/ext/psych/lib/psych/nodes/sequence.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+module Psych
+ module Nodes
+ ###
+ # This class represents a
+ # {YAML sequence}[http://yaml.org/spec/1.1/#sequence/syntax].
+ #
+ # A YAML sequence is basically a list, and looks like this:
+ #
+ # %YAML 1.1
+ # ---
+ # - I am
+ # - a Sequence
+ #
+ # A YAML sequence may have an anchor like this:
+ #
+ # %YAML 1.1
+ # ---
+ # &A [
+ # "This sequence",
+ # "has an anchor"
+ # ]
+ #
+ # A YAML sequence may also have a tag like this:
+ #
+ # %YAML 1.1
+ # ---
+ # !!seq [
+ # "This sequence",
+ # "has a tag"
+ # ]
+ #
+ # This class represents a sequence in a YAML document. A
+ # Psych::Nodes::Sequence node may have 0 or more children. Valid children
+ # for this node are:
+ #
+ # * Psych::Nodes::Sequence
+ # * Psych::Nodes::Mapping
+ # * Psych::Nodes::Scalar
+ # * Psych::Nodes::Alias
+ class Sequence < Psych::Nodes::Node
+ # Any Styles, emitter chooses
+ ANY = 0
+
+ # Block style sequence
+ BLOCK = 1
+
+ # Flow style sequence
+ FLOW = 2
+
+ # The anchor for this sequence (if any)
+ attr_accessor :anchor
+
+ # The tag name for this sequence (if any)
+ attr_accessor :tag
+
+ # Is this sequence started implicitly?
+ attr_accessor :implicit
+
+ # The sequence style used
+ attr_accessor :style
+
+ ###
+ # Create a new object representing a YAML sequence.
+ #
+ # +anchor+ is the anchor associated with the sequence or nil.
+ # +tag+ is the tag associated with the sequence or nil.
+ # +implicit+ a boolean indicating whether or not the sequence was
+ # implicitly started.
+ # +style+ is an integer indicating the list style.
+ #
+ # See Psych::Handler#start_sequence
+ def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK
+ super()
+ @anchor = anchor
+ @tag = tag
+ @implicit = implicit
+ @style = style
+ end
+
+ def sequence?; true; end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/nodes/stream.rb b/ext/psych/lib/psych/nodes/stream.rb
new file mode 100644
index 0000000000..b525217821
--- /dev/null
+++ b/ext/psych/lib/psych/nodes/stream.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+module Psych
+ module Nodes
+ ###
+ # Represents a YAML stream. This is the root node for any YAML parse
+ # tree. This node must have one or more child nodes. The only valid
+ # child node for a Psych::Nodes::Stream node is Psych::Nodes::Document.
+ class Stream < Psych::Nodes::Node
+
+ # Encodings supported by Psych (and libyaml)
+
+ # Any encoding
+ ANY = Psych::Parser::ANY
+
+ # UTF-8 encoding
+ UTF8 = Psych::Parser::UTF8
+
+ # UTF-16LE encoding
+ UTF16LE = Psych::Parser::UTF16LE
+
+ # UTF-16BE encoding
+ UTF16BE = Psych::Parser::UTF16BE
+
+ # The encoding used for this stream
+ attr_accessor :encoding
+
+ ###
+ # Create a new Psych::Nodes::Stream node with an +encoding+ that
+ # defaults to Psych::Nodes::Stream::UTF8.
+ #
+ # See also Psych::Handler#start_stream
+ def initialize encoding = UTF8
+ super()
+ @encoding = encoding
+ end
+
+ def stream?; true; end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/omap.rb b/ext/psych/lib/psych/omap.rb
new file mode 100644
index 0000000000..29cde0be50
--- /dev/null
+++ b/ext/psych/lib/psych/omap.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+module Psych
+ class Omap < ::Hash
+ end
+end
diff --git a/ext/psych/lib/psych/parser.rb b/ext/psych/lib/psych/parser.rb
new file mode 100644
index 0000000000..2181c730e5
--- /dev/null
+++ b/ext/psych/lib/psych/parser.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+module Psych
+ ###
+ # YAML event parser class. This class parses a YAML document and calls
+ # events on the handler that is passed to the constructor. The events can
+ # be used for things such as constructing a YAML AST or deserializing YAML
+ # documents. It can even be fed back to Psych::Emitter to emit the same
+ # document that was parsed.
+ #
+ # See Psych::Handler for documentation on the events that Psych::Parser emits.
+ #
+ # Here is an example that prints out ever scalar found in a YAML document:
+ #
+ # # Handler for detecting scalar values
+ # class ScalarHandler < Psych::Handler
+ # def scalar value, anchor, tag, plain, quoted, style
+ # puts value
+ # end
+ # end
+ #
+ # parser = Psych::Parser.new(ScalarHandler.new)
+ # parser.parse(yaml_document)
+ #
+ # Here is an example that feeds the parser back in to Psych::Emitter. The
+ # YAML document is read from STDIN and written back out to STDERR:
+ #
+ # parser = Psych::Parser.new(Psych::Emitter.new($stderr))
+ # parser.parse($stdin)
+ #
+ # Psych uses Psych::Parser in combination with Psych::TreeBuilder to
+ # construct an AST of the parsed YAML document.
+
+ class Parser
+ class Mark < Struct.new(:index, :line, :column)
+ end
+
+ # The handler on which events will be called
+ attr_accessor :handler
+
+ # Set the encoding for this parser to +encoding+
+ attr_writer :external_encoding
+
+ ###
+ # Creates a new Psych::Parser instance with +handler+. YAML events will
+ # be called on +handler+. See Psych::Parser for more details.
+
+ def initialize handler = Handler.new
+ @handler = handler
+ @external_encoding = ANY
+ end
+
+ ###
+ # call-seq:
+ # parser.parse(yaml)
+ #
+ # Parse the YAML document contained in +yaml+. Events will be called on
+ # the handler set on the parser instance.
+ #
+ # See Psych::Parser and Psych::Parser#handler
+
+ def parse yaml, path = yaml.respond_to?(:path) ? yaml.path : "<unknown>"
+ _native_parse @handler, yaml, path
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/scalar_scanner.rb b/ext/psych/lib/psych/scalar_scanner.rb
new file mode 100644
index 0000000000..6a556fb3b8
--- /dev/null
+++ b/ext/psych/lib/psych/scalar_scanner.rb
@@ -0,0 +1,142 @@
+# frozen_string_literal: true
+
+module Psych
+ ###
+ # Scan scalars for built in types
+ class ScalarScanner
+ # Taken from http://yaml.org/type/timestamp.html
+ TIME = /^-?\d{4}-\d{1,2}-\d{1,2}(?:[Tt]|\s+)\d{1,2}:\d\d:\d\d(?:\.\d*)?(?:\s*(?:Z|[-+]\d{1,2}:?(?:\d\d)?))?$/
+
+ # Taken from http://yaml.org/type/float.html
+ # Base 60, [-+]inf and NaN are handled separately
+ FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10))$/x
+
+ # Taken from http://yaml.org/type/int.html and modified to ensure at least one numerical symbol exists
+ INTEGER_STRICT = /^(?:[-+]?0b[_]*[0-1][0-1_]* (?# base 2)
+ |[-+]?0[_]*[0-7][0-7_]* (?# base 8)
+ |[-+]?(0|[1-9][0-9_]*) (?# base 10)
+ |[-+]?0x[_]*[0-9a-fA-F][0-9a-fA-F_]* (?# base 16))$/x
+
+ # Same as above, but allows commas.
+ # Not to YML spec, but kept for backwards compatibility
+ INTEGER_LEGACY = /^(?:[-+]?0b[_,]*[0-1][0-1_,]* (?# base 2)
+ |[-+]?0[_,]*[0-7][0-7_,]* (?# base 8)
+ |[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10)
+ |[-+]?0x[_,]*[0-9a-fA-F][0-9a-fA-F_,]* (?# base 16))$/x
+
+ attr_reader :class_loader
+
+ # Create a new scanner
+ def initialize class_loader, strict_integer: false, parse_symbols: true
+ @symbol_cache = {}
+ @class_loader = class_loader
+ @strict_integer = strict_integer
+ @parse_symbols = parse_symbols
+ end
+
+ # Tokenize +string+ returning the Ruby object
+ def tokenize string
+ return nil if string.empty?
+ return @symbol_cache[string] if @symbol_cache.key?(string)
+ integer_regex = @strict_integer ? INTEGER_STRICT : INTEGER_LEGACY
+ # Check for a String type, being careful not to get caught by hash keys, hex values, and
+ # special floats (e.g., -.inf).
+ if string.match?(%r{^[^\d.:-]?[[:alpha:]_\s!@#$%\^&*(){}<>|/\\~;=]+}) || string.match?(/\n/)
+ return string if string.length > 5
+
+ if string.match?(/^[^ytonf~]/i)
+ string
+ elsif string == '~' || string.match?(/^null$/i)
+ nil
+ elsif string.match?(/^(yes|true|on)$/i)
+ true
+ elsif string.match?(/^(no|false|off)$/i)
+ false
+ else
+ string
+ end
+ elsif string.match?(TIME)
+ begin
+ parse_time string
+ rescue ArgumentError
+ string
+ end
+ elsif string.match?(/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/)
+ begin
+ class_loader.date.strptime(string, '%F', Date::GREGORIAN)
+ rescue ArgumentError
+ string
+ end
+ elsif string.match?(/^\+?\.inf$/i)
+ Float::INFINITY
+ elsif string.match?(/^-\.inf$/i)
+ -Float::INFINITY
+ elsif string.match?(/^\.nan$/i)
+ Float::NAN
+ elsif @parse_symbols && string.match?(/^:./)
+ if string =~ /^:(["'])(.*)\1/
+ @symbol_cache[string] = class_loader.symbolize($2.sub(/^:/, ''))
+ else
+ @symbol_cache[string] = class_loader.symbolize(string.sub(/^:/, ''))
+ end
+ elsif string.match?(/^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}$/)
+ i = 0
+ string.split(':').each_with_index do |n,e|
+ i += (n.to_i * 60 ** (e - 2).abs)
+ end
+ i
+ elsif string.match?(/^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}\.[0-9_]*$/)
+ i = 0
+ string.split(':').each_with_index do |n,e|
+ i += (n.to_f * 60 ** (e - 2).abs)
+ end
+ i
+ elsif string.match?(FLOAT)
+ if string.match?(/\A[-+]?\.\Z/)
+ string
+ else
+ Float(string.delete(',_').gsub(/\.([Ee]|$)/, '\1'))
+ end
+ elsif string.match?(integer_regex)
+ parse_int string
+ else
+ string
+ end
+ end
+
+ ###
+ # Parse and return an int from +string+
+ def parse_int string
+ Integer(string.delete(',_'))
+ end
+
+ ###
+ # Parse and return a Time from +string+
+ def parse_time string
+ klass = class_loader.load 'Time'
+
+ date, time = *(string.split(/[ tT]/, 2))
+ (yy, m, dd) = date.match(/^(-?\d{4})-(\d{1,2})-(\d{1,2})/).captures.map { |x| x.to_i }
+ md = time.match(/(\d+:\d+:\d+)(?:\.(\d*))?\s*(Z|[-+]\d+(:\d\d)?)?/)
+
+ (hh, mm, ss) = md[1].split(':').map { |x| x.to_i }
+ us = (md[2] ? Rational("0.#{md[2]}") : 0) * 1000000
+
+ time = klass.utc(yy, m, dd, hh, mm, ss, us)
+
+ return time if 'Z' == md[3]
+ return klass.at(time.to_i, us) unless md[3]
+
+ tz = md[3].match(/^([+\-]?\d{1,2})\:?(\d{1,2})?$/)[1..-1].compact.map { |digit| Integer(digit, 10) }
+ offset = tz.first * 3600
+
+ if offset < 0
+ offset -= ((tz[1] || 0) * 60)
+ else
+ offset += ((tz[1] || 0) * 60)
+ end
+
+ klass.new(yy, m, dd, hh, mm, ss+us/(1_000_000r), offset)
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/set.rb b/ext/psych/lib/psych/set.rb
new file mode 100644
index 0000000000..760d217098
--- /dev/null
+++ b/ext/psych/lib/psych/set.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+module Psych
+ class Set < ::Hash
+ end
+end
diff --git a/ext/psych/lib/psych/stream.rb b/ext/psych/lib/psych/stream.rb
new file mode 100644
index 0000000000..24e45afc3b
--- /dev/null
+++ b/ext/psych/lib/psych/stream.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+module Psych
+ ###
+ # Psych::Stream is a streaming YAML emitter. It will not buffer your YAML,
+ # but send it straight to an IO.
+ #
+ # Here is an example use:
+ #
+ # stream = Psych::Stream.new($stdout)
+ # stream.start
+ # stream.push({:foo => 'bar'})
+ # stream.finish
+ #
+ # YAML will be immediately emitted to $stdout with no buffering.
+ #
+ # Psych::Stream#start will take a block and ensure that Psych::Stream#finish
+ # is called, so you can do this form:
+ #
+ # stream = Psych::Stream.new($stdout)
+ # stream.start do |em|
+ # em.push(:foo => 'bar')
+ # end
+ #
+ class Stream < Psych::Visitors::YAMLTree
+ class Emitter < Psych::Emitter # :nodoc:
+ def end_document implicit_end = !streaming?
+ super
+ end
+
+ def streaming?
+ true
+ end
+ end
+
+ include Psych::Streaming
+ extend Psych::Streaming::ClassMethods
+ end
+end
diff --git a/ext/psych/lib/psych/streaming.rb b/ext/psych/lib/psych/streaming.rb
new file mode 100644
index 0000000000..eb19792ad0
--- /dev/null
+++ b/ext/psych/lib/psych/streaming.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+module Psych
+ module Streaming
+ module ClassMethods
+ ###
+ # Create a new streaming emitter. Emitter will print to +io+. See
+ # Psych::Stream for an example.
+ def new io
+ emitter = const_get(:Emitter).new(io)
+ class_loader = ClassLoader.new
+ ss = ScalarScanner.new class_loader
+ super(emitter, ss, {})
+ end
+ end
+
+ ###
+ # Start streaming using +encoding+
+ def start encoding = Nodes::Stream::UTF8
+ super.tap { yield self if block_given? }
+ ensure
+ finish if block_given?
+ end
+
+ private
+ def register target, obj
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/syntax_error.rb b/ext/psych/lib/psych/syntax_error.rb
new file mode 100644
index 0000000000..a4c9c4a376
--- /dev/null
+++ b/ext/psych/lib/psych/syntax_error.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+require_relative 'exception'
+
+module Psych
+ class SyntaxError < Psych::Exception
+ attr_reader :file, :line, :column, :offset, :problem, :context
+
+ def initialize file, line, col, offset, problem, context
+ err = [problem, context].compact.join ' '
+ filename = file || '<unknown>'
+ message = "(%s): %s at line %d column %d" % [filename, err, line, col]
+
+ @file = file
+ @line = line
+ @column = col
+ @offset = offset
+ @problem = problem
+ @context = context
+ super(message)
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/tree_builder.rb b/ext/psych/lib/psych/tree_builder.rb
new file mode 100644
index 0000000000..83115bd721
--- /dev/null
+++ b/ext/psych/lib/psych/tree_builder.rb
@@ -0,0 +1,137 @@
+# frozen_string_literal: true
+require_relative 'handler'
+
+module Psych
+ ###
+ # This class works in conjunction with Psych::Parser to build an in-memory
+ # parse tree that represents a YAML document.
+ #
+ # == Example
+ #
+ # parser = Psych::Parser.new Psych::TreeBuilder.new
+ # parser.parse('--- foo')
+ # tree = parser.handler.root
+ #
+ # See Psych::Handler for documentation on the event methods used in this
+ # class.
+ class TreeBuilder < Psych::Handler
+ # Returns the root node for the built tree
+ attr_reader :root
+
+ # Create a new TreeBuilder instance
+ def initialize
+ @stack = []
+ @last = nil
+ @root = nil
+
+ @start_line = nil
+ @start_column = nil
+ @end_line = nil
+ @end_column = nil
+ end
+
+ def event_location(start_line, start_column, end_line, end_column)
+ @start_line = start_line
+ @start_column = start_column
+ @end_line = end_line
+ @end_column = end_column
+ end
+
+ %w{
+ Sequence
+ Mapping
+ }.each do |node|
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
+ def start_#{node.downcase}(anchor, tag, implicit, style)
+ n = Nodes::#{node}.new(anchor, tag, implicit, style)
+ set_start_location(n)
+ @last.children << n
+ push n
+ end
+
+ def end_#{node.downcase}
+ n = pop
+ set_end_location(n)
+ n
+ end
+ RUBY
+ end
+
+ ###
+ # Handles start_document events with +version+, +tag_directives+,
+ # and +implicit+ styling.
+ #
+ # See Psych::Handler#start_document
+ def start_document version, tag_directives, implicit
+ n = Nodes::Document.new version, tag_directives, implicit
+ set_start_location(n)
+ @last.children << n
+ push n
+ end
+
+ ###
+ # Handles end_document events with +version+, +tag_directives+,
+ # and +implicit+ styling.
+ #
+ # See Psych::Handler#start_document
+ def end_document implicit_end = !streaming?
+ @last.implicit_end = implicit_end
+ n = pop
+ set_end_location(n)
+ n
+ end
+
+ def start_stream encoding
+ @root = Nodes::Stream.new(encoding)
+ set_start_location(@root)
+ push @root
+ end
+
+ def end_stream
+ n = pop
+ set_end_location(n)
+ n
+ end
+
+ def scalar value, anchor, tag, plain, quoted, style
+ s = Nodes::Scalar.new(value,anchor,tag,plain,quoted,style)
+ set_location(s)
+ @last.children << s
+ s
+ end
+
+ def alias anchor
+ a = Nodes::Alias.new(anchor)
+ set_location(a)
+ @last.children << a
+ a
+ end
+
+ private
+ def push value
+ @stack.push value
+ @last = value
+ end
+
+ def pop
+ x = @stack.pop
+ @last = @stack.last
+ x
+ end
+
+ def set_location(node)
+ set_start_location(node)
+ set_end_location(node)
+ end
+
+ def set_start_location(node)
+ node.start_line = @start_line
+ node.start_column = @start_column
+ end
+
+ def set_end_location(node)
+ node.end_line = @end_line
+ node.end_column = @end_column
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/versions.rb b/ext/psych/lib/psych/versions.rb
new file mode 100644
index 0000000000..6c1679bf65
--- /dev/null
+++ b/ext/psych/lib/psych/versions.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Psych
+ # The version of Psych you are using
+ VERSION = '5.4.0'
+
+ if RUBY_ENGINE == 'jruby'
+ DEFAULT_SNAKEYAML_VERSION = '2.10'.freeze
+ end
+end
diff --git a/ext/psych/lib/psych/visitors.rb b/ext/psych/lib/psych/visitors.rb
new file mode 100644
index 0000000000..508290d862
--- /dev/null
+++ b/ext/psych/lib/psych/visitors.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+require_relative 'visitors/visitor'
+require_relative 'visitors/to_ruby'
+require_relative 'visitors/emitter'
+require_relative 'visitors/yaml_tree'
+require_relative 'visitors/json_tree'
+require_relative 'visitors/depth_first'
diff --git a/ext/psych/lib/psych/visitors/depth_first.rb b/ext/psych/lib/psych/visitors/depth_first.rb
new file mode 100644
index 0000000000..b4ff9e40e7
--- /dev/null
+++ b/ext/psych/lib/psych/visitors/depth_first.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+module Psych
+ module Visitors
+ class DepthFirst < Psych::Visitors::Visitor
+ def initialize block
+ @block = block
+ end
+
+ private
+
+ def nary o
+ o.children.each { |x| visit x }
+ @block.call o
+ end
+ alias :visit_Psych_Nodes_Stream :nary
+ alias :visit_Psych_Nodes_Document :nary
+ alias :visit_Psych_Nodes_Sequence :nary
+ alias :visit_Psych_Nodes_Mapping :nary
+
+ def terminal o
+ @block.call o
+ end
+ alias :visit_Psych_Nodes_Scalar :terminal
+ alias :visit_Psych_Nodes_Alias :terminal
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/visitors/emitter.rb b/ext/psych/lib/psych/visitors/emitter.rb
new file mode 100644
index 0000000000..e3b92b7d03
--- /dev/null
+++ b/ext/psych/lib/psych/visitors/emitter.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+module Psych
+ module Visitors
+ class Emitter < Psych::Visitors::Visitor
+ def initialize io, options = {}
+ opts = [:indentation, :canonical, :line_width].find_all { |opt|
+ options.key?(opt)
+ }
+
+ if opts.empty?
+ @handler = Psych::Emitter.new io
+ else
+ du = Handler::DumperOptions.new
+ opts.each { |option| du.send :"#{option}=", options[option] }
+ @handler = Psych::Emitter.new io, du
+ end
+ end
+
+ def visit_Psych_Nodes_Stream o
+ @handler.start_stream o.encoding
+ o.children.each { |c| accept c }
+ @handler.end_stream
+ end
+
+ def visit_Psych_Nodes_Document o
+ @handler.start_document o.version, o.tag_directives, o.implicit
+ o.children.each { |c| accept c }
+ @handler.end_document o.implicit_end
+ end
+
+ def visit_Psych_Nodes_Scalar o
+ @handler.scalar o.value, o.anchor, o.tag, o.plain, o.quoted, o.style
+ end
+
+ def visit_Psych_Nodes_Sequence o
+ @handler.start_sequence o.anchor, o.tag, o.implicit, o.style
+ o.children.each { |c| accept c }
+ @handler.end_sequence
+ end
+
+ def visit_Psych_Nodes_Mapping o
+ @handler.start_mapping o.anchor, o.tag, o.implicit, o.style
+ o.children.each { |c| accept c }
+ @handler.end_mapping
+ end
+
+ def visit_Psych_Nodes_Alias o
+ @handler.alias o.anchor
+ end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/visitors/json_tree.rb b/ext/psych/lib/psych/visitors/json_tree.rb
new file mode 100644
index 0000000000..979fc100bd
--- /dev/null
+++ b/ext/psych/lib/psych/visitors/json_tree.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+require_relative '../json/ruby_events'
+
+module Psych
+ module Visitors
+ class JSONTree < YAMLTree
+ include Psych::JSON::RubyEvents
+
+ def self.create options = {}
+ emitter = Psych::JSON::TreeBuilder.new
+ class_loader = ClassLoader.new
+ ss = ScalarScanner.new class_loader
+ new(emitter, ss, options)
+ end
+
+ def accept target
+ if target.respond_to?(:encode_with)
+ dump_coder target
+ else
+ send(@dispatch_cache[target.class], target)
+ end
+ end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb
new file mode 100644
index 0000000000..475444e589
--- /dev/null
+++ b/ext/psych/lib/psych/visitors/to_ruby.rb
@@ -0,0 +1,479 @@
+# frozen_string_literal: true
+require_relative '../scalar_scanner'
+require_relative '../class_loader'
+require_relative '../exception'
+
+unless defined?(Regexp::NOENCODING)
+ Regexp::NOENCODING = 32
+end
+
+module Psych
+ module Visitors
+ ###
+ # This class walks a YAML AST, converting each node to Ruby
+ class ToRuby < Psych::Visitors::Visitor
+ unless RUBY_VERSION < "3.2"
+ DATA_INITIALIZE = Data.instance_method(:initialize)
+ end
+
+ def self.create(symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true)
+ class_loader = ClassLoader.new
+ scanner = ScalarScanner.new class_loader, strict_integer: strict_integer, parse_symbols: parse_symbols
+ new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze)
+ end
+
+ attr_reader :class_loader
+
+ def initialize ss, class_loader, symbolize_names: false, freeze: false
+ super()
+ @st = {}
+ @ss = ss
+ @load_tags = Psych.load_tags
+ @domain_types = Psych.domain_types
+ @class_loader = class_loader
+ @symbolize_names = symbolize_names
+ @freeze = freeze
+ end
+
+ def accept target
+ result = super
+
+ unless @domain_types.empty? || !target.tag
+ key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
+ key = "tag:#{key}" unless key.match?(/^(?:tag:|x-private)/)
+
+ if @domain_types.key? key
+ value, block = @domain_types[key]
+ result = block.call value, result
+ end
+ end
+
+ result = deduplicate(result).freeze if @freeze
+ result
+ end
+
+ def deserialize o
+ if klass = resolve_class(@load_tags[o.tag])
+ instance = klass.allocate
+
+ if instance.respond_to?(:init_with)
+ coder = Psych::Coder.new(o.tag)
+ coder.scalar = o.value
+ instance.init_with coder
+ end
+
+ return instance
+ end
+
+ return o.value if o.quoted
+ return @ss.tokenize(o.value) unless o.tag
+
+ case o.tag
+ when '!binary', 'tag:yaml.org,2002:binary'
+ o.value.unpack('m').first
+ when /^!(?:str|ruby\/string)(?::(.*))?$/, 'tag:yaml.org,2002:str'
+ klass = resolve_class($1)
+ if klass
+ klass.allocate.replace o.value
+ else
+ o.value
+ end
+ when '!ruby/object:BigDecimal'
+ require 'bigdecimal' unless defined? BigDecimal
+ class_loader.big_decimal._load o.value
+ when "!ruby/object:DateTime"
+ class_loader.date_time
+ t = @ss.parse_time(o.value)
+ DateTime.civil(*t.to_a[0, 6].reverse, Rational(t.utc_offset, 86400)) +
+ (t.subsec/86400)
+ when '!ruby/encoding'
+ ::Encoding.find o.value
+ when "!ruby/object:Complex"
+ class_loader.complex
+ Complex(o.value)
+ when "!ruby/object:Rational"
+ class_loader.rational
+ Rational(o.value)
+ when "!ruby/class", "!ruby/module"
+ resolve_class o.value
+ when "tag:yaml.org,2002:float", "!float"
+ Float(@ss.tokenize(o.value))
+ when "!ruby/regexp"
+ klass = class_loader.regexp
+ matches = /^\/(?<string>.*)\/(?<options>[mixn]*)$/m.match(o.value)
+ source = matches[:string].gsub('\/', '/')
+ options = 0
+ lang = nil
+ matches[:options].each_char do |option|
+ case option
+ when 'x' then options |= Regexp::EXTENDED
+ when 'i' then options |= Regexp::IGNORECASE
+ when 'm' then options |= Regexp::MULTILINE
+ when 'n' then options |= Regexp::NOENCODING
+ else lang = option
+ end
+ end
+ klass.new(*[source, options, lang].compact)
+ when "!ruby/range"
+ klass = class_loader.range
+ args = o.value.split(/([.]{2,3})/, 2).map { |s|
+ accept Nodes::Scalar.new(s)
+ }
+ args.push(args.delete_at(1) == '...')
+ klass.new(*args)
+ when /^!ruby\/sym(bol)?:?(.*)?$/
+ class_loader.symbolize o.value
+ else
+ @ss.tokenize o.value
+ end
+ end
+ private :deserialize
+
+ def visit_Psych_Nodes_Scalar o
+ register o, deserialize(o)
+ end
+
+ def visit_Psych_Nodes_Sequence o
+ if klass = resolve_class(@load_tags[o.tag])
+ instance = klass.allocate
+
+ if instance.respond_to?(:init_with)
+ coder = Psych::Coder.new(o.tag)
+ coder.seq = o.children.map { |c| accept c }
+ instance.init_with coder
+ end
+
+ return instance
+ end
+
+ case o.tag
+ when nil
+ register_empty(o)
+ when '!omap', 'tag:yaml.org,2002:omap'
+ map = register(o, Psych::Omap.new)
+ o.children.each { |a|
+ map[accept(a.children.first)] = accept a.children.last
+ }
+ map
+ when /^!(?:seq|ruby\/array):(.*)$/
+ klass = resolve_class($1)
+ list = register(o, klass.allocate)
+ o.children.each { |c| list.push accept c }
+ list
+ else
+ register_empty(o)
+ end
+ end
+
+ def visit_Psych_Nodes_Mapping o
+ if @load_tags[o.tag]
+ return revive(resolve_class(@load_tags[o.tag]), o)
+ end
+ return revive_hash(register(o, {}), o) unless o.tag
+
+ case o.tag
+ when /^!ruby\/struct:?(.*)?$/
+ klass = resolve_class($1) if $1
+
+ if klass
+ s = register(o, klass.allocate)
+
+ members = {}
+ struct_members = s.members.map { |x| class_loader.symbolize x }
+ o.children.each_slice(2) do |k,v|
+ member = accept(k)
+ value = accept(v)
+ if struct_members.include?(class_loader.symbolize(member))
+ s.send("#{member}=", value)
+ else
+ members[member.to_s.sub(/^@/, '')] = value
+ end
+ end
+ init_with(s, members, o)
+ else
+ klass = class_loader.struct
+ members = o.children.map { |c| accept c }
+ h = Hash[*members]
+ s = klass.new(*h.map { |k,v|
+ class_loader.symbolize k
+ }).new(*h.map { |k,v| v })
+ register(o, s)
+ s
+ end
+
+ when /^!ruby\/data(-with-ivars)?(?::(.*))?$/
+ data = register(o, resolve_class($2).allocate) if $2
+ members = {}
+
+ if $1 # data-with-ivars
+ ivars = {}
+ o.children.each_slice(2) do |type, vars|
+ case accept(type)
+ when 'members'
+ revive_data_members(members, vars)
+ data ||= allocate_anon_data(o, members)
+ when 'ivars'
+ revive_hash(ivars, vars)
+ end
+ end
+ ivars.each do |ivar, v|
+ data.instance_variable_set ivar, v
+ end
+ else
+ revive_data_members(members, o)
+ end
+ data ||= allocate_anon_data(o, members)
+ DATA_INITIALIZE.bind_call(data, **members)
+ data.freeze
+ data
+
+ when /^!ruby\/object:?(.*)?$/
+ name = $1 || 'Object'
+
+ if name == 'Complex'
+ class_loader.complex
+ h = Hash[*o.children.map { |c| accept c }]
+ register o, Complex(h['real'], h['image'])
+ elsif name == 'Rational'
+ class_loader.rational
+ h = Hash[*o.children.map { |c| accept c }]
+ register o, Rational(h['numerator'], h['denominator'])
+ elsif name == 'Hash'
+ revive_hash(register(o, {}), o)
+ else
+ obj = revive((resolve_class(name) || class_loader.object), o)
+ obj
+ end
+
+ when /^!(?:str|ruby\/string)(?::(.*))?$/, 'tag:yaml.org,2002:str'
+ klass = resolve_class($1)
+ members = {}
+ string = nil
+
+ o.children.each_slice(2) do |k,v|
+ key = accept k
+ value = accept v
+
+ if key == 'str'
+ if klass
+ string = klass.allocate.replace value
+ else
+ string = value
+ end
+ register(o, string)
+ else
+ members[key] = value
+ end
+ end
+ init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }, o)
+ when /^!ruby\/array:(.*)$/
+ klass = resolve_class($1)
+ list = register(o, klass.allocate)
+
+ members = Hash[o.children.map { |c| accept c }.each_slice(2).to_a]
+ list.replace members['internal']
+
+ members['ivars'].each do |ivar, v|
+ list.instance_variable_set ivar, v
+ end
+ list
+
+ when '!ruby/range'
+ klass = class_loader.range
+ h = Hash[*o.children.map { |c| accept c }]
+ register o, klass.new(h['begin'], h['end'], h['excl'])
+
+ when /^!ruby\/exception:?(.*)?$/
+ h = Hash[*o.children.map { |c| accept c }]
+
+ e = build_exception((resolve_class($1) || class_loader.exception),
+ h.delete('message'))
+
+ e.set_backtrace h.delete('backtrace') if h.key? 'backtrace'
+ init_with(e, h, o)
+
+ when '!set', 'tag:yaml.org,2002:set'
+ set = class_loader.psych_set.new
+ @st[o.anchor] = set if o.anchor
+ o.children.each_slice(2) do |k,v|
+ set[accept(k)] = accept(v)
+ end
+ set
+
+ when /^!ruby\/hash-with-ivars(?::(.*))?$/
+ hash = $1 ? resolve_class($1).allocate : {}
+ register o, hash
+ o.children.each_slice(2) do |key, value|
+ case key.value
+ when 'elements'
+ revive_hash hash, value
+ when 'ivars'
+ value.children.each_slice(2) do |k,v|
+ hash.instance_variable_set accept(k), accept(v)
+ end
+ end
+ end
+ hash
+
+ when /^!map:(.*)$/, /^!ruby\/hash:(.*)$/
+ revive_hash register(o, resolve_class($1).allocate), o
+
+ when '!omap', 'tag:yaml.org,2002:omap'
+ map = register(o, class_loader.psych_omap.new)
+ o.children.each_slice(2) do |l,r|
+ map[accept(l)] = accept r
+ end
+ map
+
+ when /^!ruby\/marshalable:(.*)$/
+ name = $1
+ klass = resolve_class(name)
+ obj = register(o, klass.allocate)
+
+ if obj.respond_to?(:init_with)
+ init_with(obj, revive_hash({}, o), o)
+ elsif obj.respond_to?(:marshal_load)
+ marshal_data = o.children.map(&method(:accept))
+ obj.marshal_load(marshal_data)
+ obj
+ else
+ raise ArgumentError, "Cannot deserialize #{name}"
+ end
+
+ else
+ revive_hash(register(o, {}), o)
+ end
+ end
+
+ def visit_Psych_Nodes_Document o
+ accept o.root
+ end
+
+ def visit_Psych_Nodes_Stream o
+ o.children.map { |c| accept c }
+ end
+
+ def visit_Psych_Nodes_Alias o
+ @st.fetch(o.anchor) { raise AnchorNotDefined, o.anchor }
+ end
+
+ private
+
+ def register node, object
+ @st[node.anchor] = object if node.anchor
+ object
+ end
+
+ def register_empty object
+ list = register(object, [])
+ object.children.each { |c| list.push accept c }
+ list
+ end
+
+ def allocate_anon_data node, members
+ klass = class_loader.data.define(*members.keys)
+ register(node, klass.allocate)
+ end
+
+ def revive_data_members hash, o
+ o.children.each_slice(2) do |k,v|
+ name = accept(k)
+ value = accept(v)
+ hash[class_loader.symbolize(name)] = value
+ end
+ hash
+ end
+
+ def revive_hash hash, o, tagged= false
+ o.children.each_slice(2) { |k,v|
+ key = accept(k)
+ val = accept(v)
+
+ if key == '<<' && k.tag != "tag:yaml.org,2002:str"
+ case v
+ when Nodes::Alias, Nodes::Mapping
+ begin
+ hash.merge! val
+ rescue TypeError
+ hash[key] = val
+ end
+ when Nodes::Sequence
+ begin
+ h = {}
+ val.reverse_each do |value|
+ h.merge! value
+ end
+ hash.merge! h
+ rescue TypeError
+ hash[key] = val
+ end
+ else
+ hash[key] = val
+ end
+ else
+ if !tagged && @symbolize_names && key.is_a?(String)
+ key = key.to_sym
+ elsif !@freeze
+ key = deduplicate(key)
+ end
+
+ hash[key] = val
+ end
+
+ }
+ hash
+ end
+
+ if RUBY_VERSION < '2.7'
+ def deduplicate key
+ if key.is_a?(String)
+ # It is important to untaint the string, otherwise it won't
+ # be deduplicated into an fstring, but simply frozen.
+ -(key.untaint)
+ else
+ key
+ end
+ end
+ else
+ def deduplicate key
+ if key.is_a?(String)
+ -key
+ else
+ key
+ end
+ end
+ end
+
+ def merge_key hash, key, val
+ end
+
+ def revive klass, node
+ s = register(node, klass.allocate)
+ init_with(s, revive_hash({}, node, true), node)
+ end
+
+ def init_with o, h, node
+ c = Psych::Coder.new(node.tag)
+ c.map = h
+
+ if o.respond_to?(:init_with)
+ o.init_with c
+ else
+ h.each { |k,v| o.instance_variable_set(:"@#{k}", v) }
+ end
+ o
+ end
+
+ # Convert +klassname+ to a Class
+ def resolve_class klassname
+ class_loader.load klassname
+ end
+ end
+
+ class NoAliasRuby < ToRuby
+ def visit_Psych_Nodes_Alias o
+ raise AliasesNotEnabled
+ end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/visitors/visitor.rb b/ext/psych/lib/psych/visitors/visitor.rb
new file mode 100644
index 0000000000..21052aa66f
--- /dev/null
+++ b/ext/psych/lib/psych/visitors/visitor.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+module Psych
+ module Visitors
+ class Visitor
+ def accept target
+ visit target
+ end
+
+ private
+
+ # @api private
+ def self.dispatch_cache
+ Hash.new do |hash, klass|
+ hash[klass] = :"visit_#{klass.name.gsub('::', '_')}"
+ end.compare_by_identity
+ end
+
+ if defined?(Ractor)
+ def dispatch
+ @dispatch_cache ||= (Ractor.current[:Psych_Visitors_Visitor] ||= Visitor.dispatch_cache)
+ end
+ else
+ DISPATCH = dispatch_cache
+ def dispatch
+ DISPATCH
+ end
+ end
+
+ def visit target
+ send dispatch[target.class], target
+ end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb
new file mode 100644
index 0000000000..b6c86f4c94
--- /dev/null
+++ b/ext/psych/lib/psych/visitors/yaml_tree.rb
@@ -0,0 +1,626 @@
+# frozen_string_literal: true
+require_relative '../tree_builder'
+require_relative '../scalar_scanner'
+require_relative '../class_loader'
+
+module Psych
+ module Visitors
+ ###
+ # YAMLTree builds a YAML ast given a Ruby object. For example:
+ #
+ # builder = Psych::Visitors::YAMLTree.new
+ # builder << { :foo => 'bar' }
+ # builder.tree # => #<Psych::Nodes::Stream .. }
+ #
+ class YAMLTree < Psych::Visitors::Visitor
+ class Registrar # :nodoc:
+ def initialize
+ @obj_to_id = {}.compare_by_identity
+ @obj_to_node = {}.compare_by_identity
+ @counter = 0
+ end
+
+ def register target, node
+ @obj_to_node[target] = node
+ end
+
+ def key? target
+ @obj_to_node.key? target
+ end
+
+ def id_for target
+ @obj_to_id[target] ||= (@counter += 1)
+ end
+
+ def node_for target
+ @obj_to_node[target]
+ end
+ end
+
+ attr_reader :started, :finished
+ alias :finished? :finished
+ alias :started? :started
+
+ def self.create options = {}, emitter = nil
+ emitter ||= TreeBuilder.new
+ class_loader = ClassLoader.new
+ ss = ScalarScanner.new class_loader
+ new(emitter, ss, options)
+ end
+
+ def initialize emitter, ss, options
+ super()
+ @started = false
+ @finished = false
+ @emitter = emitter
+ @st = Registrar.new
+ @ss = ss
+ @options = options
+ @line_width = options[:line_width]
+ if @line_width && @line_width < 0
+ if @line_width == -1
+ # Treat -1 as unlimited line-width, same as libyaml does.
+ @line_width = nil
+ else
+ fail(ArgumentError, "Invalid line_width #{@line_width}, must be non-negative or -1 for unlimited.")
+ end
+ end
+ @stringify_names = options[:stringify_names]
+ @coders = []
+
+ @dispatch_cache = Hash.new do |h,klass|
+ method = "visit_#{(klass.name || '').split('::').join('_')}"
+
+ method = respond_to?(method) ? method : h[klass.superclass]
+
+ raise(TypeError, "can't dump #{klass.name}") unless method
+
+ h[klass] = method
+ end.compare_by_identity
+ end
+
+ def start encoding = Nodes::Stream::UTF8
+ @emitter.start_stream(encoding).tap do
+ @started = true
+ end
+ end
+
+ def finish
+ @emitter.end_stream.tap do
+ @finished = true
+ end
+ end
+
+ def tree
+ finish unless finished?
+ @emitter.root
+ end
+
+ def push object
+ start unless started?
+ version = []
+ version = [1,1] if @options[:header]
+
+ case @options[:version]
+ when Array
+ version = @options[:version]
+ when String
+ version = @options[:version].split('.').map { |x| x.to_i }
+ else
+ version = [1,1]
+ end if @options.key? :version
+
+ @emitter.start_document version, [], false
+ accept object
+ @emitter.end_document !@emitter.streaming?
+ end
+ alias :<< :push
+
+ def accept target
+ # return any aliases we find
+ if @st.key? target
+ oid = @st.id_for target
+ node = @st.node_for target
+ anchor = oid.to_s
+ node.anchor = anchor
+ return @emitter.alias anchor
+ end
+
+ if target.respond_to?(:encode_with)
+ dump_coder target
+ else
+ send(@dispatch_cache[target.class], target)
+ end
+ end
+
+ def visit_Psych_Omap o
+ seq = @emitter.start_sequence(nil, 'tag:yaml.org,2002:omap', false, Nodes::Sequence::BLOCK)
+ register(o, seq)
+
+ o.each { |k,v| visit_Hash k => v }
+ @emitter.end_sequence
+ end
+
+ def visit_Encoding o
+ tag = "!ruby/encoding"
+ @emitter.scalar o.name, nil, tag, false, false, Nodes::Scalar::ANY
+ end
+
+ def visit_Object o
+ tag = Psych.dump_tags[o.class]
+ unless tag
+ klass = o.class == Object ? nil : o.class.name
+ tag = ['!ruby/object', klass].compact.join(':')
+ end
+
+ map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
+ register(o, map)
+
+ dump_ivars o
+ @emitter.end_mapping
+ end
+
+ alias :visit_Delegator :visit_Object
+
+ def visit_Data o
+ ivars = o.instance_variables
+ if ivars.empty?
+ tag = ['!ruby/data', o.class.name].compact.join(':')
+ register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
+ o.members.each do |member|
+ @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
+ accept o.send member
+ end
+ @emitter.end_mapping
+
+ else
+ tag = ['!ruby/data-with-ivars', o.class.name].compact.join(':')
+ node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
+ register(o, node)
+
+ # Dump the members
+ accept 'members'
+ @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
+ o.members.each do |member|
+ @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
+ accept o.send member
+ end
+ @emitter.end_mapping
+
+ # Dump the ivars
+ accept 'ivars'
+ @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
+ ivars.each do |ivar|
+ accept ivar.to_s
+ accept o.instance_variable_get ivar
+ end
+ @emitter.end_mapping
+
+ @emitter.end_mapping
+ end
+ end unless RUBY_VERSION < "3.2"
+
+ def visit_Struct o
+ tag = ['!ruby/struct', o.class.name].compact.join(':')
+
+ register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
+ o.members.each do |member|
+ @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
+ accept o[member]
+ end
+
+ dump_ivars o
+
+ @emitter.end_mapping
+ end
+
+ def visit_Exception o
+ dump_exception o, o.message.to_s
+ end
+
+ def visit_NameError o
+ dump_exception o, o.message.to_s
+ end
+
+ def visit_Regexp o
+ register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
+ end
+
+ def visit_Date o
+ formatted = format_date o
+ register o, @emitter.scalar(formatted, nil, nil, true, false, Nodes::Scalar::ANY)
+ end
+
+ def visit_DateTime o
+ t = o.italy
+ formatted = format_time t, t.offset.zero?
+ tag = '!ruby/object:DateTime'
+ register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY)
+ end
+
+ def visit_Time o
+ formatted = format_time o
+ register o, @emitter.scalar(formatted, nil, nil, true, false, Nodes::Scalar::ANY)
+ end
+
+ def visit_Rational o
+ register o, @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)
+
+ [
+ 'denominator', o.denominator.to_s,
+ 'numerator', o.numerator.to_s
+ ].each do |m|
+ @emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
+ end
+
+ @emitter.end_mapping
+ end
+
+ def visit_Complex o
+ register o, @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK)
+
+ ['real', o.real.to_s, 'image', o.imag.to_s].each do |m|
+ @emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
+ end
+
+ @emitter.end_mapping
+ end
+
+ def visit_Integer o
+ @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
+ end
+ alias :visit_TrueClass :visit_Integer
+ alias :visit_FalseClass :visit_Integer
+
+ def visit_Float o
+ if o.nan?
+ @emitter.scalar '.nan', nil, nil, true, false, Nodes::Scalar::ANY
+ elsif o.infinite?
+ @emitter.scalar((o.infinite? > 0 ? '.inf' : '-.inf'),
+ nil, nil, true, false, Nodes::Scalar::ANY)
+ else
+ @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
+ end
+ end
+
+ def visit_BigDecimal o
+ @emitter.scalar o._dump, nil, '!ruby/object:BigDecimal', false, false, Nodes::Scalar::ANY
+ end
+
+ def visit_String o
+ plain = true
+ quote = true
+ style = Nodes::Scalar::PLAIN
+ tag = nil
+
+ if binary?(o)
+ o = [o].pack('m0')
+ tag = '!binary' # FIXME: change to below when syck is removed
+ #tag = 'tag:yaml.org,2002:binary'
+ style = Nodes::Scalar::LITERAL
+ plain = false
+ quote = false
+ elsif o.match?(/\n(?!\Z)/) # match \n except blank line at the end of string
+ style = Nodes::Scalar::LITERAL
+ elsif o == '<<'
+ style = Nodes::Scalar::SINGLE_QUOTED
+ tag = 'tag:yaml.org,2002:str'
+ plain = false
+ quote = false
+ elsif o == 'y' || o == 'Y' || o == 'n' || o == 'N'
+ style = Nodes::Scalar::DOUBLE_QUOTED
+ elsif @line_width && o.length > @line_width
+ style = Nodes::Scalar::FOLDED
+ elsif o.match?(/^[^[:word:]][^"]*$/)
+ style = Nodes::Scalar::DOUBLE_QUOTED
+ elsif not String === @ss.tokenize(o) or /\A0[0-7]*[89]/.match?(o)
+ style = Nodes::Scalar::SINGLE_QUOTED
+ end
+
+ is_primitive = o.class == ::String
+ ivars = is_primitive ? [] : o.instance_variables
+
+ if ivars.empty?
+ unless is_primitive
+ tag = "!ruby/string:#{o.class}"
+ plain = false
+ quote = false
+ end
+ @emitter.scalar o, nil, tag, plain, quote, style
+ else
+ maptag = '!ruby/string'.dup
+ maptag << ":#{o.class}" unless o.class == ::String
+
+ register o, @emitter.start_mapping(nil, maptag, false, Nodes::Mapping::BLOCK)
+ @emitter.scalar 'str', nil, nil, true, false, Nodes::Scalar::ANY
+ @emitter.scalar o, nil, tag, plain, quote, style
+
+ dump_ivars o
+
+ @emitter.end_mapping
+ end
+ end
+
+ def visit_Module o
+ raise TypeError, "can't dump anonymous module: #{o}" unless o.name
+ register o, @emitter.scalar(o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED)
+ end
+
+ def visit_Class o
+ raise TypeError, "can't dump anonymous class: #{o}" unless o.name
+ register o, @emitter.scalar(o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED)
+ end
+
+ def visit_Range o
+ register o, @emitter.start_mapping(nil, '!ruby/range', false, Nodes::Mapping::BLOCK)
+ ['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m|
+ accept m
+ end
+ @emitter.end_mapping
+ end
+
+ def visit_Hash o
+ if o.class == ::Hash
+ register(o, @emitter.start_mapping(nil, nil, true, Psych::Nodes::Mapping::BLOCK))
+ o.each do |k,v|
+ accept(@stringify_names && Symbol === k ? k.to_s : k)
+ accept v
+ end
+ @emitter.end_mapping
+ else
+ visit_hash_subclass o
+ end
+ end
+
+ def visit_Psych_Set o
+ register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK))
+
+ o.each do |k,v|
+ accept(@stringify_names && Symbol === k ? k.to_s : k)
+ accept v
+ end
+
+ @emitter.end_mapping
+ end
+
+ def visit_Array o
+ if o.class == ::Array
+ visit_Enumerator o
+ else
+ visit_array_subclass o
+ end
+ end
+
+ def visit_Enumerator o
+ register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
+ o.each { |c| accept c }
+ @emitter.end_sequence
+ end
+
+ def visit_NilClass o
+ @emitter.scalar('', nil, 'tag:yaml.org,2002:null', true, false, Nodes::Scalar::ANY)
+ end
+
+ def visit_Symbol o
+ if o.empty?
+ @emitter.scalar "", nil, '!ruby/symbol', false, false, Nodes::Scalar::ANY
+ else
+ @emitter.scalar ":#{o}", nil, nil, true, false, Nodes::Scalar::ANY
+ end
+ end
+
+ def visit_BasicObject o
+ tag = Psych.dump_tags[o.class]
+ tag ||= "!ruby/marshalable:#{o.class.name}"
+
+ map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
+ register(o, map)
+
+ o.marshal_dump.each(&method(:accept))
+
+ @emitter.end_mapping
+ end
+
+ private
+
+ def binary? string
+ string.encoding == Encoding::ASCII_8BIT && !string.ascii_only?
+ end
+
+ def visit_array_subclass o
+ tag = "!ruby/array:#{o.class}"
+ ivars = o.instance_variables
+ if ivars.empty?
+ node = @emitter.start_sequence(nil, tag, false, Nodes::Sequence::BLOCK)
+ register o, node
+ o.each { |c| accept c }
+ @emitter.end_sequence
+ else
+ node = @emitter.start_mapping(nil, tag, false, Nodes::Sequence::BLOCK)
+ register o, node
+
+ # Dump the internal list
+ accept 'internal'
+ @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
+ o.each { |c| accept c }
+ @emitter.end_sequence
+
+ # Dump the ivars
+ accept 'ivars'
+ @emitter.start_mapping(nil, nil, true, Nodes::Sequence::BLOCK)
+ ivars.each do |ivar|
+ accept ivar
+ accept o.instance_variable_get ivar
+ end
+ @emitter.end_mapping
+
+ @emitter.end_mapping
+ end
+ end
+
+ def visit_hash_subclass o
+ ivars = o.instance_variables
+ if ivars.any?
+ tag = "!ruby/hash-with-ivars:#{o.class}"
+ node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
+ register(o, node)
+
+ # Dump the ivars
+ accept 'ivars'
+ @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
+ o.instance_variables.each do |ivar|
+ accept ivar
+ accept o.instance_variable_get ivar
+ end
+ @emitter.end_mapping
+
+ # Dump the elements
+ accept 'elements'
+ @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
+ o.each do |k,v|
+ accept k
+ accept v
+ end
+ @emitter.end_mapping
+
+ @emitter.end_mapping
+ else
+ tag = "!ruby/hash:#{o.class}"
+ node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
+ register(o, node)
+ o.each do |k,v|
+ accept k
+ accept v
+ end
+ @emitter.end_mapping
+ end
+ end
+
+ def dump_list o
+ end
+
+ def dump_exception o, msg
+ tag = ['!ruby/exception', o.class.name].join ':'
+
+ @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
+
+ if msg
+ @emitter.scalar 'message', nil, nil, true, false, Nodes::Scalar::ANY
+ accept msg
+ end
+
+ @emitter.scalar 'backtrace', nil, nil, true, false, Nodes::Scalar::ANY
+ accept o.backtrace
+
+ dump_ivars o
+
+ @emitter.end_mapping
+ end
+
+ def format_time time, utc = time.utc?
+ if utc
+ time.strftime("%Y-%m-%d %H:%M:%S.%9N Z")
+ else
+ time.strftime("%Y-%m-%d %H:%M:%S.%9N %:z")
+ end
+ end
+
+ def format_date date
+ date.strftime("%Y-%m-%d")
+ end
+
+ def register target, yaml_obj
+ @st.register target, yaml_obj
+ yaml_obj
+ end
+
+ def dump_coder o
+ @coders << o
+ tag = Psych.dump_tags[o.class]
+ unless tag
+ klass = o.class == Object ? nil : o.class.name
+ tag = ['!ruby/object', klass].compact.join(':')
+ end
+
+ c = Psych::Coder.new(tag)
+ o.encode_with(c)
+ emit_coder c, o
+ end
+
+ def emit_coder c, o
+ case c.type
+ when :scalar
+ @emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, c.style
+ when :seq
+ @emitter.start_sequence nil, c.tag, c.tag.nil?, c.style
+ c.seq.each do |thing|
+ accept thing
+ end
+ @emitter.end_sequence
+ when :map
+ register o, @emitter.start_mapping(nil, c.tag, c.implicit, c.style)
+ c.map.each do |k,v|
+ accept k
+ accept v
+ end
+ @emitter.end_mapping
+ when :object
+ accept c.object
+ end
+ end
+
+ def dump_ivars target
+ target.instance_variables.each do |iv|
+ @emitter.scalar("#{iv.to_s.sub(/^@/, '')}", nil, nil, true, false, Nodes::Scalar::ANY)
+ accept target.instance_variable_get(iv)
+ end
+ end
+ end
+
+ class RestrictedYAMLTree < YAMLTree
+ DEFAULT_PERMITTED_CLASSES = {
+ TrueClass => true,
+ FalseClass => true,
+ NilClass => true,
+ Integer => true,
+ Float => true,
+ String => true,
+ Array => true,
+ Hash => true,
+ }.compare_by_identity.freeze
+
+ def initialize emitter, ss, options
+ super
+ @permitted_classes = DEFAULT_PERMITTED_CLASSES.dup
+ Array(options[:permitted_classes]).each do |klass|
+ @permitted_classes[klass] = true
+ end
+ @permitted_symbols = {}.compare_by_identity
+ Array(options[:permitted_symbols]).each do |symbol|
+ @permitted_symbols[symbol] = true
+ end
+ @aliases = options.fetch(:aliases, false)
+ end
+
+ def accept target
+ if !@aliases && @st.key?(target)
+ raise BadAlias, "Tried to dump an aliased object"
+ end
+
+ unless Symbol === target || @permitted_classes[target.class]
+ raise DisallowedClass.new('dump', target.class.name || target.class.inspect)
+ end
+
+ super
+ end
+
+ def visit_Symbol sym
+ unless @permitted_classes[Symbol] || @permitted_symbols[sym]
+ raise DisallowedClass.new('dump', "Symbol(#{sym.inspect})")
+ end
+
+ super
+ end
+ end
+ end
+end
diff --git a/ext/psych/lib/psych/y.rb b/ext/psych/lib/psych/y.rb
new file mode 100644
index 0000000000..e857953c04
--- /dev/null
+++ b/ext/psych/lib/psych/y.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+module Kernel
+ ###
+ # An alias for Psych.dump_stream meant to be used with IRB.
+ def y *objects
+ puts Psych.dump_stream(*objects)
+ end
+ private :y
+end
+
diff --git a/ext/psych/psych.c b/ext/psych/psych.c
new file mode 100644
index 0000000000..afbd7a3571
--- /dev/null
+++ b/ext/psych/psych.c
@@ -0,0 +1,36 @@
+#include <psych.h>
+
+/* call-seq: Psych.libyaml_version
+ *
+ * Returns the version of libyaml being used
+ */
+static VALUE libyaml_version(VALUE module)
+{
+ int major, minor, patch;
+ VALUE list[3];
+
+ yaml_get_version(&major, &minor, &patch);
+
+ list[0] = INT2NUM(major);
+ list[1] = INT2NUM(minor);
+ list[2] = INT2NUM(patch);
+
+ return rb_ary_new4((long)3, list);
+}
+
+VALUE mPsych;
+
+void Init_psych(void)
+{
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
+ RB_EXT_RACTOR_SAFE(true);
+ #endif
+ mPsych = rb_define_module("Psych");
+
+ rb_define_singleton_method(mPsych, "libyaml_version", libyaml_version, 0);
+
+ Init_psych_parser();
+ Init_psych_emitter();
+ Init_psych_to_ruby();
+ Init_psych_yaml_tree();
+}
diff --git a/ext/psych/psych.gemspec b/ext/psych/psych.gemspec
new file mode 100644
index 0000000000..a32f79bc16
--- /dev/null
+++ b/ext/psych/psych.gemspec
@@ -0,0 +1,82 @@
+# -*- encoding: utf-8 -*-
+# frozen_string_literal: true
+
+version_module = Module.new do
+ version_rb = File.join(__dir__, "lib/psych/versions.rb")
+ module_eval(File.read(version_rb), version_rb)
+end
+
+Gem::Specification.new do |s|
+ s.name = "psych"
+ s.version = version_module::Psych::VERSION
+ s.authors = ["Aaron Patterson", "SHIBATA Hiroshi", "Charles Oliver Nutter"]
+ s.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org", "headius@headius.com"]
+ s.summary = "Psych is a YAML parser and emitter"
+ s.description = <<-DESCRIPTION
+Psych is a YAML parser and emitter. Psych leverages libyaml[https://pyyaml.org/wiki/LibYAML]
+for its YAML parsing and emitting capabilities. In addition to wrapping libyaml,
+Psych also knows how to serialize and de-serialize most Ruby objects to and from the YAML format.
+DESCRIPTION
+ s.homepage = "https://github.com/ruby/psych"
+ s.licenses = ["MIT"]
+ s.require_paths = ["lib"]
+
+ # for ruby core repository.
+ # It was generated by
+ # `git ls-files -z`.split("\x0").reject { |f|
+ # f.match(%r{^\.git|^(test|spec|features|bin|tool)/|^[A-Z]\w+file$|/extlibs$|\.(gemspec|java)$|jar})
+ # }
+ s.files = [
+ "CONTRIBUTING.md", "LICENSE", "README.md", "ext/psych/depend",
+ "ext/psych/extconf.rb", "ext/psych/psych.c", "ext/psych/psych.h",
+ "ext/psych/psych_emitter.c", "ext/psych/psych_emitter.h",
+ "ext/psych/psych_parser.c", "ext/psych/psych_parser.h",
+ "ext/psych/psych_to_ruby.c", "ext/psych/psych_to_ruby.h",
+ "ext/psych/psych_yaml_tree.c", "ext/psych/psych_yaml_tree.h",
+ "lib/psych.rb", "lib/psych/class_loader.rb", "lib/psych/coder.rb",
+ "lib/psych/core_ext.rb", "lib/psych/exception.rb", "lib/psych/handler.rb",
+ "lib/psych/handlers/document_stream.rb", "lib/psych/handlers/recorder.rb",
+ "lib/psych/json/ruby_events.rb", "lib/psych/json/stream.rb",
+ "lib/psych/json/tree_builder.rb", "lib/psych/json/yaml_events.rb",
+ "lib/psych/nodes.rb", "lib/psych/nodes/alias.rb",
+ "lib/psych/nodes/document.rb", "lib/psych/nodes/mapping.rb",
+ "lib/psych/nodes/node.rb", "lib/psych/nodes/scalar.rb",
+ "lib/psych/nodes/sequence.rb", "lib/psych/nodes/stream.rb",
+ "lib/psych/omap.rb", "lib/psych/parser.rb", "lib/psych/scalar_scanner.rb",
+ "lib/psych/set.rb", "lib/psych/stream.rb", "lib/psych/streaming.rb",
+ "lib/psych/syntax_error.rb", "lib/psych/tree_builder.rb",
+ "lib/psych/versions.rb", "lib/psych/visitors.rb",
+ "lib/psych/visitors/depth_first.rb", "lib/psych/visitors/emitter.rb",
+ "lib/psych/visitors/json_tree.rb", "lib/psych/visitors/to_ruby.rb",
+ "lib/psych/visitors/visitor.rb", "lib/psych/visitors/yaml_tree.rb",
+ "lib/psych/y.rb"
+ ]
+
+ s.rdoc_options = ["--main", "README.md"]
+ s.extra_rdoc_files = ["README.md"]
+
+ s.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
+ s.required_rubygems_version = Gem::Requirement.new(">= 0")
+
+ if RUBY_ENGINE == 'jruby'
+ s.platform = 'java'
+ s.files.concat [
+ "ext/java/org/jruby/ext/psych/PsychEmitter.java",
+ "ext/java/org/jruby/ext/psych/PsychLibrary.java",
+ "ext/java/org/jruby/ext/psych/PsychParser.java",
+ "ext/java/org/jruby/ext/psych/PsychToRuby.java",
+ "lib/psych_jars.rb",
+ "lib/psych.jar"
+ ]
+ s.requirements = "jar org.snakeyaml:snakeyaml-engine, #{version_module::Psych::DEFAULT_SNAKEYAML_VERSION}"
+ s.add_dependency 'jar-dependencies', '>= 0.1.7'
+ else
+ s.extensions = ["ext/psych/extconf.rb"]
+ s.add_dependency 'stringio'
+ end
+
+ s.add_dependency 'date'
+
+ s.metadata['msys2_mingw_dependencies'] = 'libyaml'
+ s.metadata['changelog_uri'] = s.homepage + '/releases'
+end
diff --git a/ext/psych/psych.h b/ext/psych/psych.h
new file mode 100644
index 0000000000..6b3d63f246
--- /dev/null
+++ b/ext/psych/psych.h
@@ -0,0 +1,17 @@
+#ifndef PSYCH_H
+#define PSYCH_H
+
+#include <ruby.h>
+#include <ruby/encoding.h>
+
+#include <yaml.h>
+
+#include <psych_parser.h>
+#include <psych_emitter.h>
+#include <psych_to_ruby.h>
+#include <psych_yaml_tree.h>
+
+extern VALUE mPsych;
+
+
+#endif
diff --git a/ext/psych/psych_emitter.c b/ext/psych/psych_emitter.c
new file mode 100644
index 0000000000..624ab7c528
--- /dev/null
+++ b/ext/psych/psych_emitter.c
@@ -0,0 +1,589 @@
+#include <psych.h>
+
+#if !defined(RARRAY_CONST_PTR)
+#define RARRAY_CONST_PTR(s) (const VALUE *)RARRAY_PTR(s)
+#endif
+#if !defined(RARRAY_AREF)
+#define RARRAY_AREF(a, i) RARRAY_CONST_PTR(a)[i]
+#endif
+
+VALUE cPsychEmitter;
+static ID id_io;
+static ID id_write;
+static ID id_line_width;
+static ID id_indentation;
+static ID id_canonical;
+
+static void emit(yaml_emitter_t * emitter, yaml_event_t * event)
+{
+ if(!yaml_emitter_emit(emitter, event))
+ rb_raise(rb_eRuntimeError, "%s", emitter->problem);
+}
+
+static int writer(void *ctx, unsigned char *buffer, size_t size)
+{
+ VALUE self = (VALUE)ctx, io = rb_attr_get(self, id_io);
+ VALUE str = rb_enc_str_new((const char *)buffer, (long)size, rb_utf8_encoding());
+ VALUE wrote = rb_funcall(io, id_write, 1, str);
+ return (int)NUM2INT(wrote);
+}
+
+static void dealloc(void * ptr)
+{
+ yaml_emitter_t * emitter;
+
+ emitter = (yaml_emitter_t *)ptr;
+ yaml_emitter_delete(emitter);
+ xfree(emitter);
+}
+
+#if 0
+static size_t memsize(const void *ptr)
+{
+ const yaml_emitter_t *emitter = ptr;
+ /* TODO: calculate emitter's size */
+ return 0;
+}
+#endif
+
+static const rb_data_type_t psych_emitter_type = {
+ "Psych/emitter",
+ {0, dealloc, 0,},
+ 0, 0,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
+ RUBY_TYPED_FREE_IMMEDIATELY,
+#endif
+};
+
+static VALUE allocate(VALUE klass)
+{
+ yaml_emitter_t * emitter;
+ VALUE obj = TypedData_Make_Struct(klass, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ yaml_emitter_initialize(emitter);
+ yaml_emitter_set_unicode(emitter, 1);
+ yaml_emitter_set_indent(emitter, 2);
+
+ return obj;
+}
+
+/* call-seq: Psych::Emitter.new(io, options = Psych::Emitter::OPTIONS)
+ *
+ * Create a new Psych::Emitter that writes to +io+.
+ */
+static VALUE initialize(int argc, VALUE *argv, VALUE self)
+{
+ yaml_emitter_t * emitter;
+ VALUE io, options;
+ VALUE line_width;
+ VALUE indent;
+ VALUE canonical;
+
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ if (rb_scan_args(argc, argv, "11", &io, &options) == 2) {
+ line_width = rb_funcall(options, id_line_width, 0);
+ indent = rb_funcall(options, id_indentation, 0);
+ canonical = rb_funcall(options, id_canonical, 0);
+
+ yaml_emitter_set_width(emitter, NUM2INT(line_width));
+ yaml_emitter_set_indent(emitter, NUM2INT(indent));
+ yaml_emitter_set_canonical(emitter, Qtrue == canonical ? 1 : 0);
+ }
+
+ rb_ivar_set(self, id_io, io);
+ yaml_emitter_set_output(emitter, writer, (void *)self);
+
+ return self;
+}
+
+/* call-seq: emitter.start_stream(encoding)
+ *
+ * Start a stream emission with +encoding+
+ *
+ * See Psych::Handler#start_stream
+ */
+static VALUE start_stream(VALUE self, VALUE encoding)
+{
+ yaml_emitter_t * emitter;
+ yaml_event_t event;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+ Check_Type(encoding, T_FIXNUM);
+
+ yaml_stream_start_event_initialize(&event, (yaml_encoding_t)NUM2INT(encoding));
+
+ emit(emitter, &event);
+
+ return self;
+}
+
+/* call-seq: emitter.end_stream
+ *
+ * End a stream emission
+ *
+ * See Psych::Handler#end_stream
+ */
+static VALUE end_stream(VALUE self)
+{
+ yaml_emitter_t * emitter;
+ yaml_event_t event;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ yaml_stream_end_event_initialize(&event);
+
+ emit(emitter, &event);
+
+ return self;
+}
+
+struct start_document_data {
+ VALUE self;
+ VALUE version;
+ VALUE tags;
+ VALUE imp;
+
+ yaml_tag_directive_t * head;
+};
+
+static VALUE start_document_try(VALUE d)
+{
+ struct start_document_data * data = (struct start_document_data *)d;
+ VALUE self = data->self;
+ VALUE version = data->version;
+ VALUE tags = data->tags;
+ VALUE imp = data->imp;
+
+ yaml_emitter_t * emitter;
+ yaml_tag_directive_t * tail = NULL;
+ yaml_event_t event;
+ yaml_version_directive_t version_directive;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ Check_Type(version, T_ARRAY);
+
+ if(RARRAY_LEN(version) > 0) {
+ VALUE major = rb_ary_entry(version, (long)0);
+ VALUE minor = rb_ary_entry(version, (long)1);
+
+ version_directive.major = NUM2INT(major);
+ version_directive.minor = NUM2INT(minor);
+ }
+
+ if(RTEST(tags)) {
+ long i = 0;
+ long len;
+ rb_encoding * encoding = rb_utf8_encoding();
+
+ Check_Type(tags, T_ARRAY);
+
+ len = RARRAY_LEN(tags);
+ data->head = xcalloc((size_t)len, sizeof(yaml_tag_directive_t));
+ tail = data->head;
+
+ for(i = 0; i < len && i < RARRAY_LEN(tags); i++) {
+ VALUE tuple = RARRAY_AREF(tags, i);
+ VALUE name;
+ VALUE value;
+
+ Check_Type(tuple, T_ARRAY);
+
+ if(RARRAY_LEN(tuple) < 2) {
+ rb_raise(rb_eRuntimeError, "tag tuple must be of length 2");
+ }
+
+ name = RARRAY_AREF(tuple, 0);
+ value = RARRAY_AREF(tuple, 1);
+ StringValue(name);
+ StringValue(value);
+ name = rb_str_export_to_enc(name, encoding);
+ value = rb_str_export_to_enc(value, encoding);
+
+ tail->handle = (yaml_char_t *)StringValueCStr(name);
+ tail->prefix = (yaml_char_t *)StringValueCStr(value);
+
+ tail++;
+ }
+ }
+
+ yaml_document_start_event_initialize(
+ &event,
+ (RARRAY_LEN(version) > 0) ? &version_directive : NULL,
+ data->head,
+ tail,
+ imp ? 1 : 0
+ );
+
+ emit(emitter, &event);
+
+ return self;
+}
+
+static VALUE start_document_ensure(VALUE d)
+{
+ struct start_document_data * data = (struct start_document_data *)d;
+
+ xfree(data->head);
+
+ return Qnil;
+}
+
+/* call-seq: emitter.start_document(version, tags, implicit)
+ *
+ * Start a document emission with YAML +version+, +tags+, and an +implicit+
+ * start.
+ *
+ * See Psych::Handler#start_document
+ */
+static VALUE start_document(VALUE self, VALUE version, VALUE tags, VALUE imp)
+{
+ struct start_document_data data = {
+ .self = self,
+ .version = version,
+ .tags = tags,
+ .imp = imp,
+
+ .head = NULL,
+ };
+
+ return rb_ensure(start_document_try, (VALUE)&data, start_document_ensure, (VALUE)&data);
+}
+
+/* call-seq: emitter.end_document(implicit)
+ *
+ * End a document emission with an +implicit+ ending.
+ *
+ * See Psych::Handler#end_document
+ */
+static VALUE end_document(VALUE self, VALUE imp)
+{
+ yaml_emitter_t * emitter;
+ yaml_event_t event;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ yaml_document_end_event_initialize(&event, imp ? 1 : 0);
+
+ emit(emitter, &event);
+
+ return self;
+}
+
+/* call-seq: emitter.scalar(value, anchor, tag, plain, quoted, style)
+ *
+ * Emit a scalar with +value+, +anchor+, +tag+, and a +plain+ or +quoted+
+ * string type with +style+.
+ *
+ * See Psych::Handler#scalar
+ */
+static VALUE scalar(
+ VALUE self,
+ VALUE value,
+ VALUE anchor,
+ VALUE tag,
+ VALUE plain,
+ VALUE quoted,
+ VALUE style
+ ) {
+ yaml_emitter_t * emitter;
+ yaml_event_t event;
+ rb_encoding *encoding;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ Check_Type(value, T_STRING);
+
+ encoding = rb_utf8_encoding();
+
+ value = rb_str_export_to_enc(value, encoding);
+
+ if(!NIL_P(anchor)) {
+ Check_Type(anchor, T_STRING);
+ anchor = rb_str_export_to_enc(anchor, encoding);
+ }
+
+ if(!NIL_P(tag)) {
+ Check_Type(tag, T_STRING);
+ tag = rb_str_export_to_enc(tag, encoding);
+ }
+
+ const char *value_ptr = StringValuePtr(value);
+ yaml_scalar_event_initialize(
+ &event,
+ (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)),
+ (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)),
+ (yaml_char_t*)value_ptr,
+ (int)RSTRING_LEN(value),
+ plain ? 1 : 0,
+ quoted ? 1 : 0,
+ (yaml_scalar_style_t)NUM2INT(style)
+ );
+
+ emit(emitter, &event);
+
+ return self;
+}
+
+/* call-seq: emitter.start_sequence(anchor, tag, implicit, style)
+ *
+ * Start emitting a sequence with +anchor+, a +tag+, +implicit+ sequence
+ * start and end, along with +style+.
+ *
+ * See Psych::Handler#start_sequence
+ */
+static VALUE start_sequence(
+ VALUE self,
+ VALUE anchor,
+ VALUE tag,
+ VALUE implicit,
+ VALUE style
+ ) {
+ yaml_emitter_t * emitter;
+ yaml_event_t event;
+
+ rb_encoding * encoding = rb_utf8_encoding();
+
+ if(!NIL_P(anchor)) {
+ Check_Type(anchor, T_STRING);
+ anchor = rb_str_export_to_enc(anchor, encoding);
+ }
+
+ if(!NIL_P(tag)) {
+ Check_Type(tag, T_STRING);
+ tag = rb_str_export_to_enc(tag, encoding);
+ }
+
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ yaml_sequence_start_event_initialize(
+ &event,
+ (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)),
+ (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)),
+ implicit ? 1 : 0,
+ (yaml_sequence_style_t)NUM2INT(style)
+ );
+
+ emit(emitter, &event);
+
+ return self;
+}
+
+/* call-seq: emitter.end_sequence
+ *
+ * End sequence emission.
+ *
+ * See Psych::Handler#end_sequence
+ */
+static VALUE end_sequence(VALUE self)
+{
+ yaml_emitter_t * emitter;
+ yaml_event_t event;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ yaml_sequence_end_event_initialize(&event);
+
+ emit(emitter, &event);
+
+ return self;
+}
+
+/* call-seq: emitter.start_mapping(anchor, tag, implicit, style)
+ *
+ * Start emitting a YAML map with +anchor+, +tag+, an +implicit+ start
+ * and end, and +style+.
+ *
+ * See Psych::Handler#start_mapping
+ */
+static VALUE start_mapping(
+ VALUE self,
+ VALUE anchor,
+ VALUE tag,
+ VALUE implicit,
+ VALUE style
+ ) {
+ yaml_emitter_t * emitter;
+ yaml_event_t event;
+ rb_encoding *encoding;
+
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ encoding = rb_utf8_encoding();
+
+ if(!NIL_P(anchor)) {
+ Check_Type(anchor, T_STRING);
+ anchor = rb_str_export_to_enc(anchor, encoding);
+ }
+
+ if(!NIL_P(tag)) {
+ Check_Type(tag, T_STRING);
+ tag = rb_str_export_to_enc(tag, encoding);
+ }
+
+ yaml_mapping_start_event_initialize(
+ &event,
+ (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)),
+ (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)),
+ implicit ? 1 : 0,
+ (yaml_mapping_style_t)NUM2INT(style)
+ );
+
+ emit(emitter, &event);
+
+ return self;
+}
+
+/* call-seq: emitter.end_mapping
+ *
+ * Emit the end of a mapping.
+ *
+ * See Psych::Handler#end_mapping
+ */
+static VALUE end_mapping(VALUE self)
+{
+ yaml_emitter_t * emitter;
+ yaml_event_t event;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ yaml_mapping_end_event_initialize(&event);
+
+ emit(emitter, &event);
+
+ return self;
+}
+
+/* call-seq: emitter.alias(anchor)
+ *
+ * Emit an alias with +anchor+.
+ *
+ * See Psych::Handler#alias
+ */
+static VALUE alias(VALUE self, VALUE anchor)
+{
+ yaml_emitter_t * emitter;
+ yaml_event_t event;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ if(!NIL_P(anchor)) {
+ Check_Type(anchor, T_STRING);
+ anchor = rb_str_export_to_enc(anchor, rb_utf8_encoding());
+ }
+
+ yaml_alias_event_initialize(
+ &event,
+ (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor))
+ );
+
+ emit(emitter, &event);
+
+ return self;
+}
+
+/* call-seq: emitter.canonical = true
+ *
+ * Set the output style to canonical, or not.
+ */
+static VALUE set_canonical(VALUE self, VALUE style)
+{
+ yaml_emitter_t * emitter;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ yaml_emitter_set_canonical(emitter, Qtrue == style ? 1 : 0);
+
+ return style;
+}
+
+/* call-seq: emitter.canonical
+ *
+ * Get the output style, canonical or not.
+ */
+static VALUE canonical(VALUE self)
+{
+ yaml_emitter_t * emitter;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ return (emitter->canonical == 0) ? Qfalse : Qtrue;
+}
+
+/* call-seq: emitter.indentation = level
+ *
+ * Set the indentation level to +level+. The level must be less than 10 and
+ * greater than 1.
+ */
+static VALUE set_indentation(VALUE self, VALUE level)
+{
+ yaml_emitter_t * emitter;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ yaml_emitter_set_indent(emitter, NUM2INT(level));
+
+ return level;
+}
+
+/* call-seq: emitter.indentation
+ *
+ * Get the indentation level.
+ */
+static VALUE indentation(VALUE self)
+{
+ yaml_emitter_t * emitter;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ return INT2NUM(emitter->best_indent);
+}
+
+/* call-seq: emitter.line_width
+ *
+ * Get the preferred line width.
+ */
+static VALUE line_width(VALUE self)
+{
+ yaml_emitter_t * emitter;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ return INT2NUM(emitter->best_width);
+}
+
+/* call-seq: emitter.line_width = width
+ *
+ * Set the preferred line with to +width+.
+ */
+static VALUE set_line_width(VALUE self, VALUE width)
+{
+ yaml_emitter_t * emitter;
+ TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
+
+ yaml_emitter_set_width(emitter, NUM2INT(width));
+
+ return width;
+}
+
+void Init_psych_emitter(void)
+{
+#undef rb_intern
+ VALUE psych = rb_define_module("Psych");
+ VALUE handler = rb_define_class_under(psych, "Handler", rb_cObject);
+ cPsychEmitter = rb_define_class_under(psych, "Emitter", handler);
+
+ rb_define_alloc_func(cPsychEmitter, allocate);
+
+ rb_define_method(cPsychEmitter, "initialize", initialize, -1);
+ rb_define_method(cPsychEmitter, "start_stream", start_stream, 1);
+ rb_define_method(cPsychEmitter, "end_stream", end_stream, 0);
+ rb_define_method(cPsychEmitter, "start_document", start_document, 3);
+ rb_define_method(cPsychEmitter, "end_document", end_document, 1);
+ rb_define_method(cPsychEmitter, "scalar", scalar, 6);
+ rb_define_method(cPsychEmitter, "start_sequence", start_sequence, 4);
+ rb_define_method(cPsychEmitter, "end_sequence", end_sequence, 0);
+ rb_define_method(cPsychEmitter, "start_mapping", start_mapping, 4);
+ rb_define_method(cPsychEmitter, "end_mapping", end_mapping, 0);
+ rb_define_method(cPsychEmitter, "alias", alias, 1);
+ rb_define_method(cPsychEmitter, "canonical", canonical, 0);
+ rb_define_method(cPsychEmitter, "canonical=", set_canonical, 1);
+ rb_define_method(cPsychEmitter, "indentation", indentation, 0);
+ rb_define_method(cPsychEmitter, "indentation=", set_indentation, 1);
+ rb_define_method(cPsychEmitter, "line_width", line_width, 0);
+ rb_define_method(cPsychEmitter, "line_width=", set_line_width, 1);
+
+ id_io = rb_intern("io");
+ id_write = rb_intern("write");
+ id_line_width = rb_intern("line_width");
+ id_indentation = rb_intern("indentation");
+ id_canonical = rb_intern("canonical");
+}
diff --git a/ext/psych/psych_emitter.h b/ext/psych/psych_emitter.h
new file mode 100644
index 0000000000..4c1482a78b
--- /dev/null
+++ b/ext/psych/psych_emitter.h
@@ -0,0 +1,8 @@
+#ifndef PSYCH_EMITTER_H
+#define PSYCH_EMITTER_H
+
+#include <psych.h>
+
+void Init_psych_emitter(void);
+
+#endif
diff --git a/ext/psych/psych_parser.c b/ext/psych/psych_parser.c
new file mode 100644
index 0000000000..00a2207b58
--- /dev/null
+++ b/ext/psych/psych_parser.c
@@ -0,0 +1,575 @@
+#include <psych.h>
+
+VALUE cPsychParser;
+
+static ID id_read;
+static ID id_path;
+static ID id_empty;
+static ID id_start_stream;
+static ID id_end_stream;
+static ID id_start_document;
+static ID id_end_document;
+static ID id_alias;
+static ID id_scalar;
+static ID id_start_sequence;
+static ID id_end_sequence;
+static ID id_start_mapping;
+static ID id_end_mapping;
+static ID id_event_location;
+
+#define PSYCH_TRANSCODE(_str, _yaml_enc, _internal_enc) \
+ do { \
+ rb_enc_associate_index((_str), (_yaml_enc)); \
+ if(_internal_enc) \
+ (_str) = rb_str_export_to_enc((_str), (_internal_enc)); \
+ } while (0)
+
+static int io_reader(void * data, unsigned char *buf, size_t size, size_t *read)
+{
+ VALUE io = (VALUE)data;
+ VALUE string = rb_funcall(io, id_read, 1, SIZET2NUM(size));
+
+ *read = 0;
+
+ if(! NIL_P(string)) {
+ char * str = StringValuePtr(string);
+ size_t len = (size_t)RSTRING_LEN(string);
+
+ /* IO#read(size) is documented to return at most `size` bytes, but a
+ * misbehaving IO-like object may return more. Clamp the copy to the
+ * buffer libyaml gave us to avoid writing past its end, rounding down
+ * to a character boundary so a multibyte character is never split. */
+ if(len > size) {
+ rb_encoding * enc = rb_enc_get(string);
+ len = (size_t)(rb_enc_left_char_head(str, str + size, str + len, enc) - str);
+ }
+
+ *read = len;
+ memcpy(buf, str, len);
+ }
+
+ return 1;
+}
+
+static void dealloc(void * ptr)
+{
+ yaml_parser_t * parser;
+
+ parser = (yaml_parser_t *)ptr;
+ yaml_parser_delete(parser);
+ xfree(parser);
+}
+
+#if 0
+static size_t memsize(const void *ptr)
+{
+ const yaml_parser_t *parser = ptr;
+ /* TODO: calculate parser's size */
+ return 0;
+}
+#endif
+
+static const rb_data_type_t psych_parser_type = {
+ "Psych/parser",
+ {0, dealloc, 0,},
+ 0, 0,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
+ RUBY_TYPED_FREE_IMMEDIATELY,
+#endif
+};
+
+static VALUE allocate(VALUE klass)
+{
+ yaml_parser_t * parser;
+ VALUE obj = TypedData_Make_Struct(klass, yaml_parser_t, &psych_parser_type, parser);
+
+ yaml_parser_initialize(parser);
+
+ return obj;
+}
+
+static VALUE make_exception(yaml_parser_t * parser, VALUE path)
+{
+ if (parser->error == YAML_MEMORY_ERROR) {
+ return rb_eNoMemError;
+ } else {
+ size_t line, column;
+ VALUE ePsychSyntaxError;
+
+ line = parser->context_mark.line + 1;
+ column = parser->context_mark.column + 1;
+
+ ePsychSyntaxError = rb_const_get(mPsych, rb_intern("SyntaxError"));
+
+ return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6,
+ path,
+ SIZET2NUM(line),
+ SIZET2NUM(column),
+ SIZET2NUM(parser->problem_offset),
+ parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil,
+ parser->context ? rb_usascii_str_new2(parser->context) : Qnil);
+ }
+}
+
+static VALUE transcode_string(VALUE src, int * parser_encoding)
+{
+ int utf8 = rb_utf8_encindex();
+ int utf16le = rb_enc_find_index("UTF-16LE");
+ int utf16be = rb_enc_find_index("UTF-16BE");
+ int source_encoding = rb_enc_get_index(src);
+
+ if (source_encoding == utf8) {
+ *parser_encoding = YAML_UTF8_ENCODING;
+ return src;
+ }
+
+ if (source_encoding == utf16le) {
+ *parser_encoding = YAML_UTF16LE_ENCODING;
+ return src;
+ }
+
+ if (source_encoding == utf16be) {
+ *parser_encoding = YAML_UTF16BE_ENCODING;
+ return src;
+ }
+
+ src = rb_str_export_to_enc(src, rb_utf8_encoding());
+ RB_GC_GUARD(src);
+
+ *parser_encoding = YAML_UTF8_ENCODING;
+ return src;
+}
+
+static VALUE transcode_io(VALUE src, int * parser_encoding)
+{
+ VALUE io_external_encoding;
+ int io_external_enc_index;
+
+ io_external_encoding = rb_funcall(src, rb_intern("external_encoding"), 0);
+
+ /* if no encoding is returned, assume ascii8bit. */
+ if (NIL_P(io_external_encoding)) {
+ io_external_enc_index = rb_ascii8bit_encindex();
+ } else {
+ io_external_enc_index = rb_to_encoding_index(io_external_encoding);
+ }
+
+ /* Treat US-ASCII as utf_8 */
+ if (io_external_enc_index == rb_usascii_encindex()) {
+ *parser_encoding = YAML_UTF8_ENCODING;
+ return src;
+ }
+
+ if (io_external_enc_index == rb_utf8_encindex()) {
+ *parser_encoding = YAML_UTF8_ENCODING;
+ return src;
+ }
+
+ if (io_external_enc_index == rb_enc_find_index("UTF-16LE")) {
+ *parser_encoding = YAML_UTF16LE_ENCODING;
+ return src;
+ }
+
+ if (io_external_enc_index == rb_enc_find_index("UTF-16BE")) {
+ *parser_encoding = YAML_UTF16BE_ENCODING;
+ return src;
+ }
+
+ /* Just guess on ASCII-8BIT */
+ if (io_external_enc_index == rb_ascii8bit_encindex()) {
+ *parser_encoding = YAML_ANY_ENCODING;
+ return src;
+ }
+
+ /* If the external encoding is something we don't know how to handle,
+ * fall back to YAML_ANY_ENCODING. */
+ *parser_encoding = YAML_ANY_ENCODING;
+
+ return src;
+}
+
+static VALUE protected_start_stream(VALUE pointer)
+{
+ VALUE *args = (VALUE *)pointer;
+ return rb_funcall(args[0], id_start_stream, 1, args[1]);
+}
+
+static VALUE protected_start_document(VALUE pointer)
+{
+ VALUE *args = (VALUE *)pointer;
+ return rb_funcall3(args[0], id_start_document, 3, args + 1);
+}
+
+static VALUE protected_end_document(VALUE pointer)
+{
+ VALUE *args = (VALUE *)pointer;
+ return rb_funcall(args[0], id_end_document, 1, args[1]);
+}
+
+static VALUE protected_alias(VALUE pointer)
+{
+ VALUE *args = (VALUE *)pointer;
+ return rb_funcall(args[0], id_alias, 1, args[1]);
+}
+
+static VALUE protected_scalar(VALUE pointer)
+{
+ VALUE *args = (VALUE *)pointer;
+ return rb_funcall3(args[0], id_scalar, 6, args + 1);
+}
+
+static VALUE protected_start_sequence(VALUE pointer)
+{
+ VALUE *args = (VALUE *)pointer;
+ return rb_funcall3(args[0], id_start_sequence, 4, args + 1);
+}
+
+static VALUE protected_end_sequence(VALUE handler)
+{
+ return rb_funcall(handler, id_end_sequence, 0);
+}
+
+static VALUE protected_start_mapping(VALUE pointer)
+{
+ VALUE *args = (VALUE *)pointer;
+ return rb_funcall3(args[0], id_start_mapping, 4, args + 1);
+}
+
+static VALUE protected_end_mapping(VALUE handler)
+{
+ return rb_funcall(handler, id_end_mapping, 0);
+}
+
+static VALUE protected_empty(VALUE handler)
+{
+ return rb_funcall(handler, id_empty, 0);
+}
+
+static VALUE protected_end_stream(VALUE handler)
+{
+ return rb_funcall(handler, id_end_stream, 0);
+}
+
+static VALUE protected_event_location(VALUE pointer)
+{
+ VALUE *args = (VALUE *)pointer;
+ return rb_funcall3(args[0], id_event_location, 4, args + 1);
+}
+
+static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
+{
+ yaml_parser_t * parser;
+ yaml_event_t event;
+ int done = 0;
+ int state = 0;
+ int parser_encoding = YAML_ANY_ENCODING;
+ int encoding = rb_utf8_encindex();
+ rb_encoding * internal_enc = rb_default_internal_encoding();
+
+ TypedData_Get_Struct(self, yaml_parser_t, &psych_parser_type, parser);
+
+ yaml_parser_delete(parser);
+ yaml_parser_initialize(parser);
+
+ if (rb_respond_to(yaml, id_read)) {
+ yaml = transcode_io(yaml, &parser_encoding);
+ yaml_parser_set_encoding(parser, parser_encoding);
+ yaml_parser_set_input(parser, io_reader, (void *)yaml);
+ } else {
+ StringValue(yaml);
+ yaml = transcode_string(yaml, &parser_encoding);
+ yaml_parser_set_encoding(parser, parser_encoding);
+ yaml_parser_set_input_string(
+ parser,
+ (const unsigned char *)RSTRING_PTR(yaml),
+ (size_t)RSTRING_LEN(yaml)
+ );
+ }
+
+ while(!done) {
+ VALUE event_args[5];
+ VALUE start_line, start_column, end_line, end_column;
+
+ if(parser->error || !yaml_parser_parse(parser, &event)) {
+ VALUE exception;
+
+ exception = make_exception(parser, path);
+ yaml_parser_delete(parser);
+ yaml_parser_initialize(parser);
+
+ rb_exc_raise(exception);
+ }
+
+ start_line = SIZET2NUM(event.start_mark.line);
+ start_column = SIZET2NUM(event.start_mark.column);
+ end_line = SIZET2NUM(event.end_mark.line);
+ end_column = SIZET2NUM(event.end_mark.column);
+
+ event_args[0] = handler;
+ event_args[1] = start_line;
+ event_args[2] = start_column;
+ event_args[3] = end_line;
+ event_args[4] = end_column;
+ rb_protect(protected_event_location, (VALUE)event_args, &state);
+
+ switch(event.type) {
+ case YAML_STREAM_START_EVENT:
+ {
+ VALUE args[2];
+
+ args[0] = handler;
+ args[1] = INT2NUM(event.data.stream_start.encoding);
+ rb_protect(protected_start_stream, (VALUE)args, &state);
+ }
+ break;
+ case YAML_DOCUMENT_START_EVENT:
+ {
+ VALUE args[4];
+ /* Get a list of tag directives (if any) */
+ VALUE tag_directives = rb_ary_new();
+ /* Grab the document version */
+ VALUE version = event.data.document_start.version_directive ?
+ rb_ary_new3(
+ (long)2,
+ INT2NUM(event.data.document_start.version_directive->major),
+ INT2NUM(event.data.document_start.version_directive->minor)
+ ) : rb_ary_new();
+
+ if(event.data.document_start.tag_directives.start) {
+ yaml_tag_directive_t *start =
+ event.data.document_start.tag_directives.start;
+ yaml_tag_directive_t *end =
+ event.data.document_start.tag_directives.end;
+ for(; start != end; start++) {
+ VALUE handle = Qnil;
+ VALUE prefix = Qnil;
+ if(start->handle) {
+ handle = rb_str_new2((const char *)start->handle);
+ PSYCH_TRANSCODE(handle, encoding, internal_enc);
+ }
+
+ if(start->prefix) {
+ prefix = rb_str_new2((const char *)start->prefix);
+ PSYCH_TRANSCODE(prefix, encoding, internal_enc);
+ }
+
+ rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix));
+ }
+ }
+ args[0] = handler;
+ args[1] = version;
+ args[2] = tag_directives;
+ args[3] = event.data.document_start.implicit == 1 ? Qtrue : Qfalse;
+ rb_protect(protected_start_document, (VALUE)args, &state);
+ }
+ break;
+ case YAML_DOCUMENT_END_EVENT:
+ {
+ VALUE args[2];
+
+ args[0] = handler;
+ args[1] = event.data.document_end.implicit == 1 ? Qtrue : Qfalse;
+ rb_protect(protected_end_document, (VALUE)args, &state);
+ }
+ break;
+ case YAML_ALIAS_EVENT:
+ {
+ VALUE args[2];
+ VALUE alias = Qnil;
+ if(event.data.alias.anchor) {
+ alias = rb_str_new2((const char *)event.data.alias.anchor);
+ PSYCH_TRANSCODE(alias, encoding, internal_enc);
+ }
+
+ args[0] = handler;
+ args[1] = alias;
+ rb_protect(protected_alias, (VALUE)args, &state);
+ }
+ break;
+ case YAML_SCALAR_EVENT:
+ {
+ VALUE args[7];
+ VALUE anchor = Qnil;
+ VALUE tag = Qnil;
+ VALUE plain_implicit, quoted_implicit, style;
+ VALUE val = rb_str_new(
+ (const char *)event.data.scalar.value,
+ (long)event.data.scalar.length
+ );
+
+ PSYCH_TRANSCODE(val, encoding, internal_enc);
+
+ if(event.data.scalar.anchor) {
+ anchor = rb_str_new2((const char *)event.data.scalar.anchor);
+ PSYCH_TRANSCODE(anchor, encoding, internal_enc);
+ }
+
+ if(event.data.scalar.tag) {
+ tag = rb_str_new2((const char *)event.data.scalar.tag);
+ PSYCH_TRANSCODE(tag, encoding, internal_enc);
+ }
+
+ plain_implicit =
+ event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue;
+
+ quoted_implicit =
+ event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue;
+
+ style = INT2NUM(event.data.scalar.style);
+
+ args[0] = handler;
+ args[1] = val;
+ args[2] = anchor;
+ args[3] = tag;
+ args[4] = plain_implicit;
+ args[5] = quoted_implicit;
+ args[6] = style;
+ rb_protect(protected_scalar, (VALUE)args, &state);
+ }
+ break;
+ case YAML_SEQUENCE_START_EVENT:
+ {
+ VALUE args[5];
+ VALUE anchor = Qnil;
+ VALUE tag = Qnil;
+ VALUE implicit, style;
+ if(event.data.sequence_start.anchor) {
+ anchor = rb_str_new2((const char *)event.data.sequence_start.anchor);
+ PSYCH_TRANSCODE(anchor, encoding, internal_enc);
+ }
+
+ tag = Qnil;
+ if(event.data.sequence_start.tag) {
+ tag = rb_str_new2((const char *)event.data.sequence_start.tag);
+ PSYCH_TRANSCODE(tag, encoding, internal_enc);
+ }
+
+ implicit =
+ event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue;
+
+ style = INT2NUM(event.data.sequence_start.style);
+
+ args[0] = handler;
+ args[1] = anchor;
+ args[2] = tag;
+ args[3] = implicit;
+ args[4] = style;
+
+ rb_protect(protected_start_sequence, (VALUE)args, &state);
+ }
+ break;
+ case YAML_SEQUENCE_END_EVENT:
+ rb_protect(protected_end_sequence, handler, &state);
+ break;
+ case YAML_MAPPING_START_EVENT:
+ {
+ VALUE args[5];
+ VALUE anchor = Qnil;
+ VALUE tag = Qnil;
+ VALUE implicit, style;
+ if(event.data.mapping_start.anchor) {
+ anchor = rb_str_new2((const char *)event.data.mapping_start.anchor);
+ PSYCH_TRANSCODE(anchor, encoding, internal_enc);
+ }
+
+ if(event.data.mapping_start.tag) {
+ tag = rb_str_new2((const char *)event.data.mapping_start.tag);
+ PSYCH_TRANSCODE(tag, encoding, internal_enc);
+ }
+
+ implicit =
+ event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue;
+
+ style = INT2NUM(event.data.mapping_start.style);
+
+ args[0] = handler;
+ args[1] = anchor;
+ args[2] = tag;
+ args[3] = implicit;
+ args[4] = style;
+
+ rb_protect(protected_start_mapping, (VALUE)args, &state);
+ }
+ break;
+ case YAML_MAPPING_END_EVENT:
+ rb_protect(protected_end_mapping, handler, &state);
+ break;
+ case YAML_NO_EVENT:
+ rb_protect(protected_empty, handler, &state);
+ break;
+ case YAML_STREAM_END_EVENT:
+ rb_protect(protected_end_stream, handler, &state);
+ done = 1;
+ break;
+ }
+ yaml_event_delete(&event);
+ if (state) rb_jump_tag(state);
+ }
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * parser.mark # => #<Psych::Parser::Mark>
+ *
+ * Returns a Psych::Parser::Mark object that contains line, column, and index
+ * information.
+ */
+static VALUE mark(VALUE self)
+{
+ VALUE mark_klass;
+ VALUE args[3];
+ yaml_parser_t * parser;
+
+ TypedData_Get_Struct(self, yaml_parser_t, &psych_parser_type, parser);
+ mark_klass = rb_const_get_at(cPsychParser, rb_intern("Mark"));
+ args[0] = SIZET2NUM(parser->mark.index);
+ args[1] = SIZET2NUM(parser->mark.line);
+ args[2] = SIZET2NUM(parser->mark.column);
+
+ return rb_class_new_instance(3, args, mark_klass);
+}
+
+void Init_psych_parser(void)
+{
+#undef rb_intern
+#if 0
+ mPsych = rb_define_module("Psych");
+#endif
+
+ cPsychParser = rb_define_class_under(mPsych, "Parser", rb_cObject);
+ rb_define_alloc_func(cPsychParser, allocate);
+
+ /* Any encoding: Let the parser choose the encoding */
+ rb_define_const(cPsychParser, "ANY", INT2NUM(YAML_ANY_ENCODING));
+
+ /* UTF-8 Encoding */
+ rb_define_const(cPsychParser, "UTF8", INT2NUM(YAML_UTF8_ENCODING));
+
+ /* UTF-16-LE Encoding with BOM */
+ rb_define_const(cPsychParser, "UTF16LE", INT2NUM(YAML_UTF16LE_ENCODING));
+
+ /* UTF-16-BE Encoding with BOM */
+ rb_define_const(cPsychParser, "UTF16BE", INT2NUM(YAML_UTF16BE_ENCODING));
+
+ rb_require("psych/syntax_error");
+
+ rb_define_private_method(cPsychParser, "_native_parse", parse, 3);
+ rb_define_method(cPsychParser, "mark", mark, 0);
+
+ id_read = rb_intern("read");
+ id_path = rb_intern("path");
+ id_empty = rb_intern("empty");
+ id_start_stream = rb_intern("start_stream");
+ id_end_stream = rb_intern("end_stream");
+ id_start_document = rb_intern("start_document");
+ id_end_document = rb_intern("end_document");
+ id_alias = rb_intern("alias");
+ id_scalar = rb_intern("scalar");
+ id_start_sequence = rb_intern("start_sequence");
+ id_end_sequence = rb_intern("end_sequence");
+ id_start_mapping = rb_intern("start_mapping");
+ id_end_mapping = rb_intern("end_mapping");
+ id_event_location = rb_intern("event_location");
+}
diff --git a/ext/psych/psych_parser.h b/ext/psych/psych_parser.h
new file mode 100644
index 0000000000..beb3dd0709
--- /dev/null
+++ b/ext/psych/psych_parser.h
@@ -0,0 +1,6 @@
+#ifndef PSYCH_PARSER_H
+#define PSYCH_PARSER_H
+
+void Init_psych_parser(void);
+
+#endif
diff --git a/ext/psych/psych_to_ruby.c b/ext/psych/psych_to_ruby.c
new file mode 100644
index 0000000000..3ab0138b52
--- /dev/null
+++ b/ext/psych/psych_to_ruby.c
@@ -0,0 +1,42 @@
+#include <psych.h>
+
+VALUE cPsychVisitorsToRuby;
+
+/* call-seq: vis.build_exception(klass, message)
+ *
+ * Create an exception with class +klass+ and +message+
+ */
+static VALUE build_exception(VALUE self, VALUE klass, VALUE mesg)
+{
+ VALUE e = rb_obj_alloc(klass);
+
+#ifdef TRUFFLERUBY
+ rb_exc_set_message(e, mesg);
+#else
+ rb_iv_set(e, "mesg", mesg);
+#endif
+
+ return e;
+}
+
+/* call-seq: vis.path2class(path)
+ *
+ * Convert +path+ string to a class
+ */
+static VALUE path2class(VALUE self, VALUE path)
+{
+ return rb_path_to_class(path);
+}
+
+void Init_psych_to_ruby(void)
+{
+ VALUE psych = rb_define_module("Psych");
+ VALUE class_loader = rb_define_class_under(psych, "ClassLoader", rb_cObject);
+
+ VALUE visitors = rb_define_module_under(psych, "Visitors");
+ VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject);
+ cPsychVisitorsToRuby = rb_define_class_under(visitors, "ToRuby", visitor);
+
+ rb_define_private_method(cPsychVisitorsToRuby, "build_exception", build_exception, 2);
+ rb_define_private_method(class_loader, "path2class", path2class, 1);
+}
diff --git a/ext/psych/psych_to_ruby.h b/ext/psych/psych_to_ruby.h
new file mode 100644
index 0000000000..7b8e757a45
--- /dev/null
+++ b/ext/psych/psych_to_ruby.h
@@ -0,0 +1,8 @@
+#ifndef PSYCH_TO_RUBY_H
+#define PSYCH_TO_RUBY_H
+
+#include <psych.h>
+
+void Init_psych_to_ruby(void);
+
+#endif
diff --git a/ext/psych/psych_yaml_tree.c b/ext/psych/psych_yaml_tree.c
new file mode 100644
index 0000000000..bbd93f874d
--- /dev/null
+++ b/ext/psych/psych_yaml_tree.c
@@ -0,0 +1,11 @@
+#include <psych.h>
+
+VALUE cPsychVisitorsYamlTree;
+
+void Init_psych_yaml_tree(void)
+{
+ VALUE psych = rb_define_module("Psych");
+ VALUE visitors = rb_define_module_under(psych, "Visitors");
+ VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject);
+ cPsychVisitorsYamlTree = rb_define_class_under(visitors, "YAMLTree", visitor);
+}
diff --git a/ext/psych/psych_yaml_tree.h b/ext/psych/psych_yaml_tree.h
new file mode 100644
index 0000000000..4628a69d71
--- /dev/null
+++ b/ext/psych/psych_yaml_tree.h
@@ -0,0 +1,8 @@
+#ifndef PSYCH_YAML_TREE_H
+#define PSYCH_YAML_TREE_H
+
+#include <psych.h>
+
+void Init_psych_yaml_tree(void);
+
+#endif
diff --git a/ext/pty/.cvsignore b/ext/pty/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/pty/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/pty/README b/ext/pty/README
deleted file mode 100644
index 42c7d4f891..0000000000
--- a/ext/pty/README
+++ /dev/null
@@ -1,65 +0,0 @@
-pty extension version 0.3 by A.ito
-
-1. Introduction
-
-This extension module adds ruby a functionality to execute an
-arbitrary command through pseudo tty (pty).
-
-2. Install
-
-Follow the instruction below.
-
-(1) Execute
-
- ruby extconf.rb
-
- then Makefile is generated.
-
-(3) Do make; make install.
-
-3. What you can do
-
-This extension module defines a module named PTY, which contains
-following module fungtions:
-
- getpty(command)
- spawn(command)
-
- This function reserves a pty, executes command over the pty
- and returns an array. The return value is an array with three
- elements. The first element in the array is for reading and the
- second for writing. The third element is the process ID of the
- child process. If this function is called with an iterator block,
- the array is passed to the block as block parameters, and the
- function itself returns nil.
-
- When the child process is suspended or finished, an exception is
- raised. If this function is called with an iterator block,
- exception is raised only within the block. Child process
- monitor is terminated on block exit.
-
- protect_signal
- reset_signal
-
- These functions are obsolete in this version of pty.
-
-4. License
-
-(C) Copyright 1998 by Akinori Ito.
-
-This software may be redistributed freely for this purpose, in full
-or in part, provided that this entire copyright notice is included
-on any copies of this software and applications and derivations thereof.
-
-This software is provided on an "as is" basis, without warranty of any
-kind, either expressed or implied, as to any matter including, but not
-limited to warranty of fitness of purpose, or merchantability, or
-results obtained from use of this software.
-
-5. Bug report
-
-Please feel free to send E-mail to
-
- aito@ei5sun.yz.yamagata-u.ac.jp
-
-for any bug report, opinion, contribution, etc.
diff --git a/ext/pty/README.expect b/ext/pty/README.expect
deleted file mode 100644
index fddbb6fdad..0000000000
--- a/ext/pty/README.expect
+++ /dev/null
@@ -1,22 +0,0 @@
- README for expect
- by A. Ito, 28 October, 1998
-
- Expect library adds IO class a method called expect(), which
-does similar act to tcl's expect extension.
-
-The usage of the method is:
-
- IO#expect(pattern,timeout=9999999)
-
-where `pattern' is an instance of String or Regexp and `timeout'
-is Fixnum, which can be omitted.
- When the method is called without block, it waits until the
-input which matches the pattern is obtained from the IO or the time
-specified as the timeout passes. When the pattern is obtained from the
-IO, the method returns an array. The first element of the array is the
-entire string obtained from the IO until the pattern matches. The
-following elements indicates the specific pattern which matched to the
-anchor in the regular expression. If the method ends because of
-timeout, it returns nil.
- When the method is called with block, the array is passed as
-the block parameter.
diff --git a/ext/pty/README.expect.ja b/ext/pty/README.expect.ja
deleted file mode 100644
index db84695ee5..0000000000
--- a/ext/pty/README.expect.ja
+++ /dev/null
@@ -1,21 +0,0 @@
- README for expect
- by A. Ito, 28 October, 1998
-
- Expect¥é¥¤¥Ö¥é¥ê¤Ï¡¤tcl ¤Î expect ¥Ñ¥Ã¥±¡¼¥¸¤È»÷¤¿¤è¤¦¤Êµ¡Ç½¤ò
-IO¥¯¥é¥¹¤ËÄɲä·¤Þ¤¹¡¥
-
- Äɲ䵤ì¤ë¥á¥½¥Ã¥É¤Î»È¤¤Êý¤Ï¼¡¤ÎÄ̤ê¤Ç¤¹¡¥
-
- IO#expect(pattern,timeout=9999999)
-
-pattern ¤Ï String ¤« Regexp ¤Î¥¤¥ó¥¹¥¿¥ó¥¹¡¤timeout ¤Ï Fixnum
-¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤Ç¤¹¡¥timeout ¤Ï¾Êά¤Ç¤­¤Þ¤¹¡¥
- ¤³¤Î¥á¥½¥Ã¥É¤¬¥Ö¥í¥Ã¥¯¤Ê¤·¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¡¤¤Þ¤º¥ì¥·¡¼¥Ð¤Ç¤¢¤ë
-IO¥ª¥Ö¥¸¥§¥¯¥È¤«¤é pattern ¤Ë¥Þ¥Ã¥Á¤¹¤ë¥Ñ¥¿¡¼¥ó¤¬ÆÉ¤ß¤³¤Þ¤ì¤ë
-¤Þ¤ÇÂÔ¤Á¤Þ¤¹¡¥¥Ñ¥¿¡¼¥ó¤¬ÆÀ¤é¤ì¤¿¤é¡¤¤½¤Î¥Ñ¥¿¡¼¥ó¤Ë´Ø¤¹¤ëÇÛÎó¤ò
-ÊÖ¤·¤Þ¤¹¡¥ÇÛÎó¤ÎºÇ½é¤ÎÍ×ÁǤϡ¤pattern ¤Ë¥Þ¥Ã¥Á¤¹¤ë¤Þ¤Ç¤ËÆÉ¤ß¤³
-¤Þ¤ì¤¿ÆâÍÆ¤Îʸ»úÎó¤Ç¤¹¡¥2ÈÖÌܰʹߤÎÍ×ÁǤϡ¤pattern ¤ÎÀµµ¬É½¸½
-¤ÎÃæ¤Ë¥¢¥ó¥«¡¼¤¬¤¢¤Ã¤¿¾ì¹ç¤Ë¡¤¤½¤Î¥¢¥ó¥«¡¼¤Ë¥Þ¥Ã¥Á¤¹¤ëÉôʬ¤Ç¤¹¡¥
-¤â¤·¥¿¥¤¥à¥¢¥¦¥È¤¬µ¯¤­¤¿¾ì¹ç¤Ï¡¤¤³¤Î¥á¥½¥Ã¥É¤Ïnil¤òÊÖ¤·¤Þ¤¹¡¥
- ¤³¤Î¥á¥½¥Ã¥É¤¬¥Ö¥í¥Ã¥¯ÉÕ¤­¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¤Ë¤Ï¡¤¥Þ¥Ã¥Á¤·¤¿Í×ÁǤÎ
-ÇÛÎ󤬥֥í¥Ã¥¯°ú¿ô¤È¤·¤ÆÅϤµ¤ì¡¤¥Ö¥í¥Ã¥¯¤¬É¾²Á¤µ¤ì¤Þ¤¹¡¥
diff --git a/ext/pty/README.ja b/ext/pty/README.ja
deleted file mode 100644
index 5ae4fb06a0..0000000000
--- a/ext/pty/README.ja
+++ /dev/null
@@ -1,89 +0,0 @@
-pty ³ÈÄ¥¥â¥¸¥å¡¼¥ë version 0.3 by A.ito
-
-1. ¤Ï¤¸¤á¤Ë
-
-¤³¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ï¡¤²¾ÁÛtty (pty) ¤òÄ̤·¤ÆÅ¬Åö¤Ê¥³¥Þ¥ó¥É¤ò
-¼Â¹Ô¤¹¤ëµ¡Ç½¤ò ruby ¤ËÄ󶡤·¤Þ¤¹¡¥
-
-2. ¥¤¥ó¥¹¥È¡¼¥ë
-
-¼¡¤Î¤è¤¦¤Ë¤·¤Æ¥¤¥ó¥¹¥È¡¼¥ë¤·¤Æ¤¯¤À¤µ¤¤¡¥
-
-(1) ruby extconf.rb
-
- ¤ò¼Â¹Ô¤¹¤ë¤È Makefile ¤¬À¸À®¤µ¤ì¤Þ¤¹¡¥
-
-(2) make; make install ¤ò¼Â¹Ô¤·¤Æ¤¯¤À¤µ¤¤¡¥
-
-3. ²¿¤¬¤Ç¤­¤ë¤«
-
-¤³¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ï¡¤PTY ¤È¤¤¤¦¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¤Þ¤¹¡¥¤½¤ÎÃæ
-¤Ë¤Ï¡¤¼¡¤Î¤è¤¦¤Ê¥â¥¸¥å¡¼¥ë´Ø¿ô¤¬´Þ¤Þ¤ì¤Æ¤¤¤Þ¤¹¡¥
-
- getpty(command)
- spawn(command)
-
- ¤³¤Î´Ø¿ô¤Ï¡¤²¾ÁÛtty¤ò³ÎÊݤ·¡¤»ØÄꤵ¤ì¤¿¥³¥Þ¥ó¥É¤ò¤½¤Î²¾ÁÛtty
- ¤Î¸þ¤³¤¦¤Ç¼Â¹Ô¤·¡¤ÇÛÎó¤òÊÖ¤·¤Þ¤¹¡¥Ìá¤êÃͤÏ3¤Ä¤ÎÍ×ÁǤ«¤é¤Ê¤ë
- ÇÛÎó¤Ç¤¹¡¥ºÇ½é¤ÎÍ×ÁǤϲ¾ÁÛtty¤«¤éÆÉ¤ß½Ð¤¹¤¿¤á¤ÎIO¥ª¥Ö¥¸¥§¥¯¥È¡¤
- 2ÈÖÌܤϽñ¤­¤³¤à¤¿¤á¤ÎIO¥ª¥Ö¥¸¥§¥¯¥È¡¤3ÈÖÌÜ¤Ï»Ò¥×¥í¥»¥¹¤Î¥×¥í
- ¥»¥¹ID¤Ç¤¹¡¥¤³¤Î´Ø¿ô¤¬¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ð¤ì¤¿¾ì¹ç¡¤¤³¤ì¤é¤Î
- Í×ÁǤϥ֥í¥Ã¥¯¥Ñ¥é¥á¡¼¥¿¤È¤·¤ÆÅϤµ¤ì¡¤´Ø¿ô¼«ÂΤÏnil¤òÊÖ¤·¤Þ¤¹¡¥
-
- ¤³¤Î´Ø¿ô¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¥µ¥Ö¥×¥í¥»¥¹¤¬Æ°¤¤¤Æ¤¤¤ë´Ö¡¤»Ò¥×¥í¥»¥¹
- ¤Î¾õÂÖ¤ò´Æ»ë¤¹¤ë¤¿¤á¤Ë SIGCHLD ¥·¥°¥Ê¥ë¤òÊ᪤·¤Þ¤¹¡¥»Ò¥×¥í¥»¥¹
- ¤¬½ªÎ»¤·¤¿¤êÄä»ß¤·¤¿¾ì¹ç¤Ë¤Ï¡¤Îã³°¤¬È¯À¸¤·¤Þ¤¹¡¥¤³¤Î´Ö¡¤¤¹¤Ù¤Æ¤Î
- SIGCHLD ¤¬ PTY ¥â¥¸¥å¡¼¥ë¤Î¥·¥°¥Ê¥ë¥Ï¥ó¥É¥é¤ËÊ᪤µ¤ì¤ë¤Î¤Ç¡¤
- ¥µ¥Ö¥×¥í¥»¥¹¤òÀ¸À®¤¹¤ë¾¤Î´Ø¿ô(system() ¤È¤« IO.popen()¤Ê¤É)¤ò
- »È¤¦¤È¡¤Í½´ü¤·¤Ê¤¤Îã³°¤¬È¯À¸¤¹¤ë¤³¤È¤¬¤¢¤ê¤Þ¤¹¡¥¤³¤ì¤òËɤ°¤¿¤á
- ¤Ë¤Ï¡¤²¼µ­¤Îprotect_signal()¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
-
- ¤³¤Î´Ø¿ô¤¬¥Ö¥í¥Ã¥¯¥Ñ¥é¥á¡¼¥¿ÉÕ¤­¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¤Ë¤Ï¡¤¤½¤Î¥Ö¥í¥Ã¥¯
- ¤ÎÃæ¤Ç¤Î¤ß SIGCHLD ¤¬Ê᪤µ¤ì¤Þ¤¹¡¥¤·¤¿¤¬¤Ã¤Æ¡¤¥Ö¥í¥Ã¥¯¥Ñ¥é¥á¡¼¥¿
- ¤È¤·¤ÆÅϤµ¤ì¤¿IO¥ª¥Ö¥¸¥§¥¯¥È¤ò¡¤¥Ö¥í¥Ã¥¯¤Î³°¤Ë»ý¤Á½Ð¤·¤Æ»È¤¦¤Î
- ¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥
-
-
- protect_signal
-
- ¤³¤Î´Ø¿ô¤Ï¥¤¥Æ¥ì¡¼¥¿¤Ç¤¹¡¥¤³¤³¤Ç»ØÄꤵ¤ì¤¿¥Ö¥í¥Ã¥¯¤ÎÃæ¤Ç¤Ï¡¤
- »Ò¥×¥í¥»¥¹¤¬½ªÎ»¤·¤Æ¤âÎã³°¤òȯÀ¸¤·¤Þ¤»¤ó¡¥¤³¤Î´Ø¿ô¤ò»È¤¦¤³¤È¤Ç¡¤
- PTY¤Î»Ò¥×¥í¥»¥¹¤¬Æ°¤¤¤Æ¤¤¤ë´Ö¤Ç¤â¡¤system()¤ä IO.popen()¤Ê¤É¤Î
- ´Ø¿ô¤ò°ÂÁ´¤Ë»È¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥Î㤨¤Ð¡¤
-
- PTY.spawn("command_foo") do |r,w|
- ...
- ...
- PTY.protect_signal do
- system "some other commands"
- end
- ...
- end
-
- ¤³¤Î¤è¤¦¤Êµ­½Ò¤Ë¤è¤ê¡¤"some other commands" ¤¬½ªÎ»¤·¤¿¤È¤­¤Ë
- Îã³°¤¬È¯À¸¤¹¤ë¤Î¤òËɤ²¤Þ¤¹¡¥
-
- reset_signal
-
- PTY ¤Î»Ò¥×¥í¥»¥¹¤¬Æ°¤¤¤Æ¤¤¤Æ¤â¡¤¤½¤Î¥×¥í¥»¥¹¤Î½ªÎ»»þ¤ËÎã³°¤¬È¯À¸
- ¤·¤Ê¤¤¤è¤¦¤Ë¤·¤Þ¤¹¡¥
-
-4. ÍøÍѤˤĤ¤¤Æ
-
-°ËÆ£¾´Â§¤¬Ãøºî¸¢¤òÊÝÍ­¤·¤Þ¤¹¡¥
-
-¥½¡¼¥¹¥×¥í¥°¥é¥à¤Þ¤¿¤Ï¥É¥­¥å¥á¥ó¥È¤Ë¸µ¤ÎÃøºî¸¢É½¼¨¤¬²þÊѤµ¤ì¤º¤Ë
-ɽ¼¨¤µ¤ì¤Æ¤¤¤ë¾ì¹ç¤Ë¸Â¤ê¡¤Ã¯¤Ç¤â¡¤¤³¤Î¥½¥Õ¥È¥¦¥§¥¢¤ò̵½þ¤«¤ÄÃøºî
-¸¢¼Ô¤Ë̵ÃǤÇÍøÍÑ¡¦ÇÛÉÛ¡¦²þÊѤǤ­¤Þ¤¹¡¥ÍøÍÑÌÜŪ¤Ï¸ÂÄꤵ¤ì¤Æ¤¤¤Þ¤»
-¤ó¡¥
-
-¤³¤Î¥×¥í¥°¥é¥à¤ÎÍøÍÑ¡¦ÇÛÉÛ¤½¤Î¾¤³¤Î¥×¥í¥°¥é¥à¤Ë´Ø·¸¤¹¤ë¹Ô°Ù¤Ë¤è
-¤Ã¤ÆÀ¸¤¸¤¿¤¤¤«¤Ê¤ë»³²¤ËÂФ·¤Æ¤â¡¤ºî¼Ô¤Ï°ìÀÚÀÕǤ¤òÉ餤¤Þ¤»¤ó¡¥
-
-5. ¥Ð¥°Êó¹ðÅù
-
-¥Ð¥°¥ì¥Ý¡¼¥È¤Ï´¿·Þ¤·¤Þ¤¹¡¥
-
- aito@ei5sun.yz.yamagata-u.ac.jp
-
-¤Þ¤ÇÅŻҥ᡼¥ë¤Ç¥Ð¥°¥ì¥Ý¡¼¥È¤ò¤ªÁ÷¤ê¤¯¤À¤µ¤¤¡¥
diff --git a/ext/pty/depend b/ext/pty/depend
index 888be6c301..8fa018d084 100644
--- a/ext/pty/depend
+++ b/ext/pty/depend
@@ -1 +1,188 @@
-pty.o: pty.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
+# AUTOGENERATED DEPENDENCIES START
+pty.o: $(RUBY_EXTCONF_H)
+pty.o: $(arch_hdrdir)/ruby/config.h
+pty.o: $(hdrdir)/ruby/assert.h
+pty.o: $(hdrdir)/ruby/backward.h
+pty.o: $(hdrdir)/ruby/backward/2/assume.h
+pty.o: $(hdrdir)/ruby/backward/2/attributes.h
+pty.o: $(hdrdir)/ruby/backward/2/bool.h
+pty.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+pty.o: $(hdrdir)/ruby/backward/2/inttypes.h
+pty.o: $(hdrdir)/ruby/backward/2/limits.h
+pty.o: $(hdrdir)/ruby/backward/2/long_long.h
+pty.o: $(hdrdir)/ruby/backward/2/stdalign.h
+pty.o: $(hdrdir)/ruby/backward/2/stdarg.h
+pty.o: $(hdrdir)/ruby/defines.h
+pty.o: $(hdrdir)/ruby/encoding.h
+pty.o: $(hdrdir)/ruby/intern.h
+pty.o: $(hdrdir)/ruby/internal/abi.h
+pty.o: $(hdrdir)/ruby/internal/anyargs.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+pty.o: $(hdrdir)/ruby/internal/assume.h
+pty.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+pty.o: $(hdrdir)/ruby/internal/attr/artificial.h
+pty.o: $(hdrdir)/ruby/internal/attr/cold.h
+pty.o: $(hdrdir)/ruby/internal/attr/const.h
+pty.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+pty.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+pty.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+pty.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+pty.o: $(hdrdir)/ruby/internal/attr/error.h
+pty.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+pty.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+pty.o: $(hdrdir)/ruby/internal/attr/format.h
+pty.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+pty.o: $(hdrdir)/ruby/internal/attr/noalias.h
+pty.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+pty.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+pty.o: $(hdrdir)/ruby/internal/attr/noinline.h
+pty.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+pty.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+pty.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+pty.o: $(hdrdir)/ruby/internal/attr/pure.h
+pty.o: $(hdrdir)/ruby/internal/attr/restrict.h
+pty.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+pty.o: $(hdrdir)/ruby/internal/attr/warning.h
+pty.o: $(hdrdir)/ruby/internal/attr/weakref.h
+pty.o: $(hdrdir)/ruby/internal/cast.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+pty.o: $(hdrdir)/ruby/internal/compiler_since.h
+pty.o: $(hdrdir)/ruby/internal/config.h
+pty.o: $(hdrdir)/ruby/internal/constant_p.h
+pty.o: $(hdrdir)/ruby/internal/core.h
+pty.o: $(hdrdir)/ruby/internal/core/rarray.h
+pty.o: $(hdrdir)/ruby/internal/core/rbasic.h
+pty.o: $(hdrdir)/ruby/internal/core/rbignum.h
+pty.o: $(hdrdir)/ruby/internal/core/rclass.h
+pty.o: $(hdrdir)/ruby/internal/core/rdata.h
+pty.o: $(hdrdir)/ruby/internal/core/rfile.h
+pty.o: $(hdrdir)/ruby/internal/core/rhash.h
+pty.o: $(hdrdir)/ruby/internal/core/robject.h
+pty.o: $(hdrdir)/ruby/internal/core/rregexp.h
+pty.o: $(hdrdir)/ruby/internal/core/rstring.h
+pty.o: $(hdrdir)/ruby/internal/core/rstruct.h
+pty.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+pty.o: $(hdrdir)/ruby/internal/ctype.h
+pty.o: $(hdrdir)/ruby/internal/dllexport.h
+pty.o: $(hdrdir)/ruby/internal/dosish.h
+pty.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+pty.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+pty.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+pty.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+pty.o: $(hdrdir)/ruby/internal/encoding/re.h
+pty.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+pty.o: $(hdrdir)/ruby/internal/encoding/string.h
+pty.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+pty.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+pty.o: $(hdrdir)/ruby/internal/error.h
+pty.o: $(hdrdir)/ruby/internal/eval.h
+pty.o: $(hdrdir)/ruby/internal/event.h
+pty.o: $(hdrdir)/ruby/internal/fl_type.h
+pty.o: $(hdrdir)/ruby/internal/gc.h
+pty.o: $(hdrdir)/ruby/internal/glob.h
+pty.o: $(hdrdir)/ruby/internal/globals.h
+pty.o: $(hdrdir)/ruby/internal/has/attribute.h
+pty.o: $(hdrdir)/ruby/internal/has/builtin.h
+pty.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+pty.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+pty.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+pty.o: $(hdrdir)/ruby/internal/has/extension.h
+pty.o: $(hdrdir)/ruby/internal/has/feature.h
+pty.o: $(hdrdir)/ruby/internal/has/warning.h
+pty.o: $(hdrdir)/ruby/internal/intern/array.h
+pty.o: $(hdrdir)/ruby/internal/intern/bignum.h
+pty.o: $(hdrdir)/ruby/internal/intern/class.h
+pty.o: $(hdrdir)/ruby/internal/intern/compar.h
+pty.o: $(hdrdir)/ruby/internal/intern/complex.h
+pty.o: $(hdrdir)/ruby/internal/intern/cont.h
+pty.o: $(hdrdir)/ruby/internal/intern/dir.h
+pty.o: $(hdrdir)/ruby/internal/intern/enum.h
+pty.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+pty.o: $(hdrdir)/ruby/internal/intern/error.h
+pty.o: $(hdrdir)/ruby/internal/intern/eval.h
+pty.o: $(hdrdir)/ruby/internal/intern/file.h
+pty.o: $(hdrdir)/ruby/internal/intern/hash.h
+pty.o: $(hdrdir)/ruby/internal/intern/io.h
+pty.o: $(hdrdir)/ruby/internal/intern/load.h
+pty.o: $(hdrdir)/ruby/internal/intern/marshal.h
+pty.o: $(hdrdir)/ruby/internal/intern/numeric.h
+pty.o: $(hdrdir)/ruby/internal/intern/object.h
+pty.o: $(hdrdir)/ruby/internal/intern/parse.h
+pty.o: $(hdrdir)/ruby/internal/intern/proc.h
+pty.o: $(hdrdir)/ruby/internal/intern/process.h
+pty.o: $(hdrdir)/ruby/internal/intern/random.h
+pty.o: $(hdrdir)/ruby/internal/intern/range.h
+pty.o: $(hdrdir)/ruby/internal/intern/rational.h
+pty.o: $(hdrdir)/ruby/internal/intern/re.h
+pty.o: $(hdrdir)/ruby/internal/intern/ruby.h
+pty.o: $(hdrdir)/ruby/internal/intern/select.h
+pty.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+pty.o: $(hdrdir)/ruby/internal/intern/set.h
+pty.o: $(hdrdir)/ruby/internal/intern/signal.h
+pty.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+pty.o: $(hdrdir)/ruby/internal/intern/string.h
+pty.o: $(hdrdir)/ruby/internal/intern/struct.h
+pty.o: $(hdrdir)/ruby/internal/intern/thread.h
+pty.o: $(hdrdir)/ruby/internal/intern/time.h
+pty.o: $(hdrdir)/ruby/internal/intern/variable.h
+pty.o: $(hdrdir)/ruby/internal/intern/vm.h
+pty.o: $(hdrdir)/ruby/internal/interpreter.h
+pty.o: $(hdrdir)/ruby/internal/iterator.h
+pty.o: $(hdrdir)/ruby/internal/memory.h
+pty.o: $(hdrdir)/ruby/internal/method.h
+pty.o: $(hdrdir)/ruby/internal/module.h
+pty.o: $(hdrdir)/ruby/internal/newobj.h
+pty.o: $(hdrdir)/ruby/internal/scan_args.h
+pty.o: $(hdrdir)/ruby/internal/special_consts.h
+pty.o: $(hdrdir)/ruby/internal/static_assert.h
+pty.o: $(hdrdir)/ruby/internal/stdalign.h
+pty.o: $(hdrdir)/ruby/internal/stdbool.h
+pty.o: $(hdrdir)/ruby/internal/stdckdint.h
+pty.o: $(hdrdir)/ruby/internal/symbol.h
+pty.o: $(hdrdir)/ruby/internal/value.h
+pty.o: $(hdrdir)/ruby/internal/value_type.h
+pty.o: $(hdrdir)/ruby/internal/variable.h
+pty.o: $(hdrdir)/ruby/internal/warning_push.h
+pty.o: $(hdrdir)/ruby/internal/xmalloc.h
+pty.o: $(hdrdir)/ruby/io.h
+pty.o: $(hdrdir)/ruby/missing.h
+pty.o: $(hdrdir)/ruby/onigmo.h
+pty.o: $(hdrdir)/ruby/oniguruma.h
+pty.o: $(hdrdir)/ruby/ruby.h
+pty.o: $(hdrdir)/ruby/st.h
+pty.o: $(hdrdir)/ruby/subst.h
+pty.o: $(hdrdir)/ruby/util.h
+pty.o: $(top_srcdir)/id_table.h
+pty.o: $(top_srcdir)/internal.h
+pty.o: $(top_srcdir)/internal/array.h
+pty.o: $(top_srcdir)/internal/compilers.h
+pty.o: $(top_srcdir)/internal/gc.h
+pty.o: $(top_srcdir)/internal/imemo.h
+pty.o: $(top_srcdir)/internal/process.h
+pty.o: $(top_srcdir)/internal/signal.h
+pty.o: $(top_srcdir)/internal/static_assert.h
+pty.o: $(top_srcdir)/internal/warnings.h
+pty.o: $(top_srcdir)/shape.h
+pty.o: pty.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/pty/expect_sample.rb b/ext/pty/expect_sample.rb
deleted file mode 100644
index bf8a2352fe..0000000000
--- a/ext/pty/expect_sample.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# sample program of expect.rb
-#
-# by A. Ito
-#
-# This program reports the latest version of ruby interpreter
-# by connecting to ftp server at ruby-lang.org.
-#
-require 'pty'
-require 'expect'
-
-fnames = []
-PTY.spawn("ftp ftp.ruby-lang.org") do |r_f,w_f,pid|
- w_f.sync = true
-
- $expect_verbose = false
-
- r_f.expect(/^Name.*: /) do
- w_f.print "ftp\n"
- end
-
- if !ENV['USER'].nil?
- username = ENV['USER']
- elsif !ENV['LOGNAME'].nil?
- username = ENV['LOGNAME']
- else
- username = 'guest'
- end
-
- r_f.expect('word:') do
- w_f.print username+"@\n"
- end
- r_f.expect("> ") do
- w_f.print "cd pub/ruby\n"
- end
- r_f.expect("> ") do
- w_f.print "dir\n"
- end
-
- r_f.expect("> ") do |output|
- for x in output[0].split("\n")
- if x =~ /(ruby.*\.tar\.gz)/ then
- fnames.push $1
- end
- end
- end
- begin
- w_f.print "quit\n"
- rescue
- end
-end
-
-print "The latest ruby interpreter is "
-print fnames.sort.pop
-print "\n"
diff --git a/ext/pty/extconf.rb b/ext/pty/extconf.rb
index 5e126fe0cf..ae2cb45d3c 100644
--- a/ext/pty/extconf.rb
+++ b/ext/pty/extconf.rb
@@ -1,15 +1,28 @@
+# frozen_string_literal: true
require 'mkmf'
-if /mswin32|mingw|bccwin32/ !~ RUBY_PLATFORM
+$INCFLAGS << " -I$(topdir) -I$(top_srcdir)"
+
+if /mswin|mingw|bccwin/ !~ RUBY_PLATFORM
have_header("sys/stropts.h")
have_func("setresuid")
have_header("libutil.h")
have_header("pty.h")
- have_library("util", "openpty")
- if have_func("openpty") or
+ have_header("pwd.h")
+ if /openbsd/ =~ RUBY_PLATFORM
+ have_header("util.h") # OpenBSD openpty
+ util = have_library("util", "openpty")
+ end
+ openpt = have_func("posix_openpt")
+ if openpt
+ have_func("ptsname_r") or have_func("ptsname")
+ end
+ if openpt or
+ (util or have_func("openpty")) or
have_func("_getpty") or
- have_func("ptsname") or
have_func("ioctl")
+ have_macro("HAVE_FCHMOD") or have_func("fchmod")
+ have_macro("HAVE_FCHOWN") or have_func("fchown")
create_makefile('pty')
end
end
diff --git a/ext/pty/lib/expect.rb b/ext/pty/lib/expect.rb
index aa9ab895d3..22cbf54115 100644
--- a/ext/pty/lib/expect.rb
+++ b/ext/pty/lib/expect.rb
@@ -1,27 +1,63 @@
+# frozen_string_literal: true
$expect_verbose = false
class IO
+ # call-seq:
+ # IO#expect(pattern,timeout=9999999) -> Array
+ # IO#expect(pattern,timeout=9999999) { |result| ... } -> nil
+ #
+ # The +expect+ library adds instance method IO#expect,
+ # which is similar to the
+ # {TCL expect extension}[https://www.tcl.tk/man/expect5.31/expect.1.html].
+ #
+ # To use this method, you must require +expect+:
+ #
+ # require 'expect'
+ #
+ # Reads from the IO until the given +pattern+ matches or the +timeout+ is over.
+ #
+ # It returns an array with the read buffer, followed by the matches.
+ # If a block is given, the result is yielded to the block and returns nil.
+ #
+ # When called without a block, it waits until the input that matches the
+ # given +pattern+ is obtained from the IO or the time specified as the
+ # timeout passes. An array is returned when the pattern is obtained from the
+ # IO. The first element of the array is the entire string obtained from the
+ # IO until the pattern matches, followed by elements indicating which the
+ # pattern which matched to the anchor in the regular expression.
+ #
+ # The optional timeout parameter defines, in seconds, the total time to wait
+ # for the pattern. If the timeout expires or eof is found, nil is returned
+ # or yielded. However, the buffer in a timeout session is kept for the next
+ # expect call. The default timeout is 9999999 seconds.
def expect(pat,timeout=9999999)
- buf = ''
+ buf = ''.dup
case pat
when String
e_pat = Regexp.new(Regexp.quote(pat))
when Regexp
e_pat = pat
+ else
+ raise TypeError, "unsupported pattern class: #{pat.class}"
end
+ @unusedBuf ||= ''
while true
- if IO.select([self],nil,nil,timeout).nil? then
+ if not @unusedBuf.empty?
+ c = @unusedBuf.slice!(0)
+ elsif !IO.select([self],nil,nil,timeout) or eof? then
result = nil
+ @unusedBuf = buf
break
+ else
+ c = getc
end
- c = getc.chr
buf << c
if $expect_verbose
STDOUT.print c
STDOUT.flush
end
if mat=e_pat.match(buf) then
- result = [buf,*mat.to_a[1..-1]]
+ result = [buf,*mat.captures]
break
end
end
@@ -33,4 +69,3 @@ class IO
nil
end
end
-
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
index 626898ae76..3d5977707f 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -1,32 +1,51 @@
-#include "config.h"
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <pwd.h>
+#include "ruby/config.h"
+
+#ifdef RUBY_EXTCONF_H
+# include RUBY_EXTCONF_H
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
+# include <sys/ioctl.h>
#endif
+
#ifdef HAVE_LIBUTIL_H
-#include <libutil.h>
+# include <libutil.h>
+#endif
+
+#ifdef HAVE_UTIL_H
+# include <util.h>
#endif
+
#ifdef HAVE_PTY_H
-#include <pty.h>
+# include <pty.h>
+#endif
+
+#if defined(HAVE_SYS_PARAM_H)
+ /* for __FreeBSD_version */
+# include <sys/param.h>
#endif
+
#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
+# include <sys/wait.h>
#else
-#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
+# define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
#endif
-#include <ctype.h>
-#include "ruby.h"
-#include "rubyio.h"
-#include "util.h"
-
-#include <signal.h>
#ifdef HAVE_SYS_STROPTS_H
#include <sys/stropts.h>
#endif
@@ -35,73 +54,13 @@
#include <unistd.h>
#endif
-#define DEVICELEN 16
-
-#if !defined(HAVE_OPENPTY)
-#if defined(__hpux)
-static
-char *MasterDevice = "/dev/ptym/pty%s",
- *SlaveDevice = "/dev/pty/tty%s",
- *deviceNo[] = {
- "p0","p1","p2","p3","p4","p5","p6","p7",
- "p8","p9","pa","pb","pc","pd","pe","pf",
- "q0","q1","q2","q3","q4","q5","q6","q7",
- "q8","q9","qa","qb","qc","qd","qe","qf",
- "r0","r1","r2","r3","r4","r5","r6","r7",
- "r8","r9","ra","rb","rc","rd","re","rf",
- "s0","s1","s2","s3","s4","s5","s6","s7",
- "s8","s9","sa","sb","sc","sd","se","sf",
- "t0","t1","t2","t3","t4","t5","t6","t7",
- "t8","t9","ta","tb","tc","td","te","tf",
- "u0","u1","u2","u3","u4","u5","u6","u7",
- "u8","u9","ua","ub","uc","ud","ue","uf",
- "v0","v1","v2","v3","v4","v5","v6","v7",
- "v8","v9","va","vb","vc","vd","ve","vf",
- "w0","w1","w2","w3","w4","w5","w6","w7",
- "w8","w9","wa","wb","wc","wd","we","wf",
- 0,
- };
-#elif defined(_IBMESA) /* AIX/ESA */
-static
-char *MasterDevice = "/dev/ptyp%s",
- *SlaveDevice = "/dev/ttyp%s",
- *deviceNo[] = {
-"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
-"10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
-"20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f",
-"30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f",
-"40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f",
-"50","51","52","53","54","55","56","57","58","59","5a","5b","5c","5d","5e","5f",
-"60","61","62","63","64","65","66","67","68","69","6a","6b","6c","6d","6e","6f",
-"70","71","72","73","74","75","76","77","78","79","7a","7b","7c","7d","7e","7f",
-"80","81","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f",
-"90","91","92","93","94","95","96","97","98","99","9a","9b","9c","9d","9e","9f",
-"a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","aa","ab","ac","ad","ae","af",
-"b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","ba","bb","bc","bd","be","bf",
-"c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","ca","cb","cc","cd","ce","cf",
-"d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","da","db","dc","dd","de","df",
-"e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef",
-"f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff",
- };
-#elif !defined(HAVE_PTSNAME)
-static
-char *MasterDevice = "/dev/pty%s",
- *SlaveDevice = "/dev/tty%s",
- *deviceNo[] = {
- "p0","p1","p2","p3","p4","p5","p6","p7",
- "p8","p9","pa","pb","pc","pd","pe","pf",
- "q0","q1","q2","q3","q4","q5","q6","q7",
- "q8","q9","qa","qb","qc","qd","qe","qf",
- "r0","r1","r2","r3","r4","r5","r6","r7",
- "r8","r9","ra","rb","rc","rd","re","rf",
- "s0","s1","s2","s3","s4","s5","s6","s7",
- "s8","s9","sa","sb","sc","sd","se","sf",
- 0,
- };
-#endif
-#endif /* !defined(HAVE_OPENPTY) */
+#include "internal.h"
+#include "internal/process.h"
+#include "internal/signal.h"
+#include "ruby/io.h"
+#include "ruby/util.h"
-static char SlaveName[DEVICELEN];
+#define DEVICELEN 16
#ifndef HAVE_SETEUID
# ifdef HAVE_SETREUID
@@ -117,9 +76,11 @@ static char SlaveName[DEVICELEN];
static VALUE eChildExited;
+/* Returns the exit status of the child for which PTY#check
+ * raised this exception
+ */
static VALUE
-echild_status(self)
- VALUE self;
+echild_status(VALUE self)
{
return rb_ivar_get(self, rb_intern("status"));
}
@@ -127,363 +88,765 @@ echild_status(self)
struct pty_info {
int fd;
rb_pid_t child_pid;
- VALUE thread;
};
-static void
-raise_from_wait(state, info)
- struct pty_info *info;
- char *state;
-{
- extern VALUE rb_last_status;
- char buf[1024];
- VALUE exc;
+static void getDevice(int*, int*, char [DEVICELEN], int);
- snprintf(buf, sizeof(buf), "pty - %s: %d", state, info->child_pid);
- exc = rb_exc_new2(eChildExited, buf);
- rb_iv_set(exc, "status", rb_last_status);
- rb_funcall(info->thread, rb_intern("raise"), 1, exc);
-}
+static int start_new_session(char *errbuf, size_t errbuf_len);
+static int obtain_ctty(int master, int slave, const char *slavename, char *errbuf, size_t errbuf_len);
+static int drop_privilege(char *errbuf, size_t errbuf_len);
-static VALUE
-pty_syswait(info)
- struct pty_info *info;
-{
- int cpid, status;
-
- for (;;) {
- cpid = rb_waitpid(info->child_pid, &status, WUNTRACED);
- if (cpid == -1) return Qnil;
-
-#if defined(IF_STOPPED)
- if (IF_STOPPED(status)) { /* suspend */
- raise_from_wait("stopped", info);
- }
-#elif defined(WIFSTOPPED)
- if (WIFSTOPPED(status)) { /* suspend */
- raise_from_wait("stopped", info);
- }
-#else
----->> Either IF_STOPPED or WIFSTOPPED is needed <<----
-#endif /* WIFSTOPPED | IF_STOPPED */
- else if (kill(info->child_pid, 0) == 0) {
- raise_from_wait("changed", info);
- }
- else {
- raise_from_wait("exited", info);
- return Qnil;
- }
- }
-}
-
-static void getDevice _((int*, int*));
-
-struct exec_info {
- int argc;
- VALUE *argv;
+struct child_info {
+ int master, slave;
+ const char *slavename;
+ VALUE execarg_obj;
+ struct rb_execarg *eargp;
};
-static VALUE
-pty_exec(arg)
- struct exec_info *arg;
+static int
+chfunc(void *data, char *errbuf, size_t errbuf_len)
{
- return rb_f_exec(arg->argc, arg->argv);
-}
+ const struct child_info *carg = data;
+ int master = carg->master;
+ int slave = carg->slave;
+ const char *slavename = carg->slavename;
-static void
-establishShell(argc, argv, info)
- int argc;
- VALUE *argv;
- struct pty_info *info;
-{
- static int i,master,slave,currentPid;
- char *p,*getenv();
- struct passwd *pwent;
- VALUE v;
- struct exec_info arg;
- int status;
+ if (start_new_session(errbuf, errbuf_len))
+ return -1;
- if (argc == 0) {
- char *shellname;
-
- if ((p = getenv("SHELL")) != NULL) {
- shellname = p;
- }
- else {
- pwent = getpwuid(getuid());
- if (pwent && pwent->pw_shell)
- shellname = pwent->pw_shell;
- else
- shellname = "/bin/sh";
- }
- v = rb_str_new2(shellname);
- argc = 1;
- argv = &v;
- }
- getDevice(&master,&slave);
-
- info->thread = rb_thread_current();
- currentPid = getpid();
- if((i = fork()) < 0) {
- close(master);
- close(slave);
- rb_sys_fail("fork failed");
- }
+ if (obtain_ctty(master, slave, slavename, errbuf, errbuf_len))
+ return -1;
+
+ if (drop_privilege(errbuf, errbuf_len))
+ return -1;
- if(i == 0) { /* child */
- currentPid = getpid();
+ return rb_exec_async_signal_safe(carg->eargp, errbuf, errbuf_len);
+}
+
+#define ERROR_EXIT(str) do { \
+ strlcpy(errbuf, (str), errbuf_len); \
+ return -1; \
+ } while (0)
- /*
- * Set free from process group and controlling terminal
- */
+/*
+ * Set free from process group and controlling terminal
+ */
+static int
+start_new_session(char *errbuf, size_t errbuf_len)
+{
#ifdef HAVE_SETSID
- (void) setsid();
+ (void) setsid();
#else /* HAS_SETSID */
# ifdef HAVE_SETPGRP
-# ifdef SETGRP_VOID
- if (setpgrp() == -1)
- perror("setpgrp()");
-# else /* SETGRP_VOID */
- if (setpgrp(0, currentPid) == -1)
- rb_sys_fail("setpgrp()");
- if ((i = open("/dev/tty", O_RDONLY)) < 0)
- rb_sys_fail("/dev/tty");
- else {
- if (ioctl(i, TIOCNOTTY, (char *)0))
- perror("ioctl(TIOCNOTTY)");
- close(i);
- }
-# endif /* SETGRP_VOID */
+# ifdef SETPGRP_VOID
+ if (setpgrp() == -1)
+ ERROR_EXIT("setpgrp()");
+# else /* SETPGRP_VOID */
+ if (setpgrp(0, getpid()) == -1)
+ ERROR_EXIT("setpgrp()");
+ {
+ int i = rb_cloexec_open("/dev/tty", O_RDONLY, 0);
+ if (i < 0) ERROR_EXIT("/dev/tty");
+ rb_update_max_fd(i);
+ if (ioctl(i, TIOCNOTTY, (char *)0))
+ ERROR_EXIT("ioctl(TIOCNOTTY)");
+ close(i);
+ }
+# endif /* SETPGRP_VOID */
# endif /* HAVE_SETPGRP */
#endif /* HAS_SETSID */
+ return 0;
+}
- /*
- * obtain new controlling terminal
- */
+/*
+ * obtain new controlling terminal
+ */
+static int
+obtain_ctty(int master, int slave, const char *slavename, char *errbuf, size_t errbuf_len)
+{
#if defined(TIOCSCTTY)
- close(master);
- (void) ioctl(slave, TIOCSCTTY, (char *)0);
- /* errors ignored for sun */
+ close(master);
+ (void) ioctl(slave, TIOCSCTTY, (char *)0);
+ /* errors ignored for sun */
#else
- close(slave);
- slave = open(SlaveName, O_RDWR);
- if (slave < 0) {
- perror("open: pty slave");
- _exit(1);
- }
- close(master);
+ close(slave);
+ slave = rb_cloexec_open(slavename, O_RDWR, 0);
+ if (slave < 0) {
+ ERROR_EXIT("open: pty slave");
+ }
+ rb_update_max_fd(slave);
+ close(master);
#endif
- dup2(slave,0);
- dup2(slave,1);
- dup2(slave,2);
- close(slave);
+ dup2(slave,0);
+ dup2(slave,1);
+ dup2(slave,2);
+ if (slave > 2) (void)!close(slave);
+ return 0;
+}
+
+static int
+drop_privilege(char *errbuf, size_t errbuf_len)
+{
#if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID)
- seteuid(getuid());
+ if (seteuid(getuid())) ERROR_EXIT("seteuid()");
#endif
+ return 0;
+}
- arg.argc = argc;
- arg.argv = argv;
- rb_protect(pty_exec, (VALUE)&arg, &status);
- sleep(1);
- _exit(1);
+#undef ERROR_EXIT
+
+static void
+establishShell(int argc, VALUE *argv, struct pty_info *info,
+ char SlaveName[DEVICELEN])
+{
+ int master, slave, status = 0;
+ rb_pid_t pid;
+ char *p;
+ VALUE v;
+ struct child_info carg;
+ char errbuf[32];
+
+ if (argc == 0) {
+ const char *shellname = "/bin/sh";
+
+ if ((p = getenv("SHELL")) != NULL) {
+ shellname = p;
+ }
+ else {
+#if defined HAVE_PWD_H
+ const char *username = getenv("USER");
+ if (username == NULL)
+ username = getlogin();
+ if (username != NULL) {
+ struct passwd *pwent = getpwnam(username);
+ if (pwent && pwent->pw_shell)
+ shellname = pwent->pw_shell;
+ }
+#endif
+ }
+ v = rb_str_new2(shellname);
+ argc = 1;
+ argv = &v;
+ }
+
+ carg.execarg_obj = rb_execarg_new(argc, argv, 1, 0);
+ carg.eargp = rb_execarg_get(carg.execarg_obj);
+ rb_execarg_parent_start(carg.execarg_obj);
+
+ getDevice(&master, &slave, SlaveName, 0);
+
+ carg.master = master;
+ carg.slave = slave;
+ carg.slavename = SlaveName;
+ errbuf[0] = '\0';
+ pid = rb_fork_async_signal_safe(&status, chfunc, &carg, Qnil, errbuf, sizeof(errbuf));
+
+ if (pid < 0) {
+ int e = errno;
+ close(master);
+ close(slave);
+ rb_execarg_parent_end(carg.execarg_obj);
+ errno = e;
+ if (status) rb_jump_tag(status);
+ rb_sys_fail(errbuf[0] ? errbuf : "fork failed");
}
close(slave);
+ rb_execarg_parent_end(carg.execarg_obj);
- info->child_pid = i;
+ info->child_pid = pid;
info->fd = master;
+
+ RB_GC_GUARD(carg.execarg_obj);
}
-static VALUE
-pty_finalize_syswait(info)
- struct pty_info *info;
+#if (defined(HAVE_POSIX_OPENPT) || defined(HAVE_PTSNAME)) && !defined(HAVE_PTSNAME_R)
+/* glibc only, not obsolete interface on Tru64 or HP-UX */
+static int
+ptsname_r(int fd, char *buf, size_t buflen)
{
- rb_thread_kill(info->thread);
- rb_funcall(info->thread, rb_intern("value"), 0);
- rb_detach_process(info->child_pid);
- return Qnil;
+ extern char *ptsname(int);
+ char *name = ptsname(fd);
+ if (!name) return -1;
+ strlcpy(buf, name, buflen);
+ return 0;
+}
+# define HAVE_PTSNAME_R 1
+#endif
+
+#ifdef HAVE_FCHMOD
+# define change_mode(name, fd, mode) fchmod(fd, mode)
+#else
+# define change_mode(name, fd, mode) chmod(name, mode)
+#endif
+#ifdef HAVE_FCHOWN
+# define change_owner(name, fd, uid, gid) fchown(fd, uid, gid)
+#else
+# define change_owner(name, fd, uid, gid) chown(name, uid, gid)
+#endif
+
+#if defined(HAVE_POSIX_OPENPT) || defined(HAVE_OPENPTY) || defined(HAVE_PTSNAME_R)
+static inline int
+prevent_messages(const char *slavedevice, int fd, int nomesg)
+{
+ if (nomesg)
+ return change_mode(slavedevice, fd, 0600);
+ else
+ return 0;
+}
+#endif
+
+#if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX)
+static inline int
+ioctl_I_PUSH(int fd, const char *const name)
+{
+ int ret = 0;
+# if defined(I_FIND)
+ ret = ioctl(fd, I_FIND, name);
+# endif
+ if (ret == 0) {
+ ret = ioctl(fd, I_PUSH, name);
+ }
+ return ret;
}
+#endif
static int
-get_device_once(master, slave, fail)
- int *master, *slave, fail;
+get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, int fail)
{
-#if defined HAVE_OPENPTY
+#if defined(HAVE_POSIX_OPENPT)
+ /* Unix98 PTY */
+ int masterfd = -1, slavefd = -1;
+ char *slavedevice;
+ struct sigaction dfl, old;
+
+ dfl.sa_handler = SIG_DFL;
+ dfl.sa_flags = 0;
+ sigemptyset(&dfl.sa_mask);
+
+#if defined(__sun) || defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD_version < 902000)
+ /* workaround for Solaris 10: grantpt() doesn't work if FD_CLOEXEC is set. [ruby-dev:44688] */
+ /* FreeBSD 9.2 or later supports O_CLOEXEC
+ * http://www.freebsd.org/cgi/query-pr.cgi?pr=162374 */
+ if ((masterfd = posix_openpt(O_RDWR|O_NOCTTY)) == -1) goto error;
+ if (sigaction(SIGCHLD, &dfl, &old) == -1) goto error;
+ if (grantpt(masterfd) == -1) goto grantpt_error;
+ rb_fd_fix_cloexec(masterfd);
+#else
+ {
+ int flags = O_RDWR|O_NOCTTY;
+# if defined(O_CLOEXEC)
+ /* glibc posix_openpt() in GNU/Linux calls open("/dev/ptmx", flags) internally.
+ * So version dependency on GNU/Linux is the same as O_CLOEXEC with open().
+ * O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
+ flags |= O_CLOEXEC;
+# endif
+ if ((masterfd = posix_openpt(flags)) == -1) goto error;
+ }
+ rb_fd_fix_cloexec(masterfd);
+ if (sigaction(SIGCHLD, &dfl, &old) == -1) goto error;
+ if (grantpt(masterfd) == -1) goto grantpt_error;
+#endif
+ if (sigaction(SIGCHLD, &old, NULL) == -1) goto error;
+ if (unlockpt(masterfd) == -1) goto error;
+ if (ptsname_r(masterfd, SlaveName, DEVICELEN) != 0) goto error;
+ slavedevice = SlaveName;
+ if ((slavefd = rb_cloexec_open(slavedevice, O_RDWR|O_NOCTTY, 0)) == -1) goto error;
+ if (prevent_messages(slavedevice, slavefd, nomesg) == -1) goto error;
+ rb_update_max_fd(slavefd);
+
+#if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX)
+ if (ioctl_I_PUSH(slavefd, "ptem") == -1) goto error;
+ if (ioctl_I_PUSH(slavefd, "ldterm") == -1) goto error;
+ if (ioctl_I_PUSH(slavefd, "ttcompat") == -1) goto error;
+#endif
+
+ *master = masterfd;
+ *slave = slavefd;
+ return 0;
+
+ grantpt_error:
+ sigaction(SIGCHLD, &old, NULL);
+ error:
+ if (slavefd != -1) close(slavefd);
+ if (masterfd != -1) close(masterfd);
+ if (fail) {
+ rb_raise(rb_eRuntimeError, "can't get Master/Slave device");
+ }
+ return -1;
+#elif defined HAVE_OPENPTY
/*
* Use openpty(3) of 4.3BSD Reno and later,
* or the same interface function.
*/
if (openpty(master, slave, SlaveName,
- (struct termios *)0, (struct winsize *)0) == -1) {
- if (!fail) return -1;
- rb_raise(rb_eRuntimeError, "openpty() failed");
+ (struct termios *)0, (struct winsize *)0) == -1) {
+ if (!fail) return -1;
+ rb_raise(rb_eRuntimeError, "openpty() failed");
+ }
+ rb_fd_fix_cloexec(*master);
+ rb_fd_fix_cloexec(*slave);
+ if (prevent_messages(SlaveName, *slave, nomesg) == -1) {
+ close(*master);
+ close(*slave);
+ if (!fail) return -1;
+ rb_raise(rb_eRuntimeError, "can't chmod slave pty");
}
return 0;
+
#elif defined HAVE__GETPTY
+ /* SGI IRIX */
char *name;
+ mode_t mode = nomesg ? 0600 : 0622;
- if (!(name = _getpty(master, O_RDWR, 0622, 0))) {
- if (!fail) return -1;
- rb_raise(rb_eRuntimeError, "_getpty() failed");
+ if (!(name = _getpty(master, O_RDWR, mode, 0))) {
+ if (!fail) return -1;
+ rb_raise(rb_eRuntimeError, "_getpty() failed");
}
+ rb_fd_fix_cloexec(*master);
- *slave = open(name, O_RDWR);
- strcpy(SlaveName, name);
+ *slave = rb_cloexec_open(name, O_RDWR, 0);
+ /* error check? */
+ rb_update_max_fd(*slave);
+ strlcpy(SlaveName, name, DEVICELEN);
return 0;
-}
-#else /* HAVE__GETPTY */
- int i,j;
-
-#ifdef HAVE_PTSNAME
- char *pn;
+#elif defined(HAVE_PTSNAME)
+ /* System V */
+ int masterfd = -1, slavefd = -1;
+ char *slavedevice;
void (*s)();
- extern char *ptsname(int);
extern int unlockpt(int);
extern int grantpt(int);
- if((i = open("/dev/ptmx", O_RDWR, 0)) != -1) {
- s = signal(SIGCHLD, SIG_DFL);
- if(grantpt(i) != -1) {
- signal(SIGCHLD, s);
- if(unlockpt(i) != -1) {
- if((pn = ptsname(i)) != NULL) {
- if((j = open(pn, O_RDWR, 0)) != -1) {
-#if defined I_PUSH && !defined linux
- if(ioctl(j, I_PUSH, "ptem") != -1) {
- if(ioctl(j, I_PUSH, "ldterm") != -1) {
+#if defined(__sun)
+ /* workaround for Solaris 10: grantpt() doesn't work if FD_CLOEXEC is set. [ruby-dev:44688] */
+ if((masterfd = open("/dev/ptmx", O_RDWR, 0)) == -1) goto error;
+ s = signal(SIGCHLD, SIG_DFL);
+ if(grantpt(masterfd) == -1) goto error;
+ rb_fd_fix_cloexec(masterfd);
+#else
+ if((masterfd = rb_cloexec_open("/dev/ptmx", O_RDWR, 0)) == -1) goto error;
+ rb_update_max_fd(masterfd);
+ s = signal(SIGCHLD, SIG_DFL);
+ if(grantpt(masterfd) == -1) goto error;
#endif
- *master = i;
- *slave = j;
- strcpy(SlaveName, pn);
- return 0;
-#if defined I_PUSH && !defined linux
- }
- }
+ signal(SIGCHLD, s);
+ if(unlockpt(masterfd) == -1) goto error;
+ if (ptsname_r(masterfd, SlaveName, DEVICELEN) != 0) goto error;
+ slavedevice = SlaveName;
+ if((slavefd = rb_cloexec_open(slavedevice, O_RDWR, 0)) == -1) goto error;
+ if (prevent_messages(slavedevice, slavefd, nomesg) == -1) goto error;
+ rb_update_max_fd(slavefd);
+#if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX)
+ if(ioctl_I_PUSH(slavefd, "ptem") == -1) goto error;
+ if(ioctl_I_PUSH(slavefd, "ldterm") == -1) goto error;
+ ioctl_I_PUSH(slavefd, "ttcompat");
#endif
- }
- }
- }
- }
- close(i);
- }
- if (!fail) rb_raise(rb_eRuntimeError, "can't get Master/Slave device");
+ *master = masterfd;
+ *slave = slavefd;
+ return 0;
+
+ error:
+ if (slavefd != -1) close(slavefd);
+ if (masterfd != -1) close(masterfd);
+ if (fail) rb_raise(rb_eRuntimeError, "can't get Master/Slave device");
return -1;
#else
- char **p;
+ /* BSD */
+ int masterfd = -1, slavefd = -1;
+ int i;
char MasterName[DEVICELEN];
- for (p = deviceNo; *p != NULL; p++) {
- sprintf(MasterName,MasterDevice,*p);
- if ((i = open(MasterName,O_RDWR,0)) >= 0) {
- *master = i;
- sprintf(SlaveName,SlaveDevice,*p);
- if ((j = open(SlaveName,O_RDWR,0)) >= 0) {
- *slave = j;
- chown(SlaveName, getuid(), getgid());
- chmod(SlaveName, 0622);
- return 0;
- }
- close(i);
- }
+#define HEX1(c) \
+ c"0",c"1",c"2",c"3",c"4",c"5",c"6",c"7", \
+ c"8",c"9",c"a",c"b",c"c",c"d",c"e",c"f"
+
+#if defined(_IBMESA) /* AIX/ESA */
+ static const char MasterDevice[] = "/dev/ptyp%s";
+ static const char SlaveDevice[] = "/dev/ttyp%s";
+ static const char deviceNo[][3] = {
+ HEX1("0"), HEX1("1"), HEX1("2"), HEX1("3"),
+ HEX1("4"), HEX1("5"), HEX1("6"), HEX1("7"),
+ HEX1("8"), HEX1("9"), HEX1("a"), HEX1("b"),
+ HEX1("c"), HEX1("d"), HEX1("e"), HEX1("f"),
+ };
+#else /* 4.2BSD */
+ static const char MasterDevice[] = "/dev/pty%s";
+ static const char SlaveDevice[] = "/dev/tty%s";
+ static const char deviceNo[][3] = {
+ HEX1("p"), HEX1("q"), HEX1("r"), HEX1("s"),
+ };
+#endif
+#undef HEX1
+ for (i = 0; i < numberof(deviceNo); i++) {
+ const char *const devno = deviceNo[i];
+ snprintf(MasterName, sizeof MasterName, MasterDevice, devno);
+ if ((masterfd = rb_cloexec_open(MasterName,O_RDWR,0)) >= 0) {
+ rb_update_max_fd(masterfd);
+ *master = masterfd;
+ snprintf(SlaveName, DEVICELEN, SlaveDevice, devno);
+ if ((slavefd = rb_cloexec_open(SlaveName,O_RDWR,0)) >= 0) {
+ rb_update_max_fd(slavefd);
+ *slave = slavefd;
+ if (change_owner(SlaveName, slavefd, getuid(), getgid()) != 0) goto error;
+ if (change_mode(SlaveName, slavefd, nomesg ? 0600 : 0622) != 0) goto error;
+ return 0;
+ }
+ close(masterfd);
+ }
}
+ error:
+ if (slavefd != -1) close(slavefd);
+ if (masterfd != -1) close(masterfd);
if (fail) rb_raise(rb_eRuntimeError, "can't get %s", SlaveName);
return -1;
#endif
-#endif
}
static void
-getDevice(master, slave)
- int *master, *slave;
+getDevice(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg)
{
- if (get_device_once(master, slave, 0)) {
- rb_gc();
- get_device_once(master, slave, 1);
+ if (get_device_once(master, slave, SlaveName, nomesg, 0)) {
+ rb_gc();
+ get_device_once(master, slave, SlaveName, nomesg, 1);
}
}
-static void
-freeDevice()
+static VALUE
+pty_close_pty(VALUE assoc)
+{
+ VALUE io;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ io = rb_ary_entry(assoc, i);
+ if (RB_TYPE_P(io, T_FILE)) {
+ /* it's OK to call rb_io_close again even if it's already closed */
+ rb_io_close(io);
+ }
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * PTY.open => [master_io, slave_file]
+ * PTY.open {|(master_io, slave_file)| ... } => block value
+ *
+ * Allocates a pty (pseudo-terminal).
+ *
+ * In the block form, yields an array of two elements (<tt>master_io, slave_file</tt>)
+ * and the value of the block is returned from +open+.
+ *
+ * The IO and File are both closed after the block completes if they haven't
+ * been already closed.
+ *
+ * PTY.open {|master, slave|
+ * p master #=> #<IO:masterpty:/dev/pts/1>
+ * p slave #=> #<File:/dev/pts/1>
+ * p slave.path #=> "/dev/pts/1"
+ * }
+ *
+ * In the non-block form, returns a two element array, <tt>[master_io,
+ * slave_file]</tt>.
+ *
+ * master, slave = PTY.open
+ * # do something with master for IO, or the slave file
+ *
+ * The arguments in both forms are:
+ *
+ * +master_io+:: the master of the pty, as an IO.
+ * +slave_file+:: the slave of the pty, as a File. The path to the
+ * terminal device is available via +slave_file.path+
+ *
+ * IO#raw! is usable to disable newline conversions:
+ *
+ * require 'io/console'
+ * PTY.open {|m, s|
+ * s.raw!
+ * # ...
+ * }
+ *
+ */
+static VALUE
+pty_open(VALUE klass)
{
- chmod(SlaveName, 0666);
- chown(SlaveName, 0, 0);
+ int master_fd, slave_fd;
+ char slavename[DEVICELEN];
+
+ getDevice(&master_fd, &slave_fd, slavename, 1);
+
+ VALUE master_path = rb_obj_freeze(rb_sprintf("masterpty:%s", slavename));
+ VALUE master_io = rb_io_open_descriptor(rb_cIO, master_fd, FMODE_READWRITE | FMODE_SYNC | FMODE_DUPLEX, master_path, RUBY_IO_TIMEOUT_DEFAULT, NULL);
+
+ VALUE slave_path = rb_obj_freeze(rb_str_new_cstr(slavename));
+ VALUE slave_file = rb_io_open_descriptor(rb_cFile, slave_fd, FMODE_READWRITE | FMODE_SYNC | FMODE_DUPLEX | FMODE_TTY, slave_path, RUBY_IO_TIMEOUT_DEFAULT, NULL);
+
+ VALUE assoc = rb_assoc_new(master_io, slave_file);
+
+ if (rb_block_given_p()) {
+ return rb_ensure(rb_yield, assoc, pty_close_pty, assoc);
+ }
+
+ return assoc;
+}
+
+static VALUE
+pty_detach_process(VALUE v)
+{
+ struct pty_info *info = (void *)v;
+#ifdef WNOHANG
+ int st;
+ if (rb_waitpid(info->child_pid, &st, WNOHANG) <= 0)
+ return Qnil;
+#endif
+ rb_detach_process(info->child_pid);
+ return Qnil;
}
-/* ruby function: getpty */
+/*
+ * call-seq:
+ * PTY.spawn([env,] command_line) { |r, w, pid| ... }
+ * PTY.spawn([env,] command_line) => [r, w, pid]
+ * PTY.spawn([env,] command, arguments, ...) { |r, w, pid| ... }
+ * PTY.spawn([env,] command, arguments, ...) => [r, w, pid]
+ *
+ * Spawns the specified command on a newly allocated pty. You can also use the
+ * alias ::getpty.
+ *
+ * The command's controlling tty is set to the slave device of the pty
+ * and its standard input/output/error is redirected to the slave device.
+ *
+ * +env+ is an optional hash that provides additional environment variables to the spawned pty.
+ *
+ * # sets FOO to "bar"
+ * PTY.spawn({"FOO"=>"bar"}, "printenv", "FOO") do |r, w, pid|
+ * p r.read #=> "bar\r\n"
+ * ensure
+ * r.close; w.close; Process.wait(pid)
+ * end
+ * # unsets FOO
+ * PTY.spawn({"FOO"=>nil}, "printenv", "FOO") do |r, w, pid|
+ * p r.read #=> ""
+ * ensure
+ * r.close; w.close; Process.wait(pid)
+ * end
+ *
+ * +command+ and +command_line+ are the full commands to run, given a String.
+ * Any additional +arguments+ will be passed to the command.
+ *
+ * === Return values
+ *
+ * In the non-block form this returns an array of size three,
+ * <tt>[r, w, pid]</tt>.
+ *
+ * In the block form these same values will be yielded to the block:
+ *
+ * +r+:: A readable IO that contains the command's
+ * standard output and standard error
+ * +w+:: A writable IO that is the command's standard input
+ * +pid+:: The process identifier for the command.
+ *
+ * === Clean up
+ *
+ * This method does not clean up like closing IOs or waiting for child
+ * process, except that the process is detached in the block form to
+ * prevent it from becoming a zombie (see Process.detach). Any other
+ * cleanup is the responsibility of the caller. If waiting for +pid+,
+ * be sure to close both +r+ and +w+ before doing so; doing it in the
+ * reverse order may cause deadlock on some OSes.
+ */
static VALUE
-pty_getpty(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+pty_getpty(int argc, VALUE *argv, VALUE self)
{
VALUE res;
struct pty_info info;
- struct pty_info thinfo;
- OpenFile *wfptr,*rfptr;
- VALUE rport = rb_obj_alloc(rb_cFile);
- VALUE wport = rb_obj_alloc(rb_cFile);
-
- MakeOpenFile(rport, rfptr);
- MakeOpenFile(wport, wfptr);
+ char SlaveName[DEVICELEN];
- establishShell(argc, argv, &info);
+ establishShell(argc, argv, &info, SlaveName);
- rfptr->mode = rb_io_mode_flags("r");
- rfptr->f = fdopen(info.fd, "r");
- rfptr->path = strdup(SlaveName);
+ VALUE pty_path = rb_obj_freeze(rb_str_new_cstr(SlaveName));
+ VALUE rport = rb_io_open_descriptor(
+ rb_cFile, info.fd, FMODE_READABLE, pty_path, RUBY_IO_TIMEOUT_DEFAULT, NULL
+ );
- wfptr->mode = rb_io_mode_flags("w") | FMODE_SYNC;
- wfptr->f = fdopen(dup(info.fd), "w");
- wfptr->path = strdup(SlaveName);
+ int wpty_fd = rb_cloexec_dup(info.fd);
+ if (wpty_fd == -1) {
+ rb_sys_fail("dup()");
+ }
+ VALUE wport = rb_io_open_descriptor(
+ rb_cFile, wpty_fd, FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE | FMODE_SYNC,
+ pty_path, RUBY_IO_TIMEOUT_DEFAULT, NULL
+ );
res = rb_ary_new2(3);
- rb_ary_store(res,0,(VALUE)rport);
- rb_ary_store(res,1,(VALUE)wport);
- rb_ary_store(res,2,INT2FIX(info.child_pid));
-
- thinfo.thread = rb_thread_create(pty_syswait, (void*)&info);
- thinfo.child_pid = info.child_pid;
- rb_thread_schedule();
+ rb_ary_store(res, 0, rport);
+ rb_ary_store(res, 1, wport);
+ rb_ary_store(res,2,PIDT2NUM(info.child_pid));
if (rb_block_given_p()) {
- rb_ensure(rb_yield, res, pty_finalize_syswait, (VALUE)&thinfo);
- return Qnil;
+ rb_ensure(rb_yield, res, pty_detach_process, (VALUE)&info);
+ return Qnil;
}
return res;
}
-/* ruby function: protect_signal - obsolete */
-static VALUE
-pty_protect(self)
- VALUE self;
+NORETURN(static void raise_from_check(rb_pid_t pid, int status));
+static void
+raise_from_check(rb_pid_t pid, int status)
{
- rb_warn("PTY::protect_signal is no longer needed");
- rb_yield(Qnil);
- return self;
+ const char *state;
+ VALUE msg;
+ VALUE exc;
+
+#if defined(WIFSTOPPED)
+#elif defined(IF_STOPPED)
+#define WIFSTOPPED(status) IF_STOPPED(status)
+#else
+---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
+#endif /* WIFSTOPPED | IF_STOPPED */
+ if (WIFSTOPPED(status)) { /* suspend */
+ state = "stopped";
+ }
+ else if (kill(pid, 0) == 0) {
+ state = "changed";
+ }
+ else {
+ state = "exited";
+ }
+ msg = rb_sprintf("pty - %s: %ld", state, (long)pid);
+ exc = rb_exc_new_str(eChildExited, msg);
+ rb_iv_set(exc, "status", rb_last_status_get());
+ rb_exc_raise(exc);
}
-/* ruby function: reset_signal - obsolete */
+/*
+ * call-seq:
+ * PTY.check(pid, raise = false) => Process::Status or nil
+ * PTY.check(pid, true) => nil or raises PTY::ChildExited
+ *
+ * Checks the status of the child process specified by +pid+.
+ * Returns +nil+ if the process is still alive.
+ *
+ * If the process is not alive, and +raise+ was true, a PTY::ChildExited
+ * exception will be raised. Otherwise it will return a Process::Status
+ * instance.
+ *
+ * +pid+:: The process id of the process to check
+ * +raise+:: If +true+ and the process identified by +pid+ is no longer
+ * alive a PTY::ChildExited is raised.
+ *
+ */
static VALUE
-pty_reset_signal(self)
- VALUE self;
+pty_check(int argc, VALUE *argv, VALUE self)
{
- rb_warn("PTY::reset_signal is no longer needed");
- return self;
+ VALUE pid, exc;
+ rb_pid_t cpid;
+ int status;
+ const int flag =
+#ifdef WNOHANG
+ WNOHANG|
+#endif
+#ifdef WUNTRACED
+ WUNTRACED|
+#endif
+ 0;
+
+ rb_scan_args(argc, argv, "11", &pid, &exc);
+ cpid = rb_waitpid(NUM2PIDT(pid), &status, flag);
+ if (cpid == -1 || cpid == 0) return Qnil;
+
+ if (!RTEST(exc)) return rb_last_status_get();
+ raise_from_check(cpid, status);
+
+ UNREACHABLE_RETURN(Qnil);
}
static VALUE cPTY;
+/*
+ * Document-class: PTY::ChildExited
+ *
+ * Thrown when PTY::check is called for a pid that represents a process that
+ * has exited.
+ */
+
+/*
+ * Document-class: PTY
+ *
+ * Creates and manages pseudo terminals (PTYs). See also
+ * https://en.wikipedia.org/wiki/Pseudo_terminal
+ *
+ * PTY allows you to allocate new terminals using ::open or ::spawn a new
+ * terminal with a specific command.
+ *
+ * == Example
+ *
+ * In this example we will change the buffering type in the +factor+ command,
+ * assuming that factor uses stdio for stdout buffering.
+ *
+ * If IO.pipe is used instead of PTY.open, this code deadlocks because factor's
+ * stdout is fully buffered.
+ *
+ * # start by requiring the standard library PTY
+ * require 'pty'
+ *
+ * master, slave = PTY.open
+ * read, write = IO.pipe
+ * pid = spawn("factor", :in=>read, :out=>slave)
+ * read.close # we dont need the read
+ * slave.close # or the slave
+ *
+ * # pipe "42" to the factor command
+ * write.puts "42"
+ * # output the response from factor
+ * p master.gets #=> "42: 2 3 7\n"
+ *
+ * # pipe "144" to factor and print out the response
+ * write.puts "144"
+ * p master.gets #=> "144: 2 2 2 2 3 3\n"
+ * write.close # close the pipe
+ *
+ * # The result of read operation when pty slave is closed is platform
+ * # dependent.
+ * ret = begin
+ * master.gets # FreeBSD returns nil.
+ * rescue Errno::EIO # GNU/Linux raises EIO.
+ * nil
+ * end
+ * p ret #=> nil
+ *
+ * == License
+ *
+ * (c) Copyright 1998 by Akinori Ito.
+ *
+ * This software may be redistributed freely for this purpose, in full
+ * or in part, provided that this entire copyright notice is included
+ * on any copies of this software and applications and derivations thereof.
+ *
+ * This software is provided on an "as is" basis, without warranty of any
+ * kind, either expressed or implied, as to any matter including, but not
+ * limited to warranty of fitness of purpose, or merchantability, or
+ * results obtained from use of this software.
+ */
+
void
-Init_pty()
+Init_pty(void)
{
cPTY = rb_define_module("PTY");
- rb_define_module_function(cPTY,"getpty",pty_getpty,-1);
+#if 1
+ rb_define_module_function(cPTY,"get""pty",pty_getpty,-1);
+#else /* for RDoc */
+ /* show getpty as an alias of spawn */
+ VALUE sPTY = rb_singleton_class(cPTY);
+ rb_define_alias(sPTY, "getpty", "spawn");
+#endif
rb_define_module_function(cPTY,"spawn",pty_getpty,-1);
- rb_define_module_function(cPTY,"protect_signal",pty_protect,0);
- rb_define_module_function(cPTY,"reset_signal",pty_reset_signal,0);
+ rb_define_singleton_method(cPTY,"check",pty_check,-1);
+ rb_define_singleton_method(cPTY,"open",pty_open,0);
eChildExited = rb_define_class_under(cPTY,"ChildExited",rb_eRuntimeError);
rb_define_method(eChildExited,"status",echild_status,0);
diff --git a/ext/pty/script.rb b/ext/pty/script.rb
deleted file mode 100644
index dbb933171f..0000000000
--- a/ext/pty/script.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'pty'
-
-if ARGV.size == 0 then
- ofile = "typescript"
-else
- ofile = ARGV[0]
-end
-
-logfile = File.open(ofile,"a")
-
-system "stty -echo raw lnext ^_"
-
-PTY.spawn("/bin/csh") do |r_pty,w_pty,pid|
-
- Thread.new do
- while true
- w_pty.print STDIN.getc.chr
- w_pty.flush
- end
- end
-
- begin
- while true
- c = r_pty.sysread(512)
- break if c.nil?
- print c
- STDOUT.flush
- logfile.print c
- end
- rescue
- # print $@,':',$!,"\n"
- logfile.close
- end
-end
-
-system "stty echo -raw lnext ^v"
-
diff --git a/ext/pty/shl.rb b/ext/pty/shl.rb
deleted file mode 100644
index cdaf8d7398..0000000000
--- a/ext/pty/shl.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-#
-# old-fashioned 'shl' like program
-# by A. Ito
-#
-# commands:
-# c creates new shell
-# C-z suspends shell
-# p lists all shell
-# 0,1,... choose shell
-# q quit
-
-require 'pty'
-
-$shells = []
-$n_shells = 0
-
-$r_pty = nil
-$w_pty = nil
-
-def writer
- system "stty -echo raw"
- begin
- while true
- c = STDIN.getc
- if c == 26 then # C-z
- $reader.raise(nil)
- return 'Suspend'
- end
- $w_pty.print c.chr
- $w_pty.flush
- end
- rescue
- $reader.raise(nil)
- return 'Exit'
- ensure
- system "stty echo -raw"
- end
-end
-
-$reader = Thread.new {
- while true
- begin
- next if $r_pty.nil?
- c = $r_pty.getc
- if c.nil? then
- Thread.stop
- end
- print c.chr
- STDOUT.flush
- rescue
- Thread.stop
- end
- end
-}
-
-# $reader.raise(nil)
-
-
-while true
- print ">> "
- STDOUT.flush
- case gets
- when /^c/i
- $shells[$n_shells] = PTY.spawn("/bin/csh")
- $r_pty,$w_pty = $shells[$n_shells]
- $n_shells += 1
- $reader.run
- if writer == 'Exit'
- $n_shells -= 1
- $shells[$n_shells] = nil
- end
- when /^p/i
- for i in 0..$n_shells
- unless $shells[i].nil?
- print i,"\n"
- end
- end
- when /^([0-9]+)/
- n = $1.to_i
- if $shells[n].nil?
- print "\##{i} doesn't exist\n"
- else
- $r_pty,$w_pty = $shells[n]
- $reader.run
- if writer == 'Exit' then
- $shells[n] = nil
- end
- end
- when /^q/i
- exit
- end
-end
diff --git a/ext/racc/cparse/.cvsignore b/ext/racc/cparse/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/racc/cparse/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/racc/cparse/cparse.c b/ext/racc/cparse/cparse.c
deleted file mode 100644
index 197a0eb40b..0000000000
--- a/ext/racc/cparse/cparse.c
+++ /dev/null
@@ -1,832 +0,0 @@
-/*
-
- cparse.c -- Racc Runtime Core
-
- Copyright (c) 1999-2006 Minero Aoki
-
- This library is free software.
- You can distribute/modify this program under the same terms of ruby.
-
- $originalId: cparse.c,v 1.8 2006/07/06 11:39:46 aamine Exp $
-
-*/
-
-#include "ruby.h"
-#include "version.h"
-
-/* -----------------------------------------------------------------------
- Important Constants
------------------------------------------------------------------------ */
-
-#define RACC_VERSION "1.4.5"
-
-#define DEFAULT_TOKEN -1
-#define ERROR_TOKEN 1
-#define FINAL_TOKEN 0
-
-#define vDEFAULT_TOKEN INT2FIX(DEFAULT_TOKEN)
-#define vERROR_TOKEN INT2FIX(ERROR_TOKEN)
-#define vFINAL_TOKEN INT2FIX(FINAL_TOKEN)
-
-/* -----------------------------------------------------------------------
- File Local Variables
------------------------------------------------------------------------ */
-
-static VALUE RaccBug;
-static VALUE CparseParams;
-
-static ID id_yydebug;
-static ID id_nexttoken;
-static ID id_onerror;
-static ID id_noreduce;
-static ID id_errstatus;
-
-static ID id_d_shift;
-static ID id_d_reduce;
-static ID id_d_accept;
-static ID id_d_read_token;
-static ID id_d_next_state;
-static ID id_d_e_pop;
-
-/* -----------------------------------------------------------------------
- Utils
------------------------------------------------------------------------ */
-
-/* For backward compatibility */
-#ifndef ID2SYM
-# define ID2SYM(i) ULONG2NUM(i)
-#endif
-#ifndef SYM2ID
-# define SYM2ID(v) ((ID)NUM2ULONG(v))
-#endif
-#ifndef SYMBOL_P
-# define SYMBOL_P(v) FIXNUM_P(v)
-#endif
-#ifndef LONG2NUM
-# define LONG2NUM(i) INT2NUM(i)
-#endif
-#if RUBY_VERSION_CODE >= 190
-# define HAVE_RB_BLOCK_CALL 1
-#endif
-
-static ID value_to_id _((VALUE v));
-static inline long num_to_long _((VALUE n));
-
-static ID
-value_to_id(VALUE v)
-{
- if (! SYMBOL_P(v)) {
- rb_raise(rb_eTypeError, "not symbol");
- }
- return SYM2ID(v);
-}
-
-static inline long
-num_to_long(VALUE n)
-{
- return NUM2LONG(n);
-}
-
-#define AREF(s, idx) \
- ((0 <= idx && idx < RARRAY(s)->len) ? RARRAY(s)->ptr[idx] : Qnil)
-
-/* -----------------------------------------------------------------------
- Parser Stack Interfaces
------------------------------------------------------------------------ */
-
-static VALUE get_stack_tail _((VALUE stack, long len));
-static void cut_stack_tail _((VALUE stack, long len));
-
-static VALUE
-get_stack_tail(VALUE stack, long len)
-{
- if (len < 0) return Qnil; /* system error */
- if (len > RARRAY(stack)->len) len = RARRAY(stack)->len;
- return rb_ary_new4(len, RARRAY(stack)->ptr + RARRAY(stack)->len - len);
-}
-
-static void
-cut_stack_tail(VALUE stack, long len)
-{
- while (len > 0) {
- rb_ary_pop(stack);
- len--;
- }
-}
-
-#define STACK_INIT_LEN 64
-#define NEW_STACK() rb_ary_new2(STACK_INIT_LEN)
-#define PUSH(s, i) rb_ary_store(s, RARRAY(s)->len, i)
-#define POP(s) rb_ary_pop(s)
-#define LAST_I(s) \
- ((RARRAY(s)->len > 0) ? RARRAY(s)->ptr[RARRAY(s)->len - 1] : Qnil)
-#define GET_TAIL(s, len) get_stack_tail(s, len)
-#define CUT_TAIL(s, len) cut_stack_tail(s, len)
-
-/* -----------------------------------------------------------------------
- struct cparse_params
------------------------------------------------------------------------ */
-
-struct cparse_params {
- VALUE value_v; /* VALUE version of this struct */
-
- VALUE parser; /* parser object */
-
- int lex_is_iterator;
- VALUE lexer; /* scanner object */
- ID lexmid; /* name of scanner method (must be an iterator) */
-
- /* State transition tables (immutable)
- Data structure is from Dragon Book 4.9 */
- /* action table */
- VALUE action_table;
- VALUE action_check;
- VALUE action_default;
- VALUE action_pointer;
- /* goto table */
- VALUE goto_table;
- VALUE goto_check;
- VALUE goto_default;
- VALUE goto_pointer;
-
- long nt_base; /* NonTerminal BASE index */
- VALUE reduce_table; /* reduce data table */
- VALUE token_table; /* token conversion table */
-
- /* parser stacks and parameters */
- VALUE state;
- long curstate;
- VALUE vstack;
- VALUE tstack;
- VALUE t;
- long shift_n;
- long reduce_n;
- long ruleno;
-
- long errstatus; /* nonzero in error recovering mode */
- long nerr; /* number of error */
-
- int use_result_var;
-
- VALUE retval; /* return value of parser routine */
- long fin; /* parse result status */
-#define CP_FIN_ACCEPT 1
-#define CP_FIN_EOT 2
-#define CP_FIN_CANTPOP 3
-
- int debug; /* user level debug */
- int sys_debug; /* system level debug */
-
- long i; /* table index */
-};
-
-/* -----------------------------------------------------------------------
- Parser Main Routines
------------------------------------------------------------------------ */
-
-static VALUE racc_cparse _((VALUE parser, VALUE arg, VALUE sysdebug));
-static VALUE racc_yyparse _((VALUE parser, VALUE lexer, VALUE lexmid,
- VALUE arg, VALUE sysdebug));
-
-static void call_lexer _((struct cparse_params *v));
-static VALUE lexer_i _((VALUE block_args, VALUE data, VALUE self));
-
-static VALUE assert_array _((VALUE a));
-static long assert_integer _((VALUE n));
-static VALUE assert_hash _((VALUE h));
-static VALUE initialize_params _((VALUE vparams, VALUE parser, VALUE arg,
- VALUE lexer, VALUE lexmid));
-static void cparse_params_mark _((void *ptr));
-
-static void parse_main _((struct cparse_params *v,
- VALUE tok, VALUE val, int resume));
-static void extract_user_token _((struct cparse_params *v,
- VALUE block_args, VALUE *tok, VALUE *val));
-static void shift _((struct cparse_params* v, long act, VALUE tok, VALUE val));
-static int reduce _((struct cparse_params* v, long act));
-static VALUE reduce0 _((VALUE block_args, VALUE data, VALUE self));
-
-#ifdef DEBUG
-# define D_puts(msg) if (v->sys_debug) puts(msg)
-# define D_printf(fmt,arg) if (v->sys_debug) printf(fmt,arg)
-#else
-# define D_puts(msg)
-# define D_printf(fmt,arg)
-#endif
-
-static VALUE
-racc_cparse(VALUE parser, VALUE arg, VALUE sysdebug)
-{
- volatile VALUE vparams;
- struct cparse_params *v;
-
- vparams = Data_Make_Struct(CparseParams, struct cparse_params,
- cparse_params_mark, -1, v);
- D_puts("starting cparse");
- v->sys_debug = RTEST(sysdebug);
- vparams = initialize_params(vparams, parser, arg, Qnil, Qnil);
- v->lex_is_iterator = Qfalse;
- parse_main(v, Qnil, Qnil, 0);
-
- return v->retval;
-}
-
-static VALUE
-racc_yyparse(VALUE parser, VALUE lexer, VALUE lexmid, VALUE arg, VALUE sysdebug)
-{
- volatile VALUE vparams;
- struct cparse_params *v;
-
- vparams = Data_Make_Struct(CparseParams, struct cparse_params,
- cparse_params_mark, -1, v);
- v->sys_debug = RTEST(sysdebug);
- D_puts("start C yyparse");
- vparams = initialize_params(vparams, parser, arg, lexer, lexmid);
- v->lex_is_iterator = Qtrue;
- D_puts("params initialized");
- parse_main(v, Qnil, Qnil, 0);
- call_lexer(v);
- if (!v->fin) {
- rb_raise(rb_eArgError, "%s() is finished before EndOfToken",
- rb_id2name(v->lexmid));
- }
-
- return v->retval;
-}
-
-#ifdef HAVE_RB_BLOCK_CALL
-static void
-call_lexer(struct cparse_params *v)
-{
- rb_block_call(v->lexer, v->lexmid, 0, NULL, lexer_i, v->value_v);
-}
-#else
-static VALUE
-lexer_iter(VALUE data)
-{
- struct cparse_params *v;
-
- Data_Get_Struct(data, struct cparse_params, v);
- rb_funcall(v->lexer, v->lexmid, 0);
- return Qnil;
-}
-
-static void
-call_lexer(struct cparse_params *v)
-{
- rb_iterate(lexer_iter, v->value_v, lexer_i, v->value_v);
-}
-#endif
-
-static VALUE
-lexer_i(VALUE block_args, VALUE data, VALUE self)
-{
- struct cparse_params *v;
- VALUE tok, val;
-
- Data_Get_Struct(data, struct cparse_params, v);
- if (v->fin)
- rb_raise(rb_eArgError, "extra token after EndOfToken");
- extract_user_token(v, block_args, &tok, &val);
- parse_main(v, tok, val, 1);
- if (v->fin && v->fin != CP_FIN_ACCEPT)
- rb_iter_break();
- return Qnil;
-}
-
-static VALUE
-assert_array(VALUE a)
-{
- Check_Type(a, T_ARRAY);
- return a;
-}
-
-static VALUE
-assert_hash(VALUE h)
-{
- Check_Type(h, T_HASH);
- return h;
-}
-
-static long
-assert_integer(VALUE n)
-{
- return NUM2LONG(n);
-}
-
-static VALUE
-initialize_params(VALUE vparams, VALUE parser, VALUE arg, VALUE lexer, VALUE lexmid)
-{
- struct cparse_params *v;
-
- Data_Get_Struct(vparams, struct cparse_params, v);
- v->value_v = vparams;
- v->parser = parser;
- v->lexer = lexer;
- if (! NIL_P(lexmid))
- v->lexmid = value_to_id(lexmid);
-
- v->debug = RTEST(rb_ivar_get(parser, id_yydebug));
-
- Check_Type(arg, T_ARRAY);
- if (!(13 <= RARRAY(arg)->len && RARRAY(arg)->len <= 14))
- rb_raise(RaccBug, "[Racc Bug] wrong arg.size %ld", RARRAY(arg)->len);
- v->action_table = assert_array (RARRAY(arg)->ptr[ 0]);
- v->action_check = assert_array (RARRAY(arg)->ptr[ 1]);
- v->action_default = assert_array (RARRAY(arg)->ptr[ 2]);
- v->action_pointer = assert_array (RARRAY(arg)->ptr[ 3]);
- v->goto_table = assert_array (RARRAY(arg)->ptr[ 4]);
- v->goto_check = assert_array (RARRAY(arg)->ptr[ 5]);
- v->goto_default = assert_array (RARRAY(arg)->ptr[ 6]);
- v->goto_pointer = assert_array (RARRAY(arg)->ptr[ 7]);
- v->nt_base = assert_integer(RARRAY(arg)->ptr[ 8]);
- v->reduce_table = assert_array (RARRAY(arg)->ptr[ 9]);
- v->token_table = assert_hash (RARRAY(arg)->ptr[10]);
- v->shift_n = assert_integer(RARRAY(arg)->ptr[11]);
- v->reduce_n = assert_integer(RARRAY(arg)->ptr[12]);
- if (RARRAY(arg)->len > 13) {
- v->use_result_var = RTEST(RARRAY(arg)->ptr[13]);
- }
- else {
- v->use_result_var = Qtrue;
- }
-
- v->tstack = v->debug ? NEW_STACK() : Qnil;
- v->vstack = NEW_STACK();
- v->state = NEW_STACK();
- v->curstate = 0;
- PUSH(v->state, INT2FIX(0));
- v->t = INT2FIX(FINAL_TOKEN + 1); /* must not init to FINAL_TOKEN */
- v->nerr = 0;
- v->errstatus = 0;
- rb_ivar_set(parser, id_errstatus, LONG2NUM(v->errstatus));
-
- v->retval = Qnil;
- v->fin = 0;
-
- v->lex_is_iterator = Qfalse;
-
- rb_iv_set(parser, "@vstack", v->vstack);
- if (v->debug) {
- rb_iv_set(parser, "@tstack", v->tstack);
- }
- else {
- rb_iv_set(parser, "@tstack", Qnil);
- }
-
- return vparams;
-}
-
-static void
-cparse_params_mark(void *ptr)
-{
- struct cparse_params *v = (struct cparse_params*)ptr;
-
- rb_gc_mark(v->value_v);
- rb_gc_mark(v->parser);
- rb_gc_mark(v->lexer);
- rb_gc_mark(v->action_table);
- rb_gc_mark(v->action_check);
- rb_gc_mark(v->action_default);
- rb_gc_mark(v->action_pointer);
- rb_gc_mark(v->goto_table);
- rb_gc_mark(v->goto_check);
- rb_gc_mark(v->goto_default);
- rb_gc_mark(v->goto_pointer);
- rb_gc_mark(v->goto_pointer);
- rb_gc_mark(v->goto_pointer);
- rb_gc_mark(v->goto_pointer);
- rb_gc_mark(v->goto_pointer);
- rb_gc_mark(v->reduce_table);
- rb_gc_mark(v->token_table);
- rb_gc_mark(v->state);
- rb_gc_mark(v->vstack);
- rb_gc_mark(v->tstack);
- rb_gc_mark(v->t);
- rb_gc_mark(v->retval);
-}
-
-static void
-extract_user_token(struct cparse_params *v, VALUE block_args,
- VALUE *tok, VALUE *val)
-{
- if (NIL_P(block_args)) {
- /* EOF */
- *tok = Qfalse;
- *val = rb_str_new("$", 1);
- return;
- }
-
- if (TYPE(block_args) != T_ARRAY) {
- rb_raise(rb_eTypeError,
- "%s() %s %s (must be Array[2])",
- v->lex_is_iterator ? rb_id2name(v->lexmid) : "next_token",
- v->lex_is_iterator ? "yielded" : "returned",
- rb_class2name(CLASS_OF(block_args)));
- }
- if (RARRAY(block_args)->len != 2) {
- rb_raise(rb_eArgError,
- "%s() %s wrong size of array (%ld for 2)",
- v->lex_is_iterator ? rb_id2name(v->lexmid) : "next_token",
- v->lex_is_iterator ? "yielded" : "returned",
- RARRAY(block_args)->len);
- }
- *tok = AREF(block_args, 0);
- *val = AREF(block_args, 1);
-}
-
-#define SHIFT(v,act,tok,val) shift(v,act,tok,val)
-#define REDUCE(v,act) do {\
- switch (reduce(v,act)) { \
- case 0: /* normal */ \
- break; \
- case 1: /* yyerror */ \
- goto user_yyerror; \
- case 2: /* yyaccept */ \
- D_puts("u accept"); \
- goto accept; \
- default: \
- break; \
- } \
-} while (0)
-
-static void
-parse_main(struct cparse_params *v, VALUE tok, VALUE val, int resume)
-{
- long i; /* table index */
- long act; /* action type */
- VALUE act_value; /* action type, VALUE version */
- int read_next = 1; /* true if we need to read next token */
- VALUE tmp;
-
- if (resume)
- goto resume;
-
- while (1) {
- D_puts("");
- D_puts("---- enter new loop ----");
- D_puts("");
-
- D_printf("(act) k1=%ld\n", v->curstate);
- tmp = AREF(v->action_pointer, v->curstate);
- if (NIL_P(tmp)) goto notfound;
- D_puts("(act) pointer[k1] ok");
- i = NUM2LONG(tmp);
-
- D_printf("read_next=%d\n", read_next);
- if (read_next && (v->t != vFINAL_TOKEN)) {
- if (v->lex_is_iterator) {
- D_puts("resuming...");
- if (v->fin) rb_raise(rb_eArgError, "token given after EOF");
- v->i = i; /* save i */
- return;
- resume:
- D_puts("resumed");
- i = v->i; /* load i */
- }
- else {
- D_puts("next_token");
- tmp = rb_funcall(v->parser, id_nexttoken, 0);
- extract_user_token(v, tmp, &tok, &val);
- }
- /* convert token */
- v->t = rb_hash_aref(v->token_table, tok);
- if (NIL_P(v->t)) {
- v->t = vERROR_TOKEN;
- }
- D_printf("(act) t(k2)=%ld\n", NUM2LONG(v->t));
- if (v->debug) {
- rb_funcall(v->parser, id_d_read_token,
- 3, v->t, tok, val);
- }
- }
- read_next = 0;
-
- i += NUM2LONG(v->t);
- D_printf("(act) i=%ld\n", i);
- if (i < 0) goto notfound;
-
- act_value = AREF(v->action_table, i);
- if (NIL_P(act_value)) goto notfound;
- act = NUM2LONG(act_value);
- D_printf("(act) table[i]=%ld\n", act);
-
- tmp = AREF(v->action_check, i);
- if (NIL_P(tmp)) goto notfound;
- if (NUM2LONG(tmp) != v->curstate) goto notfound;
- D_printf("(act) check[i]=%ld\n", NUM2LONG(tmp));
-
- D_puts("(act) found");
- act_fixed:
- D_printf("act=%ld\n", act);
- goto handle_act;
-
- notfound:
- D_puts("(act) not found: use default");
- act_value = AREF(v->action_default, v->curstate);
- act = NUM2LONG(act_value);
- goto act_fixed;
-
-
- handle_act:
- if (act > 0 && act < v->shift_n) {
- D_puts("shift");
- if (v->errstatus > 0) {
- v->errstatus--;
- rb_ivar_set(v->parser, id_errstatus, LONG2NUM(v->errstatus));
- }
- SHIFT(v, act, v->t, val);
- read_next = 1;
- }
- else if (act < 0 && act > -(v->reduce_n)) {
- D_puts("reduce");
- REDUCE(v, act);
- }
- else if (act == -(v->reduce_n)) {
- goto error;
- error_recovered:
- ; /* goto label requires stmt */
- }
- else if (act == v->shift_n) {
- D_puts("accept");
- goto accept;
- }
- else {
- rb_raise(RaccBug, "[Racc Bug] unknown act value %ld", act);
- }
-
- if (v->debug) {
- rb_funcall(v->parser, id_d_next_state,
- 2, LONG2NUM(v->curstate), v->state);
- }
- }
- /* not reach */
-
-
- accept:
- if (v->debug) rb_funcall(v->parser, id_d_accept, 0);
- v->retval = RARRAY(v->vstack)->ptr[0];
- v->fin = CP_FIN_ACCEPT;
- return;
-
-
- error:
- D_printf("error detected, status=%ld\n", v->errstatus);
- if (v->errstatus == 0) {
- v->nerr++;
- rb_funcall(v->parser, id_onerror,
- 3, v->t, val, v->vstack);
- }
- user_yyerror:
- if (v->errstatus == 3) {
- if (v->t == vFINAL_TOKEN) {
- v->retval = Qfalse;
- v->fin = CP_FIN_EOT;
- return;
- }
- read_next = 1;
- }
- v->errstatus = 3;
- rb_ivar_set(v->parser, id_errstatus, LONG2NUM(v->errstatus));
-
- /* check if we can shift/reduce error token */
- D_printf("(err) k1=%ld\n", v->curstate);
- D_printf("(err) k2=%d (error)\n", ERROR_TOKEN);
- while (1) {
- tmp = AREF(v->action_pointer, v->curstate);
- if (NIL_P(tmp)) goto error_pop;
- D_puts("(err) pointer[k1] ok");
-
- i = NUM2LONG(tmp) + ERROR_TOKEN;
- D_printf("(err) i=%ld\n", i);
- if (i < 0) goto error_pop;
-
- act_value = AREF(v->action_table, i);
- if (NIL_P(act_value)) {
- D_puts("(err) table[i] == nil");
- goto error_pop;
- }
- act = NUM2LONG(act_value);
- D_printf("(err) table[i]=%ld\n", act);
-
- tmp = AREF(v->action_check, i);
- if (NIL_P(tmp)) {
- D_puts("(err) check[i] == nil");
- goto error_pop;
- }
- if (NUM2LONG(tmp) != v->curstate) {
- D_puts("(err) check[i] != k1");
- goto error_pop;
- }
-
- D_puts("(err) found: can handle error token");
- break;
-
- error_pop:
- D_puts("(err) act not found: can't handle error token; pop");
-
- if (RARRAY(v->state)->len <= 1) {
- v->retval = Qnil;
- v->fin = CP_FIN_CANTPOP;
- return;
- }
- POP(v->state);
- POP(v->vstack);
- v->curstate = num_to_long(LAST_I(v->state));
- if (v->debug) {
- POP(v->tstack);
- rb_funcall(v->parser, id_d_e_pop,
- 3, v->state, v->tstack, v->vstack);
- }
- }
-
- /* shift/reduce error token */
- if (act > 0 && act < v->shift_n) {
- D_puts("e shift");
- SHIFT(v, act, ERROR_TOKEN, val);
- }
- else if (act < 0 && act > -(v->reduce_n)) {
- D_puts("e reduce");
- REDUCE(v, act);
- }
- else if (act == v->shift_n) {
- D_puts("e accept");
- goto accept;
- }
- else {
- rb_raise(RaccBug, "[Racc Bug] unknown act value %ld", act);
- }
- goto error_recovered;
-}
-
-static void
-shift(struct cparse_params *v, long act, VALUE tok, VALUE val)
-{
- PUSH(v->vstack, val);
- if (v->debug) {
- PUSH(v->tstack, tok);
- rb_funcall(v->parser, id_d_shift,
- 3, tok, v->tstack, v->vstack);
- }
- v->curstate = act;
- PUSH(v->state, LONG2NUM(v->curstate));
-}
-
-static int
-reduce(struct cparse_params *v, long act)
-{
- VALUE code;
- v->ruleno = -act * 3;
- code = rb_catch("racc_jump", reduce0, v->value_v);
- v->errstatus = num_to_long(rb_ivar_get(v->parser, id_errstatus));
- return NUM2INT(code);
-}
-
-static VALUE
-reduce0(VALUE val, VALUE data, VALUE self)
-{
- struct cparse_params *v;
- VALUE reduce_to, reduce_len, method_id;
- long len;
- ID mid;
- VALUE tmp, tmp_t = Qundef, tmp_v = Qundef;
- long i, k1, k2;
- VALUE goto_state;
-
- Data_Get_Struct(data, struct cparse_params, v);
- reduce_len = RARRAY(v->reduce_table)->ptr[v->ruleno];
- reduce_to = RARRAY(v->reduce_table)->ptr[v->ruleno+1];
- method_id = RARRAY(v->reduce_table)->ptr[v->ruleno+2];
- len = NUM2LONG(reduce_len);
- mid = value_to_id(method_id);
-
- /* call action */
- if (len == 0) {
- tmp = Qnil;
- if (mid != id_noreduce)
- tmp_v = rb_ary_new();
- if (v->debug)
- tmp_t = rb_ary_new();
- }
- else {
- if (mid != id_noreduce) {
- tmp_v = GET_TAIL(v->vstack, len);
- tmp = RARRAY(tmp_v)->ptr[0];
- }
- else {
- tmp = RARRAY(v->vstack)->ptr[ RARRAY(v->vstack)->len - len ];
- }
- CUT_TAIL(v->vstack, len);
- if (v->debug) {
- tmp_t = GET_TAIL(v->tstack, len);
- CUT_TAIL(v->tstack, len);
- }
- CUT_TAIL(v->state, len);
- }
- if (mid != id_noreduce) {
- if (v->use_result_var) {
- tmp = rb_funcall(v->parser, mid,
- 3, tmp_v, v->vstack, tmp);
- }
- else {
- tmp = rb_funcall(v->parser, mid,
- 2, tmp_v, v->vstack);
- }
- }
-
- /* then push result */
- PUSH(v->vstack, tmp);
- if (v->debug) {
- PUSH(v->tstack, reduce_to);
- rb_funcall(v->parser, id_d_reduce,
- 4, tmp_t, reduce_to, v->tstack, v->vstack);
- }
-
- /* calculate transition state */
- if (RARRAY(v->state)->len == 0)
- rb_raise(RaccBug, "state stack unexpectedly empty");
- k2 = num_to_long(LAST_I(v->state));
- k1 = num_to_long(reduce_to) - v->nt_base;
- D_printf("(goto) k1=%ld\n", k1);
- D_printf("(goto) k2=%ld\n", k2);
-
- tmp = AREF(v->goto_pointer, k1);
- if (NIL_P(tmp)) goto notfound;
-
- i = NUM2LONG(tmp) + k2;
- D_printf("(goto) i=%ld\n", i);
- if (i < 0) goto notfound;
-
- goto_state = AREF(v->goto_table, i);
- if (NIL_P(goto_state)) {
- D_puts("(goto) table[i] == nil");
- goto notfound;
- }
- D_printf("(goto) table[i]=%ld (goto_state)\n", NUM2LONG(goto_state));
-
- tmp = AREF(v->goto_check, i);
- if (NIL_P(tmp)) {
- D_puts("(goto) check[i] == nil");
- goto notfound;
- }
- if (tmp != LONG2NUM(k1)) {
- D_puts("(goto) check[i] != table[i]");
- goto notfound;
- }
- D_printf("(goto) check[i]=%ld\n", NUM2LONG(tmp));
-
- D_puts("(goto) found");
- transit:
- PUSH(v->state, goto_state);
- v->curstate = NUM2LONG(goto_state);
- return INT2FIX(0);
-
- notfound:
- D_puts("(goto) not found: use default");
- /* overwrite `goto-state' by default value */
- goto_state = AREF(v->goto_default, k1);
- goto transit;
-}
-
-/* -----------------------------------------------------------------------
- Ruby Interface
------------------------------------------------------------------------ */
-
-void
-Init_cparse(void)
-{
- VALUE Racc, Parser;
- ID id_racc = rb_intern("Racc");
-
- if (rb_const_defined(rb_cObject, id_racc)) {
- Racc = rb_const_get(rb_cObject, id_racc);
- Parser = rb_const_get_at(Racc, rb_intern("Parser"));
- }
- else {
- Racc = rb_define_module("Racc");
- Parser = rb_define_class_under(Racc, "Parser", rb_cObject);
- }
- rb_define_private_method(Parser, "_racc_do_parse_c", racc_cparse, 2);
- rb_define_private_method(Parser, "_racc_yyparse_c", racc_yyparse, 4);
- rb_define_const(Parser, "Racc_Runtime_Core_Version_C",
- rb_str_new2(RACC_VERSION));
- rb_define_const(Parser, "Racc_Runtime_Core_Id_C",
- rb_str_new2("$originalId: cparse.c,v 1.8 2006/07/06 11:39:46 aamine Exp $"));
-
- CparseParams = rb_define_class_under(Racc, "CparseParams", rb_cObject);
-
- RaccBug = rb_eRuntimeError;
-
- id_yydebug = rb_intern("@yydebug");
- id_nexttoken = rb_intern("next_token");
- id_onerror = rb_intern("on_error");
- id_noreduce = rb_intern("_reduce_none");
- id_errstatus = rb_intern("@racc_error_status");
-
- id_d_shift = rb_intern("racc_shift");
- id_d_reduce = rb_intern("racc_reduce");
- id_d_accept = rb_intern("racc_accept");
- id_d_read_token = rb_intern("racc_read_token");
- id_d_next_state = rb_intern("racc_next_state");
- id_d_e_pop = rb_intern("racc_e_pop");
-}
diff --git a/ext/racc/cparse/depend b/ext/racc/cparse/depend
deleted file mode 100644
index 7b06a880f5..0000000000
--- a/ext/racc/cparse/depend
+++ /dev/null
@@ -1 +0,0 @@
-cparse.o: cparse.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/racc/cparse/extconf.rb b/ext/racc/cparse/extconf.rb
deleted file mode 100644
index dd953a7e15..0000000000
--- a/ext/racc/cparse/extconf.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-# $Id$
-
-require 'mkmf'
-create_makefile 'racc/cparse'
diff --git a/ext/rbconfig/sizeof/depend b/ext/rbconfig/sizeof/depend
new file mode 100644
index 0000000000..7e6c950769
--- /dev/null
+++ b/ext/rbconfig/sizeof/depend
@@ -0,0 +1,337 @@
+# sources
+
+limits.c: $(top_srcdir)/tool/generic_erb.rb $(top_srcdir)/template/limits.c.tmpl
+ $(Q) $(RUBY) $(top_srcdir)/tool/generic_erb.rb --output=$@ \
+ $(top_srcdir)/template/limits.c.tmpl \
+
+sizes.c: $(top_srcdir)/tool/generic_erb.rb \
+ $(top_srcdir)/template/sizes.c.tmpl \
+ $(top_srcdir)/configure.ac \
+ $(top_srcdir)/ext/rbconfig/sizeof/extconf.rb
+ $(Q) $(RUBY) $(top_srcdir)/tool/generic_erb.rb --output=$@ \
+ $(top_srcdir)/template/sizes.c.tmpl \
+ $(top_srcdir)/configure.ac \
+ $(top_srcdir)/ext/rbconfig/sizeof/extconf.rb
+
+# AUTOGENERATED DEPENDENCIES START
+limits.o: $(RUBY_EXTCONF_H)
+limits.o: $(arch_hdrdir)/ruby/config.h
+limits.o: $(hdrdir)/ruby/assert.h
+limits.o: $(hdrdir)/ruby/backward.h
+limits.o: $(hdrdir)/ruby/backward/2/assume.h
+limits.o: $(hdrdir)/ruby/backward/2/attributes.h
+limits.o: $(hdrdir)/ruby/backward/2/bool.h
+limits.o: $(hdrdir)/ruby/backward/2/inttypes.h
+limits.o: $(hdrdir)/ruby/backward/2/limits.h
+limits.o: $(hdrdir)/ruby/backward/2/long_long.h
+limits.o: $(hdrdir)/ruby/backward/2/stdalign.h
+limits.o: $(hdrdir)/ruby/backward/2/stdarg.h
+limits.o: $(hdrdir)/ruby/defines.h
+limits.o: $(hdrdir)/ruby/intern.h
+limits.o: $(hdrdir)/ruby/internal/abi.h
+limits.o: $(hdrdir)/ruby/internal/anyargs.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+limits.o: $(hdrdir)/ruby/internal/assume.h
+limits.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+limits.o: $(hdrdir)/ruby/internal/attr/artificial.h
+limits.o: $(hdrdir)/ruby/internal/attr/cold.h
+limits.o: $(hdrdir)/ruby/internal/attr/const.h
+limits.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+limits.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+limits.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+limits.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+limits.o: $(hdrdir)/ruby/internal/attr/error.h
+limits.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+limits.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+limits.o: $(hdrdir)/ruby/internal/attr/format.h
+limits.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+limits.o: $(hdrdir)/ruby/internal/attr/noalias.h
+limits.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+limits.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+limits.o: $(hdrdir)/ruby/internal/attr/noinline.h
+limits.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+limits.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+limits.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+limits.o: $(hdrdir)/ruby/internal/attr/pure.h
+limits.o: $(hdrdir)/ruby/internal/attr/restrict.h
+limits.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+limits.o: $(hdrdir)/ruby/internal/attr/warning.h
+limits.o: $(hdrdir)/ruby/internal/attr/weakref.h
+limits.o: $(hdrdir)/ruby/internal/cast.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+limits.o: $(hdrdir)/ruby/internal/compiler_since.h
+limits.o: $(hdrdir)/ruby/internal/config.h
+limits.o: $(hdrdir)/ruby/internal/constant_p.h
+limits.o: $(hdrdir)/ruby/internal/core.h
+limits.o: $(hdrdir)/ruby/internal/core/rarray.h
+limits.o: $(hdrdir)/ruby/internal/core/rbasic.h
+limits.o: $(hdrdir)/ruby/internal/core/rbignum.h
+limits.o: $(hdrdir)/ruby/internal/core/rclass.h
+limits.o: $(hdrdir)/ruby/internal/core/rdata.h
+limits.o: $(hdrdir)/ruby/internal/core/rfile.h
+limits.o: $(hdrdir)/ruby/internal/core/rhash.h
+limits.o: $(hdrdir)/ruby/internal/core/robject.h
+limits.o: $(hdrdir)/ruby/internal/core/rregexp.h
+limits.o: $(hdrdir)/ruby/internal/core/rstring.h
+limits.o: $(hdrdir)/ruby/internal/core/rstruct.h
+limits.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+limits.o: $(hdrdir)/ruby/internal/ctype.h
+limits.o: $(hdrdir)/ruby/internal/dllexport.h
+limits.o: $(hdrdir)/ruby/internal/dosish.h
+limits.o: $(hdrdir)/ruby/internal/error.h
+limits.o: $(hdrdir)/ruby/internal/eval.h
+limits.o: $(hdrdir)/ruby/internal/event.h
+limits.o: $(hdrdir)/ruby/internal/fl_type.h
+limits.o: $(hdrdir)/ruby/internal/gc.h
+limits.o: $(hdrdir)/ruby/internal/glob.h
+limits.o: $(hdrdir)/ruby/internal/globals.h
+limits.o: $(hdrdir)/ruby/internal/has/attribute.h
+limits.o: $(hdrdir)/ruby/internal/has/builtin.h
+limits.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+limits.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+limits.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+limits.o: $(hdrdir)/ruby/internal/has/extension.h
+limits.o: $(hdrdir)/ruby/internal/has/feature.h
+limits.o: $(hdrdir)/ruby/internal/has/warning.h
+limits.o: $(hdrdir)/ruby/internal/intern/array.h
+limits.o: $(hdrdir)/ruby/internal/intern/bignum.h
+limits.o: $(hdrdir)/ruby/internal/intern/class.h
+limits.o: $(hdrdir)/ruby/internal/intern/compar.h
+limits.o: $(hdrdir)/ruby/internal/intern/complex.h
+limits.o: $(hdrdir)/ruby/internal/intern/cont.h
+limits.o: $(hdrdir)/ruby/internal/intern/dir.h
+limits.o: $(hdrdir)/ruby/internal/intern/enum.h
+limits.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+limits.o: $(hdrdir)/ruby/internal/intern/error.h
+limits.o: $(hdrdir)/ruby/internal/intern/eval.h
+limits.o: $(hdrdir)/ruby/internal/intern/file.h
+limits.o: $(hdrdir)/ruby/internal/intern/hash.h
+limits.o: $(hdrdir)/ruby/internal/intern/io.h
+limits.o: $(hdrdir)/ruby/internal/intern/load.h
+limits.o: $(hdrdir)/ruby/internal/intern/marshal.h
+limits.o: $(hdrdir)/ruby/internal/intern/numeric.h
+limits.o: $(hdrdir)/ruby/internal/intern/object.h
+limits.o: $(hdrdir)/ruby/internal/intern/parse.h
+limits.o: $(hdrdir)/ruby/internal/intern/proc.h
+limits.o: $(hdrdir)/ruby/internal/intern/process.h
+limits.o: $(hdrdir)/ruby/internal/intern/random.h
+limits.o: $(hdrdir)/ruby/internal/intern/range.h
+limits.o: $(hdrdir)/ruby/internal/intern/rational.h
+limits.o: $(hdrdir)/ruby/internal/intern/re.h
+limits.o: $(hdrdir)/ruby/internal/intern/ruby.h
+limits.o: $(hdrdir)/ruby/internal/intern/select.h
+limits.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+limits.o: $(hdrdir)/ruby/internal/intern/set.h
+limits.o: $(hdrdir)/ruby/internal/intern/signal.h
+limits.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+limits.o: $(hdrdir)/ruby/internal/intern/string.h
+limits.o: $(hdrdir)/ruby/internal/intern/struct.h
+limits.o: $(hdrdir)/ruby/internal/intern/thread.h
+limits.o: $(hdrdir)/ruby/internal/intern/time.h
+limits.o: $(hdrdir)/ruby/internal/intern/variable.h
+limits.o: $(hdrdir)/ruby/internal/intern/vm.h
+limits.o: $(hdrdir)/ruby/internal/interpreter.h
+limits.o: $(hdrdir)/ruby/internal/iterator.h
+limits.o: $(hdrdir)/ruby/internal/memory.h
+limits.o: $(hdrdir)/ruby/internal/method.h
+limits.o: $(hdrdir)/ruby/internal/module.h
+limits.o: $(hdrdir)/ruby/internal/newobj.h
+limits.o: $(hdrdir)/ruby/internal/scan_args.h
+limits.o: $(hdrdir)/ruby/internal/special_consts.h
+limits.o: $(hdrdir)/ruby/internal/static_assert.h
+limits.o: $(hdrdir)/ruby/internal/stdalign.h
+limits.o: $(hdrdir)/ruby/internal/stdbool.h
+limits.o: $(hdrdir)/ruby/internal/stdckdint.h
+limits.o: $(hdrdir)/ruby/internal/symbol.h
+limits.o: $(hdrdir)/ruby/internal/value.h
+limits.o: $(hdrdir)/ruby/internal/value_type.h
+limits.o: $(hdrdir)/ruby/internal/variable.h
+limits.o: $(hdrdir)/ruby/internal/warning_push.h
+limits.o: $(hdrdir)/ruby/internal/xmalloc.h
+limits.o: $(hdrdir)/ruby/missing.h
+limits.o: $(hdrdir)/ruby/ruby.h
+limits.o: $(hdrdir)/ruby/st.h
+limits.o: $(hdrdir)/ruby/subst.h
+limits.o: limits.c
+sizes.o: $(RUBY_EXTCONF_H)
+sizes.o: $(arch_hdrdir)/ruby/config.h
+sizes.o: $(hdrdir)/ruby/assert.h
+sizes.o: $(hdrdir)/ruby/backward.h
+sizes.o: $(hdrdir)/ruby/backward/2/assume.h
+sizes.o: $(hdrdir)/ruby/backward/2/attributes.h
+sizes.o: $(hdrdir)/ruby/backward/2/bool.h
+sizes.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sizes.o: $(hdrdir)/ruby/backward/2/limits.h
+sizes.o: $(hdrdir)/ruby/backward/2/long_long.h
+sizes.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sizes.o: $(hdrdir)/ruby/backward/2/stdarg.h
+sizes.o: $(hdrdir)/ruby/defines.h
+sizes.o: $(hdrdir)/ruby/intern.h
+sizes.o: $(hdrdir)/ruby/internal/abi.h
+sizes.o: $(hdrdir)/ruby/internal/anyargs.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sizes.o: $(hdrdir)/ruby/internal/assume.h
+sizes.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sizes.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sizes.o: $(hdrdir)/ruby/internal/attr/cold.h
+sizes.o: $(hdrdir)/ruby/internal/attr/const.h
+sizes.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sizes.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sizes.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sizes.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sizes.o: $(hdrdir)/ruby/internal/attr/error.h
+sizes.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sizes.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sizes.o: $(hdrdir)/ruby/internal/attr/format.h
+sizes.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sizes.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sizes.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sizes.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sizes.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sizes.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sizes.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sizes.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+sizes.o: $(hdrdir)/ruby/internal/attr/pure.h
+sizes.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sizes.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sizes.o: $(hdrdir)/ruby/internal/attr/warning.h
+sizes.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sizes.o: $(hdrdir)/ruby/internal/cast.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_since.h
+sizes.o: $(hdrdir)/ruby/internal/config.h
+sizes.o: $(hdrdir)/ruby/internal/constant_p.h
+sizes.o: $(hdrdir)/ruby/internal/core.h
+sizes.o: $(hdrdir)/ruby/internal/core/rarray.h
+sizes.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sizes.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sizes.o: $(hdrdir)/ruby/internal/core/rclass.h
+sizes.o: $(hdrdir)/ruby/internal/core/rdata.h
+sizes.o: $(hdrdir)/ruby/internal/core/rfile.h
+sizes.o: $(hdrdir)/ruby/internal/core/rhash.h
+sizes.o: $(hdrdir)/ruby/internal/core/robject.h
+sizes.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sizes.o: $(hdrdir)/ruby/internal/core/rstring.h
+sizes.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sizes.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sizes.o: $(hdrdir)/ruby/internal/ctype.h
+sizes.o: $(hdrdir)/ruby/internal/dllexport.h
+sizes.o: $(hdrdir)/ruby/internal/dosish.h
+sizes.o: $(hdrdir)/ruby/internal/error.h
+sizes.o: $(hdrdir)/ruby/internal/eval.h
+sizes.o: $(hdrdir)/ruby/internal/event.h
+sizes.o: $(hdrdir)/ruby/internal/fl_type.h
+sizes.o: $(hdrdir)/ruby/internal/gc.h
+sizes.o: $(hdrdir)/ruby/internal/glob.h
+sizes.o: $(hdrdir)/ruby/internal/globals.h
+sizes.o: $(hdrdir)/ruby/internal/has/attribute.h
+sizes.o: $(hdrdir)/ruby/internal/has/builtin.h
+sizes.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sizes.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sizes.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sizes.o: $(hdrdir)/ruby/internal/has/extension.h
+sizes.o: $(hdrdir)/ruby/internal/has/feature.h
+sizes.o: $(hdrdir)/ruby/internal/has/warning.h
+sizes.o: $(hdrdir)/ruby/internal/intern/array.h
+sizes.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sizes.o: $(hdrdir)/ruby/internal/intern/class.h
+sizes.o: $(hdrdir)/ruby/internal/intern/compar.h
+sizes.o: $(hdrdir)/ruby/internal/intern/complex.h
+sizes.o: $(hdrdir)/ruby/internal/intern/cont.h
+sizes.o: $(hdrdir)/ruby/internal/intern/dir.h
+sizes.o: $(hdrdir)/ruby/internal/intern/enum.h
+sizes.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sizes.o: $(hdrdir)/ruby/internal/intern/error.h
+sizes.o: $(hdrdir)/ruby/internal/intern/eval.h
+sizes.o: $(hdrdir)/ruby/internal/intern/file.h
+sizes.o: $(hdrdir)/ruby/internal/intern/hash.h
+sizes.o: $(hdrdir)/ruby/internal/intern/io.h
+sizes.o: $(hdrdir)/ruby/internal/intern/load.h
+sizes.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sizes.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sizes.o: $(hdrdir)/ruby/internal/intern/object.h
+sizes.o: $(hdrdir)/ruby/internal/intern/parse.h
+sizes.o: $(hdrdir)/ruby/internal/intern/proc.h
+sizes.o: $(hdrdir)/ruby/internal/intern/process.h
+sizes.o: $(hdrdir)/ruby/internal/intern/random.h
+sizes.o: $(hdrdir)/ruby/internal/intern/range.h
+sizes.o: $(hdrdir)/ruby/internal/intern/rational.h
+sizes.o: $(hdrdir)/ruby/internal/intern/re.h
+sizes.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sizes.o: $(hdrdir)/ruby/internal/intern/select.h
+sizes.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sizes.o: $(hdrdir)/ruby/internal/intern/set.h
+sizes.o: $(hdrdir)/ruby/internal/intern/signal.h
+sizes.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sizes.o: $(hdrdir)/ruby/internal/intern/string.h
+sizes.o: $(hdrdir)/ruby/internal/intern/struct.h
+sizes.o: $(hdrdir)/ruby/internal/intern/thread.h
+sizes.o: $(hdrdir)/ruby/internal/intern/time.h
+sizes.o: $(hdrdir)/ruby/internal/intern/variable.h
+sizes.o: $(hdrdir)/ruby/internal/intern/vm.h
+sizes.o: $(hdrdir)/ruby/internal/interpreter.h
+sizes.o: $(hdrdir)/ruby/internal/iterator.h
+sizes.o: $(hdrdir)/ruby/internal/memory.h
+sizes.o: $(hdrdir)/ruby/internal/method.h
+sizes.o: $(hdrdir)/ruby/internal/module.h
+sizes.o: $(hdrdir)/ruby/internal/newobj.h
+sizes.o: $(hdrdir)/ruby/internal/scan_args.h
+sizes.o: $(hdrdir)/ruby/internal/special_consts.h
+sizes.o: $(hdrdir)/ruby/internal/static_assert.h
+sizes.o: $(hdrdir)/ruby/internal/stdalign.h
+sizes.o: $(hdrdir)/ruby/internal/stdbool.h
+sizes.o: $(hdrdir)/ruby/internal/stdckdint.h
+sizes.o: $(hdrdir)/ruby/internal/symbol.h
+sizes.o: $(hdrdir)/ruby/internal/value.h
+sizes.o: $(hdrdir)/ruby/internal/value_type.h
+sizes.o: $(hdrdir)/ruby/internal/variable.h
+sizes.o: $(hdrdir)/ruby/internal/warning_push.h
+sizes.o: $(hdrdir)/ruby/internal/xmalloc.h
+sizes.o: $(hdrdir)/ruby/missing.h
+sizes.o: $(hdrdir)/ruby/ruby.h
+sizes.o: $(hdrdir)/ruby/st.h
+sizes.o: $(hdrdir)/ruby/subst.h
+sizes.o: {$(VPATH)}sizes.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/rbconfig/sizeof/extconf.rb b/ext/rbconfig/sizeof/extconf.rb
new file mode 100644
index 0000000000..f7cd58f2d9
--- /dev/null
+++ b/ext/rbconfig/sizeof/extconf.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: false
+$srcs = %w[sizes.c limits.c]
+$distcleanfiles.concat($srcs)
+
+have_type('int_least8_t')
+have_type('int_least16_t')
+have_type('int_least32_t')
+have_type('int_least64_t')
+have_type('int_fast8_t')
+have_type('int_fast16_t')
+have_type('int_fast32_t')
+have_type('int_fast64_t')
+have_type('intmax_t')
+have_type('sig_atomic_t', %w[signal.h])
+have_type('wchar_t')
+have_type('wint_t', %w[wctype.h])
+have_type('wctrans_t', %w[wctype.h])
+have_type('wctype_t', %w[wctype.h])
+have_type('_Bool')
+have_type('long double')
+have_type('float _Complex')
+have_type('double _Complex')
+have_type('long double _Complex')
+have_type('float _Imaginary')
+have_type('double _Imaginary')
+have_type('long double _Imaginary')
+have_type('__int128') # x86_64 ABI (optional)
+have_type('__float128') # x86_64 ABI (optional)
+have_type('_Decimal32') # x86_64 ABI
+have_type('_Decimal64') # x86_64 ABI
+have_type('_Decimal128') # x86_64 ABI
+have_type('__m64') # x86_64 ABI (optional)
+have_type('__m128') # x86_64 ABI (optional)
+have_type('__float80') # gcc x86
+
+create_makefile('rbconfig/sizeof')
diff --git a/ext/readline/.cvsignore b/ext/readline/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/readline/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/readline/README b/ext/readline/README
deleted file mode 100644
index 9bbf325c99..0000000000
--- a/ext/readline/README
+++ /dev/null
@@ -1,62 +0,0 @@
-Extension for GNU Readline Library
-
-Example:
-
- require "readline"
- include Readline
-
- line = readline("Prompt> ", true)
-
-[Readline]
-
-<module function>
-
-readline(prompt, add_history=nil)
-
- Reads one line with line editing. The inputted line is added to the
- history if add_history is true.
-
-<class methods>
-
-completion_proc = proc
-
- Specifies a Proc object to determine completion behavior. It
- should take input-string, and return an array of completion
- candidates.
-
-completion_proc
-
- Returns the completion Proc object.
-
-completion_case_fold = bool
-
- Sets whether or not to ignore case on completion.
-
-completion_case_fold
-
- Returns true if completion ignores case.
-
-completion_append_character = char
-
- Specifies a character to be appended on completion.
- Nothing will be appended if an empty string ("") or nil is
- specified.
-
-completion_append_character
-
- Returns a string containing a character to be appended on
- completion. The default is a space (" ").
-
-vi_editing_mode
-
- Specifies VI editing mode.
-
-emacs_editing_mode
-
- Specifies Emacs editing mode.
-
-<class constants>
-
-HISTORY
-
-The history buffer. It behaves just like an array.
diff --git a/ext/readline/README.ja b/ext/readline/README.ja
deleted file mode 100644
index beb951fbf0..0000000000
--- a/ext/readline/README.ja
+++ /dev/null
@@ -1,63 +0,0 @@
-GNU Readline Library¤òÍøÍѤ¹¤ë¤¿¤á¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ç¤¹¡£
-
-require "readline"
-include Readline
-
-line = readline("Prompt> ", true)
-
-¤Î¤è¤¦¤Ë»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤¡£
-
-[Readline]
-
-<¥â¥¸¥å¡¼¥ë´Ø¿ô>
-
-readline(prompt, add_history=nil)
-
- °ì¹ÔÆþÎϤòÆÉ¤ß¹þ¤ß¤Þ¤¹¡£
- add_history¤¬true¤Î¾ì¹ç¡¢¥Ò¥¹¥È¥ê¤ËÆÉ¤ß¹þ¤ó¤Àʸ»úÎó¤òÄɲä·¤Þ¤¹¡£
-
-<¥¯¥é¥¹¥á¥½¥Ã¥É>
-
-completion_proc = proc
-
- Êä´°»þ¤Îưºî¤ò·èÄꤹ¤ëProc¥ª¥Ö¥¸¥§¥¯¥È¤ò»ØÄꤷ¤Þ¤¹¡£
- proc¤Ï°ú¿ô¤ËÆþÎÏʸ»úÎó¤ò¼è¤ê¡¢¸õÊäʸ»úÎó¤ÎÇÛÎó¤òÊÖ¤¹¤è¤¦¤Ë
- ¤·¤Æ¤¯¤À¤µ¤¤¡£
-
-completion_proc
-
- Êä´°»þ¤Îưºî¤ò·èÄꤹ¤ëProc¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤·¤Þ¤¹¡£
-
-completion_case_fold = case_fold
-
- Êä´°»þ¤ËÂçʸ»ú¾®Ê¸»ú¤ò¶èÊ̤·¤Ê¤¤¾ì¹ç¡¢true¤ò»ØÄꤷ¤Þ¤¹¡£
-
-completion_case_fold
-
- Êä´°»þ¤ËÂçʸ»ú¾®Ê¸»ú¤ò¶èÊ̤·¤Ê¤¤¾ì¹ç¡¢true¤òÊÖ¤·¤Þ¤¹¡£
-
-completion_append_character = char
-
- Êä´°»þ¤ËÉղ䵤ì¤ëʸ»ú¤òʸ»úÎó¤Ç»ØÄꤷ¤Þ¤¹¡£ÀèÆ¬¤Î°ìʸ»ú¤¬
- ÀßÄꤵ¤ì¡¢¶õʸ»úÎó ("") ¤Þ¤¿¤Ï nil ¤ò»ØÄꤹ¤ë¤È²¿¤âÉÕ²Ã
- ¤µ¤ì¤Ê¤¯¤Ê¤ê¤Þ¤¹¡£
-
-completion_append_character
-
- Êä´°»þ¤ËÉղ䵤ì¤ëʸ»ú¤òʸ»úÎó¤ÇÊÖ¤·¤Þ¤¹¡£¥Ç¥Õ¥©¥ë¥È¤Ï
- ¶õÇò (" ") ¤Ç¤¹¡£
-
-vi_editing_mode
-
- VI¥â¡¼¥É¤Ë¤Ê¤ê¤Þ¤¹¡£
-
-emacs_editing_mode
-
- Emacs¥â¡¼¥É¤Ë¤Ê¤ê¤Þ¤¹¡£
-
-<¥¯¥é¥¹Äê¿ô>
-
-HISTORY
-
-¥Ò¥¹¥È¥ê¤ËÂФ¹¤ëÁàºî¤Ï¤³¤ÎÄê¿ô¤òÄ̤·¤Æ¹Ô¤Ã¤Æ¤¯¤À¤µ¤¤¡£
-ÇÛÎó¤ÈƱ¤¸¤è¤¦¤Ë°·¤¨¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£
diff --git a/ext/readline/depend b/ext/readline/depend
deleted file mode 100644
index 6570c5a036..0000000000
--- a/ext/readline/depend
+++ /dev/null
@@ -1 +0,0 @@
-readline.o: readline.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/readline/extconf.rb b/ext/readline/extconf.rb
deleted file mode 100644
index b67a443dad..0000000000
--- a/ext/readline/extconf.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-require "mkmf"
-
-$readline_headers = ["stdio.h"]
-
-def have_readline_header(header)
- if have_header(header)
- $readline_headers.push(header)
- return true
- else
- return false
- end
-end
-
-def have_readline_var(var)
- return have_var(var, $readline_headers)
-end
-
-dir_config('curses')
-dir_config('ncurses')
-dir_config('termcap')
-dir_config("readline")
-enable_libedit = enable_config("libedit")
-have_library("user32", nil) if /cygwin/ === RUBY_PLATFORM
-have_library("ncurses", "tgetnum") ||
- have_library("termcap", "tgetnum") ||
- have_library("curses", "tgetnum")
-
-if enable_libedit
- unless (have_readline_header("editline/readline.h") ||
- have_readline_header("readline/readline.h")) &&
- have_library("edit", "readline")
- exit
- end
-else
- unless ((have_readline_header("readline/readline.h") &&
- have_readline_header("readline/history.h")) &&
- (have_library("readline", "readline") ||
- have_library("edit", "readline"))) ||
- (have_readline_header("editline/readline.h") &&
- have_library("edit", "readline"))
- exit
- end
-end
-
-have_readline_var("rl_filename_completion_function")
-have_readline_var("rl_deprep_term_function")
-have_readline_var("rl_completion_append_character")
-have_readline_var("rl_basic_word_break_characters")
-have_readline_var("rl_completer_word_break_characters")
-have_readline_var("rl_basic_quote_characters")
-have_readline_var("rl_completer_quote_characters")
-have_readline_var("rl_filename_quote_characters")
-have_readline_var("rl_attempted_completion_over")
-have_readline_var("rl_library_version")
-have_readline_var("rl_event_hook")
-have_func("rl_cleanup_after_signal")
-have_func("rl_clear_signals")
-have_func("rl_vi_editing_mode")
-have_func("rl_emacs_editing_mode")
-have_func("rl_clear_signals")
-have_func("replace_history_entry")
-have_func("remove_history")
-create_makefile("readline")
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
deleted file mode 100644
index 4f840ee2c0..0000000000
--- a/ext/readline/readline.c
+++ /dev/null
@@ -1,820 +0,0 @@
-/* readline.c -- GNU Readline module
- Copyright (C) 1997-2001 Shugo Maeda */
-
-#include "config.h"
-#include <errno.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#ifdef HAVE_READLINE_READLINE_H
-#include <readline/readline.h>
-#endif
-#ifdef HAVE_READLINE_HISTORY_H
-#include <readline/history.h>
-#endif
-#ifdef HAVE_EDITLINE_READLINE_H
-#include <editline/readline.h>
-#endif
-
-#include "ruby.h"
-#include "rubyio.h"
-#include "rubysig.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-static VALUE mReadline;
-
-#define TOLOWER(c) (isupper(c) ? tolower(c) : c)
-
-#define COMPLETION_PROC "completion_proc"
-#define COMPLETION_CASE_FOLD "completion_case_fold"
-static ID completion_proc, completion_case_fold;
-
-#ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
-# define rl_filename_completion_function filename_completion_function
-# define rl_username_completion_function username_completion_function
-# define rl_completion_matches completion_matches
-#endif
-
-static int readline_event(void);
-static char **readline_attempted_completion_function(const char *text,
- int start, int end);
-
-static int
-readline_event()
-{
- CHECK_INTS;
- rb_thread_schedule();
- return 0;
-}
-
-static VALUE
-readline_readline(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE tmp, add_hist, result;
- char *prompt = NULL;
- char *buff;
- int status;
- OpenFile *ofp, *ifp;
-
- rb_secure(4);
- if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
- SafeStringValue(tmp);
- prompt = RSTRING(tmp)->ptr;
- }
-
- if (!isatty(0) && errno == EBADF) rb_raise(rb_eIOError, "stdin closed");
-
- Check_Type(rb_stdout, T_FILE);
- GetOpenFile(rb_stdout, ofp);
- rl_outstream = GetWriteFile(ofp);
- Check_Type(rb_stdin, T_FILE);
- GetOpenFile(rb_stdin, ifp);
- rl_instream = GetReadFile(ifp);
- buff = (char*)rb_protect((VALUE(*)_((VALUE)))readline, (VALUE)prompt,
- &status);
- if (status) {
-#if defined HAVE_RL_CLEANUP_AFTER_SIGNAL
- /* restore terminal mode and signal handler*/
- rl_cleanup_after_signal();
-#elif defined HAVE_RL_DEPREP_TERM_FUNCTION
- /* restore terminal mode */
- if (rl_deprep_term_function != NULL) /* NULL in libedit. [ruby-dev:29116] */
- (*rl_deprep_term_function)();
- else
-#else
- rl_deprep_terminal();
-#endif
- rb_jump_tag(status);
- }
-
- if (RTEST(add_hist) && buff) {
- add_history(buff);
- }
- if (buff)
- result = rb_tainted_str_new2(buff);
- else
- result = Qnil;
- if (buff) free(buff);
- return result;
-}
-
-static VALUE
-readline_s_set_completion_proc(self, proc)
- VALUE self;
- VALUE proc;
-{
- rb_secure(4);
- if (!rb_respond_to(proc, rb_intern("call")))
- rb_raise(rb_eArgError, "argument must respond to `call'");
- return rb_ivar_set(mReadline, completion_proc, proc);
-}
-
-static VALUE
-readline_s_get_completion_proc(self)
- VALUE self;
-{
- rb_secure(4);
- return rb_attr_get(mReadline, completion_proc);
-}
-
-static VALUE
-readline_s_set_completion_case_fold(self, val)
- VALUE self;
- VALUE val;
-{
- rb_secure(4);
- return rb_ivar_set(mReadline, completion_case_fold, val);
-}
-
-static VALUE
-readline_s_get_completion_case_fold(self)
- VALUE self;
-{
- rb_secure(4);
- return rb_attr_get(mReadline, completion_case_fold);
-}
-
-static char **
-readline_attempted_completion_function(text, start, end)
- const char *text;
- int start;
- int end;
-{
- VALUE proc, ary, temp;
- char **result;
- int case_fold;
- int i, matches;
-
- proc = rb_attr_get(mReadline, completion_proc);
- if (NIL_P(proc))
- return NULL;
-#ifdef HAVE_RL_ATTEMPTED_COMPLETION_OVER
- rl_attempted_completion_over = 1;
-#endif
- case_fold = RTEST(rb_attr_get(mReadline, completion_case_fold));
- ary = rb_funcall(proc, rb_intern("call"), 1, rb_tainted_str_new2(text));
- if (TYPE(ary) != T_ARRAY)
- ary = rb_Array(ary);
- matches = RARRAY(ary)->len;
- if (matches == 0)
- return NULL;
- result = ALLOC_N(char *, matches + 2);
- for (i = 0; i < matches; i++) {
- temp = rb_obj_as_string(RARRAY(ary)->ptr[i]);
- result[i + 1] = ALLOC_N(char, RSTRING(temp)->len + 1);
- strcpy(result[i + 1], RSTRING(temp)->ptr);
- }
- result[matches + 1] = NULL;
-
- if (matches == 1) {
- result[0] = strdup(result[1]);
- }
- else {
- register int i = 1;
- int low = 100000;
-
- while (i < matches) {
- register int c1, c2, si;
-
- if (case_fold) {
- for (si = 0;
- (c1 = TOLOWER(result[i][si])) &&
- (c2 = TOLOWER(result[i + 1][si]));
- si++)
- if (c1 != c2) break;
- } else {
- for (si = 0;
- (c1 = result[i][si]) &&
- (c2 = result[i + 1][si]);
- si++)
- if (c1 != c2) break;
- }
-
- if (low > si) low = si;
- i++;
- }
- result[0] = ALLOC_N(char, low + 1);
- strncpy(result[0], result[1], low);
- result[0][low] = '\0';
- }
-
- return result;
-}
-
-static VALUE
-readline_s_vi_editing_mode(self)
- VALUE self;
-{
-#ifdef HAVE_RL_VI_EDITING_MODE
- rb_secure(4);
- rl_vi_editing_mode(1,0);
- return Qnil;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_VI_EDITING_MODE */
-}
-
-static VALUE
-readline_s_emacs_editing_mode(self)
- VALUE self;
-{
-#ifdef HAVE_RL_EMACS_EDITING_MODE
- rb_secure(4);
- rl_emacs_editing_mode(1,0);
- return Qnil;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_EMACS_EDITING_MODE */
-}
-
-static VALUE
-readline_s_set_completion_append_character(self, str)
- VALUE self, str;
-{
-#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
- rb_secure(4);
- if (NIL_P(str)) {
- rl_completion_append_character = '\0';
- }
- else {
- SafeStringValue(str);
- if (RSTRING(str)->len == 0) {
- rl_completion_append_character = '\0';
- } else {
- rl_completion_append_character = RSTRING(str)->ptr[0];
- }
- }
- return self;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_COMPLETION_APPEND_CHARACTER */
-}
-
-static VALUE
-readline_s_get_completion_append_character(self)
- VALUE self;
-{
-#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
- VALUE str;
-
- rb_secure(4);
- if (rl_completion_append_character == '\0')
- return Qnil;
-
- str = rb_str_new("", 1);
- RSTRING(str)->ptr[0] = rl_completion_append_character;
- return str;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_COMPLETION_APPEND_CHARACTER */
-}
-
-static VALUE
-readline_s_set_basic_word_break_characters(self, str)
- VALUE self, str;
-{
-#ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
- static char *basic_word_break_characters = NULL;
-
- rb_secure(4);
- SafeStringValue(str);
- if (basic_word_break_characters == NULL) {
- basic_word_break_characters =
- ALLOC_N(char, RSTRING(str)->len + 1);
- }
- else {
- REALLOC_N(basic_word_break_characters, char, RSTRING(str)->len + 1);
- }
- strncpy(basic_word_break_characters,
- RSTRING(str)->ptr, RSTRING(str)->len);
- basic_word_break_characters[RSTRING(str)->len] = '\0';
- rl_basic_word_break_characters = basic_word_break_characters;
- return self;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_BASIC_WORD_BREAK_CHARACTERS */
-}
-
-static VALUE
-readline_s_get_basic_word_break_characters(self, str)
- VALUE self, str;
-{
-#ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
- rb_secure(4);
- if (rl_basic_word_break_characters == NULL)
- return Qnil;
- return rb_tainted_str_new2(rl_basic_word_break_characters);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_BASIC_WORD_BREAK_CHARACTERS */
-}
-
-static VALUE
-readline_s_set_completer_word_break_characters(self, str)
- VALUE self, str;
-{
-#ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
- static char *completer_word_break_characters = NULL;
-
- rb_secure(4);
- SafeStringValue(str);
- if (completer_word_break_characters == NULL) {
- completer_word_break_characters =
- ALLOC_N(char, RSTRING(str)->len + 1);
- }
- else {
- REALLOC_N(completer_word_break_characters, char, RSTRING(str)->len + 1);
- }
- strncpy(completer_word_break_characters,
- RSTRING(str)->ptr, RSTRING(str)->len);
- completer_word_break_characters[RSTRING(str)->len] = '\0';
- rl_completer_word_break_characters = completer_word_break_characters;
- return self;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS */
-}
-
-static VALUE
-readline_s_get_completer_word_break_characters(self, str)
- VALUE self, str;
-{
-#ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
- rb_secure(4);
- if (rl_completer_word_break_characters == NULL)
- return Qnil;
- return rb_tainted_str_new2(rl_completer_word_break_characters);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS */
-}
-
-static VALUE
-readline_s_set_basic_quote_characters(self, str)
- VALUE self, str;
-{
-#ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
- static char *basic_quote_characters = NULL;
-
- rb_secure(4);
- SafeStringValue(str);
- if (basic_quote_characters == NULL) {
- basic_quote_characters =
- ALLOC_N(char, RSTRING(str)->len + 1);
- }
- else {
- REALLOC_N(basic_quote_characters, char, RSTRING(str)->len + 1);
- }
- strncpy(basic_quote_characters,
- RSTRING(str)->ptr, RSTRING(str)->len);
- basic_quote_characters[RSTRING(str)->len] = '\0';
- rl_basic_quote_characters = basic_quote_characters;
-
- return self;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_BASIC_QUOTE_CHARACTERS */
-}
-
-static VALUE
-readline_s_get_basic_quote_characters(self, str)
- VALUE self, str;
-{
-#ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
- rb_secure(4);
- if (rl_basic_quote_characters == NULL)
- return Qnil;
- return rb_tainted_str_new2(rl_basic_quote_characters);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_BASIC_QUOTE_CHARACTERS */
-}
-
-static VALUE
-readline_s_set_completer_quote_characters(self, str)
- VALUE self, str;
-{
-#ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
- static char *completer_quote_characters = NULL;
-
- rb_secure(4);
- SafeStringValue(str);
- if (completer_quote_characters == NULL) {
- completer_quote_characters =
- ALLOC_N(char, RSTRING(str)->len + 1);
- }
- else {
- REALLOC_N(completer_quote_characters, char, RSTRING(str)->len + 1);
- }
- strncpy(completer_quote_characters,
- RSTRING(str)->ptr, RSTRING(str)->len);
- completer_quote_characters[RSTRING(str)->len] = '\0';
- rl_completer_quote_characters = completer_quote_characters;
-
- return self;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_COMPLETER_QUOTE_CHARACTERS */
-}
-
-static VALUE
-readline_s_get_completer_quote_characters(self, str)
- VALUE self, str;
-{
-#ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
- rb_secure(4);
- if (rl_completer_quote_characters == NULL)
- return Qnil;
- return rb_tainted_str_new2(rl_completer_quote_characters);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_COMPLETER_QUOTE_CHARACTERS */
-}
-
-static VALUE
-readline_s_set_filename_quote_characters(self, str)
- VALUE self, str;
-{
-#ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
- static char *filename_quote_characters = NULL;
-
- rb_secure(4);
- SafeStringValue(str);
- if (filename_quote_characters == NULL) {
- filename_quote_characters =
- ALLOC_N(char, RSTRING(str)->len + 1);
- }
- else {
- REALLOC_N(filename_quote_characters, char, RSTRING(str)->len + 1);
- }
- strncpy(filename_quote_characters,
- RSTRING(str)->ptr, RSTRING(str)->len);
- filename_quote_characters[RSTRING(str)->len] = '\0';
- rl_filename_quote_characters = filename_quote_characters;
-
- return self;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_FILENAME_QUOTE_CHARACTERS */
-}
-
-static VALUE
-readline_s_get_filename_quote_characters(self, str)
- VALUE self, str;
-{
-#ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
- rb_secure(4);
- if (rl_filename_quote_characters == NULL)
- return Qnil;
- return rb_tainted_str_new2(rl_filename_quote_characters);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif /* HAVE_RL_FILENAME_QUOTE_CHARACTERS */
-}
-
-static VALUE
-hist_to_s(self)
- VALUE self;
-{
- return rb_str_new2("HISTORY");
-}
-
-static VALUE
-hist_get(self, index)
- VALUE self;
- VALUE index;
-{
- HIST_ENTRY *entry;
- int i;
-
- rb_secure(4);
- i = NUM2INT(index);
- if (i < 0) {
- i += history_length;
- }
- entry = history_get(history_base + i);
- if (entry == NULL) {
- rb_raise(rb_eIndexError, "invalid index");
- }
- return rb_tainted_str_new2(entry->line);
-}
-
-static VALUE
-hist_set(self, index, str)
- VALUE self;
- VALUE index;
- VALUE str;
-{
-#ifdef HAVE_REPLACE_HISTORY_ENTRY
- HIST_ENTRY *entry;
- int i;
-
- rb_secure(4);
- i = NUM2INT(index);
- SafeStringValue(str);
- if (i < 0) {
- i += history_length;
- }
- entry = replace_history_entry(i, RSTRING(str)->ptr, NULL);
- if (entry == NULL) {
- rb_raise(rb_eIndexError, "invalid index");
- }
- return str;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-static VALUE
-hist_push(self, str)
- VALUE self;
- VALUE str;
-{
- rb_secure(4);
- SafeStringValue(str);
- add_history(RSTRING(str)->ptr);
- return self;
-}
-
-static VALUE
-hist_push_method(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE str;
-
- rb_secure(4);
- while (argc--) {
- str = *argv++;
- SafeStringValue(str);
- add_history(RSTRING(str)->ptr);
- }
- return self;
-}
-
-static VALUE
-rb_remove_history(index)
- int index;
-{
-#ifdef HAVE_REMOVE_HISTORY
- HIST_ENTRY *entry;
- VALUE val;
-
- rb_secure(4);
- entry = remove_history(index);
- if (entry) {
- val = rb_tainted_str_new2(entry->line);
- free(entry->line);
- free(entry);
- return val;
- }
- return Qnil;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-static VALUE
-hist_pop(self)
- VALUE self;
-{
- rb_secure(4);
- if (history_length > 0) {
- return rb_remove_history(history_length - 1);
- } else {
- return Qnil;
- }
-}
-
-static VALUE
-hist_shift(self)
- VALUE self;
-{
- rb_secure(4);
- if (history_length > 0) {
- return rb_remove_history(0);
- } else {
- return Qnil;
- }
-}
-
-static VALUE
-hist_each(self)
- VALUE self;
-{
- HIST_ENTRY *entry;
- int i;
-
- rb_secure(4);
- for (i = 0; i < history_length; i++) {
- entry = history_get(history_base + i);
- if (entry == NULL)
- break;
- rb_yield(rb_tainted_str_new2(entry->line));
- }
- return self;
-}
-
-static VALUE
-hist_length(self)
- VALUE self;
-{
- rb_secure(4);
- return INT2NUM(history_length);
-}
-
-static VALUE
-hist_empty_p(self)
- VALUE self;
-{
- rb_secure(4);
- return history_length == 0 ? Qtrue : Qfalse;
-}
-
-static VALUE
-hist_delete_at(self, index)
- VALUE self;
- VALUE index;
-{
- int i;
-
- rb_secure(4);
- i = NUM2INT(index);
- if (i < 0)
- i += history_length;
- if (i < 0 || i > history_length - 1) {
- rb_raise(rb_eIndexError, "invalid index");
- }
- return rb_remove_history(i);
-}
-
-static VALUE
-filename_completion_proc_call(self, str)
- VALUE self;
- VALUE str;
-{
- VALUE result;
- char **matches;
- int i;
-
- matches = rl_completion_matches(StringValuePtr(str),
- rl_filename_completion_function);
- if (matches) {
- result = rb_ary_new();
- for (i = 0; matches[i]; i++) {
- rb_ary_push(result, rb_tainted_str_new2(matches[i]));
- free(matches[i]);
- }
- free(matches);
- if (RARRAY(result)->len >= 2)
- rb_ary_shift(result);
- }
- else {
- result = Qnil;
- }
- return result;
-}
-
-static VALUE
-username_completion_proc_call(self, str)
- VALUE self;
- VALUE str;
-{
- VALUE result;
- char **matches;
- int i;
-
- matches = rl_completion_matches(StringValuePtr(str),
- rl_username_completion_function);
- if (matches) {
- result = rb_ary_new();
- for (i = 0; matches[i]; i++) {
- rb_ary_push(result, rb_tainted_str_new2(matches[i]));
- free(matches[i]);
- }
- free(matches);
- if (RARRAY(result)->len >= 2)
- rb_ary_shift(result);
- }
- else {
- result = Qnil;
- }
- return result;
-}
-
-void
-Init_readline()
-{
- VALUE history, fcomp, ucomp;
-
- /* Allow conditional parsing of the ~/.inputrc file. */
- rl_readline_name = "Ruby";
-
- using_history();
-
- completion_proc = rb_intern(COMPLETION_PROC);
- completion_case_fold = rb_intern(COMPLETION_CASE_FOLD);
-
- mReadline = rb_define_module("Readline");
- rb_define_module_function(mReadline, "readline",
- readline_readline, -1);
- rb_define_singleton_method(mReadline, "completion_proc=",
- readline_s_set_completion_proc, 1);
- rb_define_singleton_method(mReadline, "completion_proc",
- readline_s_get_completion_proc, 0);
- rb_define_singleton_method(mReadline, "completion_case_fold=",
- readline_s_set_completion_case_fold, 1);
- rb_define_singleton_method(mReadline, "completion_case_fold",
- readline_s_get_completion_case_fold, 0);
- rb_define_singleton_method(mReadline, "vi_editing_mode",
- readline_s_vi_editing_mode, 0);
- rb_define_singleton_method(mReadline, "emacs_editing_mode",
- readline_s_emacs_editing_mode, 0);
- rb_define_singleton_method(mReadline, "completion_append_character=",
- readline_s_set_completion_append_character, 1);
- rb_define_singleton_method(mReadline, "completion_append_character",
- readline_s_get_completion_append_character, 0);
- rb_define_singleton_method(mReadline, "basic_word_break_characters=",
- readline_s_set_basic_word_break_characters, 1);
- rb_define_singleton_method(mReadline, "basic_word_break_characters",
- readline_s_get_basic_word_break_characters, 0);
- rb_define_singleton_method(mReadline, "completer_word_break_characters=",
- readline_s_set_completer_word_break_characters, 1);
- rb_define_singleton_method(mReadline, "completer_word_break_characters",
- readline_s_get_completer_word_break_characters, 0);
- rb_define_singleton_method(mReadline, "basic_quote_characters=",
- readline_s_set_basic_quote_characters, 1);
- rb_define_singleton_method(mReadline, "basic_quote_characters",
- readline_s_get_basic_quote_characters, 0);
- rb_define_singleton_method(mReadline, "completer_quote_characters=",
- readline_s_set_completer_quote_characters, 1);
- rb_define_singleton_method(mReadline, "completer_quote_characters",
- readline_s_get_completer_quote_characters, 0);
- rb_define_singleton_method(mReadline, "filename_quote_characters=",
- readline_s_set_filename_quote_characters, 1);
- rb_define_singleton_method(mReadline, "filename_quote_characters",
- readline_s_get_filename_quote_characters, 0);
-
- history = rb_obj_alloc(rb_cObject);
- rb_extend_object(history, rb_mEnumerable);
- rb_define_singleton_method(history,"to_s", hist_to_s, 0);
- rb_define_singleton_method(history,"[]", hist_get, 1);
- rb_define_singleton_method(history,"[]=", hist_set, 2);
- rb_define_singleton_method(history,"<<", hist_push, 1);
- rb_define_singleton_method(history,"push", hist_push_method, -1);
- rb_define_singleton_method(history,"pop", hist_pop, 0);
- rb_define_singleton_method(history,"shift", hist_shift, 0);
- rb_define_singleton_method(history,"each", hist_each, 0);
- rb_define_singleton_method(history,"length", hist_length, 0);
- rb_define_singleton_method(history,"size", hist_length, 0);
- rb_define_singleton_method(history,"empty?", hist_empty_p, 0);
- rb_define_singleton_method(history,"delete_at", hist_delete_at, 1);
- rb_define_const(mReadline, "HISTORY", history);
-
- fcomp = rb_obj_alloc(rb_cObject);
- rb_define_singleton_method(fcomp, "call",
- filename_completion_proc_call, 1);
- rb_define_const(mReadline, "FILENAME_COMPLETION_PROC", fcomp);
-
- ucomp = rb_obj_alloc(rb_cObject);
- rb_define_singleton_method(ucomp, "call",
- username_completion_proc_call, 1);
- rb_define_const(mReadline, "USERNAME_COMPLETION_PROC", ucomp);
-#if defined HAVE_RL_LIBRARY_VERSION
- rb_define_const(mReadline, "VERSION", rb_str_new2(rl_library_version));
-#else
- rb_define_const(mReadline, "VERSION",
- rb_str_new2("2.0 or before version"));
-#endif
-
- rl_attempted_completion_function = readline_attempted_completion_function;
-#ifdef HAVE_RL_EVENT_HOOK
- rl_event_hook = readline_event;
-#endif
-#ifdef HAVE_RL_CLEAR_SIGNALS
- rl_clear_signals();
-#endif
-}
diff --git a/ext/ripper/README b/ext/ripper/README
new file mode 100644
index 0000000000..70fa208920
--- /dev/null
+++ b/ext/ripper/README
@@ -0,0 +1,29 @@
+Ripper README
+=============
+
+ Ripper is a Ruby script parser. You can get information
+ by event-based style from the parser.
+
+ !! WARNING !!
+
+ Ripper is still early-alpha version.
+ I never assure any kind of backward compatibility.
+
+Requirements
+------------
+
+ * ruby 1.9 (support CVS HEAD only)
+
+Usage
+-----
+
+ See test/ripper/* and sample/ripper/*.
+
+License
+-------
+
+ Ruby License.
+
+ Minero Aoki
+ aamine@loveruby.net
+ http://i.loveruby.net
diff --git a/ext/ripper/depend b/ext/ripper/depend
new file mode 100644
index 0000000000..db83378a1d
--- /dev/null
+++ b/ext/ripper/depend
@@ -0,0 +1,841 @@
+GEN = $(srcdir)/tools/generate.rb
+SRC1 = $(top_srcdir)/parse.y
+SRC2 = $(srcdir)/eventids2.c
+LRAMA = $(BASERUBY) $(top_srcdir)/tool/lrama/exe/lrama
+
+.SUFFIXES: .y
+
+src: ripper.c ripper_init.c eventids1.c eventids1.h eventids2table.c
+ripper.c ripper_init.c eventids1.c eventids1.h eventids2table.c: depend
+
+ripper.o: ripper.c
+
+.y.c:
+ $(ECHO) compiling compiler $<
+ $(Q) $(LRAMA) -o$@ - $< < $<
+
+all: check
+static: check
+
+ripper.y: $(srcdir)/tools/preproc.rb $(srcdir)/tools/dsl.rb $(top_srcdir)/parse.y $(top_srcdir)/defs/id.def
+ $(ECHO) extracting $@ from $(top_srcdir)/parse.y
+ $(Q) $(RUBY) $(top_srcdir)/tool/id2token.rb $(top_srcdir)/parse.y | \
+ $(RUBY) $(srcdir)/tools/preproc.rb --output=$@ - ripper.y
+
+check: .eventids2-check
+
+.eventids2-check: $(GEN) $(SRC1) $(SRC2)
+ $(ECHO) checking $(SRC1) and $(SRC2)
+ $(Q) $(RUBY) $(GEN) --mode=check --ids1src=$(SRC1) --ids2src=$(SRC2)
+ @exit > $@
+
+eventids1.h: $(GEN) $(srcdir)/tools/dsl.rb $(SRC1)
+ $(ECHO) generating $@ from $(SRC1)
+ $(Q) $(RUBY) $(GEN) --mode=eventids1_h --ids1src=$(SRC1) --output=$@
+
+eventids1.c: $(GEN) $(srcdir)/tools/dsl.rb $(SRC1)
+ $(ECHO) generating $@ from $(SRC1)
+ $(Q) $(RUBY) $(GEN) --mode=eventids1 --ids1src=$(SRC1) --output=$@
+
+eventids2table.c: $(GEN) $(srcdir)/tools/dsl.rb $(SRC2)
+ $(ECHO) generating $@ from $(SRC2)
+ $(Q) $(RUBY) $(GEN) --mode=eventids2table --ids2src=$(SRC2) --output=$@
+
+ripper_init.c: $(srcdir)/ripper_init.c.tmpl ripper.y $(srcdir)/tools/preproc.rb $(top_srcdir)/internal/ruby_parser.h
+ $(ECHO) generating $@ from $(srcdir)/ripper_init.c.tmpl
+ $(Q) $(RUBY) $(srcdir)/tools/preproc.rb --output=$@ --template=$(srcdir)/ripper_init.c.tmpl $(top_srcdir)/internal/ruby_parser.h
+
+# Entries for Ripper maintainer
+
+preproc: ripper.E
+ripper.E: ripper.c
+ $(ECHO) preprocessing ripper.c
+ $(Q) $(CC) -E $(INCFLAGS) $(CPPFLAGS) $< | $(RUBY) $(srcdir)/tools/strip.rb > $@
+
+# AUTOGENERATED DEPENDENCIES START
+eventids1.o: $(RUBY_EXTCONF_H)
+eventids1.o: $(arch_hdrdir)/ruby/config.h
+eventids1.o: $(hdrdir)/ruby/assert.h
+eventids1.o: $(hdrdir)/ruby/backward.h
+eventids1.o: $(hdrdir)/ruby/backward/2/assume.h
+eventids1.o: $(hdrdir)/ruby/backward/2/attributes.h
+eventids1.o: $(hdrdir)/ruby/backward/2/bool.h
+eventids1.o: $(hdrdir)/ruby/backward/2/inttypes.h
+eventids1.o: $(hdrdir)/ruby/backward/2/limits.h
+eventids1.o: $(hdrdir)/ruby/backward/2/long_long.h
+eventids1.o: $(hdrdir)/ruby/backward/2/stdalign.h
+eventids1.o: $(hdrdir)/ruby/backward/2/stdarg.h
+eventids1.o: $(hdrdir)/ruby/defines.h
+eventids1.o: $(hdrdir)/ruby/intern.h
+eventids1.o: $(hdrdir)/ruby/internal/abi.h
+eventids1.o: $(hdrdir)/ruby/internal/anyargs.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+eventids1.o: $(hdrdir)/ruby/internal/assume.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/artificial.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/cold.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/const.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/error.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/format.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/noalias.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/noinline.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/pure.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/restrict.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/warning.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/weakref.h
+eventids1.o: $(hdrdir)/ruby/internal/cast.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_since.h
+eventids1.o: $(hdrdir)/ruby/internal/config.h
+eventids1.o: $(hdrdir)/ruby/internal/constant_p.h
+eventids1.o: $(hdrdir)/ruby/internal/core.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rarray.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rbasic.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rbignum.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rclass.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rdata.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rfile.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rhash.h
+eventids1.o: $(hdrdir)/ruby/internal/core/robject.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rregexp.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rstring.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rstruct.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+eventids1.o: $(hdrdir)/ruby/internal/ctype.h
+eventids1.o: $(hdrdir)/ruby/internal/dllexport.h
+eventids1.o: $(hdrdir)/ruby/internal/dosish.h
+eventids1.o: $(hdrdir)/ruby/internal/error.h
+eventids1.o: $(hdrdir)/ruby/internal/eval.h
+eventids1.o: $(hdrdir)/ruby/internal/event.h
+eventids1.o: $(hdrdir)/ruby/internal/fl_type.h
+eventids1.o: $(hdrdir)/ruby/internal/gc.h
+eventids1.o: $(hdrdir)/ruby/internal/glob.h
+eventids1.o: $(hdrdir)/ruby/internal/globals.h
+eventids1.o: $(hdrdir)/ruby/internal/has/attribute.h
+eventids1.o: $(hdrdir)/ruby/internal/has/builtin.h
+eventids1.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+eventids1.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+eventids1.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+eventids1.o: $(hdrdir)/ruby/internal/has/extension.h
+eventids1.o: $(hdrdir)/ruby/internal/has/feature.h
+eventids1.o: $(hdrdir)/ruby/internal/has/warning.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/array.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/bignum.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/class.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/compar.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/complex.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/cont.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/dir.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/enum.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/error.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/eval.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/file.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/hash.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/io.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/load.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/marshal.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/numeric.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/object.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/parse.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/proc.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/process.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/random.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/range.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/rational.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/re.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/ruby.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/select.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/set.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/signal.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/string.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/struct.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/thread.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/time.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/variable.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/vm.h
+eventids1.o: $(hdrdir)/ruby/internal/interpreter.h
+eventids1.o: $(hdrdir)/ruby/internal/iterator.h
+eventids1.o: $(hdrdir)/ruby/internal/memory.h
+eventids1.o: $(hdrdir)/ruby/internal/method.h
+eventids1.o: $(hdrdir)/ruby/internal/module.h
+eventids1.o: $(hdrdir)/ruby/internal/newobj.h
+eventids1.o: $(hdrdir)/ruby/internal/scan_args.h
+eventids1.o: $(hdrdir)/ruby/internal/special_consts.h
+eventids1.o: $(hdrdir)/ruby/internal/static_assert.h
+eventids1.o: $(hdrdir)/ruby/internal/stdalign.h
+eventids1.o: $(hdrdir)/ruby/internal/stdbool.h
+eventids1.o: $(hdrdir)/ruby/internal/stdckdint.h
+eventids1.o: $(hdrdir)/ruby/internal/symbol.h
+eventids1.o: $(hdrdir)/ruby/internal/value.h
+eventids1.o: $(hdrdir)/ruby/internal/value_type.h
+eventids1.o: $(hdrdir)/ruby/internal/variable.h
+eventids1.o: $(hdrdir)/ruby/internal/warning_push.h
+eventids1.o: $(hdrdir)/ruby/internal/xmalloc.h
+eventids1.o: $(hdrdir)/ruby/missing.h
+eventids1.o: $(hdrdir)/ruby/ruby.h
+eventids1.o: $(hdrdir)/ruby/st.h
+eventids1.o: $(hdrdir)/ruby/subst.h
+eventids1.o: eventids1.h
+eventids1.o: {$(VPATH)}eventids1.c
+eventids1.o: {$(VPATH)}eventids1.h
+eventids2.o: $(RUBY_EXTCONF_H)
+eventids2.o: $(arch_hdrdir)/ruby/config.h
+eventids2.o: $(hdrdir)/ruby/assert.h
+eventids2.o: $(hdrdir)/ruby/backward.h
+eventids2.o: $(hdrdir)/ruby/backward/2/assume.h
+eventids2.o: $(hdrdir)/ruby/backward/2/attributes.h
+eventids2.o: $(hdrdir)/ruby/backward/2/bool.h
+eventids2.o: $(hdrdir)/ruby/backward/2/inttypes.h
+eventids2.o: $(hdrdir)/ruby/backward/2/limits.h
+eventids2.o: $(hdrdir)/ruby/backward/2/long_long.h
+eventids2.o: $(hdrdir)/ruby/backward/2/stdalign.h
+eventids2.o: $(hdrdir)/ruby/backward/2/stdarg.h
+eventids2.o: $(hdrdir)/ruby/defines.h
+eventids2.o: $(hdrdir)/ruby/encoding.h
+eventids2.o: $(hdrdir)/ruby/intern.h
+eventids2.o: $(hdrdir)/ruby/internal/abi.h
+eventids2.o: $(hdrdir)/ruby/internal/anyargs.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+eventids2.o: $(hdrdir)/ruby/internal/assume.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/artificial.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/cold.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/const.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/error.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/format.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/noalias.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/noinline.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/pure.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/restrict.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/warning.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/weakref.h
+eventids2.o: $(hdrdir)/ruby/internal/cast.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_since.h
+eventids2.o: $(hdrdir)/ruby/internal/config.h
+eventids2.o: $(hdrdir)/ruby/internal/constant_p.h
+eventids2.o: $(hdrdir)/ruby/internal/core.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rarray.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rbasic.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rbignum.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rclass.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rdata.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rfile.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rhash.h
+eventids2.o: $(hdrdir)/ruby/internal/core/robject.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rregexp.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rstring.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rstruct.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+eventids2.o: $(hdrdir)/ruby/internal/ctype.h
+eventids2.o: $(hdrdir)/ruby/internal/dllexport.h
+eventids2.o: $(hdrdir)/ruby/internal/dosish.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/re.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/string.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+eventids2.o: $(hdrdir)/ruby/internal/error.h
+eventids2.o: $(hdrdir)/ruby/internal/eval.h
+eventids2.o: $(hdrdir)/ruby/internal/event.h
+eventids2.o: $(hdrdir)/ruby/internal/fl_type.h
+eventids2.o: $(hdrdir)/ruby/internal/gc.h
+eventids2.o: $(hdrdir)/ruby/internal/glob.h
+eventids2.o: $(hdrdir)/ruby/internal/globals.h
+eventids2.o: $(hdrdir)/ruby/internal/has/attribute.h
+eventids2.o: $(hdrdir)/ruby/internal/has/builtin.h
+eventids2.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+eventids2.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+eventids2.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+eventids2.o: $(hdrdir)/ruby/internal/has/extension.h
+eventids2.o: $(hdrdir)/ruby/internal/has/feature.h
+eventids2.o: $(hdrdir)/ruby/internal/has/warning.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/array.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/bignum.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/class.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/compar.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/complex.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/cont.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/dir.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/enum.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/error.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/eval.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/file.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/hash.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/io.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/load.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/marshal.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/numeric.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/object.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/parse.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/proc.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/process.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/random.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/range.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/rational.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/re.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/ruby.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/select.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/set.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/signal.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/string.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/struct.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/thread.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/time.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/variable.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/vm.h
+eventids2.o: $(hdrdir)/ruby/internal/interpreter.h
+eventids2.o: $(hdrdir)/ruby/internal/iterator.h
+eventids2.o: $(hdrdir)/ruby/internal/memory.h
+eventids2.o: $(hdrdir)/ruby/internal/method.h
+eventids2.o: $(hdrdir)/ruby/internal/module.h
+eventids2.o: $(hdrdir)/ruby/internal/newobj.h
+eventids2.o: $(hdrdir)/ruby/internal/scan_args.h
+eventids2.o: $(hdrdir)/ruby/internal/special_consts.h
+eventids2.o: $(hdrdir)/ruby/internal/static_assert.h
+eventids2.o: $(hdrdir)/ruby/internal/stdalign.h
+eventids2.o: $(hdrdir)/ruby/internal/stdbool.h
+eventids2.o: $(hdrdir)/ruby/internal/stdckdint.h
+eventids2.o: $(hdrdir)/ruby/internal/symbol.h
+eventids2.o: $(hdrdir)/ruby/internal/value.h
+eventids2.o: $(hdrdir)/ruby/internal/value_type.h
+eventids2.o: $(hdrdir)/ruby/internal/variable.h
+eventids2.o: $(hdrdir)/ruby/internal/warning_push.h
+eventids2.o: $(hdrdir)/ruby/internal/xmalloc.h
+eventids2.o: $(hdrdir)/ruby/missing.h
+eventids2.o: $(hdrdir)/ruby/onigmo.h
+eventids2.o: $(hdrdir)/ruby/oniguruma.h
+eventids2.o: $(hdrdir)/ruby/ruby.h
+eventids2.o: $(hdrdir)/ruby/st.h
+eventids2.o: $(hdrdir)/ruby/subst.h
+eventids2.o: $(top_srcdir)/internal.h
+eventids2.o: $(top_srcdir)/internal/static_assert.h
+eventids2.o: $(top_srcdir)/rubyparser.h
+eventids2.o: eventids2.c
+eventids2.o: eventids2.h
+eventids2.o: {$(VPATH)}eventids2table.c
+eventids2.o: {$(VPATH)}parse.h
+ripper.o: $(RUBY_EXTCONF_H)
+ripper.o: $(arch_hdrdir)/ruby/config.h
+ripper.o: $(hdrdir)/ruby.h
+ripper.o: $(hdrdir)/ruby/assert.h
+ripper.o: $(hdrdir)/ruby/atomic.h
+ripper.o: $(hdrdir)/ruby/backward.h
+ripper.o: $(hdrdir)/ruby/backward/2/assume.h
+ripper.o: $(hdrdir)/ruby/backward/2/attributes.h
+ripper.o: $(hdrdir)/ruby/backward/2/bool.h
+ripper.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ripper.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ripper.o: $(hdrdir)/ruby/backward/2/limits.h
+ripper.o: $(hdrdir)/ruby/backward/2/long_long.h
+ripper.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ripper.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ripper.o: $(hdrdir)/ruby/defines.h
+ripper.o: $(hdrdir)/ruby/encoding.h
+ripper.o: $(hdrdir)/ruby/intern.h
+ripper.o: $(hdrdir)/ruby/internal/abi.h
+ripper.o: $(hdrdir)/ruby/internal/anyargs.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ripper.o: $(hdrdir)/ruby/internal/assume.h
+ripper.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ripper.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ripper.o: $(hdrdir)/ruby/internal/attr/cold.h
+ripper.o: $(hdrdir)/ruby/internal/attr/const.h
+ripper.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ripper.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ripper.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ripper.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ripper.o: $(hdrdir)/ruby/internal/attr/error.h
+ripper.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ripper.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ripper.o: $(hdrdir)/ruby/internal/attr/format.h
+ripper.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ripper.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ripper.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ripper.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ripper.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ripper.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ripper.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ripper.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ripper.o: $(hdrdir)/ruby/internal/attr/pure.h
+ripper.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ripper.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ripper.o: $(hdrdir)/ruby/internal/attr/warning.h
+ripper.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ripper.o: $(hdrdir)/ruby/internal/cast.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_since.h
+ripper.o: $(hdrdir)/ruby/internal/config.h
+ripper.o: $(hdrdir)/ruby/internal/constant_p.h
+ripper.o: $(hdrdir)/ruby/internal/core.h
+ripper.o: $(hdrdir)/ruby/internal/core/rarray.h
+ripper.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ripper.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ripper.o: $(hdrdir)/ruby/internal/core/rclass.h
+ripper.o: $(hdrdir)/ruby/internal/core/rdata.h
+ripper.o: $(hdrdir)/ruby/internal/core/rfile.h
+ripper.o: $(hdrdir)/ruby/internal/core/rhash.h
+ripper.o: $(hdrdir)/ruby/internal/core/rmatch.h
+ripper.o: $(hdrdir)/ruby/internal/core/robject.h
+ripper.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ripper.o: $(hdrdir)/ruby/internal/core/rstring.h
+ripper.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ripper.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ripper.o: $(hdrdir)/ruby/internal/ctype.h
+ripper.o: $(hdrdir)/ruby/internal/dllexport.h
+ripper.o: $(hdrdir)/ruby/internal/dosish.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/re.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/string.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ripper.o: $(hdrdir)/ruby/internal/error.h
+ripper.o: $(hdrdir)/ruby/internal/eval.h
+ripper.o: $(hdrdir)/ruby/internal/event.h
+ripper.o: $(hdrdir)/ruby/internal/fl_type.h
+ripper.o: $(hdrdir)/ruby/internal/gc.h
+ripper.o: $(hdrdir)/ruby/internal/glob.h
+ripper.o: $(hdrdir)/ruby/internal/globals.h
+ripper.o: $(hdrdir)/ruby/internal/has/attribute.h
+ripper.o: $(hdrdir)/ruby/internal/has/builtin.h
+ripper.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ripper.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ripper.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ripper.o: $(hdrdir)/ruby/internal/has/extension.h
+ripper.o: $(hdrdir)/ruby/internal/has/feature.h
+ripper.o: $(hdrdir)/ruby/internal/has/warning.h
+ripper.o: $(hdrdir)/ruby/internal/intern/array.h
+ripper.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ripper.o: $(hdrdir)/ruby/internal/intern/class.h
+ripper.o: $(hdrdir)/ruby/internal/intern/compar.h
+ripper.o: $(hdrdir)/ruby/internal/intern/complex.h
+ripper.o: $(hdrdir)/ruby/internal/intern/cont.h
+ripper.o: $(hdrdir)/ruby/internal/intern/dir.h
+ripper.o: $(hdrdir)/ruby/internal/intern/enum.h
+ripper.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ripper.o: $(hdrdir)/ruby/internal/intern/error.h
+ripper.o: $(hdrdir)/ruby/internal/intern/eval.h
+ripper.o: $(hdrdir)/ruby/internal/intern/file.h
+ripper.o: $(hdrdir)/ruby/internal/intern/hash.h
+ripper.o: $(hdrdir)/ruby/internal/intern/io.h
+ripper.o: $(hdrdir)/ruby/internal/intern/load.h
+ripper.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ripper.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ripper.o: $(hdrdir)/ruby/internal/intern/object.h
+ripper.o: $(hdrdir)/ruby/internal/intern/parse.h
+ripper.o: $(hdrdir)/ruby/internal/intern/proc.h
+ripper.o: $(hdrdir)/ruby/internal/intern/process.h
+ripper.o: $(hdrdir)/ruby/internal/intern/random.h
+ripper.o: $(hdrdir)/ruby/internal/intern/range.h
+ripper.o: $(hdrdir)/ruby/internal/intern/rational.h
+ripper.o: $(hdrdir)/ruby/internal/intern/re.h
+ripper.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ripper.o: $(hdrdir)/ruby/internal/intern/select.h
+ripper.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ripper.o: $(hdrdir)/ruby/internal/intern/set.h
+ripper.o: $(hdrdir)/ruby/internal/intern/signal.h
+ripper.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ripper.o: $(hdrdir)/ruby/internal/intern/string.h
+ripper.o: $(hdrdir)/ruby/internal/intern/struct.h
+ripper.o: $(hdrdir)/ruby/internal/intern/thread.h
+ripper.o: $(hdrdir)/ruby/internal/intern/time.h
+ripper.o: $(hdrdir)/ruby/internal/intern/variable.h
+ripper.o: $(hdrdir)/ruby/internal/intern/vm.h
+ripper.o: $(hdrdir)/ruby/internal/interpreter.h
+ripper.o: $(hdrdir)/ruby/internal/iterator.h
+ripper.o: $(hdrdir)/ruby/internal/memory.h
+ripper.o: $(hdrdir)/ruby/internal/method.h
+ripper.o: $(hdrdir)/ruby/internal/module.h
+ripper.o: $(hdrdir)/ruby/internal/newobj.h
+ripper.o: $(hdrdir)/ruby/internal/scan_args.h
+ripper.o: $(hdrdir)/ruby/internal/special_consts.h
+ripper.o: $(hdrdir)/ruby/internal/static_assert.h
+ripper.o: $(hdrdir)/ruby/internal/stdalign.h
+ripper.o: $(hdrdir)/ruby/internal/stdbool.h
+ripper.o: $(hdrdir)/ruby/internal/stdckdint.h
+ripper.o: $(hdrdir)/ruby/internal/symbol.h
+ripper.o: $(hdrdir)/ruby/internal/value.h
+ripper.o: $(hdrdir)/ruby/internal/value_type.h
+ripper.o: $(hdrdir)/ruby/internal/variable.h
+ripper.o: $(hdrdir)/ruby/internal/warning_push.h
+ripper.o: $(hdrdir)/ruby/internal/xmalloc.h
+ripper.o: $(hdrdir)/ruby/io.h
+ripper.o: $(hdrdir)/ruby/missing.h
+ripper.o: $(hdrdir)/ruby/onigmo.h
+ripper.o: $(hdrdir)/ruby/oniguruma.h
+ripper.o: $(hdrdir)/ruby/ractor.h
+ripper.o: $(hdrdir)/ruby/re.h
+ripper.o: $(hdrdir)/ruby/regex.h
+ripper.o: $(hdrdir)/ruby/ruby.h
+ripper.o: $(hdrdir)/ruby/st.h
+ripper.o: $(hdrdir)/ruby/subst.h
+ripper.o: $(hdrdir)/ruby/thread_native.h
+ripper.o: $(hdrdir)/ruby/util.h
+ripper.o: $(hdrdir)/ruby/version.h
+ripper.o: $(top_srcdir)/ccan/check_type/check_type.h
+ripper.o: $(top_srcdir)/ccan/container_of/container_of.h
+ripper.o: $(top_srcdir)/ccan/list/list.h
+ripper.o: $(top_srcdir)/ccan/str/str.h
+ripper.o: $(top_srcdir)/constant.h
+ripper.o: $(top_srcdir)/encindex.h
+ripper.o: $(top_srcdir)/id_table.h
+ripper.o: $(top_srcdir)/internal.h
+ripper.o: $(top_srcdir)/internal/array.h
+ripper.o: $(top_srcdir)/internal/basic_operators.h
+ripper.o: $(top_srcdir)/internal/bignum.h
+ripper.o: $(top_srcdir)/internal/bits.h
+ripper.o: $(top_srcdir)/internal/box.h
+ripper.o: $(top_srcdir)/internal/compar.h
+ripper.o: $(top_srcdir)/internal/compile.h
+ripper.o: $(top_srcdir)/internal/compilers.h
+ripper.o: $(top_srcdir)/internal/complex.h
+ripper.o: $(top_srcdir)/internal/encoding.h
+ripper.o: $(top_srcdir)/internal/error.h
+ripper.o: $(top_srcdir)/internal/fixnum.h
+ripper.o: $(top_srcdir)/internal/gc.h
+ripper.o: $(top_srcdir)/internal/hash.h
+ripper.o: $(top_srcdir)/internal/imemo.h
+ripper.o: $(top_srcdir)/internal/io.h
+ripper.o: $(top_srcdir)/internal/numeric.h
+ripper.o: $(top_srcdir)/internal/parse.h
+ripper.o: $(top_srcdir)/internal/rational.h
+ripper.o: $(top_srcdir)/internal/re.h
+ripper.o: $(top_srcdir)/internal/ruby_parser.h
+ripper.o: $(top_srcdir)/internal/sanitizers.h
+ripper.o: $(top_srcdir)/internal/serial.h
+ripper.o: $(top_srcdir)/internal/set_table.h
+ripper.o: $(top_srcdir)/internal/static_assert.h
+ripper.o: $(top_srcdir)/internal/string.h
+ripper.o: $(top_srcdir)/internal/struct.h
+ripper.o: $(top_srcdir)/internal/symbol.h
+ripper.o: $(top_srcdir)/internal/thread.h
+ripper.o: $(top_srcdir)/internal/variable.h
+ripper.o: $(top_srcdir)/internal/vm.h
+ripper.o: $(top_srcdir)/internal/warnings.h
+ripper.o: $(top_srcdir)/method.h
+ripper.o: $(top_srcdir)/node.h
+ripper.o: $(top_srcdir)/parser_node.h
+ripper.o: $(top_srcdir)/parser_st.h
+ripper.o: $(top_srcdir)/regenc.h
+ripper.o: $(top_srcdir)/ruby_assert.h
+ripper.o: $(top_srcdir)/ruby_atomic.h
+ripper.o: $(top_srcdir)/rubyparser.h
+ripper.o: $(top_srcdir)/shape.h
+ripper.o: $(top_srcdir)/symbol.h
+ripper.o: $(top_srcdir)/thread_pthread.h
+ripper.o: $(top_srcdir)/vm_core.h
+ripper.o: $(top_srcdir)/vm_opts.h
+ripper.o: ../../probes.h
+ripper.o: eventids1.h
+ripper.o: eventids2.c
+ripper.o: eventids2.h
+ripper.o: ripper.y
+ripper.o: ripper_init.h
+ripper.o: {$(VPATH)}eventids1.c
+ripper.o: {$(VPATH)}eventids2table.c
+ripper.o: {$(VPATH)}id.h
+ripper.o: {$(VPATH)}lex.c
+ripper.o: {$(VPATH)}parse.h
+ripper.o: {$(VPATH)}probes.dmyh
+ripper.o: {$(VPATH)}ripper.c
+ripper_init.o: $(RUBY_EXTCONF_H)
+ripper_init.o: $(arch_hdrdir)/ruby/config.h
+ripper_init.o: $(hdrdir)/ruby/assert.h
+ripper_init.o: $(hdrdir)/ruby/backward.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/assume.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/attributes.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/bool.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/limits.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/long_long.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ripper_init.o: $(hdrdir)/ruby/defines.h
+ripper_init.o: $(hdrdir)/ruby/encoding.h
+ripper_init.o: $(hdrdir)/ruby/intern.h
+ripper_init.o: $(hdrdir)/ruby/internal/abi.h
+ripper_init.o: $(hdrdir)/ruby/internal/anyargs.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/assume.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/cold.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/const.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/error.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/format.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/pure.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/warning.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ripper_init.o: $(hdrdir)/ruby/internal/cast.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_since.h
+ripper_init.o: $(hdrdir)/ruby/internal/config.h
+ripper_init.o: $(hdrdir)/ruby/internal/constant_p.h
+ripper_init.o: $(hdrdir)/ruby/internal/core.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rarray.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rclass.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rdata.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rfile.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rhash.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/robject.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rstring.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ripper_init.o: $(hdrdir)/ruby/internal/ctype.h
+ripper_init.o: $(hdrdir)/ruby/internal/dllexport.h
+ripper_init.o: $(hdrdir)/ruby/internal/dosish.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/re.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/string.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ripper_init.o: $(hdrdir)/ruby/internal/error.h
+ripper_init.o: $(hdrdir)/ruby/internal/eval.h
+ripper_init.o: $(hdrdir)/ruby/internal/event.h
+ripper_init.o: $(hdrdir)/ruby/internal/fl_type.h
+ripper_init.o: $(hdrdir)/ruby/internal/gc.h
+ripper_init.o: $(hdrdir)/ruby/internal/glob.h
+ripper_init.o: $(hdrdir)/ruby/internal/globals.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/attribute.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/builtin.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/extension.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/feature.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/warning.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/array.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/class.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/compar.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/complex.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/cont.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/dir.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/enum.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/error.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/eval.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/file.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/hash.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/io.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/load.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/object.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/parse.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/proc.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/process.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/random.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/range.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/rational.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/re.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/select.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/set.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/signal.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/string.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/struct.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/thread.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/time.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/variable.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/vm.h
+ripper_init.o: $(hdrdir)/ruby/internal/interpreter.h
+ripper_init.o: $(hdrdir)/ruby/internal/iterator.h
+ripper_init.o: $(hdrdir)/ruby/internal/memory.h
+ripper_init.o: $(hdrdir)/ruby/internal/method.h
+ripper_init.o: $(hdrdir)/ruby/internal/module.h
+ripper_init.o: $(hdrdir)/ruby/internal/newobj.h
+ripper_init.o: $(hdrdir)/ruby/internal/scan_args.h
+ripper_init.o: $(hdrdir)/ruby/internal/special_consts.h
+ripper_init.o: $(hdrdir)/ruby/internal/static_assert.h
+ripper_init.o: $(hdrdir)/ruby/internal/stdalign.h
+ripper_init.o: $(hdrdir)/ruby/internal/stdbool.h
+ripper_init.o: $(hdrdir)/ruby/internal/stdckdint.h
+ripper_init.o: $(hdrdir)/ruby/internal/symbol.h
+ripper_init.o: $(hdrdir)/ruby/internal/value.h
+ripper_init.o: $(hdrdir)/ruby/internal/value_type.h
+ripper_init.o: $(hdrdir)/ruby/internal/variable.h
+ripper_init.o: $(hdrdir)/ruby/internal/warning_push.h
+ripper_init.o: $(hdrdir)/ruby/internal/xmalloc.h
+ripper_init.o: $(hdrdir)/ruby/missing.h
+ripper_init.o: $(hdrdir)/ruby/onigmo.h
+ripper_init.o: $(hdrdir)/ruby/oniguruma.h
+ripper_init.o: $(hdrdir)/ruby/ruby.h
+ripper_init.o: $(hdrdir)/ruby/st.h
+ripper_init.o: $(hdrdir)/ruby/subst.h
+ripper_init.o: $(top_srcdir)/internal.h
+ripper_init.o: $(top_srcdir)/internal/array.h
+ripper_init.o: $(top_srcdir)/internal/basic_operators.h
+ripper_init.o: $(top_srcdir)/internal/bignum.h
+ripper_init.o: $(top_srcdir)/internal/bits.h
+ripper_init.o: $(top_srcdir)/internal/compar.h
+ripper_init.o: $(top_srcdir)/internal/compilers.h
+ripper_init.o: $(top_srcdir)/internal/complex.h
+ripper_init.o: $(top_srcdir)/internal/fixnum.h
+ripper_init.o: $(top_srcdir)/internal/imemo.h
+ripper_init.o: $(top_srcdir)/internal/numeric.h
+ripper_init.o: $(top_srcdir)/internal/parse.h
+ripper_init.o: $(top_srcdir)/internal/rational.h
+ripper_init.o: $(top_srcdir)/internal/ruby_parser.h
+ripper_init.o: $(top_srcdir)/internal/serial.h
+ripper_init.o: $(top_srcdir)/internal/static_assert.h
+ripper_init.o: $(top_srcdir)/internal/vm.h
+ripper_init.o: $(top_srcdir)/node.h
+ripper_init.o: $(top_srcdir)/ruby_assert.h
+ripper_init.o: $(top_srcdir)/rubyparser.h
+ripper_init.o: eventids1.h
+ripper_init.o: eventids2.h
+ripper_init.o: ripper_init.h
+ripper_init.o: {$(VPATH)}parse.h
+ripper_init.o: {$(VPATH)}ripper_init.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/ripper/eventids2.c b/ext/ripper/eventids2.c
new file mode 100644
index 0000000000..87f2f588ec
--- /dev/null
+++ b/ext/ripper/eventids2.c
@@ -0,0 +1,303 @@
+#include "ruby/ruby.h"
+#include "rubyparser.h"
+#define YYSTYPE_IS_DECLARED
+#include "parse.h"
+#include "eventids2.h"
+#include "internal.h"
+#include "internal/static_assert.h"
+
+typedef struct {
+ ID ripper_id_backref;
+ ID ripper_id_backtick;
+ ID ripper_id_comma;
+ ID ripper_id_const;
+ ID ripper_id_cvar;
+ ID ripper_id_embexpr_beg;
+ ID ripper_id_embexpr_end;
+ ID ripper_id_embvar;
+ ID ripper_id_float;
+ ID ripper_id_gvar;
+ ID ripper_id_ident;
+ ID ripper_id_imaginary;
+ ID ripper_id_int;
+ ID ripper_id_ivar;
+ ID ripper_id_kw;
+ ID ripper_id_lbrace;
+ ID ripper_id_lbracket;
+ ID ripper_id_lparen;
+ ID ripper_id_nl;
+ ID ripper_id_op;
+ ID ripper_id_period;
+ ID ripper_id_rbrace;
+ ID ripper_id_rbracket;
+ ID ripper_id_rparen;
+ ID ripper_id_semicolon;
+ ID ripper_id_symbeg;
+ ID ripper_id_tstring_beg;
+ ID ripper_id_tstring_content;
+ ID ripper_id_tstring_end;
+ ID ripper_id_words_beg;
+ ID ripper_id_qwords_beg;
+ ID ripper_id_qsymbols_beg;
+ ID ripper_id_symbols_beg;
+ ID ripper_id_words_sep;
+ ID ripper_id_rational;
+ ID ripper_id_regexp_beg;
+ ID ripper_id_regexp_end;
+ ID ripper_id_label;
+ ID ripper_id_label_end;
+ ID ripper_id_tlambda;
+ ID ripper_id_tlambeg;
+
+ ID ripper_id_ignored_nl;
+ ID ripper_id_comment;
+ ID ripper_id_embdoc_beg;
+ ID ripper_id_embdoc;
+ ID ripper_id_embdoc_end;
+ ID ripper_id_sp;
+ ID ripper_id_heredoc_beg;
+ ID ripper_id_heredoc_end;
+ ID ripper_id___end__;
+ ID ripper_id_CHAR;
+} ripper_scanner_ids_t;
+
+static ripper_scanner_ids_t ripper_scanner_ids;
+
+#include "eventids2table.c"
+
+STATIC_ASSERT(eventids2_table_size, RIPPER_EVENTIDS2_TABLE_SIZE == sizeof(ripper_scanner_ids)/sizeof(ID));
+
+void
+ripper_init_eventids2(void)
+{
+#define set_id2(name) ripper_scanner_ids.ripper_id_##name = rb_intern_const("on_"#name)
+ set_id2(backref);
+ set_id2(backtick);
+ set_id2(comma);
+ set_id2(const);
+ set_id2(cvar);
+ set_id2(embexpr_beg);
+ set_id2(embexpr_end);
+ set_id2(embvar);
+ set_id2(float);
+ set_id2(gvar);
+ set_id2(ident);
+ set_id2(imaginary);
+ set_id2(int);
+ set_id2(ivar);
+ set_id2(kw);
+ set_id2(lbrace);
+ set_id2(lbracket);
+ set_id2(lparen);
+ set_id2(nl);
+ set_id2(op);
+ set_id2(period);
+ set_id2(rbrace);
+ set_id2(rbracket);
+ set_id2(rparen);
+ set_id2(semicolon);
+ set_id2(symbeg);
+ set_id2(tstring_beg);
+ set_id2(tstring_content);
+ set_id2(tstring_end);
+ set_id2(words_beg);
+ set_id2(qwords_beg);
+ set_id2(qsymbols_beg);
+ set_id2(symbols_beg);
+ set_id2(words_sep);
+ set_id2(rational);
+ set_id2(regexp_beg);
+ set_id2(regexp_end);
+ set_id2(label);
+ set_id2(label_end);
+ set_id2(tlambda);
+ set_id2(tlambeg);
+
+ set_id2(ignored_nl);
+ set_id2(comment);
+ set_id2(embdoc_beg);
+ set_id2(embdoc);
+ set_id2(embdoc_end);
+ set_id2(sp);
+ set_id2(heredoc_beg);
+ set_id2(heredoc_end);
+ set_id2(__end__);
+ set_id2(CHAR);
+}
+
+STATIC_ASSERT(k__END___range, k__END__ < SHRT_MAX);
+STATIC_ASSERT(ripper_scanner_ids_size, sizeof(ripper_scanner_ids) < SHRT_MAX);
+
+ID
+ripper_token2eventid(enum yytokentype tok)
+{
+#define O(member) (int)offsetof(ripper_scanner_ids_t, ripper_id_##member)+1
+ static const unsigned short offsets[] = {
+ [' '] = O(words_sep),
+ ['!'] = O(op),
+ ['%'] = O(op),
+ ['&'] = O(op),
+ ['*'] = O(op),
+ ['+'] = O(op),
+ ['-'] = O(op),
+ ['/'] = O(op),
+ ['<'] = O(op),
+ ['='] = O(op),
+ ['>'] = O(op),
+ ['?'] = O(op),
+ ['^'] = O(op),
+ ['|'] = O(op),
+ ['~'] = O(op),
+ [':'] = O(op),
+ [','] = O(comma),
+ ['.'] = O(period),
+ [';'] = O(semicolon),
+ ['`'] = O(backtick),
+ ['\n'] = O(nl),
+ [keyword_alias] = O(kw),
+ [keyword_and] = O(kw),
+ [keyword_begin] = O(kw),
+ [keyword_break] = O(kw),
+ [keyword_case] = O(kw),
+ [keyword_class] = O(kw),
+ [keyword_def] = O(kw),
+ [keyword_defined] = O(kw),
+ [keyword_do] = O(kw),
+ [keyword_do_block] = O(kw),
+ [keyword_do_cond] = O(kw),
+ [keyword_else] = O(kw),
+ [keyword_elsif] = O(kw),
+ [keyword_end] = O(kw),
+ [keyword_ensure] = O(kw),
+ [keyword_false] = O(kw),
+ [keyword_for] = O(kw),
+ [keyword_if] = O(kw),
+ [modifier_if] = O(kw),
+ [keyword_in] = O(kw),
+ [keyword_module] = O(kw),
+ [keyword_next] = O(kw),
+ [keyword_nil] = O(kw),
+ [keyword_not] = O(kw),
+ [keyword_or] = O(kw),
+ [keyword_redo] = O(kw),
+ [keyword_rescue] = O(kw),
+ [modifier_rescue] = O(kw),
+ [keyword_retry] = O(kw),
+ [keyword_return] = O(kw),
+ [keyword_self] = O(kw),
+ [keyword_super] = O(kw),
+ [keyword_then] = O(kw),
+ [keyword_true] = O(kw),
+ [keyword_undef] = O(kw),
+ [keyword_unless] = O(kw),
+ [modifier_unless] = O(kw),
+ [keyword_until] = O(kw),
+ [modifier_until] = O(kw),
+ [keyword_when] = O(kw),
+ [keyword_while] = O(kw),
+ [modifier_while] = O(kw),
+ [keyword_yield] = O(kw),
+ [keyword__FILE__] = O(kw),
+ [keyword__LINE__] = O(kw),
+ [keyword__ENCODING__] = O(kw),
+ [keyword_BEGIN] = O(kw),
+ [keyword_END] = O(kw),
+ [keyword_do_LAMBDA] = O(kw),
+ [tAMPER] = O(op),
+ [tANDOP] = O(op),
+ [tAREF] = O(op),
+ [tASET] = O(op),
+ [tASSOC] = O(op),
+ [tBACK_REF] = O(backref),
+ [tCHAR] = O(CHAR),
+ [tCMP] = O(op),
+ [tCOLON2] = O(op),
+ [tCOLON3] = O(op),
+ [tCONSTANT] = O(const),
+ [tCVAR] = O(cvar),
+ [tDOT2] = O(op),
+ [tDOT3] = O(op),
+ [tBDOT2] = O(op),
+ [tBDOT3] = O(op),
+ [tEQ] = O(op),
+ [tEQQ] = O(op),
+ [tFID] = O(ident),
+ [tFLOAT] = O(float),
+ [tGEQ] = O(op),
+ [tGVAR] = O(gvar),
+ [tIDENTIFIER] = O(ident),
+ [tIMAGINARY] = O(imaginary),
+ [tINTEGER] = O(int),
+ [tIVAR] = O(ivar),
+ [tLBRACE] = O(lbrace),
+ [tLBRACE_ARG] = O(lbrace),
+ ['{'] = O(lbrace),
+ ['}'] = O(rbrace),
+ [tLBRACK] = O(lbracket),
+ ['['] = O(lbracket),
+ [']'] = O(rbracket),
+ [tLEQ] = O(op),
+ [tLPAREN] = O(lparen),
+ [tLPAREN_ARG] = O(lparen),
+ ['('] = O(lparen),
+ [')'] = O(rparen),
+ [tLSHFT] = O(op),
+ [tMATCH] = O(op),
+ [tNEQ] = O(op),
+ [tNMATCH] = O(op),
+ [tNTH_REF] = O(backref),
+ [tOP_ASGN] = O(op),
+ [tOROP] = O(op),
+ [tPOW] = O(op),
+ [tQWORDS_BEG] = O(qwords_beg),
+ [tQSYMBOLS_BEG] = O(qsymbols_beg),
+ [tSYMBOLS_BEG] = O(symbols_beg),
+ [tRATIONAL] = O(rational),
+ [tREGEXP_BEG] = O(regexp_beg),
+ [tREGEXP_END] = O(regexp_end),
+ [tRSHFT] = O(op),
+ [tSTAR] = O(op),
+ [tDSTAR] = O(op),
+ [tANDDOT] = O(op),
+ [tSTRING_BEG] = O(tstring_beg),
+ [tSTRING_CONTENT] = O(tstring_content),
+ [tSTRING_DBEG] = O(embexpr_beg),
+ [tSTRING_DEND] = O(embexpr_end),
+ [tSTRING_DVAR] = O(embvar),
+ [tSTRING_END] = O(tstring_end),
+ [tSYMBEG] = O(symbeg),
+ [tUMINUS] = O(op),
+ [tUMINUS_NUM] = O(op),
+ [tUPLUS] = O(op),
+ [tWORDS_BEG] = O(words_beg),
+ [tXSTRING_BEG] = O(backtick),
+ [tLABEL] = O(label),
+ [tLABEL_END] = O(label_end),
+ [tLAMBDA] = O(tlambda),
+ [tLAMBEG] = O(tlambeg),
+
+ /* ripper specific tokens */
+ [tIGNORED_NL] = O(ignored_nl),
+ [tCOMMENT] = O(comment),
+ [tEMBDOC_BEG] = O(embdoc_beg),
+ [tEMBDOC] = O(embdoc),
+ [tEMBDOC_END] = O(embdoc_end),
+ [tSP] = O(sp),
+ [tHEREDOC_BEG] = O(heredoc_beg),
+ [tHEREDOC_END] = O(heredoc_end),
+ [k__END__] = O(__end__),
+ };
+#undef O
+
+ int i = (int)tok;
+ if (i >= 0 && i < numberof(offsets) && (i = offsets[i]) > 0) {
+ return *(const ID *)((const char *)&ripper_scanner_ids-1+i);
+ }
+ /* 128..256 are used as operator tokens */
+ if (tok < 128) {
+ return ripper_scanner_ids.ripper_id_CHAR;
+ }
+ rb_raise(rb_eRuntimeError, "[Ripper FATAL] unknown token %d", tok);
+
+ UNREACHABLE_RETURN(0);
+}
diff --git a/ext/ripper/eventids2.h b/ext/ripper/eventids2.h
new file mode 100644
index 0000000000..49e46432b9
--- /dev/null
+++ b/ext/ripper/eventids2.h
@@ -0,0 +1,8 @@
+#ifndef RIPPER_EVENTIDS2
+#define RIPPER_EVENTIDS2
+
+void ripper_init_eventids2(void);
+void ripper_init_eventids2_table(VALUE self);
+ID ripper_token2eventid(enum yytokentype tok);
+
+#endif /* RIPPER_EVENTIDS2 */
diff --git a/ext/ripper/extconf.rb b/ext/ripper/extconf.rb
new file mode 100644
index 0000000000..c3c56c27c5
--- /dev/null
+++ b/ext/ripper/extconf.rb
@@ -0,0 +1,18 @@
+#!ruby -s
+# frozen_string_literal: true
+
+require 'mkmf'
+require 'rbconfig'
+
+def main
+ $objs = %w(eventids1.o eventids2.o ripper.o ripper_init.o)
+ $distcleanfiles.concat %w(ripper.y ripper.c eventids1.c eventids1.h eventids2table.c ripper_init.c)
+ $cleanfiles.concat %w(ripper.E ripper.output y.output .eventids2-check)
+ $defs << '-DRIPPER'
+ $defs << '-DRIPPER_DEBUG' if $debug
+ $VPATH << '$(topdir)' << '$(top_srcdir)'
+ $INCFLAGS << ' -I$(topdir) -I$(top_srcdir)'
+ create_makefile 'ripper'
+end
+
+main
diff --git a/ext/ripper/lib/ripper.rb b/ext/ripper/lib/ripper.rb
new file mode 100644
index 0000000000..e937d65217
--- /dev/null
+++ b/ext/ripper/lib/ripper.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+require 'ripper/core'
+require 'ripper/lexer'
+require 'ripper/filter'
+require 'ripper/sexp'
+
+# Ripper is a Ruby script parser.
+#
+# You can get information from the parser with event-based style.
+# Information such as abstract syntax trees or simple lexical analysis of the
+# Ruby program.
+#
+# == Usage
+#
+# Ripper provides an easy interface for parsing your program into a symbolic
+# expression tree (or S-expression).
+#
+# Understanding the output of the parser may come as a challenge, it's
+# recommended you use PP to format the output for legibility.
+#
+# require 'ripper'
+# require 'pp'
+#
+# pp Ripper.sexp('def hello(world) "Hello, #{world}!"; end')
+# #=> [:program,
+# [[:def,
+# [:@ident, "hello", [1, 4]],
+# [:paren,
+# [:params, [[:@ident, "world", [1, 10]]], nil, nil, nil, nil, nil, nil]],
+# [:bodystmt,
+# [[:string_literal,
+# [:string_content,
+# [:@tstring_content, "Hello, ", [1, 18]],
+# [:string_embexpr, [[:var_ref, [:@ident, "world", [1, 27]]]]],
+# [:@tstring_content, "!", [1, 33]]]]],
+# nil,
+# nil,
+# nil]]]]
+#
+# You can see in the example above, the expression starts with +:program+.
+#
+# From here, a method definition at +:def+, followed by the method's identifier
+# <code>:@ident</code>. After the method's identifier comes the parentheses
+# +:paren+ and the method parameters under +:params+.
+#
+# Next is the method body, starting at +:bodystmt+ (+stmt+ meaning statement),
+# which contains the full definition of the method.
+#
+# In our case, we're simply returning a String, so next we have the
+# +:string_literal+ expression.
+#
+# Within our +:string_literal+ you'll notice two <code>@tstring_content</code>,
+# this is the literal part for <code>Hello, </code> and <code>!</code>. Between
+# the two <code>@tstring_content</code> statements is a +:string_embexpr+,
+# where _embexpr_ is an embedded expression. Our expression consists of a local
+# variable, or +var_ref+, with the identifier (<code>@ident</code>) of +world+.
+#
+# == Resources
+#
+# * {Ruby Inside}[http://www.rubyinside.com/using-ripper-to-see-how-ruby-is-parsing-your-code-5270.html]
+#
+# == Requirements
+#
+# * ruby 1.9 (support CVS HEAD only)
+# * bison 1.28 or later (Other yaccs do not work)
+#
+# == License
+#
+# Ruby License.
+#
+# - Minero Aoki
+# - aamine@loveruby.net
+# - http://i.loveruby.net
+class Ripper; end
diff --git a/ext/ripper/lib/ripper/core.rb b/ext/ripper/lib/ripper/core.rb
new file mode 100644
index 0000000000..fa075da5b9
--- /dev/null
+++ b/ext/ripper/lib/ripper/core.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+#
+# $Id$
+#
+# Copyright (c) 2003-2005 Minero Aoki
+#
+# This program is free software.
+# You can distribute and/or modify this program under the Ruby License.
+# For details of Ruby License, see ruby/COPYING.
+#
+
+require 'ripper.so'
+
+class Ripper
+
+ # Parses the given Ruby program read from +src+.
+ # +src+ must be a String or an IO or a object with a #gets method.
+ def Ripper.parse(src, filename = '(ripper)', lineno = 1)
+ new(src, filename, lineno).parse
+ end
+
+ # This array contains name of parser events.
+ PARSER_EVENTS = PARSER_EVENT_TABLE.keys
+
+ # This array contains name of scanner events.
+ SCANNER_EVENTS = SCANNER_EVENT_TABLE.keys
+
+ # This array contains name of all ripper events.
+ EVENTS = PARSER_EVENTS + SCANNER_EVENTS
+
+ private
+
+ # :stopdoc:
+ def _dispatch_0() nil end
+ def _dispatch_1(a) a end
+ def _dispatch_2(a, b) a end
+ def _dispatch_3(a, b, c) a end
+ def _dispatch_4(a, b, c, d) a end
+ def _dispatch_5(a, b, c, d, e) a end
+ def _dispatch_6(a, b, c, d, e, f) a end
+ def _dispatch_7(a, b, c, d, e, f, g) a end
+ # :startdoc:
+
+ #
+ # Parser Events
+ #
+
+ PARSER_EVENT_TABLE.each do |id, arity|
+ alias_method "on_#{id}", "_dispatch_#{arity}"
+ end
+
+ # This method is called when weak warning is produced by the parser.
+ # +fmt+ and +args+ is printf style.
+ def warn(fmt, *args)
+ end
+
+ # This method is called when strong warning is produced by the parser.
+ # +fmt+ and +args+ is printf style.
+ def warning(fmt, *args)
+ end
+
+ # This method is called when the parser found syntax error.
+ def compile_error(msg)
+ end
+
+ #
+ # Scanner Events
+ #
+
+ SCANNER_EVENTS.each do |id|
+ alias_method "on_#{id}", :_dispatch_1
+ end
+
+end
diff --git a/ext/ripper/lib/ripper/filter.rb b/ext/ripper/lib/ripper/filter.rb
new file mode 100644
index 0000000000..9955d30550
--- /dev/null
+++ b/ext/ripper/lib/ripper/filter.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+#
+# $Id$
+#
+# Copyright (c) 2004,2005 Minero Aoki
+#
+# This program is free software.
+# You can distribute and/or modify this program under the Ruby License.
+# For details of Ruby License, see ruby/COPYING.
+#
+
+require 'ripper/lexer'
+
+class Ripper
+
+ # This class handles only scanner events,
+ # which are dispatched in the 'right' order (same with input).
+ class Filter
+
+ # Creates a new Ripper::Filter instance, passes parameters +src+,
+ # +filename+, and +lineno+ to Ripper::Lexer.new
+ #
+ # The lexer is for internal use only.
+ def initialize(src, filename = '-', lineno = 1)
+ @__lexer = Lexer.new(src, filename, lineno)
+ @__line = nil
+ @__col = nil
+ @__state = nil
+ end
+
+ # The file name of the input.
+ def filename
+ @__lexer.filename
+ end
+
+ # The line number of the current token.
+ # This value starts from 1.
+ # This method is valid only in event handlers.
+ def lineno
+ @__line
+ end
+
+ # The column number of the current token.
+ # This value starts from 0.
+ # This method is valid only in event handlers.
+ def column
+ @__col
+ end
+
+ # The scanner's state of the current token.
+ # This value is the bitwise OR of zero or more of the +Ripper::EXPR_*+ constants.
+ def state
+ @__state
+ end
+
+ # Starts the parser.
+ # +init+ is a data accumulator and is passed to the next event handler (as
+ # of Enumerable#inject).
+ def parse(init = nil)
+ data = init
+ @__lexer.lex.each do |pos, event, tok, state|
+ @__line, @__col = *pos
+ @__state = state
+ data = if respond_to?(event, true)
+ then __send__(event, tok, data)
+ else on_default(event, tok, data)
+ end
+ end
+ data
+ end
+
+ private
+
+ # This method is called when some event handler is undefined.
+ # +event+ is :on_XXX, +token+ is the scanned token, and +data+ is a data
+ # accumulator.
+ #
+ # The return value of this method is passed to the next event handler (as
+ # of Enumerable#inject).
+ def on_default(event, token, data)
+ data
+ end
+
+ end
+
+end
diff --git a/ext/ripper/lib/ripper/lexer.rb b/ext/ripper/lib/ripper/lexer.rb
new file mode 100644
index 0000000000..9b849dfeae
--- /dev/null
+++ b/ext/ripper/lib/ripper/lexer.rb
@@ -0,0 +1,379 @@
+# frozen_string_literal: true
+#
+# $Id$
+#
+# Copyright (c) 2004,2005 Minero Aoki
+#
+# This program is free software.
+# You can distribute and/or modify this program under the Ruby License.
+# For details of Ruby License, see ruby/COPYING.
+#
+
+require 'ripper/core'
+
+class Ripper
+
+ # Tokenizes the Ruby program and returns an array of strings.
+ # The +filename+ and +lineno+ arguments are mostly ignored, since the
+ # return value is just the tokenized input.
+ # By default, this method does not handle syntax errors in +src+,
+ # use the +raise_errors+ keyword to raise a SyntaxError for an error in +src+.
+ #
+ # p Ripper.tokenize("def m(a) nil end")
+ # # => ["def", " ", "m", "(", "a", ")", " ", "nil", " ", "end"]
+ #
+ def Ripper.tokenize(src, filename = '-', lineno = 1, **kw)
+ Lexer.new(src, filename, lineno).tokenize(**kw)
+ end
+
+ # Tokenizes the Ruby program and returns an array of an array,
+ # which is formatted like
+ # <code>[[lineno, column], type, token, state]</code>.
+ # The +filename+ argument is mostly ignored.
+ # By default, this method does not handle syntax errors in +src+,
+ # use the +raise_errors+ keyword to raise a SyntaxError for an error in +src+.
+ #
+ # require 'ripper'
+ # require 'pp'
+ #
+ # pp Ripper.lex("def m(a) nil end")
+ # #=> [[[1, 0], :on_kw, "def", FNAME ],
+ # [[1, 3], :on_sp, " ", FNAME ],
+ # [[1, 4], :on_ident, "m", ENDFN ],
+ # [[1, 5], :on_lparen, "(", BEG|LABEL],
+ # [[1, 6], :on_ident, "a", ARG ],
+ # [[1, 7], :on_rparen, ")", ENDFN ],
+ # [[1, 8], :on_sp, " ", BEG ],
+ # [[1, 9], :on_kw, "nil", END ],
+ # [[1, 12], :on_sp, " ", END ],
+ # [[1, 13], :on_kw, "end", END ]]
+ #
+ def Ripper.lex(src, filename = '-', lineno = 1, **kw)
+ Lexer.new(src, filename, lineno).lex(**kw)
+ end
+
+ class Lexer < ::Ripper #:nodoc: internal use only
+ # :stopdoc:
+ class State
+ attr_reader :to_int, :to_s
+
+ def initialize(i)
+ @to_int = i
+ @to_s = Ripper.lex_state_name(i)
+ freeze
+ end
+
+ def [](index)
+ case index
+ when 0, :to_int
+ @to_int
+ when 1, :to_s
+ @to_s
+ else
+ nil
+ end
+ end
+
+ alias to_i to_int
+ alias inspect to_s
+ def pretty_print(q) q.text(to_s) end
+ def ==(i) super or to_int == i end
+ def &(i) self.class.new(to_int & i) end
+ def |(i) self.class.new(to_int | i) end
+ def allbits?(i) to_int.allbits?(i) end
+ def anybits?(i) to_int.anybits?(i) end
+ def nobits?(i) to_int.nobits?(i) end
+ end
+
+ class Elem
+ attr_accessor :pos, :event, :tok, :state, :message
+
+ def initialize(pos, event, tok, state, message = nil)
+ @pos = pos
+ @event = event
+ @tok = tok
+ @state = State.new(state)
+ @message = message
+ end
+
+ def [](index)
+ case index
+ when 0, :pos
+ @pos
+ when 1, :event
+ @event
+ when 2, :tok
+ @tok
+ when 3, :state
+ @state
+ when 4, :message
+ @message
+ else
+ nil
+ end
+ end
+
+ def inspect
+ "#<#{self.class}: #{event}@#{pos[0]}:#{pos[1]}:#{state}: #{tok.inspect}#{": " if message}#{message}>"
+ end
+
+ alias to_s inspect
+
+ def pretty_print(q)
+ q.group(2, "#<#{self.class}:", ">") {
+ q.breakable
+ q.text("#{event}@#{pos[0]}:#{pos[1]}")
+ q.breakable
+ state.pretty_print(q)
+ q.breakable
+ q.text("token: ")
+ tok.pretty_print(q)
+ if message
+ q.breakable
+ q.text("message: ")
+ q.text(message)
+ end
+ }
+ end
+
+ def to_a
+ if @message
+ [@pos, @event, @tok, @state, @message]
+ else
+ [@pos, @event, @tok, @state]
+ end
+ end
+ end
+
+ attr_reader :errors
+
+ def tokenize(**kw)
+ parse(**kw).sort_by(&:pos).map(&:tok)
+ end
+
+ def lex(**kw)
+ parse(**kw).sort_by(&:pos).map(&:to_a)
+ end
+
+ # parse the code and returns elements including errors.
+ def scan(**kw)
+ result = (parse(**kw) + errors + @stack.flatten).uniq.sort_by {|e| [*e.pos, (e.message ? -1 : 0)]}
+ result.each_with_index do |e, i|
+ if e.event == :on_parse_error and e.tok.empty? and (pre = result[i-1]) and
+ pre.pos[0] == e.pos[0] and (pre.pos[1] + pre.tok.size) == e.pos[1]
+ e.tok = pre.tok
+ e.pos[1] = pre.pos[1]
+ result[i-1] = e
+ result[i] = pre
+ end
+ end
+ result
+ end
+
+ def parse(raise_errors: false)
+ @errors = []
+ @buf = []
+ @stack = []
+ super()
+ @buf = @stack.pop unless @stack.empty?
+ if raise_errors and !@errors.empty?
+ raise SyntaxError, @errors.map(&:message).join(' ;')
+ end
+ @buf.flatten!
+ unless (result = @buf).empty?
+ result.concat(@buf) until (@buf = []; super(); @buf.flatten!; @buf.empty?)
+ end
+ result
+ end
+
+ private
+
+ unless SCANNER_EVENT_TABLE.key?(:ignored_sp)
+ SCANNER_EVENT_TABLE[:ignored_sp] = 1
+ SCANNER_EVENTS << :ignored_sp
+ EVENTS << :ignored_sp
+ end
+
+ def on_heredoc_dedent(v, w)
+ ignored_sp = []
+ heredoc = @buf.last
+ if Array === heredoc
+ heredoc.each_with_index do |e, i|
+ if Elem === e and e.event == :on_tstring_content and e.pos[1].zero?
+ tok = e.tok.dup if w > 0 and /\A\s/ =~ e.tok
+ if (n = dedent_string(e.tok, w)) > 0
+ if e.tok.empty?
+ e.tok = tok[0, n]
+ e.event = :on_ignored_sp
+ next
+ end
+ ignored_sp << [i, Elem.new(e.pos.dup, :on_ignored_sp, tok[0, n], e.state)]
+ e.pos[1] += n
+ end
+ end
+ end
+ end
+ ignored_sp.reverse_each do |i, e|
+ heredoc[i, 0] = [e]
+ end
+ v
+ end
+
+ def on_heredoc_beg(tok)
+ @stack.push @buf
+ buf = []
+ @buf.push buf
+ @buf = buf
+ @buf.push Elem.new([lineno(), column()], __callee__, tok, state())
+ end
+
+ def on_heredoc_end(tok)
+ @buf.push Elem.new([lineno(), column()], __callee__, tok, state())
+ @buf = @stack.pop unless @stack.empty?
+ end
+
+ def _push_token(tok)
+ e = Elem.new([lineno(), column()], __callee__, tok, state())
+ @buf.push(e)
+ e
+ end
+
+ def on_error1(mesg)
+ @errors.push Elem.new([lineno(), column()], __callee__, token(), state(), mesg)
+ end
+
+ def on_error2(mesg, elem)
+ if elem
+ elem = Elem.new(elem.pos, __callee__, elem.tok, elem.state, mesg)
+ else
+ elem = Elem.new([lineno(), column()], __callee__, token(), state(), mesg)
+ end
+ @errors.push elem
+ end
+ PARSER_EVENTS.grep(/_error\z/) do |e|
+ arity = PARSER_EVENT_TABLE.fetch(e)
+ alias_method "on_#{e}", "on_error#{arity}"
+ end
+ alias compile_error on_error1
+
+ (SCANNER_EVENTS.map {|event|:"on_#{event}"} - private_instance_methods(false)).each do |event|
+ alias_method event, :_push_token
+ end
+ # :startdoc:
+ end
+
+ # [EXPERIMENTAL]
+ # Parses +src+ and return a string which was matched to +pattern+.
+ # +pattern+ should be described as Regexp.
+ #
+ # require 'ripper'
+ #
+ # p Ripper.slice('def m(a) nil end', 'ident') #=> "m"
+ # p Ripper.slice('def m(a) nil end', '[ident lparen rparen]+') #=> "m(a)"
+ # p Ripper.slice("<<EOS\nstring\nEOS",
+ # 'heredoc_beg nl $(tstring_content*) heredoc_end', 1)
+ # #=> "string\n"
+ #
+ def Ripper.slice(src, pattern, n = 0)
+ if m = token_match(src, pattern)
+ then m.string(n)
+ else nil
+ end
+ end
+
+ def Ripper.token_match(src, pattern) #:nodoc:
+ TokenPattern.compile(pattern).match(src)
+ end
+
+ class TokenPattern #:nodoc:
+
+ class Error < ::StandardError # :nodoc:
+ end
+ class CompileError < Error # :nodoc:
+ end
+ class MatchError < Error # :nodoc:
+ end
+
+ class << self
+ alias compile new
+ end
+
+ def initialize(pattern)
+ @source = pattern
+ @re = compile(pattern)
+ end
+
+ def match(str)
+ match_list(::Ripper.lex(str))
+ end
+
+ def match_list(tokens)
+ if m = @re.match(map_tokens(tokens))
+ then MatchData.new(tokens, m)
+ else nil
+ end
+ end
+
+ private
+
+ def compile(pattern)
+ if m = /[^\w\s$()\[\]{}?*+\.]/.match(pattern)
+ raise CompileError, "invalid char in pattern: #{m[0].inspect}"
+ end
+ buf = +''
+ pattern.scan(/(?:\w+|\$\(|[()\[\]\{\}?*+\.]+)/) do |tok|
+ case tok
+ when /\w/
+ buf.concat map_token(tok)
+ when '$('
+ buf.concat '('
+ when '('
+ buf.concat '(?:'
+ when /[?*\[\])\.]/
+ buf.concat tok
+ else
+ raise 'must not happen'
+ end
+ end
+ Regexp.compile(buf)
+ rescue RegexpError => err
+ raise CompileError, err.message
+ end
+
+ def map_tokens(tokens)
+ tokens.map {|pos,type,str| map_token(type.to_s.delete_prefix('on_')) }.join
+ end
+
+ MAP = {}
+ seed = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
+ SCANNER_EVENT_TABLE.each do |ev, |
+ raise CompileError, "[RIPPER FATAL] too many system token" if seed.empty?
+ MAP[ev.to_s.delete_prefix('on_')] = seed.shift
+ end
+
+ def map_token(tok)
+ MAP[tok] or raise CompileError, "unknown token: #{tok}"
+ end
+
+ class MatchData # :nodoc:
+ def initialize(tokens, match)
+ @tokens = tokens
+ @match = match
+ end
+
+ def string(n = 0)
+ return nil unless @match
+ match(n).join
+ end
+
+ private
+
+ def match(n = 0)
+ return [] unless @match
+ @tokens[@match.begin(n)...@match.end(n)].map {|pos,type,str| str }
+ end
+ end
+
+ end
+
+end
diff --git a/ext/ripper/lib/ripper/sexp.rb b/ext/ripper/lib/ripper/sexp.rb
new file mode 100644
index 0000000000..b1d553b1da
--- /dev/null
+++ b/ext/ripper/lib/ripper/sexp.rb
@@ -0,0 +1,187 @@
+# frozen_string_literal: true
+#
+# $Id$
+#
+# Copyright (c) 2004,2005 Minero Aoki
+#
+# This program is free software.
+# You can distribute and/or modify this program under the Ruby License.
+# For details of Ruby License, see ruby/COPYING.
+#
+
+require 'ripper/core'
+
+class Ripper
+
+ # [EXPERIMENTAL]
+ # Parses +src+ and create S-exp tree.
+ # Returns more readable tree rather than Ripper.sexp_raw.
+ # This method is mainly for developer use.
+ # The +filename+ argument is mostly ignored.
+ # By default, this method does not handle syntax errors in +src+,
+ # returning +nil+ in such cases. Use the +raise_errors+ keyword
+ # to raise a SyntaxError for an error in +src+.
+ #
+ # require 'ripper'
+ # require 'pp'
+ #
+ # pp Ripper.sexp("def m(a) nil end")
+ # #=> [:program,
+ # [[:def,
+ # [:@ident, "m", [1, 4]],
+ # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]],
+ # [:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]]
+ #
+ def Ripper.sexp(src, filename = '-', lineno = 1, raise_errors: false)
+ builder = SexpBuilderPP.new(src, filename, lineno)
+ sexp = builder.parse
+ if builder.error?
+ if raise_errors
+ raise SyntaxError, builder.error
+ end
+ else
+ sexp
+ end
+ end
+
+ # [EXPERIMENTAL]
+ # Parses +src+ and create S-exp tree.
+ # This method is mainly for developer use.
+ # The +filename+ argument is mostly ignored.
+ # By default, this method does not handle syntax errors in +src+,
+ # returning +nil+ in such cases. Use the +raise_errors+ keyword
+ # to raise a SyntaxError for an error in +src+.
+ #
+ # require 'ripper'
+ # require 'pp'
+ #
+ # pp Ripper.sexp_raw("def m(a) nil end")
+ # #=> [:program,
+ # [:stmts_add,
+ # [:stmts_new],
+ # [:def,
+ # [:@ident, "m", [1, 4]],
+ # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil]],
+ # [:bodystmt,
+ # [:stmts_add, [:stmts_new], [:var_ref, [:@kw, "nil", [1, 9]]]],
+ # nil,
+ # nil,
+ # nil]]]]
+ #
+ def Ripper.sexp_raw(src, filename = '-', lineno = 1, raise_errors: false)
+ builder = SexpBuilder.new(src, filename, lineno)
+ sexp = builder.parse
+ if builder.error?
+ if raise_errors
+ raise SyntaxError, builder.error
+ end
+ else
+ sexp
+ end
+ end
+
+ class SexpBuilder < ::Ripper #:nodoc:
+ attr_reader :error
+
+ private
+
+ def dedent_element(e, width)
+ if (n = dedent_string(e[1], width)) > 0
+ e[2][1] += n
+ end
+ e
+ end
+
+ def on_heredoc_dedent(val, width)
+ sub = proc do |cont|
+ cont.map! do |e|
+ if Array === e
+ case e[0]
+ when :@tstring_content
+ e = dedent_element(e, width)
+ when /_add\z/
+ e[1] = sub[e[1]]
+ end
+ elsif String === e
+ dedent_string(e, width)
+ end
+ e
+ end
+ end
+ sub[val]
+ val
+ end
+
+ events = private_instance_methods(false).grep(/\Aon_/) {$'.to_sym}
+ (PARSER_EVENTS - events).each do |event|
+ module_eval(<<-End, __FILE__, __LINE__ + 1)
+ def on_#{event}(*args)
+ args.unshift :#{event}
+ args
+ end
+ End
+ end
+
+ SCANNER_EVENTS.each do |event|
+ module_eval(<<-End, __FILE__, __LINE__ + 1)
+ def on_#{event}(tok)
+ [:@#{event}, tok, [lineno(), column()]]
+ end
+ End
+ end
+
+ def on_error(mesg)
+ @error = mesg
+ end
+ remove_method :on_parse_error
+ alias on_parse_error on_error
+ alias compile_error on_error
+ end
+
+ class SexpBuilderPP < SexpBuilder #:nodoc:
+ private
+
+ def on_heredoc_dedent(val, width)
+ val.map! do |e|
+ next e if Symbol === e and /_content\z/ =~ e
+ if Array === e and e[0] == :@tstring_content
+ e = dedent_element(e, width)
+ elsif String === e
+ dedent_string(e, width)
+ end
+ e
+ end
+ val
+ end
+
+ def _dispatch_event_new
+ []
+ end
+
+ def _dispatch_event_push(list, item)
+ list.push item
+ list
+ end
+
+ def on_mlhs_paren(list)
+ [:mlhs, *list]
+ end
+
+ def on_mlhs_add_star(list, star)
+ list.push([:rest_param, star])
+ end
+
+ def on_mlhs_add_post(list, post)
+ list.concat(post)
+ end
+
+ PARSER_EVENT_TABLE.each do |event, arity|
+ if /_new\z/ =~ event and arity == 0
+ alias_method "on_#{event}", :_dispatch_event_new
+ elsif /_add\z/ =~ event
+ alias_method "on_#{event}", :_dispatch_event_push
+ end
+ end
+ end
+
+end
diff --git a/ext/ripper/ripper_init.c.tmpl b/ext/ripper/ripper_init.c.tmpl
new file mode 100644
index 0000000000..11e432423d
--- /dev/null
+++ b/ext/ripper/ripper_init.c.tmpl
@@ -0,0 +1,680 @@
+%# -*- c -*-
+#include "ruby/ruby.h"
+#include "ruby/encoding.h"
+#include "internal.h"
+#include "rubyparser.h"
+#define YYSTYPE_IS_DECLARED
+#include "parse.h"
+#include "internal/parse.h"
+#include "internal/ruby_parser.h"
+#include "node.h"
+#include "eventids1.h"
+#include "eventids2.h"
+#include "ripper_init.h"
+
+#define STR_NEW2(ptr) rb_enc_str_new((ptr),strlen(ptr),rb_ruby_parser_enc(p))
+#define RIPPER_VERSION "0.1.0"
+
+ID id_warn, id_warning, id_gets, id_assoc;
+
+enum lex_type {
+ lex_type_str,
+ lex_type_io,
+ lex_type_generic,
+};
+
+struct ripper {
+ rb_parser_t *p;
+ enum lex_type type;
+ union {
+ struct lex_pointer_string ptr_str;
+ VALUE val;
+ } data;
+};
+
+static void
+ripper_parser_mark2(void *ptr)
+{
+ struct ripper *r = (struct ripper*)ptr;
+ if (r->p) {
+ ripper_parser_mark(r->p);
+
+ switch (r->type) {
+ case lex_type_str:
+ rb_gc_mark(r->data.ptr_str.str);
+ break;
+ case lex_type_io:
+ rb_gc_mark(r->data.val);
+ break;
+ case lex_type_generic:
+ rb_gc_mark(r->data.val);
+ break;
+ }
+ }
+}
+
+static void
+ripper_parser_free2(void *ptr)
+{
+ struct ripper *r = (struct ripper*)ptr;
+ if (r->p) ripper_parser_free(r->p);
+ xfree(r);
+}
+
+static size_t
+ripper_parser_memsize2(const void *ptr)
+{
+ struct ripper *r = (struct ripper*)ptr;
+ return (r->p) ? ripper_parser_memsize(r->p) : 0;
+}
+
+static const rb_data_type_t parser_data_type = {
+ "ripper",
+ {
+ ripper_parser_mark2,
+ ripper_parser_free2,
+ ripper_parser_memsize2,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static rb_parser_string_t *
+ripper_lex_get_generic(struct parser_params *p, rb_parser_input_data input, int line_count)
+{
+ VALUE src = (VALUE)input;
+ VALUE line = rb_funcallv_public(src, id_gets, 0, 0);
+ if (NIL_P(line)) return 0;
+ if (!RB_TYPE_P(line, T_STRING)) {
+ rb_raise(rb_eTypeError,
+ "gets returned %"PRIsVALUE" (expected String or nil)",
+ rb_obj_class(line));
+ }
+ return rb_str_to_parser_string(p, line);
+}
+
+void
+ripper_compile_error(struct parser_params *p, const char *fmt, ...)
+{
+ VALUE str;
+ va_list args;
+
+ va_start(args, fmt);
+ str = rb_vsprintf(fmt, args);
+ va_end(args);
+ rb_funcall(ripper_value(p), rb_intern("compile_error"), 1, str);
+ ripper_error(p);
+}
+
+static rb_parser_string_t *
+ripper_lex_io_get(struct parser_params *p, rb_parser_input_data input, int line_count)
+{
+ VALUE src = (VALUE)input;
+ VALUE line = rb_io_gets(src);
+ if (NIL_P(line)) return 0;
+ return rb_str_to_parser_string(p, line);
+}
+
+static rb_parser_string_t *
+ripper_lex_get_str(struct parser_params *p, rb_parser_input_data input, int line_count)
+{
+ return rb_parser_lex_get_str(p, (struct lex_pointer_string *)input);
+}
+
+static VALUE
+ripper_s_allocate(VALUE klass)
+{
+ struct ripper *r;
+
+ VALUE self = TypedData_Make_Struct(klass, struct ripper,
+ &parser_data_type, r);
+
+#ifdef UNIVERSAL_PARSER
+ const rb_parser_config_t *config = rb_ruby_parser_config();
+ r->p = rb_ripper_parser_params_allocate(config);
+#else
+ r->p = rb_ruby_ripper_parser_allocate();
+#endif
+ rb_ruby_parser_set_value(r->p, self);
+ return self;
+}
+
+static struct parser_params *
+ripper_parser_params(VALUE self, bool initialized)
+{
+ struct ripper *r;
+ struct parser_params *p;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ p = r->p;
+ if (initialized && !rb_ruby_ripper_initialized_p(p)) {
+ rb_raise(rb_eArgError, "method called for uninitialized object");
+ }
+ return p;
+}
+
+/*
+ * call-seq:
+ * ripper.error? -> Boolean
+ *
+ * Return true if parsed source has errors.
+ */
+static VALUE
+ripper_error_p(VALUE vparser)
+{
+ struct parser_params *p = ripper_parser_params(vparser, false);
+
+ return RBOOL(rb_ruby_parser_error_p(p));
+}
+
+/*
+ * call-seq:
+ * ripper.end_seen? -> Boolean
+ *
+ * Return true if parsed source ended by +\_\_END\_\_+.
+ */
+static VALUE
+ripper_parser_end_seen_p(VALUE vparser)
+{
+ struct parser_params *p = ripper_parser_params(vparser, false);
+
+ return RBOOL(rb_ruby_parser_end_seen_p(p));
+}
+
+/*
+ * call-seq:
+ * ripper.encoding -> encoding
+ *
+ * Return encoding of the source.
+ */
+static VALUE
+ripper_parser_encoding(VALUE vparser)
+{
+ struct parser_params *p = ripper_parser_params(vparser, false);
+
+ return rb_enc_from_encoding(rb_ruby_parser_encoding(p));
+}
+
+/*
+ * call-seq:
+ * ripper.yydebug -> true or false
+ *
+ * Get yydebug.
+ */
+static VALUE
+ripper_parser_get_yydebug(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, false);
+
+ return RBOOL(rb_ruby_parser_get_yydebug(p));
+}
+
+/*
+ * call-seq:
+ * ripper.yydebug = flag
+ *
+ * Set yydebug.
+ */
+static VALUE
+ripper_parser_set_yydebug(VALUE self, VALUE flag)
+{
+ struct parser_params *p = ripper_parser_params(self, false);
+
+ rb_ruby_parser_set_yydebug(p, RTEST(flag));
+ return flag;
+}
+
+/*
+ * call-seq:
+ * ripper.debug_output -> obj
+ *
+ * Get debug output.
+ */
+static VALUE
+ripper_parser_get_debug_output(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, false);
+
+ return rb_ruby_parser_debug_output(p);
+}
+
+/*
+ * call-seq:
+ * ripper.debug_output = obj
+ *
+ * Set debug output.
+ */
+static VALUE
+ripper_parser_set_debug_output(VALUE self, VALUE output)
+{
+ struct parser_params *p = ripper_parser_params(self, false);
+
+ rb_ruby_parser_set_debug_output(p, output);
+ return output;
+}
+
+static int
+ripper_parser_dedent_string(struct parser_params *p, VALUE string, int width)
+{
+ int col;
+ rb_parser_string_t *str;
+ str = rb_str_to_parser_string(p, string);
+ col = rb_ruby_ripper_dedent_string(p, str, width);
+ rb_str_replace(string, rb_str_new_parser_string(str));
+ rb_parser_string_free(p, str);
+ return col;
+}
+
+#ifdef UNIVERSAL_PARSER
+struct dedent_string_arg {
+ struct parser_params *p;
+ VALUE input;
+ VALUE width;
+};
+
+static VALUE
+parser_dedent_string0(VALUE a)
+{
+ struct dedent_string_arg *arg = (void *)a;
+ int wid, col;
+
+ StringValue(arg->input);
+ wid = NUM2UINT(arg->width);
+ col = ripper_parser_dedent_string(arg->p, arg->input, wid);
+ return INT2NUM(col);
+}
+
+static VALUE
+parser_free(VALUE a)
+{
+ struct parser_params *p = (void *)a;
+
+ rb_ruby_parser_free(p);
+ return Qnil;
+}
+#endif
+
+/*
+ * call-seq:
+ * Ripper.dedent_string(input, width) -> Integer
+ *
+ * USE OF RIPPER LIBRARY ONLY.
+ *
+ * Strips up to +width+ leading whitespaces from +input+,
+ * and returns the stripped column width.
+ */
+#ifdef UNIVERSAL_PARSER
+static VALUE
+parser_dedent_string(VALUE self, VALUE input, VALUE width)
+{
+ struct parser_params *p;
+ struct dedent_string_arg args;
+
+ p = rb_parser_params_new();
+
+ args.p = p;
+ args.input = input;
+ args.width = width;
+ return rb_ensure(parser_dedent_string0, (VALUE)&args, parser_free, (VALUE)p);
+}
+#else
+static VALUE
+parser_dedent_string(VALUE self, VALUE input, VALUE width)
+{
+ int wid, col;
+
+ StringValue(input);
+ wid = NUM2UINT(width);
+ col = ripper_parser_dedent_string(0, input, wid);
+ return INT2NUM(col);
+}
+#endif
+
+/*
+ * call-seq:
+ * Ripper.new(src, filename="(ripper)", lineno=1) -> ripper
+ *
+ * Create a new Ripper object.
+ * _src_ must be a String, an IO, or an Object which has #gets method.
+ *
+ * This method does not starts parsing.
+ * See also Ripper#parse and Ripper.parse.
+ */
+static VALUE
+ripper_initialize(int argc, VALUE *argv, VALUE self)
+{
+ struct ripper *r;
+ struct parser_params *p;
+ VALUE src, fname, lineno;
+ rb_parser_lex_gets_func *gets;
+ VALUE sourcefile_string;
+ const char *sourcefile;
+ int sourceline;
+ rb_parser_input_data input;
+
+ p = ripper_parser_params(self, false);
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ rb_scan_args(argc, argv, "12", &src, &fname, &lineno);
+ if (RB_TYPE_P(src, T_FILE)) {
+ gets = ripper_lex_io_get;
+ r->type = lex_type_io;
+ r->data.val = src;
+ input = (rb_parser_input_data)src;
+ }
+ else if (rb_respond_to(src, id_gets)) {
+ gets = ripper_lex_get_generic;
+ r->type = lex_type_generic;
+ r->data.val = src;
+ input = (rb_parser_input_data)src;
+ }
+ else {
+ StringValue(src);
+ gets = ripper_lex_get_str;
+ r->type = lex_type_str;
+ r->data.ptr_str.str = src;
+ r->data.ptr_str.ptr = 0;
+ input = (rb_parser_input_data)&r->data.ptr_str;
+ }
+ if (NIL_P(fname)) {
+ fname = STR_NEW2("(ripper)");
+ OBJ_FREEZE(fname);
+ }
+ else {
+ StringValueCStr(fname);
+ fname = rb_str_new_frozen(fname);
+ }
+ rb_ruby_ripper_parser_initialize(p);
+
+ sourcefile_string = fname;
+ sourcefile = RSTRING_PTR(fname);
+ sourceline = NIL_P(lineno) ? 0 : NUM2INT(lineno) - 1;
+
+ rb_ruby_parser_ripper_initialize(p, gets, input, sourcefile_string, sourcefile, sourceline);
+
+ return Qnil;
+}
+
+static VALUE
+ripper_parse0(VALUE vparser)
+{
+ struct parser_params *p = ripper_parser_params(vparser, false);
+
+ rb_ruby_ripper_parse0(p);
+ return rb_ruby_parser_result(p);
+}
+
+static VALUE
+ripper_ensure(VALUE vparser)
+{
+ struct parser_params *p = ripper_parser_params(vparser, false);
+
+ rb_ruby_parser_set_parsing_thread(p, Qnil);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * ripper.parse
+ *
+ * Start parsing and returns the value of the root action.
+ */
+static VALUE
+ripper_parse(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, true);
+ VALUE result;
+
+ if (!NIL_P(rb_ruby_parser_parsing_thread(p))) {
+ if (rb_ruby_parser_parsing_thread(p) == rb_thread_current())
+ rb_raise(rb_eArgError, "Ripper#parse is not reentrant");
+ else
+ rb_raise(rb_eArgError, "Ripper#parse is not multithread-safe");
+ }
+ rb_ruby_parser_set_parsing_thread(p, rb_thread_current());
+ result = rb_ensure(ripper_parse0, self, ripper_ensure, self);
+ RB_GC_GUARD(self);
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * ripper.column -> Integer
+ *
+ * Return column number of current parsing line.
+ * This number starts from 0.
+ */
+static VALUE
+ripper_column(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, true);
+ long col;
+
+ if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
+ col = rb_ruby_ripper_column(p);
+ return LONG2NUM(col);
+}
+
+/*
+ * call-seq:
+ * ripper.filename -> String
+ *
+ * Return current parsing filename.
+ */
+static VALUE
+ripper_filename(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, true);
+
+ return rb_ruby_parser_ruby_sourcefile_string(p);
+}
+
+/*
+ * call-seq:
+ * ripper.lineno -> Integer
+ *
+ * Return line number of current parsing line.
+ * This number starts from 1.
+ */
+static VALUE
+ripper_lineno(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, true);
+
+ if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
+ return INT2NUM(rb_ruby_parser_ruby_sourceline(p));
+}
+
+/*
+ * call-seq:
+ * ripper.state -> Integer
+ *
+ * Return scanner state of current token.
+ */
+static VALUE
+ripper_state(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, true);
+
+ if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
+ return INT2NUM(rb_ruby_parser_lex_state(p));
+}
+
+/*
+ * call-seq:
+ * ripper.token -> String
+ *
+ * Return the current token string.
+ */
+static VALUE
+ripper_token(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, true);
+ long pos, len;
+ VALUE str;
+
+ if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
+ pos = rb_ruby_ripper_column(p);
+ len = rb_ruby_ripper_token_len(p);
+ str = rb_str_new_parser_string(rb_ruby_ripper_lex_lastline(p));
+ return rb_str_subseq(str, pos, len);
+}
+
+#ifdef RIPPER_DEBUG
+/* :nodoc: */
+static VALUE
+ripper_assert_Qundef(VALUE self, VALUE obj, VALUE msg)
+{
+ StringValue(msg);
+ if (UNDEF_P(obj)) {
+ rb_raise(rb_eArgError, "%"PRIsVALUE, msg);
+ }
+ return Qnil;
+}
+
+/* :nodoc: */
+static VALUE
+ripper_raw_value(VALUE self, VALUE obj)
+{
+ return ULONG2NUM(obj);
+}
+
+/* :nodoc: */
+static VALUE
+ripper_validate_object(VALUE self, VALUE x)
+{
+ if (x == Qfalse) return x;
+ if (x == Qtrue) return x;
+ if (NIL_P(x)) return x;
+ if (UNDEF_P(x))
+ rb_raise(rb_eArgError, "Qundef given");
+ if (FIXNUM_P(x)) return x;
+ if (SYMBOL_P(x)) return x;
+ switch (BUILTIN_TYPE(x)) {
+ case T_STRING:
+ case T_OBJECT:
+ case T_ARRAY:
+ case T_BIGNUM:
+ case T_FLOAT:
+ case T_COMPLEX:
+ case T_RATIONAL:
+ break;
+ default:
+ rb_raise(rb_eArgError, "wrong type of ruby object: %p (%s)",
+ (void *)x, rb_obj_classname(x));
+ }
+ if (!RBASIC_CLASS(x)) {
+ rb_raise(rb_eArgError, "hidden ruby object: %p (%s)",
+ (void *)x, rb_builtin_type_name(TYPE(x)));
+ }
+ return x;
+}
+#endif
+
+#ifdef UNIVERSAL_PARSER
+struct lex_state_name_arg {
+ struct parser_params *p;
+ VALUE state;
+};
+
+static VALUE
+lex_state_name0(VALUE a)
+{
+ struct lex_state_name_arg *arg = (void *)a;
+
+ return rb_ruby_ripper_lex_state_name(arg->p, NUM2INT(arg->state));
+}
+#endif
+
+/*
+ * call-seq:
+ * Ripper.lex_state_name(integer) -> string
+ *
+ * Returns a string representation of lex_state.
+ */
+#ifdef UNIVERSAL_PARSER
+static VALUE
+ripper_lex_state_name(VALUE self, VALUE state)
+{
+ struct parser_params *p;
+ struct lex_state_name_arg args;
+
+ p = rb_parser_params_new();
+
+ args.p = p;
+ args.state = state;
+
+ return rb_ensure(lex_state_name0, (VALUE)&args, parser_free, (VALUE)p);
+}
+#else
+static VALUE
+ripper_lex_state_name(VALUE self, VALUE state)
+{
+ return rb_ruby_ripper_lex_state_name(0, NUM2INT(state));
+}
+#endif
+
+void
+Init_ripper(void)
+{
+ ripper_init_eventids1();
+ ripper_init_eventids2();
+ id_warn = rb_intern_const("warn");
+ id_warning = rb_intern_const("warning");
+ id_gets = rb_intern_const("gets");
+ id_assoc = rb_intern_const("=>");
+
+ InitVM(ripper);
+}
+
+void
+InitVM_ripper(void)
+{
+ VALUE Ripper;
+
+ Ripper = rb_define_class("Ripper", rb_cObject);
+ /* version of Ripper */
+ rb_define_const(Ripper, "Version", rb_usascii_str_new2(RIPPER_VERSION));
+ rb_define_alloc_func(Ripper, ripper_s_allocate);
+ rb_define_method(Ripper, "initialize", ripper_initialize, -1);
+ rb_define_method(Ripper, "parse", ripper_parse, 0);
+ rb_define_method(Ripper, "column", ripper_column, 0);
+ rb_define_method(Ripper, "filename", ripper_filename, 0);
+ rb_define_method(Ripper, "lineno", ripper_lineno, 0);
+ rb_define_method(Ripper, "state", ripper_state, 0);
+ rb_define_method(Ripper, "token", ripper_token, 0);
+ rb_define_method(Ripper, "end_seen?", ripper_parser_end_seen_p, 0);
+ rb_define_method(Ripper, "encoding", ripper_parser_encoding, 0);
+ rb_define_method(Ripper, "yydebug", ripper_parser_get_yydebug, 0);
+ rb_define_method(Ripper, "yydebug=", ripper_parser_set_yydebug, 1);
+ rb_define_method(Ripper, "debug_output", ripper_parser_get_debug_output, 0);
+ rb_define_method(Ripper, "debug_output=", ripper_parser_set_debug_output, 1);
+ rb_define_method(Ripper, "error?", ripper_error_p, 0);
+#ifdef RIPPER_DEBUG
+ rb_define_method(Ripper, "assert_Qundef", ripper_assert_Qundef, 2);
+ rb_define_method(Ripper, "rawVALUE", ripper_raw_value, 1);
+ rb_define_method(Ripper, "validate_object", ripper_validate_object, 1);
+#endif
+
+ rb_define_singleton_method(Ripper, "dedent_string", parser_dedent_string, 2);
+ rb_define_private_method(Ripper, "dedent_string", parser_dedent_string, 2);
+
+ rb_define_singleton_method(Ripper, "lex_state_name", ripper_lex_state_name, 1);
+
+<% @exprs.each do |expr, desc| -%>
+ /* <%=desc%> */
+ rb_define_const(Ripper, "<%=expr%>", INT2NUM(<%=expr%>));
+<% end %>
+ ripper_init_eventids1_table(Ripper);
+ ripper_init_eventids2_table(Ripper);
+
+# if 0
+ /* Hack to let RDoc document SCRIPT_LINES__ */
+
+ /*
+ * When a Hash is assigned to +SCRIPT_LINES__+ the contents of files loaded
+ * after the assignment will be added as an Array of lines with the file
+ * name as the key.
+ */
+ rb_define_global_const("SCRIPT_LINES__", Qnil);
+#endif
+}
diff --git a/ext/ripper/ripper_init.h b/ext/ripper/ripper_init.h
new file mode 100644
index 0000000000..9d228107d1
--- /dev/null
+++ b/ext/ripper/ripper_init.h
@@ -0,0 +1,6 @@
+#ifndef RIPPER_INIT_H
+#define RIPPER_INIT_H
+
+PRINTF_ARGS(void ripper_compile_error(struct parser_params*, const char *fmt, ...), 2, 3);
+
+#endif /* RIPPER_INIT_H */
diff --git a/ext/ripper/tools/dsl.rb b/ext/ripper/tools/dsl.rb
new file mode 100644
index 0000000000..38f859dd97
--- /dev/null
+++ b/ext/ripper/tools/dsl.rb
@@ -0,0 +1,181 @@
+# frozen_string_literal: true
+
+# Simple DSL implementation for Ripper code generation
+#
+# input: /*% ripper: stmts_add!(stmts_new!, void_stmt!) %*/
+# output:
+# VALUE v1, v2;
+# v1 = dispatch0(stmts_new);
+# v2 = dispatch0(void_stmt);
+# $$ = dispatch2(stmts_add, v1, v2);
+#
+# - The code must be a single line.
+#
+# - The code is basically Ruby code, even if it appears like in C and
+# the result will be processed as C. e.g., comments need to be in
+# Ruby style.
+
+class DSL
+ TAG_PATTERN = /(?><[a-zA-Z0-9_]+>)/.source
+ NAME_PATTERN = /(?>\$|\d+|[a-zA-Z_][a-zA-Z0-9_]*|\[[a-zA-Z_.][-a-zA-Z0-9_.]*\])(?>(?:\.|->)[a-zA-Z_][a-zA-Z0-9_]*)*/.source
+ NOT_REF_PATTERN = /(?>\#.*|[^\"$@]*|"(?>\\.|[^\"])*")/.source
+
+ def self.line?(line, lineno = nil, indent: nil)
+ if %r<(?<space>\s*)/\*% *ripper(?:\[(?<option>.*?)\])?: *(?<code>.*?) *%\*/> =~ line
+ new(code, comma_split(option), lineno, indent: indent || space)
+ end
+ end
+
+ def self.comma_split(str)
+ str or return []
+ str.scan(/(([^(,)]+|\((?:,|\g<0>)*\))+)/).map(&:first)
+ end
+
+ using Module.new {
+ refine Array do
+ def to_s
+ if empty?
+ "rb_ary_new()"
+ else
+ "rb_ary_new_from_args(#{size}, #{map(&:to_s).join(', ')})"
+ end
+ end
+ end
+ }
+
+ class Var
+ class Table < Hash
+ def initialize(&block)
+ super() {|tbl, arg|
+ tbl.fetch(arg, &block)
+ }
+ end
+
+ def fetch(arg, &block)
+ super {
+ self[arg] = Var.new(self, arg, &block)
+ }
+ end
+
+ def add(&block)
+ v = new_var
+ self[v] = Var.new(self, v, &block)
+ end
+
+ def defined?(name)
+ name = name.to_s
+ any? {|_, v| v.var == name}
+ end
+
+ def new_var
+ "v#{size+1}"
+ end
+ end
+
+ attr_reader :var, :value
+
+ PRETTY_PRINT_INSTANCE_VARIABLES = instance_methods(false).freeze
+
+ def pretty_print_instance_variables
+ PRETTY_PRINT_INSTANCE_VARIABLES
+ end
+
+ alias to_s var
+
+ def initialize(table, arg, &block)
+ @var = table.new_var
+ @value = yield arg
+ @table = table
+ end
+
+ # Indexing.
+ #
+ # $:1 -> v1=get_value($:1)
+ # $:1[0] -> rb_ary_entry(v1, 0)
+ # $:1[0..1] -> [rb_ary_entry(v1, 0), rb_ary_entry(v1, 1)]
+ # *$:1[0..1] -> rb_ary_entry(v1, 0), rb_ary_entry(v1, 1)
+ #
+ # Splat needs `[range]` because `Var` does not have the length info.
+ def [](idx)
+ if ::Range === idx
+ idx.map {|i| self[i]}
+ else
+ @table.fetch("#@var[#{idx}]") {"rb_ary_entry(#{@var}, #{idx})"}
+ end
+ end
+ end
+
+ def initialize(code, options, lineno = nil, indent: "\t\t\t")
+ @lineno = lineno
+ @indent = indent
+ @events = {}
+ @error = options.include?("error")
+ if options.include?("final")
+ @final = "p->result"
+ else
+ @final = (options.grep(/\A\$#{NAME_PATTERN}\z/o)[0] || "p->s_lvalue")
+ end
+
+ bind = dsl_binding
+ @var_table = Var::Table.new {|arg| "get_value(#{arg})"}
+ code = code.gsub(%r[\G#{NOT_REF_PATTERN}\K(\$|\$:|@)#{TAG_PATTERN}?#{NAME_PATTERN}]o) {
+ if (arg = $&) == "$:$"
+ '"p->s_lvalue"'
+ elsif arg.start_with?("$:")
+ "(#{@var_table[arg]}=@var_table[#{arg.dump}])"
+ else
+ arg.dump
+ end
+ }
+ @last_value = bind.eval(code)
+ rescue SyntaxError
+ $stderr.puts "error on line #{@lineno}" if @lineno
+ raise
+ end
+
+ def dsl_binding(p = "p")
+ # struct parser_params *p
+ binding
+ end
+
+ attr_reader :events
+
+ undef lambda
+ undef hash
+ undef :class
+
+ def generate
+ s = "#@final=#@last_value;"
+ s << "ripper_error(p);" if @error
+ unless @var_table.empty?
+ vars = @var_table.map {|_, v| "#{v.var}=#{v.value}"}.join(", ")
+ s = "VALUE #{ vars }; #{ s }"
+ end
+ "#{@indent}{#{s}}"
+ end
+
+ def add_event(event, args)
+ event = event.to_s.sub(/!\z/, "")
+ @events[event] = args.size
+ vars = []
+ args.each do |arg|
+ arg = @var_table.add {arg} unless Var === arg
+ vars << arg
+ end
+ @var_table.add {"dispatch#{ args.size }(#{ [event, *vars].join(",") })"}
+ end
+
+ def method_missing(event, *args)
+ if event.to_s =~ /!\z/
+ add_event(event, args)
+ elsif args.empty? and (/\Aid[A-Z_]/ =~ event or @var_table.defined?(event))
+ event
+ else
+ "#{ event }(#{ args.map(&:to_s).join(", ") })"
+ end
+ end
+
+ def self.const_missing(name)
+ name
+ end
+end
diff --git a/ext/ripper/tools/generate-param-macros.rb b/ext/ripper/tools/generate-param-macros.rb
new file mode 100644
index 0000000000..f0de55a5f2
--- /dev/null
+++ b/ext/ripper/tools/generate-param-macros.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+off = true
+ARGF.each do |line|
+ case line
+ when /RIPPER_PARAMS_DECL_BEGIN/
+ off = false
+ when /RIPPER_PARAMS_DECL_END/
+ exit
+ when /ripper/
+ next if off
+ var = line.scan(/\w+/).last or next
+ base = var.sub(/ripper_/, '')
+ puts %"\#define #{base}\t\t(parser->ripper_#{base})"
+ end
+end
diff --git a/ext/ripper/tools/generate.rb b/ext/ripper/tools/generate.rb
new file mode 100644
index 0000000000..57ecac0b39
--- /dev/null
+++ b/ext/ripper/tools/generate.rb
@@ -0,0 +1,194 @@
+# frozen_string_literal: true
+# $Id$
+
+require 'optparse'
+
+def main
+ mode = nil
+ ids1src = nil
+ ids2src = nil
+ output = nil
+
+ parser = @parser = OptionParser.new
+ parser.banner = "Usage: #{File.basename($0)} --mode=MODE [--ids1src=PATH] [--ids2src=PATH] [--output=PATH]"
+ parser.on('--mode=MODE', 'check, eventids1_h, eventids1, or eventids2table.') {|m|
+ mode = m
+ }
+ parser.on('--ids1src=PATH', 'A source file of event-IDs 1 (parse.y).') {|path|
+ ids1src = path
+ }
+ parser.on('--ids2src=PATH', 'A source file of event-IDs 2 (eventids2.c).') {|path|
+ ids2src = path
+ }
+ parser.on('--output=PATH', 'An output file.') {|path|
+ output = path
+ }
+ parser.on('--help', 'Prints this message and quit.') {
+ puts parser.help
+ exit true
+ }
+ begin
+ parser.parse!
+ rescue OptionParser::ParseError => err
+ usage err.message
+ end
+ usage 'no mode given' unless mode
+ case mode
+ when 'check'
+ usage 'no --ids1src' unless ids1src
+ usage 'no --ids2src' unless ids2src
+ h = read_ids1_with_locations(ids1src)
+ check_arity h
+ ids2 = read_ids2(ids2src)
+ common = h.keys & ids2
+ unless common.empty?
+ abort "event crash: #{common.join(' ')}"
+ end
+ exit 0
+ when 'eventids1_h'
+ usage 'no --ids1src' unless ids1src
+ result = generate_eventids1_h(read_ids1(ids1src))
+ when 'eventids1'
+ usage 'no --ids1src' unless ids1src
+ result = generate_eventids1(read_ids1(ids1src))
+ when 'eventids2table'
+ usage 'no --ids2src' unless ids2src
+ result = generate_eventids2_table(read_ids2(ids2src))
+ end
+ if output
+ File.open(output, 'w') {|f|
+ f.write result
+ }
+ else
+ puts result
+ end
+end
+
+def usage(msg)
+ $stderr.puts msg
+ $stderr.puts @parser.help
+ exit false
+end
+
+def generate_eventids1_h(ids)
+ buf = "".dup
+ buf << %Q[#ifndef RIPPER_EVENTIDS1\n]
+ buf << %Q[#define RIPPER_EVENTIDS1\n]
+ buf << %Q[\n]
+ buf << %Q[#define RIPPER_ID(n) ripper_parser_ids.id_ ## n\n]
+ buf << %Q[void ripper_init_eventids1(void);\n]
+ buf << %Q[void ripper_init_eventids1_table(VALUE self);\n]
+ buf << %Q[\n]
+ buf << %Q[struct ripper_parser_ids {\n]
+ ids.each do |id, arity|
+ buf << %Q[ ID id_#{id};\n]
+ end
+ buf << %Q[};\n]
+ buf << %Q[\n]
+ buf << %Q[#endif /* RIPPER_EVENTIDS1 */\n]
+ buf << %Q[\n]
+end
+
+def generate_eventids1(ids)
+ buf = "".dup
+ buf << %Q[#include "ruby/ruby.h"\n]
+ buf << %Q[#include "eventids1.h"\n]
+ buf << %Q[\n]
+ buf << %Q[struct ripper_parser_ids ripper_parser_ids;\n]
+ buf << %Q[\n]
+ buf << %Q[void\n]
+ buf << %Q[ripper_init_eventids1(void)\n]
+ buf << %Q[{\n]
+ buf << %Q[#define set_id1(name) RIPPER_ID(name) = rb_intern_const("on_"#name)\n]
+ ids.each do |id, arity|
+ buf << %Q[ set_id1(#{id});\n]
+ end
+ buf << %Q[}\n]
+ buf << %Q[\n]
+ buf << %Q[#define intern_sym(name) ID2SYM(rb_intern_const(name))\n]
+ buf << %Q[\n]
+ buf << %Q[void\n]
+ buf << %Q[ripper_init_eventids1_table(VALUE self)\n]
+ buf << %Q[{\n]
+ buf << %Q[ VALUE h = rb_hash_new();\n]
+ buf << %Q[ rb_define_const(self, "PARSER_EVENT_TABLE", h);\n]
+ ids.each do |id, arity|
+ buf << %Q[ rb_hash_aset(h, intern_sym("#{id}"), INT2FIX(#{arity}));\n]
+ end
+ buf << %Q[}\n]
+ buf
+end
+
+def generate_eventids2_table(ids)
+ buf = "".dup
+ buf << %Q[#include "ruby/ruby.h"\n]
+ buf << %Q[\n]
+ buf << %Q[#define intern_sym(name) ID2SYM(rb_intern_const(name))\n]
+ buf << %Q[\n]
+ buf << %Q[void\n]
+ buf << %Q[ripper_init_eventids2_table(VALUE self)\n]
+ buf << %Q[{\n]
+ buf << %Q[ VALUE h = rb_hash_new();\n]
+ buf << %Q[ rb_define_const(self, "SCANNER_EVENT_TABLE", h);\n]
+ ids.each do |id|
+ buf << %Q[ rb_hash_aset(h, intern_sym("#{id}"), INT2FIX(1));\n]
+ end
+ buf << %Q[}\n]
+ buf << %Q[\n]
+ buf << %Q[#define RIPPER_EVENTIDS2_TABLE_SIZE #{ids.size}\n]
+ buf
+end
+
+def read_ids1(path)
+ strip_locations(read_ids1_with_locations(path))
+end
+
+def strip_locations(h)
+ h.map {|event, list| [event, list.first[1]] }\
+ .sort_by {|event, arity| event.to_s }
+end
+
+def check_arity(h)
+ invalid = false
+ h.each do |event, list|
+ unless list.map {|line, arity| arity }.uniq.size == 1
+ invalid = true
+ locations = list.map {|line, a| "#{line}:#{a}" }.join(', ')
+ $stderr.puts "arity crash [event=#{event}]: #{locations}"
+ end
+ end
+ abort if invalid
+end
+
+require_relative "dsl"
+
+def read_ids1_with_locations(path)
+ h = {}
+ File.open(path) {|f|
+ f.each do |line|
+ next if /\A\#\s*define\s+dispatch/ =~ line
+ next if /ripper_dispatch/ =~ line
+ line.scan(/\bdispatch(\d)\((\w+)/) do |arity, event|
+ (h[event] ||= []).push [f.lineno, arity.to_i]
+ end
+ if gen = DSL.line?(line, f.lineno)
+ gen.events.each do |event, arity|
+ (h[event] ||= []).push [f.lineno, arity.to_i]
+ end
+ end
+ end
+ }
+ h
+end
+
+def read_ids2(path)
+ src = File.open(path) {|f| f.read}
+ ids2 = src.scan(/ID\s+ripper_id_(\w+)/).flatten.uniq.sort
+ diff = src.scan(/set_id2\((\w+)\);/).flatten - ids2
+ unless diff.empty?
+ abort "missing scanner IDs: #{diff}"
+ end
+ return ids2
+end
+
+main
diff --git a/ext/ripper/tools/preproc.rb b/ext/ripper/tools/preproc.rb
new file mode 100644
index 0000000000..5e8a6e0cb5
--- /dev/null
+++ b/ext/ripper/tools/preproc.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+# $Id$
+
+require 'optparse'
+
+def main
+ output = nil
+ template = nil
+ parser = OptionParser.new
+ parser.banner = "Usage: #{File.basename($0)} [--output=PATH] [--template=PATH] <parse.y>"
+ parser.on('--output=PATH', 'An output file.') {|path|
+ output = path
+ }
+ parser.on('--template=PATH', 'An template file.') {|path|
+ template = path
+ }
+ parser.on('--help', 'Prints this message and quit.') {
+ puts parser.help
+ exit true
+ }
+ begin
+ parser.parse!
+ rescue OptionParser::ParseError => err
+ warn err.message
+ abort parser.help
+ end
+ out = "".dup
+ if ARGV[0] == "-"
+ unless ARGV.size == 2
+ abort "wrong number of arguments (#{ARGV.size} for 2)"
+ end
+ process STDIN, out, ARGV[1], template
+ else
+ unless ARGV.size == 1
+ abort "wrong number of arguments (#{ARGV.size} for 1)"
+ end
+ File.open(ARGV[0]) {|f|
+ process f, out, ARGV[0], template
+ }
+ end
+ if output
+ File.write(output, out)
+ else
+ print out
+ end
+end
+
+def process(f, out, path, template)
+ prelude f, out
+ grammar f, out
+ usercode f, out, path, template
+end
+
+require_relative 'dsl'
+
+def generate_line(f, out)
+ while line = f.gets
+ case
+ when gen = DSL.line?(line, f.lineno)
+ out << gen.generate << "\n"
+ when line.start_with?("%%")
+ out << "%%\n"
+ break
+ else
+ out << yield(line)
+ end
+ end
+end
+
+def prelude(f, out)
+ @exprs = {}
+ generate_line(f, out) do |line|
+ if (/^enum lex_state_(?:bits|e) \{/ =~ line)..(/^\}/ =~ line)
+ case line
+ when /^\s*(EXPR_\w+),\s+\/\*(.+)\*\//
+ @exprs[$1.chomp("_bit")] = $2.strip
+ when /^\s*(EXPR_\w+)\s+=\s+(.+)$/
+ name = $1
+ val = $2.chomp(",")
+ @exprs[name] = "equals to " + (val.start_with?("(") ? "<tt>#{val}</tt>" : "+#{val}+")
+ end
+ end
+ line
+ end
+end
+
+def grammar(f, out)
+ generate_line(f, out) do |line|
+ case line
+ when %r</\*%%%\*/>
+ "#if 0\n"
+ when %r</\*%>
+ "#endif\n"
+ when %r<%\*/>
+ "\n"
+ else
+ line
+ end
+ end
+end
+
+def usercode(f, out, path, template)
+ require 'erb'
+ lineno = nil
+ src = nil
+ compiler = ERB::Compiler.new('%-')
+ compiler.put_cmd = compiler.insert_cmd = "out.<<"
+
+ if template
+ File.open(template) do |f|
+ out.clear
+ lineno = f.lineno
+ src, = compiler.compile(f.read)
+ path = template
+ end
+ else
+ lineno = f.lineno
+ src, = compiler.compile(f.read)
+ end
+
+ eval(src, binding, path, lineno)
+end
+
+main
diff --git a/ext/ripper/tools/strip.rb b/ext/ripper/tools/strip.rb
new file mode 100644
index 0000000000..23102f797a
--- /dev/null
+++ b/ext/ripper/tools/strip.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+last_is_void = false
+ARGF.each do |line|
+ case line
+ when /\A\s*\z/, /\A\#/
+ puts unless last_is_void
+ last_is_void = true
+ else
+ print line
+ last_is_void = false
+ end
+end
diff --git a/ext/rubyvm/depend b/ext/rubyvm/depend
new file mode 100644
index 0000000000..0301ce074c
--- /dev/null
+++ b/ext/rubyvm/depend
@@ -0,0 +1,2 @@
+# AUTOGENERATED DEPENDENCIES START
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/rubyvm/extconf.rb b/ext/rubyvm/extconf.rb
new file mode 100644
index 0000000000..8c40f58e2b
--- /dev/null
+++ b/ext/rubyvm/extconf.rb
@@ -0,0 +1 @@
+create_makefile("rubyvm")
diff --git a/ext/rubyvm/lib/forwardable/impl.rb b/ext/rubyvm/lib/forwardable/impl.rb
new file mode 100644
index 0000000000..e9bde2f299
--- /dev/null
+++ b/ext/rubyvm/lib/forwardable/impl.rb
@@ -0,0 +1,16 @@
+# :stopdoc:
+module Forwardable
+ def self._valid_method?(method)
+ iseq = RubyVM::InstructionSequence.compile("().#{method}", nil, nil, 0, false)
+ rescue SyntaxError
+ false
+ else
+ iseq.to_a.dig(-1, 1, 1, :mid) == method.to_sym
+ end
+
+ def self._compile_method(src, file, line)
+ RubyVM::InstructionSequence.compile(src, file, file, line,
+ trace_instruction: false)
+ .eval
+ end
+end
diff --git a/ext/sdbm/.cvsignore b/ext/sdbm/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/sdbm/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/sdbm/_sdbm.c b/ext/sdbm/_sdbm.c
deleted file mode 100644
index d4cf621ea5..0000000000
--- a/ext/sdbm/_sdbm.c
+++ /dev/null
@@ -1,973 +0,0 @@
-/*
- * sdbm - ndbm work-alike hashed database library
- * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
- * author: oz@nexus.yorku.ca
- * status: public domain.
- *
- * core routines
- */
-
-#ifndef lint
-/*char sdbm_rcsid[] = "$Id$";*/
-#endif
-
-#include "sdbm.h"
-#include "config.h"
-
-/*
- * sdbm - ndbm work-alike hashed database library
- * tuning and portability constructs [not nearly enough]
- * author: oz@nexus.yorku.ca
- */
-
-#define BYTESIZ 8
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef BSD42
-#define SEEK_SET L_SET
-#define memset(s,c,n) bzero(s, n) /* only when c is zero */
-#define memcpy(s1,s2,n) bcopy(s2, s1, n)
-#define memcmp(s1,s2,n) bcmp(s1,s2,n)
-#endif
-
-/*
- * important tuning parms (hah)
- */
-
-#define SEEDUPS /* always detect duplicates */
-#define BADMESS /* generate a message for worst case:
- cannot make room after SPLTMAX splits */
-/*
- * misc
- */
-#ifdef DEBUG
-#define debug(x) printf x
-#else
-#define debug(x)
-#endif
-
-#ifdef BIG_E
-#define GET_SHORT(p, i) (((unsigned)((unsigned char *)(p))[(i)*2] << 8) + (((unsigned char *)(p))[(i)*2 + 1]))
-#define PUT_SHORT(p, i, s) (((unsigned char *)(p))[(i)*2] = (unsigned char)((s) >> 8), ((unsigned char *)(p))[(i)*2 + 1] = (unsigned char)(s))
-#else
-#define GET_SHORT(p, i) ((p)[i])
-#define PUT_SHORT(p, i, s) ((p)[i] = (s))
-#endif
-
-/*#include "pair.h"*/
-static int fitpair proto((char *, int));
-static void putpair proto((char *, datum, datum));
-static datum getpair proto((char *, datum));
-static int delpair proto((char *, datum));
-static int chkpage proto((char *));
-static datum getnkey proto((char *, int));
-static void splpage proto((char *, char *, long));
-#ifdef SEEDUPS
-static int duppair proto((char *, datum));
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef MSDOS
-#include <io.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef BSD42
-#include <sys/file.h>
-#else
-#include <fcntl.h>
-/*#include <memory.h>*/
-#endif
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-#include <errno.h>
-#ifndef EPERM
-#define EPERM EACCES
-#endif
-#include <string.h>
-
-#ifdef __STDC__
-#include <stddef.h>
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-/*
- * externals
- */
-#if !defined sun && !defined MSDOS && !defined _WIN32 && !defined __CYGWIN__ && !defined(errno)
-extern int errno;
-#endif
-
-/*
- * forward
- */
-static int getdbit proto((DBM *, long));
-static int setdbit proto((DBM *, long));
-static int getpage proto((DBM *, long));
-static datum getnext proto((DBM *));
-static int makroom proto((DBM *, long, int));
-
-/*
- * useful macros
- */
-#define bad(x) ((x).dptr == NULL || (x).dsize < 0)
-#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
-#define ioerr(db) ((db)->flags |= DBM_IOERR)
-
-#define OFF_PAG(off) (long) (off) * PBLKSIZ
-#define OFF_DIR(off) (long) (off) * DBLKSIZ
-
-static long masks[] = {
- 000000000000L, 000000000001L, 000000000003L,
- 000000000007L, 000000000017L, 000000000037L,
- 000000000077L, 000000000177L, 000000000377L,
- 000000000777L, 000000001777L, 000000003777L,
- 000000007777L, 000000017777L, 000000037777L,
- 000000077777L, 000000177777L, 000000377777L,
- 000000777777L, 000001777777L, 000003777777L,
- 000007777777L, 000017777777L, 000037777777L,
- 000077777777L, 000177777777L, 000377777777L,
- 000777777777L, 001777777777L, 003777777777L,
- 007777777777L, 017777777777L
-};
-
-datum nullitem = {NULL, 0};
-
-DBM *
-sdbm_open(file, flags, mode)
-register char *file;
-register int flags;
-register int mode;
-{
- register DBM *db;
- register char *dirname;
- register char *pagname;
- register int n;
-
- if (file == NULL || !*file)
- return errno = EINVAL, (DBM *) NULL;
-/*
- * need space for two seperate filenames
- */
- n = strlen(file) * 2 + strlen(DIRFEXT) + strlen(PAGFEXT) + 2;
-
- if ((dirname = malloc((unsigned) n)) == NULL)
- return errno = ENOMEM, (DBM *) NULL;
-/*
- * build the file names
- */
- dirname = strcat(strcpy(dirname, file), DIRFEXT);
- pagname = strcpy(dirname + strlen(dirname) + 1, file);
- pagname = strcat(pagname, PAGFEXT);
-
- db = sdbm_prep(dirname, pagname, flags, mode);
- free((char *) dirname);
- return db;
-}
-
-DBM *
-sdbm_prep(dirname, pagname, flags, mode)
-char *dirname;
-char *pagname;
-int flags;
-int mode;
-{
- register DBM *db;
- struct stat dstat;
-
- if ((db = (DBM *) malloc(sizeof(DBM))) == NULL)
- return errno = ENOMEM, (DBM *) NULL;
-
- db->flags = 0;
- db->hmask = 0;
- db->blkptr = 0;
- db->keyptr = 0;
-/*
- * adjust user flags so that WRONLY becomes RDWR,
- * as required by this package. Also set our internal
- * flag for RDONLY.
- */
- if (flags & O_WRONLY)
- flags = (flags & ~O_WRONLY) | O_RDWR;
- if (flags & O_RDONLY)
- db->flags = DBM_RDONLY;
-/*
- * open the files in sequence, and stat the dirfile.
- * If we fail anywhere, undo everything, return NULL.
- */
- flags |= O_BINARY;
- if ((db->pagf = open(pagname, flags, mode)) > -1) {
- if ((db->dirf = open(dirname, flags, mode)) > -1) {
-/*
- * need the dirfile size to establish max bit number.
- */
- if (fstat(db->dirf, &dstat) == 0) {
-/*
- * zero size: either a fresh database, or one with a single,
- * unsplit data page: dirpage is all zeros.
- */
- db->dirbno = (!dstat.st_size) ? 0 : -1;
- db->pagbno = -1;
- db->maxbno = dstat.st_size * (long) BYTESIZ;
-
- (void) memset(db->pagbuf, 0, PBLKSIZ);
- (void) memset(db->dirbuf, 0, DBLKSIZ);
- /*
- * success
- */
- return db;
- }
- (void) close(db->dirf);
- }
- (void) close(db->pagf);
- }
- free((char *) db);
- return (DBM *) NULL;
-}
-
-void
-sdbm_close(db)
-register DBM *db;
-{
- if (db == NULL)
- errno = EINVAL;
- else {
- (void) close(db->dirf);
- (void) close(db->pagf);
- free((char *) db);
- }
-}
-
-datum
-sdbm_fetch(db, key)
-register DBM *db;
-datum key;
-{
- if (db == NULL || bad(key))
- return errno = EINVAL, nullitem;
-
- if (getpage(db, exhash(key)))
- return getpair(db->pagbuf, key);
-
- return ioerr(db), nullitem;
-}
-
-int
-sdbm_delete(db, key)
-register DBM *db;
-datum key;
-{
- if (db == NULL || bad(key))
- return errno = EINVAL, -1;
- if (sdbm_rdonly(db))
- return errno = EPERM, -1;
-
- if (getpage(db, exhash(key))) {
- if (!delpair(db->pagbuf, key))
- return -1;
-/*
- * update the page file
- */
- if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
- || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return ioerr(db), -1;
-
- return 0;
- }
-
- return ioerr(db), -1;
-}
-
-int
-sdbm_store(db, key, val, flags)
-register DBM *db;
-datum key;
-datum val;
-int flags;
-{
- int need;
- register long hash;
-
- if (db == NULL || bad(key))
- return errno = EINVAL, -1;
- if (sdbm_rdonly(db))
- return errno = EPERM, -1;
-
- need = key.dsize + val.dsize;
-/*
- * is the pair too big (or too small) for this database ??
- */
- if (need < 0 || need > PAIRMAX)
- return errno = EINVAL, -1;
-
- if (getpage(db, (hash = exhash(key)))) {
-/*
- * if we need to replace, delete the key/data pair
- * first. If it is not there, ignore.
- */
- if (flags == DBM_REPLACE)
- (void) delpair(db->pagbuf, key);
-#ifdef SEEDUPS
- else if (duppair(db->pagbuf, key))
- return 1;
-#endif
-/*
- * if we do not have enough room, we have to split.
- */
- if (!fitpair(db->pagbuf, need))
- if (!makroom(db, hash, need))
- return ioerr(db), -1;
-/*
- * we have enough room or split is successful. insert the key,
- * and update the page file.
- */
- (void) putpair(db->pagbuf, key, val);
-
- if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
- || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return ioerr(db), -1;
- /*
- * success
- */
- return 0;
- }
-
- return ioerr(db), -1;
-}
-
-/*
- * makroom - make room by splitting the overfull page
- * this routine will attempt to make room for SPLTMAX times before
- * giving up.
- */
-static int
-makroom(db, hash, need)
-register DBM *db;
-long hash;
-int need;
-{
- long newp;
- char twin[PBLKSIZ];
-#if defined MSDOS || (defined _WIN32 && !defined __CYGWIN__)
- char zer[PBLKSIZ];
- long oldtail;
-#endif
- char *pag = db->pagbuf;
- char *new = twin;
- register int smax = SPLTMAX;
-
- do {
-/*
- * split the current page
- */
- (void) splpage(pag, new, db->hmask + 1);
-/*
- * address of the new page
- */
- newp = (hash & db->hmask) | (db->hmask + 1);
- debug(("newp: %ld\n", newp));
-/*
- * write delay, read avoidence/cache shuffle:
- * select the page for incoming pair: if key is to go to the new page,
- * write out the previous one, and copy the new one over, thus making
- * it the current page. If not, simply write the new page, and we are
- * still looking at the page of interest. current page is not updated
- * here, as sdbm_store will do so, after it inserts the incoming pair.
- */
-
-#if defined MSDOS || (defined _WIN32 && !defined __CYGWIN__)
- /*
- * Fill hole with 0 if made it.
- * (hole is NOT read as 0)
- */
- oldtail = lseek(db->pagf, 0L, SEEK_END);
- memset(zer, 0, PBLKSIZ);
- while (OFF_PAG(newp) > oldtail) {
- if (lseek(db->pagf, 0L, SEEK_END) < 0 ||
- write(db->pagf, zer, PBLKSIZ) < 0) {
-
- return 0;
- }
- oldtail += PBLKSIZ;
- }
-#endif
-
- if (hash & (db->hmask + 1)) {
- if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
- || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return 0;
- db->pagbno = newp;
- (void) memcpy(pag, new, PBLKSIZ);
- }
- else if (lseek(db->pagf, OFF_PAG(newp), SEEK_SET) < 0
- || write(db->pagf, new, PBLKSIZ) < 0)
- return 0;
-
- if (!setdbit(db, db->curbit))
- return 0;
-/*
- * see if we have enough room now
- */
- if (fitpair(pag, need))
- return 1;
-/*
- * try again... update curbit and hmask as getpage would have
- * done. because of our update of the current page, we do not
- * need to read in anything. BUT we have to write the current
- * [deferred] page out, as the window of failure is too great.
- */
- db->curbit = 2 * db->curbit +
- ((hash & (db->hmask + 1)) ? 2 : 1);
- db->hmask |= (db->hmask + 1);
-
- if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
- || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return 0;
-
- } while (--smax);
-/*
- * if we are here, this is real bad news. After SPLTMAX splits,
- * we still cannot fit the key. say goodnight.
- */
-#ifdef BADMESS
- (void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
-#endif
- return 0;
-
-}
-
-/*
- * the following two routines will break if
- * deletions aren't taken into account. (ndbm bug)
- */
-datum
-sdbm_firstkey(db)
-register DBM *db;
-{
- if (db == NULL)
- return errno = EINVAL, nullitem;
-/*
- * start at page 0
- */
- (void) memset(db->pagbuf, 0, PBLKSIZ);
- if (lseek(db->pagf, OFF_PAG(0), SEEK_SET) < 0
- || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return ioerr(db), nullitem;
- db->pagbno = 0;
- db->blkptr = 0;
- db->keyptr = 0;
-
- return getnext(db);
-}
-
-datum
-sdbm_nextkey(db)
-register DBM *db;
-{
- if (db == NULL)
- return errno = EINVAL, nullitem;
- return getnext(db);
-}
-
-/*
- * all important binary trie traversal
- */
-static int
-getpage(db, hash)
-register DBM *db;
-register long hash;
-{
- register int hbit;
- register long dbit;
- register long pagb;
-
- dbit = 0;
- hbit = 0;
- while (dbit < db->maxbno && getdbit(db, dbit))
- dbit = 2 * dbit + ((hash & ((long) 1 << hbit++)) ? 2 : 1);
-
- debug(("dbit: %d...", dbit));
-
- db->curbit = dbit;
- db->hmask = masks[hbit];
-
- pagb = hash & db->hmask;
-/*
- * see if the block we need is already in memory.
- * note: this lookaside cache has about 10% hit rate.
- */
- if (pagb != db->pagbno) {
-/*
- * note: here, we assume a "hole" is read as 0s.
- * if not, must zero pagbuf first.
- */
- (void) memset(db->pagbuf, 0, PBLKSIZ);
-
- if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0
- || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return 0;
- if (!chkpage(db->pagbuf)) {
- return 0;
- }
- db->pagbno = pagb;
-
- debug(("pag read: %d\n", pagb));
- }
- return 1;
-}
-
-static int
-getdbit(db, dbit)
-register DBM *db;
-register long dbit;
-{
- register long c;
- register long dirb;
-
- c = dbit / BYTESIZ;
- dirb = c / DBLKSIZ;
-
- if (dirb != db->dirbno) {
- if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
- || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
- return 0;
- db->dirbno = dirb;
-
- debug(("dir read: %d\n", dirb));
- }
-
- return db->dirbuf[c % DBLKSIZ] & (1 << (dbit % BYTESIZ));
-}
-
-static int
-setdbit(db, dbit)
-register DBM *db;
-register long dbit;
-{
- register long c;
- register long dirb;
-
- c = dbit / BYTESIZ;
- dirb = c / DBLKSIZ;
-
- if (dirb != db->dirbno) {
- if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
- || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
- return 0;
- db->dirbno = dirb;
-
- debug(("dir read: %d\n", dirb));
- }
-
- db->dirbuf[c % DBLKSIZ] |= (1 << (dbit % BYTESIZ));
-
- if (dbit >= db->maxbno)
- db->maxbno += (long) DBLKSIZ * BYTESIZ;
-
- if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
- || write(db->dirf, db->dirbuf, DBLKSIZ) < 0)
- return 0;
-
- return 1;
-}
-
-/*
- * getnext - get the next key in the page, and if done with
- * the page, try the next page in sequence
- */
-static datum
-getnext(db)
-register DBM *db;
-{
- datum key;
-
- for (;;) {
- db->keyptr++;
- key = getnkey(db->pagbuf, db->keyptr);
- if (key.dptr != NULL)
- return key;
-/*
- * we either run out, or there is nothing on this page..
- * try the next one... If we lost our position on the
- * file, we will have to seek.
- */
- db->keyptr = 0;
- if (db->pagbno != db->blkptr++)
- if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0)
- break;
- db->pagbno = db->blkptr;
- if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0)
- break;
- if (!chkpage(db->pagbuf)) {
- break;
- }
- }
-
- return ioerr(db), nullitem;
-}
-
-/* pair.c */
-/*
- * sdbm - ndbm work-alike hashed database library
- * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
- * author: oz@nexus.yorku.ca
- * status: public domain.
- *
- * page-level routines
- */
-
-#ifndef lint
-/*char pair_rcsid[] = "$Id$";*/
-#endif
-
-#ifndef BSD42
-/*#include <memory.h>*/
-#endif
-
-#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
-
-/*
- * forward
- */
-static int seepair proto((char *, int, char *, int));
-
-/*
- * page format:
- * +------------------------------+
- * ino | n | keyoff | datoff | keyoff |
- * +------------+--------+--------+
- * | datoff | - - - ----> |
- * +--------+---------------------+
- * | F R E E A R E A |
- * +--------------+---------------+
- * | <---- - - - | data |
- * +--------+-----+----+----------+
- * | key | data | key |
- * +--------+----------+----------+
- *
- * calculating the offsets for free area: if the number
- * of entries (ino[0]) is zero, the offset to the END of
- * the free area is the block size. Otherwise, it is the
- * nth (ino[ino[0]]) entry's offset.
- */
-
-static int
-fitpair(pag, need)
-char *pag;
-int need;
-{
- register int n;
- register int off;
- register int free;
- register short *ino = (short *) pag;
-
- off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ;
- free = off - (n + 1) * sizeof(short);
- need += 2 * sizeof(short);
-
- debug(("free %d need %d\n", free, need));
-
- return need <= free;
-}
-
-static void
-putpair(pag, key, val)
-char *pag;
-datum key;
-datum val;
-{
- register int n;
- register int off;
- register short *ino = (short *) pag;
-
- off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ;
-/*
- * enter the key first
- */
- off -= key.dsize;
- if (key.dsize)
- (void) memcpy(pag + off, key.dptr, key.dsize);
- PUT_SHORT(ino,n + 1,off);
-/*
- * now the data
- */
- off -= val.dsize;
- if (val.dsize)
- (void) memcpy(pag + off, val.dptr, val.dsize);
- PUT_SHORT(ino,n + 2,off);
-/*
- * adjust item count
- */
- PUT_SHORT(ino,0,GET_SHORT(ino,0) + 2);
-}
-
-static datum
-getpair(pag, key)
-char *pag;
-datum key;
-{
- register int i;
- register int n;
- datum val;
- register short *ino = (short *) pag;
-
- if ((n = GET_SHORT(ino,0)) == 0)
- return nullitem;
-
- if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
- return nullitem;
-
- val.dptr = pag + GET_SHORT(ino,i + 1);
- val.dsize = GET_SHORT(ino,i) - GET_SHORT(ino,i + 1);
- return val;
-}
-
-#ifdef SEEDUPS
-static int
-duppair(pag, key)
-char *pag;
-datum key;
-{
- register short *ino = (short *) pag;
- return GET_SHORT(ino,0) > 0 &&
- seepair(pag, GET_SHORT(ino,0), key.dptr, key.dsize) > 0;
-}
-#endif
-
-static datum
-getnkey(pag, num)
-char *pag;
-int num;
-{
- datum key;
- register int off;
- register short *ino = (short *) pag;
-
- num = num * 2 - 1;
- if (GET_SHORT(ino,0) == 0 || num > GET_SHORT(ino,0))
- return nullitem;
-
- off = (num > 1) ? GET_SHORT(ino,num - 1) : PBLKSIZ;
-
- key.dptr = pag + GET_SHORT(ino,num);
- key.dsize = off - GET_SHORT(ino,num);
-
- return key;
-}
-
-static int
-delpair(pag, key)
-char *pag;
-datum key;
-{
- register int n;
- register int i;
- register short *ino = (short *) pag;
-
- if ((n = GET_SHORT(ino,0)) == 0)
- return 0;
-
- if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
- return 0;
-/*
- * found the key. if it is the last entry
- * [i.e. i == n - 1] we just adjust the entry count.
- * hard case: move all data down onto the deleted pair,
- * shift offsets onto deleted offsets, and adjust them.
- * [note: 0 < i < n]
- */
- if (i < n - 1) {
- register int m;
- register char *dst = pag + (i == 1 ? PBLKSIZ : GET_SHORT(ino,i - 1));
- register char *src = pag + GET_SHORT(ino,i + 1);
- register int zoo = dst - src;
-
- debug(("free-up %d ", zoo));
-/*
- * shift data/keys down
- */
- m = GET_SHORT(ino,i + 1) - GET_SHORT(ino,n);
-#ifdef DUFF
-#define MOVB *--dst = *--src
-
- if (m > 0) {
- register int loop = (m + 8 - 1) >> 3;
-
- switch (m & (8 - 1)) {
- case 0: do {
- MOVB; case 7: MOVB;
- case 6: MOVB; case 5: MOVB;
- case 4: MOVB; case 3: MOVB;
- case 2: MOVB; case 1: MOVB;
- } while (--loop);
- }
- }
-#else
-#ifdef MEMMOVE
- memmove(dst, src, m);
-#else
- while (m--)
- *--dst = *--src;
-#endif
-#endif
-/*
- * adjust offset index up
- */
- while (i < n - 1) {
- PUT_SHORT(ino,i, GET_SHORT(ino,i + 2) + zoo);
- i++;
- }
- }
- PUT_SHORT(ino, 0, GET_SHORT(ino, 0) - 2);
- return 1;
-}
-
-/*
- * search for the key in the page.
- * return offset index in the range 0 < i < n.
- * return 0 if not found.
- */
-static int
-seepair(pag, n, key, siz)
-char *pag;
-register int n;
-register char *key;
-register int siz;
-{
- register int i;
- register int off = PBLKSIZ;
- register short *ino = (short *) pag;
-
- for (i = 1; i < n; i += 2) {
- if (siz == off - GET_SHORT(ino,i) &&
- memcmp(key, pag + GET_SHORT(ino,i), siz) == 0)
- return i;
- off = GET_SHORT(ino,i + 1);
- }
- return 0;
-}
-
-static void
-splpage(pag, new, sbit)
-char *pag;
-char *new;
-long sbit;
-{
- datum key;
- datum val;
-
- register int n;
- register int off = PBLKSIZ;
- char cur[PBLKSIZ];
- register short *ino = (short *) cur;
-
- (void) memcpy(cur, pag, PBLKSIZ);
- (void) memset(pag, 0, PBLKSIZ);
- (void) memset(new, 0, PBLKSIZ);
-
- n = GET_SHORT(ino,0);
- for (ino++; n > 0; ino += 2) {
- key.dptr = cur + GET_SHORT(ino,0);
- key.dsize = off - GET_SHORT(ino,0);
- val.dptr = cur + GET_SHORT(ino,1);
- val.dsize = GET_SHORT(ino,0) - GET_SHORT(ino,1);
-/*
- * select the page pointer (by looking at sbit) and insert
- */
- (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
-
- off = GET_SHORT(ino,1);
- n -= 2;
- }
-
- debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
- ((short *) new)[0] / 2,
- ((short *) pag)[0] / 2));
-}
-
-/*
- * check page sanity:
- * number of entries should be something
- * reasonable, and all offsets in the index should be in order.
- * this could be made more rigorous.
- */
-static int
-chkpage(pag)
-char *pag;
-{
- register int n;
- register int off;
- register short *ino = (short *) pag;
-
- if ((n = GET_SHORT(ino,0)) < 0 || n > PBLKSIZ / sizeof(short))
- return 0;
-
- if (n > 0) {
- off = PBLKSIZ;
- for (ino++; n > 0; ino += 2) {
- if (GET_SHORT(ino,0) > off || GET_SHORT(ino,1) > off ||
- GET_SHORT(ino,1) > GET_SHORT(ino,0))
- return 0;
- off = GET_SHORT(ino,1);
- n -= 2;
- }
- }
- return 1;
-}
-
-/* hash.c */
-/*
- * sdbm - ndbm work-alike hashed database library
- * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
- * author: oz@nexus.yorku.ca
- * status: public domain. keep it that way.
- *
- * hashing routine
- */
-
-/*
- * polynomial conversion ignoring overflows
- * [this seems to work remarkably well, in fact better
- * then the ndbm hash function. Replace at your own risk]
- * use: 65599 nice.
- * 65587 even better.
- */
-long
-sdbm_hash(str, len)
-register char *str;
-register int len;
-{
- register unsigned long n = 0;
-
-#ifdef DUFF
-
-#define HASHC n = *str++ + 65599 * n
-
- if (len > 0) {
- register int loop = (len + 8 - 1) >> 3;
-
- switch(len & (8 - 1)) {
- case 0: do {
- HASHC; case 7: HASHC;
- case 6: HASHC; case 5: HASHC;
- case 4: HASHC; case 3: HASHC;
- case 2: HASHC; case 1: HASHC;
- } while (--loop);
- }
-
- }
-#else
- while (len--)
- n = ((*str++) & 255) + 65587L * n;
-#endif
- return n;
-}
diff --git a/ext/sdbm/depend b/ext/sdbm/depend
deleted file mode 100644
index 1d8b13d13f..0000000000
--- a/ext/sdbm/depend
+++ /dev/null
@@ -1,2 +0,0 @@
-_sdbm.o: _sdbm.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
-init.o: init.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/sdbm/extconf.rb b/ext/sdbm/extconf.rb
deleted file mode 100644
index cc6c8cefd1..0000000000
--- a/ext/sdbm/extconf.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-require 'mkmf'
-
-create_makefile("sdbm")
diff --git a/ext/sdbm/init.c b/ext/sdbm/init.c
deleted file mode 100644
index acadc9b26a..0000000000
--- a/ext/sdbm/init.c
+++ /dev/null
@@ -1,788 +0,0 @@
-/************************************************
-
- sdbminit.c -
-
- $Author$
- $Date$
- created at: Fri May 7 08:34:24 JST 1999
-
- Copyright (C) 1995-2001 Yukihiro Matsumoto
-
-************************************************/
-
-#include "ruby.h"
-
-#include "sdbm.h"
-#include <fcntl.h>
-#include <errno.h>
-
-static VALUE rb_cDBM, rb_eDBMError;
-
-struct dbmdata {
- int di_size;
- DBM *di_dbm;
-};
-
-static void
-closed_sdbm()
-{
- rb_raise(rb_eDBMError, "closed SDBM file");
-}
-
-#define GetDBM(obj, dbmp) {\
- Data_Get_Struct(obj, struct dbmdata, dbmp);\
- if (dbmp == 0) closed_sdbm();\
- if (dbmp->di_dbm == 0) closed_sdbm();\
-}
-
-#define GetDBM2(obj, data, dbm) {\
- GetDBM(obj, data);\
- (dbm) = dbmp->di_dbm;\
-}
-
-static void
-free_sdbm(dbmp)
- struct dbmdata *dbmp;
-{
-
- if (dbmp->di_dbm) sdbm_close(dbmp->di_dbm);
- free(dbmp);
-}
-
-static VALUE
-fsdbm_close(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
-
- GetDBM(obj, dbmp);
- sdbm_close(dbmp->di_dbm);
- dbmp->di_dbm = 0;
-
- return Qnil;
-}
-
-static VALUE
-fsdbm_closed(obj)
- VALUE obj;
-{
- struct dbmdata *dbmp;
-
- Data_Get_Struct(obj, struct dbmdata, dbmp);
- if (dbmp == 0)
- return Qtrue;
- if (dbmp->di_dbm == 0)
- return Qtrue;
-
- return Qfalse;
-}
-
-static VALUE fsdbm_alloc _((VALUE));
-static VALUE
-fsdbm_alloc(klass)
- VALUE klass;
-{
- return Data_Wrap_Struct(klass, 0, free_sdbm, 0);
-}
-
-static VALUE
-fsdbm_initialize(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE file, vmode;
- DBM *dbm;
- struct dbmdata *dbmp;
- int mode;
-
- if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
- mode = 0666; /* default value */
- }
- else if (NIL_P(vmode)) {
- mode = -1; /* return nil if DB not exist */
- }
- else {
- mode = NUM2INT(vmode);
- }
- SafeStringValue(file);
-
- dbm = 0;
- if (mode >= 0)
- dbm = sdbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode);
- if (!dbm)
- dbm = sdbm_open(RSTRING(file)->ptr, O_RDWR, 0);
- if (!dbm)
- dbm = sdbm_open(RSTRING(file)->ptr, O_RDONLY, 0);
-
- if (!dbm) {
- if (mode == -1) return Qnil;
- rb_sys_fail(RSTRING(file)->ptr);
- }
-
- dbmp = ALLOC(struct dbmdata);
- DATA_PTR(obj) = dbmp;
- dbmp->di_dbm = dbm;
- dbmp->di_size = -1;
-
- return obj;
-}
-
-static VALUE
-fsdbm_s_open(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE obj = Data_Wrap_Struct(klass, 0, free_sdbm, 0);
-
- if (NIL_P(fsdbm_initialize(argc, argv, obj))) {
- return Qnil;
- }
-
- if (rb_block_given_p()) {
- return rb_ensure(rb_yield, obj, fsdbm_close, obj);
- }
-
- return obj;
-}
-
-static VALUE
-fsdbm_fetch(obj, keystr, ifnone)
- VALUE obj, keystr, ifnone;
-{
- datum key, value;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- StringValue(keystr);
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- value = sdbm_fetch(dbm, key);
- if (value.dptr == 0) {
- if (ifnone == Qnil && rb_block_given_p())
- return rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
- return ifnone;
- }
- return rb_tainted_str_new(value.dptr, value.dsize);
-}
-
-static VALUE
-fsdbm_aref(obj, keystr)
- VALUE obj, keystr;
-{
- return fsdbm_fetch(obj, keystr, Qnil);
-}
-
-static VALUE
-fsdbm_fetch_m(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE keystr, valstr, ifnone;
-
- rb_scan_args(argc, argv, "11", &keystr, &ifnone);
- valstr = fsdbm_fetch(obj, keystr, ifnone);
- if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
- rb_raise(rb_eIndexError, "key not found");
-
- return valstr;
-}
-
-static VALUE
-fsdbm_index(obj, valstr)
- VALUE obj, valstr;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- StringValue(valstr);
- val.dptr = RSTRING(valstr)->ptr;
- val.dsize = RSTRING(valstr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- if (val.dsize == RSTRING(valstr)->len &&
- memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
- return rb_tainted_str_new(key.dptr, key.dsize);
- }
- return Qnil;
-}
-
-static VALUE
-fsdbm_indexes(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE new;
- int i;
-
- new = rb_ary_new2(argc);
- for (i=0; i<argc; i++) {
- rb_ary_push(new, fsdbm_fetch(obj, argv[i], Qnil));
- }
-
- return new;
-}
-
-static VALUE
-fsdbm_select(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE new = rb_ary_new2(argc);
- int i;
-
- if (rb_block_given_p()) {
- datum key, val;
- DBM *dbm;
- struct dbmdata *dbmp;
-
- if (argc > 0) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
- }
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- VALUE assoc, v;
- val = sdbm_fetch(dbm, key);
- assoc = rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
- rb_tainted_str_new(val.dptr, val.dsize));
- v = rb_yield(assoc);
- if (RTEST(v)) {
- rb_ary_push(new, assoc);
- }
- GetDBM2(obj, dbmp, dbm);
- }
- }
- else {
- rb_warn("SDBM#select(index..) is deprecated; use SDBM#values_at");
-
- for (i=0; i<argc; i++) {
- rb_ary_push(new, fsdbm_fetch(obj, argv[i], Qnil));
- }
- }
-
- return new;
-}
-
-static VALUE
-fsdbm_values_at(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE new = rb_ary_new2(argc);
- int i;
-
- for (i=0; i<argc; i++) {
- rb_ary_push(new, fsdbm_fetch(obj, argv[i], Qnil));
- }
-
- return new;
-}
-
-static void
-fdbm_modify(obj)
- VALUE obj;
-{
- rb_secure(4);
- if (OBJ_FROZEN(obj)) rb_error_frozen("SDBM");
-}
-
-static VALUE
-fsdbm_delete(obj, keystr)
- VALUE obj, keystr;
-{
- datum key, value;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE valstr;
-
- fdbm_modify(obj);
- StringValue(keystr);
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- dbmp->di_size = -1;
-
- value = sdbm_fetch(dbm, key);
- if (value.dptr == 0) {
- if (rb_block_given_p()) return rb_yield(keystr);
- return Qnil;
- }
-
- /* need to save value before sdbm_delete() */
- valstr = rb_tainted_str_new(value.dptr, value.dsize);
-
- if (sdbm_delete(dbm, key)) {
- dbmp->di_size = -1;
- rb_raise(rb_eDBMError, "dbm_delete failed");
- }
- else if (dbmp->di_size >= 0) {
- dbmp->di_size--;
- }
- return valstr;
-}
-
-static VALUE
-fsdbm_shift(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE keystr, valstr;
-
- fdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- key = sdbm_firstkey(dbm);
- if (!key.dptr) return Qnil;
- val = sdbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
- sdbm_delete(dbm, key);
- if (dbmp->di_size >= 0) {
- dbmp->di_size--;
- }
-
- return rb_assoc_new(keystr, valstr);
-}
-
-static VALUE
-fsdbm_delete_if(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE keystr, valstr;
- VALUE ret, ary = rb_ary_new();
- int i, status = 0, n;
-
- fdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- n = dbmp->di_size;
- dbmp->di_size = -1;
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
- ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
- if (status != 0) break;
- if (RTEST(ret)) rb_ary_push(ary, keystr);
- GetDBM2(obj, dbmp, dbm);
- }
-
- for (i = 0; i < RARRAY(ary)->len; i++) {
- keystr = RARRAY(ary)->ptr[i];
- StringValue(keystr);
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
- if (sdbm_delete(dbm, key)) {
- rb_raise(rb_eDBMError, "sdbm_delete failed");
- }
- }
- if (status) rb_jump_tag(status);
- if (n > 0) dbmp->di_size = n - RARRAY(ary)->len;
-
- return obj;
-}
-
-static VALUE
-fsdbm_clear(obj)
- VALUE obj;
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- fdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- dbmp->di_size = -1;
- while (key = sdbm_firstkey(dbm), key.dptr) {
- if (sdbm_delete(dbm, key)) {
- rb_raise(rb_eDBMError, "sdbm_delete failed");
- }
- }
- dbmp->di_size = 0;
-
- return obj;
-}
-
-static VALUE
-fsdbm_invert(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE keystr, valstr;
- VALUE hash = rb_hash_new();
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
- rb_hash_aset(hash, valstr, keystr);
- }
- return hash;
-}
-
-static VALUE each_pair _((VALUE));
-
-static VALUE
-each_pair(obj)
- VALUE obj;
-{
- return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
-}
-
-static VALUE fsdbm_store _((VALUE,VALUE,VALUE));
-
-static VALUE
-update_i(pair, dbm)
- VALUE pair, dbm;
-{
- Check_Type(pair, T_ARRAY);
- if (RARRAY(pair)->len < 2) {
- rb_raise(rb_eArgError, "pair must be [key, value]");
- }
- fsdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]);
- return Qnil;
-}
-
-static VALUE
-fsdbm_update(obj, other)
- VALUE obj, other;
-{
- rb_iterate(each_pair, other, update_i, obj);
- return obj;
-}
-
-static VALUE
-fsdbm_replace(obj, other)
- VALUE obj, other;
-{
- fsdbm_clear(obj);
- rb_iterate(each_pair, other, update_i, obj);
- return obj;
-}
-
-static VALUE
-fsdbm_store(obj, keystr, valstr)
- VALUE obj, keystr, valstr;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- if (valstr == Qnil) {
- fsdbm_delete(obj, keystr);
- return Qnil;
- }
-
- fdbm_modify(obj);
- StringValue(keystr);
- StringValue(valstr);
-
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
-
- val.dptr = RSTRING(valstr)->ptr;
- val.dsize = RSTRING(valstr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- dbmp->di_size = -1;
- if (sdbm_store(dbm, key, val, DBM_REPLACE)) {
-#ifdef HAVE_DBM_CLAERERR
- sdbm_clearerr(dbm);
-#endif
- if (errno == EPERM) rb_sys_fail(0);
- rb_raise(rb_eDBMError, "sdbm_store failed");
- }
-
- return valstr;
-}
-
-static VALUE
-fsdbm_length(obj)
- VALUE obj;
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
- int i = 0;
-
- GetDBM2(obj, dbmp, dbm);
- if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
-
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- i++;
- }
- dbmp->di_size = i;
-
- return INT2FIX(i);
-}
-
-static VALUE
-fsdbm_empty_p(obj)
- VALUE obj;
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
- int i = 0;
-
- GetDBM(obj, dbmp);
- if (dbmp->di_size < 0) {
- dbm = dbmp->di_dbm;
-
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- i++;
- }
- }
- else {
- i = dbmp->di_size;
- }
- if (i == 0) return Qtrue;
- return Qfalse;
-}
-
-static VALUE
-fsdbm_each_value(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
- GetDBM2(obj, dbmp, dbm);
- }
- return obj;
-}
-
-static VALUE
-fsdbm_each_key(obj)
- VALUE obj;
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
- GetDBM2(obj, dbmp, dbm);
- }
- return obj;
-}
-
-static VALUE
-fsdbm_each_pair(obj)
- VALUE obj;
-{
- datum key, val;
- DBM *dbm;
- struct dbmdata *dbmp;
- VALUE keystr, valstr;
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
- rb_yield(rb_assoc_new(keystr, valstr));
- GetDBM2(obj, dbmp, dbm);
- }
-
- return obj;
-}
-
-static VALUE
-fsdbm_keys(obj)
- VALUE obj;
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE ary;
-
- GetDBM2(obj, dbmp, dbm);
- ary = rb_ary_new();
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
- }
-
- return ary;
-}
-
-static VALUE
-fsdbm_values(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE ary;
-
- GetDBM2(obj, dbmp, dbm);
- ary = rb_ary_new();
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
- }
-
- return ary;
-}
-
-static VALUE
-fsdbm_has_key(obj, keystr)
- VALUE obj, keystr;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- StringValue(keystr);
- key.dptr = RSTRING(keystr)->ptr;
- key.dsize = RSTRING(keystr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- val = sdbm_fetch(dbm, key);
- if (val.dptr) return Qtrue;
- return Qfalse;
-}
-
-static VALUE
-fsdbm_has_value(obj, valstr)
- VALUE obj, valstr;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- StringValue(valstr);
- val.dptr = RSTRING(valstr)->ptr;
- val.dsize = RSTRING(valstr)->len;
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- if (val.dsize == RSTRING(valstr)->len &&
- memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
- return Qtrue;
- }
- return Qfalse;
-}
-
-static VALUE
-fsdbm_to_a(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE ary;
-
- GetDBM2(obj, dbmp, dbm);
- ary = rb_ary_new();
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
- rb_tainted_str_new(val.dptr, val.dsize)));
- }
-
- return ary;
-}
-
-static VALUE
-fsdbm_to_hash(obj)
- VALUE obj;
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE hash;
-
- GetDBM2(obj, dbmp, dbm);
- hash = rb_hash_new();
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize),
- rb_tainted_str_new(val.dptr, val.dsize));
- }
-
- return hash;
-}
-
-static VALUE
-fsdbm_reject(obj)
- VALUE obj;
-{
- return rb_hash_delete_if(fsdbm_to_hash(obj));
-}
-
-void
-Init_sdbm()
-{
- rb_cDBM = rb_define_class("SDBM", rb_cObject);
- rb_eDBMError = rb_define_class("SDBMError", rb_eStandardError);
- rb_include_module(rb_cDBM, rb_mEnumerable);
-
- rb_define_alloc_func(rb_cDBM, fsdbm_alloc);
- rb_define_singleton_method(rb_cDBM, "open", fsdbm_s_open, -1);
-
- rb_define_method(rb_cDBM, "initialize", fsdbm_initialize, -1);
- rb_define_method(rb_cDBM, "close", fsdbm_close, 0);
- rb_define_method(rb_cDBM, "closed?", fsdbm_closed, 0);
- rb_define_method(rb_cDBM, "[]", fsdbm_aref, 1);
- rb_define_method(rb_cDBM, "fetch", fsdbm_fetch_m, -1);
- rb_define_method(rb_cDBM, "[]=", fsdbm_store, 2);
- rb_define_method(rb_cDBM, "store", fsdbm_store, 2);
- rb_define_method(rb_cDBM, "index", fsdbm_index, 1);
- rb_define_method(rb_cDBM, "indexes", fsdbm_indexes, -1);
- rb_define_method(rb_cDBM, "indices", fsdbm_indexes, -1);
- rb_define_method(rb_cDBM, "select", fsdbm_select, -1);
- rb_define_method(rb_cDBM, "values_at", fsdbm_values_at, -1);
- rb_define_method(rb_cDBM, "length", fsdbm_length, 0);
- rb_define_method(rb_cDBM, "size", fsdbm_length, 0);
- rb_define_method(rb_cDBM, "empty?", fsdbm_empty_p, 0);
- rb_define_method(rb_cDBM, "each", fsdbm_each_pair, 0);
- rb_define_method(rb_cDBM, "each_value", fsdbm_each_value, 0);
- rb_define_method(rb_cDBM, "each_key", fsdbm_each_key, 0);
- rb_define_method(rb_cDBM, "each_pair", fsdbm_each_pair, 0);
- rb_define_method(rb_cDBM, "keys", fsdbm_keys, 0);
- rb_define_method(rb_cDBM, "values", fsdbm_values, 0);
- rb_define_method(rb_cDBM, "shift", fsdbm_shift, 0);
- rb_define_method(rb_cDBM, "delete", fsdbm_delete, 1);
- rb_define_method(rb_cDBM, "delete_if", fsdbm_delete_if, 0);
- rb_define_method(rb_cDBM, "reject!", fsdbm_delete_if, 0);
- rb_define_method(rb_cDBM, "reject", fsdbm_reject, 0);
- rb_define_method(rb_cDBM, "clear", fsdbm_clear, 0);
- rb_define_method(rb_cDBM,"invert", fsdbm_invert, 0);
- rb_define_method(rb_cDBM,"update", fsdbm_update, 1);
- rb_define_method(rb_cDBM,"replace", fsdbm_replace, 1);
-
- rb_define_method(rb_cDBM, "include?", fsdbm_has_key, 1);
- rb_define_method(rb_cDBM, "has_key?", fsdbm_has_key, 1);
- rb_define_method(rb_cDBM, "member?", fsdbm_has_key, 1);
- rb_define_method(rb_cDBM, "has_value?", fsdbm_has_value, 1);
- rb_define_method(rb_cDBM, "key?", fsdbm_has_key, 1);
- rb_define_method(rb_cDBM, "value?", fsdbm_has_value, 1);
-
- rb_define_method(rb_cDBM, "to_a", fsdbm_to_a, 0);
- rb_define_method(rb_cDBM, "to_hash", fsdbm_to_hash, 0);
-}
diff --git a/ext/sdbm/sdbm.h b/ext/sdbm/sdbm.h
deleted file mode 100644
index ce8f54c4d4..0000000000
--- a/ext/sdbm/sdbm.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * sdbm - ndbm work-alike hashed database library
- * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
- * author: oz@nexus.yorku.ca
- * status: public domain.
- */
-#ifndef _SDBM_H_
-#define _SDBM_H_
-
-#define DBLKSIZ 4096
-#define PBLKSIZ 1024
-#define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */
-#define SPLTMAX 10 /* maximum allowed splits */
- /* for a single insertion */
-#define DIRFEXT ".dir"
-#define PAGFEXT ".pag"
-
-typedef struct {
- int dirf; /* directory file descriptor */
- int pagf; /* page file descriptor */
- int flags; /* status/error flags, see below */
- long maxbno; /* size of dirfile in bits */
- long curbit; /* current bit number */
- long hmask; /* current hash mask */
- long blkptr; /* current block for nextkey */
- int keyptr; /* current key for nextkey */
- long blkno; /* current page to read/write */
- long pagbno; /* current page in pagbuf */
- char pagbuf[PBLKSIZ]; /* page file block buffer */
- long dirbno; /* current block in dirbuf */
- char dirbuf[DBLKSIZ]; /* directory file block buffer */
-} DBM;
-
-#define DBM_RDONLY 0x1 /* data base open read-only */
-#define DBM_IOERR 0x2 /* data base I/O error */
-
-/*
- * utility macros
- */
-#define sdbm_rdonly(db) ((db)->flags & DBM_RDONLY)
-#define sdbm_error(db) ((db)->flags & DBM_IOERR)
-
-#define sdbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */
-
-#define sdbm_dirfno(db) ((db)->dirf)
-#define sdbm_pagfno(db) ((db)->pagf)
-
-typedef struct {
- char *dptr;
- int dsize;
-} datum;
-
-extern datum nullitem;
-
-#if defined(__STDC__) || defined(MSDOS)
-#define proto(p) p
-#else
-#define proto(p) ()
-#endif
-
-/*
- * flags to sdbm_store
- */
-#define DBM_INSERT 0
-#define DBM_REPLACE 1
-
-/*
- * ndbm interface
- */
-extern DBM *sdbm_open proto((char *, int, int));
-extern void sdbm_close proto((DBM *));
-extern datum sdbm_fetch proto((DBM *, datum));
-extern int sdbm_delete proto((DBM *, datum));
-extern int sdbm_store proto((DBM *, datum, datum, int));
-extern datum sdbm_firstkey proto((DBM *));
-extern datum sdbm_nextkey proto((DBM *));
-
-/*
- * other
- */
-extern DBM *sdbm_prep proto((char *, char *, int, int));
-extern long sdbm_hash proto((char *, int));
-
-#endif /* _SDBM_H_ */
diff --git a/ext/socket/.cvsignore b/ext/socket/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/socket/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/socket/.document b/ext/socket/.document
new file mode 100644
index 0000000000..53cfac0b10
--- /dev/null
+++ b/ext/socket/.document
@@ -0,0 +1,17 @@
+ancdata.c
+basicsocket.c
+constants.c
+constdefs.c
+ifaddr.c
+init.c
+ipsocket.c
+option.c
+raddrinfo.c
+socket.c
+sockssocket.c
+tcpserver.c
+tcpsocket.c
+udpsocket.c
+unixserver.c
+unixsocket.c
+lib
diff --git a/ext/socket/addrinfo.h b/ext/socket/addrinfo.h
index a22615ee00..eb9eb8ae0e 100644
--- a/ext/socket/addrinfo.h
+++ b/ext/socket/addrinfo.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -13,7 +13,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -29,7 +29,6 @@
#ifndef ADDR_INFO_H
#define ADDR_INFO_H
-#ifndef HAVE_GETADDRINFO
/* special compatibility hack */
#undef EAI_ADDRFAMILY
@@ -50,6 +49,7 @@
#undef AI_PASSIVE
#undef AI_CANONNAME
#undef AI_NUMERICHOST
+#undef AI_NUMERICSERV
#undef AI_ALL
#undef AI_ADDRCONFIG
#undef AI_V4MAPPED
@@ -61,12 +61,6 @@
#undef NI_NUMERICSERV
#undef NI_DGRAM
-#define addrinfo addrinfo__compat
-#define getaddrinfo getaddrinfo__compat
-#define getnameinfo getnameinfo__compat
-#define freehostent freehostent__compat
-#define freeaddrinfo freeaddrinfo__compat
-
#ifndef __P
# ifdef HAVE_PROTOTYPES
# define __P(args) args
@@ -102,8 +96,12 @@
#define AI_PASSIVE 0x00000001 /* get address to use bind() */
#define AI_CANONNAME 0x00000002 /* fill ai_canonname */
#define AI_NUMERICHOST 0x00000004 /* prevent name resolution */
+#define AI_NUMERICSERV 0x00000008 /* prevent service name resolution */
/* valid flags for addrinfo */
-#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
+#ifndef __HAIKU__
+#undef AI_MASK
+#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV)
+#endif
#define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
#define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */
@@ -129,37 +127,57 @@
#define NI_NUMERICSERV 0x00000008
#define NI_DGRAM 0x00000010
+#ifndef HAVE_TYPE_STRUCT_ADDRINFO
struct addrinfo {
- int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
- int ai_family; /* PF_xxx */
- int ai_socktype; /* SOCK_xxx */
- int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
- size_t ai_addrlen; /* length of ai_addr */
- char *ai_canonname; /* canonical name for hostname */
- struct sockaddr *ai_addr; /* binary address */
- struct addrinfo *ai_next; /* next structure in linked list */
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for hostname */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
};
+#endif
+
+#ifndef HAVE_GETADDRINFO
+#undef getaddrinfo
+#define getaddrinfo getaddrinfo__compat
+#endif
+#ifndef HAVE_GETNAMEINFO
+#undef getnameinfo
+#define getnameinfo getnameinfo__compat
+#endif
+#ifndef HAVE_FREEHOSTENT
+#undef freehostent
+#define freehostent freehostent__compat
+#endif
+#ifndef HAVE_FREEADDRINFO
+#undef freeaddrinfo
+#define freeaddrinfo freeaddrinfo__compat
+#endif
extern int getaddrinfo __P((
- const char *hostname, const char *servname,
- const struct addrinfo *hints,
- struct addrinfo **res));
+ const char *hostname, const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res));
extern int getnameinfo __P((
- const struct sockaddr *sa,
- size_t salen,
- char *host,
- size_t hostlen,
- char *serv,
- size_t servlen,
- int flags));
+ const struct sockaddr *sa,
+ socklen_t salen,
+ char *host,
+ socklen_t hostlen,
+ char *serv,
+ socklen_t servlen,
+ int flags));
extern void freehostent __P((struct hostent *));
extern void freeaddrinfo __P((struct addrinfo *));
-#if defined __UCLIBC__
+extern
+#ifdef GAI_STRERROR_CONST
const
#endif
-extern char *gai_strerror __P((int));
+char *gai_strerror __P((int));
/* In case there is no definition of offsetof() provided - though any proper
Standard C system should have one. */
@@ -169,4 +187,3 @@ Standard C system should have one. */
#endif
#endif
-#endif
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
new file mode 100644
index 0000000000..f1e9e42524
--- /dev/null
+++ b/ext/socket/ancdata.c
@@ -0,0 +1,1742 @@
+#include "rubysocket.h"
+
+#include <time.h>
+
+static VALUE sym_wait_readable, sym_wait_writable;
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+static VALUE rb_cAncillaryData;
+
+static VALUE
+constant_to_sym(int constant, ID (*intern_const)(int))
+{
+ ID name = intern_const(constant);
+ if (name) {
+ return ID2SYM(name);
+ }
+
+ return INT2NUM(constant);
+}
+
+static VALUE
+ip_cmsg_type_to_sym(int level, int cmsg_type)
+{
+ switch (level) {
+ case SOL_SOCKET:
+ return constant_to_sym(cmsg_type, rsock_intern_scm_optname);
+ case IPPROTO_IP:
+ return constant_to_sym(cmsg_type, rsock_intern_ip_optname);
+#ifdef IPPROTO_IPV6
+ case IPPROTO_IPV6:
+ return constant_to_sym(cmsg_type, rsock_intern_ipv6_optname);
+#endif
+ case IPPROTO_TCP:
+ return constant_to_sym(cmsg_type, rsock_intern_tcp_optname);
+ case IPPROTO_UDP:
+ return constant_to_sym(cmsg_type, rsock_intern_udp_optname);
+ default:
+ return INT2NUM(cmsg_type);
+ }
+}
+
+/*
+ * call-seq:
+ * Socket::AncillaryData.new(family, cmsg_level, cmsg_type, cmsg_data) -> ancillarydata
+ *
+ * _family_ should be an integer, a string or a symbol.
+ * - Socket::AF_INET, "AF_INET", "INET", :AF_INET, :INET
+ * - Socket::AF_UNIX, "AF_UNIX", "UNIX", :AF_UNIX, :UNIX
+ * - etc.
+ *
+ * _cmsg_level_ should be an integer, a string or a symbol.
+ * - Socket::SOL_SOCKET, "SOL_SOCKET", "SOCKET", :SOL_SOCKET and :SOCKET
+ * - Socket::IPPROTO_IP, "IP" and :IP
+ * - Socket::IPPROTO_IPV6, "IPV6" and :IPV6
+ * - Socket::IPPROTO_TCP, "TCP" and :TCP
+ * - etc.
+ *
+ * _cmsg_type_ should be an integer, a string or a symbol.
+ * If a string/symbol is specified, it is interpreted depend on _cmsg_level_.
+ * - Socket::SCM_RIGHTS, "SCM_RIGHTS", "RIGHTS", :SCM_RIGHTS, :RIGHTS for SOL_SOCKET
+ * - Socket::IP_RECVTTL, "RECVTTL" and :RECVTTL for IPPROTO_IP
+ * - Socket::IPV6_PKTINFO, "PKTINFO" and :PKTINFO for IPPROTO_IPV6
+ * - etc.
+ *
+ * _cmsg_data_ should be a string.
+ *
+ * p Socket::AncillaryData.new(:INET, :TCP, :NODELAY, "")
+ * #=> #<Socket::AncillaryData: INET TCP NODELAY "">
+ *
+ * p Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "")
+ * #=> #<Socket::AncillaryData: INET6 IPV6 PKTINFO "">
+ *
+ */
+static VALUE
+ancillary_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE vtype, VALUE data)
+{
+ int family = rsock_family_arg(vfamily);
+ int level = rsock_level_arg(family, vlevel);
+ int type = rsock_cmsg_type_arg(family, level, vtype);
+ StringValue(data);
+ rb_ivar_set(self, rb_intern("family"), INT2NUM(family));
+ rb_ivar_set(self, rb_intern("level"), INT2NUM(level));
+ rb_ivar_set(self, rb_intern("type"), INT2NUM(type));
+ rb_ivar_set(self, rb_intern("data"), data);
+ return self;
+}
+
+static VALUE
+ancdata_new(int family, int level, int type, VALUE data)
+{
+ VALUE obj = rb_obj_alloc(rb_cAncillaryData);
+ StringValue(data);
+ ancillary_initialize(obj, INT2NUM(family), INT2NUM(level), INT2NUM(type), data);
+ return (VALUE)obj;
+}
+
+static int
+ancillary_family(VALUE self)
+{
+ VALUE v = rb_attr_get(self, rb_intern("family"));
+ return NUM2INT(v);
+}
+
+/*
+ * call-seq:
+ * ancillarydata.family => integer
+ *
+ * returns the socket family as an integer.
+ *
+ * p Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "").family
+ * #=> 10
+ */
+static VALUE
+ancillary_family_m(VALUE self)
+{
+ return INT2NUM(ancillary_family(self));
+}
+
+static int
+ancillary_level(VALUE self)
+{
+ VALUE v = rb_attr_get(self, rb_intern("level"));
+ return NUM2INT(v);
+}
+
+/*
+ * call-seq:
+ * ancillarydata.level => integer
+ *
+ * returns the cmsg level as an integer.
+ *
+ * p Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "").level
+ * #=> 41
+ */
+static VALUE
+ancillary_level_m(VALUE self)
+{
+ return INT2NUM(ancillary_level(self));
+}
+
+static int
+ancillary_type(VALUE self)
+{
+ VALUE v = rb_attr_get(self, rb_intern("type"));
+ return NUM2INT(v);
+}
+
+/*
+ * call-seq:
+ * ancillarydata.type => integer
+ *
+ * returns the cmsg type as an integer.
+ *
+ * p Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "").type
+ * #=> 2
+ */
+static VALUE
+ancillary_type_m(VALUE self)
+{
+ return INT2NUM(ancillary_type(self));
+}
+
+/*
+ * call-seq:
+ * ancillarydata.data => string
+ *
+ * returns the cmsg data as a string.
+ *
+ * p Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "").data
+ * #=> ""
+ */
+static VALUE
+ancillary_data(VALUE self)
+{
+ VALUE v = rb_attr_get(self, rb_intern("data"));
+ StringValue(v);
+ return v;
+}
+
+#ifdef SCM_RIGHTS
+/*
+ * call-seq:
+ * Socket::AncillaryData.unix_rights(io1, io2, ...) => ancillarydata
+ *
+ * Creates a new Socket::AncillaryData object which contains file descriptors as data.
+ *
+ * p Socket::AncillaryData.unix_rights(STDERR)
+ * #=> #<Socket::AncillaryData: UNIX SOCKET RIGHTS 2>
+ */
+static VALUE
+ancillary_s_unix_rights(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE result, str, ary;
+ int i;
+
+ ary = rb_ary_new();
+
+ for (i = 0 ; i < argc; i++) {
+ VALUE obj = argv[i];
+ if (!RB_TYPE_P(obj, T_FILE)) {
+ rb_raise(rb_eTypeError, "IO expected");
+ }
+ rb_ary_push(ary, obj);
+ }
+
+ str = rb_str_buf_new(sizeof(int) * argc);
+
+ for (i = 0 ; i < argc; i++) {
+ VALUE obj = RARRAY_AREF(ary, i);
+ rb_io_t *fptr;
+ int fd;
+ GetOpenFile(obj, fptr);
+ fd = fptr->fd;
+ rb_str_buf_cat(str, (char *)&fd, sizeof(int));
+ }
+
+ result = ancdata_new(AF_UNIX, SOL_SOCKET, SCM_RIGHTS, str);
+ rb_ivar_set(result, rb_intern("unix_rights"), ary);
+ return result;
+}
+#else
+#define ancillary_s_unix_rights rb_f_notimplement
+#endif
+
+#ifdef SCM_RIGHTS
+/*
+ * call-seq:
+ * ancillarydata.unix_rights => array-of-IOs or nil
+ *
+ * returns the array of IO objects for SCM_RIGHTS control message in UNIX domain socket.
+ *
+ * The class of the IO objects in the array is IO or Socket.
+ *
+ * The array is attached to _ancillarydata_ when it is instantiated.
+ * For example, BasicSocket#recvmsg attach the array when
+ * receives a SCM_RIGHTS control message and :scm_rights=>true option is given.
+ *
+ * # recvmsg needs :scm_rights=>true for unix_rights
+ * s1, s2 = UNIXSocket.pair
+ * p s1 #=> #<UNIXSocket:fd 3>
+ * s1.sendmsg "stdin and a socket", 0, nil, Socket::AncillaryData.unix_rights(STDIN, s1)
+ * _, _, _, ctl = s2.recvmsg(:scm_rights=>true)
+ * p ctl #=> #<Socket::AncillaryData: UNIX SOCKET RIGHTS 6 7>
+ * p ctl.unix_rights #=> [#<IO:fd 6>, #<Socket:fd 7>]
+ * p File.identical?(STDIN, ctl.unix_rights[0]) #=> true
+ * p File.identical?(s1, ctl.unix_rights[1]) #=> true
+ *
+ * # If :scm_rights=>true is not given, unix_rights returns nil
+ * s1, s2 = UNIXSocket.pair
+ * s1.sendmsg "stdin and a socket", 0, nil, Socket::AncillaryData.unix_rights(STDIN, s1)
+ * _, _, _, ctl = s2.recvmsg
+ * p ctl #=> #<Socket::AncillaryData: UNIX SOCKET RIGHTS 6 7>
+ * p ctl.unix_rights #=> nil
+ *
+ */
+static VALUE
+ancillary_unix_rights(VALUE self)
+{
+ int level, type;
+
+ level = ancillary_level(self);
+ type = ancillary_type(self);
+
+ if (level != SOL_SOCKET || type != SCM_RIGHTS)
+ rb_raise(rb_eTypeError, "SCM_RIGHTS ancillary data expected");
+
+ return rb_attr_get(self, rb_intern("unix_rights"));
+}
+#else
+#define ancillary_unix_rights rb_f_notimplement
+#endif
+
+#if defined(SCM_TIMESTAMP) || defined(SCM_TIMESTAMPNS) || defined(SCM_BINTIME)
+/*
+ * call-seq:
+ * ancillarydata.timestamp => time
+ *
+ * returns the timestamp as a time object.
+ *
+ * _ancillarydata_ should be one of following type:
+ * - SOL_SOCKET/SCM_TIMESTAMP (microsecond) GNU/Linux, FreeBSD, NetBSD, OpenBSD, Solaris, MacOS X
+ * - SOL_SOCKET/SCM_TIMESTAMPNS (nanosecond) GNU/Linux
+ * - SOL_SOCKET/SCM_BINTIME (2**(-64) second) FreeBSD
+ *
+ * Addrinfo.udp("127.0.0.1", 0).bind {|s1|
+ * Addrinfo.udp("127.0.0.1", 0).bind {|s2|
+ * s1.setsockopt(:SOCKET, :TIMESTAMP, true)
+ * s2.send "a", 0, s1.local_address
+ * ctl = s1.recvmsg.last
+ * p ctl #=> #<Socket::AncillaryData: INET SOCKET TIMESTAMP 2009-02-24 17:35:46.775581>
+ * t = ctl.timestamp
+ * p t #=> 2009-02-24 17:35:46 +0900
+ * p t.usec #=> 775581
+ * p t.nsec #=> 775581000
+ * }
+ * }
+ *
+ */
+static VALUE
+ancillary_timestamp(VALUE self)
+{
+ int level, type;
+ VALUE data;
+ VALUE result = Qnil;
+
+ level = ancillary_level(self);
+ type = ancillary_type(self);
+ data = ancillary_data(self);
+
+# ifdef SCM_TIMESTAMP
+ if (level == SOL_SOCKET && type == SCM_TIMESTAMP &&
+ RSTRING_LEN(data) == sizeof(struct timeval)) {
+ struct timeval tv;
+ memcpy((char*)&tv, RSTRING_PTR(data), sizeof(tv));
+ result = rb_time_new(tv.tv_sec, tv.tv_usec);
+ }
+# endif
+
+# ifdef SCM_TIMESTAMPNS
+ if (level == SOL_SOCKET && type == SCM_TIMESTAMPNS &&
+ RSTRING_LEN(data) == sizeof(struct timespec)) {
+ struct timespec ts;
+ memcpy((char*)&ts, RSTRING_PTR(data), sizeof(ts));
+ result = rb_time_nano_new(ts.tv_sec, ts.tv_nsec);
+ }
+# endif
+
+#define add(x,y) (rb_funcall((x), '+', 1, (y)))
+#define mul(x,y) (rb_funcall((x), '*', 1, (y)))
+#define quo(x,y) (rb_funcall((x), rb_intern("quo"), 1, (y)))
+
+# ifdef SCM_BINTIME
+ if (level == SOL_SOCKET && type == SCM_BINTIME &&
+ RSTRING_LEN(data) == sizeof(struct bintime)) {
+ struct bintime bt;
+ VALUE d, timev;
+ memcpy((char*)&bt, RSTRING_PTR(data), sizeof(bt));
+ d = ULL2NUM(0x100000000ULL);
+ d = mul(d,d);
+ timev = add(TIMET2NUM(bt.sec), quo(ULL2NUM(bt.frac), d));
+ result = rb_time_num_new(timev, Qnil);
+ }
+# endif
+
+ if (result == Qnil)
+ rb_raise(rb_eTypeError, "timestamp ancillary data expected");
+
+ return result;
+}
+#else
+#define ancillary_timestamp rb_f_notimplement
+#endif
+
+/*
+ * call-seq:
+ * Socket::AncillaryData.int(family, cmsg_level, cmsg_type, integer) => ancillarydata
+ *
+ * Creates a new Socket::AncillaryData object which contains a int as data.
+ *
+ * The size and endian is dependent on the host.
+ *
+ * require 'socket'
+ *
+ * p Socket::AncillaryData.int(:UNIX, :SOCKET, :RIGHTS, STDERR.fileno)
+ * #=> #<Socket::AncillaryData: UNIX SOCKET RIGHTS 2>
+ */
+static VALUE
+ancillary_s_int(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE vtype, VALUE integer)
+{
+ int family = rsock_family_arg(vfamily);
+ int level = rsock_level_arg(family, vlevel);
+ int type = rsock_cmsg_type_arg(family, level, vtype);
+ int i = NUM2INT(integer);
+ return ancdata_new(family, level, type, rb_str_new((char*)&i, sizeof(i)));
+}
+
+/*
+ * call-seq:
+ * ancillarydata.int => integer
+ *
+ * Returns the data in _ancillarydata_ as an int.
+ *
+ * The size and endian is dependent on the host.
+ *
+ * ancdata = Socket::AncillaryData.int(:UNIX, :SOCKET, :RIGHTS, STDERR.fileno)
+ * p ancdata.int #=> 2
+ */
+static VALUE
+ancillary_int(VALUE self)
+{
+ VALUE data;
+ int i;
+ data = ancillary_data(self);
+ if (RSTRING_LEN(data) != sizeof(int))
+ rb_raise(rb_eTypeError, "size differ. expected as sizeof(int)=%d but %ld", (int)sizeof(int), (long)RSTRING_LEN(data));
+ memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
+ return INT2NUM(i);
+}
+
+#if defined(IPPROTO_IP) && defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST) /* GNU/Linux */
+/*
+ * call-seq:
+ * Socket::AncillaryData.ip_pktinfo(addr, ifindex) => ancdata
+ * Socket::AncillaryData.ip_pktinfo(addr, ifindex, spec_dst) => ancdata
+ *
+ * Returns new ancillary data for IP_PKTINFO.
+ *
+ * If spec_dst is not given, addr is used.
+ *
+ * IP_PKTINFO is not standard.
+ *
+ * Supported platform: GNU/Linux
+ *
+ * addr = Addrinfo.ip("127.0.0.1")
+ * ifindex = 0
+ * spec_dst = Addrinfo.ip("127.0.0.1")
+ * p Socket::AncillaryData.ip_pktinfo(addr, ifindex, spec_dst)
+ * #=> #<Socket::AncillaryData: INET IP PKTINFO 127.0.0.1 ifindex:0 spec_dst:127.0.0.1>
+ *
+ */
+static VALUE
+ancillary_s_ip_pktinfo(int argc, VALUE *argv, VALUE self)
+{
+ VALUE v_addr, v_ifindex, v_spec_dst;
+ unsigned int ifindex;
+ struct sockaddr_in sa;
+ struct in_pktinfo pktinfo;
+
+ rb_scan_args(argc, argv, "21", &v_addr, &v_ifindex, &v_spec_dst);
+
+ SockAddrStringValue(v_addr);
+ ifindex = NUM2UINT(v_ifindex);
+ if (NIL_P(v_spec_dst))
+ v_spec_dst = v_addr;
+ else
+ SockAddrStringValue(v_spec_dst);
+
+ memset(&pktinfo, 0, sizeof(pktinfo));
+
+ memset(&sa, 0, sizeof(sa));
+ if (RSTRING_LEN(v_addr) != sizeof(sa))
+ rb_raise(rb_eArgError, "addr size different to AF_INET sockaddr");
+ memcpy(&sa, RSTRING_PTR(v_addr), sizeof(sa));
+ if (sa.sin_family != AF_INET)
+ rb_raise(rb_eArgError, "addr is not AF_INET sockaddr");
+ memcpy(&pktinfo.ipi_addr, &sa.sin_addr, sizeof(pktinfo.ipi_addr));
+
+ pktinfo.ipi_ifindex = ifindex;
+
+ memset(&sa, 0, sizeof(sa));
+ if (RSTRING_LEN(v_spec_dst) != sizeof(sa))
+ rb_raise(rb_eArgError, "spec_dat size different to AF_INET sockaddr");
+ memcpy(&sa, RSTRING_PTR(v_spec_dst), sizeof(sa));
+ if (sa.sin_family != AF_INET)
+ rb_raise(rb_eArgError, "spec_dst is not AF_INET sockaddr");
+ memcpy(&pktinfo.ipi_spec_dst, &sa.sin_addr, sizeof(pktinfo.ipi_spec_dst));
+
+ return ancdata_new(AF_INET, IPPROTO_IP, IP_PKTINFO, rb_str_new((char *)&pktinfo, sizeof(pktinfo)));
+}
+#else
+#define ancillary_s_ip_pktinfo rb_f_notimplement
+#endif
+
+#if defined(IPPROTO_IP) && defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST) /* GNU/Linux */
+/*
+ * call-seq:
+ * ancdata.ip_pktinfo => [addr, ifindex, spec_dst]
+ *
+ * Extracts addr, ifindex and spec_dst from IP_PKTINFO ancillary data.
+ *
+ * IP_PKTINFO is not standard.
+ *
+ * Supported platform: GNU/Linux
+ *
+ * addr = Addrinfo.ip("127.0.0.1")
+ * ifindex = 0
+ * spec_dest = Addrinfo.ip("127.0.0.1")
+ * ancdata = Socket::AncillaryData.ip_pktinfo(addr, ifindex, spec_dest)
+ * p ancdata.ip_pktinfo
+ * #=> [#<Addrinfo: 127.0.0.1>, 0, #<Addrinfo: 127.0.0.1>]
+ *
+ *
+ */
+static VALUE
+ancillary_ip_pktinfo(VALUE self)
+{
+ int level, type;
+ VALUE data;
+ struct in_pktinfo pktinfo;
+ struct sockaddr_in sa;
+ VALUE v_spec_dst, v_addr;
+
+ level = ancillary_level(self);
+ type = ancillary_type(self);
+ data = ancillary_data(self);
+
+ if (level != IPPROTO_IP || type != IP_PKTINFO ||
+ RSTRING_LEN(data) != sizeof(struct in_pktinfo)) {
+ rb_raise(rb_eTypeError, "IP_PKTINFO ancillary data expected");
+ }
+
+ memcpy(&pktinfo, RSTRING_PTR(data), sizeof(struct in_pktinfo));
+ memset(&sa, 0, sizeof(sa));
+
+ sa.sin_family = AF_INET;
+ memcpy(&sa.sin_addr, &pktinfo.ipi_addr, sizeof(sa.sin_addr));
+ v_addr = rsock_addrinfo_new((struct sockaddr *)&sa, sizeof(sa), PF_INET, 0, 0, Qnil, Qnil);
+
+ sa.sin_family = AF_INET;
+ memcpy(&sa.sin_addr, &pktinfo.ipi_spec_dst, sizeof(sa.sin_addr));
+ v_spec_dst = rsock_addrinfo_new((struct sockaddr *)&sa, sizeof(sa), PF_INET, 0, 0, Qnil, Qnil);
+
+ return rb_ary_new3(3, v_addr, UINT2NUM(pktinfo.ipi_ifindex), v_spec_dst);
+}
+#else
+#define ancillary_ip_pktinfo rb_f_notimplement
+#endif
+
+#if defined(IPPROTO_IPV6) && defined(IPV6_PKTINFO) /* IPv6 RFC3542 */
+/*
+ * call-seq:
+ * Socket::AncillaryData.ipv6_pktinfo(addr, ifindex) => ancdata
+ *
+ * Returns new ancillary data for IPV6_PKTINFO.
+ *
+ * IPV6_PKTINFO is defined by RFC 3542.
+ *
+ * addr = Addrinfo.ip("::1")
+ * ifindex = 0
+ * p Socket::AncillaryData.ipv6_pktinfo(addr, ifindex)
+ * #=> #<Socket::AncillaryData: INET6 IPV6 PKTINFO ::1 ifindex:0>
+ *
+ */
+static VALUE
+ancillary_s_ipv6_pktinfo(VALUE self, VALUE v_addr, VALUE v_ifindex)
+{
+ unsigned int ifindex;
+ struct sockaddr_in6 sa;
+ struct in6_pktinfo pktinfo;
+
+ SockAddrStringValue(v_addr);
+ ifindex = NUM2UINT(v_ifindex);
+
+ memset(&pktinfo, 0, sizeof(pktinfo));
+
+ memset(&sa, 0, sizeof(sa));
+ if (RSTRING_LEN(v_addr) != sizeof(sa))
+ rb_raise(rb_eArgError, "addr size different to AF_INET6 sockaddr");
+ memcpy(&sa, RSTRING_PTR(v_addr), sizeof(sa));
+ if (sa.sin6_family != AF_INET6)
+ rb_raise(rb_eArgError, "addr is not AF_INET6 sockaddr");
+ memcpy(&pktinfo.ipi6_addr, &sa.sin6_addr, sizeof(pktinfo.ipi6_addr));
+
+ pktinfo.ipi6_ifindex = ifindex;
+
+ return ancdata_new(AF_INET6, IPPROTO_IPV6, IPV6_PKTINFO, rb_str_new((char *)&pktinfo, sizeof(pktinfo)));
+}
+#else
+#define ancillary_s_ipv6_pktinfo rb_f_notimplement
+#endif
+
+#if defined(IPPROTO_IPV6) && defined(IPV6_PKTINFO) /* IPv6 RFC3542 */
+static void
+extract_ipv6_pktinfo(VALUE self, struct in6_pktinfo *pktinfo_ptr, struct sockaddr_in6 *sa_ptr)
+{
+ int level, type;
+ VALUE data;
+
+ level = ancillary_level(self);
+ type = ancillary_type(self);
+ data = ancillary_data(self);
+
+ if (level != IPPROTO_IPV6 || type != IPV6_PKTINFO ||
+ RSTRING_LEN(data) != sizeof(struct in6_pktinfo)) {
+ rb_raise(rb_eTypeError, "IPV6_PKTINFO ancillary data expected");
+ }
+
+ memcpy(pktinfo_ptr, RSTRING_PTR(data), sizeof(*pktinfo_ptr));
+
+ INIT_SOCKADDR((struct sockaddr *)sa_ptr, AF_INET6, sizeof(*sa_ptr));
+ memcpy(&sa_ptr->sin6_addr, &pktinfo_ptr->ipi6_addr, sizeof(sa_ptr->sin6_addr));
+ if (IN6_IS_ADDR_LINKLOCAL(&sa_ptr->sin6_addr))
+ sa_ptr->sin6_scope_id = pktinfo_ptr->ipi6_ifindex;
+}
+#endif
+
+#if defined(IPPROTO_IPV6) && defined(IPV6_PKTINFO) /* IPv6 RFC3542 */
+/*
+ * call-seq:
+ * ancdata.ipv6_pktinfo => [addr, ifindex]
+ *
+ * Extracts addr and ifindex from IPV6_PKTINFO ancillary data.
+ *
+ * IPV6_PKTINFO is defined by RFC 3542.
+ *
+ * addr = Addrinfo.ip("::1")
+ * ifindex = 0
+ * ancdata = Socket::AncillaryData.ipv6_pktinfo(addr, ifindex)
+ * p ancdata.ipv6_pktinfo #=> [#<Addrinfo: ::1>, 0]
+ *
+ */
+static VALUE
+ancillary_ipv6_pktinfo(VALUE self)
+{
+ struct in6_pktinfo pktinfo;
+ struct sockaddr_in6 sa;
+ VALUE v_addr;
+
+ extract_ipv6_pktinfo(self, &pktinfo, &sa);
+ v_addr = rsock_addrinfo_new((struct sockaddr *)&sa, (socklen_t)sizeof(sa), PF_INET6, 0, 0, Qnil, Qnil);
+ return rb_ary_new3(2, v_addr, UINT2NUM(pktinfo.ipi6_ifindex));
+}
+#else
+#define ancillary_ipv6_pktinfo rb_f_notimplement
+#endif
+
+#if defined(IPPROTO_IPV6) && defined(IPV6_PKTINFO) /* IPv6 RFC3542 */
+/*
+ * call-seq:
+ * ancdata.ipv6_pktinfo_addr => addr
+ *
+ * Extracts addr from IPV6_PKTINFO ancillary data.
+ *
+ * IPV6_PKTINFO is defined by RFC 3542.
+ *
+ * addr = Addrinfo.ip("::1")
+ * ifindex = 0
+ * ancdata = Socket::AncillaryData.ipv6_pktinfo(addr, ifindex)
+ * p ancdata.ipv6_pktinfo_addr #=> #<Addrinfo: ::1>
+ *
+ */
+static VALUE
+ancillary_ipv6_pktinfo_addr(VALUE self)
+{
+ struct in6_pktinfo pktinfo;
+ struct sockaddr_in6 sa;
+ extract_ipv6_pktinfo(self, &pktinfo, &sa);
+ return rsock_addrinfo_new((struct sockaddr *)&sa, (socklen_t)sizeof(sa), PF_INET6, 0, 0, Qnil, Qnil);
+}
+#else
+#define ancillary_ipv6_pktinfo_addr rb_f_notimplement
+#endif
+
+#if defined(IPPROTO_IPV6) && defined(IPV6_PKTINFO) /* IPv6 RFC3542 */
+/*
+ * call-seq:
+ * ancdata.ipv6_pktinfo_ifindex => addr
+ *
+ * Extracts ifindex from IPV6_PKTINFO ancillary data.
+ *
+ * IPV6_PKTINFO is defined by RFC 3542.
+ *
+ * addr = Addrinfo.ip("::1")
+ * ifindex = 0
+ * ancdata = Socket::AncillaryData.ipv6_pktinfo(addr, ifindex)
+ * p ancdata.ipv6_pktinfo_ifindex #=> 0
+ *
+ */
+static VALUE
+ancillary_ipv6_pktinfo_ifindex(VALUE self)
+{
+ struct in6_pktinfo pktinfo;
+ struct sockaddr_in6 sa;
+ extract_ipv6_pktinfo(self, &pktinfo, &sa);
+ return UINT2NUM(pktinfo.ipi6_ifindex);
+}
+#else
+#define ancillary_ipv6_pktinfo_ifindex rb_f_notimplement
+#endif
+
+#if defined(SOL_SOCKET) && defined(SCM_RIGHTS) /* 4.4BSD */
+static int
+anc_inspect_socket_rights(int level, int type, VALUE data, VALUE ret)
+{
+ if (level == SOL_SOCKET && type == SCM_RIGHTS &&
+ 0 < RSTRING_LEN(data) && (RSTRING_LEN(data) % sizeof(int) == 0)) {
+ long off;
+ for (off = 0; off < RSTRING_LEN(data); off += sizeof(int)) {
+ int fd;
+ memcpy((char*)&fd, RSTRING_PTR(data)+off, sizeof(int));
+ rb_str_catf(ret, " %d", fd);
+ }
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(SCM_CREDENTIALS) /* GNU/Linux */
+static int
+anc_inspect_passcred_credentials(int level, int type, VALUE data, VALUE ret)
+{
+ if (level == SOL_SOCKET && type == SCM_CREDENTIALS &&
+ RSTRING_LEN(data) == sizeof(struct ucred)) {
+ struct ucred cred;
+ memcpy(&cred, RSTRING_PTR(data), sizeof(struct ucred));
+ rb_str_catf(ret, " pid=%u uid=%u gid=%u", cred.pid, cred.uid, cred.gid);
+ rb_str_cat2(ret, " (ucred)");
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(SCM_CREDS)
+#define INSPECT_SCM_CREDS
+static int
+anc_inspect_socket_creds(int level, int type, VALUE data, VALUE ret)
+{
+ if (level != SOL_SOCKET && type != SCM_CREDS)
+ return 0;
+
+ /*
+ * FreeBSD has struct cmsgcred and struct sockcred.
+ * They use both SOL_SOCKET/SCM_CREDS in the ancillary message.
+ * They are not ambiguous from the view of the caller
+ * because struct sockcred is sent if and only if the caller sets LOCAL_CREDS socket option.
+ * But inspect method doesn't know it.
+ * So they are ambiguous from the view of inspect.
+ * This function distinguish them by the size of the ancillary message.
+ * This heuristics works well except when sc_ngroups == CMGROUP_MAX.
+ */
+
+#if defined(HAVE_TYPE_STRUCT_CMSGCRED) /* FreeBSD */
+ if (RSTRING_LEN(data) == sizeof(struct cmsgcred)) {
+ struct cmsgcred cred;
+ memcpy(&cred, RSTRING_PTR(data), sizeof(struct cmsgcred));
+ rb_str_catf(ret, " pid=%u", cred.cmcred_pid);
+ rb_str_catf(ret, " uid=%u", cred.cmcred_uid);
+ rb_str_catf(ret, " euid=%u", cred.cmcred_euid);
+ rb_str_catf(ret, " gid=%u", cred.cmcred_gid);
+ if (cred.cmcred_ngroups) {
+ int i;
+ const char *sep = " groups=";
+ for (i = 0; i < cred.cmcred_ngroups; i++) {
+ rb_str_catf(ret, "%s%u", sep, cred.cmcred_groups[i]);
+ sep = ",";
+ }
+ }
+ rb_str_cat2(ret, " (cmsgcred)");
+ return 1;
+ }
+#endif
+#if defined(HAVE_TYPE_STRUCT_SOCKCRED) /* FreeBSD, NetBSD */
+ if ((size_t)RSTRING_LEN(data) >= SOCKCREDSIZE(0)) {
+ struct sockcred cred0, *cred;
+ memcpy(&cred0, RSTRING_PTR(data), SOCKCREDSIZE(0));
+ if ((size_t)RSTRING_LEN(data) == SOCKCREDSIZE(cred0.sc_ngroups)) {
+ cred = (struct sockcred *)ALLOCA_N(char, SOCKCREDSIZE(cred0.sc_ngroups));
+ memcpy(cred, RSTRING_PTR(data), SOCKCREDSIZE(cred0.sc_ngroups));
+ rb_str_catf(ret, " uid=%u", cred->sc_uid);
+ rb_str_catf(ret, " euid=%u", cred->sc_euid);
+ rb_str_catf(ret, " gid=%u", cred->sc_gid);
+ rb_str_catf(ret, " egid=%u", cred->sc_egid);
+ if (cred0.sc_ngroups) {
+ int i;
+ const char *sep = " groups=";
+ for (i = 0; i < cred0.sc_ngroups; i++) {
+ rb_str_catf(ret, "%s%u", sep, cred->sc_groups[i]);
+ sep = ",";
+ }
+ }
+ rb_str_cat2(ret, " (sockcred)");
+ return 1;
+ }
+ }
+#endif
+ return 0;
+}
+#endif
+
+#if defined(IPPROTO_IP) && defined(IP_RECVDSTADDR) /* 4.4BSD */
+static int
+anc_inspect_ip_recvdstaddr(int level, int type, VALUE data, VALUE ret)
+{
+ if (level == IPPROTO_IP && type == IP_RECVDSTADDR &&
+ RSTRING_LEN(data) == sizeof(struct in_addr)) {
+ struct in_addr addr;
+ char addrbuf[INET_ADDRSTRLEN];
+ memcpy(&addr, RSTRING_PTR(data), sizeof(addr));
+ if (inet_ntop(AF_INET, &addr, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
+ rb_str_cat2(ret, " invalid-address");
+ else
+ rb_str_catf(ret, " %s", addrbuf);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(IPPROTO_IP) && defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST) /* GNU/Linux */
+static int
+anc_inspect_ip_pktinfo(int level, int type, VALUE data, VALUE ret)
+{
+ if (level == IPPROTO_IP && type == IP_PKTINFO &&
+ RSTRING_LEN(data) == sizeof(struct in_pktinfo)) {
+ struct in_pktinfo pktinfo;
+ char buf[INET_ADDRSTRLEN > IFNAMSIZ ? INET_ADDRSTRLEN : IFNAMSIZ];
+ memcpy(&pktinfo, RSTRING_PTR(data), sizeof(pktinfo));
+ if (inet_ntop(AF_INET, &pktinfo.ipi_addr, buf, sizeof(buf)) == NULL)
+ rb_str_cat2(ret, " invalid-address");
+ else
+ rb_str_catf(ret, " %s", buf);
+ if (if_indextoname(pktinfo.ipi_ifindex, buf) == NULL)
+ rb_str_catf(ret, " ifindex:%d", pktinfo.ipi_ifindex);
+ else
+ rb_str_catf(ret, " %s", buf);
+ if (inet_ntop(AF_INET, &pktinfo.ipi_spec_dst, buf, sizeof(buf)) == NULL)
+ rb_str_cat2(ret, " spec_dst:invalid-address");
+ else
+ rb_str_catf(ret, " spec_dst:%s", buf);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(IPPROTO_IPV6) && defined(IPV6_PKTINFO) && defined(HAVE_TYPE_STRUCT_IN6_PKTINFO) /* IPv6 RFC3542 */
+static int
+anc_inspect_ipv6_pktinfo(int level, int type, VALUE data, VALUE ret)
+{
+ if (level == IPPROTO_IPV6 && type == IPV6_PKTINFO &&
+ RSTRING_LEN(data) == sizeof(struct in6_pktinfo)) {
+ struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)RSTRING_PTR(data);
+ struct in6_addr addr;
+ unsigned int ifindex;
+ char addrbuf[INET6_ADDRSTRLEN], ifbuf[IFNAMSIZ];
+ memcpy(&addr, &pktinfo->ipi6_addr, sizeof(addr));
+ memcpy(&ifindex, &pktinfo->ipi6_ifindex, sizeof(ifindex));
+ if (inet_ntop(AF_INET6, &addr, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
+ rb_str_cat2(ret, " invalid-address");
+ else
+ rb_str_catf(ret, " %s", addrbuf);
+ if (if_indextoname(ifindex, ifbuf) == NULL)
+ rb_str_catf(ret, " ifindex:%d", ifindex);
+ else
+ rb_str_catf(ret, " %s", ifbuf);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#ifdef HAVE_GMTIME_R
+# define LOCALTIME(time, tm) localtime_r(&(time), &(tm))
+#else
+# define LOCALTIME(time, tm) ((tm) = *localtime(&(time)))
+#endif
+
+#if defined(SCM_TIMESTAMP) /* GNU/Linux, FreeBSD, NetBSD, OpenBSD, MacOS X, Solaris */
+static int
+inspect_timeval_as_abstime(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(struct timeval)) {
+ struct timeval tv;
+ time_t time;
+ struct tm tm;
+ char buf[32];
+ memcpy((char*)&tv, RSTRING_PTR(data), sizeof(tv));
+ time = tv.tv_sec;
+ LOCALTIME(time, tm);
+ strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
+ rb_str_catf(ret, " %s.%06ld", buf, (long)tv.tv_usec);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(SCM_TIMESTAMPNS) /* GNU/Linux */
+static int
+inspect_timespec_as_abstime(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(struct timespec)) {
+ struct timespec ts;
+ struct tm tm;
+ char buf[32];
+ memcpy((char*)&ts, RSTRING_PTR(data), sizeof(ts));
+ LOCALTIME(ts.tv_sec, tm);
+ strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
+ rb_str_catf(ret, " %s.%09ld", buf, (long)ts.tv_nsec);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(SCM_BINTIME) /* FreeBSD */
+static int
+inspect_bintime_as_abstime(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(struct bintime)) {
+ struct bintime bt;
+ struct tm tm;
+ uint64_t frac_h, frac_l;
+ uint64_t scale_h, scale_l;
+ uint64_t tmp1, tmp2;
+ uint64_t res_h, res_l;
+ char buf[32];
+ memcpy((char*)&bt, RSTRING_PTR(data), sizeof(bt));
+ LOCALTIME(bt.sec, tm);
+ strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
+
+ /* res_h = frac * 10**19 / 2**64 */
+
+ frac_h = bt.frac >> 32;
+ frac_l = bt.frac & 0xffffffff;
+
+ scale_h = 0x8ac72304; /* 0x8ac7230489e80000 == 10**19 */
+ scale_l = 0x89e80000;
+
+ res_h = frac_h * scale_h;
+ res_l = frac_l * scale_l;
+
+ tmp1 = frac_h * scale_l;
+ res_h += tmp1 >> 32;
+ tmp2 = res_l;
+ res_l += tmp1 & 0xffffffff;
+ if (res_l < tmp2) res_h++;
+
+ tmp1 = frac_l * scale_h;
+ res_h += tmp1 >> 32;
+ tmp2 = res_l;
+ res_l += tmp1 & 0xffffffff;
+ if (res_l < tmp2) res_h++;
+
+ rb_str_catf(ret, " %s.%019"PRIu64, buf, res_h);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+/*
+ * call-seq:
+ * ancillarydata.inspect => string
+ *
+ * returns a string which shows ancillarydata in human-readable form.
+ *
+ * p Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "").inspect
+ * #=> "#<Socket::AncillaryData: INET6 IPV6 PKTINFO \"\">"
+ */
+static VALUE
+ancillary_inspect(VALUE self)
+{
+ VALUE ret;
+ int family, level, type;
+ VALUE data;
+ ID family_id, level_id, type_id;
+ VALUE vtype;
+ int inspected;
+
+ family = ancillary_family(self);
+ level = ancillary_level(self);
+ type = ancillary_type(self);
+ data = ancillary_data(self);
+
+ ret = rb_sprintf("#<%s:", rb_obj_classname(self));
+
+ family_id = rsock_intern_family_noprefix(family);
+ if (family_id)
+ rb_str_catf(ret, " %s", rb_id2name(family_id));
+ else
+ rb_str_catf(ret, " family:%d", family);
+
+ if (level == SOL_SOCKET) {
+ rb_str_cat2(ret, " SOCKET");
+
+ type_id = rsock_intern_scm_optname(type);
+ if (type_id)
+ rb_str_catf(ret, " %s", rb_id2name(type_id));
+ else
+ rb_str_catf(ret, " cmsg_type:%d", type);
+ }
+ else if (IS_IP_FAMILY(family)) {
+ level_id = rsock_intern_iplevel(level);
+ if (level_id)
+ rb_str_catf(ret, " %s", rb_id2name(level_id));
+ else
+ rb_str_catf(ret, " cmsg_level:%d", level);
+
+ vtype = ip_cmsg_type_to_sym(level, type);
+ if (SYMBOL_P(vtype))
+ rb_str_catf(ret, " %"PRIsVALUE, rb_sym2str(vtype));
+ else
+ rb_str_catf(ret, " cmsg_type:%d", type);
+ }
+ else {
+ rb_str_catf(ret, " cmsg_level:%d", level);
+ rb_str_catf(ret, " cmsg_type:%d", type);
+ }
+
+ inspected = 0;
+
+ if (level == SOL_SOCKET)
+ family = AF_UNSPEC;
+
+ switch (family) {
+ case AF_UNSPEC:
+ switch (level) {
+# if defined(SOL_SOCKET)
+ case SOL_SOCKET:
+ switch (type) {
+# if defined(SCM_TIMESTAMP) /* GNU/Linux, FreeBSD, NetBSD, OpenBSD, MacOS X, Solaris */
+ case SCM_TIMESTAMP: inspected = inspect_timeval_as_abstime(level, type, data, ret); break;
+# endif
+# if defined(SCM_TIMESTAMPNS) /* GNU/Linux */
+ case SCM_TIMESTAMPNS: inspected = inspect_timespec_as_abstime(level, type, data, ret); break;
+# endif
+# if defined(SCM_BINTIME) /* FreeBSD */
+ case SCM_BINTIME: inspected = inspect_bintime_as_abstime(level, type, data, ret); break;
+# endif
+# if defined(SCM_RIGHTS) /* 4.4BSD */
+ case SCM_RIGHTS: inspected = anc_inspect_socket_rights(level, type, data, ret); break;
+# endif
+# if defined(SCM_CREDENTIALS) /* GNU/Linux */
+ case SCM_CREDENTIALS: inspected = anc_inspect_passcred_credentials(level, type, data, ret); break;
+# endif
+# if defined(INSPECT_SCM_CREDS) /* NetBSD */
+ case SCM_CREDS: inspected = anc_inspect_socket_creds(level, type, data, ret); break;
+# endif
+ }
+ break;
+# endif
+ }
+ break;
+
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ switch (level) {
+# if defined(IPPROTO_IP)
+ case IPPROTO_IP:
+ switch (type) {
+# if defined(IP_RECVDSTADDR) /* 4.4BSD */
+ case IP_RECVDSTADDR: inspected = anc_inspect_ip_recvdstaddr(level, type, data, ret); break;
+# endif
+# if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST) /* GNU/Linux */
+ case IP_PKTINFO: inspected = anc_inspect_ip_pktinfo(level, type, data, ret); break;
+# endif
+ }
+ break;
+# endif
+
+# if defined(IPPROTO_IPV6)
+ case IPPROTO_IPV6:
+ switch (type) {
+# if defined(IPV6_PKTINFO) && defined(HAVE_TYPE_STRUCT_IN6_PKTINFO) /* RFC 3542 */
+ case IPV6_PKTINFO: inspected = anc_inspect_ipv6_pktinfo(level, type, data, ret); break;
+# endif
+ }
+ break;
+# endif
+ }
+ break;
+ }
+
+ if (!inspected) {
+ rb_str_cat2(ret, " ");
+ rb_str_append(ret, rb_str_dump(data));
+ }
+
+ rb_str_cat2(ret, ">");
+
+ return ret;
+}
+
+/*
+ * call-seq:
+ * ancillarydata.cmsg_is?(level, type) => true or false
+ *
+ * tests the level and type of _ancillarydata_.
+ *
+ * ancdata = Socket::AncillaryData.new(:INET6, :IPV6, :PKTINFO, "")
+ * ancdata.cmsg_is?(Socket::IPPROTO_IPV6, Socket::IPV6_PKTINFO) #=> true
+ * ancdata.cmsg_is?(:IPV6, :PKTINFO) #=> true
+ * ancdata.cmsg_is?(:IP, :PKTINFO) #=> false
+ * ancdata.cmsg_is?(:SOCKET, :RIGHTS) #=> false
+ */
+static VALUE
+ancillary_cmsg_is_p(VALUE self, VALUE vlevel, VALUE vtype)
+{
+ int family = ancillary_family(self);
+ int level = rsock_level_arg(family, vlevel);
+ int type = rsock_cmsg_type_arg(family, level, vtype);
+
+ if (ancillary_level(self) == level &&
+ ancillary_type(self) == type)
+ return Qtrue;
+ else
+ return Qfalse;
+}
+
+#endif
+
+#if defined(HAVE_SENDMSG)
+struct sendmsg_args_struct {
+ int fd;
+ int flags;
+ const struct msghdr *msg;
+};
+
+static void *
+nogvl_sendmsg_func(void *ptr)
+{
+ struct sendmsg_args_struct *args = ptr;
+ return (void *)(VALUE)sendmsg(args->fd, args->msg, args->flags);
+}
+
+static ssize_t
+rb_sendmsg(int fd, const struct msghdr *msg, int flags)
+{
+ struct sendmsg_args_struct args;
+ args.fd = fd;
+ args.msg = msg;
+ args.flags = flags;
+ return (ssize_t)rb_thread_call_without_gvl(nogvl_sendmsg_func, &args, RUBY_UBF_IO, 0);
+}
+
+static VALUE
+bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags,
+ VALUE dest_sockaddr, VALUE controls, VALUE ex,
+ int nonblock)
+{
+ rb_io_t *fptr;
+ struct msghdr mh;
+ struct iovec iov;
+ VALUE tmp;
+ int controls_num;
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ VALUE controls_str = 0;
+ int family;
+#endif
+ int flags;
+ ssize_t ss;
+
+ GetOpenFile(sock, fptr);
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ family = rsock_getfamily(fptr);
+#endif
+
+ StringValue(data);
+ tmp = rb_str_tmp_frozen_acquire(data);
+
+ if (!RB_TYPE_P(controls, T_ARRAY)) {
+ controls = rb_ary_new();
+ }
+ controls_num = RARRAY_LENINT(controls);
+
+ if (controls_num) {
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ int i;
+ size_t last_pad = 0;
+ const VALUE *controls_ptr = RARRAY_CONST_PTR(controls);
+#if defined(__NetBSD__)
+ int last_level = 0;
+ int last_type = 0;
+#endif
+ controls_str = rb_str_tmp_new(0);
+ for (i = 0; i < controls_num; i++) {
+ VALUE elt = controls_ptr[i], v;
+ VALUE vlevel, vtype;
+ int level, type;
+ VALUE cdata;
+ long oldlen;
+ struct cmsghdr cmh;
+ char *cmsg;
+ size_t cspace;
+ v = rb_check_convert_type(elt, T_ARRAY, "Array", "to_ary");
+ if (!NIL_P(v)) {
+ elt = v;
+ if (RARRAY_LEN(elt) != 3)
+ rb_raise(rb_eArgError, "an element of controls should be 3-elements array");
+ vlevel = rb_ary_entry(elt, 0);
+ vtype = rb_ary_entry(elt, 1);
+ cdata = rb_ary_entry(elt, 2);
+ }
+ else {
+ vlevel = rb_funcall(elt, rb_intern("level"), 0);
+ vtype = rb_funcall(elt, rb_intern("type"), 0);
+ cdata = rb_funcall(elt, rb_intern("data"), 0);
+ }
+ level = rsock_level_arg(family, vlevel);
+ type = rsock_cmsg_type_arg(family, level, vtype);
+ StringValue(cdata);
+ oldlen = RSTRING_LEN(controls_str);
+ cspace = CMSG_SPACE(RSTRING_LEN(cdata));
+ rb_str_resize(controls_str, oldlen + cspace);
+ cmsg = RSTRING_PTR(controls_str)+oldlen;
+ memset((char *)cmsg, 0, cspace);
+ memset((char *)&cmh, 0, sizeof(cmh));
+ cmh.cmsg_level = level;
+ cmh.cmsg_type = type;
+ cmh.cmsg_len = (socklen_t)CMSG_LEN(RSTRING_LEN(cdata));
+ MEMCPY(cmsg, &cmh, char, sizeof(cmh));
+ MEMCPY(cmsg+((char*)CMSG_DATA(&cmh)-(char*)&cmh), RSTRING_PTR(cdata), char, RSTRING_LEN(cdata));
+#if defined(__NetBSD__)
+ last_level = cmh.cmsg_level;
+ last_type = cmh.cmsg_type;
+#endif
+ last_pad = cspace - cmh.cmsg_len;
+ }
+ if (last_pad) {
+ /*
+ * This code removes the last padding from msg_controllen.
+ *
+ * 4.3BSD-Reno reject the padding for SCM_RIGHTS. (There was no 64bit environments in those days?)
+ * RFC 2292 require the padding.
+ * RFC 3542 relaxes the condition - implementation must accept both as valid.
+ *
+ * Actual problems:
+ *
+ * - NetBSD 4.0.1
+ * SCM_RIGHTS with padding causes EINVAL
+ * IPV6_PKTINFO without padding causes "page fault trap"
+ * http://www.netbsd.org/cgi-bin/query-pr-single.pl?number=40661
+ *
+ * - OpenBSD 4.4
+ * IPV6_PKTINFO without padding causes EINVAL
+ *
+ * Basically, msg_controllen should contains the padding.
+ * So the padding is removed only if a problem really exists.
+ */
+#if defined(__NetBSD__)
+ if (last_level == SOL_SOCKET && last_type == SCM_RIGHTS)
+ rb_str_set_len(controls_str, RSTRING_LEN(controls_str)-last_pad);
+#endif
+ }
+ RB_GC_GUARD(controls);
+#else
+ rb_raise(rb_eNotImpError, "control message for sendmsg is unimplemented");
+#endif
+ }
+
+ flags = NIL_P(vflags) ? 0 : NUM2INT(vflags);
+#ifdef MSG_DONTWAIT
+ if (nonblock)
+ flags |= MSG_DONTWAIT;
+#endif
+
+ if (!NIL_P(dest_sockaddr))
+ SockAddrStringValue(dest_sockaddr);
+
+ rb_io_check_closed(fptr);
+
+ retry:
+ memset(&mh, 0, sizeof(mh));
+ if (!NIL_P(dest_sockaddr)) {
+ mh.msg_name = RSTRING_PTR(dest_sockaddr);
+ mh.msg_namelen = RSTRING_SOCKLEN(dest_sockaddr);
+ }
+ mh.msg_iovlen = 1;
+ mh.msg_iov = &iov;
+ iov.iov_base = RSTRING_PTR(tmp);
+ iov.iov_len = RSTRING_LEN(tmp);
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ if (controls_str) {
+ mh.msg_control = RSTRING_PTR(controls_str);
+ mh.msg_controllen = RSTRING_SOCKLEN(controls_str);
+ }
+#endif
+
+ rb_io_check_closed(fptr);
+ if (nonblock && !MSG_DONTWAIT_RELIABLE)
+ rb_io_set_nonblock(fptr);
+
+ ss = rb_sendmsg(fptr->fd, &mh, flags);
+
+ if (ss == -1) {
+ int e;
+ if (!nonblock && rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) {
+ rb_io_check_closed(fptr);
+ goto retry;
+ }
+ e = errno;
+ if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
+ if (ex == Qfalse) {
+ return sym_wait_writable;
+ }
+ rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e,
+ "sendmsg(2) would block");
+ }
+ rb_syserr_fail(e, "sendmsg(2)");
+ }
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ RB_GC_GUARD(controls_str);
+#endif
+ rb_str_tmp_frozen_release(data, tmp);
+
+ return SSIZET2NUM(ss);
+}
+#endif
+
+#if defined(HAVE_SENDMSG)
+VALUE
+rsock_bsock_sendmsg(VALUE sock, VALUE data, VALUE flags, VALUE dest_sockaddr,
+ VALUE controls)
+{
+ return bsock_sendmsg_internal(sock, data, flags, dest_sockaddr, controls,
+ Qtrue, 0);
+}
+#endif
+
+#if defined(HAVE_SENDMSG)
+VALUE
+rsock_bsock_sendmsg_nonblock(VALUE sock, VALUE data, VALUE flags,
+ VALUE dest_sockaddr, VALUE controls, VALUE ex)
+{
+ return bsock_sendmsg_internal(sock, data, flags, dest_sockaddr,
+ controls, ex, 1);
+}
+#endif
+
+#if defined(HAVE_RECVMSG)
+struct recvmsg_args_struct {
+ int fd;
+ int flags;
+ struct msghdr *msg;
+};
+
+ssize_t
+rsock_recvmsg(int socket, struct msghdr *message, int flags)
+{
+ ssize_t ret;
+ socklen_t len0;
+#ifdef MSG_CMSG_CLOEXEC
+ /* MSG_CMSG_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
+ flags |= MSG_CMSG_CLOEXEC;
+#endif
+ len0 = message->msg_namelen;
+ ret = recvmsg(socket, message, flags);
+ if (ret != -1 && len0 < message->msg_namelen)
+ message->msg_namelen = len0;
+ return ret;
+}
+
+static void *
+nogvl_recvmsg_func(void *ptr)
+{
+ struct recvmsg_args_struct *args = ptr;
+ int flags = args->flags;
+ return (void *)rsock_recvmsg(args->fd, args->msg, flags);
+}
+
+static ssize_t
+rb_recvmsg(int fd, struct msghdr *msg, int flags)
+{
+ struct recvmsg_args_struct args;
+ args.fd = fd;
+ args.msg = msg;
+ args.flags = flags;
+ return (ssize_t)rb_thread_call_without_gvl(nogvl_recvmsg_func, &args, RUBY_UBF_IO, 0);
+}
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+static void
+discard_cmsg(struct cmsghdr *cmh, char *msg_end, int msg_peek_p)
+{
+# if !defined(FD_PASSING_WORK_WITH_RECVMSG_MSG_PEEK)
+ /*
+ * FreeBSD 8.2.0, NetBSD 5 and MacOS X Snow Leopard doesn't
+ * allocate fds by recvmsg with MSG_PEEK.
+ * [ruby-dev:44189]
+ * http://bugs.ruby-lang.org/issues/5075
+ *
+ * Linux 2.6.38 allocate fds by recvmsg with MSG_PEEK.
+ */
+ if (msg_peek_p)
+ return;
+# endif
+ if (cmh->cmsg_level == SOL_SOCKET && cmh->cmsg_type == SCM_RIGHTS) {
+ int *fdp = (int *)CMSG_DATA(cmh);
+ int *end = (int *)((char *)cmh + cmh->cmsg_len);
+ while ((char *)fdp + sizeof(int) <= (char *)end &&
+ (char *)fdp + sizeof(int) <= msg_end) {
+ rb_update_max_fd(*fdp);
+ close(*fdp);
+ fdp++;
+ }
+ }
+}
+#endif
+
+void
+rsock_discard_cmsg_resource(struct msghdr *mh, int msg_peek_p)
+{
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ struct cmsghdr *cmh;
+ char *msg_end;
+
+ if (mh->msg_controllen == 0)
+ return;
+
+ msg_end = (char *)mh->msg_control + mh->msg_controllen;
+
+ for (cmh = CMSG_FIRSTHDR(mh); cmh != NULL; cmh = CMSG_NXTHDR(mh, cmh)) {
+ discard_cmsg(cmh, msg_end, msg_peek_p);
+ }
+#endif
+}
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+static void
+make_io_for_unix_rights(VALUE ctl, struct cmsghdr *cmh, char *msg_end)
+{
+ if (cmh->cmsg_level == SOL_SOCKET && cmh->cmsg_type == SCM_RIGHTS) {
+ int *fdp, *end;
+ VALUE ary = rb_ary_new();
+ rb_ivar_set(ctl, rb_intern("unix_rights"), ary);
+ fdp = (int *)CMSG_DATA(cmh);
+ end = (int *)((char *)cmh + cmh->cmsg_len);
+ while ((char *)fdp + sizeof(int) <= (char *)end &&
+ (char *)fdp + sizeof(int) <= msg_end) {
+ int fd = *fdp;
+ struct stat stbuf;
+ VALUE io;
+ if (fstat(fd, &stbuf) == -1)
+ rb_raise(rb_eSocket, "invalid fd in SCM_RIGHTS");
+ rb_update_max_fd(fd);
+ rb_maygvl_fd_fix_cloexec(fd);
+ if (S_ISSOCK(stbuf.st_mode))
+ io = rsock_init_sock(rb_obj_alloc(rb_cSocket), fd);
+ else
+ io = rb_io_fdopen(fd, O_RDWR, NULL);
+ ary = rb_attr_get(ctl, rb_intern("unix_rights"));
+ rb_ary_push(ary, io);
+ fdp++;
+ }
+ OBJ_FREEZE(ary);
+ }
+}
+#endif
+
+static VALUE
+bsock_recvmsg_internal(VALUE sock,
+ VALUE vmaxdatlen, VALUE vflags, VALUE vmaxctllen,
+ VALUE scm_rights, VALUE ex, int nonblock)
+{
+ rb_io_t *fptr;
+ int grow_buffer;
+ size_t maxdatlen;
+ int flags, orig_flags;
+ struct msghdr mh;
+ struct iovec iov;
+ union_sockaddr namebuf;
+ char *datbuf;
+ VALUE dat_str = Qnil;
+ VALUE ret;
+ ssize_t ss;
+ int request_scm_rights;
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ struct cmsghdr *cmh;
+ size_t maxctllen;
+ char *ctlbuf;
+ VALUE ctl_str = Qnil;
+ int family;
+ int gc_done = 0;
+#endif
+
+ maxdatlen = NIL_P(vmaxdatlen) ? 4096 : NUM2SIZET(vmaxdatlen);
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ maxctllen = NIL_P(vmaxctllen) ? 4096 : NUM2SIZET(vmaxctllen);
+#else
+ if (!NIL_P(vmaxctllen))
+ rb_raise(rb_eArgError, "control message not supported");
+#endif
+ flags = NUM2INT(vflags);
+#ifdef MSG_DONTWAIT
+ if (nonblock)
+ flags |= MSG_DONTWAIT;
+#endif
+ orig_flags = flags;
+
+ grow_buffer = NIL_P(vmaxdatlen) || NIL_P(vmaxctllen);
+
+ request_scm_rights = 0;
+ if (RTEST(scm_rights))
+ request_scm_rights = 1;
+#if !defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ if (request_scm_rights)
+ rb_raise(rb_eNotImpError, "control message for recvmsg is unimplemented");
+#endif
+
+ GetOpenFile(sock, fptr);
+ if (rb_io_read_pending(fptr)) {
+ rb_raise(rb_eIOError, "recvmsg for buffered IO");
+ }
+
+#if !defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ if (grow_buffer) {
+ int socktype;
+ socklen_t optlen = (socklen_t)sizeof(socktype);
+ if (getsockopt(fptr->fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen) == -1) {
+ rb_sys_fail("getsockopt(SO_TYPE)");
+ }
+ if (socktype == SOCK_STREAM)
+ grow_buffer = 0;
+ }
+#endif
+
+ retry:
+ if (NIL_P(dat_str))
+ dat_str = rb_str_tmp_new(maxdatlen);
+ else
+ rb_str_resize(dat_str, maxdatlen);
+ datbuf = RSTRING_PTR(dat_str);
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ if (NIL_P(ctl_str))
+ ctl_str = rb_str_tmp_new(maxctllen);
+ else
+ rb_str_resize(ctl_str, maxctllen);
+ ctlbuf = RSTRING_PTR(ctl_str);
+#endif
+
+ memset(&mh, 0, sizeof(mh));
+
+ memset(&namebuf, 0, sizeof(namebuf));
+ mh.msg_name = &namebuf.addr;
+ mh.msg_namelen = (socklen_t)sizeof(namebuf);
+
+ mh.msg_iov = &iov;
+ mh.msg_iovlen = 1;
+ iov.iov_base = datbuf;
+ iov.iov_len = maxdatlen;
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ mh.msg_control = ctlbuf;
+ mh.msg_controllen = (socklen_t)maxctllen;
+#endif
+
+ if (grow_buffer)
+ flags |= MSG_PEEK;
+
+ rb_io_check_closed(fptr);
+ if (nonblock && !MSG_DONTWAIT_RELIABLE)
+ rb_io_set_nonblock(fptr);
+
+ ss = rb_recvmsg(fptr->fd, &mh, flags);
+
+ if (ss == 0 && !rsock_is_dgram(fptr)) {
+ return Qnil;
+ }
+
+ if (ss == -1) {
+ int e;
+ if (!nonblock && rb_io_maybe_wait_readable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) {
+ rb_io_check_closed(fptr);
+ goto retry;
+ }
+ e = errno;
+ if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
+ if (ex == Qfalse) {
+ return sym_wait_readable;
+ }
+ rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "recvmsg(2) would block");
+ }
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ if (!gc_done && (e == EMFILE || e == EMSGSIZE)) {
+ /*
+ * When SCM_RIGHTS hit the file descriptors limit:
+ * - Linux 2.6.18 causes success with MSG_CTRUNC
+ * - MacOS X 10.4 causes EMSGSIZE (and lost file descriptors?)
+ * - Solaris 11 causes EMFILE
+ */
+ gc_and_retry:
+ rb_gc();
+ gc_done = 1;
+ goto retry;
+ }
+#else
+ if (NIL_P(vmaxdatlen) && grow_buffer && e == EMSGSIZE)
+ ss = (ssize_t)iov.iov_len;
+ else
+#endif
+ rb_syserr_fail(e, "recvmsg(2)");
+ }
+
+ if (grow_buffer) {
+ int grown = 0;
+ if (NIL_P(vmaxdatlen) && ss != -1 && ss == (ssize_t)iov.iov_len) {
+ if (SIZE_MAX/2 < maxdatlen)
+ rb_raise(rb_eArgError, "max data length too big");
+ maxdatlen *= 2;
+ grown = 1;
+ }
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ if (NIL_P(vmaxctllen) && (mh.msg_flags & MSG_CTRUNC)) {
+#define BIG_ENOUGH_SPACE 65536
+ if (BIG_ENOUGH_SPACE < maxctllen &&
+ (socklen_t)mh.msg_controllen < (socklen_t)(maxctllen - BIG_ENOUGH_SPACE)) {
+ /* there are big space bug truncated.
+ * file descriptors limit? */
+ if (!gc_done) {
+ rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
+ goto gc_and_retry;
+ }
+ }
+ else {
+ if (SIZE_MAX/2 < maxctllen)
+ rb_raise(rb_eArgError, "max control message length too big");
+ maxctllen *= 2;
+ grown = 1;
+ }
+#undef BIG_ENOUGH_SPACE
+ }
+#endif
+ if (grown) {
+ rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
+ goto retry;
+ }
+ else {
+ grow_buffer = 0;
+ if (flags != orig_flags) {
+ rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
+ flags = orig_flags;
+ goto retry;
+ }
+ }
+ }
+
+ if (NIL_P(dat_str))
+ dat_str = rb_str_new(datbuf, ss);
+ else {
+ rb_str_resize(dat_str, ss);
+ rb_obj_reveal(dat_str, rb_cString);
+ }
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ VALUE msg_flags = INT2NUM(mh.msg_flags);
+#else
+ VALUE msg_flags = Qnil;
+#endif
+ ret = rb_ary_new3(3, dat_str,
+ rsock_io_socket_addrinfo(sock, mh.msg_name, mh.msg_namelen),
+ msg_flags);
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ family = rsock_getfamily(fptr);
+ if (mh.msg_controllen) {
+ char *msg_end = (char *)mh.msg_control + mh.msg_controllen;
+ for (cmh = CMSG_FIRSTHDR(&mh); cmh != NULL; cmh = CMSG_NXTHDR(&mh, cmh)) {
+ VALUE ctl;
+ char *ctl_end;
+ size_t clen;
+ if (cmh->cmsg_len == 0) {
+ rb_raise(rb_eTypeError, "invalid control message (cmsg_len == 0)");
+ }
+ ctl_end = (char*)cmh + cmh->cmsg_len;
+ clen = (ctl_end <= msg_end ? ctl_end : msg_end) - (char*)CMSG_DATA(cmh);
+ ctl = ancdata_new(family, cmh->cmsg_level, cmh->cmsg_type, rb_str_new((char*)CMSG_DATA(cmh), clen));
+ if (request_scm_rights)
+ make_io_for_unix_rights(ctl, cmh, msg_end);
+ else
+ discard_cmsg(cmh, msg_end, (flags & MSG_PEEK) != 0);
+ rb_ary_push(ret, ctl);
+ }
+ RB_GC_GUARD(ctl_str);
+ }
+#endif
+
+ return ret;
+}
+#endif
+
+#if defined(HAVE_RECVMSG)
+VALUE
+rsock_bsock_recvmsg(VALUE sock, VALUE dlen, VALUE flags, VALUE clen,
+ VALUE scm_rights)
+{
+ VALUE ex = Qtrue;
+ return bsock_recvmsg_internal(sock, dlen, flags, clen, scm_rights, ex, 0);
+}
+#endif
+
+#if defined(HAVE_RECVMSG)
+VALUE
+rsock_bsock_recvmsg_nonblock(VALUE sock, VALUE dlen, VALUE flags, VALUE clen,
+ VALUE scm_rights, VALUE ex)
+{
+ return bsock_recvmsg_internal(sock, dlen, flags, clen, scm_rights, ex, 1);
+}
+#endif
+
+void
+rsock_init_ancdata(void)
+{
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ /*
+ * Document-class: Socket::AncillaryData
+ *
+ * Socket::AncillaryData represents the ancillary data (control information)
+ * used by sendmsg and recvmsg system call. It contains socket #family,
+ * control message (cmsg) #level, cmsg #type and cmsg #data.
+ */
+ rb_cAncillaryData = rb_define_class_under(rb_cSocket, "AncillaryData", rb_cObject);
+ rb_define_method(rb_cAncillaryData, "initialize", ancillary_initialize, 4);
+ rb_define_method(rb_cAncillaryData, "inspect", ancillary_inspect, 0);
+ rb_define_method(rb_cAncillaryData, "family", ancillary_family_m, 0);
+ rb_define_method(rb_cAncillaryData, "level", ancillary_level_m, 0);
+ rb_define_method(rb_cAncillaryData, "type", ancillary_type_m, 0);
+ rb_define_method(rb_cAncillaryData, "data", ancillary_data, 0);
+
+ rb_define_method(rb_cAncillaryData, "cmsg_is?", ancillary_cmsg_is_p, 2);
+
+ rb_define_singleton_method(rb_cAncillaryData, "int", ancillary_s_int, 4);
+ rb_define_method(rb_cAncillaryData, "int", ancillary_int, 0);
+
+ rb_define_singleton_method(rb_cAncillaryData, "unix_rights", ancillary_s_unix_rights, -1);
+ rb_define_method(rb_cAncillaryData, "unix_rights", ancillary_unix_rights, 0);
+
+ rb_define_method(rb_cAncillaryData, "timestamp", ancillary_timestamp, 0);
+
+ rb_define_singleton_method(rb_cAncillaryData, "ip_pktinfo", ancillary_s_ip_pktinfo, -1);
+ rb_define_method(rb_cAncillaryData, "ip_pktinfo", ancillary_ip_pktinfo, 0);
+
+ rb_define_singleton_method(rb_cAncillaryData, "ipv6_pktinfo", ancillary_s_ipv6_pktinfo, 2);
+ rb_define_method(rb_cAncillaryData, "ipv6_pktinfo", ancillary_ipv6_pktinfo, 0);
+ rb_define_method(rb_cAncillaryData, "ipv6_pktinfo_addr", ancillary_ipv6_pktinfo_addr, 0);
+ rb_define_method(rb_cAncillaryData, "ipv6_pktinfo_ifindex", ancillary_ipv6_pktinfo_ifindex, 0);
+#endif
+#undef rb_intern
+ sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
+ sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
+}
diff --git a/ext/socket/basicsocket.c b/ext/socket/basicsocket.c
new file mode 100644
index 0000000000..2fcae8eb54
--- /dev/null
+++ b/ext/socket/basicsocket.c
@@ -0,0 +1,792 @@
+/************************************************
+
+ basicsocket.c -
+
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
+
+************************************************/
+
+#include "rubysocket.h"
+
+#ifdef _WIN32
+#define is_socket(fd) rb_w32_is_socket(fd)
+#else
+static int
+is_socket(int fd)
+{
+ struct stat sbuf;
+
+ if (fstat(fd, &sbuf) < 0)
+ rb_sys_fail("fstat(2)");
+ return S_ISSOCK(sbuf.st_mode);
+}
+#endif
+
+static void
+rsock_validate_descriptor(int descriptor)
+{
+ if (!is_socket(descriptor) || rb_reserved_fd_p(descriptor)) {
+ rb_syserr_fail(EBADF, "not a socket file descriptor");
+ }
+}
+
+/*
+ * call-seq:
+ * BasicSocket.for_fd(fd) => basicsocket
+ *
+ * Returns a socket object which contains the file descriptor, _fd_.
+ *
+ * # If invoked by inetd, STDIN/STDOUT/STDERR is a socket.
+ * STDIN_SOCK = Socket.for_fd(STDIN.fileno)
+ * p STDIN_SOCK.remote_address
+ *
+ */
+static VALUE
+bsock_s_for_fd(VALUE klass, VALUE _descriptor)
+{
+ rb_io_t *fptr;
+
+ int descriptor = RB_NUM2INT(_descriptor);
+ rsock_validate_descriptor(descriptor);
+
+ VALUE sock = rsock_init_sock(rb_obj_alloc(klass), descriptor);
+
+ GetOpenFile(sock, fptr);
+
+ return sock;
+}
+
+/*
+ * call-seq:
+ * basicsocket.shutdown([how]) => 0
+ *
+ * Calls shutdown(2) system call.
+ *
+ * s.shutdown(Socket::SHUT_RD) disallows further read.
+ *
+ * s.shutdown(Socket::SHUT_WR) disallows further write.
+ *
+ * s.shutdown(Socket::SHUT_RDWR) disallows further read and write.
+ *
+ * _how_ can be symbol or string:
+ * - :RD, :SHUT_RD, "RD" and "SHUT_RD" are accepted as Socket::SHUT_RD.
+ * - :WR, :SHUT_WR, "WR" and "SHUT_WR" are accepted as Socket::SHUT_WR.
+ * - :RDWR, :SHUT_RDWR, "RDWR" and "SHUT_RDWR" are accepted as Socket::SHUT_RDWR.
+ *
+ * UNIXSocket.pair {|s1, s2|
+ * s1.puts "ping"
+ * s1.shutdown(:WR)
+ * p s2.read #=> "ping\n"
+ * s2.puts "pong"
+ * s2.close
+ * p s1.read #=> "pong\n"
+ * }
+ *
+ */
+static VALUE
+bsock_shutdown(int argc, VALUE *argv, VALUE sock)
+{
+ VALUE howto;
+ int how;
+ rb_io_t *fptr;
+
+ rb_scan_args(argc, argv, "01", &howto);
+ if (howto == Qnil)
+ how = SHUT_RDWR;
+ else {
+ how = rsock_shutdown_how_arg(howto);
+ if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) {
+ rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR");
+ }
+ }
+ GetOpenFile(sock, fptr);
+ if (shutdown(fptr->fd, how) == -1)
+ rb_sys_fail("shutdown(2)");
+
+ return INT2FIX(0);
+}
+
+/*
+ * call-seq:
+ * basicsocket.close_read => nil
+ *
+ * Disallows further read using shutdown system call.
+ *
+ * s1, s2 = UNIXSocket.pair
+ * s1.close_read
+ * s2.puts #=> Broken pipe (Errno::EPIPE)
+ */
+static VALUE
+bsock_close_read(VALUE sock)
+{
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ shutdown(fptr->fd, SHUT_RD);
+ if (!(fptr->mode & FMODE_WRITABLE)) {
+ return rb_io_close(sock);
+ }
+ fptr->mode &= ~FMODE_READABLE;
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * basicsocket.close_write => nil
+ *
+ * Disallows further write using shutdown system call.
+ *
+ * UNIXSocket.pair {|s1, s2|
+ * s1.print "ping"
+ * s1.close_write
+ * p s2.read #=> "ping"
+ * s2.print "pong"
+ * s2.close
+ * p s1.read #=> "pong"
+ * }
+ */
+static VALUE
+bsock_close_write(VALUE sock)
+{
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (!(fptr->mode & FMODE_READABLE)) {
+ return rb_io_close(sock);
+ }
+ shutdown(fptr->fd, SHUT_WR);
+ fptr->mode &= ~FMODE_WRITABLE;
+
+ return Qnil;
+}
+
+/*
+ * Document-method: setsockopt
+ * call-seq:
+ * setsockopt(level, optname, optval)
+ * setsockopt(socketoption)
+ *
+ * Sets a socket option. These are protocol and system specific, see your
+ * local system documentation for details.
+ *
+ * === Parameters
+ * * +level+ is an integer, usually one of the SOL_ constants such as
+ * Socket::SOL_SOCKET, or a protocol level.
+ * A string or symbol of the name, possibly without prefix, is also
+ * accepted.
+ * * +optname+ is an integer, usually one of the SO_ constants, such
+ * as Socket::SO_REUSEADDR.
+ * A string or symbol of the name, possibly without prefix, is also
+ * accepted.
+ * * +optval+ is the value of the option, it is passed to the underlying
+ * setsockopt() as a pointer to a certain number of bytes. How this is
+ * done depends on the type:
+ * - Integer: value is assigned to an int, and a pointer to the int is
+ * passed, with length of sizeof(int).
+ * - true or false: 1 or 0 (respectively) is assigned to an int, and the
+ * int is passed as for an Integer. Note that +false+ must be passed,
+ * not +nil+.
+ * - String: the string's data and length is passed to the socket.
+ * * +socketoption+ is an instance of Socket::Option
+ *
+ * === Examples
+ *
+ * Some socket options are integers with boolean values, in this case
+ * #setsockopt could be called like this:
+ * sock.setsockopt(:SOCKET, :REUSEADDR, true)
+ * sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
+ * sock.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true))
+ *
+ * Some socket options are integers with numeric values, in this case
+ * #setsockopt could be called like this:
+ * sock.setsockopt(:IP, :TTL, 255)
+ * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
+ * sock.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255))
+ *
+ * Option values may be structs. Passing them can be complex as it involves
+ * examining your system headers to determine the correct definition. An
+ * example is an +ip_mreq+, which may be defined in your system headers as:
+ * struct ip_mreq {
+ * struct in_addr imr_multiaddr;
+ * struct in_addr imr_interface;
+ * };
+ *
+ * In this case #setsockopt could be called like this:
+ * optval = IPAddr.new("224.0.0.251").hton +
+ * IPAddr.new(Socket::INADDR_ANY, Socket::AF_INET).hton
+ * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)
+ *
+*/
+static VALUE
+bsock_setsockopt(int argc, VALUE *argv, VALUE sock)
+{
+ VALUE lev, optname, val;
+ int family, level, option;
+ rb_io_t *fptr;
+ int i;
+ char *v;
+ int vlen;
+
+ if (argc == 1) {
+ lev = rb_funcall(argv[0], rb_intern("level"), 0);
+ optname = rb_funcall(argv[0], rb_intern("optname"), 0);
+ val = rb_funcall(argv[0], rb_intern("data"), 0);
+ }
+ else {
+ rb_scan_args(argc, argv, "30", &lev, &optname, &val);
+ }
+
+ GetOpenFile(sock, fptr);
+ family = rsock_getfamily(fptr);
+ level = rsock_level_arg(family, lev);
+ option = rsock_optname_arg(family, level, optname);
+
+ switch (TYPE(val)) {
+ case T_FIXNUM:
+ i = FIX2INT(val);
+ goto numval;
+ case T_FALSE:
+ i = 0;
+ goto numval;
+ case T_TRUE:
+ i = 1;
+ numval:
+ v = (char*)&i; vlen = (int)sizeof(i);
+ break;
+ default:
+ StringValue(val);
+ v = RSTRING_PTR(val);
+ vlen = RSTRING_SOCKLEN(val);
+ break;
+ }
+
+ rb_io_check_closed(fptr);
+ if (setsockopt(fptr->fd, level, option, v, vlen) < 0)
+ rsock_sys_fail_path("setsockopt(2)", fptr->pathv);
+
+ return INT2FIX(0);
+}
+
+/*
+ * Document-method: getsockopt
+ * call-seq:
+ * getsockopt(level, optname) => socketoption
+ *
+ * Gets a socket option. These are protocol and system specific, see your
+ * local system documentation for details. The option is returned as
+ * a Socket::Option object.
+ *
+ * === Parameters
+ * * +level+ is an integer, usually one of the SOL_ constants such as
+ * Socket::SOL_SOCKET, or a protocol level.
+ * A string or symbol of the name, possibly without prefix, is also
+ * accepted.
+ * * +optname+ is an integer, usually one of the SO_ constants, such
+ * as Socket::SO_REUSEADDR.
+ * A string or symbol of the name, possibly without prefix, is also
+ * accepted.
+ *
+ * === Examples
+ *
+ * Some socket options are integers with boolean values, in this case
+ * #getsockopt could be called like this:
+ *
+ * reuseaddr = sock.getsockopt(:SOCKET, :REUSEADDR).bool
+ *
+ * optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR)
+ * optval = optval.unpack "i"
+ * reuseaddr = optval[0] == 0 ? false : true
+ *
+ * Some socket options are integers with numeric values, in this case
+ * #getsockopt could be called like this:
+ *
+ * ipttl = sock.getsockopt(:IP, :TTL).int
+ *
+ * optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
+ * ipttl = optval.unpack1("i")
+ *
+ * Option values may be structs. Decoding them can be complex as it involves
+ * examining your system headers to determine the correct definition. An
+ * example is a +struct linger+, which may be defined in your system headers
+ * as:
+ * struct linger {
+ * int l_onoff;
+ * int l_linger;
+ * };
+ *
+ * In this case #getsockopt could be called like this:
+ *
+ * # Socket::Option knows linger structure.
+ * onoff, linger = sock.getsockopt(:SOCKET, :LINGER).linger
+ *
+ * optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER)
+ * onoff, linger = optval.unpack "ii"
+ * onoff = onoff == 0 ? false : true
+*/
+static VALUE
+bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname)
+{
+ int level, option;
+ socklen_t len;
+ char *buf;
+ rb_io_t *fptr;
+ int family;
+
+ GetOpenFile(sock, fptr);
+ family = rsock_getfamily(fptr);
+ level = rsock_level_arg(family, lev);
+ option = rsock_optname_arg(family, level, optname);
+ len = 256;
+#ifdef _AIX
+ switch (option) {
+ case SO_DEBUG:
+ case SO_REUSEADDR:
+ case SO_KEEPALIVE:
+ case SO_DONTROUTE:
+ case SO_BROADCAST:
+ case SO_OOBINLINE:
+ /* AIX doesn't set len for boolean options */
+ len = sizeof(int);
+ }
+#endif
+ buf = ALLOCA_N(char,len);
+
+ rb_io_check_closed(fptr);
+
+ if (getsockopt(fptr->fd, level, option, buf, &len) < 0)
+ rsock_sys_fail_path("getsockopt(2)", fptr->pathv);
+
+ return rsock_sockopt_new(family, level, option, rb_str_new(buf, len));
+}
+
+/*
+ * call-seq:
+ * basicsocket.getsockname => sockaddr
+ *
+ * Returns the local address of the socket as a sockaddr string.
+ *
+ * TCPServer.open("127.0.0.1", 15120) {|serv|
+ * p serv.getsockname #=> "\x02\x00;\x10\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
+ * }
+ *
+ * If Addrinfo object is preferred over the binary string,
+ * use BasicSocket#local_address.
+ */
+static VALUE
+bsock_getsockname(VALUE sock)
+{
+ union_sockaddr buf;
+ socklen_t len = (socklen_t)sizeof buf;
+ socklen_t len0 = len;
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (getsockname(fptr->fd, &buf.addr, &len) < 0)
+ rb_sys_fail("getsockname(2)");
+ if (len0 < len) len = len0;
+ return rb_str_new((char*)&buf, len);
+}
+
+/*
+ * call-seq:
+ * basicsocket.getpeername => sockaddr
+ *
+ * Returns the remote address of the socket as a sockaddr string.
+ *
+ * TCPServer.open("127.0.0.1", 1440) {|serv|
+ * c = TCPSocket.new("127.0.0.1", 1440)
+ * s = serv.accept
+ * p s.getpeername #=> "\x02\x00\x82u\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
+ * }
+ *
+ * If Addrinfo object is preferred over the binary string,
+ * use BasicSocket#remote_address.
+ *
+ */
+static VALUE
+bsock_getpeername(VALUE sock)
+{
+ union_sockaddr buf;
+ socklen_t len = (socklen_t)sizeof buf;
+ socklen_t len0 = len;
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (getpeername(fptr->fd, &buf.addr, &len) < 0)
+ rb_sys_fail("getpeername(2)");
+ if (len0 < len) len = len0;
+ return rb_str_new((char*)&buf, len);
+}
+
+#if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED)
+/*
+ * call-seq:
+ * basicsocket.getpeereid => [euid, egid]
+ *
+ * Returns the user and group on the peer of the UNIX socket.
+ * The result is a two element array which contains the effective uid and the effective gid.
+ *
+ * Socket.unix_server_loop("/tmp/sock") {|s|
+ * begin
+ * euid, egid = s.getpeereid
+ *
+ * # Check the connected client is myself or not.
+ * next if euid != Process.uid
+ *
+ * # do something about my resource.
+ *
+ * ensure
+ * s.close
+ * end
+ * }
+ *
+ */
+static VALUE
+bsock_getpeereid(VALUE self)
+{
+#if defined(HAVE_GETPEEREID)
+ rb_io_t *fptr;
+ uid_t euid;
+ gid_t egid;
+ GetOpenFile(self, fptr);
+ if (getpeereid(fptr->fd, &euid, &egid) == -1)
+ rb_sys_fail("getpeereid(3)");
+ return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid));
+#elif defined(SO_PEERCRED) /* GNU/Linux */
+ rb_io_t *fptr;
+ struct ucred cred;
+ socklen_t len = sizeof(cred);
+ GetOpenFile(self, fptr);
+ if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
+ rb_sys_fail("getsockopt(SO_PEERCRED)");
+ return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid));
+#elif defined(HAVE_GETPEERUCRED) /* Solaris */
+ rb_io_t *fptr;
+ ucred_t *uc = NULL;
+ VALUE ret;
+ GetOpenFile(self, fptr);
+ if (getpeerucred(fptr->fd, &uc) == -1)
+ rb_sys_fail("getpeerucred(3C)");
+ ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc)));
+ ucred_free(uc);
+ return ret;
+#endif
+}
+#else
+#define bsock_getpeereid rb_f_notimplement
+#endif
+
+/*
+ * call-seq:
+ * bsock.local_address => addrinfo
+ *
+ * Returns an Addrinfo object for local address obtained by getsockname.
+ *
+ * Note that addrinfo.protocol is filled by 0.
+ *
+ * TCPSocket.open("www.ruby-lang.org", 80) {|s|
+ * p s.local_address #=> #<Addrinfo: 192.168.0.129:36873 TCP>
+ * }
+ *
+ * TCPServer.open("127.0.0.1", 1512) {|serv|
+ * p serv.local_address #=> #<Addrinfo: 127.0.0.1:1512 TCP>
+ * }
+ *
+ */
+static VALUE
+bsock_local_address(VALUE sock)
+{
+ union_sockaddr buf;
+ socklen_t len = (socklen_t)sizeof buf;
+ socklen_t len0 = len;
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (getsockname(fptr->fd, &buf.addr, &len) < 0)
+ rb_sys_fail("getsockname(2)");
+ if (len0 < len) len = len0;
+ return rsock_fd_socket_addrinfo(fptr->fd, &buf.addr, len);
+}
+
+/*
+ * call-seq:
+ * bsock.remote_address => addrinfo
+ *
+ * Returns an Addrinfo object for remote address obtained by getpeername.
+ *
+ * Note that addrinfo.protocol is filled by 0.
+ *
+ * TCPSocket.open("www.ruby-lang.org", 80) {|s|
+ * p s.remote_address #=> #<Addrinfo: 221.186.184.68:80 TCP>
+ * }
+ *
+ * TCPServer.open("127.0.0.1", 1728) {|serv|
+ * c = TCPSocket.new("127.0.0.1", 1728)
+ * s = serv.accept
+ * p s.remote_address #=> #<Addrinfo: 127.0.0.1:36504 TCP>
+ * }
+ *
+ */
+static VALUE
+bsock_remote_address(VALUE sock)
+{
+ union_sockaddr buf;
+ socklen_t len = (socklen_t)sizeof buf;
+ socklen_t len0 = len;
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (getpeername(fptr->fd, &buf.addr, &len) < 0)
+ rb_sys_fail("getpeername(2)");
+ if (len0 < len) len = len0;
+ return rsock_fd_socket_addrinfo(fptr->fd, &buf.addr, len);
+}
+
+/*
+ * call-seq:
+ * basicsocket.send(mesg, flags [, dest_sockaddr]) => numbytes_sent
+ *
+ * send _mesg_ via _basicsocket_.
+ *
+ * _mesg_ should be a string.
+ *
+ * _flags_ should be a bitwise OR of Socket::MSG_* constants.
+ *
+ * _dest_sockaddr_ should be a packed sockaddr string or an addrinfo.
+ *
+ * TCPSocket.open("localhost", 80) {|s|
+ * s.send "GET / HTTP/1.0\r\n\r\n", 0
+ * p s.read
+ * }
+ */
+VALUE
+rsock_bsock_send(int argc, VALUE *argv, VALUE socket)
+{
+ struct rsock_send_arg arg;
+ VALUE flags, to;
+ rb_io_t *fptr;
+ rb_blocking_function_t *func;
+ const char *funcname;
+
+ rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
+
+ StringValue(arg.mesg);
+ if (!NIL_P(to)) {
+ SockAddrStringValue(to);
+ to = rb_str_new4(to);
+ arg.to = (struct sockaddr *)RSTRING_PTR(to);
+ arg.tolen = RSTRING_SOCKLEN(to);
+ func = rsock_sendto_blocking;
+ funcname = "sendto(2)";
+ }
+ else {
+ func = rsock_send_blocking;
+ funcname = "send(2)";
+ }
+
+ RB_IO_POINTER(socket, fptr);
+
+ arg.fd = fptr->fd;
+ arg.flags = NUM2INT(flags);
+
+ while (true) {
+#ifdef RSOCK_WAIT_BEFORE_BLOCKING
+ rb_io_wait(socket, RB_INT2NUM(RUBY_IO_WRITABLE), Qnil);
+#endif
+
+ ssize_t n = (ssize_t)rb_io_blocking_region(fptr, func, &arg);
+
+ if (n >= 0) return SSIZET2NUM(n);
+
+ if (rb_io_maybe_wait_writable(errno, socket, RUBY_IO_TIMEOUT_DEFAULT)) {
+ continue;
+ }
+
+ rb_sys_fail(funcname);
+ }
+}
+
+/*
+ * call-seq:
+ * basicsocket.do_not_reverse_lookup => true or false
+ *
+ * Gets the do_not_reverse_lookup flag of _basicsocket_.
+ *
+ * require 'socket'
+ *
+ * BasicSocket.do_not_reverse_lookup = false
+ * TCPSocket.open("www.ruby-lang.org", 80) {|sock|
+ * p sock.do_not_reverse_lookup #=> false
+ * }
+ * BasicSocket.do_not_reverse_lookup = true
+ * TCPSocket.open("www.ruby-lang.org", 80) {|sock|
+ * p sock.do_not_reverse_lookup #=> true
+ * }
+ */
+static VALUE
+bsock_do_not_reverse_lookup(VALUE sock)
+{
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * basicsocket.do_not_reverse_lookup = bool
+ *
+ * Sets the do_not_reverse_lookup flag of _basicsocket_.
+ *
+ * TCPSocket.open("www.ruby-lang.org", 80) {|sock|
+ * p sock.do_not_reverse_lookup #=> true
+ * p sock.peeraddr #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
+ * sock.do_not_reverse_lookup = false
+ * p sock.peeraddr #=> ["AF_INET", 80, "carbon.ruby-lang.org", "54.163.249.195"]
+ * }
+ *
+ */
+static VALUE
+bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state)
+{
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (RTEST(state)) {
+ fptr->mode |= FMODE_NOREVLOOKUP;
+ }
+ else {
+ fptr->mode &= ~FMODE_NOREVLOOKUP;
+ }
+ return sock;
+}
+
+/*
+ * call-seq:
+ * basicsocket.recv(maxlen[, flags[, outbuf]]) => mesg
+ *
+ * Receives a message.
+ *
+ * _maxlen_ is the maximum number of bytes to receive.
+ *
+ * _flags_ should be a bitwise OR of Socket::MSG_* constants.
+ *
+ * _outbuf_ will contain only the received data after the method call
+ * even if it is not empty at the beginning.
+ *
+ * UNIXSocket.pair {|s1, s2|
+ * s1.puts "Hello World"
+ * p s2.recv(4) #=> "Hell"
+ * p s2.recv(4, Socket::MSG_PEEK) #=> "o Wo"
+ * p s2.recv(4) #=> "o Wo"
+ * p s2.recv(10) #=> "rld\n"
+ * }
+ */
+static VALUE
+bsock_recv(int argc, VALUE *argv, VALUE sock)
+{
+ return rsock_s_recvfrom(sock, argc, argv, RECV_RECV);
+}
+
+/* :nodoc: */
+static VALUE
+bsock_recv_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, VALUE ex)
+{
+ return rsock_s_recvfrom_nonblock(sock, len, flg, str, ex, RECV_RECV);
+}
+
+/*
+ * call-seq:
+ * BasicSocket.do_not_reverse_lookup => true or false
+ *
+ * Gets the global do_not_reverse_lookup flag.
+ *
+ * BasicSocket.do_not_reverse_lookup #=> false
+ */
+static VALUE
+bsock_do_not_rev_lookup(VALUE _)
+{
+ return rsock_do_not_reverse_lookup?Qtrue:Qfalse;
+}
+
+/*
+ * call-seq:
+ * BasicSocket.do_not_reverse_lookup = bool
+ *
+ * Sets the global do_not_reverse_lookup flag.
+ *
+ * The flag is used for initial value of do_not_reverse_lookup for each socket.
+ *
+ * s1 = TCPSocket.new("localhost", 80)
+ * p s1.do_not_reverse_lookup #=> true
+ * BasicSocket.do_not_reverse_lookup = false
+ * s2 = TCPSocket.new("localhost", 80)
+ * p s2.do_not_reverse_lookup #=> false
+ * p s1.do_not_reverse_lookup #=> true
+ *
+ */
+static VALUE
+bsock_do_not_rev_lookup_set(VALUE self, VALUE val)
+{
+ rsock_do_not_reverse_lookup = RTEST(val);
+ return val;
+}
+
+void
+rsock_init_basicsocket(void)
+{
+ /*
+ * Document-class: BasicSocket < IO
+ *
+ * BasicSocket is the super class for all the Socket classes.
+ */
+ rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
+ rb_undef_method(rb_cBasicSocket, "initialize");
+
+ rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
+ bsock_do_not_rev_lookup, 0);
+ rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
+ bsock_do_not_rev_lookup_set, 1);
+ rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1);
+
+ rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
+ rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
+ rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
+ rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, -1);
+ rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2);
+ rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0);
+ rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
+ rb_define_method(rb_cBasicSocket, "getpeereid", bsock_getpeereid, 0);
+ rb_define_method(rb_cBasicSocket, "local_address", bsock_local_address, 0);
+ rb_define_method(rb_cBasicSocket, "remote_address", bsock_remote_address, 0);
+ rb_define_method(rb_cBasicSocket, "send", rsock_bsock_send, -1);
+ rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
+
+ rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup", bsock_do_not_reverse_lookup, 0);
+ rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup=", bsock_do_not_reverse_lookup_set, 1);
+
+ /* for ext/socket/lib/socket.rb use only: */
+ rb_define_private_method(rb_cBasicSocket,
+ "__recv_nonblock", bsock_recv_nonblock, 4);
+
+#if MSG_DONTWAIT_RELIABLE
+ rb_define_private_method(rb_cBasicSocket,
+ "__read_nonblock", rsock_read_nonblock, 3);
+ rb_define_private_method(rb_cBasicSocket,
+ "__write_nonblock", rsock_write_nonblock, 2);
+#endif
+
+ /* in ancdata.c */
+ rb_define_private_method(rb_cBasicSocket, "__sendmsg",
+ rsock_bsock_sendmsg, 4);
+ rb_define_private_method(rb_cBasicSocket, "__sendmsg_nonblock",
+ rsock_bsock_sendmsg_nonblock, 5);
+ rb_define_private_method(rb_cBasicSocket, "__recvmsg",
+ rsock_bsock_recvmsg, 4);
+ rb_define_private_method(rb_cBasicSocket, "__recvmsg_nonblock",
+ rsock_bsock_recvmsg_nonblock, 5);
+
+}
diff --git a/ext/socket/constants.c b/ext/socket/constants.c
new file mode 100644
index 0000000000..1213f2ae17
--- /dev/null
+++ b/ext/socket/constants.c
@@ -0,0 +1,144 @@
+/************************************************
+
+ constants.c -
+
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
+
+************************************************/
+
+#include "rubysocket.h"
+
+static VALUE rb_mSockConst;
+
+#include "constdefs.c"
+
+static int
+constant_arg(VALUE arg, int (*str_to_int)(const char*, long, int*), const char *errmsg)
+{
+ VALUE tmp;
+ char *ptr;
+ int ret;
+
+ if (SYMBOL_P(arg)) {
+ arg = rb_sym2str(arg);
+ goto str;
+ }
+ else if (!NIL_P(tmp = rb_check_string_type(arg))) {
+ arg = tmp;
+ str:
+ ptr = RSTRING_PTR(arg);
+ if (str_to_int(ptr, RSTRING_LEN(arg), &ret) == -1)
+ rb_raise(rb_eSocket, "%s: %s", errmsg, ptr);
+ }
+ else {
+ ret = NUM2INT(arg);
+ }
+ return ret;
+}
+
+int
+rsock_family_arg(VALUE domain)
+{
+ /* convert AF_INET, etc. */
+ return constant_arg(domain, rsock_family_to_int, "unknown socket domain");
+}
+
+int
+rsock_socktype_arg(VALUE type)
+{
+ /* convert SOCK_STREAM, etc. */
+ return constant_arg(type, rsock_socktype_to_int, "unknown socket type");
+}
+
+int
+rsock_level_arg(int family, VALUE level)
+{
+ /* convert SOL_SOCKET, IPPROTO_TCP, etc. */
+ if (IS_IP_FAMILY(family)) {
+ return constant_arg(level, rsock_ip_level_to_int, "unknown protocol level");
+ }
+ else {
+ return constant_arg(level, rsock_unknown_level_to_int, "unknown protocol level");
+ }
+}
+
+int
+rsock_optname_arg(int family, int level, VALUE optname)
+{
+ if (IS_IP_FAMILY(family)) {
+ switch (level) {
+ case SOL_SOCKET:
+ return constant_arg(optname, rsock_so_optname_to_int, "unknown socket level option name");
+ case IPPROTO_IP:
+ return constant_arg(optname, rsock_ip_optname_to_int, "unknown IP level option name");
+#ifdef IPPROTO_IPV6
+ case IPPROTO_IPV6:
+ return constant_arg(optname, rsock_ipv6_optname_to_int, "unknown IPv6 level option name");
+#endif
+ case IPPROTO_TCP:
+ return constant_arg(optname, rsock_tcp_optname_to_int, "unknown TCP level option name");
+ case IPPROTO_UDP:
+ return constant_arg(optname, rsock_udp_optname_to_int, "unknown UDP level option name");
+ default:
+ return NUM2INT(optname);
+ }
+ }
+ else {
+ switch (level) {
+ case SOL_SOCKET:
+ return constant_arg(optname, rsock_so_optname_to_int, "unknown socket level option name");
+ default:
+ return NUM2INT(optname);
+ }
+ }
+}
+
+int
+rsock_cmsg_type_arg(int family, int level, VALUE type)
+{
+ if (IS_IP_FAMILY(family)) {
+ switch (level) {
+ case SOL_SOCKET:
+ return constant_arg(type, rsock_scm_optname_to_int, "unknown UNIX control message");
+ case IPPROTO_IP:
+ return constant_arg(type, rsock_ip_optname_to_int, "unknown IP control message");
+#ifdef IPPROTO_IPV6
+ case IPPROTO_IPV6:
+ return constant_arg(type, rsock_ipv6_optname_to_int, "unknown IPv6 control message");
+#endif
+ case IPPROTO_TCP:
+ return constant_arg(type, rsock_tcp_optname_to_int, "unknown TCP control message");
+ case IPPROTO_UDP:
+ return constant_arg(type, rsock_udp_optname_to_int, "unknown UDP control message");
+ default:
+ return NUM2INT(type);
+ }
+ }
+ else {
+ switch (level) {
+ case SOL_SOCKET:
+ return constant_arg(type, rsock_scm_optname_to_int, "unknown UNIX control message");
+ default:
+ return NUM2INT(type);
+ }
+ }
+}
+
+int
+rsock_shutdown_how_arg(VALUE how)
+{
+ /* convert SHUT_RD, SHUT_WR, SHUT_RDWR. */
+ return constant_arg(how, rsock_shutdown_how_to_int, "unknown shutdown argument");
+}
+
+/*
+ * Socket::Constants module
+ */
+void
+rsock_init_socket_constants(void)
+{
+ /* constants */
+ init_constants();
+}
diff --git a/ext/socket/depend b/ext/socket/depend
index cca6d4e62a..77f6239a3d 100644
--- a/ext/socket/depend
+++ b/ext/socket/depend
@@ -1,3 +1,3254 @@
-socket.o : socket.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/rubyio.h $(hdrdir)/rubysig.h sockport.h
-getnameinfo.o: getnameinfo.c $(topdir)/config.h addrinfo.h sockport.h
-getaddrinfo.o: getaddrinfo.c $(topdir)/config.h addrinfo.h sockport.h
+srcs: constdefs.h constdefs.c
+
+getnameinfo.o: getnameinfo.c $(arch_hdrdir)/ruby/config.h addrinfo.h sockport.h rubysocket.h
+getaddrinfo.o: getaddrinfo.c $(arch_hdrdir)/ruby/config.h addrinfo.h sockport.h
+
+constdefs.h: $(srcdir)/mkconstants.rb
+ @echo "generating constant definitions"
+ @$(RUBY) $(srcdir)/mkconstants.rb -H constdefs.h -o constdefs.c
+
+constdefs.c: constdefs.h
+
+# AUTOGENERATED DEPENDENCIES START
+ancdata.o: $(RUBY_EXTCONF_H)
+ancdata.o: $(arch_hdrdir)/ruby/config.h
+ancdata.o: $(hdrdir)/ruby/assert.h
+ancdata.o: $(hdrdir)/ruby/atomic.h
+ancdata.o: $(hdrdir)/ruby/backward.h
+ancdata.o: $(hdrdir)/ruby/backward/2/assume.h
+ancdata.o: $(hdrdir)/ruby/backward/2/attributes.h
+ancdata.o: $(hdrdir)/ruby/backward/2/bool.h
+ancdata.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ancdata.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ancdata.o: $(hdrdir)/ruby/backward/2/limits.h
+ancdata.o: $(hdrdir)/ruby/backward/2/long_long.h
+ancdata.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ancdata.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ancdata.o: $(hdrdir)/ruby/defines.h
+ancdata.o: $(hdrdir)/ruby/encoding.h
+ancdata.o: $(hdrdir)/ruby/fiber/scheduler.h
+ancdata.o: $(hdrdir)/ruby/intern.h
+ancdata.o: $(hdrdir)/ruby/internal/abi.h
+ancdata.o: $(hdrdir)/ruby/internal/anyargs.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ancdata.o: $(hdrdir)/ruby/internal/assume.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/cold.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/const.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/error.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/format.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/pure.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/warning.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ancdata.o: $(hdrdir)/ruby/internal/cast.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_since.h
+ancdata.o: $(hdrdir)/ruby/internal/config.h
+ancdata.o: $(hdrdir)/ruby/internal/constant_p.h
+ancdata.o: $(hdrdir)/ruby/internal/core.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rarray.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rclass.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rdata.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rfile.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rhash.h
+ancdata.o: $(hdrdir)/ruby/internal/core/robject.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rstring.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ancdata.o: $(hdrdir)/ruby/internal/ctype.h
+ancdata.o: $(hdrdir)/ruby/internal/dllexport.h
+ancdata.o: $(hdrdir)/ruby/internal/dosish.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/re.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/string.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ancdata.o: $(hdrdir)/ruby/internal/error.h
+ancdata.o: $(hdrdir)/ruby/internal/eval.h
+ancdata.o: $(hdrdir)/ruby/internal/event.h
+ancdata.o: $(hdrdir)/ruby/internal/fl_type.h
+ancdata.o: $(hdrdir)/ruby/internal/gc.h
+ancdata.o: $(hdrdir)/ruby/internal/glob.h
+ancdata.o: $(hdrdir)/ruby/internal/globals.h
+ancdata.o: $(hdrdir)/ruby/internal/has/attribute.h
+ancdata.o: $(hdrdir)/ruby/internal/has/builtin.h
+ancdata.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ancdata.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ancdata.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ancdata.o: $(hdrdir)/ruby/internal/has/extension.h
+ancdata.o: $(hdrdir)/ruby/internal/has/feature.h
+ancdata.o: $(hdrdir)/ruby/internal/has/warning.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/array.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/class.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/compar.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/complex.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/cont.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/dir.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/enum.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/error.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/eval.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/file.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/hash.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/io.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/load.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/object.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/parse.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/proc.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/process.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/random.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/range.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/rational.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/re.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/select.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/set.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/signal.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/string.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/struct.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/thread.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/time.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/variable.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/vm.h
+ancdata.o: $(hdrdir)/ruby/internal/interpreter.h
+ancdata.o: $(hdrdir)/ruby/internal/iterator.h
+ancdata.o: $(hdrdir)/ruby/internal/memory.h
+ancdata.o: $(hdrdir)/ruby/internal/method.h
+ancdata.o: $(hdrdir)/ruby/internal/module.h
+ancdata.o: $(hdrdir)/ruby/internal/newobj.h
+ancdata.o: $(hdrdir)/ruby/internal/scan_args.h
+ancdata.o: $(hdrdir)/ruby/internal/special_consts.h
+ancdata.o: $(hdrdir)/ruby/internal/static_assert.h
+ancdata.o: $(hdrdir)/ruby/internal/stdalign.h
+ancdata.o: $(hdrdir)/ruby/internal/stdbool.h
+ancdata.o: $(hdrdir)/ruby/internal/stdckdint.h
+ancdata.o: $(hdrdir)/ruby/internal/symbol.h
+ancdata.o: $(hdrdir)/ruby/internal/value.h
+ancdata.o: $(hdrdir)/ruby/internal/value_type.h
+ancdata.o: $(hdrdir)/ruby/internal/variable.h
+ancdata.o: $(hdrdir)/ruby/internal/warning_push.h
+ancdata.o: $(hdrdir)/ruby/internal/xmalloc.h
+ancdata.o: $(hdrdir)/ruby/io.h
+ancdata.o: $(hdrdir)/ruby/missing.h
+ancdata.o: $(hdrdir)/ruby/onigmo.h
+ancdata.o: $(hdrdir)/ruby/oniguruma.h
+ancdata.o: $(hdrdir)/ruby/ruby.h
+ancdata.o: $(hdrdir)/ruby/st.h
+ancdata.o: $(hdrdir)/ruby/subst.h
+ancdata.o: $(hdrdir)/ruby/thread.h
+ancdata.o: $(hdrdir)/ruby/thread_native.h
+ancdata.o: $(hdrdir)/ruby/util.h
+ancdata.o: $(hdrdir)/ruby/version.h
+ancdata.o: $(top_srcdir)/ccan/check_type/check_type.h
+ancdata.o: $(top_srcdir)/ccan/container_of/container_of.h
+ancdata.o: $(top_srcdir)/ccan/list/list.h
+ancdata.o: $(top_srcdir)/ccan/str/str.h
+ancdata.o: $(top_srcdir)/encindex.h
+ancdata.o: $(top_srcdir)/id_table.h
+ancdata.o: $(top_srcdir)/internal.h
+ancdata.o: $(top_srcdir)/internal/array.h
+ancdata.o: $(top_srcdir)/internal/basic_operators.h
+ancdata.o: $(top_srcdir)/internal/box.h
+ancdata.o: $(top_srcdir)/internal/compilers.h
+ancdata.o: $(top_srcdir)/internal/error.h
+ancdata.o: $(top_srcdir)/internal/gc.h
+ancdata.o: $(top_srcdir)/internal/imemo.h
+ancdata.o: $(top_srcdir)/internal/io.h
+ancdata.o: $(top_srcdir)/internal/sanitizers.h
+ancdata.o: $(top_srcdir)/internal/serial.h
+ancdata.o: $(top_srcdir)/internal/set_table.h
+ancdata.o: $(top_srcdir)/internal/static_assert.h
+ancdata.o: $(top_srcdir)/internal/string.h
+ancdata.o: $(top_srcdir)/internal/thread.h
+ancdata.o: $(top_srcdir)/internal/vm.h
+ancdata.o: $(top_srcdir)/internal/warnings.h
+ancdata.o: $(top_srcdir)/method.h
+ancdata.o: $(top_srcdir)/node.h
+ancdata.o: $(top_srcdir)/ruby_assert.h
+ancdata.o: $(top_srcdir)/ruby_atomic.h
+ancdata.o: $(top_srcdir)/rubyparser.h
+ancdata.o: $(top_srcdir)/shape.h
+ancdata.o: $(top_srcdir)/thread_pthread.h
+ancdata.o: $(top_srcdir)/vm_core.h
+ancdata.o: $(top_srcdir)/vm_opts.h
+ancdata.o: ancdata.c
+ancdata.o: constdefs.h
+ancdata.o: rubysocket.h
+ancdata.o: sockport.h
+ancdata.o: {$(VPATH)}id.h
+basicsocket.o: $(RUBY_EXTCONF_H)
+basicsocket.o: $(arch_hdrdir)/ruby/config.h
+basicsocket.o: $(hdrdir)/ruby/assert.h
+basicsocket.o: $(hdrdir)/ruby/atomic.h
+basicsocket.o: $(hdrdir)/ruby/backward.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/assume.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/attributes.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/bool.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/limits.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/long_long.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h
+basicsocket.o: $(hdrdir)/ruby/defines.h
+basicsocket.o: $(hdrdir)/ruby/encoding.h
+basicsocket.o: $(hdrdir)/ruby/fiber/scheduler.h
+basicsocket.o: $(hdrdir)/ruby/intern.h
+basicsocket.o: $(hdrdir)/ruby/internal/abi.h
+basicsocket.o: $(hdrdir)/ruby/internal/anyargs.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/assume.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/cold.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/const.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/error.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/format.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/pure.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/warning.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+basicsocket.o: $(hdrdir)/ruby/internal/cast.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_since.h
+basicsocket.o: $(hdrdir)/ruby/internal/config.h
+basicsocket.o: $(hdrdir)/ruby/internal/constant_p.h
+basicsocket.o: $(hdrdir)/ruby/internal/core.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rarray.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rclass.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rdata.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rfile.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rhash.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/robject.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rstring.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+basicsocket.o: $(hdrdir)/ruby/internal/ctype.h
+basicsocket.o: $(hdrdir)/ruby/internal/dllexport.h
+basicsocket.o: $(hdrdir)/ruby/internal/dosish.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/re.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/string.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+basicsocket.o: $(hdrdir)/ruby/internal/error.h
+basicsocket.o: $(hdrdir)/ruby/internal/eval.h
+basicsocket.o: $(hdrdir)/ruby/internal/event.h
+basicsocket.o: $(hdrdir)/ruby/internal/fl_type.h
+basicsocket.o: $(hdrdir)/ruby/internal/gc.h
+basicsocket.o: $(hdrdir)/ruby/internal/glob.h
+basicsocket.o: $(hdrdir)/ruby/internal/globals.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/attribute.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/builtin.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/extension.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/feature.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/warning.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/array.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/class.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/compar.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/complex.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/cont.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/dir.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/enum.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/error.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/eval.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/file.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/hash.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/io.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/load.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/object.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/parse.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/proc.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/process.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/random.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/range.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/rational.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/re.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/select.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/set.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/signal.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/string.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/struct.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/thread.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/time.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/variable.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/vm.h
+basicsocket.o: $(hdrdir)/ruby/internal/interpreter.h
+basicsocket.o: $(hdrdir)/ruby/internal/iterator.h
+basicsocket.o: $(hdrdir)/ruby/internal/memory.h
+basicsocket.o: $(hdrdir)/ruby/internal/method.h
+basicsocket.o: $(hdrdir)/ruby/internal/module.h
+basicsocket.o: $(hdrdir)/ruby/internal/newobj.h
+basicsocket.o: $(hdrdir)/ruby/internal/scan_args.h
+basicsocket.o: $(hdrdir)/ruby/internal/special_consts.h
+basicsocket.o: $(hdrdir)/ruby/internal/static_assert.h
+basicsocket.o: $(hdrdir)/ruby/internal/stdalign.h
+basicsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+basicsocket.o: $(hdrdir)/ruby/internal/stdckdint.h
+basicsocket.o: $(hdrdir)/ruby/internal/symbol.h
+basicsocket.o: $(hdrdir)/ruby/internal/value.h
+basicsocket.o: $(hdrdir)/ruby/internal/value_type.h
+basicsocket.o: $(hdrdir)/ruby/internal/variable.h
+basicsocket.o: $(hdrdir)/ruby/internal/warning_push.h
+basicsocket.o: $(hdrdir)/ruby/internal/xmalloc.h
+basicsocket.o: $(hdrdir)/ruby/io.h
+basicsocket.o: $(hdrdir)/ruby/missing.h
+basicsocket.o: $(hdrdir)/ruby/onigmo.h
+basicsocket.o: $(hdrdir)/ruby/oniguruma.h
+basicsocket.o: $(hdrdir)/ruby/ruby.h
+basicsocket.o: $(hdrdir)/ruby/st.h
+basicsocket.o: $(hdrdir)/ruby/subst.h
+basicsocket.o: $(hdrdir)/ruby/thread.h
+basicsocket.o: $(hdrdir)/ruby/thread_native.h
+basicsocket.o: $(hdrdir)/ruby/util.h
+basicsocket.o: $(hdrdir)/ruby/version.h
+basicsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
+basicsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
+basicsocket.o: $(top_srcdir)/ccan/list/list.h
+basicsocket.o: $(top_srcdir)/ccan/str/str.h
+basicsocket.o: $(top_srcdir)/encindex.h
+basicsocket.o: $(top_srcdir)/id_table.h
+basicsocket.o: $(top_srcdir)/internal.h
+basicsocket.o: $(top_srcdir)/internal/array.h
+basicsocket.o: $(top_srcdir)/internal/basic_operators.h
+basicsocket.o: $(top_srcdir)/internal/box.h
+basicsocket.o: $(top_srcdir)/internal/compilers.h
+basicsocket.o: $(top_srcdir)/internal/error.h
+basicsocket.o: $(top_srcdir)/internal/gc.h
+basicsocket.o: $(top_srcdir)/internal/imemo.h
+basicsocket.o: $(top_srcdir)/internal/io.h
+basicsocket.o: $(top_srcdir)/internal/sanitizers.h
+basicsocket.o: $(top_srcdir)/internal/serial.h
+basicsocket.o: $(top_srcdir)/internal/set_table.h
+basicsocket.o: $(top_srcdir)/internal/static_assert.h
+basicsocket.o: $(top_srcdir)/internal/string.h
+basicsocket.o: $(top_srcdir)/internal/thread.h
+basicsocket.o: $(top_srcdir)/internal/vm.h
+basicsocket.o: $(top_srcdir)/internal/warnings.h
+basicsocket.o: $(top_srcdir)/method.h
+basicsocket.o: $(top_srcdir)/node.h
+basicsocket.o: $(top_srcdir)/ruby_assert.h
+basicsocket.o: $(top_srcdir)/ruby_atomic.h
+basicsocket.o: $(top_srcdir)/rubyparser.h
+basicsocket.o: $(top_srcdir)/shape.h
+basicsocket.o: $(top_srcdir)/thread_pthread.h
+basicsocket.o: $(top_srcdir)/vm_core.h
+basicsocket.o: $(top_srcdir)/vm_opts.h
+basicsocket.o: basicsocket.c
+basicsocket.o: constdefs.h
+basicsocket.o: rubysocket.h
+basicsocket.o: sockport.h
+basicsocket.o: {$(VPATH)}id.h
+constants.o: $(RUBY_EXTCONF_H)
+constants.o: $(arch_hdrdir)/ruby/config.h
+constants.o: $(hdrdir)/ruby/assert.h
+constants.o: $(hdrdir)/ruby/atomic.h
+constants.o: $(hdrdir)/ruby/backward.h
+constants.o: $(hdrdir)/ruby/backward/2/assume.h
+constants.o: $(hdrdir)/ruby/backward/2/attributes.h
+constants.o: $(hdrdir)/ruby/backward/2/bool.h
+constants.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+constants.o: $(hdrdir)/ruby/backward/2/inttypes.h
+constants.o: $(hdrdir)/ruby/backward/2/limits.h
+constants.o: $(hdrdir)/ruby/backward/2/long_long.h
+constants.o: $(hdrdir)/ruby/backward/2/stdalign.h
+constants.o: $(hdrdir)/ruby/backward/2/stdarg.h
+constants.o: $(hdrdir)/ruby/defines.h
+constants.o: $(hdrdir)/ruby/encoding.h
+constants.o: $(hdrdir)/ruby/fiber/scheduler.h
+constants.o: $(hdrdir)/ruby/intern.h
+constants.o: $(hdrdir)/ruby/internal/abi.h
+constants.o: $(hdrdir)/ruby/internal/anyargs.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+constants.o: $(hdrdir)/ruby/internal/assume.h
+constants.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+constants.o: $(hdrdir)/ruby/internal/attr/artificial.h
+constants.o: $(hdrdir)/ruby/internal/attr/cold.h
+constants.o: $(hdrdir)/ruby/internal/attr/const.h
+constants.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+constants.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+constants.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+constants.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+constants.o: $(hdrdir)/ruby/internal/attr/error.h
+constants.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+constants.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+constants.o: $(hdrdir)/ruby/internal/attr/format.h
+constants.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+constants.o: $(hdrdir)/ruby/internal/attr/noalias.h
+constants.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+constants.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+constants.o: $(hdrdir)/ruby/internal/attr/noinline.h
+constants.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+constants.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+constants.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+constants.o: $(hdrdir)/ruby/internal/attr/pure.h
+constants.o: $(hdrdir)/ruby/internal/attr/restrict.h
+constants.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+constants.o: $(hdrdir)/ruby/internal/attr/warning.h
+constants.o: $(hdrdir)/ruby/internal/attr/weakref.h
+constants.o: $(hdrdir)/ruby/internal/cast.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+constants.o: $(hdrdir)/ruby/internal/compiler_since.h
+constants.o: $(hdrdir)/ruby/internal/config.h
+constants.o: $(hdrdir)/ruby/internal/constant_p.h
+constants.o: $(hdrdir)/ruby/internal/core.h
+constants.o: $(hdrdir)/ruby/internal/core/rarray.h
+constants.o: $(hdrdir)/ruby/internal/core/rbasic.h
+constants.o: $(hdrdir)/ruby/internal/core/rbignum.h
+constants.o: $(hdrdir)/ruby/internal/core/rclass.h
+constants.o: $(hdrdir)/ruby/internal/core/rdata.h
+constants.o: $(hdrdir)/ruby/internal/core/rfile.h
+constants.o: $(hdrdir)/ruby/internal/core/rhash.h
+constants.o: $(hdrdir)/ruby/internal/core/robject.h
+constants.o: $(hdrdir)/ruby/internal/core/rregexp.h
+constants.o: $(hdrdir)/ruby/internal/core/rstring.h
+constants.o: $(hdrdir)/ruby/internal/core/rstruct.h
+constants.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+constants.o: $(hdrdir)/ruby/internal/ctype.h
+constants.o: $(hdrdir)/ruby/internal/dllexport.h
+constants.o: $(hdrdir)/ruby/internal/dosish.h
+constants.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+constants.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+constants.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+constants.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+constants.o: $(hdrdir)/ruby/internal/encoding/re.h
+constants.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+constants.o: $(hdrdir)/ruby/internal/encoding/string.h
+constants.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+constants.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+constants.o: $(hdrdir)/ruby/internal/error.h
+constants.o: $(hdrdir)/ruby/internal/eval.h
+constants.o: $(hdrdir)/ruby/internal/event.h
+constants.o: $(hdrdir)/ruby/internal/fl_type.h
+constants.o: $(hdrdir)/ruby/internal/gc.h
+constants.o: $(hdrdir)/ruby/internal/glob.h
+constants.o: $(hdrdir)/ruby/internal/globals.h
+constants.o: $(hdrdir)/ruby/internal/has/attribute.h
+constants.o: $(hdrdir)/ruby/internal/has/builtin.h
+constants.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+constants.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+constants.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+constants.o: $(hdrdir)/ruby/internal/has/extension.h
+constants.o: $(hdrdir)/ruby/internal/has/feature.h
+constants.o: $(hdrdir)/ruby/internal/has/warning.h
+constants.o: $(hdrdir)/ruby/internal/intern/array.h
+constants.o: $(hdrdir)/ruby/internal/intern/bignum.h
+constants.o: $(hdrdir)/ruby/internal/intern/class.h
+constants.o: $(hdrdir)/ruby/internal/intern/compar.h
+constants.o: $(hdrdir)/ruby/internal/intern/complex.h
+constants.o: $(hdrdir)/ruby/internal/intern/cont.h
+constants.o: $(hdrdir)/ruby/internal/intern/dir.h
+constants.o: $(hdrdir)/ruby/internal/intern/enum.h
+constants.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+constants.o: $(hdrdir)/ruby/internal/intern/error.h
+constants.o: $(hdrdir)/ruby/internal/intern/eval.h
+constants.o: $(hdrdir)/ruby/internal/intern/file.h
+constants.o: $(hdrdir)/ruby/internal/intern/hash.h
+constants.o: $(hdrdir)/ruby/internal/intern/io.h
+constants.o: $(hdrdir)/ruby/internal/intern/load.h
+constants.o: $(hdrdir)/ruby/internal/intern/marshal.h
+constants.o: $(hdrdir)/ruby/internal/intern/numeric.h
+constants.o: $(hdrdir)/ruby/internal/intern/object.h
+constants.o: $(hdrdir)/ruby/internal/intern/parse.h
+constants.o: $(hdrdir)/ruby/internal/intern/proc.h
+constants.o: $(hdrdir)/ruby/internal/intern/process.h
+constants.o: $(hdrdir)/ruby/internal/intern/random.h
+constants.o: $(hdrdir)/ruby/internal/intern/range.h
+constants.o: $(hdrdir)/ruby/internal/intern/rational.h
+constants.o: $(hdrdir)/ruby/internal/intern/re.h
+constants.o: $(hdrdir)/ruby/internal/intern/ruby.h
+constants.o: $(hdrdir)/ruby/internal/intern/select.h
+constants.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+constants.o: $(hdrdir)/ruby/internal/intern/set.h
+constants.o: $(hdrdir)/ruby/internal/intern/signal.h
+constants.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+constants.o: $(hdrdir)/ruby/internal/intern/string.h
+constants.o: $(hdrdir)/ruby/internal/intern/struct.h
+constants.o: $(hdrdir)/ruby/internal/intern/thread.h
+constants.o: $(hdrdir)/ruby/internal/intern/time.h
+constants.o: $(hdrdir)/ruby/internal/intern/variable.h
+constants.o: $(hdrdir)/ruby/internal/intern/vm.h
+constants.o: $(hdrdir)/ruby/internal/interpreter.h
+constants.o: $(hdrdir)/ruby/internal/iterator.h
+constants.o: $(hdrdir)/ruby/internal/memory.h
+constants.o: $(hdrdir)/ruby/internal/method.h
+constants.o: $(hdrdir)/ruby/internal/module.h
+constants.o: $(hdrdir)/ruby/internal/newobj.h
+constants.o: $(hdrdir)/ruby/internal/scan_args.h
+constants.o: $(hdrdir)/ruby/internal/special_consts.h
+constants.o: $(hdrdir)/ruby/internal/static_assert.h
+constants.o: $(hdrdir)/ruby/internal/stdalign.h
+constants.o: $(hdrdir)/ruby/internal/stdbool.h
+constants.o: $(hdrdir)/ruby/internal/stdckdint.h
+constants.o: $(hdrdir)/ruby/internal/symbol.h
+constants.o: $(hdrdir)/ruby/internal/value.h
+constants.o: $(hdrdir)/ruby/internal/value_type.h
+constants.o: $(hdrdir)/ruby/internal/variable.h
+constants.o: $(hdrdir)/ruby/internal/warning_push.h
+constants.o: $(hdrdir)/ruby/internal/xmalloc.h
+constants.o: $(hdrdir)/ruby/io.h
+constants.o: $(hdrdir)/ruby/missing.h
+constants.o: $(hdrdir)/ruby/onigmo.h
+constants.o: $(hdrdir)/ruby/oniguruma.h
+constants.o: $(hdrdir)/ruby/ruby.h
+constants.o: $(hdrdir)/ruby/st.h
+constants.o: $(hdrdir)/ruby/subst.h
+constants.o: $(hdrdir)/ruby/thread.h
+constants.o: $(hdrdir)/ruby/thread_native.h
+constants.o: $(hdrdir)/ruby/util.h
+constants.o: $(hdrdir)/ruby/version.h
+constants.o: $(top_srcdir)/ccan/check_type/check_type.h
+constants.o: $(top_srcdir)/ccan/container_of/container_of.h
+constants.o: $(top_srcdir)/ccan/list/list.h
+constants.o: $(top_srcdir)/ccan/str/str.h
+constants.o: $(top_srcdir)/encindex.h
+constants.o: $(top_srcdir)/id_table.h
+constants.o: $(top_srcdir)/internal.h
+constants.o: $(top_srcdir)/internal/array.h
+constants.o: $(top_srcdir)/internal/basic_operators.h
+constants.o: $(top_srcdir)/internal/box.h
+constants.o: $(top_srcdir)/internal/compilers.h
+constants.o: $(top_srcdir)/internal/error.h
+constants.o: $(top_srcdir)/internal/gc.h
+constants.o: $(top_srcdir)/internal/imemo.h
+constants.o: $(top_srcdir)/internal/io.h
+constants.o: $(top_srcdir)/internal/sanitizers.h
+constants.o: $(top_srcdir)/internal/serial.h
+constants.o: $(top_srcdir)/internal/set_table.h
+constants.o: $(top_srcdir)/internal/static_assert.h
+constants.o: $(top_srcdir)/internal/string.h
+constants.o: $(top_srcdir)/internal/thread.h
+constants.o: $(top_srcdir)/internal/vm.h
+constants.o: $(top_srcdir)/internal/warnings.h
+constants.o: $(top_srcdir)/method.h
+constants.o: $(top_srcdir)/node.h
+constants.o: $(top_srcdir)/ruby_assert.h
+constants.o: $(top_srcdir)/ruby_atomic.h
+constants.o: $(top_srcdir)/rubyparser.h
+constants.o: $(top_srcdir)/shape.h
+constants.o: $(top_srcdir)/thread_pthread.h
+constants.o: $(top_srcdir)/vm_core.h
+constants.o: $(top_srcdir)/vm_opts.h
+constants.o: constants.c
+constants.o: constdefs.c
+constants.o: constdefs.h
+constants.o: rubysocket.h
+constants.o: sockport.h
+constants.o: {$(VPATH)}id.h
+ifaddr.o: $(RUBY_EXTCONF_H)
+ifaddr.o: $(arch_hdrdir)/ruby/config.h
+ifaddr.o: $(hdrdir)/ruby/assert.h
+ifaddr.o: $(hdrdir)/ruby/atomic.h
+ifaddr.o: $(hdrdir)/ruby/backward.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/assume.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/attributes.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/bool.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/limits.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/long_long.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ifaddr.o: $(hdrdir)/ruby/defines.h
+ifaddr.o: $(hdrdir)/ruby/encoding.h
+ifaddr.o: $(hdrdir)/ruby/fiber/scheduler.h
+ifaddr.o: $(hdrdir)/ruby/intern.h
+ifaddr.o: $(hdrdir)/ruby/internal/abi.h
+ifaddr.o: $(hdrdir)/ruby/internal/anyargs.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/assume.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/cold.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/const.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/error.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/format.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/pure.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/warning.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ifaddr.o: $(hdrdir)/ruby/internal/cast.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_since.h
+ifaddr.o: $(hdrdir)/ruby/internal/config.h
+ifaddr.o: $(hdrdir)/ruby/internal/constant_p.h
+ifaddr.o: $(hdrdir)/ruby/internal/core.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rarray.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rclass.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rdata.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rfile.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rhash.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/robject.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rstring.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ifaddr.o: $(hdrdir)/ruby/internal/ctype.h
+ifaddr.o: $(hdrdir)/ruby/internal/dllexport.h
+ifaddr.o: $(hdrdir)/ruby/internal/dosish.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/re.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/string.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ifaddr.o: $(hdrdir)/ruby/internal/error.h
+ifaddr.o: $(hdrdir)/ruby/internal/eval.h
+ifaddr.o: $(hdrdir)/ruby/internal/event.h
+ifaddr.o: $(hdrdir)/ruby/internal/fl_type.h
+ifaddr.o: $(hdrdir)/ruby/internal/gc.h
+ifaddr.o: $(hdrdir)/ruby/internal/glob.h
+ifaddr.o: $(hdrdir)/ruby/internal/globals.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/attribute.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/builtin.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/extension.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/feature.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/warning.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/array.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/class.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/compar.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/complex.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/cont.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/dir.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/enum.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/error.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/eval.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/file.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/hash.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/io.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/load.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/object.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/parse.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/proc.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/process.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/random.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/range.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/rational.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/re.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/select.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/set.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/signal.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/string.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/struct.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/thread.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/time.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/variable.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/vm.h
+ifaddr.o: $(hdrdir)/ruby/internal/interpreter.h
+ifaddr.o: $(hdrdir)/ruby/internal/iterator.h
+ifaddr.o: $(hdrdir)/ruby/internal/memory.h
+ifaddr.o: $(hdrdir)/ruby/internal/method.h
+ifaddr.o: $(hdrdir)/ruby/internal/module.h
+ifaddr.o: $(hdrdir)/ruby/internal/newobj.h
+ifaddr.o: $(hdrdir)/ruby/internal/scan_args.h
+ifaddr.o: $(hdrdir)/ruby/internal/special_consts.h
+ifaddr.o: $(hdrdir)/ruby/internal/static_assert.h
+ifaddr.o: $(hdrdir)/ruby/internal/stdalign.h
+ifaddr.o: $(hdrdir)/ruby/internal/stdbool.h
+ifaddr.o: $(hdrdir)/ruby/internal/stdckdint.h
+ifaddr.o: $(hdrdir)/ruby/internal/symbol.h
+ifaddr.o: $(hdrdir)/ruby/internal/value.h
+ifaddr.o: $(hdrdir)/ruby/internal/value_type.h
+ifaddr.o: $(hdrdir)/ruby/internal/variable.h
+ifaddr.o: $(hdrdir)/ruby/internal/warning_push.h
+ifaddr.o: $(hdrdir)/ruby/internal/xmalloc.h
+ifaddr.o: $(hdrdir)/ruby/io.h
+ifaddr.o: $(hdrdir)/ruby/missing.h
+ifaddr.o: $(hdrdir)/ruby/onigmo.h
+ifaddr.o: $(hdrdir)/ruby/oniguruma.h
+ifaddr.o: $(hdrdir)/ruby/ruby.h
+ifaddr.o: $(hdrdir)/ruby/st.h
+ifaddr.o: $(hdrdir)/ruby/subst.h
+ifaddr.o: $(hdrdir)/ruby/thread.h
+ifaddr.o: $(hdrdir)/ruby/thread_native.h
+ifaddr.o: $(hdrdir)/ruby/util.h
+ifaddr.o: $(hdrdir)/ruby/version.h
+ifaddr.o: $(top_srcdir)/ccan/check_type/check_type.h
+ifaddr.o: $(top_srcdir)/ccan/container_of/container_of.h
+ifaddr.o: $(top_srcdir)/ccan/list/list.h
+ifaddr.o: $(top_srcdir)/ccan/str/str.h
+ifaddr.o: $(top_srcdir)/encindex.h
+ifaddr.o: $(top_srcdir)/id_table.h
+ifaddr.o: $(top_srcdir)/internal.h
+ifaddr.o: $(top_srcdir)/internal/array.h
+ifaddr.o: $(top_srcdir)/internal/basic_operators.h
+ifaddr.o: $(top_srcdir)/internal/box.h
+ifaddr.o: $(top_srcdir)/internal/compilers.h
+ifaddr.o: $(top_srcdir)/internal/error.h
+ifaddr.o: $(top_srcdir)/internal/gc.h
+ifaddr.o: $(top_srcdir)/internal/imemo.h
+ifaddr.o: $(top_srcdir)/internal/io.h
+ifaddr.o: $(top_srcdir)/internal/sanitizers.h
+ifaddr.o: $(top_srcdir)/internal/serial.h
+ifaddr.o: $(top_srcdir)/internal/set_table.h
+ifaddr.o: $(top_srcdir)/internal/static_assert.h
+ifaddr.o: $(top_srcdir)/internal/string.h
+ifaddr.o: $(top_srcdir)/internal/thread.h
+ifaddr.o: $(top_srcdir)/internal/vm.h
+ifaddr.o: $(top_srcdir)/internal/warnings.h
+ifaddr.o: $(top_srcdir)/method.h
+ifaddr.o: $(top_srcdir)/node.h
+ifaddr.o: $(top_srcdir)/ruby_assert.h
+ifaddr.o: $(top_srcdir)/ruby_atomic.h
+ifaddr.o: $(top_srcdir)/rubyparser.h
+ifaddr.o: $(top_srcdir)/shape.h
+ifaddr.o: $(top_srcdir)/thread_pthread.h
+ifaddr.o: $(top_srcdir)/vm_core.h
+ifaddr.o: $(top_srcdir)/vm_opts.h
+ifaddr.o: constdefs.h
+ifaddr.o: ifaddr.c
+ifaddr.o: rubysocket.h
+ifaddr.o: sockport.h
+ifaddr.o: {$(VPATH)}id.h
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/atomic.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/encoding.h
+init.o: $(hdrdir)/ruby/fiber/scheduler.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+init.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+init.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+init.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+init.o: $(hdrdir)/ruby/internal/encoding/re.h
+init.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+init.o: $(hdrdir)/ruby/internal/encoding/string.h
+init.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+init.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/io.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/onigmo.h
+init.o: $(hdrdir)/ruby/oniguruma.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: $(hdrdir)/ruby/thread.h
+init.o: $(hdrdir)/ruby/thread_native.h
+init.o: $(hdrdir)/ruby/util.h
+init.o: $(hdrdir)/ruby/version.h
+init.o: $(top_srcdir)/ccan/check_type/check_type.h
+init.o: $(top_srcdir)/ccan/container_of/container_of.h
+init.o: $(top_srcdir)/ccan/list/list.h
+init.o: $(top_srcdir)/ccan/str/str.h
+init.o: $(top_srcdir)/encindex.h
+init.o: $(top_srcdir)/id_table.h
+init.o: $(top_srcdir)/internal.h
+init.o: $(top_srcdir)/internal/array.h
+init.o: $(top_srcdir)/internal/basic_operators.h
+init.o: $(top_srcdir)/internal/box.h
+init.o: $(top_srcdir)/internal/compilers.h
+init.o: $(top_srcdir)/internal/error.h
+init.o: $(top_srcdir)/internal/gc.h
+init.o: $(top_srcdir)/internal/imemo.h
+init.o: $(top_srcdir)/internal/io.h
+init.o: $(top_srcdir)/internal/sanitizers.h
+init.o: $(top_srcdir)/internal/serial.h
+init.o: $(top_srcdir)/internal/set_table.h
+init.o: $(top_srcdir)/internal/static_assert.h
+init.o: $(top_srcdir)/internal/string.h
+init.o: $(top_srcdir)/internal/thread.h
+init.o: $(top_srcdir)/internal/vm.h
+init.o: $(top_srcdir)/internal/warnings.h
+init.o: $(top_srcdir)/method.h
+init.o: $(top_srcdir)/node.h
+init.o: $(top_srcdir)/ruby_assert.h
+init.o: $(top_srcdir)/ruby_atomic.h
+init.o: $(top_srcdir)/rubyparser.h
+init.o: $(top_srcdir)/shape.h
+init.o: $(top_srcdir)/thread_pthread.h
+init.o: $(top_srcdir)/vm_core.h
+init.o: $(top_srcdir)/vm_opts.h
+init.o: constdefs.h
+init.o: init.c
+init.o: rubysocket.h
+init.o: sockport.h
+init.o: {$(VPATH)}id.h
+ipsocket.o: $(RUBY_EXTCONF_H)
+ipsocket.o: $(arch_hdrdir)/ruby/config.h
+ipsocket.o: $(hdrdir)/ruby/assert.h
+ipsocket.o: $(hdrdir)/ruby/atomic.h
+ipsocket.o: $(hdrdir)/ruby/backward.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/assume.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/attributes.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/bool.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/limits.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/long_long.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ipsocket.o: $(hdrdir)/ruby/defines.h
+ipsocket.o: $(hdrdir)/ruby/encoding.h
+ipsocket.o: $(hdrdir)/ruby/fiber/scheduler.h
+ipsocket.o: $(hdrdir)/ruby/intern.h
+ipsocket.o: $(hdrdir)/ruby/internal/abi.h
+ipsocket.o: $(hdrdir)/ruby/internal/anyargs.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/assume.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/cold.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/const.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/error.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/format.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/pure.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/warning.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ipsocket.o: $(hdrdir)/ruby/internal/cast.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_since.h
+ipsocket.o: $(hdrdir)/ruby/internal/config.h
+ipsocket.o: $(hdrdir)/ruby/internal/constant_p.h
+ipsocket.o: $(hdrdir)/ruby/internal/core.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rarray.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rclass.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rdata.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rfile.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rhash.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/robject.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rstring.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ipsocket.o: $(hdrdir)/ruby/internal/ctype.h
+ipsocket.o: $(hdrdir)/ruby/internal/dllexport.h
+ipsocket.o: $(hdrdir)/ruby/internal/dosish.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/re.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/string.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ipsocket.o: $(hdrdir)/ruby/internal/error.h
+ipsocket.o: $(hdrdir)/ruby/internal/eval.h
+ipsocket.o: $(hdrdir)/ruby/internal/event.h
+ipsocket.o: $(hdrdir)/ruby/internal/fl_type.h
+ipsocket.o: $(hdrdir)/ruby/internal/gc.h
+ipsocket.o: $(hdrdir)/ruby/internal/glob.h
+ipsocket.o: $(hdrdir)/ruby/internal/globals.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/attribute.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/builtin.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/extension.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/feature.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/warning.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/array.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/class.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/compar.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/complex.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/cont.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/dir.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/enum.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/error.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/eval.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/file.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/hash.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/io.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/load.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/object.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/parse.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/proc.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/process.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/random.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/range.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/rational.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/re.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/select.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/set.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/signal.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/string.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/struct.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/thread.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/time.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/variable.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/vm.h
+ipsocket.o: $(hdrdir)/ruby/internal/interpreter.h
+ipsocket.o: $(hdrdir)/ruby/internal/iterator.h
+ipsocket.o: $(hdrdir)/ruby/internal/memory.h
+ipsocket.o: $(hdrdir)/ruby/internal/method.h
+ipsocket.o: $(hdrdir)/ruby/internal/module.h
+ipsocket.o: $(hdrdir)/ruby/internal/newobj.h
+ipsocket.o: $(hdrdir)/ruby/internal/scan_args.h
+ipsocket.o: $(hdrdir)/ruby/internal/special_consts.h
+ipsocket.o: $(hdrdir)/ruby/internal/static_assert.h
+ipsocket.o: $(hdrdir)/ruby/internal/stdalign.h
+ipsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+ipsocket.o: $(hdrdir)/ruby/internal/stdckdint.h
+ipsocket.o: $(hdrdir)/ruby/internal/symbol.h
+ipsocket.o: $(hdrdir)/ruby/internal/value.h
+ipsocket.o: $(hdrdir)/ruby/internal/value_type.h
+ipsocket.o: $(hdrdir)/ruby/internal/variable.h
+ipsocket.o: $(hdrdir)/ruby/internal/warning_push.h
+ipsocket.o: $(hdrdir)/ruby/internal/xmalloc.h
+ipsocket.o: $(hdrdir)/ruby/io.h
+ipsocket.o: $(hdrdir)/ruby/missing.h
+ipsocket.o: $(hdrdir)/ruby/onigmo.h
+ipsocket.o: $(hdrdir)/ruby/oniguruma.h
+ipsocket.o: $(hdrdir)/ruby/ruby.h
+ipsocket.o: $(hdrdir)/ruby/st.h
+ipsocket.o: $(hdrdir)/ruby/subst.h
+ipsocket.o: $(hdrdir)/ruby/thread.h
+ipsocket.o: $(hdrdir)/ruby/thread_native.h
+ipsocket.o: $(hdrdir)/ruby/util.h
+ipsocket.o: $(hdrdir)/ruby/version.h
+ipsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
+ipsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
+ipsocket.o: $(top_srcdir)/ccan/list/list.h
+ipsocket.o: $(top_srcdir)/ccan/str/str.h
+ipsocket.o: $(top_srcdir)/encindex.h
+ipsocket.o: $(top_srcdir)/id_table.h
+ipsocket.o: $(top_srcdir)/internal.h
+ipsocket.o: $(top_srcdir)/internal/array.h
+ipsocket.o: $(top_srcdir)/internal/basic_operators.h
+ipsocket.o: $(top_srcdir)/internal/box.h
+ipsocket.o: $(top_srcdir)/internal/compilers.h
+ipsocket.o: $(top_srcdir)/internal/error.h
+ipsocket.o: $(top_srcdir)/internal/gc.h
+ipsocket.o: $(top_srcdir)/internal/imemo.h
+ipsocket.o: $(top_srcdir)/internal/io.h
+ipsocket.o: $(top_srcdir)/internal/sanitizers.h
+ipsocket.o: $(top_srcdir)/internal/serial.h
+ipsocket.o: $(top_srcdir)/internal/set_table.h
+ipsocket.o: $(top_srcdir)/internal/static_assert.h
+ipsocket.o: $(top_srcdir)/internal/string.h
+ipsocket.o: $(top_srcdir)/internal/thread.h
+ipsocket.o: $(top_srcdir)/internal/vm.h
+ipsocket.o: $(top_srcdir)/internal/warnings.h
+ipsocket.o: $(top_srcdir)/method.h
+ipsocket.o: $(top_srcdir)/node.h
+ipsocket.o: $(top_srcdir)/ruby_assert.h
+ipsocket.o: $(top_srcdir)/ruby_atomic.h
+ipsocket.o: $(top_srcdir)/rubyparser.h
+ipsocket.o: $(top_srcdir)/shape.h
+ipsocket.o: $(top_srcdir)/thread_pthread.h
+ipsocket.o: $(top_srcdir)/vm_core.h
+ipsocket.o: $(top_srcdir)/vm_opts.h
+ipsocket.o: constdefs.h
+ipsocket.o: ipsocket.c
+ipsocket.o: rubysocket.h
+ipsocket.o: sockport.h
+ipsocket.o: {$(VPATH)}id.h
+option.o: $(RUBY_EXTCONF_H)
+option.o: $(arch_hdrdir)/ruby/config.h
+option.o: $(hdrdir)/ruby/assert.h
+option.o: $(hdrdir)/ruby/atomic.h
+option.o: $(hdrdir)/ruby/backward.h
+option.o: $(hdrdir)/ruby/backward/2/assume.h
+option.o: $(hdrdir)/ruby/backward/2/attributes.h
+option.o: $(hdrdir)/ruby/backward/2/bool.h
+option.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+option.o: $(hdrdir)/ruby/backward/2/inttypes.h
+option.o: $(hdrdir)/ruby/backward/2/limits.h
+option.o: $(hdrdir)/ruby/backward/2/long_long.h
+option.o: $(hdrdir)/ruby/backward/2/stdalign.h
+option.o: $(hdrdir)/ruby/backward/2/stdarg.h
+option.o: $(hdrdir)/ruby/defines.h
+option.o: $(hdrdir)/ruby/encoding.h
+option.o: $(hdrdir)/ruby/fiber/scheduler.h
+option.o: $(hdrdir)/ruby/intern.h
+option.o: $(hdrdir)/ruby/internal/abi.h
+option.o: $(hdrdir)/ruby/internal/anyargs.h
+option.o: $(hdrdir)/ruby/internal/arithmetic.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+option.o: $(hdrdir)/ruby/internal/assume.h
+option.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+option.o: $(hdrdir)/ruby/internal/attr/artificial.h
+option.o: $(hdrdir)/ruby/internal/attr/cold.h
+option.o: $(hdrdir)/ruby/internal/attr/const.h
+option.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+option.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+option.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+option.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+option.o: $(hdrdir)/ruby/internal/attr/error.h
+option.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+option.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+option.o: $(hdrdir)/ruby/internal/attr/format.h
+option.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+option.o: $(hdrdir)/ruby/internal/attr/noalias.h
+option.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+option.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+option.o: $(hdrdir)/ruby/internal/attr/noinline.h
+option.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+option.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+option.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+option.o: $(hdrdir)/ruby/internal/attr/pure.h
+option.o: $(hdrdir)/ruby/internal/attr/restrict.h
+option.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+option.o: $(hdrdir)/ruby/internal/attr/warning.h
+option.o: $(hdrdir)/ruby/internal/attr/weakref.h
+option.o: $(hdrdir)/ruby/internal/cast.h
+option.o: $(hdrdir)/ruby/internal/compiler_is.h
+option.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+option.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+option.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+option.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+option.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+option.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+option.o: $(hdrdir)/ruby/internal/compiler_since.h
+option.o: $(hdrdir)/ruby/internal/config.h
+option.o: $(hdrdir)/ruby/internal/constant_p.h
+option.o: $(hdrdir)/ruby/internal/core.h
+option.o: $(hdrdir)/ruby/internal/core/rarray.h
+option.o: $(hdrdir)/ruby/internal/core/rbasic.h
+option.o: $(hdrdir)/ruby/internal/core/rbignum.h
+option.o: $(hdrdir)/ruby/internal/core/rclass.h
+option.o: $(hdrdir)/ruby/internal/core/rdata.h
+option.o: $(hdrdir)/ruby/internal/core/rfile.h
+option.o: $(hdrdir)/ruby/internal/core/rhash.h
+option.o: $(hdrdir)/ruby/internal/core/robject.h
+option.o: $(hdrdir)/ruby/internal/core/rregexp.h
+option.o: $(hdrdir)/ruby/internal/core/rstring.h
+option.o: $(hdrdir)/ruby/internal/core/rstruct.h
+option.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+option.o: $(hdrdir)/ruby/internal/ctype.h
+option.o: $(hdrdir)/ruby/internal/dllexport.h
+option.o: $(hdrdir)/ruby/internal/dosish.h
+option.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+option.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+option.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+option.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+option.o: $(hdrdir)/ruby/internal/encoding/re.h
+option.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+option.o: $(hdrdir)/ruby/internal/encoding/string.h
+option.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+option.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+option.o: $(hdrdir)/ruby/internal/error.h
+option.o: $(hdrdir)/ruby/internal/eval.h
+option.o: $(hdrdir)/ruby/internal/event.h
+option.o: $(hdrdir)/ruby/internal/fl_type.h
+option.o: $(hdrdir)/ruby/internal/gc.h
+option.o: $(hdrdir)/ruby/internal/glob.h
+option.o: $(hdrdir)/ruby/internal/globals.h
+option.o: $(hdrdir)/ruby/internal/has/attribute.h
+option.o: $(hdrdir)/ruby/internal/has/builtin.h
+option.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+option.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+option.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+option.o: $(hdrdir)/ruby/internal/has/extension.h
+option.o: $(hdrdir)/ruby/internal/has/feature.h
+option.o: $(hdrdir)/ruby/internal/has/warning.h
+option.o: $(hdrdir)/ruby/internal/intern/array.h
+option.o: $(hdrdir)/ruby/internal/intern/bignum.h
+option.o: $(hdrdir)/ruby/internal/intern/class.h
+option.o: $(hdrdir)/ruby/internal/intern/compar.h
+option.o: $(hdrdir)/ruby/internal/intern/complex.h
+option.o: $(hdrdir)/ruby/internal/intern/cont.h
+option.o: $(hdrdir)/ruby/internal/intern/dir.h
+option.o: $(hdrdir)/ruby/internal/intern/enum.h
+option.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+option.o: $(hdrdir)/ruby/internal/intern/error.h
+option.o: $(hdrdir)/ruby/internal/intern/eval.h
+option.o: $(hdrdir)/ruby/internal/intern/file.h
+option.o: $(hdrdir)/ruby/internal/intern/hash.h
+option.o: $(hdrdir)/ruby/internal/intern/io.h
+option.o: $(hdrdir)/ruby/internal/intern/load.h
+option.o: $(hdrdir)/ruby/internal/intern/marshal.h
+option.o: $(hdrdir)/ruby/internal/intern/numeric.h
+option.o: $(hdrdir)/ruby/internal/intern/object.h
+option.o: $(hdrdir)/ruby/internal/intern/parse.h
+option.o: $(hdrdir)/ruby/internal/intern/proc.h
+option.o: $(hdrdir)/ruby/internal/intern/process.h
+option.o: $(hdrdir)/ruby/internal/intern/random.h
+option.o: $(hdrdir)/ruby/internal/intern/range.h
+option.o: $(hdrdir)/ruby/internal/intern/rational.h
+option.o: $(hdrdir)/ruby/internal/intern/re.h
+option.o: $(hdrdir)/ruby/internal/intern/ruby.h
+option.o: $(hdrdir)/ruby/internal/intern/select.h
+option.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+option.o: $(hdrdir)/ruby/internal/intern/set.h
+option.o: $(hdrdir)/ruby/internal/intern/signal.h
+option.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+option.o: $(hdrdir)/ruby/internal/intern/string.h
+option.o: $(hdrdir)/ruby/internal/intern/struct.h
+option.o: $(hdrdir)/ruby/internal/intern/thread.h
+option.o: $(hdrdir)/ruby/internal/intern/time.h
+option.o: $(hdrdir)/ruby/internal/intern/variable.h
+option.o: $(hdrdir)/ruby/internal/intern/vm.h
+option.o: $(hdrdir)/ruby/internal/interpreter.h
+option.o: $(hdrdir)/ruby/internal/iterator.h
+option.o: $(hdrdir)/ruby/internal/memory.h
+option.o: $(hdrdir)/ruby/internal/method.h
+option.o: $(hdrdir)/ruby/internal/module.h
+option.o: $(hdrdir)/ruby/internal/newobj.h
+option.o: $(hdrdir)/ruby/internal/scan_args.h
+option.o: $(hdrdir)/ruby/internal/special_consts.h
+option.o: $(hdrdir)/ruby/internal/static_assert.h
+option.o: $(hdrdir)/ruby/internal/stdalign.h
+option.o: $(hdrdir)/ruby/internal/stdbool.h
+option.o: $(hdrdir)/ruby/internal/stdckdint.h
+option.o: $(hdrdir)/ruby/internal/symbol.h
+option.o: $(hdrdir)/ruby/internal/value.h
+option.o: $(hdrdir)/ruby/internal/value_type.h
+option.o: $(hdrdir)/ruby/internal/variable.h
+option.o: $(hdrdir)/ruby/internal/warning_push.h
+option.o: $(hdrdir)/ruby/internal/xmalloc.h
+option.o: $(hdrdir)/ruby/io.h
+option.o: $(hdrdir)/ruby/missing.h
+option.o: $(hdrdir)/ruby/onigmo.h
+option.o: $(hdrdir)/ruby/oniguruma.h
+option.o: $(hdrdir)/ruby/ruby.h
+option.o: $(hdrdir)/ruby/st.h
+option.o: $(hdrdir)/ruby/subst.h
+option.o: $(hdrdir)/ruby/thread.h
+option.o: $(hdrdir)/ruby/thread_native.h
+option.o: $(hdrdir)/ruby/util.h
+option.o: $(hdrdir)/ruby/version.h
+option.o: $(top_srcdir)/ccan/check_type/check_type.h
+option.o: $(top_srcdir)/ccan/container_of/container_of.h
+option.o: $(top_srcdir)/ccan/list/list.h
+option.o: $(top_srcdir)/ccan/str/str.h
+option.o: $(top_srcdir)/encindex.h
+option.o: $(top_srcdir)/id_table.h
+option.o: $(top_srcdir)/internal.h
+option.o: $(top_srcdir)/internal/array.h
+option.o: $(top_srcdir)/internal/basic_operators.h
+option.o: $(top_srcdir)/internal/box.h
+option.o: $(top_srcdir)/internal/compilers.h
+option.o: $(top_srcdir)/internal/error.h
+option.o: $(top_srcdir)/internal/gc.h
+option.o: $(top_srcdir)/internal/imemo.h
+option.o: $(top_srcdir)/internal/io.h
+option.o: $(top_srcdir)/internal/sanitizers.h
+option.o: $(top_srcdir)/internal/serial.h
+option.o: $(top_srcdir)/internal/set_table.h
+option.o: $(top_srcdir)/internal/static_assert.h
+option.o: $(top_srcdir)/internal/string.h
+option.o: $(top_srcdir)/internal/thread.h
+option.o: $(top_srcdir)/internal/vm.h
+option.o: $(top_srcdir)/internal/warnings.h
+option.o: $(top_srcdir)/method.h
+option.o: $(top_srcdir)/node.h
+option.o: $(top_srcdir)/ruby_assert.h
+option.o: $(top_srcdir)/ruby_atomic.h
+option.o: $(top_srcdir)/rubyparser.h
+option.o: $(top_srcdir)/shape.h
+option.o: $(top_srcdir)/thread_pthread.h
+option.o: $(top_srcdir)/vm_core.h
+option.o: $(top_srcdir)/vm_opts.h
+option.o: constdefs.h
+option.o: option.c
+option.o: rubysocket.h
+option.o: sockport.h
+option.o: {$(VPATH)}id.h
+raddrinfo.o: $(RUBY_EXTCONF_H)
+raddrinfo.o: $(arch_hdrdir)/ruby/config.h
+raddrinfo.o: $(hdrdir)/ruby/assert.h
+raddrinfo.o: $(hdrdir)/ruby/atomic.h
+raddrinfo.o: $(hdrdir)/ruby/backward.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/assume.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/attributes.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/bool.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/inttypes.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/limits.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/long_long.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/stdalign.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/stdarg.h
+raddrinfo.o: $(hdrdir)/ruby/defines.h
+raddrinfo.o: $(hdrdir)/ruby/encoding.h
+raddrinfo.o: $(hdrdir)/ruby/fiber/scheduler.h
+raddrinfo.o: $(hdrdir)/ruby/intern.h
+raddrinfo.o: $(hdrdir)/ruby/internal/abi.h
+raddrinfo.o: $(hdrdir)/ruby/internal/anyargs.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/assume.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/artificial.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/cold.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/const.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/error.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/format.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/noalias.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/noinline.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/pure.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/restrict.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/warning.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/weakref.h
+raddrinfo.o: $(hdrdir)/ruby/internal/cast.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_since.h
+raddrinfo.o: $(hdrdir)/ruby/internal/config.h
+raddrinfo.o: $(hdrdir)/ruby/internal/constant_p.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rarray.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rbasic.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rbignum.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rclass.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rdata.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rfile.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rhash.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/robject.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rregexp.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rstring.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rstruct.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+raddrinfo.o: $(hdrdir)/ruby/internal/ctype.h
+raddrinfo.o: $(hdrdir)/ruby/internal/dllexport.h
+raddrinfo.o: $(hdrdir)/ruby/internal/dosish.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/re.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/string.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+raddrinfo.o: $(hdrdir)/ruby/internal/error.h
+raddrinfo.o: $(hdrdir)/ruby/internal/eval.h
+raddrinfo.o: $(hdrdir)/ruby/internal/event.h
+raddrinfo.o: $(hdrdir)/ruby/internal/fl_type.h
+raddrinfo.o: $(hdrdir)/ruby/internal/gc.h
+raddrinfo.o: $(hdrdir)/ruby/internal/glob.h
+raddrinfo.o: $(hdrdir)/ruby/internal/globals.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/attribute.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/builtin.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/extension.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/feature.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/warning.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/array.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/bignum.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/class.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/compar.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/complex.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/cont.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/dir.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/enum.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/error.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/eval.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/file.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/hash.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/io.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/load.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/marshal.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/numeric.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/object.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/parse.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/proc.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/process.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/random.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/range.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/rational.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/re.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/ruby.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/select.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/set.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/signal.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/string.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/struct.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/thread.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/time.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/variable.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/vm.h
+raddrinfo.o: $(hdrdir)/ruby/internal/interpreter.h
+raddrinfo.o: $(hdrdir)/ruby/internal/iterator.h
+raddrinfo.o: $(hdrdir)/ruby/internal/memory.h
+raddrinfo.o: $(hdrdir)/ruby/internal/method.h
+raddrinfo.o: $(hdrdir)/ruby/internal/module.h
+raddrinfo.o: $(hdrdir)/ruby/internal/newobj.h
+raddrinfo.o: $(hdrdir)/ruby/internal/scan_args.h
+raddrinfo.o: $(hdrdir)/ruby/internal/special_consts.h
+raddrinfo.o: $(hdrdir)/ruby/internal/static_assert.h
+raddrinfo.o: $(hdrdir)/ruby/internal/stdalign.h
+raddrinfo.o: $(hdrdir)/ruby/internal/stdbool.h
+raddrinfo.o: $(hdrdir)/ruby/internal/stdckdint.h
+raddrinfo.o: $(hdrdir)/ruby/internal/symbol.h
+raddrinfo.o: $(hdrdir)/ruby/internal/value.h
+raddrinfo.o: $(hdrdir)/ruby/internal/value_type.h
+raddrinfo.o: $(hdrdir)/ruby/internal/variable.h
+raddrinfo.o: $(hdrdir)/ruby/internal/warning_push.h
+raddrinfo.o: $(hdrdir)/ruby/internal/xmalloc.h
+raddrinfo.o: $(hdrdir)/ruby/io.h
+raddrinfo.o: $(hdrdir)/ruby/missing.h
+raddrinfo.o: $(hdrdir)/ruby/onigmo.h
+raddrinfo.o: $(hdrdir)/ruby/oniguruma.h
+raddrinfo.o: $(hdrdir)/ruby/ruby.h
+raddrinfo.o: $(hdrdir)/ruby/st.h
+raddrinfo.o: $(hdrdir)/ruby/subst.h
+raddrinfo.o: $(hdrdir)/ruby/thread.h
+raddrinfo.o: $(hdrdir)/ruby/thread_native.h
+raddrinfo.o: $(hdrdir)/ruby/util.h
+raddrinfo.o: $(hdrdir)/ruby/version.h
+raddrinfo.o: $(top_srcdir)/ccan/check_type/check_type.h
+raddrinfo.o: $(top_srcdir)/ccan/container_of/container_of.h
+raddrinfo.o: $(top_srcdir)/ccan/list/list.h
+raddrinfo.o: $(top_srcdir)/ccan/str/str.h
+raddrinfo.o: $(top_srcdir)/encindex.h
+raddrinfo.o: $(top_srcdir)/id_table.h
+raddrinfo.o: $(top_srcdir)/internal.h
+raddrinfo.o: $(top_srcdir)/internal/array.h
+raddrinfo.o: $(top_srcdir)/internal/basic_operators.h
+raddrinfo.o: $(top_srcdir)/internal/box.h
+raddrinfo.o: $(top_srcdir)/internal/compilers.h
+raddrinfo.o: $(top_srcdir)/internal/error.h
+raddrinfo.o: $(top_srcdir)/internal/gc.h
+raddrinfo.o: $(top_srcdir)/internal/imemo.h
+raddrinfo.o: $(top_srcdir)/internal/io.h
+raddrinfo.o: $(top_srcdir)/internal/sanitizers.h
+raddrinfo.o: $(top_srcdir)/internal/serial.h
+raddrinfo.o: $(top_srcdir)/internal/set_table.h
+raddrinfo.o: $(top_srcdir)/internal/static_assert.h
+raddrinfo.o: $(top_srcdir)/internal/string.h
+raddrinfo.o: $(top_srcdir)/internal/thread.h
+raddrinfo.o: $(top_srcdir)/internal/vm.h
+raddrinfo.o: $(top_srcdir)/internal/warnings.h
+raddrinfo.o: $(top_srcdir)/method.h
+raddrinfo.o: $(top_srcdir)/node.h
+raddrinfo.o: $(top_srcdir)/ruby_assert.h
+raddrinfo.o: $(top_srcdir)/ruby_atomic.h
+raddrinfo.o: $(top_srcdir)/rubyparser.h
+raddrinfo.o: $(top_srcdir)/shape.h
+raddrinfo.o: $(top_srcdir)/thread_pthread.h
+raddrinfo.o: $(top_srcdir)/vm_core.h
+raddrinfo.o: $(top_srcdir)/vm_opts.h
+raddrinfo.o: constdefs.h
+raddrinfo.o: raddrinfo.c
+raddrinfo.o: rubysocket.h
+raddrinfo.o: sockport.h
+raddrinfo.o: {$(VPATH)}id.h
+socket.o: $(RUBY_EXTCONF_H)
+socket.o: $(arch_hdrdir)/ruby/config.h
+socket.o: $(hdrdir)/ruby/assert.h
+socket.o: $(hdrdir)/ruby/atomic.h
+socket.o: $(hdrdir)/ruby/backward.h
+socket.o: $(hdrdir)/ruby/backward/2/assume.h
+socket.o: $(hdrdir)/ruby/backward/2/attributes.h
+socket.o: $(hdrdir)/ruby/backward/2/bool.h
+socket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+socket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+socket.o: $(hdrdir)/ruby/backward/2/limits.h
+socket.o: $(hdrdir)/ruby/backward/2/long_long.h
+socket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+socket.o: $(hdrdir)/ruby/backward/2/stdarg.h
+socket.o: $(hdrdir)/ruby/defines.h
+socket.o: $(hdrdir)/ruby/encoding.h
+socket.o: $(hdrdir)/ruby/fiber/scheduler.h
+socket.o: $(hdrdir)/ruby/intern.h
+socket.o: $(hdrdir)/ruby/internal/abi.h
+socket.o: $(hdrdir)/ruby/internal/anyargs.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+socket.o: $(hdrdir)/ruby/internal/assume.h
+socket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+socket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+socket.o: $(hdrdir)/ruby/internal/attr/cold.h
+socket.o: $(hdrdir)/ruby/internal/attr/const.h
+socket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+socket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+socket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+socket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+socket.o: $(hdrdir)/ruby/internal/attr/error.h
+socket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+socket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+socket.o: $(hdrdir)/ruby/internal/attr/format.h
+socket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+socket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+socket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+socket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+socket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+socket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+socket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+socket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+socket.o: $(hdrdir)/ruby/internal/attr/pure.h
+socket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+socket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+socket.o: $(hdrdir)/ruby/internal/attr/warning.h
+socket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+socket.o: $(hdrdir)/ruby/internal/cast.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+socket.o: $(hdrdir)/ruby/internal/compiler_since.h
+socket.o: $(hdrdir)/ruby/internal/config.h
+socket.o: $(hdrdir)/ruby/internal/constant_p.h
+socket.o: $(hdrdir)/ruby/internal/core.h
+socket.o: $(hdrdir)/ruby/internal/core/rarray.h
+socket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+socket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+socket.o: $(hdrdir)/ruby/internal/core/rclass.h
+socket.o: $(hdrdir)/ruby/internal/core/rdata.h
+socket.o: $(hdrdir)/ruby/internal/core/rfile.h
+socket.o: $(hdrdir)/ruby/internal/core/rhash.h
+socket.o: $(hdrdir)/ruby/internal/core/robject.h
+socket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+socket.o: $(hdrdir)/ruby/internal/core/rstring.h
+socket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+socket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+socket.o: $(hdrdir)/ruby/internal/ctype.h
+socket.o: $(hdrdir)/ruby/internal/dllexport.h
+socket.o: $(hdrdir)/ruby/internal/dosish.h
+socket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+socket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+socket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+socket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+socket.o: $(hdrdir)/ruby/internal/encoding/re.h
+socket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+socket.o: $(hdrdir)/ruby/internal/encoding/string.h
+socket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+socket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+socket.o: $(hdrdir)/ruby/internal/error.h
+socket.o: $(hdrdir)/ruby/internal/eval.h
+socket.o: $(hdrdir)/ruby/internal/event.h
+socket.o: $(hdrdir)/ruby/internal/fl_type.h
+socket.o: $(hdrdir)/ruby/internal/gc.h
+socket.o: $(hdrdir)/ruby/internal/glob.h
+socket.o: $(hdrdir)/ruby/internal/globals.h
+socket.o: $(hdrdir)/ruby/internal/has/attribute.h
+socket.o: $(hdrdir)/ruby/internal/has/builtin.h
+socket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+socket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+socket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+socket.o: $(hdrdir)/ruby/internal/has/extension.h
+socket.o: $(hdrdir)/ruby/internal/has/feature.h
+socket.o: $(hdrdir)/ruby/internal/has/warning.h
+socket.o: $(hdrdir)/ruby/internal/intern/array.h
+socket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+socket.o: $(hdrdir)/ruby/internal/intern/class.h
+socket.o: $(hdrdir)/ruby/internal/intern/compar.h
+socket.o: $(hdrdir)/ruby/internal/intern/complex.h
+socket.o: $(hdrdir)/ruby/internal/intern/cont.h
+socket.o: $(hdrdir)/ruby/internal/intern/dir.h
+socket.o: $(hdrdir)/ruby/internal/intern/enum.h
+socket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+socket.o: $(hdrdir)/ruby/internal/intern/error.h
+socket.o: $(hdrdir)/ruby/internal/intern/eval.h
+socket.o: $(hdrdir)/ruby/internal/intern/file.h
+socket.o: $(hdrdir)/ruby/internal/intern/hash.h
+socket.o: $(hdrdir)/ruby/internal/intern/io.h
+socket.o: $(hdrdir)/ruby/internal/intern/load.h
+socket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+socket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+socket.o: $(hdrdir)/ruby/internal/intern/object.h
+socket.o: $(hdrdir)/ruby/internal/intern/parse.h
+socket.o: $(hdrdir)/ruby/internal/intern/proc.h
+socket.o: $(hdrdir)/ruby/internal/intern/process.h
+socket.o: $(hdrdir)/ruby/internal/intern/random.h
+socket.o: $(hdrdir)/ruby/internal/intern/range.h
+socket.o: $(hdrdir)/ruby/internal/intern/rational.h
+socket.o: $(hdrdir)/ruby/internal/intern/re.h
+socket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+socket.o: $(hdrdir)/ruby/internal/intern/select.h
+socket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+socket.o: $(hdrdir)/ruby/internal/intern/set.h
+socket.o: $(hdrdir)/ruby/internal/intern/signal.h
+socket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+socket.o: $(hdrdir)/ruby/internal/intern/string.h
+socket.o: $(hdrdir)/ruby/internal/intern/struct.h
+socket.o: $(hdrdir)/ruby/internal/intern/thread.h
+socket.o: $(hdrdir)/ruby/internal/intern/time.h
+socket.o: $(hdrdir)/ruby/internal/intern/variable.h
+socket.o: $(hdrdir)/ruby/internal/intern/vm.h
+socket.o: $(hdrdir)/ruby/internal/interpreter.h
+socket.o: $(hdrdir)/ruby/internal/iterator.h
+socket.o: $(hdrdir)/ruby/internal/memory.h
+socket.o: $(hdrdir)/ruby/internal/method.h
+socket.o: $(hdrdir)/ruby/internal/module.h
+socket.o: $(hdrdir)/ruby/internal/newobj.h
+socket.o: $(hdrdir)/ruby/internal/scan_args.h
+socket.o: $(hdrdir)/ruby/internal/special_consts.h
+socket.o: $(hdrdir)/ruby/internal/static_assert.h
+socket.o: $(hdrdir)/ruby/internal/stdalign.h
+socket.o: $(hdrdir)/ruby/internal/stdbool.h
+socket.o: $(hdrdir)/ruby/internal/stdckdint.h
+socket.o: $(hdrdir)/ruby/internal/symbol.h
+socket.o: $(hdrdir)/ruby/internal/value.h
+socket.o: $(hdrdir)/ruby/internal/value_type.h
+socket.o: $(hdrdir)/ruby/internal/variable.h
+socket.o: $(hdrdir)/ruby/internal/warning_push.h
+socket.o: $(hdrdir)/ruby/internal/xmalloc.h
+socket.o: $(hdrdir)/ruby/io.h
+socket.o: $(hdrdir)/ruby/missing.h
+socket.o: $(hdrdir)/ruby/onigmo.h
+socket.o: $(hdrdir)/ruby/oniguruma.h
+socket.o: $(hdrdir)/ruby/ruby.h
+socket.o: $(hdrdir)/ruby/st.h
+socket.o: $(hdrdir)/ruby/subst.h
+socket.o: $(hdrdir)/ruby/thread.h
+socket.o: $(hdrdir)/ruby/thread_native.h
+socket.o: $(hdrdir)/ruby/util.h
+socket.o: $(hdrdir)/ruby/version.h
+socket.o: $(top_srcdir)/ccan/check_type/check_type.h
+socket.o: $(top_srcdir)/ccan/container_of/container_of.h
+socket.o: $(top_srcdir)/ccan/list/list.h
+socket.o: $(top_srcdir)/ccan/str/str.h
+socket.o: $(top_srcdir)/encindex.h
+socket.o: $(top_srcdir)/id_table.h
+socket.o: $(top_srcdir)/internal.h
+socket.o: $(top_srcdir)/internal/array.h
+socket.o: $(top_srcdir)/internal/basic_operators.h
+socket.o: $(top_srcdir)/internal/box.h
+socket.o: $(top_srcdir)/internal/compilers.h
+socket.o: $(top_srcdir)/internal/error.h
+socket.o: $(top_srcdir)/internal/gc.h
+socket.o: $(top_srcdir)/internal/imemo.h
+socket.o: $(top_srcdir)/internal/io.h
+socket.o: $(top_srcdir)/internal/sanitizers.h
+socket.o: $(top_srcdir)/internal/serial.h
+socket.o: $(top_srcdir)/internal/set_table.h
+socket.o: $(top_srcdir)/internal/static_assert.h
+socket.o: $(top_srcdir)/internal/string.h
+socket.o: $(top_srcdir)/internal/thread.h
+socket.o: $(top_srcdir)/internal/vm.h
+socket.o: $(top_srcdir)/internal/warnings.h
+socket.o: $(top_srcdir)/method.h
+socket.o: $(top_srcdir)/node.h
+socket.o: $(top_srcdir)/ruby_assert.h
+socket.o: $(top_srcdir)/ruby_atomic.h
+socket.o: $(top_srcdir)/rubyparser.h
+socket.o: $(top_srcdir)/shape.h
+socket.o: $(top_srcdir)/thread_pthread.h
+socket.o: $(top_srcdir)/vm_core.h
+socket.o: $(top_srcdir)/vm_opts.h
+socket.o: constdefs.h
+socket.o: rubysocket.h
+socket.o: socket.c
+socket.o: sockport.h
+socket.o: {$(VPATH)}id.h
+sockssocket.o: $(RUBY_EXTCONF_H)
+sockssocket.o: $(arch_hdrdir)/ruby/config.h
+sockssocket.o: $(hdrdir)/ruby/assert.h
+sockssocket.o: $(hdrdir)/ruby/atomic.h
+sockssocket.o: $(hdrdir)/ruby/backward.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/assume.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/attributes.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/bool.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/limits.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/long_long.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/stdarg.h
+sockssocket.o: $(hdrdir)/ruby/defines.h
+sockssocket.o: $(hdrdir)/ruby/encoding.h
+sockssocket.o: $(hdrdir)/ruby/fiber/scheduler.h
+sockssocket.o: $(hdrdir)/ruby/intern.h
+sockssocket.o: $(hdrdir)/ruby/internal/abi.h
+sockssocket.o: $(hdrdir)/ruby/internal/anyargs.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/assume.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/cold.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/const.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/error.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/format.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/pure.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/warning.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sockssocket.o: $(hdrdir)/ruby/internal/cast.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_since.h
+sockssocket.o: $(hdrdir)/ruby/internal/config.h
+sockssocket.o: $(hdrdir)/ruby/internal/constant_p.h
+sockssocket.o: $(hdrdir)/ruby/internal/core.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rarray.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rclass.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rdata.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rfile.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rhash.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/robject.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rstring.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sockssocket.o: $(hdrdir)/ruby/internal/ctype.h
+sockssocket.o: $(hdrdir)/ruby/internal/dllexport.h
+sockssocket.o: $(hdrdir)/ruby/internal/dosish.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/re.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/string.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+sockssocket.o: $(hdrdir)/ruby/internal/error.h
+sockssocket.o: $(hdrdir)/ruby/internal/eval.h
+sockssocket.o: $(hdrdir)/ruby/internal/event.h
+sockssocket.o: $(hdrdir)/ruby/internal/fl_type.h
+sockssocket.o: $(hdrdir)/ruby/internal/gc.h
+sockssocket.o: $(hdrdir)/ruby/internal/glob.h
+sockssocket.o: $(hdrdir)/ruby/internal/globals.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/attribute.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/builtin.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/extension.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/feature.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/warning.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/array.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/class.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/compar.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/complex.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/cont.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/dir.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/enum.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/error.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/eval.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/file.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/hash.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/io.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/load.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/object.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/parse.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/proc.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/process.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/random.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/range.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/rational.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/re.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/select.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/set.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/signal.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/string.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/struct.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/thread.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/time.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/variable.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/vm.h
+sockssocket.o: $(hdrdir)/ruby/internal/interpreter.h
+sockssocket.o: $(hdrdir)/ruby/internal/iterator.h
+sockssocket.o: $(hdrdir)/ruby/internal/memory.h
+sockssocket.o: $(hdrdir)/ruby/internal/method.h
+sockssocket.o: $(hdrdir)/ruby/internal/module.h
+sockssocket.o: $(hdrdir)/ruby/internal/newobj.h
+sockssocket.o: $(hdrdir)/ruby/internal/scan_args.h
+sockssocket.o: $(hdrdir)/ruby/internal/special_consts.h
+sockssocket.o: $(hdrdir)/ruby/internal/static_assert.h
+sockssocket.o: $(hdrdir)/ruby/internal/stdalign.h
+sockssocket.o: $(hdrdir)/ruby/internal/stdbool.h
+sockssocket.o: $(hdrdir)/ruby/internal/stdckdint.h
+sockssocket.o: $(hdrdir)/ruby/internal/symbol.h
+sockssocket.o: $(hdrdir)/ruby/internal/value.h
+sockssocket.o: $(hdrdir)/ruby/internal/value_type.h
+sockssocket.o: $(hdrdir)/ruby/internal/variable.h
+sockssocket.o: $(hdrdir)/ruby/internal/warning_push.h
+sockssocket.o: $(hdrdir)/ruby/internal/xmalloc.h
+sockssocket.o: $(hdrdir)/ruby/io.h
+sockssocket.o: $(hdrdir)/ruby/missing.h
+sockssocket.o: $(hdrdir)/ruby/onigmo.h
+sockssocket.o: $(hdrdir)/ruby/oniguruma.h
+sockssocket.o: $(hdrdir)/ruby/ruby.h
+sockssocket.o: $(hdrdir)/ruby/st.h
+sockssocket.o: $(hdrdir)/ruby/subst.h
+sockssocket.o: $(hdrdir)/ruby/thread.h
+sockssocket.o: $(hdrdir)/ruby/thread_native.h
+sockssocket.o: $(hdrdir)/ruby/util.h
+sockssocket.o: $(hdrdir)/ruby/version.h
+sockssocket.o: $(top_srcdir)/ccan/check_type/check_type.h
+sockssocket.o: $(top_srcdir)/ccan/container_of/container_of.h
+sockssocket.o: $(top_srcdir)/ccan/list/list.h
+sockssocket.o: $(top_srcdir)/ccan/str/str.h
+sockssocket.o: $(top_srcdir)/encindex.h
+sockssocket.o: $(top_srcdir)/id_table.h
+sockssocket.o: $(top_srcdir)/internal.h
+sockssocket.o: $(top_srcdir)/internal/array.h
+sockssocket.o: $(top_srcdir)/internal/basic_operators.h
+sockssocket.o: $(top_srcdir)/internal/box.h
+sockssocket.o: $(top_srcdir)/internal/compilers.h
+sockssocket.o: $(top_srcdir)/internal/error.h
+sockssocket.o: $(top_srcdir)/internal/gc.h
+sockssocket.o: $(top_srcdir)/internal/imemo.h
+sockssocket.o: $(top_srcdir)/internal/io.h
+sockssocket.o: $(top_srcdir)/internal/sanitizers.h
+sockssocket.o: $(top_srcdir)/internal/serial.h
+sockssocket.o: $(top_srcdir)/internal/set_table.h
+sockssocket.o: $(top_srcdir)/internal/static_assert.h
+sockssocket.o: $(top_srcdir)/internal/string.h
+sockssocket.o: $(top_srcdir)/internal/thread.h
+sockssocket.o: $(top_srcdir)/internal/vm.h
+sockssocket.o: $(top_srcdir)/internal/warnings.h
+sockssocket.o: $(top_srcdir)/method.h
+sockssocket.o: $(top_srcdir)/node.h
+sockssocket.o: $(top_srcdir)/ruby_assert.h
+sockssocket.o: $(top_srcdir)/ruby_atomic.h
+sockssocket.o: $(top_srcdir)/rubyparser.h
+sockssocket.o: $(top_srcdir)/shape.h
+sockssocket.o: $(top_srcdir)/thread_pthread.h
+sockssocket.o: $(top_srcdir)/vm_core.h
+sockssocket.o: $(top_srcdir)/vm_opts.h
+sockssocket.o: constdefs.h
+sockssocket.o: rubysocket.h
+sockssocket.o: sockport.h
+sockssocket.o: sockssocket.c
+sockssocket.o: {$(VPATH)}id.h
+tcpserver.o: $(RUBY_EXTCONF_H)
+tcpserver.o: $(arch_hdrdir)/ruby/config.h
+tcpserver.o: $(hdrdir)/ruby/assert.h
+tcpserver.o: $(hdrdir)/ruby/atomic.h
+tcpserver.o: $(hdrdir)/ruby/backward.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/assume.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/attributes.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/bool.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/inttypes.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/limits.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/long_long.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/stdalign.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/stdarg.h
+tcpserver.o: $(hdrdir)/ruby/defines.h
+tcpserver.o: $(hdrdir)/ruby/encoding.h
+tcpserver.o: $(hdrdir)/ruby/fiber/scheduler.h
+tcpserver.o: $(hdrdir)/ruby/intern.h
+tcpserver.o: $(hdrdir)/ruby/internal/abi.h
+tcpserver.o: $(hdrdir)/ruby/internal/anyargs.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/assume.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/artificial.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/cold.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/const.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/error.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/format.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/noalias.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/noinline.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/pure.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/restrict.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/warning.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/weakref.h
+tcpserver.o: $(hdrdir)/ruby/internal/cast.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_since.h
+tcpserver.o: $(hdrdir)/ruby/internal/config.h
+tcpserver.o: $(hdrdir)/ruby/internal/constant_p.h
+tcpserver.o: $(hdrdir)/ruby/internal/core.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rarray.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rbasic.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rbignum.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rclass.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rdata.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rfile.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rhash.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/robject.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rregexp.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rstring.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rstruct.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+tcpserver.o: $(hdrdir)/ruby/internal/ctype.h
+tcpserver.o: $(hdrdir)/ruby/internal/dllexport.h
+tcpserver.o: $(hdrdir)/ruby/internal/dosish.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/re.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/string.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+tcpserver.o: $(hdrdir)/ruby/internal/error.h
+tcpserver.o: $(hdrdir)/ruby/internal/eval.h
+tcpserver.o: $(hdrdir)/ruby/internal/event.h
+tcpserver.o: $(hdrdir)/ruby/internal/fl_type.h
+tcpserver.o: $(hdrdir)/ruby/internal/gc.h
+tcpserver.o: $(hdrdir)/ruby/internal/glob.h
+tcpserver.o: $(hdrdir)/ruby/internal/globals.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/attribute.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/builtin.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/extension.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/feature.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/warning.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/array.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/bignum.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/class.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/compar.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/complex.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/cont.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/dir.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/enum.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/error.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/eval.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/file.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/hash.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/io.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/load.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/marshal.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/numeric.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/object.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/parse.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/proc.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/process.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/random.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/range.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/rational.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/re.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/ruby.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/select.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/set.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/signal.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/string.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/struct.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/thread.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/time.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/variable.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/vm.h
+tcpserver.o: $(hdrdir)/ruby/internal/interpreter.h
+tcpserver.o: $(hdrdir)/ruby/internal/iterator.h
+tcpserver.o: $(hdrdir)/ruby/internal/memory.h
+tcpserver.o: $(hdrdir)/ruby/internal/method.h
+tcpserver.o: $(hdrdir)/ruby/internal/module.h
+tcpserver.o: $(hdrdir)/ruby/internal/newobj.h
+tcpserver.o: $(hdrdir)/ruby/internal/scan_args.h
+tcpserver.o: $(hdrdir)/ruby/internal/special_consts.h
+tcpserver.o: $(hdrdir)/ruby/internal/static_assert.h
+tcpserver.o: $(hdrdir)/ruby/internal/stdalign.h
+tcpserver.o: $(hdrdir)/ruby/internal/stdbool.h
+tcpserver.o: $(hdrdir)/ruby/internal/stdckdint.h
+tcpserver.o: $(hdrdir)/ruby/internal/symbol.h
+tcpserver.o: $(hdrdir)/ruby/internal/value.h
+tcpserver.o: $(hdrdir)/ruby/internal/value_type.h
+tcpserver.o: $(hdrdir)/ruby/internal/variable.h
+tcpserver.o: $(hdrdir)/ruby/internal/warning_push.h
+tcpserver.o: $(hdrdir)/ruby/internal/xmalloc.h
+tcpserver.o: $(hdrdir)/ruby/io.h
+tcpserver.o: $(hdrdir)/ruby/missing.h
+tcpserver.o: $(hdrdir)/ruby/onigmo.h
+tcpserver.o: $(hdrdir)/ruby/oniguruma.h
+tcpserver.o: $(hdrdir)/ruby/ruby.h
+tcpserver.o: $(hdrdir)/ruby/st.h
+tcpserver.o: $(hdrdir)/ruby/subst.h
+tcpserver.o: $(hdrdir)/ruby/thread.h
+tcpserver.o: $(hdrdir)/ruby/thread_native.h
+tcpserver.o: $(hdrdir)/ruby/util.h
+tcpserver.o: $(hdrdir)/ruby/version.h
+tcpserver.o: $(top_srcdir)/ccan/check_type/check_type.h
+tcpserver.o: $(top_srcdir)/ccan/container_of/container_of.h
+tcpserver.o: $(top_srcdir)/ccan/list/list.h
+tcpserver.o: $(top_srcdir)/ccan/str/str.h
+tcpserver.o: $(top_srcdir)/encindex.h
+tcpserver.o: $(top_srcdir)/id_table.h
+tcpserver.o: $(top_srcdir)/internal.h
+tcpserver.o: $(top_srcdir)/internal/array.h
+tcpserver.o: $(top_srcdir)/internal/basic_operators.h
+tcpserver.o: $(top_srcdir)/internal/box.h
+tcpserver.o: $(top_srcdir)/internal/compilers.h
+tcpserver.o: $(top_srcdir)/internal/error.h
+tcpserver.o: $(top_srcdir)/internal/gc.h
+tcpserver.o: $(top_srcdir)/internal/imemo.h
+tcpserver.o: $(top_srcdir)/internal/io.h
+tcpserver.o: $(top_srcdir)/internal/sanitizers.h
+tcpserver.o: $(top_srcdir)/internal/serial.h
+tcpserver.o: $(top_srcdir)/internal/set_table.h
+tcpserver.o: $(top_srcdir)/internal/static_assert.h
+tcpserver.o: $(top_srcdir)/internal/string.h
+tcpserver.o: $(top_srcdir)/internal/thread.h
+tcpserver.o: $(top_srcdir)/internal/vm.h
+tcpserver.o: $(top_srcdir)/internal/warnings.h
+tcpserver.o: $(top_srcdir)/method.h
+tcpserver.o: $(top_srcdir)/node.h
+tcpserver.o: $(top_srcdir)/ruby_assert.h
+tcpserver.o: $(top_srcdir)/ruby_atomic.h
+tcpserver.o: $(top_srcdir)/rubyparser.h
+tcpserver.o: $(top_srcdir)/shape.h
+tcpserver.o: $(top_srcdir)/thread_pthread.h
+tcpserver.o: $(top_srcdir)/vm_core.h
+tcpserver.o: $(top_srcdir)/vm_opts.h
+tcpserver.o: constdefs.h
+tcpserver.o: rubysocket.h
+tcpserver.o: sockport.h
+tcpserver.o: tcpserver.c
+tcpserver.o: {$(VPATH)}id.h
+tcpsocket.o: $(RUBY_EXTCONF_H)
+tcpsocket.o: $(arch_hdrdir)/ruby/config.h
+tcpsocket.o: $(hdrdir)/ruby/assert.h
+tcpsocket.o: $(hdrdir)/ruby/atomic.h
+tcpsocket.o: $(hdrdir)/ruby/backward.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/assume.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/attributes.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/bool.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/limits.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/long_long.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h
+tcpsocket.o: $(hdrdir)/ruby/defines.h
+tcpsocket.o: $(hdrdir)/ruby/encoding.h
+tcpsocket.o: $(hdrdir)/ruby/fiber/scheduler.h
+tcpsocket.o: $(hdrdir)/ruby/intern.h
+tcpsocket.o: $(hdrdir)/ruby/internal/abi.h
+tcpsocket.o: $(hdrdir)/ruby/internal/anyargs.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/assume.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/cold.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/const.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/error.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/format.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/pure.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/warning.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+tcpsocket.o: $(hdrdir)/ruby/internal/cast.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_since.h
+tcpsocket.o: $(hdrdir)/ruby/internal/config.h
+tcpsocket.o: $(hdrdir)/ruby/internal/constant_p.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rarray.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rclass.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rdata.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rfile.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rhash.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/robject.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rstring.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+tcpsocket.o: $(hdrdir)/ruby/internal/ctype.h
+tcpsocket.o: $(hdrdir)/ruby/internal/dllexport.h
+tcpsocket.o: $(hdrdir)/ruby/internal/dosish.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/re.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/string.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+tcpsocket.o: $(hdrdir)/ruby/internal/error.h
+tcpsocket.o: $(hdrdir)/ruby/internal/eval.h
+tcpsocket.o: $(hdrdir)/ruby/internal/event.h
+tcpsocket.o: $(hdrdir)/ruby/internal/fl_type.h
+tcpsocket.o: $(hdrdir)/ruby/internal/gc.h
+tcpsocket.o: $(hdrdir)/ruby/internal/glob.h
+tcpsocket.o: $(hdrdir)/ruby/internal/globals.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/attribute.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/builtin.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/extension.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/feature.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/warning.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/array.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/class.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/compar.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/complex.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/cont.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/dir.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/enum.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/error.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/eval.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/file.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/hash.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/io.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/load.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/object.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/parse.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/proc.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/process.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/random.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/range.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/rational.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/re.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/select.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/set.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/signal.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/string.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/struct.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/thread.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/time.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/variable.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/vm.h
+tcpsocket.o: $(hdrdir)/ruby/internal/interpreter.h
+tcpsocket.o: $(hdrdir)/ruby/internal/iterator.h
+tcpsocket.o: $(hdrdir)/ruby/internal/memory.h
+tcpsocket.o: $(hdrdir)/ruby/internal/method.h
+tcpsocket.o: $(hdrdir)/ruby/internal/module.h
+tcpsocket.o: $(hdrdir)/ruby/internal/newobj.h
+tcpsocket.o: $(hdrdir)/ruby/internal/scan_args.h
+tcpsocket.o: $(hdrdir)/ruby/internal/special_consts.h
+tcpsocket.o: $(hdrdir)/ruby/internal/static_assert.h
+tcpsocket.o: $(hdrdir)/ruby/internal/stdalign.h
+tcpsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+tcpsocket.o: $(hdrdir)/ruby/internal/stdckdint.h
+tcpsocket.o: $(hdrdir)/ruby/internal/symbol.h
+tcpsocket.o: $(hdrdir)/ruby/internal/value.h
+tcpsocket.o: $(hdrdir)/ruby/internal/value_type.h
+tcpsocket.o: $(hdrdir)/ruby/internal/variable.h
+tcpsocket.o: $(hdrdir)/ruby/internal/warning_push.h
+tcpsocket.o: $(hdrdir)/ruby/internal/xmalloc.h
+tcpsocket.o: $(hdrdir)/ruby/io.h
+tcpsocket.o: $(hdrdir)/ruby/missing.h
+tcpsocket.o: $(hdrdir)/ruby/onigmo.h
+tcpsocket.o: $(hdrdir)/ruby/oniguruma.h
+tcpsocket.o: $(hdrdir)/ruby/ruby.h
+tcpsocket.o: $(hdrdir)/ruby/st.h
+tcpsocket.o: $(hdrdir)/ruby/subst.h
+tcpsocket.o: $(hdrdir)/ruby/thread.h
+tcpsocket.o: $(hdrdir)/ruby/thread_native.h
+tcpsocket.o: $(hdrdir)/ruby/util.h
+tcpsocket.o: $(hdrdir)/ruby/version.h
+tcpsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
+tcpsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
+tcpsocket.o: $(top_srcdir)/ccan/list/list.h
+tcpsocket.o: $(top_srcdir)/ccan/str/str.h
+tcpsocket.o: $(top_srcdir)/encindex.h
+tcpsocket.o: $(top_srcdir)/id_table.h
+tcpsocket.o: $(top_srcdir)/internal.h
+tcpsocket.o: $(top_srcdir)/internal/array.h
+tcpsocket.o: $(top_srcdir)/internal/basic_operators.h
+tcpsocket.o: $(top_srcdir)/internal/box.h
+tcpsocket.o: $(top_srcdir)/internal/compilers.h
+tcpsocket.o: $(top_srcdir)/internal/error.h
+tcpsocket.o: $(top_srcdir)/internal/gc.h
+tcpsocket.o: $(top_srcdir)/internal/imemo.h
+tcpsocket.o: $(top_srcdir)/internal/io.h
+tcpsocket.o: $(top_srcdir)/internal/sanitizers.h
+tcpsocket.o: $(top_srcdir)/internal/serial.h
+tcpsocket.o: $(top_srcdir)/internal/set_table.h
+tcpsocket.o: $(top_srcdir)/internal/static_assert.h
+tcpsocket.o: $(top_srcdir)/internal/string.h
+tcpsocket.o: $(top_srcdir)/internal/thread.h
+tcpsocket.o: $(top_srcdir)/internal/vm.h
+tcpsocket.o: $(top_srcdir)/internal/warnings.h
+tcpsocket.o: $(top_srcdir)/method.h
+tcpsocket.o: $(top_srcdir)/node.h
+tcpsocket.o: $(top_srcdir)/ruby_assert.h
+tcpsocket.o: $(top_srcdir)/ruby_atomic.h
+tcpsocket.o: $(top_srcdir)/rubyparser.h
+tcpsocket.o: $(top_srcdir)/shape.h
+tcpsocket.o: $(top_srcdir)/thread_pthread.h
+tcpsocket.o: $(top_srcdir)/vm_core.h
+tcpsocket.o: $(top_srcdir)/vm_opts.h
+tcpsocket.o: constdefs.h
+tcpsocket.o: rubysocket.h
+tcpsocket.o: sockport.h
+tcpsocket.o: tcpsocket.c
+tcpsocket.o: {$(VPATH)}id.h
+udpsocket.o: $(RUBY_EXTCONF_H)
+udpsocket.o: $(arch_hdrdir)/ruby/config.h
+udpsocket.o: $(hdrdir)/ruby/assert.h
+udpsocket.o: $(hdrdir)/ruby/atomic.h
+udpsocket.o: $(hdrdir)/ruby/backward.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/assume.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/attributes.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/bool.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/limits.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/long_long.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h
+udpsocket.o: $(hdrdir)/ruby/defines.h
+udpsocket.o: $(hdrdir)/ruby/encoding.h
+udpsocket.o: $(hdrdir)/ruby/fiber/scheduler.h
+udpsocket.o: $(hdrdir)/ruby/intern.h
+udpsocket.o: $(hdrdir)/ruby/internal/abi.h
+udpsocket.o: $(hdrdir)/ruby/internal/anyargs.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/assume.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/cold.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/const.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/error.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/format.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/pure.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/warning.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+udpsocket.o: $(hdrdir)/ruby/internal/cast.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_since.h
+udpsocket.o: $(hdrdir)/ruby/internal/config.h
+udpsocket.o: $(hdrdir)/ruby/internal/constant_p.h
+udpsocket.o: $(hdrdir)/ruby/internal/core.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rarray.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rclass.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rdata.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rfile.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rhash.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/robject.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rstring.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+udpsocket.o: $(hdrdir)/ruby/internal/ctype.h
+udpsocket.o: $(hdrdir)/ruby/internal/dllexport.h
+udpsocket.o: $(hdrdir)/ruby/internal/dosish.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/re.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/string.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+udpsocket.o: $(hdrdir)/ruby/internal/error.h
+udpsocket.o: $(hdrdir)/ruby/internal/eval.h
+udpsocket.o: $(hdrdir)/ruby/internal/event.h
+udpsocket.o: $(hdrdir)/ruby/internal/fl_type.h
+udpsocket.o: $(hdrdir)/ruby/internal/gc.h
+udpsocket.o: $(hdrdir)/ruby/internal/glob.h
+udpsocket.o: $(hdrdir)/ruby/internal/globals.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/attribute.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/builtin.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/extension.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/feature.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/warning.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/array.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/class.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/compar.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/complex.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/cont.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/dir.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/enum.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/error.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/eval.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/file.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/hash.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/io.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/load.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/object.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/parse.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/proc.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/process.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/random.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/range.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/rational.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/re.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/select.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/set.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/signal.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/string.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/struct.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/thread.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/time.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/variable.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/vm.h
+udpsocket.o: $(hdrdir)/ruby/internal/interpreter.h
+udpsocket.o: $(hdrdir)/ruby/internal/iterator.h
+udpsocket.o: $(hdrdir)/ruby/internal/memory.h
+udpsocket.o: $(hdrdir)/ruby/internal/method.h
+udpsocket.o: $(hdrdir)/ruby/internal/module.h
+udpsocket.o: $(hdrdir)/ruby/internal/newobj.h
+udpsocket.o: $(hdrdir)/ruby/internal/scan_args.h
+udpsocket.o: $(hdrdir)/ruby/internal/special_consts.h
+udpsocket.o: $(hdrdir)/ruby/internal/static_assert.h
+udpsocket.o: $(hdrdir)/ruby/internal/stdalign.h
+udpsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+udpsocket.o: $(hdrdir)/ruby/internal/stdckdint.h
+udpsocket.o: $(hdrdir)/ruby/internal/symbol.h
+udpsocket.o: $(hdrdir)/ruby/internal/value.h
+udpsocket.o: $(hdrdir)/ruby/internal/value_type.h
+udpsocket.o: $(hdrdir)/ruby/internal/variable.h
+udpsocket.o: $(hdrdir)/ruby/internal/warning_push.h
+udpsocket.o: $(hdrdir)/ruby/internal/xmalloc.h
+udpsocket.o: $(hdrdir)/ruby/io.h
+udpsocket.o: $(hdrdir)/ruby/missing.h
+udpsocket.o: $(hdrdir)/ruby/onigmo.h
+udpsocket.o: $(hdrdir)/ruby/oniguruma.h
+udpsocket.o: $(hdrdir)/ruby/ruby.h
+udpsocket.o: $(hdrdir)/ruby/st.h
+udpsocket.o: $(hdrdir)/ruby/subst.h
+udpsocket.o: $(hdrdir)/ruby/thread.h
+udpsocket.o: $(hdrdir)/ruby/thread_native.h
+udpsocket.o: $(hdrdir)/ruby/util.h
+udpsocket.o: $(hdrdir)/ruby/version.h
+udpsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
+udpsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
+udpsocket.o: $(top_srcdir)/ccan/list/list.h
+udpsocket.o: $(top_srcdir)/ccan/str/str.h
+udpsocket.o: $(top_srcdir)/encindex.h
+udpsocket.o: $(top_srcdir)/id_table.h
+udpsocket.o: $(top_srcdir)/internal.h
+udpsocket.o: $(top_srcdir)/internal/array.h
+udpsocket.o: $(top_srcdir)/internal/basic_operators.h
+udpsocket.o: $(top_srcdir)/internal/box.h
+udpsocket.o: $(top_srcdir)/internal/compilers.h
+udpsocket.o: $(top_srcdir)/internal/error.h
+udpsocket.o: $(top_srcdir)/internal/gc.h
+udpsocket.o: $(top_srcdir)/internal/imemo.h
+udpsocket.o: $(top_srcdir)/internal/io.h
+udpsocket.o: $(top_srcdir)/internal/sanitizers.h
+udpsocket.o: $(top_srcdir)/internal/serial.h
+udpsocket.o: $(top_srcdir)/internal/set_table.h
+udpsocket.o: $(top_srcdir)/internal/static_assert.h
+udpsocket.o: $(top_srcdir)/internal/string.h
+udpsocket.o: $(top_srcdir)/internal/thread.h
+udpsocket.o: $(top_srcdir)/internal/vm.h
+udpsocket.o: $(top_srcdir)/internal/warnings.h
+udpsocket.o: $(top_srcdir)/method.h
+udpsocket.o: $(top_srcdir)/node.h
+udpsocket.o: $(top_srcdir)/ruby_assert.h
+udpsocket.o: $(top_srcdir)/ruby_atomic.h
+udpsocket.o: $(top_srcdir)/rubyparser.h
+udpsocket.o: $(top_srcdir)/shape.h
+udpsocket.o: $(top_srcdir)/thread_pthread.h
+udpsocket.o: $(top_srcdir)/vm_core.h
+udpsocket.o: $(top_srcdir)/vm_opts.h
+udpsocket.o: constdefs.h
+udpsocket.o: rubysocket.h
+udpsocket.o: sockport.h
+udpsocket.o: udpsocket.c
+udpsocket.o: {$(VPATH)}id.h
+unixserver.o: $(RUBY_EXTCONF_H)
+unixserver.o: $(arch_hdrdir)/ruby/config.h
+unixserver.o: $(hdrdir)/ruby/assert.h
+unixserver.o: $(hdrdir)/ruby/atomic.h
+unixserver.o: $(hdrdir)/ruby/backward.h
+unixserver.o: $(hdrdir)/ruby/backward/2/assume.h
+unixserver.o: $(hdrdir)/ruby/backward/2/attributes.h
+unixserver.o: $(hdrdir)/ruby/backward/2/bool.h
+unixserver.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+unixserver.o: $(hdrdir)/ruby/backward/2/inttypes.h
+unixserver.o: $(hdrdir)/ruby/backward/2/limits.h
+unixserver.o: $(hdrdir)/ruby/backward/2/long_long.h
+unixserver.o: $(hdrdir)/ruby/backward/2/stdalign.h
+unixserver.o: $(hdrdir)/ruby/backward/2/stdarg.h
+unixserver.o: $(hdrdir)/ruby/defines.h
+unixserver.o: $(hdrdir)/ruby/encoding.h
+unixserver.o: $(hdrdir)/ruby/fiber/scheduler.h
+unixserver.o: $(hdrdir)/ruby/intern.h
+unixserver.o: $(hdrdir)/ruby/internal/abi.h
+unixserver.o: $(hdrdir)/ruby/internal/anyargs.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+unixserver.o: $(hdrdir)/ruby/internal/assume.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/artificial.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/cold.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/const.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/error.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/format.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/noalias.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/noinline.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/pure.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/restrict.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/warning.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/weakref.h
+unixserver.o: $(hdrdir)/ruby/internal/cast.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_since.h
+unixserver.o: $(hdrdir)/ruby/internal/config.h
+unixserver.o: $(hdrdir)/ruby/internal/constant_p.h
+unixserver.o: $(hdrdir)/ruby/internal/core.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rarray.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rbasic.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rbignum.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rclass.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rdata.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rfile.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rhash.h
+unixserver.o: $(hdrdir)/ruby/internal/core/robject.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rregexp.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rstring.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rstruct.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+unixserver.o: $(hdrdir)/ruby/internal/ctype.h
+unixserver.o: $(hdrdir)/ruby/internal/dllexport.h
+unixserver.o: $(hdrdir)/ruby/internal/dosish.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/re.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/string.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+unixserver.o: $(hdrdir)/ruby/internal/error.h
+unixserver.o: $(hdrdir)/ruby/internal/eval.h
+unixserver.o: $(hdrdir)/ruby/internal/event.h
+unixserver.o: $(hdrdir)/ruby/internal/fl_type.h
+unixserver.o: $(hdrdir)/ruby/internal/gc.h
+unixserver.o: $(hdrdir)/ruby/internal/glob.h
+unixserver.o: $(hdrdir)/ruby/internal/globals.h
+unixserver.o: $(hdrdir)/ruby/internal/has/attribute.h
+unixserver.o: $(hdrdir)/ruby/internal/has/builtin.h
+unixserver.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+unixserver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+unixserver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+unixserver.o: $(hdrdir)/ruby/internal/has/extension.h
+unixserver.o: $(hdrdir)/ruby/internal/has/feature.h
+unixserver.o: $(hdrdir)/ruby/internal/has/warning.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/array.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/bignum.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/class.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/compar.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/complex.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/cont.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/dir.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/enum.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/error.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/eval.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/file.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/hash.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/io.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/load.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/marshal.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/numeric.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/object.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/parse.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/proc.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/process.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/random.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/range.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/rational.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/re.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/ruby.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/select.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/set.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/signal.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/string.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/struct.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/thread.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/time.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/variable.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/vm.h
+unixserver.o: $(hdrdir)/ruby/internal/interpreter.h
+unixserver.o: $(hdrdir)/ruby/internal/iterator.h
+unixserver.o: $(hdrdir)/ruby/internal/memory.h
+unixserver.o: $(hdrdir)/ruby/internal/method.h
+unixserver.o: $(hdrdir)/ruby/internal/module.h
+unixserver.o: $(hdrdir)/ruby/internal/newobj.h
+unixserver.o: $(hdrdir)/ruby/internal/scan_args.h
+unixserver.o: $(hdrdir)/ruby/internal/special_consts.h
+unixserver.o: $(hdrdir)/ruby/internal/static_assert.h
+unixserver.o: $(hdrdir)/ruby/internal/stdalign.h
+unixserver.o: $(hdrdir)/ruby/internal/stdbool.h
+unixserver.o: $(hdrdir)/ruby/internal/stdckdint.h
+unixserver.o: $(hdrdir)/ruby/internal/symbol.h
+unixserver.o: $(hdrdir)/ruby/internal/value.h
+unixserver.o: $(hdrdir)/ruby/internal/value_type.h
+unixserver.o: $(hdrdir)/ruby/internal/variable.h
+unixserver.o: $(hdrdir)/ruby/internal/warning_push.h
+unixserver.o: $(hdrdir)/ruby/internal/xmalloc.h
+unixserver.o: $(hdrdir)/ruby/io.h
+unixserver.o: $(hdrdir)/ruby/missing.h
+unixserver.o: $(hdrdir)/ruby/onigmo.h
+unixserver.o: $(hdrdir)/ruby/oniguruma.h
+unixserver.o: $(hdrdir)/ruby/ruby.h
+unixserver.o: $(hdrdir)/ruby/st.h
+unixserver.o: $(hdrdir)/ruby/subst.h
+unixserver.o: $(hdrdir)/ruby/thread.h
+unixserver.o: $(hdrdir)/ruby/thread_native.h
+unixserver.o: $(hdrdir)/ruby/util.h
+unixserver.o: $(hdrdir)/ruby/version.h
+unixserver.o: $(top_srcdir)/ccan/check_type/check_type.h
+unixserver.o: $(top_srcdir)/ccan/container_of/container_of.h
+unixserver.o: $(top_srcdir)/ccan/list/list.h
+unixserver.o: $(top_srcdir)/ccan/str/str.h
+unixserver.o: $(top_srcdir)/encindex.h
+unixserver.o: $(top_srcdir)/id_table.h
+unixserver.o: $(top_srcdir)/internal.h
+unixserver.o: $(top_srcdir)/internal/array.h
+unixserver.o: $(top_srcdir)/internal/basic_operators.h
+unixserver.o: $(top_srcdir)/internal/box.h
+unixserver.o: $(top_srcdir)/internal/compilers.h
+unixserver.o: $(top_srcdir)/internal/error.h
+unixserver.o: $(top_srcdir)/internal/gc.h
+unixserver.o: $(top_srcdir)/internal/imemo.h
+unixserver.o: $(top_srcdir)/internal/io.h
+unixserver.o: $(top_srcdir)/internal/sanitizers.h
+unixserver.o: $(top_srcdir)/internal/serial.h
+unixserver.o: $(top_srcdir)/internal/set_table.h
+unixserver.o: $(top_srcdir)/internal/static_assert.h
+unixserver.o: $(top_srcdir)/internal/string.h
+unixserver.o: $(top_srcdir)/internal/thread.h
+unixserver.o: $(top_srcdir)/internal/vm.h
+unixserver.o: $(top_srcdir)/internal/warnings.h
+unixserver.o: $(top_srcdir)/method.h
+unixserver.o: $(top_srcdir)/node.h
+unixserver.o: $(top_srcdir)/ruby_assert.h
+unixserver.o: $(top_srcdir)/ruby_atomic.h
+unixserver.o: $(top_srcdir)/rubyparser.h
+unixserver.o: $(top_srcdir)/shape.h
+unixserver.o: $(top_srcdir)/thread_pthread.h
+unixserver.o: $(top_srcdir)/vm_core.h
+unixserver.o: $(top_srcdir)/vm_opts.h
+unixserver.o: constdefs.h
+unixserver.o: rubysocket.h
+unixserver.o: sockport.h
+unixserver.o: unixserver.c
+unixserver.o: {$(VPATH)}id.h
+unixsocket.o: $(RUBY_EXTCONF_H)
+unixsocket.o: $(arch_hdrdir)/ruby/config.h
+unixsocket.o: $(hdrdir)/ruby/assert.h
+unixsocket.o: $(hdrdir)/ruby/atomic.h
+unixsocket.o: $(hdrdir)/ruby/backward.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/assume.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/attributes.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/bool.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/limits.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/long_long.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h
+unixsocket.o: $(hdrdir)/ruby/defines.h
+unixsocket.o: $(hdrdir)/ruby/encoding.h
+unixsocket.o: $(hdrdir)/ruby/fiber/scheduler.h
+unixsocket.o: $(hdrdir)/ruby/intern.h
+unixsocket.o: $(hdrdir)/ruby/internal/abi.h
+unixsocket.o: $(hdrdir)/ruby/internal/anyargs.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/assume.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/cold.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/const.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/error.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/format.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/pure.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/warning.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+unixsocket.o: $(hdrdir)/ruby/internal/cast.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_since.h
+unixsocket.o: $(hdrdir)/ruby/internal/config.h
+unixsocket.o: $(hdrdir)/ruby/internal/constant_p.h
+unixsocket.o: $(hdrdir)/ruby/internal/core.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rarray.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rclass.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rdata.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rfile.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rhash.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/robject.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rstring.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+unixsocket.o: $(hdrdir)/ruby/internal/ctype.h
+unixsocket.o: $(hdrdir)/ruby/internal/dllexport.h
+unixsocket.o: $(hdrdir)/ruby/internal/dosish.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/re.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/string.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+unixsocket.o: $(hdrdir)/ruby/internal/error.h
+unixsocket.o: $(hdrdir)/ruby/internal/eval.h
+unixsocket.o: $(hdrdir)/ruby/internal/event.h
+unixsocket.o: $(hdrdir)/ruby/internal/fl_type.h
+unixsocket.o: $(hdrdir)/ruby/internal/gc.h
+unixsocket.o: $(hdrdir)/ruby/internal/glob.h
+unixsocket.o: $(hdrdir)/ruby/internal/globals.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/attribute.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/builtin.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/extension.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/feature.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/warning.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/array.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/class.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/compar.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/complex.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/cont.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/dir.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/enum.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/error.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/eval.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/file.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/hash.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/io.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/load.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/object.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/parse.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/proc.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/process.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/random.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/range.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/rational.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/re.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/select.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/set.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/signal.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/string.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/struct.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/thread.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/time.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/variable.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/vm.h
+unixsocket.o: $(hdrdir)/ruby/internal/interpreter.h
+unixsocket.o: $(hdrdir)/ruby/internal/iterator.h
+unixsocket.o: $(hdrdir)/ruby/internal/memory.h
+unixsocket.o: $(hdrdir)/ruby/internal/method.h
+unixsocket.o: $(hdrdir)/ruby/internal/module.h
+unixsocket.o: $(hdrdir)/ruby/internal/newobj.h
+unixsocket.o: $(hdrdir)/ruby/internal/scan_args.h
+unixsocket.o: $(hdrdir)/ruby/internal/special_consts.h
+unixsocket.o: $(hdrdir)/ruby/internal/static_assert.h
+unixsocket.o: $(hdrdir)/ruby/internal/stdalign.h
+unixsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+unixsocket.o: $(hdrdir)/ruby/internal/stdckdint.h
+unixsocket.o: $(hdrdir)/ruby/internal/symbol.h
+unixsocket.o: $(hdrdir)/ruby/internal/value.h
+unixsocket.o: $(hdrdir)/ruby/internal/value_type.h
+unixsocket.o: $(hdrdir)/ruby/internal/variable.h
+unixsocket.o: $(hdrdir)/ruby/internal/warning_push.h
+unixsocket.o: $(hdrdir)/ruby/internal/xmalloc.h
+unixsocket.o: $(hdrdir)/ruby/io.h
+unixsocket.o: $(hdrdir)/ruby/missing.h
+unixsocket.o: $(hdrdir)/ruby/onigmo.h
+unixsocket.o: $(hdrdir)/ruby/oniguruma.h
+unixsocket.o: $(hdrdir)/ruby/ruby.h
+unixsocket.o: $(hdrdir)/ruby/st.h
+unixsocket.o: $(hdrdir)/ruby/subst.h
+unixsocket.o: $(hdrdir)/ruby/thread.h
+unixsocket.o: $(hdrdir)/ruby/thread_native.h
+unixsocket.o: $(hdrdir)/ruby/util.h
+unixsocket.o: $(hdrdir)/ruby/version.h
+unixsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
+unixsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
+unixsocket.o: $(top_srcdir)/ccan/list/list.h
+unixsocket.o: $(top_srcdir)/ccan/str/str.h
+unixsocket.o: $(top_srcdir)/encindex.h
+unixsocket.o: $(top_srcdir)/id_table.h
+unixsocket.o: $(top_srcdir)/internal.h
+unixsocket.o: $(top_srcdir)/internal/array.h
+unixsocket.o: $(top_srcdir)/internal/basic_operators.h
+unixsocket.o: $(top_srcdir)/internal/box.h
+unixsocket.o: $(top_srcdir)/internal/compilers.h
+unixsocket.o: $(top_srcdir)/internal/error.h
+unixsocket.o: $(top_srcdir)/internal/gc.h
+unixsocket.o: $(top_srcdir)/internal/imemo.h
+unixsocket.o: $(top_srcdir)/internal/io.h
+unixsocket.o: $(top_srcdir)/internal/sanitizers.h
+unixsocket.o: $(top_srcdir)/internal/serial.h
+unixsocket.o: $(top_srcdir)/internal/set_table.h
+unixsocket.o: $(top_srcdir)/internal/static_assert.h
+unixsocket.o: $(top_srcdir)/internal/string.h
+unixsocket.o: $(top_srcdir)/internal/thread.h
+unixsocket.o: $(top_srcdir)/internal/vm.h
+unixsocket.o: $(top_srcdir)/internal/warnings.h
+unixsocket.o: $(top_srcdir)/method.h
+unixsocket.o: $(top_srcdir)/node.h
+unixsocket.o: $(top_srcdir)/ruby_assert.h
+unixsocket.o: $(top_srcdir)/ruby_atomic.h
+unixsocket.o: $(top_srcdir)/rubyparser.h
+unixsocket.o: $(top_srcdir)/shape.h
+unixsocket.o: $(top_srcdir)/thread_pthread.h
+unixsocket.o: $(top_srcdir)/vm_core.h
+unixsocket.o: $(top_srcdir)/vm_opts.h
+unixsocket.o: constdefs.h
+unixsocket.o: rubysocket.h
+unixsocket.o: sockport.h
+unixsocket.o: unixsocket.c
+unixsocket.o: {$(VPATH)}id.h
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index 41b715e0af..a814e21c3a 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -1,124 +1,20 @@
+# frozen_string_literal: false
require 'mkmf'
-case RUBY_PLATFORM
-when /bccwin32/
- test_func = "WSACleanup"
- have_library("ws2_32", "WSACleanup")
-when /mswin32|mingw/
- test_func = "WSACleanup"
- if with_config("winsock2")
- have_library("ws2_32", "WSACleanup")
- else
- have_library("wsock32", "WSACleanup")
- end
-when /cygwin/
- test_func = "socket"
-when /beos/
- test_func = "socket"
- have_library("net", "socket")
- have_func("closesocket")
-when /i386-os2_emx/
- test_func = "socket"
- have_library("socket", "socket")
-else
- test_func = "socket"
- have_library("nsl", "t_open")
- have_library("socket", "socket")
-end
-
-unless $mswin or $bccwin or $mingw
- headers = %w<sys/types.h netdb.h string.h sys/socket.h netinet/in.h>
-end
-if /solaris/ =~ RUBY_PLATFORM and !try_compile("")
- # bug of gcc 3.0 on Solaris 8 ?
- headers << "sys/feature_tests.h"
-end
-
-ipv6 = false
-default_ipv6 = /cygwin/ !~ RUBY_PLATFORM
-if enable_config("ipv6", default_ipv6)
- if checking_for("ipv6") {try_link(<<EOF)}
+AF_INET6_SOCKET_CREATION_TEST = <<EOF
#include <sys/types.h>
+#ifndef _WIN32
#include <sys/socket.h>
-main()
+#endif
+int
+main(void)
{
socket(AF_INET6, SOCK_STREAM, 0);
+ return 0;
}
EOF
- $defs << "-DENABLE_IPV6" << "-DINET6"
- ipv6 = true
- end
-end
-
-if ipv6
- ipv6lib = nil
- class << (fmt = "unknown")
- def %(s) s || self end
- end
- idirs, ldirs = dir_config("inet6", %w[/usr/inet6 /usr/local/v6].find {|d| File.directory?(d)})
- checking_for("ipv6 type", fmt) do
- if have_macro("IPV6_INRIA_VERSION", "netinet/in.h")
- "inria"
- elsif have_macro("__KAME__", "netinet/in.h")
- have_library(ipv6lib = "inet6")
- "kame"
- elsif have_macro("_TOSHIBA_INET6", "sys/param.h")
- have_library(ipv6lib = "inet6") and "toshiba"
- elsif have_macro("__V6D__", "sys/v6config.h")
- have_library(ipv6lib = "v6") and "v6d"
- elsif have_macro("_ZETA_MINAMI_INET6", "sys/param.h")
- have_library(ipv6lib = "inet6") and "zeta"
- elsif ipv6lib = with_config("ipv6-lib")
- warn <<EOS
---with-ipv6-lib and --with-ipv6-libdir option will be obsolete, use
---with-inet6lib and --with-inet6-{include,lib} options instead.
-EOS
- find_library(ipv6lib, nil, with_config("ipv6-libdir", ldirs)) and
- ipv6lib
- elsif have_library("inet6")
- "inet6"
- end
- end or not ipv6lib or abort <<EOS
-Fatal: no #{ipv6lib} library found. cannot continue.
-You need to fetch lib#{ipv6lib}.a from appropriate
-ipv6 kit and compile beforehand.
-EOS
-end
-
-if have_struct_member("struct sockaddr_in", "sin_len", headers)
- $defs[-1] = "-DHAVE_SIN_LEN"
-end
-
-# doug's fix, NOW add -Dss_family... only if required!
-[nil, " -Dss_family=__ss_family -Dss_len=__ss_len"].each do |flags|
- if flags
- cppflags = $CPPFLAGS
- $CPPFLAGS += flags
- end
- if have_struct_member("struct sockaddr_storage", "ss_family", headers)
- $defs[-1] = "-DHAVE_SOCKADDR_STORAGE"
- break
- elsif flags
- $CPPFLAGS = cppflags
- end
-end
-
-if have_struct_member("struct sockaddr", "sa_len", headers)
- $defs[-1] = "-DHAVE_SA_LEN "
-end
-
-have_header("netinet/tcp.h") if not /cygwin/ =~ RUBY_PLATFORM # for cygwin 1.1.5
-have_header("netinet/udp.h")
-
-if have_func("sendmsg") | have_func("recvmsg")
- have_struct_member('struct msghdr', 'msg_control', ['sys/types.h', 'sys/socket.h'])
- have_struct_member('struct msghdr', 'msg_accrights', ['sys/types.h', 'sys/socket.h'])
-end
-
-getaddr_info_ok = enable_config("wide-getaddrinfo") do
- checking_for("wide getaddrinfo") {try_run(<<EOF)}
-#{cpp_include(headers)}
+GETADDRINFO_GETNAMEINFO_TEST = <<EOF
#include <stdlib.h>
#ifndef EXIT_SUCCESS
@@ -132,11 +28,17 @@ getaddr_info_ok = enable_config("wide-getaddrinfo") do
#define AF_LOCAL AF_UNIX
#endif
-main()
+int
+main(void)
{
int passive, gaierr, inet4 = 0, inet6 = 0;
struct addrinfo hints, *ai, *aitop;
char straddr[INET6_ADDRSTRLEN], strport[16];
+#ifdef _WIN32
+ WSADATA retdata;
+
+ WSAStartup(MAKEWORD(2, 0), &retdata);
+#endif
for (passive = 0; passive <= 1; passive++) {
memset(&hints, 0, sizeof(hints));
@@ -153,6 +55,10 @@ main()
if (ai->ai_addr == NULL)
goto bad;
#if defined(_AIX)
+ if (ai->ai_family == AF_INET6 && passive) {
+ inet6++;
+ continue;
+ }
ai->ai_addr->sa_len = ai->ai_addrlen;
ai->ai_addr->sa_family = ai->ai_family;
#endif
@@ -207,76 +113,599 @@ main()
if (aitop)
freeaddrinfo(aitop);
- exit(EXIT_SUCCESS);
+ return EXIT_SUCCESS;
bad:
if (aitop)
freeaddrinfo(aitop);
- exit(EXIT_FAILURE);
+ return EXIT_FAILURE;
+}
+EOF
+
+RECVMSG_WITH_MSG_PEEK_ALLOCATE_FD_TEST = <<'EOF'
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+ int ps[2], sv[2];
+ int ret;
+ ssize_t ss;
+ int s_fd, r_fd;
+ struct msghdr s_msg, r_msg;
+ union {
+ struct cmsghdr hdr;
+ char dummy[CMSG_SPACE(sizeof(int))];
+ } s_cmsg, r_cmsg;
+ struct iovec s_iov, r_iov;
+ char s_buf[1], r_buf[1];
+ struct stat s_statbuf, r_statbuf;
+
+ ret = pipe(ps);
+ if (ret == -1) { perror("pipe"); exit(EXIT_FAILURE); }
+
+ s_fd = ps[0];
+
+ ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sv);
+ if (ret == -1) { perror("socketpair"); exit(EXIT_FAILURE); }
+
+ s_msg.msg_name = NULL;
+ s_msg.msg_namelen = 0;
+ s_msg.msg_iov = &s_iov;
+ s_msg.msg_iovlen = 1;
+ s_msg.msg_control = &s_cmsg;
+ s_msg.msg_controllen = CMSG_SPACE(sizeof(int));;
+ s_msg.msg_flags = 0;
+
+ s_iov.iov_base = &s_buf;
+ s_iov.iov_len = sizeof(s_buf);
+
+ s_buf[0] = 'a';
+
+ s_cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
+ s_cmsg.hdr.cmsg_level = SOL_SOCKET;
+ s_cmsg.hdr.cmsg_type = SCM_RIGHTS;
+ memcpy(CMSG_DATA(&s_cmsg.hdr), (char *)&s_fd, sizeof(int));
+
+ ss = sendmsg(sv[0], &s_msg, 0);
+ if (ss == -1) { perror("sendmsg"); exit(EXIT_FAILURE); }
+
+ r_msg.msg_name = NULL;
+ r_msg.msg_namelen = 0;
+ r_msg.msg_iov = &r_iov;
+ r_msg.msg_iovlen = 1;
+ r_msg.msg_control = &r_cmsg;
+ r_msg.msg_controllen = CMSG_SPACE(sizeof(int));
+ r_msg.msg_flags = 0;
+
+ r_iov.iov_base = &r_buf;
+ r_iov.iov_len = sizeof(r_buf);
+
+ r_buf[0] = '0';
+
+ memset(&r_cmsg, 0xff, CMSG_SPACE(sizeof(int)));
+
+ ss = recvmsg(sv[1], &r_msg, MSG_PEEK);
+ if (ss == -1) { perror("recvmsg"); exit(EXIT_FAILURE); }
+
+ if (ss != 1) {
+ fprintf(stderr, "unexpected return value from recvmsg: %ld\n", (long)ss);
+ exit(EXIT_FAILURE);
+ }
+ if (r_buf[0] != 'a') {
+ fprintf(stderr, "unexpected return data from recvmsg: 0x%02x\n", r_buf[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (r_msg.msg_controllen < CMSG_LEN(sizeof(int))) {
+ fprintf(stderr, "unexpected: r_msg.msg_controllen < CMSG_LEN(sizeof(int)) not hold: %ld\n",
+ (long)r_msg.msg_controllen);
+ exit(EXIT_FAILURE);
+ }
+ if (r_cmsg.hdr.cmsg_len < CMSG_LEN(sizeof(int))) {
+ fprintf(stderr, "unexpected: r_cmsg.hdr.cmsg_len < CMSG_LEN(sizeof(int)) not hold: %ld\n",
+ (long)r_cmsg.hdr.cmsg_len);
+ exit(EXIT_FAILURE);
+ }
+ memcpy((char *)&r_fd, CMSG_DATA(&r_cmsg.hdr), sizeof(int));
+
+ if (r_fd < 0) {
+ fprintf(stderr, "negative r_fd: %d\n", r_fd);
+ exit(EXIT_FAILURE);
+ }
+
+ if (r_fd == s_fd) {
+ fprintf(stderr, "r_fd and s_fd is same: %d\n", r_fd);
+ exit(EXIT_FAILURE);
+ }
+
+ ret = fstat(s_fd, &s_statbuf);
+ if (ret == -1) { perror("fstat(s_fd)"); exit(EXIT_FAILURE); }
+
+ ret = fstat(r_fd, &r_statbuf);
+ if (ret == -1) { perror("fstat(r_fd)"); exit(EXIT_FAILURE); }
+
+ if (s_statbuf.st_dev != r_statbuf.st_dev ||
+ s_statbuf.st_ino != r_statbuf.st_ino) {
+ fprintf(stderr, "dev/ino doesn't match: s_fd:%ld/%ld r_fd:%ld/%ld\n",
+ (long)s_statbuf.st_dev, (long)s_statbuf.st_ino,
+ (long)r_statbuf.st_dev, (long)r_statbuf.st_ino);
+ exit(EXIT_FAILURE);
+ }
+
+ return EXIT_SUCCESS;
}
EOF
+
+def test_recvmsg_with_msg_peek_creates_fds(headers)
+ case RUBY_PLATFORM
+ when /linux/
+ # Linux 2.6.38 allocate fds by recvmsg with MSG_PEEK.
+ close_fds = true
+ when /bsd|darwin/
+ # FreeBSD 8.2.0, NetBSD 5 and MacOS X Snow Leopard doesn't
+ # allocate fds by recvmsg with MSG_PEEK.
+ # [ruby-dev:44189]
+ # http://bugs.ruby-lang.org/issues/5075
+ close_fds = false
+ when /cygwin/
+ # Cygwin doesn't support fd passing.
+ # http://cygwin.com/ml/cygwin/2003-09/msg01808.html
+ close_fds = false
+ else
+ close_fds = nil
+ end
+ if !CROSS_COMPILING
+ if checking_for("recvmsg() with MSG_PEEK allocate file descriptors") {
+ try_run(cpp_include(headers) + RECVMSG_WITH_MSG_PEEK_ALLOCATE_FD_TEST)
+ }
+ if close_fds == false
+ warn "unexpected fd-passing recvmsg() with MSG_PEEK behavor on #{RUBY_PLATFORM}: fd allocation unexpected."
+ elsif close_fds == nil
+ puts "info: #{RUBY_PLATFORM} recvmsg() with MSG_PEEK allocates fds on fd-passing."
+ end
+ close_fds = true
+ else
+ if close_fds == true
+ warn "unexpected fd-passing recvmsg() with MSG_PEEK behavor on #{RUBY_PLATFORM}: fd allocation expected."
+ elsif close_fds == nil
+ puts "info: #{RUBY_PLATFORM}: recvmsg() with MSG_PEEK doesn't allocates fds on fd-passing."
+ end
+ close_fds = false
+ end
+ end
+ if close_fds == nil
+ abort <<EOS
+Fatal: cannot test fd-passing recvmsg() with MSG_PEEK behavor
+because cross-compilation for #{RUBY_PLATFORM}.
+If recvmsg() with MSG_PEEK allocates fds on fd passing:
+--enable-close-fds-by-recvmsg-with-peek
+If recvmsg() with MSG_PEEK doesn't allocate fds on fd passing:
+--disable-close-fds-by-recvmsg-with-peek
+EOS
+ end
+ close_fds
+end
+
+$INCFLAGS << " -I$(topdir) -I$(top_srcdir)"
+
+if /darwin/ =~ RUBY_PLATFORM
+ # For IPv6 extension header access on OS X 10.7+ [Bug #8517]
+ $CFLAGS << " -D__APPLE_USE_RFC_3542"
end
-if ipv6 and not getaddr_info_ok
- abort <<EOS
+
+headers = []
+unless $mswin or $mingw
+ headers = %w<sys/types.h netdb.h string.h sys/socket.h netinet/in.h>
+end
+
+%w[
+ sys/uio.h
+ xti.h
+ netinet/in_systm.h
+ netinet/tcp.h
+ netinet/tcp_fsm.h
+ netinet/udp.h
+ arpa/inet.h
+ netpacket/packet.h
+ net/ethernet.h
+ sys/un.h
+ afunix.h
+ ifaddrs.h
+ sys/ioctl.h
+ sys/sockio.h
+ net/if.h
+ sys/param.h
+ sys/ucred.h
+ ucred.h
+ net/if_dl.h
+ arpa/nameser.h
+ resolv.h
+ pthread.h
+ sched.h
+].each {|h|
+ if have_header(h, headers)
+ headers << h
+ end
+}
+
+have_struct_member("struct sockaddr", "sa_len", headers) # 4.4BSD
+have_struct_member("struct sockaddr_in", "sin_len", headers) # 4.4BSD
+have_struct_member("struct sockaddr_in6", "sin6_len", headers) # 4.4BSD
+
+if have_type("struct sockaddr_un", headers) # POSIX
+ have_struct_member("struct sockaddr_un", "sun_len", headers) # 4.4BSD
+end
+
+have_type("struct sockaddr_dl", headers) # AF_LINK address. 4.4BSD since Net2
+
+have_type("struct sockaddr_storage", headers)
+
+have_type("struct addrinfo", headers)
+
+def check_socklen(headers)
+ def (fmt = "none").%(x)
+ x || self
+ end
+ s = checking_for("RSTRING_SOCKLEN", fmt) do
+ if try_static_assert("sizeof(socklen_t) >= sizeof(long)", headers)
+ "RSTRING_LEN"
+ else
+ "RSTRING_LENINT"
+ end
+ end
+ $defs << "-DRSTRING_SOCKLEN=(socklen_t)"+s
+end
+
+if have_type("socklen_t", headers)
+ check_socklen(headers)
+end
+
+have_type("struct in_pktinfo", headers) {|src|
+ src.sub(%r'^/\*top\*/', '\&'"\n#if defined(IPPROTO_IP) && defined(IP_PKTINFO)") <<
+ "#else\n" << "#error\n" << ">>>>>> no in_pktinfo <<<<<<\n" << "#endif\n"
+} and have_struct_member("struct in_pktinfo", "ipi_spec_dst", headers)
+have_type("struct in6_pktinfo", headers) {|src|
+ src.sub(%r'^/\*top\*/', '\&'"\n#if defined(IPPROTO_IPV6) && defined(IPV6_PKTINFO)") <<
+ "#else\n" << "#error\n" << ">>>>>> no in6_pktinfo <<<<<<\n" << "#endif\n"
+}
+
+have_type("struct sockcred", headers)
+have_type("struct cmsgcred", headers)
+
+have_type("struct ip_mreq", headers) # 4.4BSD
+have_type("struct ip_mreqn", headers) # Linux 2.4
+have_type("struct ipv6_mreq", headers) # RFC 3493
+
+have_msg_control = nil
+have_msg_control = have_struct_member('struct msghdr', 'msg_control', headers) unless $mswin or $mingw
+have_struct_member('struct msghdr', 'msg_accrights', headers)
+
+if have_type("struct tcp_info", headers)
+ have_const("TCP_ESTABLISHED", headers)
+ have_const("TCP_SYN_SENT", headers)
+ have_const("TCP_SYN_RECV", headers)
+ have_const("TCP_FIN_WAIT1", headers)
+ have_const("TCP_FIN_WAIT2", headers)
+ have_const("TCP_TIME_WAIT", headers)
+ have_const("TCP_CLOSE", headers)
+ have_const("TCP_CLOSE_WAIT", headers)
+ have_const("TCP_LAST_ACK", headers)
+ have_const("TCP_LISTEN", headers)
+ have_const("TCP_CLOSING", headers)
+ have_struct_member('struct tcp_info', 'tcpi_state', headers)
+ if /solaris/ !~ RUBY_PLATFORM
+ have_struct_member('struct tcp_info', 'tcpi_ca_state', headers)
+ end
+ have_struct_member('struct tcp_info', 'tcpi_retransmits', headers)
+ have_struct_member('struct tcp_info', 'tcpi_probes', headers)
+ have_struct_member('struct tcp_info', 'tcpi_backoff', headers)
+ have_struct_member('struct tcp_info', 'tcpi_options', headers)
+ have_struct_member('struct tcp_info', 'tcpi_snd_wscale', headers)
+ have_struct_member('struct tcp_info', 'tcpi_rcv_wscale', headers)
+ have_struct_member('struct tcp_info', 'tcpi_rto', headers)
+ have_struct_member('struct tcp_info', 'tcpi_ato', headers)
+ have_struct_member('struct tcp_info', 'tcpi_snd_mss', headers)
+ have_struct_member('struct tcp_info', 'tcpi_rcv_mss', headers)
+ have_struct_member('struct tcp_info', 'tcpi_unacked', headers)
+ have_struct_member('struct tcp_info', 'tcpi_sacked', headers)
+ have_struct_member('struct tcp_info', 'tcpi_lost', headers)
+ have_struct_member('struct tcp_info', 'tcpi_retrans', headers)
+ have_struct_member('struct tcp_info', 'tcpi_fackets', headers)
+ have_struct_member('struct tcp_info', 'tcpi_last_data_sent', headers)
+ have_struct_member('struct tcp_info', 'tcpi_last_ack_sent', headers)
+ have_struct_member('struct tcp_info', 'tcpi_last_data_recv', headers)
+ have_struct_member('struct tcp_info', 'tcpi_last_ack_recv', headers)
+ have_struct_member('struct tcp_info', 'tcpi_pmtu', headers)
+ have_struct_member('struct tcp_info', 'tcpi_rcv_ssthresh', headers)
+ have_struct_member('struct tcp_info', 'tcpi_rtt', headers)
+ have_struct_member('struct tcp_info', 'tcpi_rttvar', headers)
+ have_struct_member('struct tcp_info', 'tcpi_snd_ssthresh', headers)
+ have_struct_member('struct tcp_info', 'tcpi_snd_cwnd', headers)
+ have_struct_member('struct tcp_info', 'tcpi_advmss', headers)
+ have_struct_member('struct tcp_info', 'tcpi_reordering', headers)
+ have_struct_member('struct tcp_info', 'tcpi_rcv_rtt', headers)
+ have_struct_member('struct tcp_info', 'tcpi_rcv_space', headers)
+ have_struct_member('struct tcp_info', 'tcpi_total_retrans', headers)
+
+ # FreeBSD extension
+ have_struct_member('struct tcp_info', 'tcpi_snd_wnd', headers)
+ have_struct_member('struct tcp_info', 'tcpi_snd_bwnd', headers)
+ have_struct_member('struct tcp_info', 'tcpi_snd_nxt', headers)
+ have_struct_member('struct tcp_info', 'tcpi_rcv_nxt', headers)
+ have_struct_member('struct tcp_info', 'tcpi_toe_tid', headers)
+ have_struct_member('struct tcp_info', 'tcpi_snd_rexmitpack', headers)
+ have_struct_member('struct tcp_info', 'tcpi_rcv_ooopack', headers)
+ have_struct_member('struct tcp_info', 'tcpi_snd_zerowin', headers)
+end
+
+case RUBY_PLATFORM
+when /mswin(32|64)|mingw/
+ test_func = "WSACleanup"
+ have_library("iphlpapi")
+ have_library("ws2_32", "WSACleanup", headers)
+when /cygwin/
+ test_func = "socket(0,0,0)"
+when /haiku/
+ test_func = "socket(0,0,0)"
+ have_library("network", "socket(0,0,0)", headers)
+else
+ test_func = "socket(0,0,0)"
+ have_library("nsl", 't_open("", 0, (struct t_info *)NULL)', headers) # SunOS
+ have_library("socket", "socket(0,0,0)", headers) # SunOS
+end
+
+if have_func(test_func, headers)
+
+ have_func("sendmsg(0, (struct msghdr *)NULL, 0)", headers) # POSIX
+ have_recvmsg = have_func("recvmsg(0, (struct msghdr *)NULL, 0)", headers) # POSIX
+
+ have_func("freehostent((struct hostent *)NULL)", headers) # RFC 2553
+ have_func("freeaddrinfo((struct addrinfo *)NULL)", headers) # RFC 2553
+
+ if /haiku/ !~ RUBY_PLATFORM and
+ have_func("gai_strerror(0)", headers) # POSIX
+ if checking_for("gai_strerror() returns const pointer") {!try_compile(<<EOF)}
+#{cpp_include(headers)}
+#include <stdlib.h>
+void
+conftest_gai_strerror_is_const()
+{
+ *gai_strerror(0) = 0;
+}
+EOF
+ $defs << "-DGAI_STRERROR_CONST"
+ end
+ end
+
+ have_func("accept4", headers)
+
+ have_func('inet_ntop(0, (const void *)0, (char *)0, 0)', headers) or
+ have_func("inet_ntoa(*(struct in_addr *)NULL)", headers)
+ have_func('inet_pton(0, "", (void *)0)', headers) or
+ have_func('inet_aton("", (struct in_addr *)0)', headers)
+ have_func('getservbyport(0, "")', headers)
+ have_func("getifaddrs((struct ifaddrs **)NULL)", headers)
+ have_struct_member("struct if_data", "ifi_vhid", headers) # FreeBSD
+
+ have_func("getpeereid", headers)
+
+ have_func("getpeerucred(0, (ucred_t **)NULL)", headers) # SunOS
+
+ have_func_decl = proc do |name, headers|
+ # check if there is a declaration of <name> by trying to declare
+ # both "int <name>(void)" and "void <name>(void)"
+ # (at least one attempt should fail if there is a declaration)
+ if !checking_for("declaration of #{name}()") {!%w[int void].all? {|ret| try_compile(<<EOF)}}
+#{cpp_include(headers)}
+#{ret} #{name}(void);
+EOF
+ $defs << "-DNEED_#{name.tr_cpp}_DECL"
+ end
+ end
+ if have_func('if_indextoname(0, "")', headers)
+ have_func_decl["if_indextoname", headers]
+ end
+ if have_func('if_nametoindex("")', headers)
+ have_func_decl["if_nametoindex", headers]
+ end
+
+ have_func("hsterror", headers)
+ have_func('getipnodebyname("", 0, 0, (int *)0)', headers) # RFC 2553
+ have_func('gethostbyname2("", 0)', headers) # RFC 2133
+ have_func("socketpair(0, 0, 0, 0)", headers)
+ unless have_func("gethostname((char *)0, 0)", headers)
+ have_func("uname((struct utsname *)NULL)", headers)
+ end
+
+ ipv6 = false
+ default_ipv6 = /haiku/ !~ RUBY_PLATFORM
+ if enable_config("ipv6", default_ipv6)
+ if checking_for("ipv6") {try_link(AF_INET6_SOCKET_CREATION_TEST)}
+ $defs << "-DENABLE_IPV6" << "-DINET6"
+ ipv6 = true
+ end
+ end
+
+ if ipv6
+ if $mingw
+ $CPPFLAGS << " -D_WIN32_WINNT=0x501" unless $CPPFLAGS.include?("_WIN32_WINNT")
+ end
+ ipv6lib = nil
+ class << (fmt = "unknown")
+ def %(s) s || self end
+ end
+ idirs, ldirs = dir_config("inet6", %w[/usr/inet6 /usr/local/v6].find {|d| File.directory?(d)})
+ checking_for("ipv6 type", fmt) do
+ if have_macro("IPV6_INRIA_VERSION", "netinet/in.h")
+ "inria"
+ elsif have_macro("__KAME__", "netinet/in.h")
+ have_library(ipv6lib = "inet6")
+ "kame"
+ elsif have_macro("_TOSHIBA_INET6", "sys/param.h")
+ have_library(ipv6lib = "inet6") and "toshiba"
+ elsif have_macro("__V6D__", "sys/v6config.h")
+ have_library(ipv6lib = "v6") and "v6d"
+ elsif have_macro("_ZETA_MINAMI_INET6", "sys/param.h")
+ have_library(ipv6lib = "inet6") and "zeta"
+ elsif have_library("inet6")
+ "inet6"
+ end
+ end or not ipv6lib or abort <<EOS
+
+Fatal: no #{ipv6lib} library found. cannot continue.
+You need to fetch lib#{ipv6lib}.a from appropriate
+ipv6 kit and compile beforehand.
+EOS
+ end
+
+ if !have_macro("IPPROTO_IPV6", headers) && have_const("IPPROTO_IPV6", headers)
+ File.read(File.join(File.dirname(__FILE__), "mkconstants.rb")).sub(/\A.*^__END__$/m, '').split(/\r?\n/).grep(/\AIPPROTO_\w*/){$&}.each {|name|
+ have_const(name, headers) unless $defs.include?("-DHAVE_CONST_#{name.upcase}")
+ }
+ end
+
+ if enable_config("close-fds-by-recvmsg-with-peek") {
+ have_msg_control && have_recvmsg &&
+ have_const('AF_UNIX', headers) && have_const('SCM_RIGHTS', headers) &&
+ test_recvmsg_with_msg_peek_creates_fds(headers)
+ }
+ $defs << "-DFD_PASSING_WORK_WITH_RECVMSG_MSG_PEEK"
+ end
+
+ case enable_config("wide-getaddrinfo")
+ when true
+ getaddr_info_ok = :wide
+ when nil, false
+ getaddr_info_ok = (:wide if getaddr_info_ok.nil?)
+ if have_func("getnameinfo", headers) and have_func("getaddrinfo", headers)
+ if CROSS_COMPILING ||
+ $mingw || $mswin ||
+ checking_for("system getaddrinfo working") {
+ try_run(cpp_include(headers) + GETADDRINFO_GETNAMEINFO_TEST)
+ }
+ getaddr_info_ok = :os
+ end
+ end
+ else
+ raise "unexpected enable_config() value"
+ end
+
+ if ipv6 and not getaddr_info_ok
+ abort <<EOS
Fatal: --enable-ipv6 is specified, and your OS seems to support IPv6 feature.
But your getaddrinfo() and getnameinfo() are appeared to be broken. Sorry,
you cannot compile IPv6 socket classes with broken these functions.
You can try --enable-wide-getaddrinfo.
EOS
-end
+ end
-case with_config("lookup-order-hack", "UNSPEC")
-when "INET"
- $defs << "-DLOOKUP_ORDER_HACK_INET"
-when "INET6"
- $defs << "-DLOOKUP_ORDER_HACK_INET6"
-when "UNSPEC"
- # nothing special
-else
- abort <<EOS
+ case with_config("lookup-order-hack", "UNSPEC")
+ when "INET"
+ $defs << "-DLOOKUP_ORDER_HACK_INET"
+ when "INET6"
+ $defs << "-DLOOKUP_ORDER_HACK_INET6"
+ when "UNSPEC"
+ # nothing special
+ else
+ abort <<EOS
Fatal: invalid value for --with-lookup-order-hack (expected INET, INET6 or UNSPEC)
EOS
-end
+ end
-$objs = ["socket.#{$OBJEXT}"]
+ $objs = [
+ "init.#{$OBJEXT}",
+ "constants.#{$OBJEXT}",
+ "basicsocket.#{$OBJEXT}",
+ "socket.#{$OBJEXT}",
+ "ipsocket.#{$OBJEXT}",
+ "tcpsocket.#{$OBJEXT}",
+ "tcpserver.#{$OBJEXT}",
+ "sockssocket.#{$OBJEXT}",
+ "udpsocket.#{$OBJEXT}",
+ "unixsocket.#{$OBJEXT}",
+ "unixserver.#{$OBJEXT}",
+ "option.#{$OBJEXT}",
+ "ancdata.#{$OBJEXT}",
+ "raddrinfo.#{$OBJEXT}",
+ "ifaddr.#{$OBJEXT}"
+ ]
-unless getaddr_info_ok and have_func("getnameinfo", "netdb.h") and have_func("getaddrinfo", "netdb.h")
- if have_struct_member("struct in6_addr", "s6_addr8", headers)
- $defs[-1] = "-DHAVE_ADDR8"
+ if getaddr_info_ok == :wide
+ if !have_type("struct in6_addr", headers) and have_type("struct in_addr6", headers)
+ $defs.pop(2)
+ $defs << "-Din_addr6=in6_addr"
+ end
+ if have_struct_member("struct in6_addr", "s6_addr8", headers)
+ $defs[-1] = "-Ds6_addr=s6_addr8"
+ end
+ if ipv6 == "kame" && have_struct_member("struct in6_addr", "s6_addr32", headers)
+ $defs[-1] = "-DFAITH"
+ end
+ $CPPFLAGS="-I. "+$CPPFLAGS
+ $objs += ["getaddrinfo.#{$OBJEXT}"]
+ $objs += ["getnameinfo.#{$OBJEXT}"]
+ $defs << "-DGETADDRINFO_EMU"
end
- $CPPFLAGS="-I. "+$CPPFLAGS
- $objs += ["getaddrinfo.#{$OBJEXT}"]
- $objs += ["getnameinfo.#{$OBJEXT}"]
- have_func("inet_ntop") or have_func("inet_ntoa")
- have_func("inet_pton") or have_func("inet_aton")
- have_func("getservbyport")
- have_header("arpa/inet.h")
- have_header("arpa/nameser.h")
- have_header("resolv.h")
-end
-unless have_type("socklen_t", headers)
- $defs << "-Dsocklen_t=int"
-end
+ # workaround for recent Windows SDK
+ $defs << "-DIPPROTO_IPV6=IPPROTO_IPV6" if $defs.include?("-DHAVE_CONST_IPPROTO_IPV6") && !have_macro("IPPROTO_IPV6")
-have_header("sys/un.h")
-have_header("sys/uio.h")
+ $distcleanfiles << "constants.h" << "constdefs.*"
-if have_func(test_func)
- have_func("hsterror")
- have_func("getipnodebyname") or have_func("gethostbyname2")
- have_func("socketpair")
- unless have_func("gethostname")
- have_func("uname")
- end
if enable_config("socks", ENV["SOCKS_SERVER"])
if have_library("socks5", "SOCKSinit")
$defs << "-DSOCKS5" << "-DSOCKS"
- elsif have_library("socks", "Rconnect")
+ elsif have_library("socksd", "Rconnect") || have_library("socks", "Rconnect")
$defs << "-DSOCKS"
end
end
+
+ hdr = "netinet6/in6.h"
+ /darwin/ =~ RUBY_PLATFORM and
+ checking_for("if apple's #{hdr} needs s6_addr patch") {!try_compile(<<"SRC", nil, :werror=>true)} and
+#include <netinet/in.h>
+int t(struct in6_addr *addr) {return IN6_IS_ADDR_UNSPECIFIED(addr);}
+SRC
+ checking_for("fixing apple's #{hdr}", "%s") do
+ file = xpopen(%w"clang -include netinet/in.h -E -xc -", in: IO::NULL) do |f|
+ re = %r[^# *\d+ *"(.*/netinet/in\.h)"]
+ Logging.message " grep(#{re})\n"
+ f.read[re, 1]
+ end
+ Logging.message "Substitute from #{file}\n"
+
+ in6 = File.read(file)
+ if in6.gsub!(/\*\(const\s+__uint32_t\s+\*\)\(const\s+void\s+\*\)\(&(\(\w+\))->s6_addr\[(\d+)\]\)/) do
+ i, r = $2.to_i.divmod(4)
+ if r.zero?
+ "#$1->__u6_addr.__u6_addr32[#{i}]"
+ else
+ $&
+ end
+ end
+ FileUtils.mkdir_p(File.dirname(hdr))
+ File.write(hdr, in6)
+ $distcleanfiles << hdr
+ $distcleandirs << File.dirname(hdr)
+ "done"
+ else
+ "not needed"
+ end
+ end
+
+ have_func("pthread_create")
+ have_func("pthread_detach")
+ have_func("pthread_attr_setdetachstate")
+
+ $VPATH << '$(topdir)' << '$(top_srcdir)'
create_makefile("socket")
end
diff --git a/ext/socket/getaddrinfo.c b/ext/socket/getaddrinfo.c
index 9fb4ebcb06..9a65490b1d 100644
--- a/ext/socket/getaddrinfo.c
+++ b/ext/socket/getaddrinfo.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -13,7 +13,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -38,15 +38,14 @@
* - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag.
*/
-#include "config.h"
+#include "ruby/config.h"
+#ifdef RUBY_EXTCONF_H
+#include RUBY_EXTCONF_H
+#endif
#include <sys/types.h>
-#if !defined(_WIN32) && !defined(__VMS)
+#ifndef _WIN32
#include <sys/param.h>
-#if defined(__BEOS__)
-# include <net/socket.h>
-#else
-# include <sys/socket.h>
-#endif
+#include <sys/socket.h>
#include <netinet/in.h>
#if defined(HAVE_ARPA_INET_H)
#include <arpa/inet.h>
@@ -62,13 +61,9 @@
#include <resolv.h>
#endif
#include <unistd.h>
-#elif defined(__VMS )
-#include <socket.h>
-#include <inet.h>
-#include <in.h>
-#include <netdb.h>
#else
#include <winsock2.h>
+#include <ws2tcpip.h>
#include <io.h>
#endif
#include <string.h>
@@ -81,13 +76,13 @@
#include <socks.h>
#endif
+#ifndef HAVE_TYPE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
#include "addrinfo.h"
#include "sockport.h"
-#if defined(__KAME__) && defined(INET6)
-# define FAITH
-#endif
-
#define SUCCESS 0
#define ANY 0
#define YES 1
@@ -100,42 +95,42 @@ static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
static const char in_addrany[] = { 0, 0, 0, 0 };
static const char in6_addrany[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-static const char in_loopback[] = { 127, 0, 0, 1 };
+static const char in_loopback[] = { 127, 0, 0, 1 };
static const char in6_loopback[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
struct sockinet {
- u_char si_len;
- u_char si_family;
- u_short si_port;
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
};
static const struct afd {
- int a_af;
- int a_addrlen;
- int a_socklen;
- int a_off;
- const char *a_addrany;
- const char *a_loopback;
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
+ const char *a_addrany;
+ const char *a_loopback;
} afdl [] = {
#ifdef INET6
#define N_INET6 0
- {PF_INET6, sizeof(struct in6_addr),
- sizeof(struct sockaddr_in6),
- offsetof(struct sockaddr_in6, sin6_addr),
- in6_addrany, in6_loopback},
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr),
+ in6_addrany, in6_loopback},
#define N_INET 1
#else
#define N_INET 0
#endif
- {PF_INET, sizeof(struct in_addr),
- sizeof(struct sockaddr_in),
- offsetof(struct sockaddr_in, sin_addr),
- in_addrany, in_loopback},
- {0, 0, 0, 0, NULL, NULL},
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr),
+ in_addrany, in_loopback},
+ {0, 0, 0, 0, NULL, NULL},
};
#ifdef INET6
@@ -145,554 +140,532 @@ static const struct afd {
#endif
static int get_name __P((const char *, const struct afd *,
- struct addrinfo **, char *, struct addrinfo *,
- int));
+ struct addrinfo **, char *, struct addrinfo *,
+ int));
static int get_addr __P((const char *, int, struct addrinfo **,
- struct addrinfo *, int));
+ struct addrinfo *, int));
static int str_isnumber __P((const char *));
-
+
+#ifndef HAVE_GAI_STRERROR
static const char *const ai_errlist[] = {
- "success.",
- "address family for hostname not supported.", /* EAI_ADDRFAMILY */
- "temporary failure in name resolution.", /* EAI_AGAIN */
- "invalid value for ai_flags.", /* EAI_BADFLAGS */
- "non-recoverable failure in name resolution.", /* EAI_FAIL */
- "ai_family not supported.", /* EAI_FAMILY */
- "memory allocation failure.", /* EAI_MEMORY */
- "no address associated with hostname.", /* EAI_NODATA */
- "hostname nor servname provided, or not known.",/* EAI_NONAME */
- "servname not supported for ai_socktype.", /* EAI_SERVICE */
- "ai_socktype not supported.", /* EAI_SOCKTYPE */
- "system error returned in errno.", /* EAI_SYSTEM */
- "invalid value for hints.", /* EAI_BADHINTS */
- "resolved protocol is unknown.", /* EAI_PROTOCOL */
- "unknown error.", /* EAI_MAX */
+ "success.",
+ "address family for hostname not supported.", /* EAI_ADDRFAMILY */
+ "temporary failure in name resolution.", /* EAI_AGAIN */
+ "invalid value for ai_flags.", /* EAI_BADFLAGS */
+ "non-recoverable failure in name resolution.", /* EAI_FAIL */
+ "ai_family not supported.", /* EAI_FAMILY */
+ "memory allocation failure.", /* EAI_MEMORY */
+ "no address associated with hostname.", /* EAI_NODATA */
+ "hostname nor servname provided, or not known.",/* EAI_NONAME */
+ "servname not supported for ai_socktype.", /* EAI_SERVICE */
+ "ai_socktype not supported.", /* EAI_SOCKTYPE */
+ "system error returned in errno.", /* EAI_SYSTEM */
+ "invalid value for hints.", /* EAI_BADHINTS */
+ "resolved protocol is unknown.", /* EAI_PROTOCOL */
+ "unknown error.", /* EAI_MAX */
};
+#endif
#define GET_CANONNAME(ai, str) \
if (pai->ai_flags & AI_CANONNAME) {\
- if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
- strcpy((ai)->ai_canonname, (str));\
- } else {\
- error = EAI_MEMORY;\
- goto free;\
- }\
+ if (((ai)->ai_canonname = strdup(str)) == NULL) {\
+ error = EAI_MEMORY;\
+ goto free;\
+ }\
}
#define GET_AI(ai, afd, addr, port) {\
- char *p;\
- if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
- ((afd)->a_socklen)))\
- == NULL) {\
- error = EAI_MEMORY;\
- goto free;\
- }\
- memcpy(ai, pai, sizeof(struct addrinfo));\
- (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
- memset((ai)->ai_addr, 0, (afd)->a_socklen);\
- SET_SA_LEN((ai)->ai_addr, (ai)->ai_addrlen = (afd)->a_socklen);\
- (ai)->ai_addr->sa_family = (ai)->ai_family = (afd)->a_af;\
- ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
- p = (char *)((ai)->ai_addr);\
- memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
+ char *p;\
+ if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
+ ((afd)->a_socklen)))\
+ == NULL) {\
+ error = EAI_MEMORY;\
+ goto free;\
+ }\
+ memcpy((ai), pai, sizeof(struct addrinfo));\
+ (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
+ (ai)->ai_family = (afd)->a_af;\
+ (ai)->ai_addrlen = (afd)->a_socklen;\
+ INIT_SOCKADDR((ai)->ai_addr, (afd)->a_af, (afd)->a_socklen);\
+ ((struct sockinet *)(ai)->ai_addr)->si_port = (port);\
+ p = (char *)((ai)->ai_addr);\
+ memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
}
#define ERR(err) { error = (err); goto bad; }
-#if defined __UCLIBC__
+#ifndef HAVE_GAI_STRERROR
+#ifdef GAI_STRERROR_CONST
const
#endif
char *
-gai_strerror(ecode)
- int ecode;
+gai_strerror(int ecode)
{
- if (ecode < 0 || ecode > EAI_MAX)
- ecode = EAI_MAX;
- return (char *)ai_errlist[ecode];
+ if (ecode < 0 || ecode > EAI_MAX)
+ ecode = EAI_MAX;
+ return (char *)ai_errlist[ecode];
}
+#endif
void
-freeaddrinfo(ai)
- struct addrinfo *ai;
+freeaddrinfo(struct addrinfo *ai)
{
- struct addrinfo *next;
-
- do {
- next = ai->ai_next;
- if (ai->ai_canonname)
- free(ai->ai_canonname);
- /* no need to free(ai->ai_addr) */
- free(ai);
- } while ((ai = next) != NULL);
+ struct addrinfo *next;
+
+ do {
+ next = ai->ai_next;
+ free(ai->ai_canonname);
+ /* no need to free(ai->ai_addr) */
+ free(ai);
+ } while ((ai = next) != NULL);
}
static int
-str_isnumber(p)
- const char *p;
+str_isnumber(const char *p)
{
- char *q = (char *)p;
- while (*q) {
- if (! isdigit(*q))
- return NO;
- q++;
- }
- return YES;
+ char *q = (char *)p;
+ while (*q) {
+ if (! isdigit(*q))
+ return NO;
+ q++;
+ }
+ return YES;
}
#ifndef HAVE_INET_PTON
static int
-inet_pton(af, hostname, pton)
- int af;
- const char *hostname;
- void *pton;
+inet_pton(int af, const char *hostname, void *pton)
{
- struct in_addr in;
+ struct in_addr in;
#ifdef HAVE_INET_ATON
- if (!inet_aton(hostname, &in))
- return 0;
+ if (!inet_aton(hostname, &in))
+ return 0;
#else
- int d1, d2, d3, d4;
- char ch;
-
- if (sscanf(hostname, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
- 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
- 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
- in.s_addr = htonl(
- ((long) d1 << 24) | ((long) d2 << 16) |
- ((long) d3 << 8) | ((long) d4 << 0));
- }
- else {
- return 0;
- }
-#endif
- memcpy(pton, &in, sizeof(in));
- return 1;
+ int d1, d2, d3, d4;
+ char ch;
+
+ if (sscanf(hostname, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
+ 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
+ 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
+ in.s_addr = htonl(
+ ((long) d1 << 24) | ((long) d2 << 16) |
+ ((long) d3 << 8) | ((long) d4 << 0));
+ }
+ else {
+ return 0;
+ }
+#endif
+ memcpy(pton, &in, sizeof(in));
+ return 1;
}
#endif
int
-getaddrinfo(hostname, servname, hints, res)
- const char *hostname, *servname;
- const struct addrinfo *hints;
- struct addrinfo **res;
+getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
{
- struct addrinfo sentinel;
- struct addrinfo *top = NULL;
- struct addrinfo *cur;
- int i, error = 0;
- char pton[PTON_MAX];
- struct addrinfo ai;
- struct addrinfo *pai;
- u_short port;
+ struct addrinfo sentinel;
+ struct addrinfo *top = NULL;
+ struct addrinfo *cur;
+ int i, error = 0;
+ char pton[PTON_MAX];
+ struct addrinfo ai;
+ struct addrinfo *pai;
+ u_short port;
#ifdef FAITH
- static int firsttime = 1;
-
- if (firsttime) {
- /* translator hack */
- {
- char *q = getenv("GAI");
- if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
- translate = YES;
- }
- firsttime = 0;
- }
-#endif
-
- /* initialize file static vars */
- sentinel.ai_next = NULL;
- cur = &sentinel;
- pai = &ai;
- pai->ai_flags = 0;
- pai->ai_family = PF_UNSPEC;
- pai->ai_socktype = ANY;
- pai->ai_protocol = ANY;
- pai->ai_addrlen = 0;
- pai->ai_canonname = NULL;
- pai->ai_addr = NULL;
- pai->ai_next = NULL;
- port = ANY;
-
- if (hostname == NULL && servname == NULL)
- return EAI_NONAME;
- if (hints) {
- /* error check for hints */
- if (hints->ai_addrlen || hints->ai_canonname ||
- hints->ai_addr || hints->ai_next)
- ERR(EAI_BADHINTS); /* xxx */
- if (hints->ai_flags & ~AI_MASK)
- ERR(EAI_BADFLAGS);
- switch (hints->ai_family) {
- case PF_UNSPEC:
- case PF_INET:
+ static int firsttime = 1;
+
+ if (firsttime) {
+ /* translator hack */
+ {
+ char *q = getenv("GAI");
+ if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
+ translate = YES;
+ }
+ firsttime = 0;
+ }
+#endif
+
+ /* initialize file static vars */
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+ pai = &ai;
+ pai->ai_flags = 0;
+ pai->ai_family = PF_UNSPEC;
+ pai->ai_socktype = ANY;
+ pai->ai_protocol = ANY;
+ pai->ai_addrlen = 0;
+ pai->ai_canonname = NULL;
+ pai->ai_addr = NULL;
+ pai->ai_next = NULL;
+ port = ANY;
+
+ if (hostname == NULL && servname == NULL)
+ return EAI_NONAME;
+ if (hints) {
+ /* error check for hints */
+ if (hints->ai_addrlen || hints->ai_canonname ||
+ hints->ai_addr || hints->ai_next)
+ ERR(EAI_BADHINTS); /* xxx */
+ if (hints->ai_flags & ~AI_MASK)
+ ERR(EAI_BADFLAGS);
+ switch (hints->ai_family) {
+ case PF_UNSPEC:
+ case PF_INET:
#ifdef INET6
- case PF_INET6:
-#endif
- break;
- default:
- ERR(EAI_FAMILY);
- }
- memcpy(pai, hints, sizeof(*pai));
- switch (pai->ai_socktype) {
- case ANY:
- switch (pai->ai_protocol) {
- case ANY:
- break;
- case IPPROTO_UDP:
- pai->ai_socktype = SOCK_DGRAM;
- break;
- case IPPROTO_TCP:
- pai->ai_socktype = SOCK_STREAM;
- break;
- default:
+ case PF_INET6:
+#endif
+ break;
+ default:
+ ERR(EAI_FAMILY);
+ }
+ memcpy(pai, hints, sizeof(*pai));
+ switch (pai->ai_socktype) {
+ case ANY:
+ switch (pai->ai_protocol) {
+ case ANY:
+ break;
+ case IPPROTO_UDP:
+ pai->ai_socktype = SOCK_DGRAM;
+ break;
+ case IPPROTO_TCP:
+ pai->ai_socktype = SOCK_STREAM;
+ break;
+ default:
#if defined(SOCK_RAW)
- pai->ai_socktype = SOCK_RAW;
+ pai->ai_socktype = SOCK_RAW;
#endif
- break;
- }
- break;
+ break;
+ }
+ break;
#if defined(SOCK_RAW)
- case SOCK_RAW:
- break;
-#endif
- case SOCK_DGRAM:
- if (pai->ai_protocol != IPPROTO_UDP &&
- pai->ai_protocol != ANY)
- ERR(EAI_BADHINTS); /*xxx*/
- pai->ai_protocol = IPPROTO_UDP;
- break;
- case SOCK_STREAM:
- if (pai->ai_protocol != IPPROTO_TCP &&
- pai->ai_protocol != ANY)
- ERR(EAI_BADHINTS); /*xxx*/
- pai->ai_protocol = IPPROTO_TCP;
- break;
- default:
- ERR(EAI_SOCKTYPE);
- break;
- }
- }
-
- /*
- * service port
- */
- if (servname) {
- if (str_isnumber(servname)) {
- if (pai->ai_socktype == ANY) {
- /* caller accept *ANY* socktype */
- pai->ai_socktype = SOCK_DGRAM;
- pai->ai_protocol = IPPROTO_UDP;
- }
- port = htons((unsigned short)atoi(servname));
- } else {
- struct servent *sp;
- char *proto;
-
- proto = NULL;
- switch (pai->ai_socktype) {
- case ANY:
- proto = NULL;
- break;
- case SOCK_DGRAM:
- proto = "udp";
- break;
- case SOCK_STREAM:
- proto = "tcp";
- break;
- default:
- fprintf(stderr, "panic!\n");
- break;
- }
- if ((sp = getservbyname((char*)servname, proto)) == NULL)
- ERR(EAI_SERVICE);
- port = sp->s_port;
- if (pai->ai_socktype == ANY)
- if (strcmp(sp->s_proto, "udp") == 0) {
- pai->ai_socktype = SOCK_DGRAM;
- pai->ai_protocol = IPPROTO_UDP;
- } else if (strcmp(sp->s_proto, "tcp") == 0) {
- pai->ai_socktype = SOCK_STREAM;
- pai->ai_protocol = IPPROTO_TCP;
- } else
- ERR(EAI_PROTOCOL); /*xxx*/
- }
- }
-
- /*
- * hostname == NULL.
- * passive socket -> anyaddr (0.0.0.0 or ::)
- * non-passive socket -> localhost (127.0.0.1 or ::1)
- */
- if (hostname == NULL) {
- const struct afd *afd;
- int s;
-
- for (afd = &afdl[0]; afd->a_af; afd++) {
- if (!(pai->ai_family == PF_UNSPEC
- || pai->ai_family == afd->a_af)) {
- continue;
- }
-
- /*
- * filter out AFs that are not supported by the kernel
- * XXX errno?
- */
- s = socket(afd->a_af, SOCK_DGRAM, 0);
- if (s < 0)
- continue;
-#if defined(HAVE_CLOSESOCKET)
- closesocket(s);
-#else
- close(s);
-#endif
-
- if (pai->ai_flags & AI_PASSIVE) {
- GET_AI(cur->ai_next, afd, afd->a_addrany, port);
- /* xxx meaningless?
- * GET_CANONNAME(cur->ai_next, "anyaddr");
- */
- } else {
- GET_AI(cur->ai_next, afd, afd->a_loopback,
- port);
- /* xxx meaningless?
- * GET_CANONNAME(cur->ai_next, "localhost");
- */
- }
- cur = cur->ai_next;
- }
- top = sentinel.ai_next;
- if (top)
- goto good;
- else
- ERR(EAI_FAMILY);
- }
-
- /* hostname as numeric name */
- for (i = 0; afdl[i].a_af; i++) {
- if (inet_pton(afdl[i].a_af, hostname, pton)) {
- u_long v4a;
+ case SOCK_RAW:
+ break;
+#endif
+ case SOCK_DGRAM:
+ if (pai->ai_protocol != IPPROTO_UDP &&
+ pai->ai_protocol != ANY)
+ ERR(EAI_BADHINTS); /*xxx*/
+ pai->ai_protocol = IPPROTO_UDP;
+ break;
+ case SOCK_STREAM:
+ if (pai->ai_protocol != IPPROTO_TCP &&
+ pai->ai_protocol != ANY)
+ ERR(EAI_BADHINTS); /*xxx*/
+ pai->ai_protocol = IPPROTO_TCP;
+ break;
+ default:
+ ERR(EAI_SOCKTYPE);
+ break;
+ }
+ }
+
+ /*
+ * service port
+ */
+ if (servname) {
+ if (str_isnumber(servname)) {
+ if (pai->ai_socktype == ANY) {
+ /* caller accept *ANY* socktype */
+ pai->ai_socktype = SOCK_DGRAM;
+ pai->ai_protocol = IPPROTO_UDP;
+ }
+ port = htons((unsigned short)atoi(servname));
+ } else if (pai->ai_flags & AI_NUMERICSERV) {
+ ERR(EAI_NONAME);
+ } else {
+ struct servent *sp;
+ const char *proto;
+
+ proto = NULL;
+ switch (pai->ai_socktype) {
+ case ANY:
+ proto = NULL;
+ break;
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ default:
+ fprintf(stderr, "panic!\n");
+ break;
+ }
+ if ((sp = getservbyname((char*)servname, proto)) == NULL)
+ ERR(EAI_SERVICE);
+ port = sp->s_port;
+ if (pai->ai_socktype == ANY)
+ if (strcmp(sp->s_proto, "udp") == 0) {
+ pai->ai_socktype = SOCK_DGRAM;
+ pai->ai_protocol = IPPROTO_UDP;
+ } else if (strcmp(sp->s_proto, "tcp") == 0) {
+ pai->ai_socktype = SOCK_STREAM;
+ pai->ai_protocol = IPPROTO_TCP;
+ } else
+ ERR(EAI_PROTOCOL); /*xxx*/
+ }
+ }
+
+ /*
+ * hostname == NULL.
+ * passive socket -> anyaddr (0.0.0.0 or ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+ if (hostname == NULL) {
+ const struct afd *afd;
+ int s;
+
+ for (afd = &afdl[0]; afd->a_af; afd++) {
+ if (!(pai->ai_family == PF_UNSPEC
+ || pai->ai_family == afd->a_af)) {
+ continue;
+ }
+
+ /*
+ * filter out AFs that are not supported by the kernel
+ * XXX errno?
+ */
+ s = socket(afd->a_af, SOCK_DGRAM, 0);
+ if (s < 0)
+ continue;
+
+ close(s);
+
+ if (pai->ai_flags & AI_PASSIVE) {
+ GET_AI(cur->ai_next, afd, afd->a_addrany, port);
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "anyaddr");
+ */
+ } else {
+ GET_AI(cur->ai_next, afd, afd->a_loopback,
+ port);
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "localhost");
+ */
+ }
+ cur = cur->ai_next;
+ }
+ top = sentinel.ai_next;
+ if (top)
+ goto good;
+ else
+ ERR(EAI_FAMILY);
+ }
+
+ /* hostname as numeric name */
+ for (i = 0; afdl[i].a_af; i++) {
+ if (inet_pton(afdl[i].a_af, hostname, pton)) {
+ u_long v4a;
#ifdef INET6
- u_char pfx;
-#endif
-
- switch (afdl[i].a_af) {
- case AF_INET:
- v4a = ((struct in_addr *)pton)->s_addr;
- if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
- pai->ai_flags &= ~AI_CANONNAME;
- v4a >>= IN_CLASSA_NSHIFT;
- if (v4a == 0 || v4a == IN_LOOPBACKNET)
- pai->ai_flags &= ~AI_CANONNAME;
- break;
+ u_char pfx;
+#endif
+
+ switch (afdl[i].a_af) {
+ case AF_INET:
+ v4a = ((struct in_addr *)pton)->s_addr;
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ pai->ai_flags &= ~AI_CANONNAME;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0 || v4a == IN_LOOPBACKNET)
+ pai->ai_flags &= ~AI_CANONNAME;
+ break;
#ifdef INET6
- case AF_INET6:
-#ifdef HAVE_ADDR8
- pfx = ((struct in6_addr *)pton)->s6_addr8[0];
-#else
- pfx = ((struct in6_addr *)pton)->s6_addr[0];
-#endif
- if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
- pai->ai_flags &= ~AI_CANONNAME;
- break;
-#endif
- }
-
- if (pai->ai_family == afdl[i].a_af ||
- pai->ai_family == PF_UNSPEC) {
- if (! (pai->ai_flags & AI_CANONNAME)) {
- GET_AI(top, &afdl[i], pton, port);
- goto good;
- }
- /*
- * if AI_CANONNAME and if reverse lookup
- * fail, return ai anyway to pacify
- * calling application.
- *
- * XXX getaddrinfo() is a name->address
- * translation function, and it looks strange
- * that we do addr->name translation here.
- */
- get_name(pton, &afdl[i], &top, pton, pai, port);
- goto good;
- } else
- ERR(EAI_FAMILY); /*xxx*/
- }
- }
-
- if (pai->ai_flags & AI_NUMERICHOST)
- ERR(EAI_NONAME);
-
- /* hostname as alphabetical name */
- error = get_addr(hostname, pai->ai_family, &top, pai, port);
- if (error == 0) {
- if (top) {
+ case AF_INET6:
+ pfx = ((struct in6_addr *)pton)->s6_addr[0];
+ if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
+ pai->ai_flags &= ~AI_CANONNAME;
+ break;
+#endif
+ }
+
+ if (pai->ai_family == afdl[i].a_af ||
+ pai->ai_family == PF_UNSPEC) {
+ if (! (pai->ai_flags & AI_CANONNAME)) {
+ GET_AI(top, &afdl[i], pton, port);
+ goto good;
+ }
+ /*
+ * if AI_CANONNAME and if reverse lookup
+ * fail, return ai anyway to pacify
+ * calling application.
+ *
+ * XXX getaddrinfo() is a name->address
+ * translation function, and it looks strange
+ * that we do addr->name translation here.
+ */
+ get_name(pton, &afdl[i], &top, pton, pai, port);
+ goto good;
+ } else
+ ERR(EAI_FAMILY); /*xxx*/
+ }
+ }
+
+ if (pai->ai_flags & AI_NUMERICHOST)
+ ERR(EAI_NONAME);
+
+ /* hostname as alphabetical name */
+ error = get_addr(hostname, pai->ai_family, &top, pai, port);
+ if (error == 0) {
+ if (top) {
good:
- *res = top;
- return SUCCESS;
- } else
- error = EAI_FAIL;
- }
+ *res = top;
+ return SUCCESS;
+ } else
+ error = EAI_FAIL;
+ }
free:
- if (top)
- freeaddrinfo(top);
+ if (top)
+ freeaddrinfo(top);
bad:
- *res = NULL;
- return error;
+ *res = NULL;
+ return error;
}
static int
-get_name(addr, afd, res, numaddr, pai, port0)
- const char *addr;
- const struct afd *afd;
- struct addrinfo **res;
- char *numaddr;
- struct addrinfo *pai;
- int port0;
+get_name(const char *addr, const struct afd *afd, struct addrinfo **res, char *numaddr, struct addrinfo *pai, int port0)
{
- u_short port = port0 & 0xffff;
- struct hostent *hp;
- struct addrinfo *cur;
- int error = 0;
+ u_short port = port0 & 0xffff;
+ struct hostent *hp;
+ struct addrinfo *cur;
+ int error = 0;
#ifdef INET6
- int h_error;
+ int h_error;
#endif
#ifdef INET6
- hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
#else
- hp = gethostbyaddr((char*)addr, afd->a_addrlen, AF_INET);
-#endif
- if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
- GET_AI(cur, afd, hp->h_addr_list[0], port);
- GET_CANONNAME(cur, hp->h_name);
- } else
- GET_AI(cur, afd, numaddr, port);
-
+ hp = gethostbyaddr((char*)addr, afd->a_addrlen, AF_INET);
+#endif
+ if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
+ GET_AI(cur, afd, hp->h_addr_list[0], port);
+ GET_CANONNAME(cur, hp->h_name);
+ } else
+ GET_AI(cur, afd, numaddr, port);
+
#ifdef INET6
- if (hp)
- freehostent(hp);
+ if (hp)
+ freehostent(hp);
#endif
- *res = cur;
- return SUCCESS;
+ *res = cur;
+ return SUCCESS;
free:
- if (cur)
- freeaddrinfo(cur);
+ if (cur)
+ freeaddrinfo(cur);
#ifdef INET6
- if (hp)
- freehostent(hp);
+ if (hp)
+ freehostent(hp);
#endif
/* bad: */
- *res = NULL;
- return error;
+ *res = NULL;
+ return error;
}
static int
-get_addr(hostname, af, res, pai, port0)
- const char *hostname;
- int af;
- struct addrinfo **res;
- struct addrinfo *pai;
- int port0;
+get_addr(const char *hostname, int af, struct addrinfo **res, struct addrinfo *pai, int port0)
{
- u_short port = port0 & 0xffff;
- struct addrinfo sentinel;
- struct hostent *hp;
- struct addrinfo *top, *cur;
- const struct afd *afd;
- int i, error = 0, h_error;
- char *ap;
-
- top = NULL;
- sentinel.ai_next = NULL;
- cur = &sentinel;
+ u_short port = port0 & 0xffff;
+ struct addrinfo sentinel;
+ struct hostent *hp;
+ struct addrinfo *top, *cur;
+ const struct afd *afd;
+ int i, error = 0, h_error;
+ char *ap;
+
+ top = NULL;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
#ifdef INET6
- if (af == AF_UNSPEC) {
- hp = getipnodebyname(hostname, AF_INET6,
- AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
- } else
- hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
+ if (af == AF_UNSPEC) {
+ hp = getipnodebyname(hostname, AF_INET6,
+ AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
+ } else
+ hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
#else
- hp = gethostbyname((char*)hostname);
- h_error = h_errno;
-#endif
- if (hp == NULL) {
- switch (h_error) {
- case HOST_NOT_FOUND:
- case NO_DATA:
- error = EAI_NODATA;
- break;
- case TRY_AGAIN:
- error = EAI_AGAIN;
- break;
- case NO_RECOVERY:
- default:
- error = EAI_FAIL;
- break;
- }
- goto bad;
- }
-
- if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
- (hp->h_addr_list[0] == NULL))
- ERR(EAI_FAIL);
-
- for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
- switch (af) {
+ if (strlen(hostname) >= NI_MAXHOST) ERR(EAI_NODATA);
+ hp = gethostbyname((char*)hostname);
+ h_error = h_errno;
+#endif
+ if (hp == NULL) {
+ switch (h_error) {
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ error = EAI_NODATA;
+ break;
+ case TRY_AGAIN:
+ error = EAI_AGAIN;
+ break;
+ case NO_RECOVERY:
+ default:
+ error = EAI_FAIL;
+ break;
+ }
+ goto bad;
+ }
+
+ if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
+ (hp->h_addr_list[0] == NULL))
+ ERR(EAI_FAIL);
+
+ for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
+ switch (af) {
#ifdef INET6
- case AF_INET6:
- afd = &afdl[N_INET6];
- break;
+ case AF_INET6:
+ afd = &afdl[N_INET6];
+ break;
#endif
#ifndef INET6
- default: /* AF_UNSPEC */
+ default: /* AF_UNSPEC */
#endif
- case AF_INET:
- afd = &afdl[N_INET];
- break;
+ case AF_INET:
+ afd = &afdl[N_INET];
+ break;
#ifdef INET6
- default: /* AF_UNSPEC */
- if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
- ap += sizeof(struct in6_addr) -
- sizeof(struct in_addr);
- afd = &afdl[N_INET];
- } else
- afd = &afdl[N_INET6];
- break;
-#endif
- }
+ default: /* AF_UNSPEC */
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
+ ap += sizeof(struct in6_addr) -
+ sizeof(struct in_addr);
+ afd = &afdl[N_INET];
+ } else
+ afd = &afdl[N_INET6];
+ break;
+#endif
+ }
#ifdef FAITH
- if (translate && afd->a_af == AF_INET) {
- struct in6_addr *in6;
-
- GET_AI(cur->ai_next, &afdl[N_INET6], ap, port);
- in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
- memcpy(&in6->s6_addr32[0], &faith_prefix,
- sizeof(struct in6_addr) - sizeof(struct in_addr));
- memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr));
- } else
+ if (translate && afd->a_af == AF_INET) {
+ struct in6_addr *in6;
+
+ GET_AI(cur->ai_next, &afdl[N_INET6], ap, port);
+ in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
+ memcpy(&in6->s6_addr, &faith_prefix,
+ sizeof(struct in6_addr) - sizeof(struct in_addr));
+ memcpy(&in6->s6_addr + sizeof(struct in_addr), ap,
+ sizeof(struct in_addr));
+ } else
#endif /* FAITH */
- GET_AI(cur->ai_next, afd, ap, port);
- if (cur == &sentinel) {
- top = cur->ai_next;
- GET_CANONNAME(top, hp->h_name);
- }
- cur = cur->ai_next;
- }
+ GET_AI(cur->ai_next, afd, ap, port);
+ if (cur == &sentinel) {
+ top = cur->ai_next;
+ GET_CANONNAME(top, hp->h_name);
+ }
+ cur = cur->ai_next;
+ }
#ifdef INET6
- freehostent(hp);
+ freehostent(hp);
#endif
- *res = top;
- return SUCCESS;
+ *res = top;
+ return SUCCESS;
free:
- if (top)
- freeaddrinfo(top);
+ if (top)
+ freeaddrinfo(top);
#ifdef INET6
- if (hp)
- freehostent(hp);
+ if (hp)
+ freehostent(hp);
#endif
bad:
- *res = NULL;
- return error;
+ *res = NULL;
+ return error;
}
diff --git a/ext/socket/getnameinfo.c b/ext/socket/getnameinfo.c
index 4c9c8f03c4..98da8c1647 100644
--- a/ext/socket/getnameinfo.c
+++ b/ext/socket/getnameinfo.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -13,7 +13,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -34,14 +34,14 @@
* but INRIA implementation returns EAI_xxx defined for getaddrinfo().
*/
-#include "config.h"
+#include "ruby/config.h"
+#ifdef RUBY_EXTCONF_H
+#include RUBY_EXTCONF_H
+#endif
+#include <stdio.h>
#include <sys/types.h>
#ifndef _WIN32
-#if defined(__BEOS__)
-# include <net/socket.h>
-#else
-# include <sys/socket.h>
-#endif
+#include <sys/socket.h>
#include <netinet/in.h>
#if defined(HAVE_ARPA_INET_H)
#include <arpa/inet.h>
@@ -51,15 +51,12 @@
#endif
#include <netdb.h>
#if defined(HAVE_RESOLV_H)
-#ifdef _SX
-#include <stdio.h>
-#endif
#include <resolv.h>
#endif
#endif
#ifdef _WIN32
#include <winsock2.h>
-#include <stdio.h>
+#include <ws2tcpip.h>
#define snprintf _snprintf
#endif
@@ -70,8 +67,13 @@
#include <socks.h>
#endif
+#ifndef HAVE_TYPE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
#include "addrinfo.h"
#include "sockport.h"
+#include "rubysocket.h"
#define SUCCESS 0
#define ANY 0
@@ -79,30 +81,30 @@
#define NO 0
struct sockinet {
- u_char si_len;
- u_char si_family;
- u_short si_port;
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
};
static struct afd {
- int a_af;
- int a_addrlen;
- int a_socklen;
- int a_off;
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
} afdl [] = {
#ifdef INET6
#define N_INET6 0
- {PF_INET6, sizeof(struct in6_addr),
- sizeof(struct sockaddr_in6),
- offsetof(struct sockaddr_in6, sin6_addr)},
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr)},
#define N_INET 1
#else
#define N_INET 0
#endif
- {PF_INET, sizeof(struct in_addr),
- sizeof(struct sockaddr_in),
- offsetof(struct sockaddr_in, sin_addr)},
- {0, 0, 0, 0},
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr)},
+ {0, 0, 0, 0},
};
#define ENI_NOSOCKET 0
@@ -113,156 +115,121 @@ static struct afd {
#define ENI_FAMILY 5
#define ENI_SALEN 6
-#ifndef HAVE_INET_NTOP
-static const char *
-inet_ntop(af, addr, numaddr, numaddr_len)
- int af;
- const void *addr;
- char *numaddr;
- size_t numaddr_len;
-{
-#ifdef HAVE_INET_NTOA
- struct in_addr in;
- memcpy(&in.s_addr, addr, sizeof(in.s_addr));
- snprintf(numaddr, numaddr_len, "%s", inet_ntoa(in));
-#else
- unsigned long x = ntohl(*(unsigned long*)addr);
- snprintf(numaddr, numaddr_len, "%d.%d.%d.%d",
- (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
- (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
-#endif
- return numaddr;
-}
-#endif
-
int
-getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
- const struct sockaddr *sa;
- size_t salen;
- char *host;
- size_t hostlen;
- char *serv;
- size_t servlen;
- int flags;
+getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
{
- struct afd *afd;
- struct servent *sp;
- struct hostent *hp;
- u_short port;
- int family, len, i;
- char *addr, *p;
- u_long v4a;
+ struct afd *afd;
+ struct hostent *hp;
+ u_short port;
+ int family, len, i;
+ char *addr, *p;
+ u_long v4a;
#ifdef INET6
- u_char pfx;
+ u_char pfx;
#endif
- int h_error;
- char numserv[512];
- char numaddr[512];
+ int h_error;
+ char numserv[512];
+ char numaddr[512];
- if (sa == NULL)
- return ENI_NOSOCKET;
+ if (sa == NULL)
+ return ENI_NOSOCKET;
- len = SA_LEN(sa);
- if (len != salen) return ENI_SALEN;
-
- family = sa->sa_family;
- for (i = 0; afdl[i].a_af; i++)
- if (afdl[i].a_af == family) {
- afd = &afdl[i];
- goto found;
- }
- return ENI_FAMILY;
-
- found:
- if (len != afd->a_socklen) return ENI_SALEN;
-
- port = ((struct sockinet *)sa)->si_port; /* network byte order */
- addr = (char *)sa + afd->a_off;
+ if (!VALIDATE_SOCKLEN(sa, salen)) return ENI_SALEN;
+ len = salen;
+
+ family = sa->sa_family;
+ for (i = 0; afdl[i].a_af; i++)
+ if (afdl[i].a_af == family) {
+ afd = &afdl[i];
+ goto found;
+ }
+ return ENI_FAMILY;
- if (serv == NULL || servlen == 0) {
- /* what we should do? */
- } else if (flags & NI_NUMERICSERV) {
- snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
- if (strlen(numserv) + 1 > servlen)
- return ENI_MEMORY;
- strcpy(serv, numserv);
- } else {
+ found:
+ if (len != afd->a_socklen) return ENI_SALEN;
+
+ port = ((struct sockinet *)sa)->si_port; /* network byte order */
+ addr = (char *)sa + afd->a_off;
+
+ if (serv == NULL || servlen == 0) {
+ /* what we should do? */
+ } else if (flags & NI_NUMERICSERV) {
+ snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
+ if (strlcpy(serv, numserv, servlen) >= servlen)
+ return ENI_MEMORY;
+ } else {
#if defined(HAVE_GETSERVBYPORT)
- sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
- if (sp) {
- if (strlen(sp->s_name) + 1 > servlen)
- return ENI_MEMORY;
- strcpy(serv, sp->s_name);
- } else
- return ENI_NOSERVNAME;
+ struct servent *sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
+ if (sp) {
+ if (strlcpy(serv, sp->s_name, servlen) >= servlen)
+ return ENI_MEMORY;
+ } else
+ return ENI_NOSERVNAME;
#else
- return ENI_NOSERVNAME;
-#endif
- }
-
- switch (sa->sa_family) {
- case AF_INET:
- v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
- if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
- flags |= NI_NUMERICHOST;
- v4a >>= IN_CLASSA_NSHIFT;
- if (v4a == 0)
- flags |= NI_NUMERICHOST;
- break;
+ return ENI_NOSERVNAME;
+#endif
+ }
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ flags |= NI_NUMERICHOST;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0)
+ flags |= NI_NUMERICHOST;
+ break;
#ifdef INET6
- case AF_INET6:
+ case AF_INET6:
#ifdef HAVE_ADDR8
- pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
+ pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
#else
- pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
-#endif
- if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
- flags |= NI_NUMERICHOST;
- break;
-#endif
- }
- if (host == NULL || hostlen == 0) {
- /* what should we do? */
- } else if (flags & NI_NUMERICHOST) {
- if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
- == NULL)
- return ENI_SYSTEM;
- if (strlen(numaddr) > hostlen)
- return ENI_MEMORY;
- strcpy(host, numaddr);
- } else {
+ pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
+#endif
+ if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
+ flags |= NI_NUMERICHOST;
+ break;
+#endif
+ }
+ if (host == NULL || hostlen == 0) {
+ /* what should we do? */
+ } else if (flags & NI_NUMERICHOST) {
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return ENI_SYSTEM;
+ if (strlcpy(host, numaddr, hostlen) >= hostlen)
+ return ENI_MEMORY;
+ } else {
#ifdef INET6
- hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
#else
- hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
- h_error = h_errno;
+ hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+ h_error = h_errno;
#endif
- if (hp) {
- if (flags & NI_NOFQDN) {
- p = strchr(hp->h_name, '.');
- if (p) *p = '\0';
- }
- if (strlen(hp->h_name) + 1 > hostlen) {
+ if (hp) {
+ if (flags & NI_NOFQDN) {
+ p = strchr(hp->h_name, '.');
+ if (p) *p = '\0';
+ }
+ if (strlcpy(host, hp->h_name, hostlen) >= hostlen) {
#ifdef INET6
- freehostent(hp);
+ freehostent(hp);
#endif
- return ENI_MEMORY;
- }
- strcpy(host, hp->h_name);
+ return ENI_MEMORY;
+ }
#ifdef INET6
- freehostent(hp);
-#endif
- } else {
- if (flags & NI_NAMEREQD)
- return ENI_NOHOSTNAME;
- if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
- == NULL)
- return ENI_NOHOSTNAME;
- if (strlen(numaddr) > hostlen)
- return ENI_MEMORY;
- strcpy(host, numaddr);
- }
- }
- return SUCCESS;
+ freehostent(hp);
+#endif
+ } else {
+ if (flags & NI_NAMEREQD)
+ return ENI_NOHOSTNAME;
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return ENI_NOHOSTNAME;
+ if (strlcpy(host, numaddr, hostlen) >= hostlen)
+ return ENI_MEMORY;
+ }
+ }
+ return SUCCESS;
}
diff --git a/ext/socket/ifaddr.c b/ext/socket/ifaddr.c
new file mode 100644
index 0000000000..3596c40a11
--- /dev/null
+++ b/ext/socket/ifaddr.c
@@ -0,0 +1,480 @@
+#include "rubysocket.h"
+
+#ifdef HAVE_GETIFADDRS
+
+/*
+ * ifa_flags is usually unsigned int.
+ * However it is uint64_t on SunOS 5.11 (OpenIndiana).
+ */
+#ifdef HAVE_LONG_LONG
+typedef unsigned LONG_LONG ifa_flags_t;
+#define PRIxIFAFLAGS PRI_LL_PREFIX"x"
+#define IFAFLAGS2NUM(flags) ULL2NUM(flags)
+#else
+typedef unsigned int ifa_flags_t;
+#define PRIxIFAFLAGS "x"
+#define IFAFLAGS2NUM(flags) UINT2NUM(flags)
+#endif
+
+VALUE rb_cSockIfaddr;
+
+typedef struct rb_ifaddr_tag rb_ifaddr_t;
+typedef struct rb_ifaddr_root_tag rb_ifaddr_root_t;
+
+struct rb_ifaddr_tag {
+ int ord;
+ struct ifaddrs *ifaddr;
+};
+
+struct rb_ifaddr_root_tag {
+ int refcount;
+ int numifaddrs;
+ rb_ifaddr_t ary[1];
+};
+
+static rb_ifaddr_root_t *
+get_root(const rb_ifaddr_t *ifaddr)
+{
+ return (rb_ifaddr_root_t *)((char *)&ifaddr[-ifaddr->ord] -
+ offsetof(rb_ifaddr_root_t, ary));
+}
+
+static void
+ifaddr_free(void *ptr)
+{
+ rb_ifaddr_t *ifaddr = ptr;
+ rb_ifaddr_root_t *root = get_root(ifaddr);
+ root->refcount--;
+ if (root->refcount == 0) {
+ freeifaddrs(root->ary[0].ifaddr);
+ xfree(root);
+ }
+}
+
+static size_t
+ifaddr_memsize(const void *ptr)
+{
+ size_t size = offsetof(rb_ifaddr_root_t, ary);
+ const rb_ifaddr_t *ifaddr;
+ ifaddr = ptr;
+ if (ifaddr->ord == 0) size = sizeof(rb_ifaddr_root_t);
+ size += sizeof(struct ifaddrs);
+ return size;
+}
+
+static const rb_data_type_t ifaddr_type = {
+ "socket/ifaddr",
+ {0, ifaddr_free, ifaddr_memsize,},
+};
+
+static inline rb_ifaddr_t *
+check_ifaddr(VALUE self)
+{
+ return rb_check_typeddata(self, &ifaddr_type);
+}
+
+static rb_ifaddr_t *
+get_ifaddr(VALUE self)
+{
+ rb_ifaddr_t *rifaddr = check_ifaddr(self);
+
+ if (!rifaddr) {
+ rb_raise(rb_eTypeError, "uninitialized ifaddr");
+ }
+ return rifaddr;
+}
+
+static struct ifaddrs *
+get_ifaddrs(VALUE self)
+{
+ return get_ifaddr(self)->ifaddr;
+}
+
+static VALUE
+rsock_getifaddrs(void)
+{
+ int ret;
+ int numifaddrs, i;
+ struct ifaddrs *ifaddrs, *ifa;
+ rb_ifaddr_root_t *root;
+ VALUE result, addr;
+
+ ret = getifaddrs(&ifaddrs);
+ if (ret == -1)
+ rb_sys_fail("getifaddrs");
+
+ if (!ifaddrs) {
+ return rb_ary_new();
+ }
+
+ numifaddrs = 0;
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next)
+ numifaddrs++;
+
+ addr = TypedData_Wrap_Struct(rb_cSockIfaddr, &ifaddr_type, 0);
+ root = xmalloc(offsetof(rb_ifaddr_root_t, ary) + numifaddrs * sizeof(rb_ifaddr_t));
+ root->refcount = 0;
+ root->numifaddrs = numifaddrs;
+
+ ifa = ifaddrs;
+ for (i = 0; i < numifaddrs; i++) {
+ root->ary[i].ord = i;
+ root->ary[i].ifaddr = ifa;
+ ifa = ifa->ifa_next;
+ }
+ RTYPEDDATA_DATA(addr) = &root->ary[0];
+ root->refcount++;
+
+ result = rb_ary_new2(numifaddrs);
+ rb_ary_push(result, addr);
+ for (i = 1; i < numifaddrs; i++) {
+ addr = TypedData_Wrap_Struct(rb_cSockIfaddr, &ifaddr_type, &root->ary[i]);
+ root->refcount++;
+ rb_ary_push(result, addr);
+ }
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * ifaddr.name => string
+ *
+ * Returns the interface name of _ifaddr_.
+ */
+
+static VALUE
+ifaddr_name(VALUE self)
+{
+ struct ifaddrs *ifa = get_ifaddrs(self);
+ return rb_str_new_cstr(ifa->ifa_name);
+}
+
+#ifdef HAVE_IF_NAMETOINDEX
+/*
+ * call-seq:
+ * ifaddr.ifindex => integer
+ *
+ * Returns the interface index of _ifaddr_.
+ */
+
+static VALUE
+ifaddr_ifindex(VALUE self)
+{
+ struct ifaddrs *ifa = get_ifaddrs(self);
+ unsigned int ifindex = if_nametoindex(ifa->ifa_name);
+ if (ifindex == 0) {
+ rb_raise(rb_eArgError, "invalid interface name: %s", ifa->ifa_name);
+ }
+ return UINT2NUM(ifindex);
+}
+#else
+#define ifaddr_ifindex rb_f_notimplement
+#endif
+
+/*
+ * call-seq:
+ * ifaddr.flags => integer
+ *
+ * Returns the flags of _ifaddr_.
+ *
+ * The value is bitwise-or of Socket::IFF_* constants such as Socket::IFF_LOOPBACK.
+ */
+
+static VALUE
+ifaddr_flags(VALUE self)
+{
+ struct ifaddrs *ifa = get_ifaddrs(self);
+ return IFAFLAGS2NUM(ifa->ifa_flags);
+}
+
+/*
+ * call-seq:
+ * ifaddr.addr => addrinfo
+ *
+ * Returns the address of _ifaddr_.
+ * nil is returned if address is not available in _ifaddr_.
+ */
+
+static VALUE
+ifaddr_addr(VALUE self)
+{
+ struct ifaddrs *ifa = get_ifaddrs(self);
+ if (ifa->ifa_addr)
+ return rsock_sockaddr_obj(ifa->ifa_addr, rsock_sockaddr_len(ifa->ifa_addr));
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * ifaddr.netmask => addrinfo
+ *
+ * Returns the netmask address of _ifaddr_.
+ * nil is returned if netmask is not available in _ifaddr_.
+ */
+
+static VALUE
+ifaddr_netmask(VALUE self)
+{
+ struct ifaddrs *ifa = get_ifaddrs(self);
+ if (ifa->ifa_netmask)
+ return rsock_sockaddr_obj(ifa->ifa_netmask, rsock_sockaddr_len(ifa->ifa_netmask));
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * ifaddr.broadaddr => addrinfo
+ *
+ * Returns the broadcast address of _ifaddr_.
+ * nil is returned if the flags doesn't have IFF_BROADCAST.
+ */
+
+static VALUE
+ifaddr_broadaddr(VALUE self)
+{
+ struct ifaddrs *ifa = get_ifaddrs(self);
+ if ((ifa->ifa_flags & IFF_BROADCAST) && ifa->ifa_broadaddr)
+ return rsock_sockaddr_obj(ifa->ifa_broadaddr, rsock_sockaddr_len(ifa->ifa_broadaddr));
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * ifaddr.dstaddr => addrinfo
+ *
+ * Returns the destination address of _ifaddr_.
+ * nil is returned if the flags doesn't have IFF_POINTOPOINT.
+ */
+
+static VALUE
+ifaddr_dstaddr(VALUE self)
+{
+ struct ifaddrs *ifa = get_ifaddrs(self);
+ if ((ifa->ifa_flags & IFF_POINTOPOINT) && ifa->ifa_dstaddr)
+ return rsock_sockaddr_obj(ifa->ifa_dstaddr, rsock_sockaddr_len(ifa->ifa_dstaddr));
+ return Qnil;
+}
+
+#ifdef HAVE_STRUCT_IF_DATA_IFI_VHID
+/*
+ * call-seq:
+ * ifaddr.vhid => Integer
+ *
+ * Returns the vhid address of _ifaddr_.
+ * nil is returned if there is no vhid.
+ */
+
+static VALUE
+ifaddr_vhid(VALUE self)
+{
+ struct ifaddrs *ifa = get_ifaddrs(self);
+ if (ifa->ifa_data)
+ return (INT2FIX(((struct if_data*)ifa->ifa_data)->ifi_vhid));
+ else
+ return Qnil;
+}
+#endif
+
+static void
+ifaddr_inspect_flags(ifa_flags_t flags, VALUE result)
+{
+ const char *sep = " ";
+#define INSPECT_BIT(bit, name) \
+ if (flags & (bit)) { rb_str_catf(result, "%s" name, sep); flags &= ~(ifa_flags_t)(bit); sep = ","; }
+#ifdef IFF_UP
+ INSPECT_BIT(IFF_UP, "UP")
+#endif
+#ifdef IFF_BROADCAST
+ INSPECT_BIT(IFF_BROADCAST, "BROADCAST")
+#endif
+#ifdef IFF_DEBUG
+ INSPECT_BIT(IFF_DEBUG, "DEBUG")
+#endif
+#ifdef IFF_LOOPBACK
+ INSPECT_BIT(IFF_LOOPBACK, "LOOPBACK")
+#endif
+#ifdef IFF_POINTOPOINT
+ INSPECT_BIT(IFF_POINTOPOINT, "POINTOPOINT")
+#endif
+#ifdef IFF_RUNNING
+ INSPECT_BIT(IFF_RUNNING, "RUNNING")
+#endif
+#ifdef IFF_NOARP
+ INSPECT_BIT(IFF_NOARP, "NOARP")
+#endif
+#ifdef IFF_PROMISC
+ INSPECT_BIT(IFF_PROMISC, "PROMISC")
+#endif
+#ifdef IFF_NOTRAILERS
+ INSPECT_BIT(IFF_NOTRAILERS, "NOTRAILERS")
+#endif
+#ifdef IFF_ALLMULTI
+ INSPECT_BIT(IFF_ALLMULTI, "ALLMULTI")
+#endif
+#ifdef IFF_SIMPLEX
+ INSPECT_BIT(IFF_SIMPLEX, "SIMPLEX")
+#endif
+#ifdef IFF_MASTER
+ INSPECT_BIT(IFF_MASTER, "MASTER")
+#endif
+#ifdef IFF_SLAVE
+ INSPECT_BIT(IFF_SLAVE, "SLAVE")
+#endif
+#ifdef IFF_MULTICAST
+ INSPECT_BIT(IFF_MULTICAST, "MULTICAST")
+#endif
+#ifdef IFF_PORTSEL
+ INSPECT_BIT(IFF_PORTSEL, "PORTSEL")
+#endif
+#ifdef IFF_AUTOMEDIA
+ INSPECT_BIT(IFF_AUTOMEDIA, "AUTOMEDIA")
+#endif
+#ifdef IFF_DYNAMIC
+ INSPECT_BIT(IFF_DYNAMIC, "DYNAMIC")
+#endif
+#ifdef IFF_LOWER_UP
+ INSPECT_BIT(IFF_LOWER_UP, "LOWER_UP")
+#endif
+#ifdef IFF_DORMANT
+ INSPECT_BIT(IFF_DORMANT, "DORMANT")
+#endif
+#ifdef IFF_ECHO
+ INSPECT_BIT(IFF_ECHO, "ECHO")
+#endif
+#undef INSPECT_BIT
+ if (flags) {
+ rb_str_catf(result, "%s%#"PRIxIFAFLAGS, sep, flags);
+ }
+}
+
+/*
+ * call-seq:
+ * ifaddr.inspect => string
+ *
+ * Returns a string to show contents of _ifaddr_.
+ */
+
+static VALUE
+ifaddr_inspect(VALUE self)
+{
+ struct ifaddrs *ifa = get_ifaddrs(self);
+ VALUE result;
+
+ result = rb_str_new_cstr("#<");
+
+ rb_str_append(result, rb_class_name(CLASS_OF(self)));
+ rb_str_cat2(result, " ");
+ rb_str_cat2(result, ifa->ifa_name);
+
+ if (ifa->ifa_flags)
+ ifaddr_inspect_flags(ifa->ifa_flags, result);
+
+ if (ifa->ifa_addr) {
+ rb_str_cat2(result, " ");
+ rsock_inspect_sockaddr(ifa->ifa_addr,
+ rsock_sockaddr_len(ifa->ifa_addr),
+ result);
+ }
+ if (ifa->ifa_netmask) {
+ rb_str_cat2(result, " netmask=");
+ rsock_inspect_sockaddr(ifa->ifa_netmask,
+ rsock_sockaddr_len(ifa->ifa_netmask),
+ result);
+ }
+
+ if ((ifa->ifa_flags & IFF_BROADCAST) && ifa->ifa_broadaddr) {
+ rb_str_cat2(result, " broadcast=");
+ rsock_inspect_sockaddr(ifa->ifa_broadaddr,
+ rsock_sockaddr_len(ifa->ifa_broadaddr),
+ result);
+ }
+
+ if ((ifa->ifa_flags & IFF_POINTOPOINT) && ifa->ifa_dstaddr) {
+ rb_str_cat2(result, " dstaddr=");
+ rsock_inspect_sockaddr(ifa->ifa_dstaddr,
+ rsock_sockaddr_len(ifa->ifa_dstaddr),
+ result);
+ }
+
+ rb_str_cat2(result, ">");
+ return result;
+}
+#endif
+
+#ifdef HAVE_GETIFADDRS
+/*
+ * call-seq:
+ * Socket.getifaddrs => [ifaddr1, ...]
+ *
+ * Returns an array of interface addresses.
+ * An element of the array is an instance of Socket::Ifaddr.
+ *
+ * This method can be used to find multicast-enabled interfaces:
+ *
+ * pp Socket.getifaddrs.reject {|ifaddr|
+ * !ifaddr.addr.ip? || (ifaddr.flags & Socket::IFF_MULTICAST == 0)
+ * }.map {|ifaddr| [ifaddr.name, ifaddr.ifindex, ifaddr.addr] }
+ * #=> [["eth0", 2, #<Addrinfo: 221.186.184.67>],
+ * # ["eth0", 2, #<Addrinfo: fe80::216:3eff:fe95:88bb%eth0>]]
+ *
+ * Example result on GNU/Linux:
+ * pp Socket.getifaddrs
+ * #=> [#<Socket::Ifaddr lo UP,LOOPBACK,RUNNING,0x10000 PACKET[protocol=0 lo hatype=772 HOST hwaddr=00:00:00:00:00:00]>,
+ * # #<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000 PACKET[protocol=0 eth0 hatype=1 HOST hwaddr=00:16:3e:95:88:bb] broadcast=PACKET[protocol=0 eth0 hatype=1 HOST hwaddr=ff:ff:ff:ff:ff:ff]>,
+ * # #<Socket::Ifaddr sit0 NOARP PACKET[protocol=0 sit0 hatype=776 HOST hwaddr=00:00:00:00]>,
+ * # #<Socket::Ifaddr lo UP,LOOPBACK,RUNNING,0x10000 127.0.0.1 netmask=255.0.0.0>,
+ * # #<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000 221.186.184.67 netmask=255.255.255.240 broadcast=221.186.184.79>,
+ * # #<Socket::Ifaddr lo UP,LOOPBACK,RUNNING,0x10000 ::1 netmask=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>,
+ * # #<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000 fe80::216:3eff:fe95:88bb%eth0 netmask=ffff:ffff:ffff:ffff::>]
+ *
+ * Example result on FreeBSD:
+ * pp Socket.getifaddrs
+ * #=> [#<Socket::Ifaddr usbus0 UP,0x10000 LINK[usbus0]>,
+ * # #<Socket::Ifaddr re0 UP,BROADCAST,RUNNING,MULTICAST,0x800 LINK[re0 3a:d0:40:9a:fe:e8]>,
+ * # #<Socket::Ifaddr re0 UP,BROADCAST,RUNNING,MULTICAST,0x800 10.250.10.18 netmask=255.255.255.? (7 bytes for 16 bytes sockaddr_in) broadcast=10.250.10.255>,
+ * # #<Socket::Ifaddr re0 UP,BROADCAST,RUNNING,MULTICAST,0x800 fe80:2::38d0:40ff:fe9a:fee8 netmask=ffff:ffff:ffff:ffff::>,
+ * # #<Socket::Ifaddr re0 UP,BROADCAST,RUNNING,MULTICAST,0x800 2001:2e8:408:10::12 netmask=UNSPEC>,
+ * # #<Socket::Ifaddr plip0 POINTOPOINT,MULTICAST,0x800 LINK[plip0]>,
+ * # #<Socket::Ifaddr lo0 UP,LOOPBACK,RUNNING,MULTICAST LINK[lo0]>,
+ * # #<Socket::Ifaddr lo0 UP,LOOPBACK,RUNNING,MULTICAST ::1 netmask=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>,
+ * # #<Socket::Ifaddr lo0 UP,LOOPBACK,RUNNING,MULTICAST fe80:4::1 netmask=ffff:ffff:ffff:ffff::>,
+ * # #<Socket::Ifaddr lo0 UP,LOOPBACK,RUNNING,MULTICAST 127.0.0.1 netmask=255.?.?.? (5 bytes for 16 bytes sockaddr_in)>]
+ *
+ */
+
+static VALUE
+socket_s_getifaddrs(VALUE self)
+{
+ return rsock_getifaddrs();
+}
+#else
+#define socket_s_getifaddrs rb_f_notimplement
+#endif
+
+void
+rsock_init_sockifaddr(void)
+{
+#ifdef HAVE_GETIFADDRS
+ /*
+ * Document-class: Socket::Ifaddr
+ *
+ * Socket::Ifaddr represents a result of getifaddrs() function.
+ */
+ rb_cSockIfaddr = rb_define_class_under(rb_cSocket, "Ifaddr", rb_cObject);
+ rb_undef_alloc_func(rb_cSockIfaddr);
+ rb_define_method(rb_cSockIfaddr, "inspect", ifaddr_inspect, 0);
+ rb_define_method(rb_cSockIfaddr, "name", ifaddr_name, 0);
+ rb_define_method(rb_cSockIfaddr, "ifindex", ifaddr_ifindex, 0);
+ rb_define_method(rb_cSockIfaddr, "flags", ifaddr_flags, 0);
+ rb_define_method(rb_cSockIfaddr, "addr", ifaddr_addr, 0);
+ rb_define_method(rb_cSockIfaddr, "netmask", ifaddr_netmask, 0);
+ rb_define_method(rb_cSockIfaddr, "broadaddr", ifaddr_broadaddr, 0);
+ rb_define_method(rb_cSockIfaddr, "dstaddr", ifaddr_dstaddr, 0);
+#ifdef HAVE_STRUCT_IF_DATA_IFI_VHID
+ rb_define_method(rb_cSockIfaddr, "vhid", ifaddr_vhid, 0);
+#endif
+#endif
+
+ rb_define_singleton_method(rb_cSocket, "getifaddrs", socket_s_getifaddrs, 0);
+}
diff --git a/ext/socket/init.c b/ext/socket/init.c
new file mode 100644
index 0000000000..6091385561
--- /dev/null
+++ b/ext/socket/init.c
@@ -0,0 +1,842 @@
+/************************************************
+
+ init.c -
+
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
+
+************************************************/
+
+#include "rubysocket.h"
+
+#ifdef _WIN32
+VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
+#endif
+
+VALUE rb_cBasicSocket;
+VALUE rb_cIPSocket;
+VALUE rb_cTCPSocket;
+VALUE rb_cTCPServer;
+VALUE rb_cUDPSocket;
+#ifdef AF_UNIX
+VALUE rb_cUNIXSocket;
+VALUE rb_cUNIXServer;
+#endif
+VALUE rb_cSocket;
+VALUE rb_cAddrinfo;
+
+VALUE rb_eSocket;
+VALUE rb_eResolution;
+
+#ifdef SOCKS
+VALUE rb_cSOCKSSocket;
+#endif
+
+int rsock_do_not_reverse_lookup = 1;
+static VALUE sym_wait_readable;
+static ID id_error_code;
+
+void
+rsock_raise_resolution_error(const char *reason, int error)
+{
+#ifdef EAI_SYSTEM
+ int e;
+ if (error == EAI_SYSTEM && (e = errno) != 0)
+ rb_syserr_fail(e, reason);
+#endif
+#ifdef _WIN32
+ rb_encoding *enc = rb_default_internal_encoding();
+ VALUE msg = rb_sprintf("%s: ", reason);
+ if (!enc) enc = rb_default_internal_encoding();
+ rb_str_concat(msg, rb_w32_conv_from_wchar(gai_strerrorW(error), enc));
+#else
+ VALUE msg = rb_sprintf("%s: %s", reason, gai_strerror(error));
+#endif
+
+ StringValue(msg);
+ VALUE self = rb_class_new_instance(1, &msg, rb_eResolution);
+ rb_ivar_set(self, id_error_code, INT2NUM(error));
+ rb_exc_raise(self);
+}
+
+#if defined __APPLE__
+# define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
+#else
+# define do_write_retry(code) ret = code
+#endif
+
+VALUE
+rsock_init_sock(VALUE sock, int fd)
+{
+ rb_io_t *fp;
+
+ rb_update_max_fd(fd);
+ MakeOpenFile(sock, fp);
+ fp->fd = fd;
+ fp->mode = FMODE_READWRITE|FMODE_DUPLEX;
+ rb_io_ascii8bit_binmode(sock);
+ if (rsock_do_not_reverse_lookup) {
+ fp->mode |= FMODE_NOREVLOOKUP;
+ }
+ rb_io_synchronized(fp);
+
+ return sock;
+}
+
+VALUE
+rsock_sendto_blocking(void *data)
+{
+ struct rsock_send_arg *arg = data;
+ VALUE mesg = arg->mesg;
+ ssize_t ret;
+ do_write_retry(sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
+ arg->flags, arg->to, arg->tolen));
+ return (VALUE)ret;
+}
+
+VALUE
+rsock_send_blocking(void *data)
+{
+ struct rsock_send_arg *arg = data;
+ VALUE mesg = arg->mesg;
+ ssize_t ret;
+ do_write_retry(send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
+ arg->flags));
+ return (VALUE)ret;
+}
+
+struct recvfrom_arg {
+ rb_io_t *fptr;
+ int fd, flags;
+ VALUE str;
+ size_t length;
+ socklen_t alen;
+ union_sockaddr buf;
+};
+
+static VALUE
+recvfrom_blocking(void *data)
+{
+ struct recvfrom_arg *arg = data;
+ socklen_t len0 = arg->alen;
+ ssize_t ret;
+ ret = recvfrom(arg->fd, RSTRING_PTR(arg->str), arg->length,
+ arg->flags, &arg->buf.addr, &arg->alen);
+
+ if (ret != -1 && len0 < arg->alen)
+ arg->alen = len0;
+
+ return (VALUE)ret;
+}
+
+static VALUE
+rsock_strbuf(VALUE str, long buflen)
+{
+ long len;
+
+ if (NIL_P(str)) return rb_str_new(0, buflen);
+
+ StringValue(str);
+ len = RSTRING_LEN(str);
+ if (len >= buflen) {
+ rb_str_modify(str);
+ } else {
+ rb_str_modify_expand(str, buflen - len);
+ }
+ return str;
+}
+
+static VALUE
+recvfrom_locktmp(VALUE v)
+{
+ struct recvfrom_arg *arg = (struct recvfrom_arg *)v;
+
+ return rb_io_blocking_region(arg->fptr, recvfrom_blocking, arg);
+}
+
+int
+rsock_is_dgram(rb_io_t *fptr)
+{
+ int socktype;
+ socklen_t optlen = (socklen_t)sizeof(socktype);
+ int ret = getsockopt(fptr->fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen);
+ if (ret == -1) {
+ rb_sys_fail("getsockopt(SO_TYPE)");
+ }
+ return socktype == SOCK_DGRAM;
+}
+
+VALUE
+rsock_s_recvfrom(VALUE socket, int argc, VALUE *argv, enum sock_recv_type from)
+{
+ rb_io_t *fptr;
+ VALUE str;
+ struct recvfrom_arg arg;
+ VALUE len, flg;
+ long buflen;
+ long slen;
+
+ rb_scan_args(argc, argv, "12", &len, &flg, &str);
+
+ if (flg == Qnil)
+ arg.flags = 0;
+ else
+ arg.flags = NUM2INT(flg);
+
+ buflen = NUM2INT(len);
+ str = rsock_strbuf(str, buflen);
+
+ RB_IO_POINTER(socket, fptr);
+
+ if (rb_io_read_pending(fptr)) {
+ rb_raise(rb_eIOError, "recv for buffered IO");
+ }
+
+ arg.fptr = fptr;
+ arg.fd = fptr->fd;
+ arg.alen = (socklen_t)sizeof(arg.buf);
+ arg.str = str;
+ arg.length = buflen;
+
+ while (true) {
+ rb_io_check_closed(fptr);
+
+#ifdef RSOCK_WAIT_BEFORE_BLOCKING
+ rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
+#endif
+
+ rb_str_locktmp(str);
+ slen = (long)rb_ensure(recvfrom_locktmp, (VALUE)&arg, rb_str_unlocktmp, str);
+
+ if (slen == 0 && !rsock_is_dgram(fptr)) {
+ return Qnil;
+ }
+ if (slen >= 0) break;
+
+ if (!rb_io_maybe_wait_readable(errno, socket, RUBY_IO_TIMEOUT_DEFAULT))
+ rb_sys_fail("recvfrom(2)");
+ }
+
+ /* Resize the string to the amount of data received */
+ rb_str_set_len(str, slen);
+ switch (from) {
+ case RECV_RECV:
+ return str;
+ case RECV_IP:
+#if 0
+ if (arg.alen != sizeof(struct sockaddr_in)) {
+ rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
+ }
+#endif
+ if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */
+ return rb_assoc_new(str, rsock_ipaddr(&arg.buf.addr, arg.alen, fptr->mode & FMODE_NOREVLOOKUP));
+ else
+ return rb_assoc_new(str, Qnil);
+
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ case RECV_UNIX:
+ return rb_assoc_new(str, rsock_unixaddr(&arg.buf.un, arg.alen));
+#endif
+ case RECV_SOCKET:
+ return rb_assoc_new(str, rsock_io_socket_addrinfo(socket, &arg.buf.addr, arg.alen));
+ default:
+ rb_bug("rsock_s_recvfrom called with bad value");
+ }
+}
+
+VALUE
+rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str,
+ VALUE ex, enum sock_recv_type from)
+{
+ rb_io_t *fptr;
+ union_sockaddr buf;
+ socklen_t alen = (socklen_t)sizeof buf;
+ long buflen;
+ long slen;
+ int fd, flags;
+ VALUE addr = Qnil;
+ socklen_t len0;
+
+ flags = NUM2INT(flg);
+ buflen = NUM2INT(len);
+ str = rsock_strbuf(str, buflen);
+
+#ifdef MSG_DONTWAIT
+ /* MSG_DONTWAIT avoids the race condition between fcntl and recvfrom.
+ It is not portable, though. */
+ flags |= MSG_DONTWAIT;
+#endif
+
+ GetOpenFile(sock, fptr);
+ if (rb_io_read_pending(fptr)) {
+ rb_raise(rb_eIOError, "recvfrom for buffered IO");
+ }
+ fd = fptr->fd;
+
+ rb_io_check_closed(fptr);
+
+ if (!MSG_DONTWAIT_RELIABLE)
+ rb_io_set_nonblock(fptr);
+
+ len0 = alen;
+ slen = recvfrom(fd, RSTRING_PTR(str), buflen, flags, &buf.addr, &alen);
+ if (slen != -1 && len0 < alen)
+ alen = len0;
+
+ if (slen == 0 && !rsock_is_dgram(fptr)) {
+ return Qnil;
+ }
+
+ if (slen < 0) {
+ int e = errno;
+ switch (e) {
+ case EAGAIN:
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ if (ex == Qfalse)
+ return sym_wait_readable;
+ rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "recvfrom(2) would block");
+ }
+ rb_syserr_fail(e, "recvfrom(2)");
+ }
+ if (slen != RSTRING_LEN(str)) {
+ rb_str_set_len(str, slen);
+ }
+ switch (from) {
+ case RECV_RECV:
+ return str;
+
+ case RECV_IP:
+ if (alen && alen != sizeof(buf)) /* connection-oriented socket may not return a from result */
+ addr = rsock_ipaddr(&buf.addr, alen, fptr->mode & FMODE_NOREVLOOKUP);
+ break;
+
+ case RECV_SOCKET:
+ addr = rsock_io_socket_addrinfo(sock, &buf.addr, alen);
+ break;
+
+ default:
+ rb_bug("rsock_s_recvfrom_nonblock called with bad value");
+ }
+ return rb_assoc_new(str, addr);
+}
+
+#if MSG_DONTWAIT_RELIABLE
+static VALUE sym_wait_writable;
+
+/* copied from io.c :< */
+static long
+read_buffered_data(char *ptr, long len, rb_io_t *fptr)
+{
+ int n = fptr->rbuf.len;
+
+ if (n <= 0) return 0;
+ if (n > len) n = (int)len;
+ MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
+ fptr->rbuf.off += n;
+ fptr->rbuf.len -= n;
+ return n;
+}
+
+/* :nodoc: */
+VALUE
+rsock_read_nonblock(VALUE sock, VALUE length, VALUE buf, VALUE ex)
+{
+ rb_io_t *fptr;
+ long n;
+ long len = NUM2LONG(length);
+ VALUE str = rsock_strbuf(buf, len);
+ char *ptr;
+
+ GetOpenFile(sock, fptr);
+
+ if (len == 0) {
+ rb_str_set_len(str, 0);
+ return str;
+ }
+
+ ptr = RSTRING_PTR(str);
+ n = read_buffered_data(ptr, len, fptr);
+ if (n <= 0) {
+ n = (long)recv(fptr->fd, ptr, len, MSG_DONTWAIT);
+ if (n < 0) {
+ int e = errno;
+ if ((e == EWOULDBLOCK || e == EAGAIN)) {
+ if (ex == Qfalse) return sym_wait_readable;
+ rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
+ e, "read would block");
+ }
+ rb_syserr_fail_path(e, fptr->pathv);
+ }
+ }
+ if (n != RSTRING_LEN(str)) {
+ rb_str_modify(str);
+ rb_str_set_len(str, n);
+ }
+ if (n == 0) {
+ if (ex == Qfalse) return Qnil;
+ rb_eof_error();
+ }
+
+ return str;
+}
+
+/* :nodoc: */
+VALUE
+rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex)
+{
+ rb_io_t *fptr;
+ long n;
+
+ if (!RB_TYPE_P(str, T_STRING))
+ str = rb_obj_as_string(str);
+
+ sock = rb_io_get_write_io(sock);
+ GetOpenFile(sock, fptr);
+ rb_io_check_writable(fptr);
+
+ /*
+ * As with IO#write_nonblock, we may block if somebody is relying on
+ * buffered I/O; but nobody actually hits this because pipes and sockets
+ * are not userspace-buffered in Ruby by default.
+ */
+ if (fptr->wbuf.len > 0) {
+ rb_io_flush(sock);
+ }
+
+#ifdef __APPLE__
+ again:
+#endif
+ n = (long)send(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str), MSG_DONTWAIT);
+ if (n < 0) {
+ int e = errno;
+
+#ifdef __APPLE__
+ if (e == EPROTOTYPE) {
+ goto again;
+ }
+#endif
+ if (e == EWOULDBLOCK || e == EAGAIN) {
+ if (ex == Qfalse) return sym_wait_writable;
+ rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e,
+ "write would block");
+ }
+ rb_syserr_fail_path(e, fptr->pathv);
+ }
+
+ return LONG2FIX(n);
+}
+#endif /* MSG_DONTWAIT_RELIABLE */
+
+static int
+rsock_socket0(int domain, int type, int proto)
+{
+#ifdef SOCK_CLOEXEC
+ type |= SOCK_CLOEXEC;
+#endif
+
+#ifdef SOCK_NONBLOCK
+ type |= SOCK_NONBLOCK;
+#endif
+
+ int result = socket(domain, type, proto);
+
+ if (result == -1)
+ return -1;
+
+ rb_fd_fix_cloexec(result);
+
+#ifndef SOCK_NONBLOCK
+ rsock_make_fd_nonblock(result);
+#endif
+
+ return result;
+}
+
+int
+rsock_socket(int domain, int type, int proto)
+{
+ int fd;
+
+ fd = rsock_socket0(domain, type, proto);
+ if (fd < 0) {
+ if (rb_gc_for_fd(errno)) {
+ fd = rsock_socket0(domain, type, proto);
+ }
+ }
+ if (0 <= fd)
+ rb_update_max_fd(fd);
+ return fd;
+}
+
+/* emulate blocking connect behavior on EINTR or non-blocking socket */
+static int
+wait_connectable(VALUE self, VALUE timeout, const struct sockaddr *sockaddr, int len)
+{
+ int sockerr;
+ socklen_t sockerrlen;
+ int fd = rb_io_descriptor(self);
+
+ sockerrlen = (socklen_t)sizeof(sockerr);
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen) < 0)
+ return -1;
+
+ /* necessary for non-blocking sockets (at least ECONNREFUSED) */
+ switch (sockerr) {
+ case 0:
+ break;
+#ifdef EALREADY
+ case EALREADY:
+#endif
+#ifdef EISCONN
+ case EISCONN:
+#endif
+#ifdef ECONNREFUSED
+ case ECONNREFUSED:
+#endif
+#ifdef EHOSTUNREACH
+ case EHOSTUNREACH:
+#endif
+ errno = sockerr;
+ return -1;
+ }
+
+ /*
+ * Stevens book says, successful finish turn on RB_WAITFD_OUT and
+ * failure finish turn on both RB_WAITFD_IN and RB_WAITFD_OUT.
+ * So it's enough to wait only RB_WAITFD_OUT and check the pending error
+ * by getsockopt().
+ *
+ * Note: rb_wait_for_single_fd already retries on EINTR/ERESTART
+ */
+ VALUE result = rb_io_wait(self, RB_INT2NUM(RUBY_IO_READABLE|RUBY_IO_WRITABLE), timeout);
+
+ if (result == Qfalse) {
+ VALUE rai = rsock_addrinfo_new((struct sockaddr *)sockaddr, len, PF_UNSPEC, 0, 0, Qnil, Qnil);
+ VALUE addr_str = rsock_addrinfo_inspect_sockaddr(rai);
+ rb_raise(rb_eIOTimeoutError, "user specified timeout for %" PRIsVALUE, addr_str);
+ }
+
+ int revents = RB_NUM2INT(result);
+
+ if (revents < 0)
+ return -1;
+
+ sockerrlen = (socklen_t)sizeof(sockerr);
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen) < 0)
+ return -1;
+
+ switch (sockerr) {
+ case 0:
+ /*
+ * be defensive in case some platforms set SO_ERROR on the original,
+ * interrupted connect()
+ */
+ case EINTR:
+#ifdef ERESTART
+ case ERESTART:
+#endif
+ case EAGAIN:
+#ifdef EINPROGRESS
+ case EINPROGRESS:
+#endif
+#ifdef EALREADY
+ case EALREADY:
+#endif
+#ifdef EISCONN
+ case EISCONN:
+#endif
+ return 0; /* success */
+ default:
+ /* likely (but not limited to): ECONNREFUSED, ETIMEDOUT, EHOSTUNREACH */
+ errno = sockerr;
+ return -1;
+ }
+
+ return 0;
+}
+
+struct connect_arg {
+ int fd;
+ socklen_t len;
+ const struct sockaddr *sockaddr;
+};
+
+static VALUE
+connect_blocking(void *data)
+{
+ struct connect_arg *arg = data;
+ return (VALUE)connect(arg->fd, arg->sockaddr, arg->len);
+}
+
+#if defined(SOCKS) && !defined(SOCKS5)
+static VALUE
+socks_connect_blocking(void *data)
+{
+ struct connect_arg *arg = data;
+ return (VALUE)Rconnect(arg->fd, arg->sockaddr, arg->len);
+}
+#endif
+
+int
+rsock_connect(VALUE self, const struct sockaddr *sockaddr, int len, int socks, VALUE timeout)
+{
+ int descriptor = rb_io_descriptor(self);
+ rb_blocking_function_t *func = connect_blocking;
+ struct connect_arg arg = {.fd = descriptor, .sockaddr = sockaddr, .len = len};
+
+ rb_io_t *fptr;
+ RB_IO_POINTER(self, fptr);
+
+#if defined(SOCKS) && !defined(SOCKS5)
+ if (socks) func = socks_connect_blocking;
+#endif
+ int status = (int)rb_io_blocking_region(fptr, func, &arg);
+
+ if (status < 0) {
+ switch (errno) {
+ case EINTR:
+#ifdef ERESTART
+ case ERESTART:
+#endif
+ case EAGAIN:
+#ifdef EINPROGRESS
+ case EINPROGRESS:
+#endif
+ return wait_connectable(self, timeout, sockaddr, len);
+ }
+ }
+ return status;
+}
+
+void
+rsock_make_fd_nonblock(int fd)
+{
+#ifdef _WIN32
+ return;
+#endif
+
+ int flags;
+#ifdef F_GETFL
+ flags = fcntl(fd, F_GETFL);
+ if (flags == -1) {
+ rb_sys_fail("fnctl(2)");
+ }
+#else
+ flags = 0;
+#endif
+ flags |= O_NONBLOCK;
+ if (fcntl(fd, F_SETFL, flags) == -1) {
+ rb_sys_fail("fnctl(2)");
+ }
+}
+
+static int
+cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
+{
+ socklen_t len0 = 0;
+ if (address_len) len0 = *address_len;
+
+#ifdef HAVE_ACCEPT4
+ int flags = SOCK_CLOEXEC;
+
+#ifdef SOCK_NONBLOCK
+ flags |= SOCK_NONBLOCK;
+#endif
+
+ int result = accept4(socket, address, address_len, flags);
+ if (result == -1) return -1;
+
+#ifndef SOCK_NONBLOCK
+ rsock_make_fd_nonblock(result);
+#endif
+#else
+ int result = accept(socket, address, address_len);
+ if (result == -1) return -1;
+
+ rb_maygvl_fd_fix_cloexec(result);
+ rsock_make_fd_nonblock(result);
+#endif
+
+ if (address_len && len0 < *address_len) *address_len = len0;
+ return result;
+}
+
+VALUE
+rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr,
+ struct sockaddr *sockaddr, socklen_t *len)
+{
+ int fd2;
+
+ rb_io_set_nonblock(fptr);
+ fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len);
+ if (fd2 < 0) {
+ int e = errno;
+ switch (e) {
+ case EAGAIN:
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ case ECONNABORTED:
+#if defined EPROTO
+ case EPROTO:
+#endif
+ if (ex == Qfalse)
+ return sym_wait_readable;
+ rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "accept(2) would block");
+ }
+ rb_syserr_fail(e, "accept(2)");
+ }
+ rb_update_max_fd(fd2);
+ return rsock_init_sock(rb_obj_alloc(klass), fd2);
+}
+
+struct accept_arg {
+ int fd;
+ struct sockaddr *sockaddr;
+ socklen_t *len;
+};
+
+static VALUE
+accept_blocking(void *data)
+{
+ struct accept_arg *arg = data;
+ return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len);
+}
+
+VALUE
+rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len)
+{
+ rb_io_t *fptr = NULL;
+ RB_IO_POINTER(io, fptr);
+
+ struct accept_arg accept_arg = {
+ .fd = fptr->fd,
+ .sockaddr = sockaddr,
+ .len = len
+ };
+
+ int retry = 0, peer;
+
+ retry:
+#ifdef RSOCK_WAIT_BEFORE_BLOCKING
+ rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
+#endif
+ peer = (int)rb_io_blocking_region(fptr, accept_blocking, &accept_arg);
+ if (peer < 0) {
+ int error = errno;
+
+ switch (error) {
+ case EMFILE:
+ case ENFILE:
+ case ENOMEM:
+ if (retry) break;
+ rb_gc();
+ retry = 1;
+ goto retry;
+ default:
+ if (!rb_io_maybe_wait_readable(error, io, RUBY_IO_TIMEOUT_DEFAULT)) break;
+ retry = 0;
+ goto retry;
+ }
+
+ rb_syserr_fail(error, "accept(2)");
+ }
+
+ rb_update_max_fd(peer);
+
+ if (!klass) return INT2NUM(peer);
+
+ return rsock_init_sock(rb_obj_alloc(klass), peer);
+}
+
+int
+rsock_getfamily(rb_io_t *fptr)
+{
+ union_sockaddr ss;
+ socklen_t sslen = (socklen_t)sizeof(ss);
+ int cached = fptr->mode & FMODE_SOCK;
+
+ if (cached) {
+ switch (cached) {
+#ifdef AF_UNIX
+ case FMODE_UNIX: return AF_UNIX;
+#endif
+ case FMODE_INET: return AF_INET;
+ case FMODE_INET6: return AF_INET6;
+ }
+ }
+
+ ss.addr.sa_family = AF_UNSPEC;
+ if (getsockname(fptr->fd, &ss.addr, &sslen) < 0)
+ return AF_UNSPEC;
+
+ switch (ss.addr.sa_family) {
+#ifdef AF_UNIX
+ case AF_UNIX: fptr->mode |= FMODE_UNIX; break;
+#endif
+ case AF_INET: fptr->mode |= FMODE_INET; break;
+ case AF_INET6: fptr->mode |= FMODE_INET6; break;
+ }
+
+ return ss.addr.sa_family;
+}
+
+/*
+ * call-seq:
+ * error_code -> integer
+ *
+ * Returns the raw error code indicating the cause of the hostname resolution failure.
+ *
+ * begin
+ * Addrinfo.getaddrinfo("ruby-lang.org", nil)
+ * rescue Socket::ResolutionError => e
+ * if e.error_code == Socket::EAI_AGAIN
+ * puts "Temporary failure in name resolution."
+ * end
+ * end
+ *
+ * Note that error codes depend on the operating system.
+ */
+static VALUE
+sock_resolv_error_code(VALUE self)
+{
+ return rb_attr_get(self, id_error_code);
+}
+
+void
+rsock_init_socket_init(void)
+{
+ /*
+ * SocketError is the error class for socket.
+ */
+ rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
+ /*
+ * Socket::ResolutionError is the error class for hostname resolution.
+ */
+ rb_eResolution = rb_define_class_under(rb_cSocket, "ResolutionError", rb_eSocket);
+ rb_define_method(rb_eResolution, "error_code", sock_resolv_error_code, 0);
+ rsock_init_ipsocket();
+ rsock_init_tcpsocket();
+ rsock_init_tcpserver();
+ rsock_init_sockssocket();
+ rsock_init_udpsocket();
+ rsock_init_unixsocket();
+ rsock_init_unixserver();
+ rsock_init_sockopt();
+ rsock_init_ancdata();
+ rsock_init_addrinfo();
+ rsock_init_sockifaddr();
+ rsock_init_socket_constants();
+
+ id_error_code = rb_intern_const("error_code");
+
+#undef rb_intern
+ sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
+
+#if MSG_DONTWAIT_RELIABLE
+ sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
+#endif
+}
diff --git a/ext/socket/ipsocket.c b/ext/socket/ipsocket.c
new file mode 100644
index 0000000000..e1943b8496
--- /dev/null
+++ b/ext/socket/ipsocket.c
@@ -0,0 +1,1640 @@
+/************************************************
+
+ ipsocket.c -
+
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
+
+************************************************/
+
+#include "rubysocket.h"
+#include <stdio.h>
+
+struct inetsock_arg
+{
+ VALUE self;
+ VALUE io;
+
+ struct {
+ VALUE host, serv;
+ struct rb_addrinfo *res;
+ } remote, local;
+ int type;
+ VALUE resolv_timeout;
+ VALUE connect_timeout;
+ VALUE open_timeout;
+};
+
+void
+rsock_raise_user_specified_timeout(struct addrinfo *ai, VALUE host, VALUE port)
+{
+ VALUE message;
+
+ if (ai && ai->ai_addr) {
+ VALUE rai = rsock_addrinfo_new((struct sockaddr *)ai->ai_addr, (socklen_t)ai->ai_addrlen, PF_UNSPEC, 0, 0, Qnil, Qnil);
+ VALUE addr_str = rsock_addrinfo_inspect_sockaddr(rai);
+ message = rb_sprintf("user specified timeout for %" PRIsVALUE, addr_str);
+ } else {
+ message = rb_sprintf("user specified timeout for %" PRIsVALUE " port %" PRIsVALUE, host, port);
+ }
+
+ rb_exc_raise(rb_exc_new_str(rb_eIOTimeoutError, message));
+}
+
+static VALUE
+inetsock_cleanup(VALUE v)
+{
+ struct inetsock_arg *arg = (void *)v;
+ if (arg->remote.res) {
+ rb_freeaddrinfo(arg->remote.res);
+ arg->remote.res = 0;
+ }
+ if (arg->local.res) {
+ rb_freeaddrinfo(arg->local.res);
+ arg->local.res = 0;
+ }
+ if (arg->io != Qnil) {
+ rb_io_close(arg->io);
+ arg->io = Qnil;
+ }
+ return Qnil;
+}
+
+static VALUE
+current_clocktime(void)
+{
+ VALUE clock_monotnic_const = rb_const_get(rb_mProcess, rb_intern("CLOCK_MONOTONIC"));
+ return rb_funcall(rb_mProcess, rb_intern("clock_gettime"), 1, clock_monotnic_const);
+}
+
+static VALUE
+init_inetsock_internal(VALUE v)
+{
+ struct inetsock_arg *arg = (void *)v;
+ int error = 0;
+ int type = arg->type;
+ struct addrinfo *res, *lres;
+ int status = 0, local = 0;
+ int family = AF_UNSPEC;
+ const char *syscall = 0;
+ VALUE resolv_timeout = arg->resolv_timeout;
+ VALUE connect_timeout = arg->connect_timeout;
+ VALUE open_timeout = arg->open_timeout;
+ VALUE timeout;
+ VALUE starts_at;
+
+ timeout = NIL_P(open_timeout) ? resolv_timeout : open_timeout;
+ starts_at = current_clocktime();
+
+ arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv,
+ family, SOCK_STREAM,
+ (type == INET_SERVER) ? AI_PASSIVE : 0, timeout);
+
+ /*
+ * Maybe also accept a local address
+ */
+
+ if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) {
+ arg->local.res = rsock_addrinfo(arg->local.host, arg->local.serv,
+ family, SOCK_STREAM, 0, timeout);
+ }
+
+ VALUE io = Qnil;
+
+ for (res = arg->remote.res->ai; res; res = res->ai_next) {
+#if !defined(INET6) && defined(AF_INET6)
+ if (res->ai_family == AF_INET6)
+ continue;
+#endif
+ lres = NULL;
+ if (arg->local.res) {
+ for (lres = arg->local.res->ai; lres; lres = lres->ai_next) {
+ if (lres->ai_family == res->ai_family)
+ break;
+ }
+ if (!lres) {
+ if (res->ai_next || status < 0)
+ continue;
+ /* Use a different family local address if no choice, this
+ * will cause EAFNOSUPPORT. */
+ lres = arg->local.res->ai;
+ }
+ }
+ status = rsock_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
+ syscall = "socket(2)";
+ if (status < 0) {
+ error = errno;
+ continue;
+ }
+
+ int fd = status;
+ io = arg->io = rsock_init_sock(arg->self, fd);
+
+ if (type == INET_SERVER) {
+#if !defined(_WIN32) && !defined(__CYGWIN__)
+ status = 1;
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+ (char*)&status, (socklen_t)sizeof(status));
+#endif
+ status = bind(fd, res->ai_addr, res->ai_addrlen);
+ syscall = "bind(2)";
+ }
+ else {
+ if (lres) {
+#if !defined(_WIN32) && !defined(__CYGWIN__)
+ status = 1;
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+ (char*)&status, (socklen_t)sizeof(status));
+#endif
+ status = bind(fd, lres->ai_addr, lres->ai_addrlen);
+ local = status;
+ syscall = "bind(2)";
+ }
+
+ if (NIL_P(open_timeout)) {
+ timeout = connect_timeout;
+ } else {
+ VALUE elapsed = rb_funcall(current_clocktime(), '-', 1, starts_at);
+ timeout = rb_funcall(open_timeout, '-', 1, elapsed);
+ if (rb_funcall(timeout, '<', 1, INT2FIX(0)) == Qtrue) {
+ rsock_raise_user_specified_timeout(res, arg->remote.host, arg->remote.serv);
+ }
+ }
+
+ if (status >= 0) {
+ status = rsock_connect(io, res->ai_addr, res->ai_addrlen, (type == INET_SOCKS), timeout);
+ syscall = "connect(2)";
+ }
+ }
+
+ if (status < 0) {
+ error = errno;
+ arg->io = Qnil;
+ rb_io_close(io);
+ io = Qnil;
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ if (status < 0) {
+ VALUE host, port;
+
+ if (local < 0) {
+ host = arg->local.host;
+ port = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ port = arg->remote.serv;
+ }
+
+ rsock_syserr_fail_host_port(error, syscall, host, port);
+ }
+
+ // Don't close the socket in `inetsock_cleanup` if we are returning it:
+ arg->io = Qnil;
+
+ if (type == INET_SERVER && io != Qnil) {
+ status = listen(rb_io_descriptor(io), SOMAXCONN);
+ if (status < 0) {
+ error = errno;
+ rb_io_close(io);
+ rb_syserr_fail(error, "listen(2)");
+ }
+ }
+
+ /* create new instance */
+ return io;
+}
+
+#if FAST_FALLBACK_INIT_INETSOCK_IMPL == 0
+
+VALUE
+rsock_init_inetsock(
+ VALUE self, VALUE remote_host, VALUE remote_serv,
+ VALUE local_host, VALUE local_serv, int type,
+ VALUE resolv_timeout, VALUE connect_timeout, VALUE open_timeout,
+ VALUE _fast_fallback, VALUE _test_mode_settings)
+{
+ if (!NIL_P(open_timeout) && (!NIL_P(resolv_timeout) || !NIL_P(connect_timeout))) {
+ rb_raise(rb_eArgError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout");
+ }
+
+ struct inetsock_arg arg;
+ arg.self = self;
+ arg.io = Qnil;
+ arg.remote.host = remote_host;
+ arg.remote.serv = remote_serv;
+ arg.remote.res = 0;
+ arg.local.host = local_host;
+ arg.local.serv = local_serv;
+ arg.local.res = 0;
+ arg.type = type;
+ arg.resolv_timeout = resolv_timeout;
+ arg.connect_timeout = connect_timeout;
+ arg.open_timeout = open_timeout;
+ return rb_ensure(init_inetsock_internal, (VALUE)&arg,
+ inetsock_cleanup, (VALUE)&arg);
+}
+
+#elif FAST_FALLBACK_INIT_INETSOCK_IMPL == 1
+
+#define IPV6_ENTRY_POS 0
+#define IPV4_ENTRY_POS 1
+#define RESOLUTION_ERROR 0
+#define SYSCALL_ERROR 1
+
+static int
+is_specified_ip_address(const char *hostname)
+{
+ if (!hostname) return false;
+
+ struct in_addr ipv4addr;
+ struct in6_addr ipv6addr;
+
+ return (inet_pton(AF_INET6, hostname, &ipv6addr) == 1 ||
+ inet_pton(AF_INET, hostname, &ipv4addr) == 1);
+}
+
+static int
+is_local_port_fixed(const char *portp)
+{
+ if (!portp) return 0;
+
+ char *endp;
+ errno = 0;
+ long port = strtol(portp, &endp, 10);
+
+ if (endp == portp) return 0;
+ if (errno == ERANGE) return 0;
+
+ return port > 0;
+}
+
+struct fast_fallback_inetsock_arg
+{
+ VALUE self;
+ VALUE io;
+
+ struct {
+ VALUE host, serv;
+ struct rb_addrinfo *res;
+ } remote, local;
+ int type;
+ VALUE resolv_timeout;
+ VALUE connect_timeout;
+ VALUE open_timeout;
+
+ const char *hostp, *portp;
+ int *families;
+ int family_size;
+ int additional_flags;
+ struct fast_fallback_getaddrinfo_entry *getaddrinfo_entries[2];
+ struct fast_fallback_getaddrinfo_shared *getaddrinfo_shared;
+ rb_fdset_t readfds, writefds;
+ int wait;
+ int connection_attempt_fds_size;
+ int *connection_attempt_fds;
+ VALUE test_mode_settings;
+};
+
+static struct fast_fallback_getaddrinfo_shared *
+allocate_fast_fallback_getaddrinfo_shared(int family_size)
+{
+ struct fast_fallback_getaddrinfo_shared *shared;
+
+ shared = (struct fast_fallback_getaddrinfo_shared *)calloc(
+ 1,
+ sizeof(struct fast_fallback_getaddrinfo_shared) + (family_size == 1 ? 0 : 2) * sizeof(struct fast_fallback_getaddrinfo_entry)
+ );
+
+ return shared;
+}
+
+static void
+allocate_fast_fallback_getaddrinfo_hints(struct addrinfo *hints, int family, int remote_addrinfo_hints, int additional_flags)
+{
+ MEMZERO(hints, struct addrinfo, 1);
+ hints->ai_family = family;
+ hints->ai_socktype = SOCK_STREAM;
+ hints->ai_protocol = IPPROTO_TCP;
+ hints->ai_flags = remote_addrinfo_hints;
+ hints->ai_flags |= additional_flags;
+}
+
+static int*
+allocate_connection_attempt_fds(int additional_capacity)
+{
+ int *fds = (int *)malloc(additional_capacity * sizeof(int));
+ if (!fds) rb_syserr_fail(errno, "malloc(3)");
+ for (int i = 0; i < additional_capacity; i++) fds[i] = -1;
+ return fds;
+}
+
+static int
+reallocate_connection_attempt_fds(int **fds, int current_capacity, int additional_capacity)
+{
+ int new_capacity = current_capacity + additional_capacity;
+ int *new_fds;
+
+ new_fds = realloc(*fds, new_capacity * sizeof(int));
+ if (new_fds == NULL) {
+ rb_syserr_fail(errno, "realloc(3)");
+ }
+ *fds = new_fds;
+
+ for (int i = current_capacity; i < new_capacity; i++) (*fds)[i] = -1;
+ return new_capacity;
+}
+
+struct hostname_resolution_result
+{
+ struct addrinfo *ai;
+ int finished;
+ int has_error;
+};
+
+struct hostname_resolution_store
+{
+ struct hostname_resolution_result v6;
+ struct hostname_resolution_result v4;
+ int is_all_finished;
+};
+
+static int
+any_addrinfos(struct hostname_resolution_store *resolution_store)
+{
+ return resolution_store->v6.ai || resolution_store->v4.ai;
+}
+
+static struct timespec
+current_clocktime_ts(void)
+{
+ struct timespec ts;
+ if ((clock_gettime(CLOCK_MONOTONIC, &ts)) < 0) {
+ rb_syserr_fail(errno, "clock_gettime(2)");
+ }
+ return ts;
+}
+
+static void
+set_timeout_tv(struct timeval *tv, long ms, struct timespec from)
+{
+ long sec = ms / 1000;
+ long nsec = (ms % 1000) * 1000000;
+ long result_sec = from.tv_sec + sec;
+ long result_nsec = from.tv_nsec + nsec;
+
+ result_sec += result_nsec / 1000000000;
+ result_nsec = result_nsec % 1000000000;
+
+ tv->tv_sec = result_sec;
+ tv->tv_usec = (int)(result_nsec / 1000);
+}
+
+static struct timeval
+add_ts_to_tv(struct timeval tv, struct timespec ts)
+{
+ long ts_usec = ts.tv_nsec / 1000;
+ tv.tv_sec += ts.tv_sec;
+ tv.tv_usec += ts_usec;
+
+ if (tv.tv_usec >= 1000000) {
+ tv.tv_sec += tv.tv_usec / 1000000;
+ tv.tv_usec = tv.tv_usec % 1000000;
+ }
+
+ return tv;
+}
+
+static VALUE
+tv_to_seconds(struct timeval *timeout) {
+ if (timeout == NULL) return Qnil;
+
+ double seconds = (double)timeout->tv_sec + (double)timeout->tv_usec / 1000000.0;
+
+ return DBL2NUM(seconds);
+}
+
+static int
+is_infinity(struct timeval tv)
+{
+ // { -1, -1 } as infinity
+ return tv.tv_sec == -1 || tv.tv_usec == -1;
+}
+
+static int
+is_timeout_tv(struct timeval *timeout_tv, struct timespec now) {
+ if (!timeout_tv) return false;
+ if (timeout_tv->tv_sec == -1 && timeout_tv->tv_usec == -1) return false;
+
+ struct timespec ts;
+ ts.tv_sec = timeout_tv->tv_sec;
+ ts.tv_nsec = timeout_tv->tv_usec * 1000;
+
+ if (now.tv_sec > ts.tv_sec) return true;
+ if (now.tv_sec == ts.tv_sec && now.tv_nsec >= ts.tv_nsec) return true;
+ return false;
+}
+
+static struct timeval *
+select_expires_at(
+ struct hostname_resolution_store *resolution_store,
+ struct timeval *resolution_delay,
+ struct timeval *connection_attempt_delay,
+ struct timeval *user_specified_resolv_timeout_at,
+ struct timeval *user_specified_connect_timeout_at,
+ struct timeval *user_specified_open_timeout_at)
+{
+ if (any_addrinfos(resolution_store)) {
+ struct timeval *delay;
+ delay = resolution_delay ? resolution_delay : connection_attempt_delay;
+
+ if (user_specified_open_timeout_at &&
+ timercmp(user_specified_open_timeout_at, delay, <)) {
+ return user_specified_open_timeout_at;
+ }
+ return delay;
+ }
+
+ if (user_specified_open_timeout_at) return user_specified_open_timeout_at;
+
+ struct timeval *timeout = NULL;
+
+ if (user_specified_resolv_timeout_at) {
+ if (is_infinity(*user_specified_resolv_timeout_at)) return NULL;
+ timeout = user_specified_resolv_timeout_at;
+ }
+
+ if (user_specified_connect_timeout_at) {
+ if (is_infinity(*user_specified_connect_timeout_at)) return NULL;
+ if (!timeout || timercmp(user_specified_connect_timeout_at, timeout, >)) {
+ return user_specified_connect_timeout_at;
+ }
+ }
+
+ return timeout;
+}
+
+static struct timeval
+tv_to_timeout(struct timeval *ends_at, struct timespec now)
+{
+ struct timeval delay;
+ struct timespec expires_at;
+ expires_at.tv_sec = ends_at->tv_sec;
+ expires_at.tv_nsec = ends_at->tv_usec * 1000;
+
+ struct timespec diff;
+ diff.tv_sec = expires_at.tv_sec - now.tv_sec;
+
+ if (expires_at.tv_nsec >= now.tv_nsec) {
+ diff.tv_nsec = expires_at.tv_nsec - now.tv_nsec;
+ } else {
+ diff.tv_sec -= 1;
+ diff.tv_nsec = (1000000000 + expires_at.tv_nsec) - now.tv_nsec;
+ }
+
+ delay.tv_sec = diff.tv_sec;
+ delay.tv_usec = (int)diff.tv_nsec / 1000;
+
+ return delay;
+}
+
+static struct addrinfo *
+pick_addrinfo(struct hostname_resolution_store *resolution_store, int last_family)
+{
+ int priority_on_v6[2] = { AF_INET6, AF_INET };
+ int priority_on_v4[2] = { AF_INET, AF_INET6 };
+ int *precedences = last_family == AF_INET6 ? priority_on_v4 : priority_on_v6;
+ struct addrinfo *selected_ai = NULL;
+
+ for (int i = 0; i < 2; i++) {
+ if (precedences[i] == AF_INET6) {
+ selected_ai = resolution_store->v6.ai;
+ if (selected_ai) {
+ resolution_store->v6.ai = selected_ai->ai_next;
+ break;
+ }
+ } else {
+ selected_ai = resolution_store->v4.ai;
+ if (selected_ai) {
+ resolution_store->v4.ai = selected_ai->ai_next;
+ break;
+ }
+ }
+ }
+ return selected_ai;
+}
+
+static void
+socket_nonblock_set(int fd)
+{
+ int flags = fcntl(fd, F_GETFL);
+
+ if (flags < 0) rb_syserr_fail(errno, "fcntl(2)");
+ if ((flags & O_NONBLOCK) != 0) return;
+
+ flags |= O_NONBLOCK;
+
+ if (fcntl(fd, F_SETFL, flags) < 0) rb_syserr_fail(errno, "fcntl(2)");
+ return;
+}
+
+static int
+in_progress_fds(int fds_size)
+{
+ return fds_size > 0;
+}
+
+static void
+remove_connection_attempt_fd(int *fds, int *fds_size, int removing_fd)
+{
+ int i, j;
+
+ for (i = 0; i < *fds_size; i++) {
+ if (fds[i] != removing_fd) continue;
+
+ for (j = i; j < *fds_size - 1; j++) {
+ fds[j] = fds[j + 1];
+ }
+
+ (*fds_size)--;
+ fds[*fds_size] = -1;
+ break;
+ }
+}
+
+struct fast_fallback_error
+{
+ int type;
+ int ecode;
+};
+
+static VALUE
+init_fast_fallback_inetsock_internal(VALUE v)
+{
+ struct fast_fallback_inetsock_arg *arg = (void *)v;
+ VALUE io = arg->io;
+ VALUE resolv_timeout = arg->resolv_timeout;
+ VALUE connect_timeout = arg->connect_timeout;
+ VALUE open_timeout = arg->open_timeout;
+ VALUE test_mode_settings = arg->test_mode_settings;
+ struct addrinfo *remote_ai = NULL, *local_ai = NULL;
+ int connected_fd = -1, status = 0, local_status = 0;
+ int remote_addrinfo_hints = 0;
+ struct fast_fallback_error last_error = { 0, 0 };
+ const char *syscall = 0;
+ VALUE host, serv;
+
+ #ifdef HAVE_CONST_AI_ADDRCONFIG
+ remote_addrinfo_hints |= AI_ADDRCONFIG;
+ #endif
+
+ pthread_t threads[arg->family_size];
+ char resolved_type[2];
+ ssize_t resolved_type_size;
+ int hostname_resolution_waiter = -1, hostname_resolution_notifier = -1;
+ int pipefd[2];
+
+ int nfds = 0;
+ struct timeval *ends_at = NULL;
+ struct timeval delay = (struct timeval){ -1, -1 };
+ struct timeval *delay_p = NULL;
+
+ struct hostname_resolution_store resolution_store;
+ resolution_store.is_all_finished = false;
+ resolution_store.v6.ai = NULL;
+ resolution_store.v6.finished = false;
+ resolution_store.v6.has_error = false;
+ resolution_store.v4.ai = NULL;
+ resolution_store.v4.finished = false;
+ resolution_store.v4.has_error = false;
+
+ int last_family = 0;
+ int additional_capacity = 10;
+ int current_capacity = additional_capacity;
+ arg->connection_attempt_fds = allocate_connection_attempt_fds(additional_capacity);
+ arg->connection_attempt_fds_size = 0;
+
+ struct timeval resolution_delay_storage;
+ struct timeval *resolution_delay_expires_at = NULL;
+ struct timeval connection_attempt_delay_strage;
+ struct timeval *connection_attempt_delay_expires_at = NULL;
+ struct timeval user_specified_resolv_timeout_storage;
+ struct timeval *user_specified_resolv_timeout_at = NULL;
+ struct timeval user_specified_connect_timeout_storage;
+ struct timeval *user_specified_connect_timeout_at = NULL;
+ struct timeval user_specified_open_timeout_storage;
+ struct timeval *user_specified_open_timeout_at = NULL;
+ struct timespec now = current_clocktime_ts();
+ VALUE starts_at = current_clocktime();
+
+ if (!NIL_P(open_timeout)) {
+ struct timeval open_timeout_tv = rb_time_interval(open_timeout);
+ user_specified_open_timeout_storage = add_ts_to_tv(open_timeout_tv, now);
+ user_specified_open_timeout_at = &user_specified_open_timeout_storage;
+ }
+
+ /* start of hostname resolution */
+ if (arg->family_size == 1) {
+ arg->wait = -1;
+ arg->getaddrinfo_shared = NULL;
+
+ int family = arg->families[0];
+ VALUE t = NIL_P(open_timeout) ? resolv_timeout : open_timeout;
+
+ arg->remote.res = rsock_addrinfo(
+ arg->remote.host,
+ arg->remote.serv,
+ family,
+ SOCK_STREAM,
+ 0,
+ t
+ );
+
+ if (family == AF_INET6) {
+ resolution_store.v6.ai = arg->remote.res->ai;
+ resolution_store.v6.finished = true;
+ resolution_store.v4.finished = true;
+ } else if (family == AF_INET) {
+ resolution_store.v4.ai = arg->remote.res->ai;
+ resolution_store.v4.finished = true;
+ resolution_store.v6.finished = true;
+ }
+ resolution_store.is_all_finished = true;
+ } else {
+ if (pipe(pipefd) != 0) rb_syserr_fail(errno, "pipe(2)");
+ hostname_resolution_waiter = pipefd[0];
+ int waiter_flags = fcntl(hostname_resolution_waiter, F_GETFL, 0);
+ if (waiter_flags < 0) rb_syserr_fail(errno, "fcntl(2)");
+ if ((fcntl(hostname_resolution_waiter, F_SETFL, waiter_flags | O_NONBLOCK)) < 0) {
+ rb_syserr_fail(errno, "fcntl(2)");
+ }
+ arg->wait = hostname_resolution_waiter;
+ hostname_resolution_notifier = pipefd[1];
+
+ arg->getaddrinfo_shared = allocate_fast_fallback_getaddrinfo_shared(arg->family_size);
+ if (!arg->getaddrinfo_shared) rb_syserr_fail(errno, "calloc(3)");
+
+ rb_nativethread_lock_initialize(&arg->getaddrinfo_shared->lock);
+ arg->getaddrinfo_shared->notify = hostname_resolution_notifier;
+
+ arg->getaddrinfo_shared->node = arg->hostp ? ruby_strdup(arg->hostp) : NULL;
+ arg->getaddrinfo_shared->service = arg->portp ? ruby_strdup(arg->portp) : NULL;
+ arg->getaddrinfo_shared->refcount = arg->family_size + 1;
+
+ for (int i = 0; i < arg->family_size; i++) {
+ arg->getaddrinfo_entries[i] = &arg->getaddrinfo_shared->getaddrinfo_entries[i];
+ arg->getaddrinfo_entries[i]->shared = arg->getaddrinfo_shared;
+
+ struct addrinfo getaddrinfo_hints[arg->family_size];
+
+ allocate_fast_fallback_getaddrinfo_hints(
+ &getaddrinfo_hints[i],
+ arg->families[i],
+ remote_addrinfo_hints,
+ arg->additional_flags
+ );
+
+ arg->getaddrinfo_entries[i]->hints = getaddrinfo_hints[i];
+ arg->getaddrinfo_entries[i]->ai = NULL;
+ arg->getaddrinfo_entries[i]->family = arg->families[i];
+ arg->getaddrinfo_entries[i]->refcount = 2;
+ arg->getaddrinfo_entries[i]->has_syserr = false;
+ arg->getaddrinfo_entries[i]->test_sleep_ms = 0;
+ arg->getaddrinfo_entries[i]->test_ecode = 0;
+
+ /* for testing HEv2 */
+ if (!NIL_P(test_mode_settings) && RB_TYPE_P(test_mode_settings, T_HASH)) {
+ const char *family_sym = arg->families[i] == AF_INET6 ? "ipv6" : "ipv4";
+
+ VALUE test_delay_setting = rb_hash_aref(test_mode_settings, ID2SYM(rb_intern("delay")));
+ if (!NIL_P(test_delay_setting)) {
+ VALUE rb_test_delay_ms = rb_hash_aref(test_delay_setting, ID2SYM(rb_intern(family_sym)));
+ long test_delay_ms = NIL_P(rb_test_delay_ms) ? 0 : rb_test_delay_ms;
+ arg->getaddrinfo_entries[i]->test_sleep_ms = test_delay_ms;
+ }
+
+ VALUE test_error_setting = rb_hash_aref(test_mode_settings, ID2SYM(rb_intern("error")));
+ if (!NIL_P(test_error_setting)) {
+ VALUE rb_test_ecode = rb_hash_aref(test_error_setting, ID2SYM(rb_intern(family_sym)));
+ if (!NIL_P(rb_test_ecode)) {
+ arg->getaddrinfo_entries[i]->test_ecode = NUM2INT(rb_test_ecode);
+ }
+ }
+ }
+
+ if (raddrinfo_pthread_create(&threads[i], fork_safe_do_fast_fallback_getaddrinfo, arg->getaddrinfo_entries[i]) != 0) {
+ rsock_raise_resolution_error("getaddrinfo(3)", EAI_AGAIN);
+ }
+ }
+
+ if (NIL_P(resolv_timeout)) {
+ user_specified_resolv_timeout_storage = (struct timeval){ -1, -1 };
+ } else {
+ struct timeval resolv_timeout_tv = rb_time_interval(resolv_timeout);
+ user_specified_resolv_timeout_storage = add_ts_to_tv(resolv_timeout_tv, now);
+ }
+ user_specified_resolv_timeout_at = &user_specified_resolv_timeout_storage;
+ }
+
+ while (true) {
+ /* start of connection */
+ if (any_addrinfos(&resolution_store) &&
+ !resolution_delay_expires_at &&
+ !connection_attempt_delay_expires_at) {
+ while ((remote_ai = pick_addrinfo(&resolution_store, last_family))) {
+ int fd = -1;
+
+ #if !defined(INET6) && defined(AF_INET6)
+ if (remote_ai->ai_family == AF_INET6) {
+ if (any_addrinfos(&resolution_store)) continue;
+ if (!in_progress_fds(arg->connection_attempt_fds_size)) break;
+ if (resolution_store.is_all_finished) break;
+
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+ #endif
+
+ local_ai = NULL;
+
+ if (arg->local.res) {
+ for (local_ai = arg->local.res->ai; local_ai; local_ai = local_ai->ai_next) {
+ if (local_ai->ai_family == remote_ai->ai_family) break;
+ }
+ if (!local_ai) {
+ if (any_addrinfos(&resolution_store)) continue;
+ if (in_progress_fds(arg->connection_attempt_fds_size)) break;
+ if (!resolution_store.is_all_finished) break;
+
+ /* Use a different family local address if no choice, this
+ * will cause EAFNOSUPPORT. */
+ rsock_syserr_fail_host_port(EAFNOSUPPORT, syscall, arg->local.host, arg->local.serv);
+ }
+ }
+
+ status = rsock_socket(remote_ai->ai_family, remote_ai->ai_socktype, remote_ai->ai_protocol);
+ syscall = "socket(2)";
+
+ if (status < 0) {
+ last_error.type = SYSCALL_ERROR;
+ last_error.ecode = errno;
+
+ if (any_addrinfos(&resolution_store)) continue;
+ if (in_progress_fds(arg->connection_attempt_fds_size)) break;
+ if (!resolution_store.is_all_finished) break;
+
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+
+ fd = status;
+
+ if (local_ai) {
+ #if !defined(_WIN32) && !defined(__CYGWIN__)
+ status = 1;
+ if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&status, (socklen_t)sizeof(status))) < 0) {
+ rb_syserr_fail(errno, "setsockopt(2)");
+ }
+ #endif
+ status = bind(fd, local_ai->ai_addr, local_ai->ai_addrlen);
+ local_status = status;
+ syscall = "bind(2)";
+
+ if (status < 0) {
+ last_error.type = SYSCALL_ERROR;
+ last_error.ecode = errno;
+ close(fd);
+
+ if (any_addrinfos(&resolution_store)) continue;
+ if (in_progress_fds(arg->connection_attempt_fds_size)) break;
+ if (!resolution_store.is_all_finished) break;
+
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+ }
+
+ syscall = "connect(2)";
+
+ if (any_addrinfos(&resolution_store) ||
+ in_progress_fds(arg->connection_attempt_fds_size) ||
+ !resolution_store.is_all_finished) {
+ socket_nonblock_set(fd);
+ status = connect(fd, remote_ai->ai_addr, remote_ai->ai_addrlen);
+ last_family = remote_ai->ai_family;
+ } else {
+ VALUE timeout = Qnil;
+
+ if (!NIL_P(open_timeout)) {
+ VALUE elapsed = rb_funcall(current_clocktime(), '-', 1, starts_at);
+ timeout = rb_funcall(open_timeout, '-', 1, elapsed);
+
+ if (rb_funcall(timeout, '<', 1, INT2FIX(0)) == Qtrue) {
+ rsock_raise_user_specified_timeout(NULL, arg->remote.host, arg->remote.serv);
+ }
+ }
+ if (NIL_P(timeout)) {
+ if (!NIL_P(connect_timeout)) {
+ user_specified_connect_timeout_storage = rb_time_interval(connect_timeout);
+ user_specified_connect_timeout_at = &user_specified_connect_timeout_storage;
+ }
+ timeout =
+ (user_specified_connect_timeout_at && is_infinity(*user_specified_connect_timeout_at)) ?
+ Qnil : tv_to_seconds(user_specified_connect_timeout_at);
+ }
+
+ io = arg->io = rsock_init_sock(arg->self, fd);
+ status = rsock_connect(io, remote_ai->ai_addr, remote_ai->ai_addrlen, 0, timeout);
+ }
+
+ if (status == 0) {
+ connected_fd = fd;
+ break;
+ }
+
+ if (errno == EINPROGRESS) {
+ if (current_capacity == arg->connection_attempt_fds_size) {
+ current_capacity = reallocate_connection_attempt_fds(
+ &arg->connection_attempt_fds,
+ current_capacity,
+ additional_capacity
+ );
+ }
+ arg->connection_attempt_fds[arg->connection_attempt_fds_size] = fd;
+ (arg->connection_attempt_fds_size)++;
+
+ set_timeout_tv(&connection_attempt_delay_strage, 250, now);
+ connection_attempt_delay_expires_at = &connection_attempt_delay_strage;
+
+ if (!any_addrinfos(&resolution_store)) {
+ if (NIL_P(connect_timeout)) {
+ user_specified_connect_timeout_storage = (struct timeval){ -1, -1 };
+ } else {
+ struct timeval connect_timeout_tv = rb_time_interval(connect_timeout);
+ user_specified_connect_timeout_storage = add_ts_to_tv(connect_timeout_tv, now);
+ }
+ user_specified_connect_timeout_at = &user_specified_connect_timeout_storage;
+ }
+
+ break;
+ }
+
+ last_error.type = SYSCALL_ERROR;
+ last_error.ecode = errno;
+
+ if (NIL_P(io)) {
+ close(fd);
+ } else {
+ rb_io_close(io);
+ }
+
+ if (any_addrinfos(&resolution_store)) continue;
+ if (in_progress_fds(arg->connection_attempt_fds_size)) break;
+ if (!resolution_store.is_all_finished) break;
+
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+ }
+
+ if (connected_fd >= 0) break;
+
+ ends_at = select_expires_at(
+ &resolution_store,
+ resolution_delay_expires_at,
+ connection_attempt_delay_expires_at,
+ user_specified_resolv_timeout_at,
+ user_specified_connect_timeout_at,
+ user_specified_open_timeout_at
+ );
+ if (ends_at) {
+ delay = tv_to_timeout(ends_at, now);
+ delay_p = &delay;
+ } else {
+ if (((resolution_store.v6.finished && !resolution_store.v4.finished) ||
+ (resolution_store.v4.finished && !resolution_store.v6.finished)) &&
+ !any_addrinfos(&resolution_store) &&
+ !in_progress_fds(arg->connection_attempt_fds_size)) {
+ /* A limited timeout is introduced to prevent select(2) from hanging when it is exclusively
+ * waiting for name resolution and write(2) failure occurs in a child thread. */
+ delay.tv_sec = 0;
+ delay.tv_usec = 50000;
+ delay_p = &delay;
+ } else {
+ delay_p = NULL;
+ }
+ }
+
+ nfds = 0;
+ rb_fd_zero(&arg->writefds);
+ if (in_progress_fds(arg->connection_attempt_fds_size)) {
+ int n = 0;
+ for (int i = 0; i < arg->connection_attempt_fds_size; i++) {
+ int cfd = arg->connection_attempt_fds[i];
+ if (cfd < 0) continue;
+ if (cfd > n) n = cfd;
+ rb_fd_set(cfd, &arg->writefds);
+ }
+ if (n > 0) n++;
+ nfds = n;
+ }
+
+ rb_fd_zero(&arg->readfds);
+ if (arg->family_size > 1) {
+ rb_fd_set(hostname_resolution_waiter, &arg->readfds);
+
+ if ((hostname_resolution_waiter + 1) > nfds) {
+ nfds = hostname_resolution_waiter + 1;
+ }
+ }
+
+ status = rb_thread_fd_select(nfds, &arg->readfds, &arg->writefds, NULL, delay_p);
+
+ now = current_clocktime_ts();
+ if (is_timeout_tv(resolution_delay_expires_at, now)) {
+ resolution_delay_expires_at = NULL;
+ }
+ if (is_timeout_tv(connection_attempt_delay_expires_at, now)) {
+ connection_attempt_delay_expires_at = NULL;
+ }
+
+ if (status < 0 && (errno && errno != EINTR)) rb_syserr_fail(errno, "select(2)");
+
+ if (status > 0) {
+ /* check for connection */
+ if (in_progress_fds(arg->connection_attempt_fds_size)) {
+ for (int i = 0; i < arg->connection_attempt_fds_size; i++) {
+ int fd = arg->connection_attempt_fds[i];
+ if (fd < 0 || !rb_fd_isset(fd, &arg->writefds)) continue;
+
+ int err;
+ socklen_t len = sizeof(err);
+
+ status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len);
+
+ if (status < 0) {
+ last_error.type = SYSCALL_ERROR;
+ last_error.ecode = errno;
+ close(fd);
+
+ if (any_addrinfos(&resolution_store)) continue;
+ if (in_progress_fds(arg->connection_attempt_fds_size)) break;
+ if (!resolution_store.is_all_finished) break;
+
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+
+ if (err == 0) { /* success */
+ remove_connection_attempt_fd(
+ arg->connection_attempt_fds,
+ &arg->connection_attempt_fds_size,
+ fd
+ );
+ connected_fd = fd;
+ break;
+ } else { /* fail */
+ close(fd);
+ remove_connection_attempt_fd(
+ arg->connection_attempt_fds,
+ &arg->connection_attempt_fds_size,
+ fd
+ );
+ last_error.type = SYSCALL_ERROR;
+ last_error.ecode = err;
+ }
+ }
+
+ if (connected_fd >= 0) break;
+
+ if (!in_progress_fds(arg->connection_attempt_fds_size)) {
+ if (!any_addrinfos(&resolution_store) && resolution_store.is_all_finished) {
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+ connection_attempt_delay_expires_at = NULL;
+ user_specified_connect_timeout_at = NULL;
+ }
+ }
+
+ /* check for hostname resolution */
+ if (!resolution_store.is_all_finished && rb_fd_isset(hostname_resolution_waiter, &arg->readfds)) {
+ while (true) {
+ resolved_type_size = read(
+ hostname_resolution_waiter,
+ resolved_type,
+ sizeof(resolved_type) - 1
+ );
+
+ if (resolved_type_size > 0) {
+ resolved_type[resolved_type_size] = '\0';
+
+ if (resolved_type[0] == IPV6_HOSTNAME_RESOLVED) {
+ resolution_store.v6.finished = true;
+
+ if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err &&
+ arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err != EAI_ADDRFAMILY) {
+ if (!resolution_store.v4.finished || resolution_store.v4.has_error) {
+ last_error.type = RESOLUTION_ERROR;
+ last_error.ecode = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err;
+ syscall = "getaddrinfo(3)";
+ }
+ resolution_store.v6.has_error = true;
+ } else {
+ resolution_store.v6.ai = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->ai;
+ }
+ if (resolution_store.v4.finished) {
+ resolution_store.is_all_finished = true;
+ resolution_delay_expires_at = NULL;
+ user_specified_resolv_timeout_at = NULL;
+ break;
+ }
+ } else if (resolved_type[0] == IPV4_HOSTNAME_RESOLVED) {
+ resolution_store.v4.finished = true;
+
+ if (arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err) {
+ if (!resolution_store.v6.finished || resolution_store.v6.has_error) {
+ last_error.type = RESOLUTION_ERROR;
+ last_error.ecode = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err;
+ syscall = "getaddrinfo(3)";
+ }
+ resolution_store.v4.has_error = true;
+ } else {
+ resolution_store.v4.ai = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->ai;
+ }
+
+ if (resolution_store.v6.finished) {
+ resolution_store.is_all_finished = true;
+ resolution_delay_expires_at = NULL;
+ user_specified_resolv_timeout_at = NULL;
+ break;
+ }
+ } else {
+ /* Retry to read from hostname_resolution_waiter */
+ }
+ } else if (resolved_type_size < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
+ errno = 0;
+ break;
+ } else {
+ /* Retry to read from hostname_resolution_waiter */
+ }
+
+ if (!resolution_store.v6.finished &&
+ resolution_store.v4.finished &&
+ !resolution_store.v4.has_error) {
+ set_timeout_tv(&resolution_delay_storage, 50, now);
+ resolution_delay_expires_at = &resolution_delay_storage;
+ }
+ }
+ }
+
+ status = 0;
+ }
+
+ /* For cases where write(2) fails in child threads */
+ if (!resolution_store.is_all_finished) {
+ if (!resolution_store.v6.finished && arg->getaddrinfo_entries[IPV6_ENTRY_POS]->has_syserr) {
+ resolution_store.v6.finished = true;
+
+ if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err) {
+ if (!resolution_store.v4.finished || resolution_store.v4.has_error) {
+ last_error.type = RESOLUTION_ERROR;
+ last_error.ecode = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err;
+ syscall = "getaddrinfo(3)";
+ }
+ resolution_store.v6.has_error = true;
+ } else {
+ resolution_store.v6.ai = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->ai;
+ }
+
+ if (resolution_store.v4.finished) {
+ resolution_store.is_all_finished = true;
+ resolution_delay_expires_at = NULL;
+ user_specified_resolv_timeout_at = NULL;
+ }
+ }
+ if (!resolution_store.v4.finished && arg->getaddrinfo_entries[IPV4_ENTRY_POS]->has_syserr) {
+ resolution_store.v4.finished = true;
+
+ if (arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err) {
+ if (!resolution_store.v6.finished || resolution_store.v6.has_error) {
+ last_error.type = RESOLUTION_ERROR;
+ last_error.ecode = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err;
+ syscall = "getaddrinfo(3)";
+ }
+ resolution_store.v4.has_error = true;
+ } else {
+ resolution_store.v4.ai = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->ai;
+ }
+
+ if (resolution_store.v6.finished) {
+ resolution_store.is_all_finished = true;
+ resolution_delay_expires_at = NULL;
+ user_specified_resolv_timeout_at = NULL;
+ } else {
+ set_timeout_tv(&resolution_delay_storage, 50, now);
+ resolution_delay_expires_at = &resolution_delay_storage;
+ }
+ }
+ }
+
+ if (is_timeout_tv(user_specified_open_timeout_at, now)) {
+ rsock_raise_user_specified_timeout(NULL, arg->remote.host, arg->remote.serv);
+ }
+
+ if (!any_addrinfos(&resolution_store)) {
+ if (!in_progress_fds(arg->connection_attempt_fds_size) &&
+ resolution_store.is_all_finished) {
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+
+ if ((is_timeout_tv(user_specified_resolv_timeout_at, now) ||
+ resolution_store.is_all_finished) &&
+ (is_timeout_tv(user_specified_connect_timeout_at, now) ||
+ !in_progress_fds(arg->connection_attempt_fds_size))) {
+ rsock_raise_user_specified_timeout(NULL, arg->remote.host, arg->remote.serv);
+ }
+ }
+ }
+
+ if (NIL_P(arg->io)) {
+ /* create new instance */
+ arg->io = rsock_init_sock(arg->self, connected_fd);
+ }
+
+ return arg->io;
+}
+
+static VALUE
+fast_fallback_inetsock_cleanup(VALUE v)
+{
+ struct fast_fallback_inetsock_arg *arg = (void *)v;
+ struct fast_fallback_getaddrinfo_shared *getaddrinfo_shared = arg->getaddrinfo_shared;
+
+ if (arg->remote.res) {
+ rb_freeaddrinfo(arg->remote.res);
+ arg->remote.res = 0;
+ }
+ if (arg->local.res) {
+ rb_freeaddrinfo(arg->local.res);
+ arg->local.res = 0;
+ }
+
+ if (arg->wait != -1) close(arg->wait);
+
+ if (getaddrinfo_shared) {
+ if (getaddrinfo_shared->notify != -1) close(getaddrinfo_shared->notify);
+ getaddrinfo_shared->notify = -1;
+
+ int shared_need_free = 0;
+ struct addrinfo *ais[arg->family_size];
+ for (int i = 0; i < arg->family_size; i++) ais[i] = NULL;
+
+ rb_nativethread_lock_lock(&getaddrinfo_shared->lock);
+ {
+ for (int i = 0; i < arg->family_size; i++) {
+ struct fast_fallback_getaddrinfo_entry *getaddrinfo_entry = arg->getaddrinfo_entries[i];
+
+ if (!getaddrinfo_entry) continue;
+
+ if (--(getaddrinfo_entry->refcount) == 0) {
+ ais[i] = getaddrinfo_entry->ai;
+ getaddrinfo_entry->ai = NULL;
+ }
+ }
+ if (--(getaddrinfo_shared->refcount) == 0) {
+ shared_need_free = 1;
+ }
+ }
+ rb_nativethread_lock_unlock(&getaddrinfo_shared->lock);
+
+ for (int i = 0; i < arg->family_size; i++) {
+ if (ais[i]) freeaddrinfo(ais[i]);
+ }
+ if (getaddrinfo_shared && shared_need_free) {
+ free_fast_fallback_getaddrinfo_shared(&getaddrinfo_shared);
+ }
+ }
+
+ int connection_attempt_fd;
+
+ for (int i = 0; i < arg->connection_attempt_fds_size; i++) {
+ connection_attempt_fd = arg->connection_attempt_fds[i];
+
+ if (connection_attempt_fd >= 0) {
+ int error = 0;
+ socklen_t len = sizeof(error);
+ getsockopt(connection_attempt_fd, SOL_SOCKET, SO_ERROR, &error, &len);
+ if (error == 0) shutdown(connection_attempt_fd, SHUT_RDWR);
+ close(connection_attempt_fd);
+ }
+ }
+
+ if (arg->readfds.fdset) rb_fd_term(&arg->readfds);
+ if (arg->writefds.fdset) rb_fd_term(&arg->writefds);
+
+ if (arg->connection_attempt_fds) {
+ free(arg->connection_attempt_fds);
+ arg->connection_attempt_fds = NULL;
+ }
+
+ return Qnil;
+}
+
+VALUE
+rsock_init_inetsock(
+ VALUE self, VALUE remote_host, VALUE remote_serv,
+ VALUE local_host, VALUE local_serv, int type,
+ VALUE resolv_timeout, VALUE connect_timeout, VALUE open_timeout,
+ VALUE fast_fallback, VALUE test_mode_settings)
+{
+ if (!NIL_P(open_timeout) && (!NIL_P(resolv_timeout) || !NIL_P(connect_timeout))) {
+ rb_raise(rb_eArgError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout");
+ }
+
+ if (type == INET_CLIENT && FAST_FALLBACK_INIT_INETSOCK_IMPL == 1 && RTEST(fast_fallback)) {
+ struct rb_addrinfo *local_res = NULL;
+ char *hostp, *portp, *local_portp;
+ char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV], local_pbuf[NI_MAXSERV];
+ int additional_flags = 0;
+ int local_flags = 0;
+ hostp = raddrinfo_host_str(remote_host, hbuf, sizeof(hbuf), &additional_flags);
+ portp = raddrinfo_port_str(remote_serv, pbuf, sizeof(pbuf), &additional_flags);
+ local_portp = raddrinfo_port_str(local_serv, local_pbuf, sizeof(local_pbuf), &local_flags);
+
+ if (!is_specified_ip_address(hostp) && !is_local_port_fixed(local_portp)) {
+ int target_families[2] = { 0, 0 };
+ int resolving_family_size = 0;
+
+ /*
+ * Maybe also accept a local address
+ */
+ if (!NIL_P(local_host) || !NIL_P(local_serv)) {
+ VALUE t = NIL_P(open_timeout) ? resolv_timeout : open_timeout;
+ local_res = rsock_addrinfo(
+ local_host,
+ local_serv,
+ AF_UNSPEC,
+ SOCK_STREAM,
+ 0,
+ t
+ );
+
+ struct addrinfo *tmp_p = local_res->ai;
+ for (; tmp_p != NULL; tmp_p = tmp_p->ai_next) {
+ if (target_families[0] == 0 && tmp_p->ai_family == AF_INET6) {
+ target_families[0] = AF_INET6;
+ resolving_family_size++;
+ }
+ if (target_families[1] == 0 && tmp_p->ai_family == AF_INET) {
+ target_families[1] = AF_INET;
+ resolving_family_size++;
+ }
+ }
+ } else {
+ resolving_family_size = 2;
+ target_families[0] = AF_INET6;
+ target_families[1] = AF_INET;
+ }
+
+ struct fast_fallback_inetsock_arg fast_fallback_arg;
+ memset(&fast_fallback_arg, 0, sizeof(fast_fallback_arg));
+
+ fast_fallback_arg.self = self;
+ fast_fallback_arg.io = Qnil;
+ fast_fallback_arg.remote.host = remote_host;
+ fast_fallback_arg.remote.serv = remote_serv;
+ fast_fallback_arg.remote.res = 0;
+ fast_fallback_arg.local.host = local_host;
+ fast_fallback_arg.local.serv = local_serv;
+ fast_fallback_arg.local.res = local_res;
+ fast_fallback_arg.type = type;
+ fast_fallback_arg.resolv_timeout = resolv_timeout;
+ fast_fallback_arg.connect_timeout = connect_timeout;
+ fast_fallback_arg.open_timeout = open_timeout;
+ fast_fallback_arg.hostp = hostp;
+ fast_fallback_arg.portp = portp;
+ fast_fallback_arg.additional_flags = additional_flags;
+
+ int resolving_families[resolving_family_size];
+ int resolving_family_index = 0;
+ for (int i = 0; 2 > i; i++) {
+ if (target_families[i] != 0) {
+ resolving_families[resolving_family_index] = target_families[i];
+ resolving_family_index++;
+ }
+ }
+ fast_fallback_arg.families = resolving_families;
+ fast_fallback_arg.family_size = resolving_family_size;
+ fast_fallback_arg.test_mode_settings = test_mode_settings;
+
+ rb_fd_init(&fast_fallback_arg.readfds);
+ rb_fd_init(&fast_fallback_arg.writefds);
+
+ return rb_ensure(init_fast_fallback_inetsock_internal, (VALUE)&fast_fallback_arg,
+ fast_fallback_inetsock_cleanup, (VALUE)&fast_fallback_arg);
+ }
+ }
+
+ struct inetsock_arg arg;
+ arg.self = self;
+ arg.io = Qnil;
+ arg.remote.host = remote_host;
+ arg.remote.serv = remote_serv;
+ arg.remote.res = 0;
+ arg.local.host = local_host;
+ arg.local.serv = local_serv;
+ arg.local.res = 0;
+ arg.type = type;
+ arg.resolv_timeout = resolv_timeout;
+ arg.connect_timeout = connect_timeout;
+ arg.open_timeout = open_timeout;
+
+ return rb_ensure(init_inetsock_internal, (VALUE)&arg,
+ inetsock_cleanup, (VALUE)&arg);
+}
+
+#endif
+
+static ID id_numeric, id_hostname;
+
+int
+rsock_revlookup_flag(VALUE revlookup, int *norevlookup)
+{
+#define return_norevlookup(x) {*norevlookup = (x); return 1;}
+ ID id;
+
+ switch (revlookup) {
+ case Qtrue: return_norevlookup(0);
+ case Qfalse: return_norevlookup(1);
+ case Qnil: break;
+ default:
+ Check_Type(revlookup, T_SYMBOL);
+ id = SYM2ID(revlookup);
+ if (id == id_numeric) return_norevlookup(1);
+ if (id == id_hostname) return_norevlookup(0);
+ rb_raise(rb_eArgError, "invalid reverse_lookup flag: :%s", rb_id2name(id));
+ }
+ return 0;
+#undef return_norevlookup
+}
+
+/*
+ * call-seq:
+ * ipsocket.inspect -> string
+ *
+ * Return a string describing this IPSocket object.
+ */
+static VALUE
+ip_inspect(VALUE sock)
+{
+ VALUE str = rb_call_super(0, 0);
+ rb_io_t *fptr = RFILE(sock)->fptr;
+ union_sockaddr addr;
+ socklen_t len = (socklen_t)sizeof addr;
+ ID id;
+ if (fptr && fptr->fd >= 0 &&
+ getsockname(fptr->fd, &addr.addr, &len) >= 0 &&
+ (id = rsock_intern_family(addr.addr.sa_family)) != 0) {
+ VALUE family = rb_id2str(id);
+ char hbuf[1024], pbuf[1024];
+ long slen = RSTRING_LEN(str);
+ const char last = (slen > 1 && RSTRING_PTR(str)[slen - 1] == '>') ?
+ (--slen, '>') : 0;
+ str = rb_str_subseq(str, 0, slen);
+ rb_str_cat_cstr(str, ", ");
+ rb_str_append(str, family);
+ if (!rb_getnameinfo(&addr.addr, len, hbuf, sizeof(hbuf),
+ pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
+ rb_str_cat_cstr(str, ", ");
+ rb_str_cat_cstr(str, hbuf);
+ rb_str_cat_cstr(str, ", ");
+ rb_str_cat_cstr(str, pbuf);
+ }
+ if (last) rb_str_cat(str, &last, 1);
+ }
+ return str;
+}
+
+/*
+ * call-seq:
+ * ipsocket.addr([reverse_lookup]) => [address_family, port, hostname, numeric_address]
+ *
+ * Returns the local address as an array which contains
+ * address_family, port, hostname and numeric_address.
+ *
+ * If +reverse_lookup+ is +true+ or +:hostname+,
+ * hostname is obtained from numeric_address using reverse lookup.
+ * Or if it is +false+, or +:numeric+,
+ * hostname is the same as numeric_address.
+ * Or if it is +nil+ or omitted, obeys to +ipsocket.do_not_reverse_lookup+.
+ * See +Socket.getaddrinfo+ also.
+ *
+ * TCPSocket.open("www.ruby-lang.org", 80) {|sock|
+ * p sock.addr #=> ["AF_INET", 49429, "hal", "192.168.0.128"]
+ * p sock.addr(true) #=> ["AF_INET", 49429, "hal", "192.168.0.128"]
+ * p sock.addr(false) #=> ["AF_INET", 49429, "192.168.0.128", "192.168.0.128"]
+ * p sock.addr(:hostname) #=> ["AF_INET", 49429, "hal", "192.168.0.128"]
+ * p sock.addr(:numeric) #=> ["AF_INET", 49429, "192.168.0.128", "192.168.0.128"]
+ * }
+ *
+ */
+static VALUE
+ip_addr(int argc, VALUE *argv, VALUE sock)
+{
+ union_sockaddr addr;
+ socklen_t len = (socklen_t)sizeof addr;
+ int norevlookup;
+
+ if (argc < 1 || !rsock_revlookup_flag(argv[0], &norevlookup))
+ norevlookup = rb_io_mode(sock) & FMODE_NOREVLOOKUP;
+ if (getsockname(rb_io_descriptor(sock), &addr.addr, &len) < 0)
+ rb_sys_fail("getsockname(2)");
+ return rsock_ipaddr(&addr.addr, len, norevlookup);
+}
+
+/*
+ * call-seq:
+ * ipsocket.peeraddr([reverse_lookup]) => [address_family, port, hostname, numeric_address]
+ *
+ * Returns the remote address as an array which contains
+ * address_family, port, hostname and numeric_address.
+ * It is defined for connection oriented socket such as TCPSocket.
+ *
+ * If +reverse_lookup+ is +true+ or +:hostname+,
+ * hostname is obtained from numeric_address using reverse lookup.
+ * Or if it is +false+, or +:numeric+,
+ * hostname is the same as numeric_address.
+ * Or if it is +nil+ or omitted, obeys to +ipsocket.do_not_reverse_lookup+.
+ * See +Socket.getaddrinfo+ also.
+ *
+ * TCPSocket.open("www.ruby-lang.org", 80) {|sock|
+ * p sock.peeraddr #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
+ * p sock.peeraddr(true) #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
+ * p sock.peeraddr(false) #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
+ * p sock.peeraddr(:hostname) #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
+ * p sock.peeraddr(:numeric) #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
+ * }
+ *
+ */
+static VALUE
+ip_peeraddr(int argc, VALUE *argv, VALUE sock)
+{
+ union_sockaddr addr;
+ socklen_t len = (socklen_t)sizeof addr;
+ int norevlookup;
+
+ if (argc < 1 || !rsock_revlookup_flag(argv[0], &norevlookup))
+ norevlookup = rb_io_mode(sock) & FMODE_NOREVLOOKUP;
+ if (getpeername(rb_io_descriptor(sock), &addr.addr, &len) < 0)
+ rb_sys_fail("getpeername(2)");
+ return rsock_ipaddr(&addr.addr, len, norevlookup);
+}
+
+/*
+ * call-seq:
+ * ipsocket.recvfrom(maxlen) => [mesg, ipaddr]
+ * ipsocket.recvfrom(maxlen, flags) => [mesg, ipaddr]
+ *
+ * Receives a message and return the message as a string and
+ * an address which the message come from.
+ *
+ * _maxlen_ is the maximum number of bytes to receive.
+ *
+ * _flags_ should be a bitwise OR of Socket::MSG_* constants.
+ *
+ * ipaddr is the same as IPSocket#{peeraddr,addr}.
+ *
+ * u1 = UDPSocket.new
+ * u1.bind("127.0.0.1", 4913)
+ * u2 = UDPSocket.new
+ * u2.send "uuuu", 0, "127.0.0.1", 4913
+ * p u1.recvfrom(10) #=> ["uuuu", ["AF_INET", 33230, "localhost", "127.0.0.1"]]
+ *
+ */
+static VALUE
+ip_recvfrom(int argc, VALUE *argv, VALUE sock)
+{
+ return rsock_s_recvfrom(sock, argc, argv, RECV_IP);
+}
+
+/*
+ * call-seq:
+ * IPSocket.getaddress(host) => ipaddress
+ *
+ * Lookups the IP address of _host_.
+ *
+ * require 'socket'
+ *
+ * IPSocket.getaddress("localhost") #=> "127.0.0.1"
+ * IPSocket.getaddress("ip6-localhost") #=> "::1"
+ *
+ */
+static VALUE
+ip_s_getaddress(VALUE obj, VALUE host)
+{
+ union_sockaddr addr;
+ struct rb_addrinfo *res = rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, 0, Qnil);
+ socklen_t len = res->ai->ai_addrlen;
+
+ /* just take the first one */
+ memcpy(&addr, res->ai->ai_addr, len);
+ rb_freeaddrinfo(res);
+
+ return rsock_make_ipaddr(&addr.addr, len);
+}
+
+void
+rsock_init_ipsocket(void)
+{
+ /*
+ * Document-class: IPSocket < BasicSocket
+ *
+ * IPSocket is the super class of TCPSocket and UDPSocket.
+ */
+ rb_cIPSocket = rb_define_class("IPSocket", rb_cBasicSocket);
+ rb_define_method(rb_cIPSocket, "inspect", ip_inspect, 0);
+ rb_define_method(rb_cIPSocket, "addr", ip_addr, -1);
+ rb_define_method(rb_cIPSocket, "peeraddr", ip_peeraddr, -1);
+ rb_define_method(rb_cIPSocket, "recvfrom", ip_recvfrom, -1);
+ rb_define_singleton_method(rb_cIPSocket, "getaddress", ip_s_getaddress, 1);
+ rb_undef_method(rb_cIPSocket, "getpeereid");
+
+ id_numeric = rb_intern_const("numeric");
+ id_hostname = rb_intern_const("hostname");
+}
diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb
new file mode 100644
index 0000000000..465b74964f
--- /dev/null
+++ b/ext/socket/lib/socket.rb
@@ -0,0 +1,1816 @@
+# frozen_string_literal: true
+
+require 'socket.so'
+
+unless IO.method_defined?(:wait_writable, false)
+ # It's only required on older Rubies < v3.2:
+ require 'io/wait'
+end
+
+class Addrinfo
+ # creates an Addrinfo object from the arguments.
+ #
+ # The arguments are interpreted as similar to self.
+ #
+ # Addrinfo.tcp("0.0.0.0", 4649).family_addrinfo("www.ruby-lang.org", 80)
+ # #=> #<Addrinfo: 221.186.184.68:80 TCP (www.ruby-lang.org:80)>
+ #
+ # Addrinfo.unix("/tmp/sock").family_addrinfo("/tmp/sock2")
+ # #=> #<Addrinfo: /tmp/sock2 SOCK_STREAM>
+ #
+ def family_addrinfo(*args)
+ if args.empty?
+ raise ArgumentError, "no address specified"
+ elsif Addrinfo === args.first
+ raise ArgumentError, "too many arguments" if args.length != 1
+ addrinfo = args.first
+ if (self.pfamily != addrinfo.pfamily) ||
+ (self.socktype != addrinfo.socktype)
+ raise ArgumentError, "Addrinfo type mismatch"
+ end
+ addrinfo
+ elsif self.ip?
+ raise ArgumentError, "IP address needs host and port but #{args.length} arguments given" if args.length != 2
+ host, port = args
+ Addrinfo.getaddrinfo(host, port, self.pfamily, self.socktype, self.protocol)[0]
+ elsif self.unix?
+ raise ArgumentError, "UNIX socket needs single path argument but #{args.length} arguments given" if args.length != 1
+ path, = args
+ Addrinfo.unix(path)
+ else
+ raise ArgumentError, "unexpected family"
+ end
+ end
+
+ # creates a new Socket connected to the address of +local_addrinfo+.
+ #
+ # If _local_addrinfo_ is nil, the address of the socket is not bound.
+ #
+ # The _timeout_ specify the seconds for timeout.
+ # Errno::ETIMEDOUT is raised when timeout occur.
+ #
+ # If a block is given the created socket is yielded for each address.
+ #
+ def connect_internal(local_addrinfo, timeout=nil) # :yields: socket
+ sock = Socket.new(self.pfamily, self.socktype, self.protocol)
+ begin
+ sock.ipv6only! if self.ipv6?
+ sock.bind local_addrinfo if local_addrinfo
+ if timeout
+ case sock.connect_nonblock(self, exception: false)
+ when 0 # success or EISCONN, other errors raise
+ break
+ when :wait_writable
+ sock.wait_writable(timeout) or
+ raise Errno::ETIMEDOUT, "user specified timeout for #{self.ip_address}:#{self.ip_port}"
+ end while true
+ else
+ sock.connect(self)
+ end
+ rescue Exception
+ sock.close
+ raise
+ end
+ if block_given?
+ begin
+ yield sock
+ ensure
+ sock.close
+ end
+ else
+ sock
+ end
+ end
+ protected :connect_internal
+
+ # :call-seq:
+ # addrinfo.connect_from([local_addr_args], [opts]) {|socket| ... }
+ # addrinfo.connect_from([local_addr_args], [opts])
+ #
+ # creates a socket connected to the address of self.
+ #
+ # If one or more arguments given as _local_addr_args_,
+ # it is used as the local address of the socket.
+ # _local_addr_args_ is given for family_addrinfo to obtain actual address.
+ #
+ # If _local_addr_args_ is not given, the local address of the socket is not bound.
+ #
+ # The optional last argument _opts_ is options represented by a hash.
+ # _opts_ may have following options:
+ #
+ # [:timeout] specify the timeout in seconds.
+ #
+ # If a block is given, it is called with the socket and the value of the block is returned.
+ # The socket is returned otherwise.
+ #
+ # Addrinfo.tcp("www.ruby-lang.org", 80).connect_from("0.0.0.0", 4649) {|s|
+ # s.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n"
+ # puts s.read
+ # }
+ #
+ # # Addrinfo object can be taken for the argument.
+ # Addrinfo.tcp("www.ruby-lang.org", 80).connect_from(Addrinfo.tcp("0.0.0.0", 4649)) {|s|
+ # s.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n"
+ # puts s.read
+ # }
+ #
+ def connect_from(*args, timeout: nil, &block)
+ connect_internal(family_addrinfo(*args), timeout, &block)
+ end
+
+ # :call-seq:
+ # addrinfo.connect([opts]) {|socket| ... }
+ # addrinfo.connect([opts])
+ #
+ # creates a socket connected to the address of self.
+ #
+ # The optional argument _opts_ is options represented by a hash.
+ # _opts_ may have following options:
+ #
+ # [:timeout] specify the timeout in seconds.
+ #
+ # If a block is given, it is called with the socket and the value of the block is returned.
+ # The socket is returned otherwise.
+ #
+ # Addrinfo.tcp("www.ruby-lang.org", 80).connect {|s|
+ # s.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n"
+ # puts s.read
+ # }
+ #
+ def connect(timeout: nil, &block)
+ connect_internal(nil, timeout, &block)
+ end
+
+ # :call-seq:
+ # addrinfo.connect_to([remote_addr_args], [opts]) {|socket| ... }
+ # addrinfo.connect_to([remote_addr_args], [opts])
+ #
+ # creates a socket connected to _remote_addr_args_ and bound to self.
+ #
+ # The optional last argument _opts_ is options represented by a hash.
+ # _opts_ may have following options:
+ #
+ # [:timeout] specify the timeout in seconds.
+ #
+ # If a block is given, it is called with the socket and the value of the block is returned.
+ # The socket is returned otherwise.
+ #
+ # Addrinfo.tcp("0.0.0.0", 4649).connect_to("www.ruby-lang.org", 80) {|s|
+ # s.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n"
+ # puts s.read
+ # }
+ #
+ def connect_to(*args, timeout: nil, &block)
+ remote_addrinfo = family_addrinfo(*args)
+ remote_addrinfo.connect_internal(self, timeout, &block)
+ end
+
+ # creates a socket bound to self.
+ #
+ # If a block is given, it is called with the socket and the value of the block is returned.
+ # The socket is returned otherwise.
+ #
+ # Addrinfo.udp("0.0.0.0", 9981).bind {|s|
+ # s.local_address.connect {|s| s.send "hello", 0 }
+ # p s.recv(10) #=> "hello"
+ # }
+ #
+ def bind
+ sock = Socket.new(self.pfamily, self.socktype, self.protocol)
+ begin
+ sock.ipv6only! if self.ipv6?
+ sock.setsockopt(:SOCKET, :REUSEADDR, 1)
+ sock.bind(self)
+ rescue Exception
+ sock.close
+ raise
+ end
+ if block_given?
+ begin
+ yield sock
+ ensure
+ sock.close
+ end
+ else
+ sock
+ end
+ end
+
+ # creates a listening socket bound to self.
+ def listen(backlog=Socket::SOMAXCONN)
+ sock = Socket.new(self.pfamily, self.socktype, self.protocol)
+ begin
+ sock.ipv6only! if self.ipv6?
+ sock.setsockopt(:SOCKET, :REUSEADDR, 1) unless self.pfamily == Socket::PF_UNIX
+ sock.bind(self)
+ sock.listen(backlog)
+ rescue Exception
+ sock.close
+ raise
+ end
+ if block_given?
+ begin
+ yield sock
+ ensure
+ sock.close
+ end
+ else
+ sock
+ end
+ end
+
+ # iterates over the list of Addrinfo objects obtained by Addrinfo.getaddrinfo.
+ #
+ # Addrinfo.foreach(nil, 80) {|x| p x }
+ # #=> #<Addrinfo: 127.0.0.1:80 TCP (:80)>
+ # # #<Addrinfo: 127.0.0.1:80 UDP (:80)>
+ # # #<Addrinfo: [::1]:80 TCP (:80)>
+ # # #<Addrinfo: [::1]:80 UDP (:80)>
+ #
+ def self.foreach(nodename, service, family=nil, socktype=nil, protocol=nil, flags=nil, timeout: nil, &block)
+ Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags, timeout: timeout).each(&block)
+ end
+end
+
+class BasicSocket < IO
+ # Returns an address of the socket suitable for connect in the local machine.
+ #
+ # This method returns _self_.local_address, except following condition.
+ #
+ # - IPv4 unspecified address (0.0.0.0) is replaced by IPv4 loopback address (127.0.0.1).
+ # - IPv6 unspecified address (::) is replaced by IPv6 loopback address (::1).
+ #
+ # If the local address is not suitable for connect, SocketError is raised.
+ # IPv4 and IPv6 address which port is 0 is not suitable for connect.
+ # Unix domain socket which has no path is not suitable for connect.
+ #
+ # Addrinfo.tcp("0.0.0.0", 0).listen {|serv|
+ # p serv.connect_address #=> #<Addrinfo: 127.0.0.1:53660 TCP>
+ # serv.connect_address.connect {|c|
+ # s, _ = serv.accept
+ # p [c, s] #=> [#<Socket:fd 4>, #<Socket:fd 6>]
+ # }
+ # }
+ #
+ def connect_address
+ addr = local_address
+ afamily = addr.afamily
+ if afamily == Socket::AF_INET
+ raise SocketError, "unbound IPv4 socket" if addr.ip_port == 0
+ if addr.ip_address == "0.0.0.0"
+ addr = Addrinfo.new(["AF_INET", addr.ip_port, nil, "127.0.0.1"], addr.pfamily, addr.socktype, addr.protocol)
+ end
+ elsif defined?(Socket::AF_INET6) && afamily == Socket::AF_INET6
+ raise SocketError, "unbound IPv6 socket" if addr.ip_port == 0
+ if addr.ip_address == "::"
+ addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol)
+ elsif addr.ip_address == "0.0.0.0" # MacOS X 10.4 returns "a.b.c.d" for IPv4-mapped IPv6 address.
+ addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol)
+ elsif addr.ip_address == "::ffff:0.0.0.0" # MacOS X 10.6 returns "::ffff:a.b.c.d" for IPv4-mapped IPv6 address.
+ addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol)
+ end
+ elsif defined?(Socket::AF_UNIX) && afamily == Socket::AF_UNIX
+ raise SocketError, "unbound Unix socket" if addr.unix_path == ""
+ end
+ addr
+ end
+
+ # call-seq:
+ # basicsocket.sendmsg(mesg, flags=0, dest_sockaddr=nil, *controls) => numbytes_sent
+ #
+ # sendmsg sends a message using sendmsg(2) system call in blocking manner.
+ #
+ # _mesg_ is a string to send.
+ #
+ # _flags_ is bitwise OR of MSG_* constants such as Socket::MSG_OOB.
+ #
+ # _dest_sockaddr_ is a destination socket address for connection-less socket.
+ # It should be a sockaddr such as a result of Socket.sockaddr_in.
+ # An Addrinfo object can be used too.
+ #
+ # _controls_ is a list of ancillary data.
+ # The element of _controls_ should be Socket::AncillaryData or
+ # 3-elements array.
+ # The 3-element array should contains cmsg_level, cmsg_type and data.
+ #
+ # The return value, _numbytes_sent_ is an integer which is the number of bytes sent.
+ #
+ # sendmsg can be used to implement send_io as follows:
+ #
+ # # use Socket::AncillaryData.
+ # ancdata = Socket::AncillaryData.int(:UNIX, :SOCKET, :RIGHTS, io.fileno)
+ # sock.sendmsg("a", 0, nil, ancdata)
+ #
+ # # use 3-element array.
+ # ancdata = [:SOCKET, :RIGHTS, [io.fileno].pack("i!")]
+ # sock.sendmsg("\0", 0, nil, ancdata)
+ def sendmsg(mesg, flags = 0, dest_sockaddr = nil, *controls)
+ __sendmsg(mesg, flags, dest_sockaddr, controls)
+ end
+
+ # call-seq:
+ # basicsocket.sendmsg_nonblock(mesg, flags=0, dest_sockaddr=nil, *controls, opts={}) => numbytes_sent
+ #
+ # sendmsg_nonblock sends a message using sendmsg(2) system call in non-blocking manner.
+ #
+ # It is similar to BasicSocket#sendmsg
+ # but the non-blocking flag is set before the system call
+ # and it doesn't retry the system call.
+ #
+ # By specifying a keyword argument _exception_ to +false+, you can indicate
+ # that sendmsg_nonblock should not raise an IO::WaitWritable exception, but
+ # return the symbol +:wait_writable+ instead.
+ def sendmsg_nonblock(mesg, flags = 0, dest_sockaddr = nil, *controls,
+ exception: true)
+ __sendmsg_nonblock(mesg, flags, dest_sockaddr, controls, exception)
+ end
+
+ # call-seq:
+ # basicsocket.recv_nonblock(maxlen [, flags [, buf [, options ]]]) => mesg
+ #
+ # Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
+ # O_NONBLOCK is set for the underlying file descriptor.
+ # _flags_ is zero or more of the +MSG_+ options.
+ # The result, _mesg_, is the data received.
+ #
+ # When recvfrom(2) returns 0, Socket#recv_nonblock returns nil.
+ # In most cases it means the connection was closed, but for UDP connections
+ # it may mean an empty packet was received, as the underlying API makes
+ # it impossible to distinguish these two cases.
+ #
+ # === Parameters
+ # * +maxlen+ - the number of bytes to receive from the socket
+ # * +flags+ - zero or more of the +MSG_+ options
+ # * +buf+ - destination String buffer
+ # * +options+ - keyword hash, supporting `exception: false`
+ #
+ # === Example
+ # serv = TCPServer.new("127.0.0.1", 0)
+ # af, port, host, addr = serv.addr
+ # c = TCPSocket.new(addr, port)
+ # s = serv.accept
+ # c.send "aaa", 0
+ # begin # emulate blocking recv.
+ # p s.recv_nonblock(10) #=> "aaa"
+ # rescue IO::WaitReadable
+ # IO.select([s])
+ # retry
+ # end
+ #
+ # Refer to Socket#recvfrom for the exceptions that may be thrown if the call
+ # to _recv_nonblock_ fails.
+ #
+ # BasicSocket#recv_nonblock may raise any error corresponding to recvfrom(2) failure,
+ # including Errno::EWOULDBLOCK.
+ #
+ # If the exception is Errno::EWOULDBLOCK or Errno::EAGAIN,
+ # it is extended by IO::WaitReadable.
+ # So IO::WaitReadable can be used to rescue the exceptions for retrying recv_nonblock.
+ #
+ # By specifying a keyword argument _exception_ to +false+, you can indicate
+ # that recv_nonblock should not raise an IO::WaitReadable exception, but
+ # return the symbol +:wait_readable+ instead.
+ #
+ # === See
+ # * Socket#recvfrom
+ def recv_nonblock(len, flag = 0, str = nil, exception: true)
+ __recv_nonblock(len, flag, str, exception)
+ end
+
+ # call-seq:
+ # basicsocket.recvmsg(maxmesglen=nil, flags=0, maxcontrollen=nil, opts={}) => [mesg, sender_addrinfo, rflags, *controls]
+ #
+ # recvmsg receives a message using recvmsg(2) system call in blocking manner.
+ #
+ # _maxmesglen_ is the maximum length of mesg to receive.
+ #
+ # _flags_ is bitwise OR of MSG_* constants such as Socket::MSG_PEEK.
+ #
+ # _maxcontrollen_ is the maximum length of controls (ancillary data) to receive.
+ #
+ # _opts_ is option hash.
+ # Currently :scm_rights=>bool is the only option.
+ #
+ # :scm_rights option specifies that application expects SCM_RIGHTS control message.
+ # If the value is nil or false, application don't expects SCM_RIGHTS control message.
+ # In this case, recvmsg closes the passed file descriptors immediately.
+ # This is the default behavior.
+ #
+ # If :scm_rights value is neither nil nor false, application expects SCM_RIGHTS control message.
+ # In this case, recvmsg creates IO objects for each file descriptors for
+ # Socket::AncillaryData#unix_rights method.
+ #
+ # The return value is 4-elements array.
+ #
+ # _mesg_ is a string of the received message.
+ #
+ # _sender_addrinfo_ is a sender socket address for connection-less socket.
+ # It is an Addrinfo object.
+ # For connection-oriented socket such as TCP, sender_addrinfo is platform dependent.
+ #
+ # _rflags_ is a flags on the received message which is bitwise OR of MSG_* constants such as Socket::MSG_TRUNC.
+ # It will be nil if the system uses 4.3BSD style old recvmsg system call.
+ #
+ # _controls_ is ancillary data which is an array of Socket::AncillaryData objects such as:
+ #
+ # #<Socket::AncillaryData: AF_UNIX SOCKET RIGHTS 7>
+ #
+ # _maxmesglen_ and _maxcontrollen_ can be nil.
+ # In that case, the buffer will be grown until the message is not truncated.
+ # Internally, MSG_PEEK is used.
+ # Buffer full and MSG_CTRUNC are checked for truncation.
+ #
+ # recvmsg can be used to implement recv_io as follows:
+ #
+ # mesg, sender_sockaddr, rflags, *controls = sock.recvmsg(:scm_rights=>true)
+ # controls.each {|ancdata|
+ # if ancdata.cmsg_is?(:SOCKET, :RIGHTS)
+ # return ancdata.unix_rights[0]
+ # end
+ # }
+ def recvmsg(dlen = nil, flags = 0, clen = nil, scm_rights: false)
+ __recvmsg(dlen, flags, clen, scm_rights)
+ end
+
+ # call-seq:
+ # basicsocket.recvmsg_nonblock(maxdatalen=nil, flags=0, maxcontrollen=nil, opts={}) => [data, sender_addrinfo, rflags, *controls]
+ #
+ # recvmsg receives a message using recvmsg(2) system call in non-blocking manner.
+ #
+ # It is similar to BasicSocket#recvmsg
+ # but non-blocking flag is set before the system call
+ # and it doesn't retry the system call.
+ #
+ # By specifying a keyword argument _exception_ to +false+, you can indicate
+ # that recvmsg_nonblock should not raise an IO::WaitReadable exception, but
+ # return the symbol +:wait_readable+ instead.
+ def recvmsg_nonblock(dlen = nil, flags = 0, clen = nil,
+ scm_rights: false, exception: true)
+ __recvmsg_nonblock(dlen, flags, clen, scm_rights, exception)
+ end
+
+ # Linux-specific optimizations to avoid fcntl for IO#read_nonblock
+ # and IO#write_nonblock using MSG_DONTWAIT
+ # Do other platforms support MSG_DONTWAIT reliably?
+ if RUBY_PLATFORM =~ /linux/ && Socket.const_defined?(:MSG_DONTWAIT)
+ def read_nonblock(len, str = nil, exception: true) # :nodoc:
+ __read_nonblock(len, str, exception)
+ end
+
+ def write_nonblock(buf, exception: true) # :nodoc:
+ __write_nonblock(buf, exception)
+ end
+ end
+end
+
+class Socket < BasicSocket
+ # enable the socket option IPV6_V6ONLY if IPV6_V6ONLY is available.
+ def ipv6only!
+ if defined? Socket::IPV6_V6ONLY
+ self.setsockopt(:IPV6, :V6ONLY, 1)
+ end
+ end
+
+ # call-seq:
+ # socket.recvfrom_nonblock(maxlen[, flags[, outbuf[, opts]]]) => [mesg, sender_addrinfo]
+ #
+ # Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
+ # O_NONBLOCK is set for the underlying file descriptor.
+ # _flags_ is zero or more of the +MSG_+ options.
+ # The first element of the results, _mesg_, is the data received.
+ # The second element, _sender_addrinfo_, contains protocol-specific address
+ # information of the sender.
+ #
+ # When recvfrom(2) returns 0, Socket#recv_nonblock returns nil.
+ # In most cases it means the connection was closed, but for UDP connections
+ # it may mean an empty packet was received, as the underlying API makes
+ # it impossible to distinguish these two cases.
+ #
+ # === Parameters
+ # * +maxlen+ - the maximum number of bytes to receive from the socket
+ # * +flags+ - zero or more of the +MSG_+ options
+ # * +outbuf+ - destination String buffer
+ # * +opts+ - keyword hash, supporting `exception: false`
+ #
+ # === Example
+ # # In one file, start this first
+ # require 'socket'
+ # include Socket::Constants
+ # socket = Socket.new(AF_INET, SOCK_STREAM, 0)
+ # sockaddr = Socket.sockaddr_in(2200, 'localhost')
+ # socket.bind(sockaddr)
+ # socket.listen(5)
+ # client, client_addrinfo = socket.accept
+ # begin # emulate blocking recvfrom
+ # pair = client.recvfrom_nonblock(20)
+ # rescue IO::WaitReadable
+ # IO.select([client])
+ # retry
+ # end
+ # data = pair[0].chomp
+ # puts "I only received 20 bytes '#{data}'"
+ # sleep 1
+ # socket.close
+ #
+ # # In another file, start this second
+ # require 'socket'
+ # include Socket::Constants
+ # socket = Socket.new(AF_INET, SOCK_STREAM, 0)
+ # sockaddr = Socket.sockaddr_in(2200, 'localhost')
+ # socket.connect(sockaddr)
+ # socket.puts "Watch this get cut short!"
+ # socket.close
+ #
+ # Refer to Socket#recvfrom for the exceptions that may be thrown if the call
+ # to _recvfrom_nonblock_ fails.
+ #
+ # Socket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
+ # including Errno::EWOULDBLOCK.
+ #
+ # If the exception is Errno::EWOULDBLOCK or Errno::EAGAIN,
+ # it is extended by IO::WaitReadable.
+ # So IO::WaitReadable can be used to rescue the exceptions for retrying
+ # recvfrom_nonblock.
+ #
+ # By specifying a keyword argument _exception_ to +false+, you can indicate
+ # that recvfrom_nonblock should not raise an IO::WaitReadable exception, but
+ # return the symbol +:wait_readable+ instead.
+ #
+ # === See
+ # * Socket#recvfrom
+ def recvfrom_nonblock(len, flag = 0, str = nil, exception: true)
+ __recvfrom_nonblock(len, flag, str, exception)
+ end
+
+ # call-seq:
+ # socket.accept_nonblock([options]) => [client_socket, client_addrinfo]
+ #
+ # Accepts an incoming connection using accept(2) after
+ # O_NONBLOCK is set for the underlying file descriptor.
+ # It returns an array containing the accepted socket
+ # for the incoming connection, _client_socket_,
+ # and an Addrinfo, _client_addrinfo_.
+ #
+ # === Example
+ # # In one script, start this first
+ # require 'socket'
+ # include Socket::Constants
+ # socket = Socket.new(AF_INET, SOCK_STREAM, 0)
+ # sockaddr = Socket.sockaddr_in(2200, 'localhost')
+ # socket.bind(sockaddr)
+ # socket.listen(5)
+ # begin # emulate blocking accept
+ # client_socket, client_addrinfo = socket.accept_nonblock
+ # rescue IO::WaitReadable, Errno::EINTR
+ # IO.select([socket])
+ # retry
+ # end
+ # puts "The client said, '#{client_socket.readline.chomp}'"
+ # client_socket.puts "Hello from script one!"
+ # socket.close
+ #
+ # # In another script, start this second
+ # require 'socket'
+ # include Socket::Constants
+ # socket = Socket.new(AF_INET, SOCK_STREAM, 0)
+ # sockaddr = Socket.sockaddr_in(2200, 'localhost')
+ # socket.connect(sockaddr)
+ # socket.puts "Hello from script 2."
+ # puts "The server said, '#{socket.readline.chomp}'"
+ # socket.close
+ #
+ # Refer to Socket#accept for the exceptions that may be thrown if the call
+ # to _accept_nonblock_ fails.
+ #
+ # Socket#accept_nonblock may raise any error corresponding to accept(2) failure,
+ # including Errno::EWOULDBLOCK.
+ #
+ # If the exception is Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::ECONNABORTED or Errno::EPROTO,
+ # it is extended by IO::WaitReadable.
+ # So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock.
+ #
+ # By specifying a keyword argument _exception_ to +false+, you can indicate
+ # that accept_nonblock should not raise an IO::WaitReadable exception, but
+ # return the symbol +:wait_readable+ instead.
+ #
+ # === See
+ # * Socket#accept
+ def accept_nonblock(exception: true)
+ __accept_nonblock(exception)
+ end
+
+ # :stopdoc:
+ RESOLUTION_DELAY = 0.05
+ private_constant :RESOLUTION_DELAY
+
+ CONNECTION_ATTEMPT_DELAY = 0.25
+ private_constant :CONNECTION_ATTEMPT_DELAY
+
+ ADDRESS_FAMILIES = {
+ ipv6: Socket::AF_INET6,
+ ipv4: Socket::AF_INET
+ }.freeze
+ private_constant :ADDRESS_FAMILIES
+
+ HOSTNAME_RESOLUTION_QUEUE_UPDATED = 0
+ private_constant :HOSTNAME_RESOLUTION_QUEUE_UPDATED
+
+ IPV6_ADDRESS_FORMAT = /\A(?i:(?:(?:[0-9A-F]{1,4}:){7}(?:[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){6}(?:[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){5}(?:(?::[0-9A-F]{1,4}){1,2}|:(?:[0-9A-F]{1,4}:){1,4}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){4}(?:(?::[0-9A-F]{1,4}){1,3}|:(?:[0-9A-F]{1,4}:){1,3}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){3}(?:(?::[0-9A-F]{1,4}){1,4}|:(?:[0-9A-F]{1,4}:){1,2}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){2}(?:(?::[0-9A-F]{1,4}){1,5}|:(?:[0-9A-F]{1,4}:)[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){1}(?:(?::[0-9A-F]{1,4}){1,6}|:(?:[0-9A-F]{1,4}:){0,5}[0-9A-F]{1,4}|:)|(?:::(?:[0-9A-F]{1,4}:){0,7}[0-9A-F]{1,4}|::)))(?:%.+)?\z/
+ private_constant :IPV6_ADDRESS_FORMAT
+ # :startdoc:
+
+ # :call-seq:
+ # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| ... }
+ # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts])
+ #
+ # creates a new socket object connected to host:port using TCP/IP.
+ #
+ # Starting from Ruby 3.4, this method operates according to the
+ # Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305])
+ # algorithm by default.
+ #
+ # For details on Happy Eyeballs Version 2,
+ # see {Socket.tcp_fast_fallback=}[rdoc-ref:Socket.tcp_fast_fallback=].
+ #
+ # To make it behave the same as in Ruby 3.3 and earlier,
+ # explicitly specify the option fast_fallback:false.
+ # Or, setting Socket.tcp_fast_fallback=false will disable
+ # Happy Eyeballs Version 2 not only for this method but for all Socket globally.
+ #
+ # If local_host:local_port is given,
+ # the socket is bound to it.
+ #
+ # The optional last argument _opts_ is options represented by a hash.
+ # _opts_ may have following options:
+ #
+ # [:resolv_timeout] Specifies the timeout in seconds from when the hostname resolution starts.
+ # [:connect_timeout] This method sequentially attempts connecting to all candidate destination addresses.<br>The +connect_timeout+ specifies the timeout in seconds from the start of the connection attempt to the last candidate.<br>By default, all connection attempts continue until the timeout occurs.<br>When +fast_fallback:false+ is explicitly specified,<br>a timeout is set for each connection attempt and any connection attempt that exceeds its timeout will be canceled.
+ # [:open_timeout] Specifies the timeout in seconds from the start of the method execution.<br>If this timeout is reached while there are still addresses that have not yet been attempted for connection, no further attempts will be made.<br>If this option is specified together with other timeout options, an +ArgumentError+ will be raised.
+ # [:fast_fallback] Enables the Happy Eyeballs Version 2 algorithm (enabled by default).
+ #
+ # If a block is given, the block is called with the socket.
+ # The value of the block is returned.
+ # The socket is closed when this method returns.
+ #
+ # If no block is given, the socket is returned.
+ #
+ # Socket.tcp("www.ruby-lang.org", 80) {|sock|
+ # sock.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n"
+ # sock.close_write
+ # puts sock.read
+ # }
+ def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, open_timeout: nil, fast_fallback: tcp_fast_fallback, &) # :yield: socket
+ if open_timeout && (connect_timeout || resolv_timeout)
+ raise ArgumentError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout"
+ end
+
+ sock = if fast_fallback && !(host && ip_address?(host)) && !(local_port && local_port.to_i != 0)
+ tcp_with_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:)
+ else
+ tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:)
+ end
+
+ if block_given?
+ begin
+ yield sock
+ ensure
+ sock.close
+ end
+ else
+ sock
+ end
+ end
+
+ # :stopdoc:
+ def self.tcp_with_fast_fallback(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, open_timeout: nil)
+ if local_host || local_port
+ local_addrinfos = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, timeout: open_timeout || resolv_timeout)
+ resolving_family_names = local_addrinfos.map { |lai| ADDRESS_FAMILIES.key(lai.afamily) }.uniq
+ else
+ local_addrinfos = []
+ resolving_family_names = ADDRESS_FAMILIES.keys
+ end
+
+ hostname_resolution_threads = []
+ resolution_store = HostnameResolutionStore.new(resolving_family_names)
+ connecting_sockets = {}
+ is_windows_environment ||= (RUBY_PLATFORM =~ /mswin|mingw|cygwin/)
+
+ now = current_clock_time
+ starts_at = now
+ resolution_delay_expires_at = nil
+ connection_attempt_delay_expires_at = nil
+ user_specified_connect_timeout_at = nil
+ user_specified_open_timeout_at = open_timeout ? now + open_timeout : nil
+ last_error = nil
+ last_error_from_thread = false
+
+ if resolving_family_names.size == 1
+ family_name = resolving_family_names.first
+ addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[:family_name], :STREAM, timeout: open_timeout || resolv_timeout)
+ resolution_store.add_resolved(family_name, addrinfos)
+ hostname_resolution_result = nil
+ hostname_resolution_notifier = nil
+ user_specified_resolv_timeout_at = nil
+ else
+ hostname_resolution_result = HostnameResolutionResult.new(resolving_family_names.size)
+ hostname_resolution_notifier = hostname_resolution_result.notifier
+
+ hostname_resolution_threads.concat(
+ resolving_family_names.map { |family|
+ thread_args = [family, host, port, hostname_resolution_result]
+ thread = Thread.new(*thread_args) { |*thread_args| resolve_hostname(*thread_args) }
+ Thread.pass
+ thread
+ }
+ )
+ user_specified_resolv_timeout_at = resolv_timeout ? now + resolv_timeout : Float::INFINITY
+ end
+
+ loop do
+ if resolution_store.any_addrinfos? &&
+ !resolution_delay_expires_at &&
+ !connection_attempt_delay_expires_at
+ while (addrinfo = resolution_store.get_addrinfo)
+ if local_addrinfos.any?
+ local_addrinfo = local_addrinfos.find { |lai| lai.afamily == addrinfo.afamily }
+
+ if local_addrinfo.nil?
+ if resolution_store.any_addrinfos?
+ # Try other Addrinfo in next "while"
+ next
+ elsif connecting_sockets.any? || resolution_store.any_unresolved_family?
+ # Exit this "while" and wait for connections to be established or hostname resolution in next loop
+ # Or exit this "while" and wait for hostname resolution in next loop
+ break
+ else
+ raise SocketError.new 'no appropriate local address'
+ end
+ end
+ end
+
+ begin
+ if resolution_store.any_addrinfos? ||
+ connecting_sockets.any? ||
+ resolution_store.any_unresolved_family?
+ socket = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol)
+ socket.bind(local_addrinfo) if local_addrinfo
+ result = socket.connect_nonblock(addrinfo, exception: false)
+ else
+ timeout =
+ if open_timeout
+ t = open_timeout - (current_clock_time - starts_at)
+ t.negative? ? 0 : t
+ else
+ connect_timeout
+ end
+ result = socket = local_addrinfo ?
+ addrinfo.connect_from(local_addrinfo, timeout:) :
+ addrinfo.connect(timeout:)
+ end
+
+ if result == :wait_writable
+ connection_attempt_delay_expires_at = now + CONNECTION_ATTEMPT_DELAY
+ if resolution_store.empty_addrinfos?
+ user_specified_connect_timeout_at = connect_timeout ? now + connect_timeout : Float::INFINITY
+ end
+
+ connecting_sockets[socket] = addrinfo
+ break
+ else
+ return socket # connection established
+ end
+ rescue SystemCallError => e
+ socket&.close
+ last_error = e
+
+ if resolution_store.any_addrinfos?
+ # Try other Addrinfo in next "while"
+ next
+ elsif connecting_sockets.any? || resolution_store.any_unresolved_family?
+ # Exit this "while" and wait for connections to be established or hostname resolution in next loop
+ # Or exit this "while" and wait for hostname resolution in next loop
+ break
+ else
+ raise last_error
+ end
+ end
+ end
+ end
+
+ ends_at =
+ if resolution_store.any_addrinfos?
+ [(resolution_delay_expires_at || connection_attempt_delay_expires_at),
+ user_specified_open_timeout_at].compact.min
+ elsif user_specified_open_timeout_at
+ user_specified_open_timeout_at
+ else
+ [user_specified_resolv_timeout_at, user_specified_connect_timeout_at].compact.max
+ end
+
+ hostname_resolved, writable_sockets, except_sockets = IO.select(
+ hostname_resolution_notifier,
+ connecting_sockets.keys,
+ # Use errorfds to wait for non-blocking connect failures on Windows
+ is_windows_environment ? connecting_sockets.keys : nil,
+ second_to_timeout(current_clock_time, ends_at),
+ )
+ now = current_clock_time
+ resolution_delay_expires_at = nil if expired?(now, resolution_delay_expires_at)
+ connection_attempt_delay_expires_at = nil if expired?(now, connection_attempt_delay_expires_at)
+
+ if writable_sockets&.any?
+ while (writable_socket = writable_sockets.pop)
+ is_connected = is_windows_environment || (
+ sockopt = writable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)
+ sockopt.int.zero?
+ )
+
+ if is_connected
+ connecting_sockets.delete writable_socket
+ return writable_socket
+ else
+ failed_ai = connecting_sockets.delete writable_socket
+ writable_socket.close
+ ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address
+ last_error = SystemCallError.new("connect(2) for #{ip_address}:#{failed_ai.ip_port}", sockopt.int)
+
+ if writable_sockets.any? || connecting_sockets.any?
+ # Try other writable socket in next "while"
+ # Or exit this "while" and wait for connections to be established or hostname resolution in next loop
+ elsif resolution_store.any_addrinfos? || resolution_store.any_unresolved_family?
+ # Exit this "while" and try other connection attempt
+ # Or exit this "while" and wait for hostname resolution in next loop
+ connection_attempt_delay_expires_at = nil
+ user_specified_connect_timeout_at = nil
+ else
+ raise last_error
+ end
+ end
+ end
+ end
+
+ if except_sockets&.any?
+ except_sockets.each do |except_socket|
+ failed_ai = connecting_sockets.delete except_socket
+ sockopt = except_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)
+ except_socket.close
+ ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address
+ last_error = SystemCallError.new("connect(2) for #{ip_address}:#{failed_ai.ip_port}", sockopt.int)
+
+ if except_sockets.any? || connecting_sockets.any?
+ # Cleanup other except socket in next "each"
+ # Or exit this "while" and wait for connections to be established or hostname resolution in next loop
+ elsif resolution_store.any_addrinfos? || resolution_store.any_unresolved_family?
+ # Exit this "while" and try other connection attempt
+ # Or exit this "while" and wait for hostname resolution in next loop
+ connection_attempt_delay_expires_at = nil
+ user_specified_connect_timeout_at = nil
+ else
+ raise last_error
+ end
+ end
+ end
+
+ if hostname_resolved&.any?
+ while (family_and_result = hostname_resolution_result.get)
+ family_name, result = family_and_result
+
+ if result.is_a? Exception
+ resolution_store.add_error(family_name, result)
+
+ unless (Socket.const_defined?(:EAI_ADDRFAMILY)) &&
+ (result.is_a?(Socket::ResolutionError)) &&
+ (result.error_code == Socket::EAI_ADDRFAMILY)
+ other = family_name == :ipv6 ? :ipv4 : :ipv6
+ if !resolution_store.resolved?(other) || !resolution_store.resolved_successfully?(other)
+ last_error = result
+ last_error_from_thread = true
+ end
+ end
+ else
+ resolution_store.add_resolved(family_name, result)
+ end
+ end
+
+ if resolution_store.resolved?(:ipv4)
+ if resolution_store.resolved?(:ipv6)
+ hostname_resolution_notifier = nil
+ resolution_delay_expires_at = nil
+ user_specified_resolv_timeout_at = nil
+ elsif resolution_store.resolved_successfully?(:ipv4)
+ resolution_delay_expires_at = now + RESOLUTION_DELAY
+ end
+ end
+ end
+
+ if expired?(now, user_specified_open_timeout_at)
+ raise(IO::TimeoutError, "user specified timeout for #{host}:#{port}")
+ end
+
+ if resolution_store.empty_addrinfos?
+ if connecting_sockets.empty? && resolution_store.resolved_all_families?
+ if last_error_from_thread
+ raise last_error.class, last_error.message, cause: last_error
+ else
+ raise last_error
+ end
+ end
+
+ if (expired?(now, user_specified_resolv_timeout_at) || resolution_store.resolved_all_families?) &&
+ (expired?(now, user_specified_connect_timeout_at) || connecting_sockets.empty?)
+ raise(IO::TimeoutError, "user specified timeout for #{host}:#{port}")
+ end
+ end
+ end
+ ensure
+ hostname_resolution_threads.each(&:exit).each(&:join)
+
+ hostname_resolution_result&.close
+
+ connecting_sockets.each_key(&:close)
+ end
+ private_class_method :tcp_with_fast_fallback
+
+ def self.tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:)
+ last_error = nil
+ ret = nil
+
+ local_addr_list = nil
+ if local_host != nil || local_port != nil
+ local_addr_list = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, nil, timeout: open_timeout || resolv_timeout)
+ end
+
+ timeout = open_timeout ? open_timeout : resolv_timeout
+ starts_at = current_clock_time
+
+ Addrinfo.foreach(host, port, nil, :STREAM, timeout:) {|ai|
+ if local_addr_list
+ local_addr = local_addr_list.find {|local_ai| local_ai.afamily == ai.afamily }
+ next unless local_addr
+ else
+ local_addr = nil
+ end
+ begin
+ timeout =
+ if open_timeout
+ t = open_timeout - (current_clock_time - starts_at)
+ t.negative? ? 0 : t
+ else
+ connect_timeout
+ end
+
+ sock = local_addr ?
+ ai.connect_from(local_addr, timeout:) :
+ ai.connect(timeout:)
+ rescue SystemCallError
+ last_error = $!
+ next
+ end
+ ret = sock
+ break
+ }
+ unless ret
+ if last_error
+ raise last_error
+ else
+ raise SocketError, "no appropriate local address"
+ end
+ end
+
+ ret
+ end
+ private_class_method :tcp_without_fast_fallback
+
+ def self.ip_address?(hostname)
+ hostname.match?(IPV6_ADDRESS_FORMAT) || hostname.match?(/\A([0-9]{1,3}\.){3}[0-9]{1,3}\z/)
+ end
+ private_class_method :ip_address?
+
+ def self.resolve_hostname(family, host, port, hostname_resolution_result)
+ begin
+ resolved_addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[family], :STREAM)
+ hostname_resolution_result.add(family, resolved_addrinfos)
+ rescue => e
+ hostname_resolution_result.add(family, e)
+ end
+ end
+ private_class_method :resolve_hostname
+
+ def self.current_clock_time
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ end
+ private_class_method :current_clock_time
+
+ def self.second_to_timeout(started_at, ends_at)
+ return nil if ends_at == Float::INFINITY || ends_at.nil?
+
+ remaining = (ends_at - started_at)
+ remaining.negative? ? 0 : remaining
+ end
+ private_class_method :second_to_timeout
+
+ def self.expired?(started_at, ends_at)
+ second_to_timeout(started_at, ends_at)&.zero?
+ end
+ private_class_method :expired?
+
+ class HostnameResolutionResult
+ def initialize(size)
+ @size = size
+ @taken_count = 0
+ @rpipe, @wpipe = IO.pipe
+ @results = []
+ @mutex = Mutex.new
+ end
+
+ def notifier
+ [@rpipe]
+ end
+
+ def add(family, result)
+ @mutex.synchronize do
+ @results.push [family, result]
+ @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED
+ end
+ end
+
+ def get
+ return nil if @results.empty?
+
+ res = nil
+
+ @mutex.synchronize do
+ @rpipe.getbyte
+ res = @results.shift
+ end
+
+ @taken_count += 1
+ close if @taken_count == @size
+ res
+ end
+
+ def close
+ @rpipe.close
+ @wpipe.close
+ end
+ end
+ private_constant :HostnameResolutionResult
+
+ class HostnameResolutionStore
+ PRIORITY_ON_V6 = [:ipv6, :ipv4].freeze
+ PRIORITY_ON_V4 = [:ipv4, :ipv6].freeze
+
+ def initialize(family_names)
+ @family_names = family_names
+ @addrinfo_dict = {}
+ @error_dict = {}
+ @last_family = nil
+ end
+
+ def add_resolved(family_name, addrinfos)
+ @addrinfo_dict[family_name] = addrinfos
+ end
+
+ def add_error(family_name, error)
+ @addrinfo_dict[family_name] = []
+ @error_dict[family_name] = error
+ end
+
+ def get_addrinfo
+ precedences =
+ case @last_family
+ when :ipv4, nil then PRIORITY_ON_V6
+ when :ipv6 then PRIORITY_ON_V4
+ end
+
+ precedences.each do |family_name|
+ addrinfo = @addrinfo_dict[family_name]&.shift
+ next unless addrinfo
+
+ @last_family = family_name
+ return addrinfo
+ end
+
+ nil
+ end
+
+ def empty_addrinfos?
+ @addrinfo_dict.all? { |_, addrinfos| addrinfos.empty? }
+ end
+
+ def any_addrinfos?
+ !empty_addrinfos?
+ end
+
+ def resolved?(family)
+ @addrinfo_dict.has_key? family
+ end
+
+ def resolved_successfully?(family)
+ resolved?(family) && !@error_dict[family]
+ end
+
+ def resolved_all_families?
+ (@family_names - @addrinfo_dict.keys).empty?
+ end
+
+ def any_unresolved_family?
+ !resolved_all_families?
+ end
+ end
+ private_constant :HostnameResolutionStore
+
+ def self.ip_sockets_port0(ai_list, reuseaddr)
+ sockets = []
+ begin
+ sockets.clear
+ port = nil
+ ai_list.each {|ai|
+ begin
+ s = Socket.new(ai.pfamily, ai.socktype, ai.protocol)
+ rescue SystemCallError
+ next
+ end
+ sockets << s
+ s.ipv6only! if ai.ipv6?
+ if reuseaddr
+ s.setsockopt(:SOCKET, :REUSEADDR, 1)
+ end
+ unless port
+ s.bind(ai)
+ port = s.local_address.ip_port
+ else
+ s.bind(ai.family_addrinfo(ai.ip_address, port))
+ end
+ }
+ rescue Errno::EADDRINUSE
+ sockets.each(&:close)
+ retry
+ rescue Exception
+ sockets.each(&:close)
+ raise
+ end
+ sockets
+ end
+ private_class_method :ip_sockets_port0
+
+ def self.tcp_server_sockets_port0(host)
+ ai_list = Addrinfo.getaddrinfo(host, 0, nil, :STREAM, nil, Socket::AI_PASSIVE)
+ sockets = ip_sockets_port0(ai_list, true)
+ begin
+ sockets.each {|s|
+ s.listen(Socket::SOMAXCONN)
+ }
+ rescue Exception
+ sockets.each(&:close)
+ raise
+ end
+ sockets
+ end
+ class << self
+ private :tcp_server_sockets_port0
+ end
+ # :startdoc:
+
+ # creates TCP/IP server sockets for _host_ and _port_.
+ # _host_ is optional.
+ #
+ # If no block given,
+ # it returns an array of listening sockets.
+ #
+ # If a block is given, the block is called with the sockets.
+ # The value of the block is returned.
+ # The socket is closed when this method returns.
+ #
+ # If _port_ is 0, actual port number is chosen dynamically.
+ # However all sockets in the result has same port number.
+ #
+ # # tcp_server_sockets returns two sockets.
+ # sockets = Socket.tcp_server_sockets(1296)
+ # p sockets #=> [#<Socket:fd 3>, #<Socket:fd 4>]
+ #
+ # # The sockets contains IPv6 and IPv4 sockets.
+ # sockets.each {|s| p s.local_address }
+ # #=> #<Addrinfo: [::]:1296 TCP>
+ # # #<Addrinfo: 0.0.0.0:1296 TCP>
+ #
+ # # IPv6 and IPv4 socket has same port number, 53114, even if it is chosen dynamically.
+ # sockets = Socket.tcp_server_sockets(0)
+ # sockets.each {|s| p s.local_address }
+ # #=> #<Addrinfo: [::]:53114 TCP>
+ # # #<Addrinfo: 0.0.0.0:53114 TCP>
+ #
+ # # The block is called with the sockets.
+ # Socket.tcp_server_sockets(0) {|sockets|
+ # p sockets #=> [#<Socket:fd 3>, #<Socket:fd 4>]
+ # }
+ #
+ def self.tcp_server_sockets(host=nil, port)
+ if port == 0
+ sockets = tcp_server_sockets_port0(host)
+ else
+ last_error = nil
+ sockets = []
+ begin
+ Addrinfo.foreach(host, port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai|
+ begin
+ s = ai.listen
+ rescue SystemCallError
+ last_error = $!
+ next
+ end
+ sockets << s
+ }
+ if sockets.empty?
+ raise last_error
+ end
+ rescue Exception
+ sockets.each(&:close)
+ raise
+ end
+ end
+ if block_given?
+ begin
+ yield sockets
+ ensure
+ sockets.each(&:close)
+ end
+ else
+ sockets
+ end
+ end
+
+ # yield socket and client address for each a connection accepted via given sockets.
+ #
+ # The arguments are a list of sockets.
+ # The individual argument should be a socket or an array of sockets.
+ #
+ # This method yields the block sequentially.
+ # It means that the next connection is not accepted until the block returns.
+ # So concurrent mechanism, thread for example, should be used to service multiple clients at a time.
+ #
+ def self.accept_loop(*sockets) # :yield: socket, client_addrinfo
+ sockets.flatten!(1)
+ if sockets.empty?
+ raise ArgumentError, "no sockets"
+ end
+ loop {
+ readable, _, _ = IO.select(sockets)
+ readable.each {|r|
+ sock, addr = r.accept_nonblock(exception: false)
+ next if sock == :wait_readable
+ yield sock, addr
+ }
+ }
+ end
+
+ # creates a TCP/IP server on _port_ and calls the block for each connection accepted.
+ # The block is called with a socket and a client_address as an Addrinfo object.
+ #
+ # If _host_ is specified, it is used with _port_ to determine the server addresses.
+ #
+ # The socket is *not* closed when the block returns.
+ # So application should close it explicitly.
+ #
+ # This method calls the block sequentially.
+ # It means that the next connection is not accepted until the block returns.
+ # So concurrent mechanism, thread for example, should be used to service multiple clients at a time.
+ #
+ # Note that Addrinfo.getaddrinfo is used to determine the server socket addresses.
+ # When Addrinfo.getaddrinfo returns two or more addresses,
+ # IPv4 and IPv6 address for example,
+ # all of them are used.
+ # Socket.tcp_server_loop succeeds if one socket can be used at least.
+ #
+ # # Sequential echo server.
+ # # It services only one client at a time.
+ # Socket.tcp_server_loop(16807) {|sock, client_addrinfo|
+ # begin
+ # IO.copy_stream(sock, sock)
+ # ensure
+ # sock.close
+ # end
+ # }
+ #
+ # # Threaded echo server
+ # # It services multiple clients at a time.
+ # # Note that it may accept connections too much.
+ # Socket.tcp_server_loop(16807) {|sock, client_addrinfo|
+ # Thread.new {
+ # begin
+ # IO.copy_stream(sock, sock)
+ # ensure
+ # sock.close
+ # end
+ # }
+ # }
+ #
+ def self.tcp_server_loop(host=nil, port, &b) # :yield: socket, client_addrinfo
+ tcp_server_sockets(host, port) {|sockets|
+ accept_loop(sockets, &b)
+ }
+ end
+
+ # :call-seq:
+ # Socket.udp_server_sockets([host, ] port)
+ #
+ # Creates UDP/IP sockets for a UDP server.
+ #
+ # If no block given, it returns an array of sockets.
+ #
+ # If a block is given, the block is called with the sockets.
+ # The value of the block is returned.
+ # The sockets are closed when this method returns.
+ #
+ # If _port_ is zero, some port is chosen.
+ # But the chosen port is used for the all sockets.
+ #
+ # # UDP/IP echo server
+ # Socket.udp_server_sockets(0) {|sockets|
+ # p sockets.first.local_address.ip_port #=> 32963
+ # Socket.udp_server_loop_on(sockets) {|msg, msg_src|
+ # msg_src.reply msg
+ # }
+ # }
+ #
+ def self.udp_server_sockets(host=nil, port)
+ last_error = nil
+ sockets = []
+
+ ipv6_recvpktinfo = nil
+ if defined? Socket::AncillaryData
+ if defined? Socket::IPV6_RECVPKTINFO # RFC 3542
+ ipv6_recvpktinfo = Socket::IPV6_RECVPKTINFO
+ elsif defined? Socket::IPV6_PKTINFO # RFC 2292
+ ipv6_recvpktinfo = Socket::IPV6_PKTINFO
+ end
+ end
+
+ local_addrs = Socket.ip_address_list
+
+ ip_list = []
+ Addrinfo.foreach(host, port, nil, :DGRAM, nil, Socket::AI_PASSIVE) {|ai|
+ if ai.ipv4? && ai.ip_address == "0.0.0.0"
+ local_addrs.each {|a|
+ next unless a.ipv4?
+ ip_list << Addrinfo.new(a.to_sockaddr, :INET, :DGRAM, 0);
+ }
+ elsif ai.ipv6? && ai.ip_address == "::" && !ipv6_recvpktinfo
+ local_addrs.each {|a|
+ next unless a.ipv6?
+ ip_list << Addrinfo.new(a.to_sockaddr, :INET6, :DGRAM, 0);
+ }
+ else
+ ip_list << ai
+ end
+ }
+ ip_list.uniq!(&:to_sockaddr)
+
+ if port == 0
+ sockets = ip_sockets_port0(ip_list, false)
+ else
+ ip_list.each {|ip|
+ ai = Addrinfo.udp(ip.ip_address, port)
+ begin
+ s = ai.bind
+ rescue SystemCallError
+ last_error = $!
+ next
+ end
+ sockets << s
+ }
+ if sockets.empty?
+ raise last_error
+ end
+ end
+
+ sockets.each {|s|
+ ai = s.local_address
+ if ipv6_recvpktinfo && ai.ipv6? && ai.ip_address == "::"
+ s.setsockopt(:IPV6, ipv6_recvpktinfo, 1)
+ end
+ }
+
+ if block_given?
+ begin
+ yield sockets
+ ensure
+ sockets.each(&:close) if sockets
+ end
+ else
+ sockets
+ end
+ end
+
+ # :call-seq:
+ # Socket.udp_server_recv(sockets) {|msg, msg_src| ... }
+ #
+ # Receive UDP/IP packets from the given _sockets_.
+ # For each packet received, the block is called.
+ #
+ # The block receives _msg_ and _msg_src_.
+ # _msg_ is a string which is the payload of the received packet.
+ # _msg_src_ is a Socket::UDPSource object which is used for reply.
+ #
+ # Socket.udp_server_loop can be implemented using this method as follows.
+ #
+ # udp_server_sockets(host, port) {|sockets|
+ # loop {
+ # readable, _, _ = IO.select(sockets)
+ # udp_server_recv(readable) {|msg, msg_src| ... }
+ # }
+ # }
+ #
+ def self.udp_server_recv(sockets)
+ sockets.each {|r|
+ msg, sender_addrinfo, _, *controls = r.recvmsg_nonblock(exception: false)
+ next if msg == :wait_readable
+ ai = r.local_address
+ if ai.ipv6? and pktinfo = controls.find {|c| c.cmsg_is?(:IPV6, :PKTINFO) }
+ ai = Addrinfo.udp(pktinfo.ipv6_pktinfo_addr.ip_address, ai.ip_port)
+ yield msg, UDPSource.new(sender_addrinfo, ai) {|reply_msg|
+ r.sendmsg reply_msg, 0, sender_addrinfo, pktinfo
+ }
+ else
+ yield msg, UDPSource.new(sender_addrinfo, ai) {|reply_msg|
+ r.send reply_msg, 0, sender_addrinfo
+ }
+ end
+ }
+ end
+
+ # :call-seq:
+ # Socket.udp_server_loop_on(sockets) {|msg, msg_src| ... }
+ #
+ # Run UDP/IP server loop on the given sockets.
+ #
+ # The return value of Socket.udp_server_sockets is appropriate for the argument.
+ #
+ # It calls the block for each message received.
+ #
+ def self.udp_server_loop_on(sockets, &b) # :yield: msg, msg_src
+ loop {
+ readable, _, _ = IO.select(sockets)
+ udp_server_recv(readable, &b)
+ }
+ end
+
+ # :call-seq:
+ # Socket.udp_server_loop(port) {|msg, msg_src| ... }
+ # Socket.udp_server_loop(host, port) {|msg, msg_src| ... }
+ #
+ # creates a UDP/IP server on _port_ and calls the block for each message arrived.
+ # The block is called with the message and its source information.
+ #
+ # This method allocates sockets internally using _port_.
+ # If _host_ is specified, it is used conjunction with _port_ to determine the server addresses.
+ #
+ # The _msg_ is a string.
+ #
+ # The _msg_src_ is a Socket::UDPSource object.
+ # It is used for reply.
+ #
+ # # UDP/IP echo server.
+ # Socket.udp_server_loop(9261) {|msg, msg_src|
+ # msg_src.reply msg
+ # }
+ #
+ def self.udp_server_loop(host=nil, port, &b) # :yield: message, message_source
+ udp_server_sockets(host, port) {|sockets|
+ udp_server_loop_on(sockets, &b)
+ }
+ end
+
+ # UDP/IP address information used by Socket.udp_server_loop.
+ class UDPSource
+ # +remote_address+ is an Addrinfo object.
+ #
+ # +local_address+ is an Addrinfo object.
+ #
+ # +reply_proc+ is a Proc used to send reply back to the source.
+ def initialize(remote_address, local_address, &reply_proc)
+ @remote_address = remote_address
+ @local_address = local_address
+ @reply_proc = reply_proc
+ end
+
+ # Address of the source
+ attr_reader :remote_address
+
+ # Local address
+ attr_reader :local_address
+
+ def inspect # :nodoc:
+ "\#<#{self.class}: #{@remote_address.inspect_sockaddr} to #{@local_address.inspect_sockaddr}>".dup
+ end
+
+ # Sends the String +msg+ to the source
+ def reply(msg)
+ @reply_proc.call msg
+ end
+ end
+
+ # creates a new socket connected to path using UNIX socket socket.
+ #
+ # If a block is given, the block is called with the socket.
+ # The value of the block is returned.
+ # The socket is closed when this method returns.
+ #
+ # If no block is given, the socket is returned.
+ #
+ # # talk to /tmp/sock socket.
+ # Socket.unix("/tmp/sock") {|sock|
+ # t = Thread.new { IO.copy_stream(sock, STDOUT) }
+ # IO.copy_stream(STDIN, sock)
+ # t.join
+ # }
+ #
+ def self.unix(path) # :yield: socket
+ addr = Addrinfo.unix(path)
+ sock = addr.connect
+ if block_given?
+ begin
+ yield sock
+ ensure
+ sock.close
+ end
+ else
+ sock
+ end
+ end
+
+ # creates a UNIX server socket on _path_
+ #
+ # If no block given, it returns a listening socket.
+ #
+ # If a block is given, it is called with the socket and the block value is returned.
+ # When the block exits, the socket is closed and the socket file is removed.
+ #
+ # socket = Socket.unix_server_socket("/tmp/s")
+ # p socket #=> #<Socket:fd 3>
+ # p socket.local_address #=> #<Addrinfo: /tmp/s SOCK_STREAM>
+ #
+ # Socket.unix_server_socket("/tmp/sock") {|s|
+ # p s #=> #<Socket:fd 3>
+ # p s.local_address #=> # #<Addrinfo: /tmp/sock SOCK_STREAM>
+ # }
+ #
+ def self.unix_server_socket(path)
+ unless unix_socket_abstract_name?(path)
+ begin
+ st = File.lstat(path)
+ rescue Errno::ENOENT
+ end
+ if st&.socket? && st.owned?
+ File.unlink path
+ end
+ end
+ s = Addrinfo.unix(path).listen
+ if block_given?
+ begin
+ yield s
+ ensure
+ s.close
+ unless unix_socket_abstract_name?(path)
+ File.unlink path
+ end
+ end
+ else
+ s
+ end
+ end
+
+ # :stopdoc:
+ if RUBY_PLATFORM.include?("linux")
+ def self.unix_socket_abstract_name?(path)
+ path.empty? or path.start_with?("\0")
+ end
+ else
+ def self.unix_socket_abstract_name?(path)
+ false
+ end
+ end
+ private_class_method :unix_socket_abstract_name?
+ # :startdoc:
+
+ # creates a UNIX socket server on _path_.
+ # It calls the block for each socket accepted.
+ #
+ # If _host_ is specified, it is used with _port_ to determine the server ports.
+ #
+ # The socket is *not* closed when the block returns.
+ # So application should close it.
+ #
+ # This method deletes the socket file pointed by _path_ at first if
+ # the file is a socket file and it is owned by the user of the application.
+ # This is safe only if the directory of _path_ is not changed by a malicious user.
+ # So don't use /tmp/malicious-users-directory/socket.
+ # Note that /tmp/socket and /tmp/your-private-directory/socket is safe assuming that /tmp has sticky bit.
+ #
+ # # Sequential echo server.
+ # # It services only one client at a time.
+ # Socket.unix_server_loop("/tmp/sock") {|sock, client_addrinfo|
+ # begin
+ # IO.copy_stream(sock, sock)
+ # ensure
+ # sock.close
+ # end
+ # }
+ #
+ def self.unix_server_loop(path, &b) # :yield: socket, client_addrinfo
+ unix_server_socket(path) {|serv|
+ accept_loop(serv, &b)
+ }
+ end
+
+ # call-seq:
+ # socket.connect_nonblock(remote_sockaddr, [options]) => 0
+ #
+ # Requests a connection to be made on the given +remote_sockaddr+ after
+ # O_NONBLOCK is set for the underlying file descriptor.
+ # Returns 0 if successful, otherwise an exception is raised.
+ #
+ # === Parameter
+ # * +remote_sockaddr+ - the +struct+ sockaddr contained in a string or Addrinfo object
+ #
+ # === Example:
+ # # Pull down Google's web page
+ # require 'socket'
+ # include Socket::Constants
+ # socket = Socket.new(AF_INET, SOCK_STREAM, 0)
+ # sockaddr = Socket.sockaddr_in(80, 'www.google.com')
+ # begin # emulate blocking connect
+ # socket.connect_nonblock(sockaddr)
+ # rescue IO::WaitWritable
+ # IO.select(nil, [socket]) # wait 3-way handshake completion
+ # begin
+ # socket.connect_nonblock(sockaddr) # check connection failure
+ # rescue Errno::EISCONN
+ # end
+ # end
+ # socket.write("GET / HTTP/1.0\r\n\r\n")
+ # results = socket.read
+ #
+ # Refer to Socket#connect for the exceptions that may be thrown if the call
+ # to _connect_nonblock_ fails.
+ #
+ # Socket#connect_nonblock may raise any error corresponding to connect(2) failure,
+ # including Errno::EINPROGRESS.
+ #
+ # If the exception is Errno::EINPROGRESS,
+ # it is extended by IO::WaitWritable.
+ # So IO::WaitWritable can be used to rescue the exceptions for retrying connect_nonblock.
+ #
+ # By specifying a keyword argument _exception_ to +false+, you can indicate
+ # that connect_nonblock should not raise an IO::WaitWritable exception, but
+ # return the symbol +:wait_writable+ instead.
+ #
+ # === See
+ # * Socket#connect
+ def connect_nonblock(addr, exception: true)
+ __connect_nonblock(addr, exception)
+ end
+end
+
+class UDPSocket < IPSocket
+
+ # call-seq:
+ # udpsocket.recvfrom_nonblock(maxlen [, flags[, outbuf [, options]]]) => [mesg, sender_inet_addr]
+ #
+ # Receives up to _maxlen_ bytes from +udpsocket+ using recvfrom(2) after
+ # O_NONBLOCK is set for the underlying file descriptor.
+ # _flags_ is zero or more of the +MSG_+ options.
+ # The first element of the results, _mesg_, is the data received.
+ # The second element, _sender_inet_addr_, is an array to represent the sender address.
+ #
+ # When recvfrom(2) returns 0, Socket#recv_nonblock returns nil.
+ # In most cases it means the connection was closed, but it may also mean
+ # an empty packet was received, as the underlying API makes
+ # it impossible to distinguish these two cases.
+ #
+ # === Parameters
+ # * +maxlen+ - the number of bytes to receive from the socket
+ # * +flags+ - zero or more of the +MSG_+ options
+ # * +outbuf+ - destination String buffer
+ # * +options+ - keyword hash, supporting `exception: false`
+ #
+ # === Example
+ # require 'socket'
+ # s1 = UDPSocket.new
+ # s1.bind("127.0.0.1", 0)
+ # s2 = UDPSocket.new
+ # s2.bind("127.0.0.1", 0)
+ # s2.connect(*s1.addr.values_at(3,1))
+ # s1.connect(*s2.addr.values_at(3,1))
+ # s1.send "aaa", 0
+ # begin # emulate blocking recvfrom
+ # p s2.recvfrom_nonblock(10) #=> ["aaa", ["AF_INET", 33302, "localhost.localdomain", "127.0.0.1"]]
+ # rescue IO::WaitReadable
+ # IO.select([s2])
+ # retry
+ # end
+ #
+ # Refer to Socket#recvfrom for the exceptions that may be thrown if the call
+ # to _recvfrom_nonblock_ fails.
+ #
+ # UDPSocket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
+ # including Errno::EWOULDBLOCK.
+ #
+ # If the exception is Errno::EWOULDBLOCK or Errno::EAGAIN,
+ # it is extended by IO::WaitReadable.
+ # So IO::WaitReadable can be used to rescue the exceptions for retrying recvfrom_nonblock.
+ #
+ # By specifying a keyword argument _exception_ to +false+, you can indicate
+ # that recvfrom_nonblock should not raise an IO::WaitReadable exception, but
+ # return the symbol +:wait_readable+ instead.
+ #
+ # === See
+ # * Socket#recvfrom
+ def recvfrom_nonblock(len, flag = 0, outbuf = nil, exception: true)
+ __recvfrom_nonblock(len, flag, outbuf, exception)
+ end
+end
+
+class TCPServer < TCPSocket
+
+ # call-seq:
+ # tcpserver.accept_nonblock([options]) => tcpsocket
+ #
+ # Accepts an incoming connection using accept(2) after
+ # O_NONBLOCK is set for the underlying file descriptor.
+ # It returns an accepted TCPSocket for the incoming connection.
+ #
+ # === Example
+ # require 'socket'
+ # serv = TCPServer.new(2202)
+ # begin # emulate blocking accept
+ # sock = serv.accept_nonblock
+ # rescue IO::WaitReadable, Errno::EINTR
+ # IO.select([serv])
+ # retry
+ # end
+ # # sock is an accepted socket.
+ #
+ # Refer to Socket#accept for the exceptions that may be thrown if the call
+ # to TCPServer#accept_nonblock fails.
+ #
+ # TCPServer#accept_nonblock may raise any error corresponding to accept(2) failure,
+ # including Errno::EWOULDBLOCK.
+ #
+ # If the exception is Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO,
+ # it is extended by IO::WaitReadable.
+ # So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock.
+ #
+ # By specifying a keyword argument _exception_ to +false+, you can indicate
+ # that accept_nonblock should not raise an IO::WaitReadable exception, but
+ # return the symbol +:wait_readable+ instead.
+ #
+ # === See
+ # * TCPServer#accept
+ # * Socket#accept
+ def accept_nonblock(exception: true)
+ __accept_nonblock(exception)
+ end
+end
+
+class UNIXServer < UNIXSocket
+ # call-seq:
+ # unixserver.accept_nonblock([options]) => unixsocket
+ #
+ # Accepts an incoming connection using accept(2) after
+ # O_NONBLOCK is set for the underlying file descriptor.
+ # It returns an accepted UNIXSocket for the incoming connection.
+ #
+ # === Example
+ # require 'socket'
+ # serv = UNIXServer.new("/tmp/sock")
+ # begin # emulate blocking accept
+ # sock = serv.accept_nonblock
+ # rescue IO::WaitReadable, Errno::EINTR
+ # IO.select([serv])
+ # retry
+ # end
+ # # sock is an accepted socket.
+ #
+ # Refer to Socket#accept for the exceptions that may be thrown if the call
+ # to UNIXServer#accept_nonblock fails.
+ #
+ # UNIXServer#accept_nonblock may raise any error corresponding to accept(2) failure,
+ # including Errno::EWOULDBLOCK.
+ #
+ # If the exception is Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::ECONNABORTED or Errno::EPROTO,
+ # it is extended by IO::WaitReadable.
+ # So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock.
+ #
+ # By specifying a keyword argument _exception_ to +false+, you can indicate
+ # that accept_nonblock should not raise an IO::WaitReadable exception, but
+ # return the symbol +:wait_readable+ instead.
+ #
+ # === See
+ # * UNIXServer#accept
+ # * Socket#accept
+ def accept_nonblock(exception: true)
+ __accept_nonblock(exception)
+ end
+end if defined?(UNIXSocket)
diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb
new file mode 100644
index 0000000000..4271e40cd8
--- /dev/null
+++ b/ext/socket/mkconstants.rb
@@ -0,0 +1,854 @@
+# frozen_string_literal: false
+require 'optparse'
+require 'erb'
+
+opt = OptionParser.new
+
+opt.def_option('-h', 'help') {
+ puts opt
+ exit 0
+}
+
+opt_o = nil
+opt.def_option('-o FILE', 'specify output file') {|filename|
+ opt_o = filename
+}
+
+opt_H = nil
+opt.def_option('-H FILE', 'specify output header file') {|filename|
+ opt_H = filename
+}
+
+C_ESC = {
+ "\\" => "\\\\",
+ '"' => '\"',
+ "\n" => '\n',
+}
+
+0x00.upto(0x1f) {|ch| C_ESC[[ch].pack("C")] ||= "\\%03o" % ch }
+0x7f.upto(0xff) {|ch| C_ESC[[ch].pack("C")] = "\\%03o" % ch }
+C_ESC_PAT = Regexp.union(*C_ESC.keys)
+
+def c_str(str)
+ '"' + str.gsub(C_ESC_PAT) {|s| C_ESC[s]} + '"'
+end
+
+opt.parse!
+
+
+
+h = {}
+COMMENTS = Hash.new { |h, name| h[name] = name }
+
+DATA.each_line {|s|
+ name, default_value, comment = s.chomp.split(/\s+/, 3)
+ next unless name && name[0] != ?#
+
+ default_value = nil if default_value == 'nil'
+
+ if h.has_key? name
+ warn "#{$.}: warning: duplicate name: #{name}"
+ next
+ end
+ h[name] = default_value
+ if comment
+ # Stop unintentional references
+ COMMENTS[name] = comment.gsub(/\b(Data|Kernel|Process|Set|Socket|Time)\b/, '\\\\\\&')
+ end
+}
+DEFS = h.to_a
+
+def each_const
+ DEFS.each {|name, default_value|
+ guard = nil
+ if /\A(AF_INET6|PF_INET6|IPV6_.*)\z/ =~ name
+ # IPv6 is not supported although AF_INET6 is defined on mingw
+ guard = "defined(INET6)"
+ end
+ yield guard, name, default_value
+ }
+end
+
+def each_name(pat)
+ DEFS.each {|name, default_value|
+ next if pat !~ name
+ yield name
+ }
+end
+
+erb_new = lambda do |src, trim|
+ ERB.new(src, trim_mode: trim)
+end
+
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_decls")
+% each_const {|guard, name, default_value|
+#if !defined(<%=name%>)
+# if defined(HAVE_CONST_<%=name.upcase%>)
+# define <%=name%> <%=name%>
+%if default_value
+# else
+# define <%=name%> <%=default_value%>
+%end
+# endif
+#endif
+% }
+EOS
+
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_defs_in_guard(name, default_value)")
+#if defined(<%=name%>)
+ /* <%= COMMENTS[name] %> */
+ rb_define_const(rb_cSocket, <%=c_str name%>, INTEGER2NUM(<%=name%>));
+ /* <%= COMMENTS[name] %> */
+ rb_define_const(rb_mSockConst, <%=c_str name%>, INTEGER2NUM(<%=name%>));
+#endif
+EOS
+
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_defs")
+% each_const {|guard, name, default_value|
+% if guard
+#if <%=guard%>
+<%= gen_const_defs_in_guard(name, default_value).chomp %>
+#endif
+% else
+<%= gen_const_defs_in_guard(name, default_value).chomp %>
+% end
+% }
+EOS
+
+def reverse_each_name(pat)
+ DEFS.reverse_each {|name, default_value|
+ next if pat !~ name
+ yield name
+ }
+end
+
+def each_names_with_len(pat, prefix_optional=nil)
+ h = {}
+ DEFS.each {|name, default_value|
+ next if pat !~ name
+ (h[name.length] ||= []) << [name, name]
+ }
+ if prefix_optional
+ if Regexp === prefix_optional
+ prefix_pat = prefix_optional
+ else
+ prefix_pat = /\A#{Regexp.escape prefix_optional}/
+ end
+ DEFS.each {|const, default_value|
+ next if pat !~ const
+ next if prefix_pat !~ const
+ name = $'
+ (h[name.length] ||= []) << [name, const]
+ }
+ end
+ hh = {}
+ h.each {|len, pairs|
+ pairs.each {|name, const|
+ raise "name crash: #{name}" if hh[name]
+ hh[name] = true
+ }
+ }
+ h.keys.sort.each {|len|
+ yield h[len], len
+ }
+end
+
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_name_to_int_decl(funcname, pat, prefix_optional, guard=nil)")
+%if guard
+#ifdef <%=guard%>
+int <%=funcname%>(const char *str, long len, int *valp);
+#endif
+%else
+int <%=funcname%>(const char *str, long len, int *valp);
+%end
+EOS
+
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard=nil)")
+int
+<%=funcname%>(const char *str, long len, int *valp)
+{
+ switch (len) {
+% each_names_with_len(pat, prefix_optional) {|pairs, len|
+ case <%=len%>:
+% pairs.each {|name, const|
+#ifdef <%=const%>
+ if (memcmp(str, <%=c_str name%>, <%=len%>) == 0) { *valp = <%=const%>; return 0; }
+#endif
+% }
+ return -1;
+
+% }
+ default:
+ if (!str || !valp) {/* wrong argument */}
+ return -1;
+ }
+}
+EOS
+
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_name_to_int_func(funcname, pat, prefix_optional, guard=nil)")
+%if guard
+#ifdef <%=guard%>
+<%=gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard)%>
+#endif
+%else
+<%=gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard)%>
+%end
+EOS
+
+NAME_TO_INT_DEFS = []
+def def_name_to_int(funcname, pat, prefix_optional, guard=nil)
+ decl = gen_name_to_int_decl(funcname, pat, prefix_optional, guard)
+ func = gen_name_to_int_func(funcname, pat, prefix_optional, guard)
+ NAME_TO_INT_DEFS << [decl, func]
+end
+
+def reverse_each_name_with_prefix_optional(pat, prefix_pat)
+ reverse_each_name(pat) {|n|
+ yield n, n
+ }
+ if prefix_pat
+ reverse_each_name(pat) {|n|
+ next if prefix_pat !~ n
+ yield n, $'
+ }
+ end
+end
+
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_int_to_name_hash(hash_var, pat, prefix_pat)")
+ <%=hash_var%> = st_init_numtable();
+% reverse_each_name_with_prefix_optional(pat, prefix_pat) {|n,s|
+#ifdef <%=n%>
+ st_insert(<%=hash_var%>, (st_data_t)<%=n%>, (st_data_t)rb_intern2(<%=c_str s%>, <%=s.length%>));
+#endif
+% }
+EOS
+
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_int_to_name_func(func_name, hash_var)")
+ID
+<%=func_name%>(int val)
+{
+ st_data_t name;
+ if (st_lookup(<%=hash_var%>, (st_data_t)val, &name))
+ return (ID)name;
+ return 0;
+}
+EOS
+
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_int_to_name_decl(func_name, hash_var)")
+ID <%=func_name%>(int val);
+EOS
+
+INTERN_DEFS = []
+def def_intern(func_name, pat, prefix_optional=nil)
+ prefix_pat = nil
+ if prefix_optional
+ if Regexp === prefix_optional
+ prefix_pat = prefix_optional
+ else
+ prefix_pat = /\A#{Regexp.escape prefix_optional}/
+ end
+ end
+ hash_var = "#{func_name}_hash"
+ vardef = "static st_table *#{hash_var};"
+ gen_hash = gen_int_to_name_hash(hash_var, pat, prefix_pat)
+ decl = gen_int_to_name_decl(func_name, hash_var)
+ func = gen_int_to_name_func(func_name, hash_var)
+ INTERN_DEFS << [vardef, gen_hash, decl, func]
+end
+
+def_name_to_int("rsock_family_to_int", /\A(AF_|PF_)/, "AF_")
+def_name_to_int("rsock_socktype_to_int", /\ASOCK_/, "SOCK_")
+def_name_to_int("rsock_ipproto_to_int", /\AIPPROTO_/, "IPPROTO_")
+def_name_to_int("rsock_unknown_level_to_int", /\ASOL_SOCKET\z/, "SOL_")
+def_name_to_int("rsock_ip_level_to_int", /\A(SOL_SOCKET\z|IPPROTO_)/, /\A(SOL_|IPPROTO_)/)
+def_name_to_int("rsock_so_optname_to_int", /\ASO_/, "SO_")
+def_name_to_int("rsock_ip_optname_to_int", /\AIP_/, "IP_")
+def_name_to_int("rsock_ipv6_optname_to_int", /\AIPV6_/, "IPV6_", "IPPROTO_IPV6")
+def_name_to_int("rsock_tcp_optname_to_int", /\ATCP_/, "TCP_")
+def_name_to_int("rsock_udp_optname_to_int", /\AUDP_/, "UDP_")
+def_name_to_int("rsock_shutdown_how_to_int", /\ASHUT_/, "SHUT_")
+def_name_to_int("rsock_scm_optname_to_int", /\ASCM_/, "SCM_")
+
+def_intern('rsock_intern_family', /\AAF_/)
+def_intern('rsock_intern_family_noprefix', /\AAF_/, "AF_")
+def_intern('rsock_intern_protocol_family', /\APF_/)
+def_intern('rsock_intern_socktype', /\ASOCK_/)
+def_intern('rsock_intern_ipproto', /\AIPPROTO_/)
+def_intern('rsock_intern_iplevel', /\A(SOL_SOCKET\z|IPPROTO_)/, /\A(SOL_|IPPROTO_)/)
+def_intern('rsock_intern_so_optname', /\ASO_/, "SO_")
+def_intern('rsock_intern_ip_optname', /\AIP_/, "IP_")
+def_intern('rsock_intern_ipv6_optname', /\AIPV6_/, "IPV6_")
+def_intern('rsock_intern_tcp_optname', /\ATCP_/, "TCP_")
+def_intern('rsock_intern_udp_optname', /\AUDP_/, "UDP_")
+def_intern('rsock_intern_scm_optname', /\ASCM_/, "SCM_")
+def_intern('rsock_intern_local_optname', /\ALOCAL_/, "LOCAL_")
+
+result = erb_new.call(<<'EOS', '%').result(binding)
+/* autogenerated file */
+
+<%= INTERN_DEFS.map {|vardef, gen_hash, decl, func| vardef }.join("\n") %>
+
+#ifdef HAVE_LONG_LONG
+#define INTEGER2NUM(n) \
+ (FIXNUM_MAX < (n) ? ULL2NUM(n) : \
+ FIXNUM_MIN > (LONG_LONG)(n) ? LL2NUM(n) : \
+ LONG2FIX(n))
+#else
+#define INTEGER2NUM(n) \
+ (FIXNUM_MAX < (n) ? ULONG2NUM(n) : \
+ FIXNUM_MIN > (long)(n) ? LONG2NUM(n) : \
+ LONG2FIX(n))
+#endif
+
+static void
+init_constants(void)
+{
+ /*
+ * Document-module: Socket::Constants
+ *
+ * Socket::Constants provides socket-related constants. All possible
+ * socket constants are listed in the documentation but they may not all
+ * be present on your platform.
+ *
+ * If the underlying platform doesn't define a constant the corresponding
+ * Ruby constant is not defined.
+ *
+ */
+ rb_mSockConst = rb_define_module_under(rb_cSocket, "Constants");
+
+<%= gen_const_defs %>
+<%= INTERN_DEFS.map {|vardef, gen_hash, decl, func| gen_hash }.join("\n") %>
+}
+
+<%= NAME_TO_INT_DEFS.map {|decl, func| func }.join("\n") %>
+
+<%= INTERN_DEFS.map {|vardef, gen_hash, decl, func| func }.join("\n") %>
+
+EOS
+
+header_result = erb_new.call(<<'EOS', '%').result(binding)
+/* autogenerated file */
+<%= gen_const_decls %>
+<%= NAME_TO_INT_DEFS.map {|decl, func| decl }.join("\n") %>
+<%= INTERN_DEFS.map {|vardef, gen_hash, decl, func| decl }.join("\n") %>
+EOS
+
+if opt_H
+ File.open(opt_H, 'w') {|f|
+ f << header_result
+ }
+else
+ result = header_result + result
+end
+
+if opt_o
+ File.open(opt_o, 'w') {|f|
+ f << result
+ }
+else
+ $stdout << result
+end
+
+__END__
+
+SOCK_STREAM nil A stream socket provides a sequenced, reliable two-way connection for a byte stream
+SOCK_DGRAM nil A datagram socket provides connectionless, unreliable messaging
+SOCK_RAW nil A raw socket provides low-level access for direct access or implementing network protocols
+SOCK_RDM nil A reliable datagram socket provides reliable delivery of messages
+SOCK_SEQPACKET nil A sequential packet socket provides sequenced, reliable two-way connection for datagrams
+SOCK_PACKET nil Device-level packet access
+SOCK_NONBLOCK nil Set the O_NONBLOCK file status flag on the open file description (see open(2)) referred to by the new file descriptor.
+SOCK_CLOEXEC nil Set the close-on-exec (FD_CLOEXEC) flag on the new file descriptor.
+
+AF_UNSPEC nil Unspecified protocol, any supported address family
+PF_UNSPEC nil Unspecified protocol, any supported address family
+AF_INET nil IPv4 protocol
+PF_INET nil IPv4 protocol
+AF_INET6 nil IPv6 protocol
+PF_INET6 nil IPv6 protocol
+AF_UNIX nil UNIX sockets
+PF_UNIX nil UNIX sockets
+AF_AX25 nil AX.25 protocol
+PF_AX25 nil AX.25 protocol
+AF_IPX nil IPX protocol
+PF_IPX nil IPX protocol
+AF_APPLETALK nil AppleTalk protocol
+PF_APPLETALK nil AppleTalk protocol
+AF_LOCAL nil Host-internal protocols
+PF_LOCAL nil Host-internal protocols
+AF_IMPLINK nil ARPANET IMP protocol
+PF_IMPLINK nil ARPANET IMP protocol
+AF_PUP nil PARC Universal Packet protocol
+PF_PUP nil PARC Universal Packet protocol
+AF_CHAOS nil MIT CHAOS protocols
+PF_CHAOS nil MIT CHAOS protocols
+AF_NS nil XEROX NS protocols
+PF_NS nil XEROX NS protocols
+AF_ISO nil ISO Open Systems Interconnection protocols
+PF_ISO nil ISO Open Systems Interconnection protocols
+AF_OSI nil ISO Open Systems Interconnection protocols
+PF_OSI nil ISO Open Systems Interconnection protocols
+AF_ECMA nil European Computer Manufacturers protocols
+PF_ECMA nil European Computer Manufacturers protocols
+AF_DATAKIT nil Datakit protocol
+PF_DATAKIT nil Datakit protocol
+AF_CCITT nil CCITT (now ITU-T) protocols
+PF_CCITT nil CCITT (now ITU-T) protocols
+AF_SNA nil IBM SNA protocol
+PF_SNA nil IBM SNA protocol
+AF_DEC nil DECnet protocol
+PF_DEC nil DECnet protocol
+AF_DECnet nil DECnet protocol
+PF_DECnet nil DECnet protocol
+AF_DLI nil DEC Direct Data Link Interface protocol
+PF_DLI nil DEC Direct Data Link Interface protocol
+AF_LAT nil Local Area Transport protocol
+PF_LAT nil Local Area Transport protocol
+AF_HYLINK nil NSC Hyperchannel protocol
+PF_HYLINK nil NSC Hyperchannel protocol
+AF_ROUTE nil Internal routing protocol
+PF_ROUTE nil Internal routing protocol
+AF_LINK nil Link layer interface
+PF_LINK nil Link layer interface
+AF_COIP nil Connection-oriented IP
+PF_COIP nil Connection-oriented IP
+AF_CNT nil Computer Network Technology
+PF_CNT nil Computer Network Technology
+AF_SIP nil Simple Internet Protocol
+PF_SIP nil Simple Internet Protocol
+AF_NDRV nil Network driver raw access
+PF_NDRV nil Network driver raw access
+AF_ISDN nil Integrated Services Digital Network
+PF_ISDN nil Integrated Services Digital Network
+AF_NATM nil Native ATM access
+PF_NATM nil Native ATM access
+AF_SYSTEM nil Kernel event messages
+PF_SYSTEM nil Kernel event messages
+AF_NETBIOS nil NetBIOS
+PF_NETBIOS nil NetBIOS
+AF_PPP nil Point-to-Point Protocol
+PF_PPP nil Point-to-Point Protocol
+AF_ATM nil Asynchronous Transfer Mode
+PF_ATM nil Asynchronous Transfer Mode
+AF_NETGRAPH nil Netgraph sockets
+PF_NETGRAPH nil Netgraph sockets
+AF_MAX nil Maximum address family for this platform
+PF_MAX nil Maximum address family for this platform
+AF_PACKET nil Direct link-layer access
+PF_PACKET nil Direct link-layer access
+
+AF_E164 nil CCITT (ITU-T) E.164 recommendation
+PF_XTP nil eXpress Transfer Protocol
+PF_RTIP nil Help Identify RTIP packets
+PF_PIP nil Help Identify PIP packets
+AF_KEY nil Key management protocol, originally developed for usage with IPsec
+PF_KEY nil Key management protocol, originally developed for usage with IPsec
+AF_NETLINK nil Kernel user interface device
+PF_NETLINK nil Kernel user interface device
+AF_RDS nil Reliable Datagram Sockets (RDS) protocol
+PF_RDS nil Reliable Datagram Sockets (RDS) protocol
+AF_PPPOX nil Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE)
+PF_PPPOX nil Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE)
+AF_LLC nil Logical link control (IEEE 802.2 LLC) protocol
+PF_LLC nil Logical link control (IEEE 802.2 LLC) protocol
+AF_IB nil InfiniBand native addressing
+PF_IB nil InfiniBand native addressing
+AF_MPLS nil Multiprotocol Label Switching
+PF_MPLS nil Multiprotocol Label Switching
+AF_CAN nil Controller Area Network automotive bus protocol
+PF_CAN nil Controller Area Network automotive bus protocol
+AF_TIPC nil TIPC, "cluster domain sockets" protocol
+PF_TIPC nil TIPC, "cluster domain sockets" protocol
+AF_BLUETOOTH nil Bluetooth low-level socket protocol
+PF_BLUETOOTH nil Bluetooth low-level socket protocol
+AF_ALG nil Interface to kernel crypto API
+PF_ALG nil Interface to kernel crypto API
+AF_VSOCK nil VSOCK (originally "VMWare VSockets") protocol for hypervisor-guest communication
+PF_VSOCK nil VSOCK (originally "VMWare VSockets") protocol for hypervisor-guest communication
+AF_KCM nil KCM (kernel connection multiplexor) interface
+PF_KCM nil KCM (kernel connection multiplexor) interface
+AF_XDP nil XDP (express data path) interface
+PF_XDP nil XDP (express data path) interface
+
+MSG_OOB nil Process out-of-band data
+MSG_PEEK nil Peek at incoming message
+MSG_DONTROUTE nil Send without using the routing tables
+MSG_EOR nil Data completes record
+MSG_TRUNC nil Data discarded before delivery
+MSG_CTRUNC nil Control data lost before delivery
+MSG_WAITALL nil Wait for full request or error
+MSG_DONTWAIT nil This message should be non-blocking
+MSG_EOF nil Data completes connection
+MSG_FLUSH nil Start of a hold sequence. Dumps to so_temp
+MSG_HOLD nil Hold fragment in so_temp
+MSG_SEND nil Send the packet in so_temp
+MSG_HAVEMORE nil Data ready to be read
+MSG_RCVMORE nil Data remains in the current packet
+MSG_COMPAT nil End of record
+MSG_PROXY nil Wait for full request
+MSG_FIN
+MSG_SYN
+MSG_CONFIRM nil Confirm path validity
+MSG_RST
+MSG_ERRQUEUE nil Fetch message from error queue
+MSG_NOSIGNAL nil Do not generate SIGPIPE
+MSG_MORE nil Sender will send more
+MSG_FASTOPEN nil Reduce step of the handshake process
+
+SOL_SOCKET nil Socket-level options
+SOL_IP nil IP socket options
+SOL_IPX nil IPX socket options
+SOL_AX25 nil AX.25 socket options
+SOL_ATALK nil AppleTalk socket options
+SOL_TCP nil TCP socket options
+SOL_UDP nil UDP socket options
+
+IPPROTO_IP 0 Dummy protocol for IP
+IPPROTO_ICMP 1 Control message protocol
+IPPROTO_IGMP nil Group Management Protocol
+IPPROTO_GGP nil Gateway to Gateway Protocol
+IPPROTO_TCP 6 TCP
+IPPROTO_EGP nil Exterior Gateway Protocol
+IPPROTO_PUP nil PARC Universal Packet protocol
+IPPROTO_UDP 17 UDP
+IPPROTO_IDP nil XNS IDP
+IPPROTO_HELLO nil "hello" routing protocol
+IPPROTO_ND nil Sun net disk protocol
+IPPROTO_TP nil ISO transport protocol class 4
+IPPROTO_XTP nil Xpress Transport Protocol
+IPPROTO_EON nil ISO cnlp
+IPPROTO_BIP
+IPPROTO_AH nil IP6 auth header
+IPPROTO_DSTOPTS nil IP6 destination option
+IPPROTO_ESP nil IP6 Encapsulated Security Payload
+IPPROTO_FRAGMENT nil IP6 fragmentation header
+IPPROTO_HOPOPTS nil IP6 hop-by-hop options
+IPPROTO_ICMPV6 nil ICMP6
+IPPROTO_IPV6 nil IP6 header
+IPPROTO_NONE nil IP6 no next header
+IPPROTO_ROUTING nil IP6 routing header
+
+IPPROTO_RAW 255 Raw IP packet
+IPPROTO_MAX nil Maximum IPPROTO constant
+
+# Some port configuration
+IPPORT_RESERVED 1024 Default minimum address for bind or connect
+IPPORT_USERRESERVED 5000 Default maximum address for bind or connect
+
+# Some reserved IP v.4 addresses
+INADDR_ANY 0x00000000 A socket bound to INADDR_ANY receives packets from all interfaces and sends from the default IP address
+INADDR_BROADCAST 0xffffffff The network broadcast address
+INADDR_LOOPBACK 0x7F000001 The loopback address
+INADDR_UNSPEC_GROUP 0xe0000000 The reserved multicast group
+INADDR_ALLHOSTS_GROUP 0xe0000001 Multicast group for all systems on this subset
+INADDR_MAX_LOCAL_GROUP 0xe00000ff The last local network multicast group
+INADDR_NONE 0xffffffff A bitmask for matching no valid IP address
+
+# IP [gs]etsockopt options
+IP_OPTIONS nil IP options to be included in packets
+IP_HDRINCL nil Header is included with data
+IP_TOS nil IP type-of-service
+IP_TTL nil IP time-to-live
+IP_RECVOPTS nil Receive all IP options with datagram
+IP_RECVRETOPTS nil Receive all IP options for response
+IP_RECVDSTADDR nil Receive IP destination address with datagram
+IP_RETOPTS nil IP options to be included in datagrams
+IP_MINTTL nil Minimum TTL allowed for received packets
+IP_DONTFRAG nil Don't fragment packets
+IP_SENDSRCADDR nil Source address for outgoing UDP datagrams
+IP_ONESBCAST nil Force outgoing broadcast datagrams to have the undirected broadcast address
+IP_RECVTTL nil Receive IP TTL with datagrams
+IP_RECVIF nil Receive interface information with datagrams
+IP_RECVSLLA nil Receive link-layer address with datagrams
+IP_PORTRANGE nil Set the port range for sockets with unspecified port numbers
+IP_MULTICAST_IF nil IP multicast interface
+IP_MULTICAST_TTL nil IP multicast TTL
+IP_MULTICAST_LOOP nil IP multicast loopback
+IP_ADD_MEMBERSHIP nil Add a multicast group membership
+IP_DROP_MEMBERSHIP nil Drop a multicast group membership
+IP_DEFAULT_MULTICAST_TTL nil Default multicast TTL
+IP_DEFAULT_MULTICAST_LOOP nil Default multicast loopback
+IP_MAX_MEMBERSHIPS nil Maximum number multicast groups a socket can join
+IP_ROUTER_ALERT nil Notify transit routers to more closely examine the contents of an IP packet
+IP_PKTINFO nil Receive packet information with datagrams
+IP_PKTOPTIONS nil Receive packet options with datagrams
+IP_MTU_DISCOVER nil Path MTU discovery
+IP_RECVERR nil Enable extended reliable error message passing
+IP_RECVTOS nil Receive TOS with incoming packets
+IP_MTU nil The Maximum Transmission Unit of the socket
+IP_FREEBIND nil Allow binding to nonexistent IP addresses
+IP_IPSEC_POLICY nil IPsec security policy
+IP_XFRM_POLICY
+IP_PASSSEC nil Retrieve security context with datagram
+IP_TRANSPARENT nil Transparent proxy
+IP_PMTUDISC_DONT nil Never send DF frames
+IP_PMTUDISC_WANT nil Use per-route hints
+IP_PMTUDISC_DO nil Always send DF frames
+IP_UNBLOCK_SOURCE nil Unblock IPv4 multicast packets with a give source address
+IP_BLOCK_SOURCE nil Block IPv4 multicast packets with a give source address
+IP_ADD_SOURCE_MEMBERSHIP nil Add a multicast group membership
+IP_DROP_SOURCE_MEMBERSHIP nil Drop a multicast group membership
+IP_MSFILTER nil Multicast source filtering
+
+MCAST_JOIN_GROUP nil Join a multicast group
+MCAST_BLOCK_SOURCE nil Block multicast packets from this source
+MCAST_UNBLOCK_SOURCE nil Unblock multicast packets from this source
+MCAST_LEAVE_GROUP nil Leave a multicast group
+MCAST_JOIN_SOURCE_GROUP nil Join a multicast source group
+MCAST_LEAVE_SOURCE_GROUP nil Leave a multicast source group
+MCAST_MSFILTER nil Multicast source filtering
+MCAST_EXCLUDE nil Exclusive multicast source filter
+MCAST_INCLUDE nil Inclusive multicast source filter
+
+SO_DEBUG nil Debug info recording
+SO_REUSEADDR nil Allow local address reuse
+SO_REUSEPORT nil Allow local address and port reuse
+SO_TYPE nil Get the socket type
+SO_ERROR nil Get and clear the error status
+SO_DONTROUTE nil Use interface addresses
+SO_BROADCAST nil Permit sending of broadcast messages
+SO_SNDBUF nil Send buffer size
+SO_RCVBUF nil Receive buffer size
+SO_SNDBUFFORCE nil Send buffer size without wmem_max limit (Linux 2.6.14)
+SO_RCVBUFFORCE nil Receive buffer size without rmem_max limit (Linux 2.6.14)
+SO_KEEPALIVE nil Keep connections alive
+SO_OOBINLINE nil Leave received out-of-band data in-line
+SO_NO_CHECK nil Disable checksums
+SO_PRIORITY nil The protocol-defined priority for all packets on this socket
+SO_LINGER nil Linger on close if data is present
+SO_PASSCRED nil Receive SCM_CREDENTIALS messages
+SO_PEERCRED nil The credentials of the foreign process connected to this socket
+SO_RCVLOWAT nil Receive low-water mark
+SO_SNDLOWAT nil Send low-water mark
+SO_RCVTIMEO nil Receive timeout
+SO_SNDTIMEO nil Send timeout
+SO_ACCEPTCONN nil Socket has had listen() called on it
+SO_USELOOPBACK nil Bypass hardware when possible
+SO_ACCEPTFILTER nil There is an accept filter
+SO_USER_COOKIE nil Setting an identifier for ipfw purpose mainly
+SO_DONTTRUNC nil Retain unread data
+SO_WANTMORE nil Give a hint when more data is ready
+SO_WANTOOBFLAG nil OOB data is wanted in MSG_FLAG on receive
+SO_NREAD nil Get first packet byte count
+SO_NKE nil Install socket-level Network Kernel Extension
+SO_NOSIGPIPE nil Don't SIGPIPE on EPIPE
+SO_SECURITY_AUTHENTICATION
+SO_SECURITY_ENCRYPTION_TRANSPORT
+SO_SECURITY_ENCRYPTION_NETWORK
+SO_BINDTODEVICE nil Only send packets from the given interface
+SO_ATTACH_FILTER nil Attach an accept filter
+SO_DETACH_FILTER nil Detach an accept filter
+SO_GET_FILTER nil Obtain filter set by SO_ATTACH_FILTER (Linux 3.8)
+SO_PEERNAME nil Name of the connecting user
+SO_TIMESTAMP nil Receive timestamp with datagrams (timeval)
+SO_TIMESTAMPNS nil Receive nanosecond timestamp with datagrams (timespec)
+SO_BINTIME nil Receive timestamp with datagrams (bintime)
+SO_RECVUCRED nil Receive user credentials with datagram
+SO_MAC_EXEMPT nil Mandatory Access Control exemption for unlabeled peers
+SO_ALLZONES nil Bypass zone boundaries
+SO_PEERSEC nil Obtain the security credentials (Linux 2.6.2)
+SO_PASSSEC nil Toggle security context passing (Linux 2.6.18)
+SO_MARK nil Set the mark for mark-based routing (Linux 2.6.25)
+SO_TIMESTAMPING nil Time stamping of incoming and outgoing packets (Linux 2.6.30)
+SO_PROTOCOL nil Protocol given for socket() (Linux 2.6.32)
+SO_DOMAIN nil Domain given for socket() (Linux 2.6.32)
+SO_RXQ_OVFL nil Toggle cmsg for number of packets dropped (Linux 2.6.33)
+SO_WIFI_STATUS nil Toggle cmsg for wifi status (Linux 3.3)
+SO_PEEK_OFF nil Set the peek offset (Linux 3.4)
+SO_NOFCS nil Set netns of a socket (Linux 3.4)
+SO_LOCK_FILTER nil Lock the filter attached to a socket (Linux 3.9)
+SO_SELECT_ERR_QUEUE nil Make select() detect socket error queue with errorfds (Linux 3.10)
+SO_BUSY_POLL nil Set the threshold in microseconds for low latency polling (Linux 3.11)
+SO_MAX_PACING_RATE nil Cap the rate computed by transport layer. [bytes per second] (Linux 3.13)
+SO_BPF_EXTENSIONS nil Query supported BPF extensions (Linux 3.14)
+SO_SETFIB nil Set the associated routing table for the socket (FreeBSD)
+SO_RTABLE nil Set the routing table for this socket (OpenBSD)
+SO_INCOMING_CPU nil Receive the cpu attached to the socket (Linux 3.19)
+SO_INCOMING_NAPI_ID nil Receive the napi ID attached to a RX queue (Linux 4.12)
+SO_CONNECT_TIME nil Returns the number of seconds a socket has been connected. This option is only valid for connection-oriented protocols (Windows)
+
+SOPRI_INTERACTIVE nil Interactive socket priority
+SOPRI_NORMAL nil Normal socket priority
+SOPRI_BACKGROUND nil Background socket priority
+
+IPX_TYPE
+
+TCP_NODELAY nil Don't delay sending to coalesce packets
+TCP_MAXSEG nil Set maximum segment size
+TCP_CONNECTION_INFO nil Retrieve information about this socket (macOS)
+TCP_CORK nil Don't send partial frames (Linux 2.2, glibc 2.2)
+TCP_DEFER_ACCEPT nil Don't notify a listening socket until data is ready (Linux 2.4, glibc 2.2)
+TCP_INFO nil Retrieve information about this socket (Linux 2.4, glibc 2.2)
+TCP_KEEPALIVE nil Idle time before keepalive probes are sent (macOS)
+TCP_KEEPCNT nil Maximum number of keepalive probes allowed before dropping a connection (Linux 2.4, glibc 2.2)
+TCP_KEEPIDLE nil Idle time before keepalive probes are sent (Linux 2.4, glibc 2.2)
+TCP_KEEPINTVL nil Time between keepalive probes (Linux 2.4, glibc 2.2)
+TCP_LINGER2 nil Lifetime of orphaned FIN_WAIT2 sockets (Linux 2.4, glibc 2.2)
+TCP_MD5SIG nil Use MD5 digests (RFC2385, Linux 2.6.20, glibc 2.7)
+TCP_NOOPT nil Don't use TCP options
+TCP_NOPUSH nil Don't push the last block of write
+TCP_QUICKACK nil Enable quickack mode (Linux 2.4.4, glibc 2.3)
+TCP_SYNCNT nil Number of SYN retransmits before a connection is dropped (Linux 2.4, glibc 2.2)
+TCP_WINDOW_CLAMP nil Clamp the size of the advertised window (Linux 2.4, glibc 2.2)
+TCP_FASTOPEN nil Reduce step of the handshake process (Linux 3.7, glibc 2.18)
+TCP_CONGESTION nil TCP congestion control algorithm (Linux 2.6.13, glibc 2.6)
+TCP_COOKIE_TRANSACTIONS nil TCP Cookie Transactions (Linux 2.6.33, glibc 2.18)
+TCP_QUEUE_SEQ nil Sequence of a queue for repair mode (Linux 3.5, glibc 2.18)
+TCP_REPAIR nil Repair mode (Linux 3.5, glibc 2.18)
+TCP_REPAIR_OPTIONS nil Options for repair mode (Linux 3.5, glibc 2.18)
+TCP_REPAIR_QUEUE nil Queue for repair mode (Linux 3.5, glibc 2.18)
+TCP_THIN_DUPACK nil Duplicated acknowledgments handling for thin-streams (Linux 2.6.34, glibc 2.18)
+TCP_THIN_LINEAR_TIMEOUTS nil Linear timeouts for thin-streams (Linux 2.6.34, glibc 2.18)
+TCP_TIMESTAMP nil TCP timestamp (Linux 3.9, glibc 2.18)
+TCP_USER_TIMEOUT nil Max timeout before a TCP connection is aborted (Linux 2.6.37, glibc 2.18)
+
+UDP_CORK nil Don't send partial frames (Linux 2.5.44, glibc 2.11)
+
+EAI_ADDRFAMILY nil Address family for hostname not supported
+EAI_AGAIN nil Temporary failure in name resolution
+EAI_BADFLAGS nil Invalid flags
+EAI_FAIL nil Non-recoverable failure in name resolution
+EAI_FAMILY nil Address family not supported
+EAI_MEMORY nil Memory allocation failure
+EAI_NODATA nil No address associated with hostname
+EAI_NONAME nil Hostname nor servname, or not known
+EAI_OVERFLOW nil Argument buffer overflow
+EAI_SERVICE nil Servname not supported for socket type
+EAI_SOCKTYPE nil Socket type not supported
+EAI_SYSTEM nil System error returned in errno
+EAI_BADHINTS nil Invalid value for hints
+EAI_PROTOCOL nil Resolved protocol is unknown
+EAI_MAX nil Maximum error code from getaddrinfo
+
+AI_PASSIVE nil Get address to use with bind()
+AI_CANONNAME nil Fill in the canonical name
+AI_NUMERICHOST nil Prevent host name resolution
+AI_NUMERICSERV nil Prevent service name resolution
+AI_MASK nil Valid flag mask for getaddrinfo (not for application use)
+AI_ALL nil Allow all addresses
+AI_V4MAPPED_CFG nil Accept IPv4 mapped addresses if the kernel supports it
+AI_ADDRCONFIG nil Accept only if any address is assigned
+AI_V4MAPPED nil Accept IPv4-mapped IPv6 addresses
+AI_DEFAULT nil Default flags for getaddrinfo
+
+NI_MAXHOST nil Maximum length of a hostname
+NI_MAXSERV nil Maximum length of a service name
+NI_NOFQDN nil An FQDN is not required for local hosts, return only the local part
+NI_NUMERICHOST nil Return a numeric address
+NI_NAMEREQD nil A name is required
+NI_NUMERICSERV nil Return the service name as a digit string
+NI_DGRAM nil The service specified is a datagram service (looks up UDP ports)
+
+SHUT_RD 0 Shut down the reading side of the socket
+SHUT_WR 1 Shut down the writing side of the socket
+SHUT_RDWR 2 Shut down the both sides of the socket
+
+IPV6_JOIN_GROUP nil Join a group membership
+IPV6_LEAVE_GROUP nil Leave a group membership
+IPV6_MTU_DISCOVER nil Path MTU discovery
+IPV6_MULTICAST_HOPS nil IP6 multicast hops
+IPV6_MULTICAST_IF nil IP6 multicast interface
+IPV6_MULTICAST_LOOP nil IP6 multicast loopback
+IPV6_UNICAST_HOPS nil IP6 unicast hops
+IPV6_V6ONLY nil Only bind IPv6 with a wildcard bind
+IPV6_CHECKSUM nil Checksum offset for raw sockets
+IPV6_DONTFRAG nil Don't fragment packets
+IPV6_DSTOPTS nil Destination option
+IPV6_HOPLIMIT nil Hop limit
+IPV6_HOPOPTS nil Hop-by-hop option
+IPV6_NEXTHOP nil Next hop address
+IPV6_PATHMTU nil Retrieve current path MTU
+IPV6_PKTINFO nil Receive packet information with datagram
+IPV6_RECVDSTOPTS nil Receive all IP6 options for response
+IPV6_RECVERR nil Enable extended reliable error message passing
+IPV6_RECVHOPLIMIT nil Receive hop limit with datagram
+IPV6_RECVHOPOPTS nil Receive hop-by-hop options
+IPV6_RECVPKTINFO nil Receive destination IP address and incoming interface
+IPV6_RECVRTHDR nil Receive routing header
+IPV6_RECVTCLASS nil Receive traffic class
+IPV6_RTHDR nil Allows removal of sticky routing headers
+IPV6_RTHDRDSTOPTS nil Allows removal of sticky destination options header
+IPV6_RTHDR_TYPE_0 nil Routing header type 0
+IPV6_RECVPATHMTU nil Receive current path MTU with datagram
+IPV6_TCLASS nil Specify the traffic class
+IPV6_USE_MIN_MTU nil Use the minimum MTU size
+
+INET_ADDRSTRLEN 16 Maximum length of an IPv4 address string
+INET6_ADDRSTRLEN 46 Maximum length of an IPv6 address string
+IFNAMSIZ nil Maximum interface name size
+IF_NAMESIZE nil Maximum interface name size
+
+SOMAXCONN 5 Maximum connection requests that may be queued for a socket
+
+SCM_RIGHTS nil Access rights
+SCM_TIMESTAMP nil Timestamp (timeval)
+SCM_TIMESTAMPNS nil Timespec (timespec)
+SCM_TIMESTAMPING nil Timestamp (timespec list) (Linux 2.6.30)
+SCM_BINTIME nil Timestamp (bintime)
+SCM_CREDENTIALS nil The sender's credentials
+SCM_CREDS nil Process credentials
+SCM_UCRED nil User credentials
+SCM_WIFI_STATUS nil Wifi status (Linux 3.3)
+
+LOCAL_PEERCRED nil Retrieve peer credentials
+LOCAL_CREDS nil Pass credentials to receiver
+LOCAL_CONNWAIT nil Connect blocks until accepted
+
+IFF_802_1Q_VLAN nil 802.1Q VLAN device
+IFF_ALLMULTI nil receive all multicast packets
+IFF_ALTPHYS nil use alternate physical connection
+IFF_AUTOMEDIA nil auto media select active
+IFF_BONDING nil bonding master or slave
+IFF_BRIDGE_PORT nil device used as bridge port
+IFF_BROADCAST nil broadcast address valid
+IFF_CANTCONFIG nil unconfigurable using ioctl(2)
+IFF_DEBUG nil turn on debugging
+IFF_DISABLE_NETPOLL nil disable netpoll at run-time
+IFF_DONT_BRIDGE nil disallow bridging this ether dev
+IFF_DORMANT nil driver signals dormant
+IFF_DRV_OACTIVE nil tx hardware queue is full
+IFF_DRV_RUNNING nil resources allocated
+IFF_DYING nil interface is winding down
+IFF_DYNAMIC nil dialup device with changing addresses
+IFF_EBRIDGE nil ethernet bridging device
+IFF_ECHO nil echo sent packets
+IFF_ISATAP nil ISATAP interface (RFC4214)
+IFF_LINK0 nil per link layer defined bit 0
+IFF_LINK1 nil per link layer defined bit 1
+IFF_LINK2 nil per link layer defined bit 2
+IFF_LIVE_ADDR_CHANGE nil hardware address change when it's running
+IFF_LOOPBACK nil loopback net
+IFF_LOWER_UP nil driver signals L1 up
+IFF_MACVLAN_PORT nil device used as macvlan port
+IFF_MASTER nil master of a load balancer
+IFF_MASTER_8023AD nil bonding master, 802.3ad.
+IFF_MASTER_ALB nil bonding master, balance-alb.
+IFF_MASTER_ARPMON nil bonding master, ARP mon in use
+IFF_MONITOR nil user-requested monitor mode
+IFF_MULTICAST nil supports multicast
+IFF_NOARP nil no address resolution protocol
+IFF_NOTRAILERS nil avoid use of trailers
+IFF_OACTIVE nil transmission in progress
+IFF_OVS_DATAPATH nil device used as Open vSwitch datapath port
+IFF_POINTOPOINT nil point-to-point link
+IFF_PORTSEL nil can set media type
+IFF_PPROMISC nil user-requested promisc mode
+IFF_PROMISC nil receive all packets
+IFF_RENAMING nil interface is being renamed
+IFF_ROUTE nil routing entry installed
+IFF_RUNNING nil resources allocated
+IFF_SIMPLEX nil can't hear own transmissions
+IFF_SLAVE nil slave of a load balancer
+IFF_SLAVE_INACTIVE nil bonding slave not the curr. active
+IFF_SLAVE_NEEDARP nil need ARPs for validation
+IFF_SMART nil interface manages own routes
+IFF_STATICARP nil static ARP
+IFF_SUPP_NOFCS nil sending custom FCS
+IFF_TEAM_PORT nil used as team port
+IFF_TX_SKB_SHARING nil sharing skbs on transmit
+IFF_UNICAST_FLT nil unicast filtering
+IFF_UP nil interface is up
+IFF_WAN_HDLC nil WAN HDLC device
+IFF_XMIT_DST_RELEASE nil dev_hard_start_xmit() is allowed to release skb->dst
+IFF_VOLATILE nil volatile flags
+IFF_CANTCHANGE nil flags not changeable
diff --git a/ext/socket/option.c b/ext/socket/option.c
new file mode 100644
index 0000000000..0d818d0c70
--- /dev/null
+++ b/ext/socket/option.c
@@ -0,0 +1,1477 @@
+#include "rubysocket.h"
+
+VALUE rb_cSockOpt;
+
+#define pack_var(v) rb_str_new((const char *)&(v), sizeof(v))
+
+#define CAT(x,y) x##y
+#define XCAT(x,y) CAT(x,y)
+
+#if defined(__linux__) || \
+ defined(__GNU__) /* GNU/Hurd */ || \
+ defined(__FreeBSD__) || \
+ defined(__DragonFly__) || \
+ defined(__APPLE__) || \
+ defined(_WIN32) || \
+ defined(__CYGWIN__)
+# define TYPE_IP_MULTICAST_LOOP int
+# define TYPE_IP_MULTICAST_TTL int
+#else
+/* The original IP multicast implementation by Steve Deering
+ * NetBSD
+ * OpenBSD
+ * SunOS
+ */
+# define TYPE_IP_MULTICAST_LOOP byte
+# define TYPE_IP_MULTICAST_TTL byte
+# define USE_INSPECT_BYTE 1
+#endif
+
+#define check_size(len, size) \
+ ((len) == (size) ? \
+ (void)0 : \
+ rb_raise(rb_eTypeError, "size differ. expected as "#size"=%d but %ld", \
+ (int)size, (long)(len)))
+
+static VALUE
+sockopt_pack_byte(VALUE value)
+{
+ char i = NUM2CHR(rb_to_int(value));
+ return pack_var(i);
+}
+
+static VALUE
+sockopt_pack_int(VALUE value)
+{
+ int i = NUM2INT(rb_to_int(value));
+ return pack_var(i);
+}
+
+static VALUE
+constant_to_sym(int constant, ID (*intern_const)(int))
+{
+ ID name = intern_const(constant);
+ if (name) {
+ return ID2SYM(name);
+ }
+
+ return INT2NUM(constant);
+}
+
+static VALUE
+optname_to_sym(int level, int optname)
+{
+ switch (level) {
+ case SOL_SOCKET:
+ return constant_to_sym(optname, rsock_intern_so_optname);
+ case IPPROTO_IP:
+ return constant_to_sym(optname, rsock_intern_ip_optname);
+#ifdef IPPROTO_IPV6
+ case IPPROTO_IPV6:
+ return constant_to_sym(optname, rsock_intern_ipv6_optname);
+#endif
+ case IPPROTO_TCP:
+ return constant_to_sym(optname, rsock_intern_tcp_optname);
+ case IPPROTO_UDP:
+ return constant_to_sym(optname, rsock_intern_udp_optname);
+ default:
+ return INT2NUM(optname);
+ }
+}
+
+/*
+ * call-seq:
+ * Socket::Option.new(family, level, optname, data) => sockopt
+ *
+ * Returns a new Socket::Option object.
+ *
+ * sockopt = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i"))
+ * p sockopt #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
+ *
+ */
+static VALUE
+sockopt_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE data)
+{
+ int family = rsock_family_arg(vfamily);
+ int level = rsock_level_arg(family, vlevel);
+ int optname = rsock_optname_arg(family, level, voptname);
+ StringValue(data);
+ rb_ivar_set(self, rb_intern("family"), INT2NUM(family));
+ rb_ivar_set(self, rb_intern("level"), INT2NUM(level));
+ rb_ivar_set(self, rb_intern("optname"), INT2NUM(optname));
+ rb_ivar_set(self, rb_intern("data"), data);
+ return self;
+}
+
+VALUE
+rsock_sockopt_new(int family, int level, int optname, VALUE data)
+{
+ VALUE obj = rb_obj_alloc(rb_cSockOpt);
+ StringValue(data);
+ sockopt_initialize(obj, INT2NUM(family), INT2NUM(level), INT2NUM(optname), data);
+ return (VALUE)obj;
+}
+
+/*
+ * call-seq:
+ * sockopt.family => integer
+ *
+ * returns the socket family as an integer.
+ *
+ * p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).family
+ * #=> 10
+ */
+static VALUE
+sockopt_family_m(VALUE self)
+{
+ return rb_attr_get(self, rb_intern("family"));
+}
+
+static int
+sockopt_level(VALUE self)
+{
+ return NUM2INT(rb_attr_get(self, rb_intern("level")));
+}
+
+/*
+ * call-seq:
+ * sockopt.level => integer
+ *
+ * returns the socket level as an integer.
+ *
+ * p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).level
+ * #=> 41
+ */
+static VALUE
+sockopt_level_m(VALUE self)
+{
+ return INT2NUM(sockopt_level(self));
+}
+
+static int
+sockopt_optname(VALUE self)
+{
+ return NUM2INT(rb_attr_get(self, rb_intern("optname")));
+}
+
+/*
+ * call-seq:
+ * sockopt.optname => integer
+ *
+ * returns the socket option name as an integer.
+ *
+ * p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).optname
+ * #=> 2
+ */
+static VALUE
+sockopt_optname_m(VALUE self)
+{
+ return INT2NUM(sockopt_optname(self));
+}
+
+/*
+ * call-seq:
+ * sockopt.data => string
+ * sockopt.to_s => string
+ *
+ * returns the socket option data as a string.
+ *
+ * p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).data
+ * #=> "\x01\x00\x00\x00"
+ */
+static VALUE
+sockopt_data(VALUE self)
+{
+ VALUE v = rb_attr_get(self, rb_intern("data"));
+ StringValue(v);
+ return v;
+}
+
+/*
+ * call-seq:
+ * Socket::Option.byte(family, level, optname, integer) => sockopt
+ *
+ * Creates a new Socket::Option object which contains a byte as data.
+ *
+ * p Socket::Option.byte(:INET, :SOCKET, :KEEPALIVE, 1)
+ * #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
+ */
+static VALUE
+sockopt_s_byte(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vint)
+{
+ int family = rsock_family_arg(vfamily);
+ int level = rsock_level_arg(family, vlevel);
+ int optname = rsock_optname_arg(family, level, voptname);
+ return rsock_sockopt_new(family, level, optname, sockopt_pack_byte(vint));
+}
+
+/*
+ * call-seq:
+ * sockopt.byte => integer
+ *
+ * Returns the data in _sockopt_ as an byte.
+ *
+ * sockopt = Socket::Option.byte(:INET, :SOCKET, :KEEPALIVE, 1)
+ * p sockopt.byte => 1
+ */
+static VALUE
+sockopt_byte(VALUE self)
+{
+ VALUE data = sockopt_data(self);
+ StringValue(data);
+ check_size(RSTRING_LEN(data), sizeof(char));
+ return CHR2FIX(*RSTRING_PTR(data));
+}
+
+/*
+ * call-seq:
+ * Socket::Option.int(family, level, optname, integer) => sockopt
+ *
+ * Creates a new Socket::Option object which contains an int as data.
+ *
+ * The size and endian is dependent on the platform.
+ *
+ * p Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
+ * #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
+ */
+static VALUE
+sockopt_s_int(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vint)
+{
+ int family = rsock_family_arg(vfamily);
+ int level = rsock_level_arg(family, vlevel);
+ int optname = rsock_optname_arg(family, level, voptname);
+ return rsock_sockopt_new(family, level, optname, sockopt_pack_int(vint));
+}
+
+/*
+ * call-seq:
+ * sockopt.int => integer
+ *
+ * Returns the data in _sockopt_ as an int.
+ *
+ * The size and endian is dependent on the platform.
+ *
+ * sockopt = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
+ * p sockopt.int => 1
+ */
+static VALUE
+sockopt_int(VALUE self)
+{
+ int i;
+ VALUE data = sockopt_data(self);
+ StringValue(data);
+ check_size(RSTRING_LEN(data), sizeof(int));
+ memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
+ return INT2NUM(i);
+}
+
+/*
+ * call-seq:
+ * Socket::Option.bool(family, level, optname, bool) => sockopt
+ *
+ * Creates a new Socket::Option object which contains boolean as data.
+ * Actually 0 or 1 as int is used.
+ *
+ * require 'socket'
+ *
+ * p Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true)
+ * #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
+ *
+ * p Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, false)
+ * #=> #<Socket::Option: AF_INET SOCKET KEEPALIVE 0>
+ *
+ */
+static VALUE
+sockopt_s_bool(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vbool)
+{
+ int family = rsock_family_arg(vfamily);
+ int level = rsock_level_arg(family, vlevel);
+ int optname = rsock_optname_arg(family, level, voptname);
+ int i = RTEST(vbool) ? 1 : 0;
+ return rsock_sockopt_new(family, level, optname, pack_var(i));
+}
+
+/*
+ * call-seq:
+ * sockopt.bool => true or false
+ *
+ * Returns the data in _sockopt_ as an boolean value.
+ *
+ * sockopt = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
+ * p sockopt.bool => true
+ */
+static VALUE
+sockopt_bool(VALUE self)
+{
+ int i;
+ long len;
+ VALUE data = sockopt_data(self);
+ StringValue(data);
+ len = RSTRING_LEN(data);
+ if (len == 1) {
+ return *RSTRING_PTR(data) == 0 ? Qfalse : Qtrue;
+ }
+ check_size(len, sizeof(int));
+ memcpy((char*)&i, RSTRING_PTR(data), len);
+ return i == 0 ? Qfalse : Qtrue;
+}
+
+/*
+ * call-seq:
+ * Socket::Option.linger(onoff, secs) => sockopt
+ *
+ * Creates a new Socket::Option object for SOL_SOCKET/SO_LINGER.
+ *
+ * _onoff_ should be an integer or a boolean.
+ *
+ * _secs_ should be the number of seconds.
+ *
+ * p Socket::Option.linger(true, 10)
+ * #=> #<Socket::Option: UNSPEC SOCKET LINGER on 10sec>
+ *
+ */
+static VALUE
+sockopt_s_linger(VALUE klass, VALUE vonoff, VALUE vsecs)
+{
+ VALUE tmp;
+ struct linger l;
+ memset(&l, 0, sizeof(l));
+ if (!NIL_P(tmp = rb_check_to_integer(vonoff, "to_int")))
+ l.l_onoff = NUM2INT(tmp);
+ else
+ l.l_onoff = RTEST(vonoff) ? 1 : 0;
+ l.l_linger = NUM2INT(vsecs);
+ return rsock_sockopt_new(AF_UNSPEC, SOL_SOCKET, SO_LINGER, pack_var(l));
+}
+
+/*
+ * call-seq:
+ * sockopt.linger => [bool, seconds]
+ *
+ * Returns the linger data in _sockopt_ as a pair of boolean and integer.
+ *
+ * sockopt = Socket::Option.linger(true, 10)
+ * p sockopt.linger => [true, 10]
+ */
+static VALUE
+sockopt_linger(VALUE self)
+{
+ int level = sockopt_level(self);
+ int optname = sockopt_optname(self);
+ VALUE data = sockopt_data(self);
+ struct linger l;
+ VALUE vonoff, vsecs;
+
+ if (level != SOL_SOCKET || optname != SO_LINGER)
+ rb_raise(rb_eTypeError, "linger socket option expected");
+ check_size(RSTRING_LEN(data), sizeof(struct linger));
+ memcpy((char*)&l, RSTRING_PTR(data), sizeof(struct linger));
+ switch (l.l_onoff) {
+ case 0: vonoff = Qfalse; break;
+ case 1: vonoff = Qtrue; break;
+ default: vonoff = INT2NUM(l.l_onoff); break;
+ }
+ vsecs = INT2NUM(l.l_linger);
+ return rb_assoc_new(vonoff, vsecs);
+}
+
+/*
+ * call-seq:
+ * Socket::Option.ipv4_multicast_loop(integer) => sockopt
+ *
+ * Creates a new Socket::Option object for IP_MULTICAST_LOOP.
+ *
+ * The size is dependent on the platform.
+ *
+ * sockopt = Socket::Option.int(:INET, :IPPROTO_IP, :IP_MULTICAST_LOOP, 1)
+ * p sockopt.int => 1
+ *
+ * p Socket::Option.ipv4_multicast_loop(10)
+ * #=> #<Socket::Option: INET IP MULTICAST_LOOP 10>
+ *
+ */
+static VALUE
+sockopt_s_ipv4_multicast_loop(VALUE klass, VALUE value)
+{
+
+#if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP)
+ VALUE o = XCAT(sockopt_pack_,TYPE_IP_MULTICAST_LOOP)(value);
+ return rsock_sockopt_new(AF_INET, IPPROTO_IP, IP_MULTICAST_LOOP, o);
+#else
+# error IPPROTO_IP or IP_MULTICAST_LOOP is not implemented
+#endif
+}
+
+/*
+ * call-seq:
+ * sockopt.ipv4_multicast_loop => integer
+ *
+ * Returns the ipv4_multicast_loop data in _sockopt_ as an integer.
+ *
+ * sockopt = Socket::Option.ipv4_multicast_loop(10)
+ * p sockopt.ipv4_multicast_loop => 10
+ */
+static VALUE
+sockopt_ipv4_multicast_loop(VALUE self)
+{
+ int family = NUM2INT(sockopt_family_m(self));
+ int level = sockopt_level(self);
+ int optname = sockopt_optname(self);
+
+#if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP)
+ if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_LOOP) {
+ return XCAT(sockopt_,TYPE_IP_MULTICAST_LOOP)(self);
+ }
+#endif
+ rb_raise(rb_eTypeError, "ipv4_multicast_loop socket option expected");
+ UNREACHABLE_RETURN(Qnil);
+}
+
+#define inspect_ipv4_multicast_loop(a,b,c,d) \
+ XCAT(inspect_,TYPE_IP_MULTICAST_LOOP)(a,b,c,d)
+
+/*
+ * call-seq:
+ * Socket::Option.ipv4_multicast_ttl(integer) => sockopt
+ *
+ * Creates a new Socket::Option object for IP_MULTICAST_TTL.
+ *
+ * The size is dependent on the platform.
+ *
+ * p Socket::Option.ipv4_multicast_ttl(10)
+ * #=> #<Socket::Option: INET IP MULTICAST_TTL 10>
+ *
+ */
+static VALUE
+sockopt_s_ipv4_multicast_ttl(VALUE klass, VALUE value)
+{
+#if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
+ VALUE o = XCAT(sockopt_pack_,TYPE_IP_MULTICAST_TTL)(value);
+ return rsock_sockopt_new(AF_INET, IPPROTO_IP, IP_MULTICAST_TTL, o);
+#else
+# error IPPROTO_IP or IP_MULTICAST_TTL is not implemented
+#endif
+}
+
+/*
+ * call-seq:
+ * sockopt.ipv4_multicast_ttl => integer
+ *
+ * Returns the ipv4_multicast_ttl data in _sockopt_ as an integer.
+ *
+ * sockopt = Socket::Option.ipv4_multicast_ttl(10)
+ * p sockopt.ipv4_multicast_ttl => 10
+ */
+static VALUE
+sockopt_ipv4_multicast_ttl(VALUE self)
+{
+ int family = NUM2INT(sockopt_family_m(self));
+ int level = sockopt_level(self);
+ int optname = sockopt_optname(self);
+
+#if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
+ if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_TTL) {
+ return XCAT(sockopt_,TYPE_IP_MULTICAST_TTL)(self);
+ }
+#endif
+ rb_raise(rb_eTypeError, "ipv4_multicast_ttl socket option expected");
+ UNREACHABLE_RETURN(Qnil);
+}
+
+#define inspect_ipv4_multicast_ttl(a,b,c,d) \
+ XCAT(inspect_,TYPE_IP_MULTICAST_TTL)(a,b,c,d)
+
+static int
+inspect_int(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(int)) {
+ int i;
+ memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
+ rb_str_catf(ret, " %d", i);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+#ifdef USE_INSPECT_BYTE
+static int
+inspect_byte(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(unsigned char)) {
+ rb_str_catf(ret, " %d", (unsigned char)*RSTRING_PTR(data));
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+static int
+inspect_errno(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(int)) {
+ int i;
+ char *err;
+ memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
+ err = strerror(i);
+ rb_str_catf(ret, " %s (%d)", err, i);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+#if defined(IPV6_MULTICAST_LOOP)
+static int
+inspect_uint(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(int)) {
+ unsigned int i;
+ memcpy((char*)&i, RSTRING_PTR(data), sizeof(unsigned int));
+ rb_str_catf(ret, " %u", i);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(SOL_SOCKET) && defined(SO_LINGER) /* POSIX */
+static int
+inspect_linger(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(struct linger)) {
+ struct linger s;
+ memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
+ switch (s.l_onoff) {
+ case 0: rb_str_cat2(ret, " off"); break;
+ case 1: rb_str_cat2(ret, " on"); break;
+ default: rb_str_catf(ret, " on(%d)", s.l_onoff); break;
+ }
+ rb_str_catf(ret, " %dsec", s.l_linger);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(SOL_SOCKET) && defined(SO_TYPE) /* POSIX */
+static int
+inspect_socktype(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(int)) {
+ int i;
+ ID id;
+ memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
+ id = rsock_intern_socktype(i);
+ if (id)
+ rb_str_catf(ret, " %s", rb_id2name(id));
+ else
+ rb_str_catf(ret, " %d", i);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+static int
+inspect_timeval_as_interval(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(struct timeval)) {
+ struct timeval s;
+ memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
+ rb_str_catf(ret, " %ld.%06ldsec", (long)s.tv_sec, (long)s.tv_usec);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+/*
+ * socket option for IPv4 multicast is bit confusing.
+ *
+ * IP Multicast is implemented by Steve Deering at first:
+ * IP Multicast Extensions for 4.3BSD UNIX and related systems
+ * (MULTICAST 1.2 Release)
+ * http://www.kohala.com/start/mcast.api.txt
+ *
+ * There are 2 socket options which takes a u_char (unsigned char).
+ *
+ * IP_MULTICAST_TTL
+ * IP_MULTICAST_LOOP
+ *
+ * However Linux and FreeBSD setsockname accepts int argument
+ * as well as u_char.
+ * Their getsockname returns int.
+ *
+ * There are 3 socket options which takes a struct.
+ *
+ * IP_MULTICAST_IF: struct in_addr
+ * IP_ADD_MEMBERSHIP: struct ip_mreq
+ * IP_DROP_MEMBERSHIP: struct ip_mreq
+ *
+ * But they uses an IP address to specify an interface.
+ * This means the API cannot specify an unnumbered interface.
+ *
+ * Linux 2.4 introduces struct ip_mreqn to fix this problem.
+ * struct ip_mreqn has imr_ifindex field to specify interface index.
+ *
+ * IP_MULTICAST_IF: struct ip_mreqn
+ * IP_ADD_MEMBERSHIP: struct ip_mreqn
+ * IP_DROP_MEMBERSHIP: struct ip_mreqn
+ *
+ * FreeBSD 7 obtained struct ip_mreqn for IP_MULTICAST_IF.
+ * http://www.FreeBSD.org/cgi/cvsweb.cgi/src/sys/netinet/in.h.diff?r1=1.99;r2=1.100
+ *
+ * Another hackish workaround is "RFC 1724 hack".
+ * RFC 1724 section 3.3 suggests unnumbered interfaces
+ * specified by pseudo address 0.0.0.0/8.
+ * NetBSD 4 and FreeBSD 5 documented it.
+ * http://cvsweb.netbsd.org/cgi-bin/cvsweb.cgi/src/share/man/man4/ip.4.diff?r1=1.16&r2=1.17
+ * http://www.FreeBSD.org/cgi/cvsweb.cgi/src/share/man/man4/ip.4.diff?r1=1.37;r2=1.38
+ * FreeBSD 7.0 removed it.
+ * http://www.FreeBSD.org/cgi/cvsweb.cgi/src/share/man/man4/ip.4.diff?r1=1.49;r2=1.50
+ *
+ * RFC 1724 hack is not supported by Socket::Option#inspect because
+ * it is not distinguishable by the size.
+ */
+
+#if !defined HAVE_INET_NTOP && ! defined _WIN32
+const char *
+inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
+{
+#ifdef HAVE_INET_NTOA
+ struct in_addr in;
+ memcpy(&in.s_addr, addr, sizeof(in.s_addr));
+ snprintf(numaddr, numaddr_len, "%s", inet_ntoa(in));
+#else
+ unsigned long x = ntohl(*(unsigned long*)addr);
+ snprintf(numaddr, numaddr_len, "%d.%d.%d.%d",
+ (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
+ (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
+#endif
+ return numaddr;
+}
+#endif
+
+/* Although the buffer size needed depends on the prefixes, "%u" may generate "4294967295". */
+static int
+rb_if_indextoname(const char *succ_prefix, const char *fail_prefix, unsigned int ifindex, char *buf, size_t len)
+{
+#if defined(HAVE_IF_INDEXTONAME)
+ char ifbuf[IFNAMSIZ];
+ if (if_indextoname(ifindex, ifbuf))
+ return snprintf(buf, len, "%s%s", succ_prefix, ifbuf);
+ else
+ return snprintf(buf, len, "%s%u", fail_prefix, ifindex);
+#else
+# ifndef IFNAMSIZ
+# define IFNAMSIZ (sizeof(unsigned int)*3+1)
+# endif
+ return snprintf(buf, len, "%s%u", fail_prefix, ifindex);
+#endif
+}
+
+#if defined(IPPROTO_IP) && defined(HAVE_TYPE_STRUCT_IP_MREQ) /* 4.4BSD, GNU/Linux */
+static int
+inspect_ipv4_mreq(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(struct ip_mreq)) {
+ struct ip_mreq s;
+ char addrbuf[INET_ADDRSTRLEN];
+ memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
+ if (inet_ntop(AF_INET, &s.imr_multiaddr, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
+ rb_str_cat2(ret, " invalid-address");
+ else
+ rb_str_catf(ret, " %s", addrbuf);
+ if (inet_ntop(AF_INET, &s.imr_interface, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
+ rb_str_catf(ret, " invalid-address");
+ else
+ rb_str_catf(ret, " %s", addrbuf);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(IPPROTO_IP) && defined(HAVE_TYPE_STRUCT_IP_MREQN) /* GNU/Linux, FreeBSD 7 */
+static int
+inspect_ipv4_mreqn(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(struct ip_mreqn)) {
+ struct ip_mreqn s;
+ char addrbuf[INET_ADDRSTRLEN], ifbuf[32+IFNAMSIZ];
+ memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
+ if (inet_ntop(AF_INET, &s.imr_multiaddr, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
+ rb_str_cat2(ret, " invalid-address");
+ else
+ rb_str_catf(ret, " %s", addrbuf);
+ if (inet_ntop(AF_INET, &s.imr_address, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
+ rb_str_catf(ret, " invalid-address");
+ else
+ rb_str_catf(ret, " %s", addrbuf);
+ rb_if_indextoname(" ", " ifindex:", s.imr_ifindex, ifbuf, sizeof(ifbuf));
+ rb_str_cat2(ret, ifbuf);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(IPPROTO_IP) && defined(HAVE_TYPE_STRUCT_IP_MREQ) /* 4.4BSD, GNU/Linux */
+static int
+inspect_ipv4_add_drop_membership(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(struct ip_mreq))
+ return inspect_ipv4_mreq(level, optname, data, ret);
+# if defined(HAVE_TYPE_STRUCT_IP_MREQN)
+ else if (RSTRING_LEN(data) == sizeof(struct ip_mreqn))
+ return inspect_ipv4_mreqn(level, optname, data, ret);
+# endif
+ else
+ return 0;
+}
+#endif
+
+#if defined(IPPROTO_IP) && defined(IP_MULTICAST_IF) && defined(HAVE_TYPE_STRUCT_IP_MREQN) /* 4.4BSD, GNU/Linux */
+static int
+inspect_ipv4_multicast_if(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(struct in_addr)) {
+ struct in_addr s;
+ char addrbuf[INET_ADDRSTRLEN];
+ memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
+ if (inet_ntop(AF_INET, &s, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
+ rb_str_cat2(ret, " invalid-address");
+ else
+ rb_str_catf(ret, " %s", addrbuf);
+ return 1;
+ }
+ else if (RSTRING_LEN(data) == sizeof(struct ip_mreqn)) {
+ return inspect_ipv4_mreqn(level, optname, data, ret);
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(IPV6_MULTICAST_IF) /* POSIX, RFC 3493 */
+static int
+inspect_ipv6_multicast_if(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(int)) {
+ char ifbuf[32+IFNAMSIZ];
+ unsigned int ifindex;
+ memcpy((char*)&ifindex, RSTRING_PTR(data), sizeof(unsigned int));
+ rb_if_indextoname(" ", " ", ifindex, ifbuf, sizeof(ifbuf));
+ rb_str_cat2(ret, ifbuf);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(IPPROTO_IPV6) && defined(HAVE_TYPE_STRUCT_IPV6_MREQ) /* POSIX, RFC 3493 */
+static int
+inspect_ipv6_mreq(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(struct ipv6_mreq)) {
+ struct ipv6_mreq s;
+ char addrbuf[INET6_ADDRSTRLEN], ifbuf[32+IFNAMSIZ];
+ memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
+ if (inet_ntop(AF_INET6, &s.ipv6mr_multiaddr, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
+ rb_str_cat2(ret, " invalid-address");
+ else
+ rb_str_catf(ret, " %s", addrbuf);
+ rb_if_indextoname(" ", " interface:", s.ipv6mr_interface, ifbuf, sizeof(ifbuf));
+ rb_str_cat2(ret, ifbuf);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(IPPROTO_TCP) && defined(TCP_INFO) && defined(HAVE_TYPE_STRUCT_TCP_INFO)
+
+#ifdef __FreeBSD__
+# ifndef HAVE_CONST_TCP_ESTABLISHED
+# define TCP_ESTABLISHED TCPS_ESTABLISHED
+# endif
+# ifndef HAVE_CONST_TCP_SYN_SENT
+# define TCP_SYN_SENT TCPS_SYN_SENT
+# endif
+# ifndef HAVE_CONST_TCP_SYN_RECV
+# define TCP_SYN_RECV TCPS_SYN_RECEIVED
+# endif
+# ifndef HAVE_CONST_TCP_FIN_WAIT1
+# define TCP_FIN_WAIT1 TCPS_FIN_WAIT_1
+# endif
+# ifndef HAVE_CONST_TCP_FIN_WAIT2
+# define TCP_FIN_WAIT2 TCPS_FIN_WAIT_2
+# endif
+# ifndef HAVE_CONST_TCP_TIME_WAIT
+# define TCP_TIME_WAIT TCPS_TIME_WAIT
+# endif
+# ifndef HAVE_CONST_TCP_CLOSE
+# define TCP_CLOSE TCPS_CLOSED
+# endif
+# ifndef HAVE_CONST_TCP_CLOSE_WAIT
+# define TCP_CLOSE_WAIT TCPS_CLOSE_WAIT
+# endif
+# ifndef HAVE_CONST_TCP_LAST_ACK
+# define TCP_LAST_ACK TCPS_LAST_ACK
+# endif
+# ifndef HAVE_CONST_TCP_LISTEN
+# define TCP_LISTEN TCPS_LISTEN
+# endif
+# ifndef HAVE_CONST_TCP_CLOSING
+# define TCP_CLOSING TCPS_CLOSING
+# endif
+#endif
+
+#if defined(HAVE_CONST_TCP_ESTABLISHED) && !defined(TCP_ESTABLISHED)
+# define TCP_ESTABLISHED TCP_ESTABLISHED
+#endif
+#if defined(HAVE_CONST_TCP_SYN_SENT) && !defined(TCP_SYN_SENT)
+# define TCP_SYN_SENT TCP_SYN_SENT
+#endif
+#if defined(HAVE_CONST_TCP_SYN_RECV) && !defined(TCP_SYN_RECV)
+# define TCP_SYN_RECV TCP_SYN_RECV
+#endif
+#if defined(HAVE_CONST_TCP_FIN_WAIT1) && !defined(TCP_FIN_WAIT1)
+# define TCP_FIN_WAIT1 TCP_FIN_WAIT1
+#endif
+#if defined(HAVE_CONST_TCP_FIN_WAIT2) && !defined(TCP_FIN_WAIT2)
+# define TCP_FIN_WAIT2 TCP_FIN_WAIT2
+#endif
+#if defined(HAVE_CONST_TCP_TIME_WAIT) && !defined(TCP_TIME_WAIT)
+# define TCP_TIME_WAIT TCP_TIME_WAIT
+#endif
+#if defined(HAVE_CONST_TCP_CLOSE) && !defined(TCP_CLOSE)
+# define TCP_CLOSE TCP_CLOSE
+#endif
+#if defined(HAVE_CONST_TCP_CLOSE_WAIT) && !defined(TCP_CLOSE_WAIT)
+# define TCP_CLOSE_WAIT TCP_CLOSE_WAIT
+#endif
+#if defined(HAVE_CONST_TCP_LAST_ACK) && !defined(TCP_LAST_ACK)
+# define TCP_LAST_ACK TCP_LAST_ACK
+#endif
+#if defined(HAVE_CONST_TCP_LISTEN) && !defined(TCP_LISTEN)
+# define TCP_LISTEN TCP_LISTEN
+#endif
+#if defined(HAVE_CONST_TCP_CLOSING) && !defined(TCP_CLOSING)
+# define TCP_CLOSING TCP_CLOSING
+#endif
+
+static void
+inspect_tcpi_options(VALUE ret, uint8_t options)
+{
+ int sep = '=';
+
+ rb_str_cat2(ret, " options");
+#define INSPECT_TCPI_OPTION(optval, name) \
+ if (options & (optval)) { \
+ options &= ~(uint8_t)(optval); \
+ rb_str_catf(ret, "%c%s", sep, name); \
+ sep = ','; \
+ }
+#ifdef TCPI_OPT_TIMESTAMPS /* GNU/Linux, FreeBSD */
+ INSPECT_TCPI_OPTION(TCPI_OPT_TIMESTAMPS, "TIMESTAMPS");
+#endif
+#ifdef TCPI_OPT_SACK /* GNU/Linux, FreeBSD */
+ INSPECT_TCPI_OPTION(TCPI_OPT_SACK, "SACK");
+#endif
+#ifdef TCPI_OPT_WSCALE /* GNU/Linux, FreeBSD */
+ INSPECT_TCPI_OPTION(TCPI_OPT_WSCALE, "WSCALE");
+#endif
+#ifdef TCPI_OPT_ECN /* GNU/Linux, FreeBSD */
+ INSPECT_TCPI_OPTION(TCPI_OPT_ECN, "ECN");
+#endif
+#ifdef TCPI_OPT_ECN_SEEN /* GNU/Linux */
+ INSPECT_TCPI_OPTION(TCPI_OPT_ECN_SEEN, "ECN_SEEN");
+#endif
+#ifdef TCPI_OPT_SYN_DATA /* GNU/Linux */
+ INSPECT_TCPI_OPTION(TCPI_OPT_SYN_DATA, "SYN_DATA");
+#endif
+#ifdef TCPI_OPT_TOE /* FreeBSD */
+ INSPECT_TCPI_OPTION(TCPI_OPT_TOE, "TOE");
+#endif
+#undef INSPECT_TCPI_OPTION
+
+ if (options || sep == '=') {
+ rb_str_catf(ret, "%c%u", sep, options);
+ }
+}
+
+static void
+inspect_tcpi_usec(VALUE ret, const char *prefix, uint32_t t)
+{
+ rb_str_catf(ret, "%s%u.%06us", prefix, t / 1000000, t % 1000000);
+}
+
+#if !defined __FreeBSD__ && ( \
+ defined HAVE_STRUCT_TCP_INFO_TCPI_LAST_DATA_SENT || \
+ defined HAVE_STRUCT_TCP_INFO_TCPI_LAST_DATA_RECV || \
+ defined HAVE_STRUCT_TCP_INFO_TCPI_LAST_ACK_SENT || \
+ defined HAVE_STRUCT_TCP_INFO_TCPI_LAST_ACK_RECV || \
+ 0)
+static void
+inspect_tcpi_msec(VALUE ret, const char *prefix, uint32_t t)
+{
+ rb_str_catf(ret, "%s%u.%03us", prefix, t / 1000, t % 1000);
+}
+#endif
+
+#ifdef __FreeBSD__
+# define inspect_tcpi_rto(ret, t) inspect_tcpi_usec(ret, " rto=", t)
+# define inspect_tcpi_last_data_recv(ret, t) inspect_tcpi_usec(ret, " last_data_recv=", t)
+# define inspect_tcpi_rtt(ret, t) inspect_tcpi_usec(ret, " rtt=", t)
+# define inspect_tcpi_rttvar(ret, t) inspect_tcpi_usec(ret, " rttvar=", t)
+#else
+# define inspect_tcpi_rto(ret, t) inspect_tcpi_usec(ret, " rto=", t)
+# define inspect_tcpi_ato(ret, t) inspect_tcpi_usec(ret, " ato=", t)
+# define inspect_tcpi_last_data_sent(ret, t) inspect_tcpi_msec(ret, " last_data_sent=", t)
+# define inspect_tcpi_last_data_recv(ret, t) inspect_tcpi_msec(ret, " last_data_recv=", t)
+# define inspect_tcpi_last_ack_sent(ret, t) inspect_tcpi_msec(ret, " last_ack_sent=", t)
+# define inspect_tcpi_last_ack_recv(ret, t) inspect_tcpi_msec(ret, " last_ack_recv=", t)
+# define inspect_tcpi_rtt(ret, t) inspect_tcpi_usec(ret, " rtt=", t)
+# define inspect_tcpi_rttvar(ret, t) inspect_tcpi_usec(ret, " rttvar=", t)
+# define inspect_tcpi_rcv_rtt(ret, t) inspect_tcpi_usec(ret, " rcv_rtt=", t)
+#endif
+
+static int
+inspect_tcp_info(int level, int optname, VALUE data, VALUE ret)
+{
+ size_t actual_size = RSTRING_LEN(data);
+ if (sizeof(struct tcp_info) <= actual_size) {
+ struct tcp_info s;
+ memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_STATE
+ switch (s.tcpi_state) {
+# ifdef TCP_ESTABLISHED
+ case TCP_ESTABLISHED: rb_str_cat_cstr(ret, " state=ESTABLISHED"); break;
+# endif
+# ifdef TCP_SYN_SENT
+ case TCP_SYN_SENT: rb_str_cat_cstr(ret, " state=SYN_SENT"); break;
+# endif
+# ifdef TCP_SYN_RECV
+ case TCP_SYN_RECV: rb_str_cat_cstr(ret, " state=SYN_RECV"); break;
+# endif
+# ifdef TCP_FIN_WAIT1
+ case TCP_FIN_WAIT1: rb_str_cat_cstr(ret, " state=FIN_WAIT1"); break;
+# endif
+# ifdef TCP_FIN_WAIT2
+ case TCP_FIN_WAIT2: rb_str_cat_cstr(ret, " state=FIN_WAIT2"); break;
+# endif
+# ifdef TCP_TIME_WAIT
+ case TCP_TIME_WAIT: rb_str_cat_cstr(ret, " state=TIME_WAIT"); break;
+# endif
+# ifdef TCP_CLOSE
+ case TCP_CLOSE: rb_str_cat_cstr(ret, " state=CLOSED"); break; /* RFC 793 uses "CLOSED", not "CLOSE" */
+# endif
+# ifdef TCP_CLOSE_WAIT
+ case TCP_CLOSE_WAIT: rb_str_cat_cstr(ret, " state=CLOSE_WAIT"); break;
+# endif
+# ifdef TCP_LAST_ACK
+ case TCP_LAST_ACK: rb_str_cat_cstr(ret, " state=LAST_ACK"); break;
+# endif
+# ifdef TCP_LISTEN
+ case TCP_LISTEN: rb_str_cat_cstr(ret, " state=LISTEN"); break;
+# endif
+# ifdef TCP_CLOSING
+ case TCP_CLOSING: rb_str_cat_cstr(ret, " state=CLOSING"); break;
+# endif
+ default: rb_str_catf(ret, " state=%u", s.tcpi_state); break;
+ }
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_CA_STATE
+ switch (s.tcpi_ca_state) {
+ case TCP_CA_Open: rb_str_cat_cstr(ret, " ca_state=Open"); break;
+ case TCP_CA_Disorder: rb_str_cat_cstr(ret, " ca_state=Disorder"); break;
+ case TCP_CA_CWR: rb_str_cat_cstr(ret, " ca_state=CWR"); break;
+ case TCP_CA_Recovery: rb_str_cat_cstr(ret, " ca_state=Recovery"); break;
+ case TCP_CA_Loss: rb_str_cat_cstr(ret, " ca_state=Loss"); break;
+ default: rb_str_catf(ret, " ca_state=%u", s.tcpi_ca_state); break;
+ }
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RETRANSMITS
+ rb_str_catf(ret, " retransmits=%u", s.tcpi_retransmits);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_PROBES
+ rb_str_catf(ret, " probes=%u", s.tcpi_probes);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_BACKOFF
+ rb_str_catf(ret, " backoff=%u", s.tcpi_backoff);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_OPTIONS
+ inspect_tcpi_options(ret, s.tcpi_options);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_SND_WSCALE
+ rb_str_catf(ret, " snd_wscale=%u", s.tcpi_snd_wscale);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RCV_WSCALE
+ rb_str_catf(ret, " rcv_wscale=%u", s.tcpi_rcv_wscale);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RTO
+ inspect_tcpi_rto(ret, s.tcpi_rto);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_ATO
+ inspect_tcpi_ato(ret, s.tcpi_ato);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_SND_MSS
+ rb_str_catf(ret, " snd_mss=%u", s.tcpi_snd_mss);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RCV_MSS
+ rb_str_catf(ret, " rcv_mss=%u", s.tcpi_rcv_mss);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_UNACKED
+ rb_str_catf(ret, " unacked=%u", s.tcpi_unacked);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_SACKED
+ rb_str_catf(ret, " sacked=%u", s.tcpi_sacked);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_LOST
+ rb_str_catf(ret, " lost=%u", s.tcpi_lost);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RETRANS
+ rb_str_catf(ret, " retrans=%u", s.tcpi_retrans);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_FACKETS
+ rb_str_catf(ret, " fackets=%u", s.tcpi_fackets);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_DATA_SENT
+ inspect_tcpi_last_data_sent(ret, s.tcpi_last_data_sent);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_ACK_SENT
+ inspect_tcpi_last_ack_sent(ret, s.tcpi_last_ack_sent);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_DATA_RECV
+ inspect_tcpi_last_data_recv(ret, s.tcpi_last_data_recv);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_ACK_RECV
+ inspect_tcpi_last_ack_recv(ret, s.tcpi_last_ack_recv);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_PMTU
+ rb_str_catf(ret, " pmtu=%u", s.tcpi_pmtu);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RCV_SSTHRESH
+ rb_str_catf(ret, " rcv_ssthresh=%u", s.tcpi_rcv_ssthresh);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RTT
+ inspect_tcpi_rtt(ret, s.tcpi_rtt);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RTTVAR
+ inspect_tcpi_rttvar(ret, s.tcpi_rttvar);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_SND_SSTHRESH
+ rb_str_catf(ret, " snd_ssthresh=%u", s.tcpi_snd_ssthresh);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_SND_CWND
+ rb_str_catf(ret, " snd_cwnd=%u", s.tcpi_snd_cwnd);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_ADVMSS
+ rb_str_catf(ret, " advmss=%u", s.tcpi_advmss);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_REORDERING
+ rb_str_catf(ret, " reordering=%u", s.tcpi_reordering);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RCV_RTT
+ inspect_tcpi_rcv_rtt(ret, s.tcpi_rcv_rtt);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RCV_SPACE
+ rb_str_catf(ret, " rcv_space=%u", s.tcpi_rcv_space);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_TOTAL_RETRANS
+ rb_str_catf(ret, " total_retrans=%u", s.tcpi_total_retrans);
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_SND_WND
+ rb_str_catf(ret, " snd_wnd=%u", s.tcpi_snd_wnd); /* FreeBSD */
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_SND_BWND
+ rb_str_catf(ret, " snd_bwnd=%u", s.tcpi_snd_bwnd); /* FreeBSD */
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_SND_NXT
+ rb_str_catf(ret, " snd_nxt=%u", s.tcpi_snd_nxt); /* FreeBSD */
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RCV_NXT
+ rb_str_catf(ret, " rcv_nxt=%u", s.tcpi_rcv_nxt); /* FreeBSD */
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_TOE_TID
+ rb_str_catf(ret, " toe_tid=%u", s.tcpi_toe_tid); /* FreeBSD */
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_SND_REXMITPACK
+ rb_str_catf(ret, " snd_rexmitpack=%u", s.tcpi_snd_rexmitpack); /* FreeBSD */
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RCV_OOOPACK
+ rb_str_catf(ret, " rcv_ooopack=%u", s.tcpi_rcv_ooopack); /* FreeBSD */
+#endif
+#ifdef HAVE_STRUCT_TCP_INFO_TCPI_SND_ZEROWIN
+ rb_str_catf(ret, " snd_zerowin=%u", s.tcpi_snd_zerowin); /* FreeBSD */
+#endif
+ if (sizeof(struct tcp_info) < actual_size)
+ rb_str_catf(ret, " (%u bytes too long)", (unsigned)(actual_size - sizeof(struct tcp_info)));
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(SOL_SOCKET) && defined(SO_PEERCRED) /* GNU/Linux, OpenBSD */
+#if defined(__OpenBSD__)
+#define RUBY_SOCK_PEERCRED struct sockpeercred
+#else
+#define RUBY_SOCK_PEERCRED struct ucred
+#endif
+static int
+inspect_peercred(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(RUBY_SOCK_PEERCRED)) {
+ RUBY_SOCK_PEERCRED cred;
+ memcpy(&cred, RSTRING_PTR(data), sizeof(RUBY_SOCK_PEERCRED));
+ rb_str_catf(ret, " pid=%u euid=%u egid=%u",
+ (unsigned)cred.pid, (unsigned)cred.uid, (unsigned)cred.gid);
+ rb_str_cat2(ret, " (ucred)");
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+#if defined(LOCAL_PEERCRED) /* FreeBSD, MacOS X */
+static int
+inspect_local_peercred(int level, int optname, VALUE data, VALUE ret)
+{
+ if (RSTRING_LEN(data) == sizeof(struct xucred)) {
+ struct xucred cred;
+ memcpy(&cred, RSTRING_PTR(data), sizeof(struct xucred));
+ if (cred.cr_version != XUCRED_VERSION)
+ return 0;
+ rb_str_catf(ret, " version=%u", cred.cr_version);
+ rb_str_catf(ret, " euid=%u", cred.cr_uid);
+ if (cred.cr_ngroups) {
+ int i;
+ const char *sep = " groups=";
+ for (i = 0; i < cred.cr_ngroups; i++) {
+ rb_str_catf(ret, "%s%u", sep, cred.cr_groups[i]);
+ sep = ",";
+ }
+ }
+ rb_str_cat2(ret, " (xucred)");
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+#endif
+
+
+/*
+ * call-seq:
+ * sockopt.inspect => string
+ *
+ * Returns a string which shows sockopt in human-readable form.
+ *
+ * p Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i")).inspect
+ * #=> "#<Socket::Option: INET SOCKET KEEPALIVE 1>"
+ *
+ */
+static VALUE
+sockopt_inspect(VALUE self)
+{
+ int family = NUM2INT(sockopt_family_m(self));
+ int level = NUM2INT(sockopt_level_m(self));
+ int optname = NUM2INT(sockopt_optname_m(self));
+ VALUE data = sockopt_data(self);
+ VALUE v, ret;
+ ID family_id, level_id, optname_id;
+ int inspected;
+
+ StringValue(data);
+
+ ret = rb_sprintf("#<%s:", rb_obj_classname(self));
+
+ family_id = rsock_intern_family_noprefix(family);
+ if (family_id)
+ rb_str_catf(ret, " %s", rb_id2name(family_id));
+ else
+ rb_str_catf(ret, " family:%d", family);
+
+ if (level == SOL_SOCKET) {
+ rb_str_cat2(ret, " SOCKET");
+
+ optname_id = rsock_intern_so_optname(optname);
+ if (optname_id)
+ rb_str_catf(ret, " %s", rb_id2name(optname_id));
+ else
+ rb_str_catf(ret, " optname:%d", optname);
+ }
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ else if (family == AF_UNIX) {
+ rb_str_catf(ret, " level:%d", level);
+
+ optname_id = rsock_intern_local_optname(optname);
+ if (optname_id)
+ rb_str_catf(ret, " %s", rb_id2name(optname_id));
+ else
+ rb_str_catf(ret, " optname:%d", optname);
+ }
+#endif
+ else if (IS_IP_FAMILY(family)) {
+ level_id = rsock_intern_iplevel(level);
+ if (level_id)
+ rb_str_catf(ret, " %s", rb_id2name(level_id));
+ else
+ rb_str_catf(ret, " level:%d", level);
+
+ v = optname_to_sym(level, optname);
+ if (SYMBOL_P(v))
+ rb_str_catf(ret, " %"PRIsVALUE, rb_sym2str(v));
+ else
+ rb_str_catf(ret, " optname:%d", optname);
+ }
+ else {
+ rb_str_catf(ret, " level:%d", level);
+ rb_str_catf(ret, " optname:%d", optname);
+ }
+
+ inspected = 0;
+
+ if (level == SOL_SOCKET)
+ family = AF_UNSPEC;
+ switch (family) {
+ case AF_UNSPEC:
+ switch (level) {
+ case SOL_SOCKET:
+ switch (optname) {
+# if defined(SO_DEBUG) /* POSIX */
+ case SO_DEBUG: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(SO_ERROR) /* POSIX */
+ case SO_ERROR: inspected = inspect_errno(level, optname, data, ret); break;
+# endif
+# if defined(SO_TYPE) /* POSIX */
+ case SO_TYPE: inspected = inspect_socktype(level, optname, data, ret); break;
+# endif
+# if defined(SO_ACCEPTCONN) /* POSIX */
+ case SO_ACCEPTCONN: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(SO_BROADCAST) /* POSIX */
+ case SO_BROADCAST: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(SO_REUSEADDR) /* POSIX */
+ case SO_REUSEADDR: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(SO_KEEPALIVE) /* POSIX */
+ case SO_KEEPALIVE: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(SO_OOBINLINE) /* POSIX */
+ case SO_OOBINLINE: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(SO_SNDBUF) /* POSIX */
+ case SO_SNDBUF: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(SO_RCVBUF) /* POSIX */
+ case SO_RCVBUF: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(SO_DONTROUTE) /* POSIX */
+ case SO_DONTROUTE: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(SO_RCVLOWAT) /* POSIX */
+ case SO_RCVLOWAT: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(SO_SNDLOWAT) /* POSIX */
+ case SO_SNDLOWAT: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(SO_LINGER) /* POSIX */
+ case SO_LINGER: inspected = inspect_linger(level, optname, data, ret); break;
+# endif
+# if defined(SO_RCVTIMEO) /* POSIX */
+ case SO_RCVTIMEO: inspected = inspect_timeval_as_interval(level, optname, data, ret); break;
+# endif
+# if defined(SO_SNDTIMEO) /* POSIX */
+ case SO_SNDTIMEO: inspected = inspect_timeval_as_interval(level, optname, data, ret); break;
+# endif
+# if defined(SO_PEERCRED) /* GNU/Linux, OpenBSD */
+ case SO_PEERCRED: inspected = inspect_peercred(level, optname, data, ret); break;
+# endif
+ }
+ break;
+ }
+ break;
+
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ switch (level) {
+# if defined(IPPROTO_IP)
+ case IPPROTO_IP:
+ switch (optname) {
+# if defined(IP_MULTICAST_IF) && defined(HAVE_TYPE_STRUCT_IP_MREQN) /* 4.4BSD, GNU/Linux */
+ case IP_MULTICAST_IF: inspected = inspect_ipv4_multicast_if(level, optname, data, ret); break;
+# endif
+# if defined(IP_ADD_MEMBERSHIP) /* 4.4BSD, GNU/Linux */
+ case IP_ADD_MEMBERSHIP: inspected = inspect_ipv4_add_drop_membership(level, optname, data, ret); break;
+# endif
+# if defined(IP_DROP_MEMBERSHIP) /* 4.4BSD, GNU/Linux */
+ case IP_DROP_MEMBERSHIP: inspected = inspect_ipv4_add_drop_membership(level, optname, data, ret); break;
+# endif
+# if defined(IP_MULTICAST_LOOP) /* 4.4BSD, GNU/Linux */
+ case IP_MULTICAST_LOOP: inspected = inspect_ipv4_multicast_loop(level, optname, data, ret); break;
+# endif
+# if defined(IP_MULTICAST_TTL) /* 4.4BSD, GNU/Linux */
+ case IP_MULTICAST_TTL: inspected = inspect_ipv4_multicast_ttl(level, optname, data, ret); break;
+# endif
+ }
+ break;
+# endif
+
+# if defined(IPPROTO_IPV6)
+ case IPPROTO_IPV6:
+ switch (optname) {
+# if defined(IPV6_MULTICAST_HOPS) /* POSIX */
+ case IPV6_MULTICAST_HOPS: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(IPV6_MULTICAST_IF) /* POSIX */
+ case IPV6_MULTICAST_IF: inspected = inspect_ipv6_multicast_if(level, optname, data, ret); break;
+# endif
+# if defined(IPV6_MULTICAST_LOOP) /* POSIX */
+ case IPV6_MULTICAST_LOOP: inspected = inspect_uint(level, optname, data, ret); break;
+# endif
+# if defined(IPV6_JOIN_GROUP) /* POSIX */
+ case IPV6_JOIN_GROUP: inspected = inspect_ipv6_mreq(level, optname, data, ret); break;
+# endif
+# if defined(IPV6_LEAVE_GROUP) /* POSIX */
+ case IPV6_LEAVE_GROUP: inspected = inspect_ipv6_mreq(level, optname, data, ret); break;
+# endif
+# if defined(IPV6_UNICAST_HOPS) /* POSIX */
+ case IPV6_UNICAST_HOPS: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(IPV6_V6ONLY) /* POSIX */
+ case IPV6_V6ONLY: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+ }
+ break;
+# endif
+
+# if defined(IPPROTO_TCP)
+ case IPPROTO_TCP:
+ switch (optname) {
+# if defined(TCP_NODELAY) /* POSIX */
+ case TCP_NODELAY: inspected = inspect_int(level, optname, data, ret); break;
+# endif
+# if defined(TCP_INFO) && defined(HAVE_TYPE_STRUCT_TCP_INFO) /* Linux, FreeBSD */
+ case TCP_INFO: inspected = inspect_tcp_info(level, optname, data, ret); break;
+# endif
+ }
+ break;
+# endif
+ }
+ break;
+
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ case AF_UNIX:
+ switch (level) {
+ case 0:
+ switch (optname) {
+# if defined(LOCAL_PEERCRED)
+ case LOCAL_PEERCRED: inspected = inspect_local_peercred(level, optname, data, ret); break;
+# endif
+ }
+ break;
+ }
+ break;
+#endif
+ }
+
+ if (!inspected) {
+ rb_str_cat2(ret, " ");
+ rb_str_append(ret, rb_str_dump(data));
+ }
+
+ rb_str_cat2(ret, ">");
+
+ return ret;
+}
+
+/*
+ * call-seq:
+ * sockopt.unpack(template) => array
+ *
+ * Calls String#unpack on sockopt.data.
+ *
+ * sockopt = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i"))
+ * p sockopt.unpack("i") #=> [1]
+ * p sockopt.data.unpack("i") #=> [1]
+ */
+static VALUE
+sockopt_unpack(VALUE self, VALUE template)
+{
+ return rb_funcall(sockopt_data(self), rb_intern("unpack"), 1, template);
+}
+
+void
+rsock_init_sockopt(void)
+{
+ /*
+ * Document-class: Socket::Option
+ *
+ * Socket::Option represents a socket option used by
+ * BasicSocket#getsockopt and BasicSocket#setsockopt. A socket option
+ * contains the socket #family, protocol #level, option name #optname and
+ * option value #data.
+ */
+ rb_cSockOpt = rb_define_class_under(rb_cSocket, "Option", rb_cObject);
+ rb_define_method(rb_cSockOpt, "initialize", sockopt_initialize, 4);
+ rb_define_method(rb_cSockOpt, "family", sockopt_family_m, 0);
+ rb_define_method(rb_cSockOpt, "level", sockopt_level_m, 0);
+ rb_define_method(rb_cSockOpt, "optname", sockopt_optname_m, 0);
+ rb_define_method(rb_cSockOpt, "data", sockopt_data, 0);
+ rb_define_method(rb_cSockOpt, "inspect", sockopt_inspect, 0);
+
+ rb_define_singleton_method(rb_cSockOpt, "int", sockopt_s_int, 4);
+ rb_define_method(rb_cSockOpt, "int", sockopt_int, 0);
+
+ rb_define_singleton_method(rb_cSockOpt, "byte", sockopt_s_byte, 4);
+ rb_define_method(rb_cSockOpt, "byte", sockopt_byte, 0);
+
+ rb_define_singleton_method(rb_cSockOpt, "bool", sockopt_s_bool, 4);
+ rb_define_method(rb_cSockOpt, "bool", sockopt_bool, 0);
+
+ rb_define_singleton_method(rb_cSockOpt, "linger", sockopt_s_linger, 2);
+ rb_define_method(rb_cSockOpt, "linger", sockopt_linger, 0);
+
+ rb_define_singleton_method(rb_cSockOpt, "ipv4_multicast_ttl", sockopt_s_ipv4_multicast_ttl, 1);
+ rb_define_method(rb_cSockOpt, "ipv4_multicast_ttl", sockopt_ipv4_multicast_ttl, 0);
+
+ rb_define_singleton_method(rb_cSockOpt, "ipv4_multicast_loop", sockopt_s_ipv4_multicast_loop, 1);
+ rb_define_method(rb_cSockOpt, "ipv4_multicast_loop", sockopt_ipv4_multicast_loop, 0);
+
+ rb_define_method(rb_cSockOpt, "unpack", sockopt_unpack, 1);
+
+ rb_define_method(rb_cSockOpt, "to_s", sockopt_data, 0); /* compatibility for ruby before 1.9.2 */
+}
diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c
new file mode 100644
index 0000000000..f1fbcc35de
--- /dev/null
+++ b/ext/socket/raddrinfo.c
@@ -0,0 +1,3274 @@
+/************************************************
+
+ raddrinfo.c -
+
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
+
+************************************************/
+
+#include "rubysocket.h"
+
+// GETADDRINFO_IMPL == 0 : call getaddrinfo/getnameinfo directly
+// GETADDRINFO_IMPL == 1 : call getaddrinfo/getnameinfo without gvl (but uncancellable)
+// GETADDRINFO_IMPL == 2 : call getaddrinfo/getnameinfo in a dedicated pthread
+// (and if the call is interrupted, the pthread is detached)
+
+#ifndef GETADDRINFO_IMPL
+# ifdef GETADDRINFO_EMU
+# define GETADDRINFO_IMPL 0
+# elif !defined(HAVE_PTHREAD_CREATE) || !defined(HAVE_PTHREAD_DETACH) || defined(__MINGW32__) || defined(__MINGW64__)
+# define GETADDRINFO_IMPL 1
+# else
+# define GETADDRINFO_IMPL 2
+# include "ruby/thread_native.h"
+# endif
+#endif
+
+#if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6))
+#define LOOKUP_ORDERS (sizeof(lookup_order_table) / sizeof(lookup_order_table[0]))
+static const int lookup_order_table[] = {
+#if defined(LOOKUP_ORDER_HACK_INET)
+ PF_INET, PF_INET6, PF_UNSPEC,
+#elif defined(LOOKUP_ORDER_HACK_INET6)
+ PF_INET6, PF_INET, PF_UNSPEC,
+#else
+ /* should not happen */
+#endif
+};
+
+static int
+ruby_getaddrinfo(const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ struct addrinfo tmp_hints;
+ int i, af, error;
+
+ if (hints->ai_family != PF_UNSPEC) {
+ return getaddrinfo(nodename, servname, hints, res);
+ }
+
+ for (i = 0; i < LOOKUP_ORDERS; i++) {
+ af = lookup_order_table[i];
+ MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
+ tmp_hints.ai_family = af;
+ error = getaddrinfo(nodename, servname, &tmp_hints, res);
+ if (error) {
+ if (tmp_hints.ai_family == PF_UNSPEC) {
+ break;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ return error;
+}
+#define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res))
+#endif
+
+#if defined(_AIX)
+static int
+ruby_getaddrinfo__aix(const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ int error = getaddrinfo(nodename, servname, hints, res);
+ struct addrinfo *r;
+ if (error)
+ return error;
+ for (r = *res; r != NULL; r = r->ai_next) {
+ if (r->ai_addr->sa_family == 0)
+ r->ai_addr->sa_family = r->ai_family;
+ if (r->ai_addr->sa_len == 0)
+ r->ai_addr->sa_len = r->ai_addrlen;
+ }
+ return 0;
+}
+#undef getaddrinfo
+#define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res))
+static int
+ruby_getnameinfo__aix(const struct sockaddr *sa, size_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
+{
+ struct sockaddr_in6 *sa6;
+ u_int32_t *a6;
+
+ if (sa->sa_family == AF_INET6) {
+ sa6 = (struct sockaddr_in6 *)sa;
+ a6 = sa6->sin6_addr.u6_addr.u6_addr32;
+
+ if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
+ strncpy(host, "::", hostlen);
+ snprintf(serv, servlen, "%d", sa6->sin6_port);
+ return 0;
+ }
+ }
+ return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+}
+#undef getnameinfo
+#define getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \
+ ruby_getnameinfo__aix((sa), (salen), (host), (hostlen), (serv), (servlen), (flags))
+#endif
+
+static int str_is_number(const char *);
+
+#if defined(__APPLE__)
+static int
+ruby_getaddrinfo__darwin(const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ /* fix [ruby-core:29427] */
+ const char *tmp_servname;
+ struct addrinfo tmp_hints;
+ int error;
+
+ tmp_servname = servname;
+ MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
+ if (nodename && servname) {
+ if (str_is_number(tmp_servname) && atoi(servname) == 0) {
+ tmp_servname = NULL;
+#ifdef AI_NUMERICSERV
+ if (tmp_hints.ai_flags) tmp_hints.ai_flags &= ~AI_NUMERICSERV;
+#endif
+ }
+ }
+
+ error = getaddrinfo(nodename, tmp_servname, &tmp_hints, res);
+ if (error == 0) {
+ /* [ruby-dev:23164] */
+ struct addrinfo *r;
+ r = *res;
+ while (r) {
+ if (! r->ai_socktype) r->ai_socktype = hints->ai_socktype;
+ if (! r->ai_protocol) {
+ if (r->ai_socktype == SOCK_DGRAM) {
+ r->ai_protocol = IPPROTO_UDP;
+ }
+ else if (r->ai_socktype == SOCK_STREAM) {
+ r->ai_protocol = IPPROTO_TCP;
+ }
+ }
+ r = r->ai_next;
+ }
+ }
+
+ return error;
+}
+#undef getaddrinfo
+#define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__darwin((node),(serv),(hints),(res))
+#endif
+
+#ifdef HAVE_INET_PTON
+static int
+parse_numeric_port(const char *service, int *portp)
+{
+ unsigned long u;
+
+ if (!service) {
+ *portp = 0;
+ return 1;
+ }
+
+ if (strspn(service, "0123456789") != strlen(service))
+ return 0;
+
+ errno = 0;
+ u = STRTOUL(service, NULL, 10);
+ if (errno)
+ return 0;
+
+ if (0x10000 <= u)
+ return 0;
+
+ *portp = (int)u;
+
+ return 1;
+}
+#endif
+
+static int
+numeric_getaddrinfo(const char *node, const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+#ifdef HAVE_INET_PTON
+# if defined __MINGW64__
+# define inet_pton(f,s,d) rb_w32_inet_pton(f,s,d)
+# endif
+
+ int port;
+
+ if (node && parse_numeric_port(service, &port)) {
+ static const struct {
+ int socktype;
+ int protocol;
+ } list[] = {
+ { SOCK_STREAM, IPPROTO_TCP },
+ { SOCK_DGRAM, IPPROTO_UDP },
+ { SOCK_RAW, 0 }
+ };
+ struct addrinfo *ai = NULL;
+ int hint_family = hints ? hints->ai_family : PF_UNSPEC;
+ int hint_socktype = hints ? hints->ai_socktype : 0;
+ int hint_protocol = hints ? hints->ai_protocol : 0;
+ char ipv4addr[4];
+#ifdef AF_INET6
+ char ipv6addr[16];
+ if ((hint_family == PF_UNSPEC || hint_family == PF_INET6) &&
+ strspn(node, "0123456789abcdefABCDEF.:") == strlen(node) &&
+ inet_pton(AF_INET6, node, ipv6addr)) {
+ int i;
+ for (i = numberof(list)-1; 0 <= i; i--) {
+ if ((hint_socktype == 0 || hint_socktype == list[i].socktype) &&
+ (hint_protocol == 0 || list[i].protocol == 0 || hint_protocol == list[i].protocol)) {
+ struct addrinfo *ai0 = xcalloc(1, sizeof(struct addrinfo));
+ struct sockaddr_in6 *sa = xmalloc(sizeof(struct sockaddr_in6));
+ INIT_SOCKADDR_IN6(sa, sizeof(struct sockaddr_in6));
+ memcpy(&sa->sin6_addr, ipv6addr, sizeof(ipv6addr));
+ sa->sin6_port = htons(port);
+ ai0->ai_family = PF_INET6;
+ ai0->ai_socktype = list[i].socktype;
+ ai0->ai_protocol = hint_protocol ? hint_protocol : list[i].protocol;
+ ai0->ai_addrlen = sizeof(struct sockaddr_in6);
+ ai0->ai_addr = (struct sockaddr *)sa;
+ ai0->ai_canonname = NULL;
+ ai0->ai_next = ai;
+ ai = ai0;
+ }
+ }
+ }
+ else
+#endif
+ if ((hint_family == PF_UNSPEC || hint_family == PF_INET) &&
+ strspn(node, "0123456789.") == strlen(node) &&
+ inet_pton(AF_INET, node, ipv4addr)) {
+ int i;
+ for (i = numberof(list)-1; 0 <= i; i--) {
+ if ((hint_socktype == 0 || hint_socktype == list[i].socktype) &&
+ (hint_protocol == 0 || list[i].protocol == 0 || hint_protocol == list[i].protocol)) {
+ struct addrinfo *ai0 = xcalloc(1, sizeof(struct addrinfo));
+ struct sockaddr_in *sa = xmalloc(sizeof(struct sockaddr_in));
+ INIT_SOCKADDR_IN(sa, sizeof(struct sockaddr_in));
+ memcpy(&sa->sin_addr, ipv4addr, sizeof(ipv4addr));
+ sa->sin_port = htons(port);
+ ai0->ai_family = PF_INET;
+ ai0->ai_socktype = list[i].socktype;
+ ai0->ai_protocol = hint_protocol ? hint_protocol : list[i].protocol;
+ ai0->ai_addrlen = sizeof(struct sockaddr_in);
+ ai0->ai_addr = (struct sockaddr *)sa;
+ ai0->ai_canonname = NULL;
+ ai0->ai_next = ai;
+ ai = ai0;
+ }
+ }
+ }
+ if (ai) {
+ *res = ai;
+ return 0;
+ }
+ }
+#endif
+ return EAI_FAIL;
+}
+
+void
+rb_freeaddrinfo(struct rb_addrinfo *ai)
+{
+ if (!ai->allocated_by_malloc) {
+ if (ai->ai) freeaddrinfo(ai->ai);
+ }
+ else {
+ struct addrinfo *ai1, *ai2;
+ ai1 = ai->ai;
+ while (ai1) {
+ ai2 = ai1->ai_next;
+ xfree(ai1->ai_addr);
+ xfree(ai1);
+ ai1 = ai2;
+ }
+ }
+ xfree(ai);
+}
+
+static int
+rsock_value_timeout_to_msec(VALUE timeout)
+{
+ double seconds = NUM2DBL(timeout);
+ if (seconds < 0) rb_raise(rb_eArgError, "timeout must not be negative");
+
+ double msec = seconds * 1000.0;
+ if (msec > UINT_MAX) rb_raise(rb_eArgError, "timeout too large");
+
+ return (unsigned int)(msec + 0.5);
+}
+
+#if GETADDRINFO_IMPL == 0
+
+static int
+rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, int _timeout)
+{
+ return getaddrinfo(hostp, portp, hints, ai);
+}
+
+#elif GETADDRINFO_IMPL == 1
+
+struct getaddrinfo_arg
+{
+ const char *node;
+ const char *service;
+ const struct addrinfo *hints;
+ struct addrinfo **res;
+};
+
+static void *
+nogvl_getaddrinfo(void *arg)
+{
+ int ret;
+ struct getaddrinfo_arg *ptr = arg;
+ ret = getaddrinfo(ptr->node, ptr->service, ptr->hints, ptr->res);
+#ifdef __linux__
+ /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and
+ * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420]
+ */
+ if (ret == EAI_SYSTEM && errno == ENOENT)
+ ret = EAI_NONAME;
+#endif
+ return (void *)(VALUE)ret;
+}
+
+static void *
+fork_safe_getaddrinfo(void *arg)
+{
+ return rb_thread_prevent_fork(nogvl_getaddrinfo, arg);
+}
+
+static int
+rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, int _timeout)
+{
+ struct getaddrinfo_arg arg;
+ MEMZERO(&arg, struct getaddrinfo_arg, 1);
+ arg.node = hostp;
+ arg.service = portp;
+ arg.hints = hints;
+ arg.res = ai;
+ return (int)(VALUE)rb_thread_call_without_gvl(fork_safe_getaddrinfo, &arg, RUBY_UBF_IO, 0);
+}
+
+#elif GETADDRINFO_IMPL == 2
+
+struct getaddrinfo_arg
+{
+ char *node, *service;
+ struct addrinfo hints;
+ struct addrinfo *ai;
+ int err, gai_errno, refcount, done, cancelled, timedout;
+ rb_nativethread_lock_t lock;
+ rb_nativethread_cond_t cond;
+ int timeout;
+};
+
+static struct getaddrinfo_arg *
+allocate_getaddrinfo_arg(const char *hostp, const char *portp, const struct addrinfo *hints, int timeout)
+{
+ size_t hostp_offset = sizeof(struct getaddrinfo_arg);
+ size_t portp_offset = hostp_offset + (hostp ? strlen(hostp) + 1 : 0);
+ size_t bufsize = portp_offset + (portp ? strlen(portp) + 1 : 0);
+
+ char *buf = malloc(bufsize);
+ if (!buf) {
+ rb_gc();
+ buf = malloc(bufsize);
+ if (!buf) return NULL;
+ }
+ struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)buf;
+
+ if (hostp) {
+ arg->node = buf + hostp_offset;
+ memcpy(arg->node, hostp, portp_offset - hostp_offset);
+ }
+ else {
+ arg->node = NULL;
+ }
+
+ if (portp) {
+ arg->service = buf + portp_offset;
+ memcpy(arg->service, portp, bufsize - portp_offset);
+ }
+ else {
+ arg->service = NULL;
+ }
+
+ arg->hints = *hints;
+ arg->ai = NULL;
+
+ arg->refcount = 2;
+ arg->done = arg->cancelled = arg->timedout = 0;
+ arg->timeout = timeout;
+
+ rb_nativethread_lock_initialize(&arg->lock);
+ rb_native_cond_initialize(&arg->cond);
+
+ return arg;
+}
+
+static void
+free_getaddrinfo_arg(struct getaddrinfo_arg *arg)
+{
+ rb_native_cond_destroy(&arg->cond);
+ rb_nativethread_lock_destroy(&arg->lock);
+ free(arg);
+}
+
+static void *
+do_getaddrinfo(void *ptr)
+{
+ struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr;
+
+ int err, gai_errno;
+ err = getaddrinfo(arg->node, arg->service, &arg->hints, &arg->ai);
+ gai_errno = errno;
+#ifdef __linux__
+ /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and
+ * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420]
+ */
+ if (err == EAI_SYSTEM && errno == ENOENT)
+ err = EAI_NONAME;
+#endif
+
+ int need_free = 0;
+ rb_nativethread_lock_lock(&arg->lock);
+ {
+ arg->err = err;
+ arg->gai_errno = gai_errno;
+ if (arg->cancelled) {
+ if (arg->ai) freeaddrinfo(arg->ai);
+ }
+ else {
+ arg->done = 1;
+ rb_native_cond_signal(&arg->cond);
+ }
+ if (--arg->refcount == 0) need_free = 1;
+ }
+ rb_nativethread_lock_unlock(&arg->lock);
+
+ if (need_free) free_getaddrinfo_arg(arg);
+
+ return 0;
+}
+
+static void *
+wait_getaddrinfo(void *ptr)
+{
+ struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr;
+ rb_nativethread_lock_lock(&arg->lock);
+ while (!arg->done && !arg->cancelled) {
+ long msec = arg->timeout;
+ if (msec == 0) {
+ arg->cancelled = 1;
+ arg->timedout = 1;
+ } else if (msec > 0) {
+ rb_native_cond_timedwait(&arg->cond, &arg->lock, msec);
+ if (!arg->done) {
+ arg->cancelled = 1;
+ arg->timedout = 1;
+ }
+ } else {
+ rb_native_cond_wait(&arg->cond, &arg->lock);
+ }
+ }
+ rb_nativethread_lock_unlock(&arg->lock);
+ return 0;
+}
+
+static void
+cancel_getaddrinfo(void *ptr)
+{
+ struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr;
+ rb_nativethread_lock_lock(&arg->lock);
+ {
+ arg->cancelled = 1;
+ rb_native_cond_signal(&arg->cond);
+ }
+ rb_nativethread_lock_unlock(&arg->lock);
+}
+
+int
+raddrinfo_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg)
+{
+ int limit = 3, ret;
+ int saved_errno;
+#ifdef HAVE_PTHREAD_ATTR_SETDETACHSTATE
+ pthread_attr_t attr;
+ pthread_attr_t *attr_p = &attr;
+ int err;
+ int init_retries = 0;
+ int init_retries_max = 3;
+retry_attr_init:
+ if ((err = pthread_attr_init(attr_p)) != 0) {
+ if (err == ENOMEM && init_retries < init_retries_max) {
+ init_retries++;
+ rb_gc();
+ goto retry_attr_init;
+ }
+ return err;
+ }
+ if ((err = pthread_attr_setdetachstate(attr_p, PTHREAD_CREATE_DETACHED)) != 0) {
+ saved_errno = errno;
+ pthread_attr_destroy(attr_p);
+ errno = saved_errno;
+ return err; // EINVAL - shouldn't happen
+ }
+#else
+ pthread_attr_t *attr_p = NULL;
+#endif
+ do {
+ // It is said that pthread_create may fail spuriously, so we follow the JDK and retry several times.
+ //
+ // https://bugs.openjdk.org/browse/JDK-8268605
+ // https://github.com/openjdk/jdk/commit/e35005d5ce383ddd108096a3079b17cb0bcf76f1
+ ret = pthread_create(th, attr_p, start_routine, arg);
+ } while (ret == EAGAIN && limit-- > 0);
+#ifdef HAVE_PTHREAD_ATTR_SETDETACHSTATE
+ saved_errno = errno;
+ pthread_attr_destroy(attr_p);
+ if (ret != 0) {
+ errno = saved_errno;
+ }
+#else
+ if (ret == 0) {
+ pthread_detach(th); // this can race with shutdown routine of thread in some glibc versions
+ }
+#endif
+ return ret;
+}
+
+static void *
+fork_safe_do_getaddrinfo(void *ptr)
+{
+ return rb_thread_prevent_fork(do_getaddrinfo, ptr);
+}
+
+static int
+rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, int timeout)
+{
+ int retry;
+ struct getaddrinfo_arg *arg;
+ int err = 0, gai_errno = 0, timedout = 0;
+
+start:
+ retry = 0;
+
+ arg = allocate_getaddrinfo_arg(hostp, portp, hints, timeout);
+ if (!arg) {
+ return EAI_MEMORY;
+ }
+
+ pthread_t th;
+ if (raddrinfo_pthread_create(&th, fork_safe_do_getaddrinfo, arg) != 0) {
+ int err = errno;
+ free_getaddrinfo_arg(arg);
+ errno = err;
+ return EAI_SYSTEM;
+ }
+
+ rb_thread_call_without_gvl2(wait_getaddrinfo, arg, cancel_getaddrinfo, arg);
+
+ int need_free = 0;
+ rb_nativethread_lock_lock(&arg->lock);
+ {
+ if (arg->done) {
+ err = arg->err;
+ gai_errno = arg->gai_errno;
+ if (err == 0) *ai = arg->ai;
+ }
+ else if (arg->cancelled) {
+ retry = 1;
+ timedout = arg->timedout;
+ }
+ else {
+ // If already interrupted, rb_thread_call_without_gvl2 may return without calling wait_getaddrinfo.
+ // In this case, it could be !arg->done && !arg->cancelled.
+ arg->cancelled = 1; // to make do_getaddrinfo call freeaddrinfo
+ retry = 1;
+ }
+ if (--arg->refcount == 0) need_free = 1;
+ }
+ rb_nativethread_lock_unlock(&arg->lock);
+
+ if (need_free) free_getaddrinfo_arg(arg);
+
+ if (timedout) {
+ VALUE host = rb_str_new_cstr(hostp);
+ VALUE port = rb_str_new_cstr(portp);
+ rsock_raise_user_specified_timeout(NULL, host, port);
+ }
+
+ // If the current thread is interrupted by asynchronous exception, the following raises the exception.
+ // But if the current thread is interrupted by timer thread, the following returns; we need to manually retry.
+ rb_thread_check_ints();
+ if (retry) goto start;
+
+ /* Because errno is threadlocal, the errno value we got from the call to getaddrinfo() in the thread
+ * (in case of EAI_SYSTEM return value) is not propagated to the caller of _this_ function. Set errno
+ * explicitly, as round-tripped through struct getaddrinfo_arg, to deal with that */
+ if (gai_errno) errno = gai_errno;
+ return err;
+}
+
+#endif
+
+#define GETNAMEINFO_WONT_BLOCK(host, serv, flags) \
+ ((!(host) || ((flags) & NI_NUMERICHOST)) && \
+ (!(serv) || ((flags) & NI_NUMERICSERV)))
+
+#if GETADDRINFO_IMPL == 0
+
+int
+rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
+{
+ return getnameinfo(sa, salen, host, (socklen_t)hostlen, serv, (socklen_t)servlen, flags);
+}
+
+#elif GETADDRINFO_IMPL == 1
+
+struct getnameinfo_arg
+{
+ const struct sockaddr *sa;
+ socklen_t salen;
+ int flags;
+ char *host;
+ size_t hostlen;
+ char *serv;
+ size_t servlen;
+};
+
+static void *
+nogvl_getnameinfo(void *arg)
+{
+ struct getnameinfo_arg *ptr = arg;
+ return (void *)(VALUE)getnameinfo(ptr->sa, ptr->salen,
+ ptr->host, (socklen_t)ptr->hostlen,
+ ptr->serv, (socklen_t)ptr->servlen,
+ ptr->flags);
+}
+int
+rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
+{
+ if (GETNAMEINFO_WONT_BLOCK(host, serv, flags)) {
+ return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+ }
+
+ struct getnameinfo_arg arg;
+ int ret;
+ arg.sa = sa;
+ arg.salen = salen;
+ arg.host = host;
+ arg.hostlen = hostlen;
+ arg.serv = serv;
+ arg.servlen = servlen;
+ arg.flags = flags;
+ ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getnameinfo, &arg, RUBY_UBF_IO, 0);
+ return ret;
+}
+
+#elif GETADDRINFO_IMPL == 2
+
+struct getnameinfo_arg
+{
+ struct sockaddr *sa;
+ socklen_t salen;
+ int flags;
+ char *host;
+ size_t hostlen;
+ char *serv;
+ size_t servlen;
+ int err, gni_errno, refcount, done, cancelled;
+ rb_nativethread_lock_t lock;
+ rb_nativethread_cond_t cond;
+};
+
+static struct getnameinfo_arg *
+allocate_getnameinfo_arg(const struct sockaddr *sa, socklen_t salen, size_t hostlen, size_t servlen, int flags)
+{
+ size_t sa_offset = sizeof(struct getnameinfo_arg);
+ size_t host_offset = sa_offset + salen;
+ size_t serv_offset = host_offset + hostlen;
+ size_t bufsize = serv_offset + servlen;
+
+ char *buf = malloc(bufsize);
+ if (!buf) {
+ rb_gc();
+ buf = malloc(bufsize);
+ if (!buf) return NULL;
+ }
+ struct getnameinfo_arg *arg = (struct getnameinfo_arg *)buf;
+
+ arg->sa = (struct sockaddr *)(buf + sa_offset);
+ memcpy(arg->sa, sa, salen);
+ arg->salen = salen;
+ arg->host = buf + host_offset;
+ arg->hostlen = hostlen;
+ arg->serv = buf + serv_offset;
+ arg->servlen = servlen;
+ arg->flags = flags;
+
+ arg->refcount = 2;
+ arg->done = arg->cancelled = 0;
+
+ rb_nativethread_lock_initialize(&arg->lock);
+ rb_native_cond_initialize(&arg->cond);
+
+ return arg;
+}
+
+static void
+free_getnameinfo_arg(struct getnameinfo_arg *arg)
+{
+ rb_native_cond_destroy(&arg->cond);
+ rb_nativethread_lock_destroy(&arg->lock);
+
+ free(arg);
+}
+
+static void *
+do_getnameinfo(void *ptr)
+{
+ struct getnameinfo_arg *arg = (struct getnameinfo_arg *)ptr;
+
+ int err, gni_errno;
+ err = getnameinfo(arg->sa, arg->salen, arg->host, (socklen_t)arg->hostlen, arg->serv, (socklen_t)arg->servlen, arg->flags);
+ gni_errno = errno;
+
+ int need_free = 0;
+ rb_nativethread_lock_lock(&arg->lock);
+ arg->err = err;
+ arg->gni_errno = gni_errno;
+ if (!arg->cancelled) {
+ arg->done = 1;
+ rb_native_cond_signal(&arg->cond);
+ }
+ if (--arg->refcount == 0) need_free = 1;
+ rb_nativethread_lock_unlock(&arg->lock);
+
+ if (need_free) free_getnameinfo_arg(arg);
+
+ return 0;
+}
+
+static void *
+wait_getnameinfo(void *ptr)
+{
+ struct getnameinfo_arg *arg = (struct getnameinfo_arg *)ptr;
+ rb_nativethread_lock_lock(&arg->lock);
+ while (!arg->done && !arg->cancelled) {
+ rb_native_cond_wait(&arg->cond, &arg->lock);
+ }
+ rb_nativethread_lock_unlock(&arg->lock);
+ return 0;
+}
+
+static void
+cancel_getnameinfo(void *ptr)
+{
+ struct getnameinfo_arg *arg = (struct getnameinfo_arg *)ptr;
+ rb_nativethread_lock_lock(&arg->lock);
+ arg->cancelled = 1;
+ rb_native_cond_signal(&arg->cond);
+ rb_nativethread_lock_unlock(&arg->lock);
+}
+
+int
+rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
+{
+ int retry;
+ struct getnameinfo_arg *arg;
+ int err = 0, gni_errno = 0;
+
+ if (GETNAMEINFO_WONT_BLOCK(host, serv, flags)) {
+ return getnameinfo(sa, salen, host, (socklen_t)hostlen, serv, (socklen_t)servlen, flags);
+ }
+
+start:
+ retry = 0;
+
+ arg = allocate_getnameinfo_arg(sa, salen, hostlen, servlen, flags);
+ if (!arg) {
+ return EAI_MEMORY;
+ }
+
+ pthread_t th;
+ if (raddrinfo_pthread_create(&th, do_getnameinfo, arg) != 0) {
+ int err = errno;
+ free_getnameinfo_arg(arg);
+ errno = err;
+ return EAI_SYSTEM;
+ }
+
+ rb_thread_call_without_gvl2(wait_getnameinfo, arg, cancel_getnameinfo, arg);
+
+ int need_free = 0;
+ rb_nativethread_lock_lock(&arg->lock);
+ if (arg->done) {
+ err = arg->err;
+ gni_errno = arg->gni_errno;
+ if (err == 0) {
+ if (host) memcpy(host, arg->host, hostlen);
+ if (serv) memcpy(serv, arg->serv, servlen);
+ }
+ }
+ else if (arg->cancelled) {
+ retry = 1;
+ }
+ else {
+ // If already interrupted, rb_thread_call_without_gvl2 may return without calling wait_getnameinfo.
+ // In this case, it could be !arg->done && !arg->cancelled.
+ arg->cancelled = 1;
+ retry = 1;
+ }
+ if (--arg->refcount == 0) need_free = 1;
+ rb_nativethread_lock_unlock(&arg->lock);
+
+ if (need_free) free_getnameinfo_arg(arg);
+
+ // If the current thread is interrupted by asynchronous exception, the following raises the exception.
+ // But if the current thread is interrupted by timer thread, the following returns; we need to manually retry.
+ rb_thread_check_ints();
+ if (retry) goto start;
+
+ /* Make sure we copy the thread-local errno value from the getnameinfo thread back to this thread, so
+ * calling code sees the correct errno */
+ if (gni_errno) errno = gni_errno;
+ return err;
+}
+
+#endif
+
+static void
+make_ipaddr0(struct sockaddr *addr, socklen_t addrlen, char *buf, size_t buflen)
+{
+ int error;
+
+ error = rb_getnameinfo(addr, addrlen, buf, buflen, NULL, 0, NI_NUMERICHOST);
+ if (error) {
+ rsock_raise_resolution_error("getnameinfo", error);
+ }
+}
+
+VALUE
+rsock_make_ipaddr(struct sockaddr *addr, socklen_t addrlen)
+{
+ char hbuf[1024];
+
+ make_ipaddr0(addr, addrlen, hbuf, sizeof(hbuf));
+ return rb_str_new2(hbuf);
+}
+
+static void
+make_inetaddr(unsigned int host, char *buf, size_t buflen)
+{
+ struct sockaddr_in sin;
+
+ INIT_SOCKADDR_IN(&sin, sizeof(sin));
+ sin.sin_addr.s_addr = host;
+ make_ipaddr0((struct sockaddr*)&sin, sizeof(sin), buf, buflen);
+}
+
+static int
+str_is_number(const char *p)
+{
+ char *ep;
+
+ if (!p || *p == '\0')
+ return 0;
+ ep = NULL;
+ (void)STRTOUL(p, &ep, 10);
+ if (ep && *ep == '\0')
+ return 1;
+ else
+ return 0;
+}
+
+#define str_equal(ptr, len, name) \
+ ((ptr)[0] == name[0] && \
+ rb_strlen_lit(name) == (len) && memcmp(ptr, name, len) == 0)
+
+char*
+raddrinfo_host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr)
+{
+ if (NIL_P(host)) {
+ return NULL;
+ }
+ else if (rb_obj_is_kind_of(host, rb_cInteger)) {
+ unsigned int i = NUM2UINT(host);
+
+ make_inetaddr(htonl(i), hbuf, hbuflen);
+ if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
+ return hbuf;
+ }
+ else {
+ const char *name;
+ size_t len;
+
+ StringValueCStr(host);
+ RSTRING_GETMEM(host, name, len);
+ if (!len || str_equal(name, len, "<any>")) {
+ make_inetaddr(INADDR_ANY, hbuf, hbuflen);
+ if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
+ }
+ else if (str_equal(name, len, "<broadcast>")) {
+ make_inetaddr(INADDR_BROADCAST, hbuf, hbuflen);
+ if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
+ }
+ else if (len >= hbuflen) {
+ rb_raise(rb_eArgError, "hostname too long (%"PRIuSIZE")",
+ len);
+ }
+ else {
+ memcpy(hbuf, name, len);
+ hbuf[len] = '\0';
+ }
+ return hbuf;
+ }
+}
+
+char*
+raddrinfo_port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr)
+{
+ if (NIL_P(port)) {
+ return 0;
+ }
+ else if (FIXNUM_P(port)) {
+ snprintf(pbuf, pbuflen, "%ld", FIX2LONG(port));
+#ifdef AI_NUMERICSERV
+ if (flags_ptr) *flags_ptr |= AI_NUMERICSERV;
+#endif
+ return pbuf;
+ }
+ else {
+ const char *serv;
+ size_t len;
+
+ StringValueCStr(port);
+ RSTRING_GETMEM(port, serv, len);
+ if (len >= pbuflen) {
+ rb_raise(rb_eArgError, "service name too long (%"PRIuSIZE")",
+ len);
+ }
+ memcpy(pbuf, serv, len);
+ pbuf[len] = '\0';
+ return pbuf;
+ }
+}
+
+static int
+rb_scheduler_getaddrinfo(VALUE scheduler, VALUE host, const char *service,
+ const struct addrinfo *hints, struct rb_addrinfo **res)
+{
+ int error, res_allocated = 0, _additional_flags = 0;
+ long i, len;
+ struct addrinfo *ai, *ai_tail = NULL;
+ char *hostp;
+ char _hbuf[NI_MAXHOST];
+ VALUE ip_addresses_array, ip_address;
+
+ ip_addresses_array = rb_fiber_scheduler_address_resolve(scheduler, host);
+
+ if (ip_addresses_array == Qundef) {
+ // Returns EAI_FAIL if the scheduler hook is not implemented:
+ return EAI_FAIL;
+ } else if (ip_addresses_array == Qnil) {
+ len = 0;
+ } else {
+ len = RARRAY_LEN(ip_addresses_array);
+ }
+
+ for(i=0; i<len; i++) {
+ ip_address = rb_ary_entry(ip_addresses_array, i);
+ hostp = raddrinfo_host_str(ip_address, _hbuf, sizeof(_hbuf), &_additional_flags);
+ error = numeric_getaddrinfo(hostp, service, hints, &ai);
+ if (error == 0) {
+ if (!res_allocated) {
+ res_allocated = 1;
+ *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo));
+ (*res)->allocated_by_malloc = 1;
+ (*res)->ai = ai;
+ ai_tail = ai;
+ } else {
+ while (ai_tail->ai_next) {
+ ai_tail = ai_tail->ai_next;
+ }
+ ai_tail->ai_next = ai;
+ ai_tail = ai;
+ }
+ }
+ }
+
+ if (res_allocated) { // At least one valid result.
+ return 0;
+ } else {
+ return EAI_NONAME;
+ }
+}
+
+struct rb_addrinfo*
+rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout)
+{
+ struct rb_addrinfo* res = NULL;
+ struct addrinfo *ai;
+ char *hostp, *portp;
+ int error = 0;
+ char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
+ int additional_flags = 0;
+
+ hostp = raddrinfo_host_str(host, hbuf, sizeof(hbuf), &additional_flags);
+ portp = raddrinfo_port_str(port, pbuf, sizeof(pbuf), &additional_flags);
+
+ if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) {
+ hints->ai_socktype = SOCK_DGRAM;
+ }
+ hints->ai_flags |= additional_flags;
+
+ error = numeric_getaddrinfo(hostp, portp, hints, &ai);
+ if (error == 0) {
+ res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo));
+ res->allocated_by_malloc = 1;
+ res->ai = ai;
+ } else {
+ VALUE scheduler = rb_fiber_scheduler_current();
+ int resolved = 0;
+
+ if (scheduler != Qnil && hostp && !(hints->ai_flags & AI_NUMERICHOST)) {
+ error = rb_scheduler_getaddrinfo(scheduler, host, portp, hints, &res);
+
+ if (error != EAI_FAIL) {
+ resolved = 1;
+ }
+ }
+
+ if (!resolved) {
+ int t = NIL_P(timeout) ? -1 : rsock_value_timeout_to_msec(timeout);
+ error = rb_getaddrinfo(hostp, portp, hints, &ai, t);
+ if (error == 0) {
+ res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo));
+ res->allocated_by_malloc = 0;
+ res->ai = ai;
+ }
+ }
+ }
+
+ if (error) {
+ if (hostp && hostp[strlen(hostp)-1] == '\n') {
+ rb_raise(rb_eSocket, "newline at the end of hostname");
+ }
+ rsock_raise_resolution_error("getaddrinfo", error);
+ }
+
+ return res;
+}
+
+int
+rsock_fd_family(int fd)
+{
+ struct sockaddr sa = { 0 };
+ socklen_t sa_len = sizeof(sa);
+
+ if (fd < 0 || getsockname(fd, &sa, &sa_len) != 0 ||
+ (size_t)sa_len < offsetof(struct sockaddr, sa_family) + sizeof(sa.sa_family)) {
+ return AF_UNSPEC;
+ }
+ return sa.sa_family;
+}
+
+struct rb_addrinfo*
+rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags, VALUE timeout)
+{
+ struct addrinfo hints;
+
+ MEMZERO(&hints, struct addrinfo, 1);
+ hints.ai_family = family;
+ hints.ai_socktype = socktype;
+ hints.ai_flags = flags;
+ return rsock_getaddrinfo(host, port, &hints, 1, timeout);
+}
+
+VALUE
+rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup)
+{
+ VALUE family, port, addr1, addr2;
+ VALUE ary;
+ int error;
+ char hbuf[1024], pbuf[1024];
+ ID id;
+
+ id = rsock_intern_family(sockaddr->sa_family);
+ if (id) {
+ family = rb_str_dup(rb_id2str(id));
+ }
+ else {
+ family = rb_sprintf("unknown:%d", sockaddr->sa_family);
+ }
+
+ addr1 = Qnil;
+ if (!norevlookup) {
+ error = rb_getnameinfo(sockaddr, sockaddrlen, hbuf, sizeof(hbuf),
+ NULL, 0, 0);
+ if (! error) {
+ addr1 = rb_str_new2(hbuf);
+ }
+ }
+ error = rb_getnameinfo(sockaddr, sockaddrlen, hbuf, sizeof(hbuf),
+ pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error) {
+ rsock_raise_resolution_error("getnameinfo", error);
+ }
+ addr2 = rb_str_new2(hbuf);
+ if (addr1 == Qnil) {
+ addr1 = addr2;
+ }
+ port = INT2FIX(atoi(pbuf));
+ ary = rb_ary_new3(4, family, port, addr1, addr2);
+
+ return ary;
+}
+
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+static long
+unixsocket_len(const struct sockaddr_un *su, socklen_t socklen)
+{
+ const char *s = su->sun_path, *e = (const char*)su + socklen;
+ while (s < e && *(e-1) == '\0')
+ e--;
+ return e - s;
+}
+
+VALUE
+rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len)
+{
+ long n = unixsocket_len(sockaddr, len);
+ if (n >= 0)
+ return rb_str_new(sockaddr->sun_path, n);
+ else
+ return rb_str_new2("");
+}
+
+VALUE
+rsock_unixaddr(struct sockaddr_un *sockaddr, socklen_t len)
+{
+ return rb_assoc_new(rb_str_new2("AF_UNIX"),
+ rsock_unixpath_str(sockaddr, len));
+}
+
+socklen_t
+rsock_unix_sockaddr_len(VALUE path)
+{
+#ifdef __linux__
+ if (RSTRING_LEN(path) == 0) {
+ /* autobind; see unix(7) for details. */
+ return (socklen_t) sizeof(sa_family_t);
+ }
+ else if (RSTRING_PTR(path)[0] == '\0') {
+ /* abstract namespace; see unix(7) for details. */
+ if (SOCKLEN_MAX - offsetof(struct sockaddr_un, sun_path) < (size_t)RSTRING_LEN(path))
+ rb_raise(rb_eArgError, "Linux abstract socket too long");
+ return (socklen_t) offsetof(struct sockaddr_un, sun_path) +
+ RSTRING_SOCKLEN(path);
+ }
+ else {
+#endif
+ return (socklen_t) sizeof(struct sockaddr_un);
+#ifdef __linux__
+ }
+#endif
+}
+#endif
+
+struct hostent_arg {
+ VALUE host;
+ struct rb_addrinfo* addr;
+ VALUE (*ipaddr)(struct sockaddr*, socklen_t);
+};
+
+static VALUE
+make_hostent_internal(VALUE v)
+{
+ struct hostent_arg *arg = (void *)v;
+ VALUE host = arg->host;
+ struct addrinfo* addr = arg->addr->ai;
+ VALUE (*ipaddr)(struct sockaddr*, socklen_t) = arg->ipaddr;
+
+ struct addrinfo *ai;
+ struct hostent *h;
+ VALUE ary, names;
+ char **pch;
+ const char* hostp;
+ char hbuf[NI_MAXHOST];
+
+ ary = rb_ary_new();
+ if (addr->ai_canonname) {
+ hostp = addr->ai_canonname;
+ }
+ else {
+ hostp = raddrinfo_host_str(host, hbuf, sizeof(hbuf), NULL);
+ }
+ rb_ary_push(ary, rb_str_new2(hostp));
+
+ if (addr->ai_canonname && strlen(addr->ai_canonname) < NI_MAXHOST &&
+ (h = gethostbyname(addr->ai_canonname))) {
+ names = rb_ary_new();
+ if (h->h_aliases != NULL) {
+ for (pch = h->h_aliases; *pch; pch++) {
+ rb_ary_push(names, rb_str_new2(*pch));
+ }
+ }
+ }
+ else {
+ names = rb_ary_new2(0);
+ }
+ rb_ary_push(ary, names);
+ rb_ary_push(ary, INT2NUM(addr->ai_family));
+ for (ai = addr; ai; ai = ai->ai_next) {
+ rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen));
+ }
+
+ return ary;
+}
+
+VALUE
+rsock_freeaddrinfo(VALUE arg)
+{
+ struct rb_addrinfo *addr = (struct rb_addrinfo *)arg;
+ rb_freeaddrinfo(addr);
+ return Qnil;
+}
+
+VALUE
+rsock_make_hostent(VALUE host, struct rb_addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, socklen_t))
+{
+ struct hostent_arg arg;
+
+ arg.host = host;
+ arg.addr = addr;
+ arg.ipaddr = ipaddr;
+ return rb_ensure(make_hostent_internal, (VALUE)&arg,
+ rsock_freeaddrinfo, (VALUE)addr);
+}
+
+typedef struct {
+ VALUE inspectname;
+ VALUE canonname;
+ int pfamily;
+ int socktype;
+ int protocol;
+ socklen_t sockaddr_len;
+ union_sockaddr addr;
+} rb_addrinfo_t;
+
+static void
+addrinfo_mark(void *ptr)
+{
+ rb_addrinfo_t *rai = ptr;
+ rb_gc_mark(rai->inspectname);
+ rb_gc_mark(rai->canonname);
+}
+
+#define addrinfo_free RUBY_TYPED_DEFAULT_FREE
+
+static size_t
+addrinfo_memsize(const void *ptr)
+{
+ return sizeof(rb_addrinfo_t);
+}
+
+static const rb_data_type_t addrinfo_type = {
+ "socket/addrinfo",
+ {addrinfo_mark, addrinfo_free, addrinfo_memsize,},
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_WB_PROTECTED,
+};
+
+static VALUE
+addrinfo_s_allocate(VALUE klass)
+{
+ return TypedData_Wrap_Struct(klass, &addrinfo_type, 0);
+}
+
+#define IS_ADDRINFO(obj) rb_typeddata_is_kind_of((obj), &addrinfo_type)
+static inline rb_addrinfo_t *
+check_addrinfo(VALUE self)
+{
+ return rb_check_typeddata(self, &addrinfo_type);
+}
+
+static rb_addrinfo_t *
+get_addrinfo(VALUE self)
+{
+ rb_addrinfo_t *rai = check_addrinfo(self);
+
+ if (!rai) {
+ rb_raise(rb_eTypeError, "uninitialized socket address");
+ }
+ return rai;
+}
+
+
+static rb_addrinfo_t *
+alloc_addrinfo(void)
+{
+ rb_addrinfo_t *rai = ZALLOC(rb_addrinfo_t);
+ rai->inspectname = Qnil;
+ rai->canonname = Qnil;
+ return rai;
+}
+
+static void
+init_addrinfo(VALUE self, rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len,
+ int pfamily, int socktype, int protocol,
+ VALUE canonname, VALUE inspectname)
+{
+ if ((socklen_t)sizeof(rai->addr) < len)
+ rb_raise(rb_eArgError, "sockaddr string too big");
+ memcpy((void *)&rai->addr, (void *)sa, len);
+ rai->sockaddr_len = len;
+
+ rai->pfamily = pfamily;
+ rai->socktype = socktype;
+ rai->protocol = protocol;
+ RB_OBJ_WRITE(self, &rai->canonname, canonname);
+ RB_OBJ_WRITE(self, &rai->inspectname, inspectname);
+}
+
+VALUE
+rsock_addrinfo_new(struct sockaddr *addr, socklen_t len,
+ int family, int socktype, int protocol,
+ VALUE canonname, VALUE inspectname)
+{
+ VALUE a;
+ rb_addrinfo_t *rai;
+
+ a = addrinfo_s_allocate(rb_cAddrinfo);
+ DATA_PTR(a) = rai = alloc_addrinfo();
+ init_addrinfo(a, rai, addr, len, family, socktype, protocol, canonname, inspectname);
+ return a;
+}
+
+static struct rb_addrinfo *
+call_getaddrinfo(VALUE node, VALUE service,
+ VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
+ int socktype_hack, VALUE timeout)
+{
+ struct addrinfo hints;
+ struct rb_addrinfo *res;
+
+ MEMZERO(&hints, struct addrinfo, 1);
+ hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
+
+ if (!NIL_P(socktype)) {
+ hints.ai_socktype = rsock_socktype_arg(socktype);
+ }
+ if (!NIL_P(protocol)) {
+ hints.ai_protocol = NUM2INT(protocol);
+ }
+ if (!NIL_P(flags)) {
+ hints.ai_flags = NUM2INT(flags);
+ }
+
+ res = rsock_getaddrinfo(node, service, &hints, socktype_hack, timeout);
+
+ if (res == NULL)
+ rb_raise(rb_eSocket, "host not found");
+ return res;
+}
+
+static VALUE make_inspectname(VALUE node, VALUE service, struct addrinfo *res);
+
+static void
+init_addrinfo_getaddrinfo(VALUE self, rb_addrinfo_t *rai, VALUE node, VALUE service,
+ VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
+ VALUE inspectnode, VALUE inspectservice)
+{
+ struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 1, Qnil);
+ VALUE canonname;
+ VALUE inspectname = rb_str_equal(node, inspectnode) ? Qnil : make_inspectname(inspectnode, inspectservice, res->ai);
+
+ canonname = Qnil;
+ if (res->ai->ai_canonname) {
+ canonname = rb_str_new_cstr(res->ai->ai_canonname);
+ OBJ_FREEZE(canonname);
+ }
+
+ init_addrinfo(self, rai, res->ai->ai_addr, res->ai->ai_addrlen,
+ NUM2INT(family), NUM2INT(socktype), NUM2INT(protocol),
+ canonname, inspectname);
+
+ rb_freeaddrinfo(res);
+}
+
+static VALUE
+make_inspectname(VALUE node, VALUE service, struct addrinfo *res)
+{
+ VALUE inspectname = Qnil;
+
+ if (res) {
+ /* drop redundant information which also shown in address:port part. */
+ char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
+ int ret;
+ ret = rb_getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
+ sizeof(hbuf), pbuf, sizeof(pbuf),
+ NI_NUMERICHOST|NI_NUMERICSERV);
+ if (ret == 0) {
+ if (RB_TYPE_P(node, T_STRING) && strcmp(hbuf, RSTRING_PTR(node)) == 0)
+ node = Qnil;
+ if (RB_TYPE_P(service, T_STRING) && strcmp(pbuf, RSTRING_PTR(service)) == 0)
+ service = Qnil;
+ else if (RB_TYPE_P(service, T_FIXNUM) && atoi(pbuf) == FIX2INT(service))
+ service = Qnil;
+ }
+ }
+
+ if (RB_TYPE_P(node, T_STRING)) {
+ inspectname = rb_str_dup(node);
+ }
+ if (RB_TYPE_P(service, T_STRING)) {
+ if (NIL_P(inspectname))
+ inspectname = rb_sprintf(":%s", StringValueCStr(service));
+ else
+ rb_str_catf(inspectname, ":%s", StringValueCStr(service));
+ }
+ else if (RB_TYPE_P(service, T_FIXNUM) && FIX2INT(service) != 0)
+ {
+ if (NIL_P(inspectname))
+ inspectname = rb_sprintf(":%d", FIX2INT(service));
+ else
+ rb_str_catf(inspectname, ":%d", FIX2INT(service));
+ }
+ if (!NIL_P(inspectname)) {
+ OBJ_FREEZE(inspectname);
+ }
+ return inspectname;
+}
+
+static VALUE
+addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags)
+{
+ VALUE ret;
+ VALUE canonname;
+ VALUE inspectname;
+
+ struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0, Qnil);
+
+ inspectname = make_inspectname(node, service, res->ai);
+
+ canonname = Qnil;
+ if (res->ai->ai_canonname) {
+ canonname = rb_str_new_cstr(res->ai->ai_canonname);
+ OBJ_FREEZE(canonname);
+ }
+
+ ret = rsock_addrinfo_new(res->ai->ai_addr, res->ai->ai_addrlen,
+ res->ai->ai_family, res->ai->ai_socktype,
+ res->ai->ai_protocol,
+ canonname, inspectname);
+
+ rb_freeaddrinfo(res);
+ return ret;
+}
+
+static VALUE
+addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags, VALUE timeout)
+{
+ VALUE ret;
+ struct addrinfo *r;
+ VALUE inspectname;
+
+ struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0, timeout);
+
+ inspectname = make_inspectname(node, service, res->ai);
+
+ ret = rb_ary_new();
+ for (r = res->ai; r; r = r->ai_next) {
+ VALUE addr;
+ VALUE canonname = Qnil;
+
+ if (r->ai_canonname) {
+ canonname = rb_str_new_cstr(r->ai_canonname);
+ OBJ_FREEZE(canonname);
+ }
+
+ addr = rsock_addrinfo_new(r->ai_addr, r->ai_addrlen,
+ r->ai_family, r->ai_socktype, r->ai_protocol,
+ canonname, inspectname);
+
+ rb_ary_push(ret, addr);
+ }
+
+ rb_freeaddrinfo(res);
+ return ret;
+}
+
+
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+static void
+init_unix_addrinfo(VALUE self, rb_addrinfo_t *rai, VALUE path, int socktype)
+{
+ struct sockaddr_un un;
+ socklen_t len;
+
+ StringValue(path);
+
+ if (sizeof(un.sun_path) < (size_t)RSTRING_LEN(path))
+ rb_raise(rb_eArgError,
+ "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
+ (size_t)RSTRING_LEN(path), sizeof(un.sun_path));
+
+ INIT_SOCKADDR_UN(&un, sizeof(struct sockaddr_un));
+ memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
+
+ len = rsock_unix_sockaddr_len(path);
+ init_addrinfo(self, rai, (struct sockaddr *)&un, len,
+ PF_UNIX, socktype, 0, Qnil, Qnil);
+}
+
+static long
+rai_unixsocket_len(const rb_addrinfo_t *rai)
+{
+ return unixsocket_len(&rai->addr.un, rai->sockaddr_len);
+}
+#endif
+
+/*
+ * call-seq:
+ * Addrinfo.new(sockaddr) => addrinfo
+ * Addrinfo.new(sockaddr, family) => addrinfo
+ * Addrinfo.new(sockaddr, family, socktype) => addrinfo
+ * Addrinfo.new(sockaddr, family, socktype, protocol) => addrinfo
+ *
+ * returns a new instance of Addrinfo.
+ * The instance contains sockaddr, family, socktype, protocol.
+ * sockaddr means struct sockaddr which can be used for connect(2), etc.
+ * family, socktype and protocol are integers which is used for arguments of socket(2).
+ *
+ * sockaddr is specified as an array or a string.
+ * The array should be compatible to the value of IPSocket#addr or UNIXSocket#addr.
+ * The string should be struct sockaddr as generated by
+ * Socket.sockaddr_in or Socket.unpack_sockaddr_un.
+ *
+ * sockaddr examples:
+ * - <code>["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"]</code>
+ * - <code>["AF_INET6", 42304, "ip6-localhost", "::1"]</code>
+ * - <code>["AF_UNIX", "/tmp/sock"]</code>
+ * - <code>Socket.sockaddr_in("smtp", "2001:DB8::1")</code>
+ * - <code>Socket.sockaddr_in(80, "172.18.22.42")</code>
+ * - <code>Socket.sockaddr_in(80, "www.ruby-lang.org")</code>
+ * - <code>Socket.sockaddr_un("/tmp/sock")</code>
+ *
+ * In an AF_INET/AF_INET6 sockaddr array, the 4th element,
+ * numeric IP address, is used to construct socket address in the Addrinfo instance.
+ * If the 3rd element, textual host name, is non-nil, it is also recorded but used only for Addrinfo#inspect.
+ *
+ * family is specified as an integer to specify the protocol family such as Socket::PF_INET.
+ * It can be a symbol or a string which is the constant name
+ * with or without PF_ prefix such as :INET, :INET6, :UNIX, "PF_INET", etc.
+ * If omitted, PF_UNSPEC is assumed.
+ *
+ * socktype is specified as an integer to specify the socket type such as Socket::SOCK_STREAM.
+ * It can be a symbol or a string which is the constant name
+ * with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW, "SOCK_STREAM", etc.
+ * If omitted, 0 is assumed.
+ *
+ * protocol is specified as an integer to specify the protocol such as Socket::IPPROTO_TCP.
+ * It must be an integer, unlike family and socktype.
+ * If omitted, 0 is assumed.
+ * Note that 0 is reasonable value for most protocols, except raw socket.
+ *
+ */
+static VALUE
+addrinfo_initialize(int argc, VALUE *argv, VALUE self)
+{
+ rb_addrinfo_t *rai;
+ VALUE sockaddr_arg, sockaddr_ary, pfamily, socktype, protocol;
+ int i_pfamily, i_socktype, i_protocol;
+ struct sockaddr *sockaddr_ptr;
+ socklen_t sockaddr_len;
+ VALUE canonname = Qnil, inspectname = Qnil;
+
+ if (check_addrinfo(self))
+ rb_raise(rb_eTypeError, "already initialized socket address");
+ DATA_PTR(self) = rai = alloc_addrinfo();
+
+ rb_scan_args(argc, argv, "13", &sockaddr_arg, &pfamily, &socktype, &protocol);
+
+ i_pfamily = NIL_P(pfamily) ? PF_UNSPEC : rsock_family_arg(pfamily);
+ i_socktype = NIL_P(socktype) ? 0 : rsock_socktype_arg(socktype);
+ i_protocol = NIL_P(protocol) ? 0 : NUM2INT(protocol);
+
+ sockaddr_ary = rb_check_array_type(sockaddr_arg);
+ if (!NIL_P(sockaddr_ary)) {
+ VALUE afamily = rb_ary_entry(sockaddr_ary, 0);
+ int af;
+ StringValue(afamily);
+ if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1)
+ rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily));
+ switch (af) {
+ case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */
+#ifdef INET6
+ case AF_INET6: /* ["AF_INET6", 42304, "ip6-localhost", "::1"] */
+#endif
+ {
+ VALUE service = rb_ary_entry(sockaddr_ary, 1);
+ VALUE nodename = rb_ary_entry(sockaddr_ary, 2);
+ VALUE numericnode = rb_ary_entry(sockaddr_ary, 3);
+ int flags;
+
+ service = INT2NUM(NUM2INT(service));
+ if (!NIL_P(nodename))
+ StringValue(nodename);
+ StringValue(numericnode);
+ flags = AI_NUMERICHOST;
+#ifdef AI_NUMERICSERV
+ flags |= AI_NUMERICSERV;
+#endif
+
+ init_addrinfo_getaddrinfo(self, rai, numericnode, service,
+ INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol),
+ INT2NUM(flags),
+ nodename, service);
+ break;
+ }
+
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */
+ {
+ VALUE path = rb_ary_entry(sockaddr_ary, 1);
+ StringValue(path);
+ init_unix_addrinfo(self, rai, path, SOCK_STREAM);
+ break;
+ }
+#endif
+
+ default:
+ rb_raise(rb_eSocket, "unexpected address family");
+ }
+ }
+ else {
+ StringValue(sockaddr_arg);
+ sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg);
+ sockaddr_len = RSTRING_SOCKLEN(sockaddr_arg);
+ init_addrinfo(self, rai, sockaddr_ptr, sockaddr_len,
+ i_pfamily, i_socktype, i_protocol,
+ canonname, inspectname);
+ }
+
+ return self;
+}
+
+static int
+get_afamily(const struct sockaddr *addr, socklen_t len)
+{
+ if ((socklen_t)((const char*)&addr->sa_family + sizeof(addr->sa_family) - (char*)addr) <= len)
+ return addr->sa_family;
+ else
+ return AF_UNSPEC;
+}
+
+static int
+ai_get_afamily(const rb_addrinfo_t *rai)
+{
+ return get_afamily(&rai->addr.addr, rai->sockaddr_len);
+}
+
+static VALUE
+inspect_sockaddr(VALUE addrinfo, VALUE ret)
+{
+ rb_addrinfo_t *rai = get_addrinfo(addrinfo);
+ union_sockaddr *sockaddr = &rai->addr;
+ socklen_t socklen = rai->sockaddr_len;
+ return rsock_inspect_sockaddr((struct sockaddr *)sockaddr, socklen, ret);
+}
+
+VALUE
+rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE ret)
+{
+ union_sockaddr *sockaddr = (union_sockaddr *)sockaddr_arg;
+ if (socklen == 0) {
+ rb_str_cat2(ret, "empty-sockaddr");
+ }
+ else if ((long)socklen < ((char*)&sockaddr->addr.sa_family + sizeof(sockaddr->addr.sa_family)) - (char*)sockaddr)
+ rb_str_cat2(ret, "too-short-sockaddr");
+ else {
+ switch (sockaddr->addr.sa_family) {
+ case AF_UNSPEC:
+ {
+ rb_str_cat2(ret, "UNSPEC");
+ break;
+ }
+
+ case AF_INET:
+ {
+ struct sockaddr_in *addr;
+ int port;
+ addr = &sockaddr->in;
+ if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+0+1) <= socklen)
+ rb_str_catf(ret, "%d", ((unsigned char*)&addr->sin_addr)[0]);
+ else
+ rb_str_cat2(ret, "?");
+ if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+1+1) <= socklen)
+ rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[1]);
+ else
+ rb_str_cat2(ret, ".?");
+ if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+2+1) <= socklen)
+ rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[2]);
+ else
+ rb_str_cat2(ret, ".?");
+ if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+3+1) <= socklen)
+ rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[3]);
+ else
+ rb_str_cat2(ret, ".?");
+
+ if ((socklen_t)(((char*)&addr->sin_port)-(char*)addr+(int)sizeof(addr->sin_port)) < socklen) {
+ port = ntohs(addr->sin_port);
+ if (port)
+ rb_str_catf(ret, ":%d", port);
+ }
+ else {
+ rb_str_cat2(ret, ":?");
+ }
+ if ((socklen_t)sizeof(struct sockaddr_in) != socklen)
+ rb_str_catf(ret, " (%d bytes for %d bytes sockaddr_in)",
+ (int)socklen,
+ (int)sizeof(struct sockaddr_in));
+ break;
+ }
+
+#ifdef AF_INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *addr;
+ char hbuf[1024];
+ int port;
+ int error;
+ if (socklen < (socklen_t)sizeof(struct sockaddr_in6)) {
+ rb_str_catf(ret, "too-short-AF_INET6-sockaddr %d bytes", (int)socklen);
+ }
+ else {
+ addr = &sockaddr->in6;
+ /* use getnameinfo for scope_id.
+ * RFC 4007: IPv6 Scoped Address Architecture
+ * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API
+ */
+ error = rb_getnameinfo(&sockaddr->addr, socklen,
+ hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
+ NI_NUMERICHOST|NI_NUMERICSERV);
+ if (error) {
+ rsock_raise_resolution_error("getnameinfo", error);
+ }
+ if (addr->sin6_port == 0) {
+ rb_str_cat2(ret, hbuf);
+ }
+ else {
+ port = ntohs(addr->sin6_port);
+ rb_str_catf(ret, "[%s]:%d", hbuf, port);
+ }
+ if ((socklen_t)sizeof(struct sockaddr_in6) < socklen)
+ rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(socklen - sizeof(struct sockaddr_in6)));
+ }
+ break;
+ }
+#endif
+
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ case AF_UNIX:
+ {
+ struct sockaddr_un *addr = &sockaddr->un;
+ char *p, *s, *e;
+ long len = unixsocket_len(addr, socklen);
+ s = addr->sun_path;
+ if (len < 0)
+ rb_str_cat2(ret, "too-short-AF_UNIX-sockaddr");
+ else if (len == 0)
+ rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr");
+ else {
+ int printable_only = 1;
+ e = s + len;
+ p = s;
+ while (p < e) {
+ printable_only = printable_only && ISPRINT(*p) && !ISSPACE(*p);
+ p++;
+ }
+ if (printable_only) { /* only printable, no space */
+ if (s[0] != '/') /* relative path */
+ rb_str_cat2(ret, "UNIX ");
+ rb_str_cat(ret, s, p - s);
+ }
+ else {
+ rb_str_cat2(ret, "UNIX");
+ while (s < e)
+ rb_str_catf(ret, ":%02x", (unsigned char)*s++);
+ }
+ }
+ break;
+ }
+#endif
+
+#if defined(AF_PACKET) && defined(__linux__)
+ /* GNU/Linux */
+ case AF_PACKET:
+ {
+ struct sockaddr_ll *addr;
+ const char *sep = "[";
+#define CATSEP do { rb_str_cat2(ret, sep); sep = " "; } while (0);
+
+ addr = (struct sockaddr_ll *)sockaddr;
+
+ rb_str_cat2(ret, "PACKET");
+
+ if (offsetof(struct sockaddr_ll, sll_protocol) + sizeof(addr->sll_protocol) <= (size_t)socklen) {
+ CATSEP;
+ rb_str_catf(ret, "protocol=%d", ntohs(addr->sll_protocol));
+ }
+ if (offsetof(struct sockaddr_ll, sll_ifindex) + sizeof(addr->sll_ifindex) <= (size_t)socklen) {
+ char buf[IFNAMSIZ];
+ CATSEP;
+ if (if_indextoname(addr->sll_ifindex, buf) == NULL)
+ rb_str_catf(ret, "ifindex=%d", addr->sll_ifindex);
+ else
+ rb_str_catf(ret, "%s", buf);
+ }
+ if (offsetof(struct sockaddr_ll, sll_hatype) + sizeof(addr->sll_hatype) <= (size_t)socklen) {
+ CATSEP;
+ rb_str_catf(ret, "hatype=%d", addr->sll_hatype);
+ }
+ if (offsetof(struct sockaddr_ll, sll_pkttype) + sizeof(addr->sll_pkttype) <= (size_t)socklen) {
+ CATSEP;
+ if (addr->sll_pkttype == PACKET_HOST)
+ rb_str_cat2(ret, "HOST");
+ else if (addr->sll_pkttype == PACKET_BROADCAST)
+ rb_str_cat2(ret, "BROADCAST");
+ else if (addr->sll_pkttype == PACKET_MULTICAST)
+ rb_str_cat2(ret, "MULTICAST");
+ else if (addr->sll_pkttype == PACKET_OTHERHOST)
+ rb_str_cat2(ret, "OTHERHOST");
+ else if (addr->sll_pkttype == PACKET_OUTGOING)
+ rb_str_cat2(ret, "OUTGOING");
+ else
+ rb_str_catf(ret, "pkttype=%d", addr->sll_pkttype);
+ }
+ if (socklen != (socklen_t)(offsetof(struct sockaddr_ll, sll_addr) + addr->sll_halen)) {
+ CATSEP;
+ if (offsetof(struct sockaddr_ll, sll_halen) + sizeof(addr->sll_halen) <= (size_t)socklen) {
+ rb_str_catf(ret, "halen=%d", addr->sll_halen);
+ }
+ }
+ if (offsetof(struct sockaddr_ll, sll_addr) < (size_t)socklen) {
+ socklen_t len, i;
+ CATSEP;
+ rb_str_cat2(ret, "hwaddr");
+ len = addr->sll_halen;
+ if ((size_t)socklen < offsetof(struct sockaddr_ll, sll_addr) + len)
+ len = socklen - offsetof(struct sockaddr_ll, sll_addr);
+ for (i = 0; i < len; i++) {
+ rb_str_cat2(ret, i == 0 ? "=" : ":");
+ rb_str_catf(ret, "%02x", addr->sll_addr[i]);
+ }
+ }
+
+ if (socklen < (socklen_t)(offsetof(struct sockaddr_ll, sll_halen) + sizeof(addr->sll_halen)) ||
+ (socklen_t)(offsetof(struct sockaddr_ll, sll_addr) + addr->sll_halen) != socklen) {
+ CATSEP;
+ rb_str_catf(ret, "(%d bytes for %d bytes sockaddr_ll)",
+ (int)socklen, (int)sizeof(struct sockaddr_ll));
+ }
+
+ rb_str_cat2(ret, "]");
+#undef CATSEP
+
+ break;
+ }
+#endif
+
+#if defined(AF_LINK) && defined(HAVE_TYPE_STRUCT_SOCKADDR_DL)
+ /* AF_LINK is defined in 4.4BSD derivations since Net2.
+ link_ntoa is also defined at Net2.
+ However Debian GNU/kFreeBSD defines AF_LINK but
+ don't have link_ntoa. */
+ case AF_LINK:
+ {
+ /*
+ * Simple implementation using link_ntoa():
+ * This doesn't work on Debian GNU/kFreeBSD 6.0.7 (squeeze).
+ * Also, the format is bit different.
+ *
+ * rb_str_catf(ret, "LINK %s", link_ntoa(&sockaddr->dl));
+ * break;
+ */
+ struct sockaddr_dl *addr = &sockaddr->dl;
+ char *np = NULL, *ap = NULL, *endp;
+ int nlen = 0, alen = 0;
+ int i, off;
+ const char *sep = "[";
+#define CATSEP do { rb_str_cat2(ret, sep); sep = " "; } while (0);
+
+ rb_str_cat2(ret, "LINK");
+
+ endp = ((char *)addr) + socklen;
+
+ if (offsetof(struct sockaddr_dl, sdl_data) < socklen) {
+ np = addr->sdl_data;
+ nlen = addr->sdl_nlen;
+ if (endp - np < nlen)
+ nlen = (int)(endp - np);
+ }
+ off = addr->sdl_nlen;
+
+ if (offsetof(struct sockaddr_dl, sdl_data) + off < socklen) {
+ ap = addr->sdl_data + off;
+ alen = addr->sdl_alen;
+ if (endp - ap < alen)
+ alen = (int)(endp - ap);
+ }
+
+ CATSEP;
+ if (np)
+ rb_str_catf(ret, "%.*s", nlen, np);
+ else
+ rb_str_cat2(ret, "?");
+
+ if (ap && 0 < alen) {
+ CATSEP;
+ for (i = 0; i < alen; i++)
+ rb_str_catf(ret, "%s%02x", i == 0 ? "" : ":", (unsigned char)ap[i]);
+ }
+
+ if (socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_nlen) + sizeof(addr->sdl_nlen)) ||
+ socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_alen) + sizeof(addr->sdl_alen)) ||
+ socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_slen) + sizeof(addr->sdl_slen)) ||
+ /* longer length is possible behavior because struct sockaddr_dl has "minimum work area, can be larger" as the last field.
+ * cf. Net2:/usr/src/sys/net/if_dl.h. */
+ socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_data) + addr->sdl_nlen + addr->sdl_alen + addr->sdl_slen)) {
+ CATSEP;
+ rb_str_catf(ret, "(%d bytes for %d bytes sockaddr_dl)",
+ (int)socklen, (int)sizeof(struct sockaddr_dl));
+ }
+
+ rb_str_cat2(ret, "]");
+#undef CATSEP
+ break;
+ }
+#endif
+
+ default:
+ {
+ ID id = rsock_intern_family(sockaddr->addr.sa_family);
+ if (id == 0)
+ rb_str_catf(ret, "unknown address family %d", sockaddr->addr.sa_family);
+ else
+ rb_str_catf(ret, "%s address format unknown", rb_id2name(id));
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * call-seq:
+ * addrinfo.inspect => string
+ *
+ * returns a string which shows addrinfo in human-readable form.
+ *
+ * Addrinfo.tcp("localhost", 80).inspect #=> "#<Addrinfo: 127.0.0.1:80 TCP (localhost)>"
+ * Addrinfo.unix("/tmp/sock").inspect #=> "#<Addrinfo: /tmp/sock SOCK_STREAM>"
+ *
+ */
+static VALUE
+addrinfo_inspect(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ int internet_p;
+ VALUE ret;
+
+ ret = rb_sprintf("#<%s: ", rb_obj_classname(self));
+
+ inspect_sockaddr(self, ret);
+
+ if (rai->pfamily && ai_get_afamily(rai) != rai->pfamily) {
+ ID id = rsock_intern_protocol_family(rai->pfamily);
+ if (id)
+ rb_str_catf(ret, " %s", rb_id2name(id));
+ else
+ rb_str_catf(ret, " PF_\?\?\?(%d)", rai->pfamily);
+ }
+
+ internet_p = rai->pfamily == PF_INET;
+#ifdef INET6
+ internet_p = internet_p || rai->pfamily == PF_INET6;
+#endif
+ if (internet_p && rai->socktype == SOCK_STREAM &&
+ (rai->protocol == 0 || rai->protocol == IPPROTO_TCP)) {
+ rb_str_cat2(ret, " TCP");
+ }
+ else if (internet_p && rai->socktype == SOCK_DGRAM &&
+ (rai->protocol == 0 || rai->protocol == IPPROTO_UDP)) {
+ rb_str_cat2(ret, " UDP");
+ }
+ else {
+ if (rai->socktype) {
+ ID id = rsock_intern_socktype(rai->socktype);
+ if (id)
+ rb_str_catf(ret, " %s", rb_id2name(id));
+ else
+ rb_str_catf(ret, " SOCK_\?\?\?(%d)", rai->socktype);
+ }
+
+ if (rai->protocol) {
+ if (internet_p) {
+ ID id = rsock_intern_ipproto(rai->protocol);
+ if (id)
+ rb_str_catf(ret, " %s", rb_id2name(id));
+ else
+ goto unknown_protocol;
+ }
+ else {
+ unknown_protocol:
+ rb_str_catf(ret, " UNKNOWN_PROTOCOL(%d)", rai->protocol);
+ }
+ }
+ }
+
+ if (!NIL_P(rai->canonname)) {
+ VALUE name = rai->canonname;
+ rb_str_catf(ret, " %s", StringValueCStr(name));
+ }
+
+ if (!NIL_P(rai->inspectname)) {
+ VALUE name = rai->inspectname;
+ rb_str_catf(ret, " (%s)", StringValueCStr(name));
+ }
+
+ rb_str_buf_cat2(ret, ">");
+ return ret;
+}
+
+/*
+ * call-seq:
+ * addrinfo.inspect_sockaddr => string
+ *
+ * returns a string which shows the sockaddr in _addrinfo_ with human-readable form.
+ *
+ * Addrinfo.tcp("localhost", 80).inspect_sockaddr #=> "127.0.0.1:80"
+ * Addrinfo.tcp("ip6-localhost", 80).inspect_sockaddr #=> "[::1]:80"
+ * Addrinfo.unix("/tmp/sock").inspect_sockaddr #=> "/tmp/sock"
+ *
+ */
+VALUE
+rsock_addrinfo_inspect_sockaddr(VALUE self)
+{
+ return inspect_sockaddr(self, rb_str_new("", 0));
+}
+
+/* :nodoc: */
+static VALUE
+addrinfo_mdump(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ VALUE sockaddr, afamily, pfamily, socktype, protocol, canonname, inspectname;
+ int afamily_int = ai_get_afamily(rai);
+ ID id;
+
+ id = rsock_intern_protocol_family(rai->pfamily);
+ if (id == 0)
+ rb_raise(rb_eSocket, "unknown protocol family: %d", rai->pfamily);
+ pfamily = rb_id2str(id);
+
+ if (rai->socktype == 0)
+ socktype = INT2FIX(0);
+ else {
+ id = rsock_intern_socktype(rai->socktype);
+ if (id == 0)
+ rb_raise(rb_eSocket, "unknown socktype: %d", rai->socktype);
+ socktype = rb_id2str(id);
+ }
+
+ if (rai->protocol == 0)
+ protocol = INT2FIX(0);
+ else if (IS_IP_FAMILY(afamily_int)) {
+ id = rsock_intern_ipproto(rai->protocol);
+ if (id == 0)
+ rb_raise(rb_eSocket, "unknown IP protocol: %d", rai->protocol);
+ protocol = rb_id2str(id);
+ }
+ else {
+ rb_raise(rb_eSocket, "unknown protocol: %d", rai->protocol);
+ }
+
+ canonname = rai->canonname;
+
+ inspectname = rai->inspectname;
+
+ id = rsock_intern_family(afamily_int);
+ if (id == 0)
+ rb_raise(rb_eSocket, "unknown address family: %d", afamily_int);
+ afamily = rb_id2str(id);
+
+ switch(afamily_int) {
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ case AF_UNIX:
+ {
+ sockaddr = rb_str_new(rai->addr.un.sun_path, rai_unixsocket_len(rai));
+ break;
+ }
+#endif
+
+ default:
+ {
+ char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
+ int error;
+ error = rb_getnameinfo(&rai->addr.addr, rai->sockaddr_len,
+ hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
+ NI_NUMERICHOST|NI_NUMERICSERV);
+ if (error) {
+ rsock_raise_resolution_error("getnameinfo", error);
+ }
+ sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf));
+ break;
+ }
+ }
+
+ return rb_ary_new3(7, afamily, sockaddr, pfamily, socktype, protocol, canonname, inspectname);
+}
+
+/* :nodoc: */
+static VALUE
+addrinfo_mload(VALUE self, VALUE ary)
+{
+ VALUE v;
+ VALUE canonname, inspectname;
+ int afamily, pfamily, socktype, protocol;
+ union_sockaddr ss;
+ socklen_t len;
+ rb_addrinfo_t *rai;
+
+ if (check_addrinfo(self))
+ rb_raise(rb_eTypeError, "already initialized socket address");
+
+ ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
+
+ v = rb_ary_entry(ary, 0);
+ StringValue(v);
+ if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &afamily) == -1)
+ rb_raise(rb_eTypeError, "unexpected address family");
+
+ v = rb_ary_entry(ary, 2);
+ StringValue(v);
+ if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &pfamily) == -1)
+ rb_raise(rb_eTypeError, "unexpected protocol family");
+
+ v = rb_ary_entry(ary, 3);
+ if (v == INT2FIX(0))
+ socktype = 0;
+ else {
+ StringValue(v);
+ if (rsock_socktype_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &socktype) == -1)
+ rb_raise(rb_eTypeError, "unexpected socktype");
+ }
+
+ v = rb_ary_entry(ary, 4);
+ if (v == INT2FIX(0))
+ protocol = 0;
+ else {
+ StringValue(v);
+ if (IS_IP_FAMILY(afamily)) {
+ if (rsock_ipproto_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &protocol) == -1)
+ rb_raise(rb_eTypeError, "unexpected protocol");
+ }
+ else {
+ rb_raise(rb_eTypeError, "unexpected protocol");
+ }
+ }
+
+ v = rb_ary_entry(ary, 5);
+ if (NIL_P(v))
+ canonname = Qnil;
+ else {
+ StringValue(v);
+ canonname = v;
+ }
+
+ v = rb_ary_entry(ary, 6);
+ if (NIL_P(v))
+ inspectname = Qnil;
+ else {
+ StringValue(v);
+ inspectname = v;
+ }
+
+ v = rb_ary_entry(ary, 1);
+ switch(afamily) {
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ case AF_UNIX:
+ {
+ struct sockaddr_un uaddr;
+ INIT_SOCKADDR_UN(&uaddr, sizeof(struct sockaddr_un));
+
+ StringValue(v);
+ if (sizeof(uaddr.sun_path) < (size_t)RSTRING_LEN(v))
+ rb_raise(rb_eSocket,
+ "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
+ (size_t)RSTRING_LEN(v), sizeof(uaddr.sun_path));
+ memcpy(uaddr.sun_path, RSTRING_PTR(v), RSTRING_LEN(v));
+ len = (socklen_t)sizeof(uaddr);
+ memcpy(&ss, &uaddr, len);
+ break;
+ }
+#endif
+
+ default:
+ {
+ VALUE pair = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
+ struct rb_addrinfo *res;
+ int flags = AI_NUMERICHOST;
+#ifdef AI_NUMERICSERV
+ flags |= AI_NUMERICSERV;
+#endif
+ res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1),
+ INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol),
+ INT2NUM(flags), 1, Qnil);
+
+ len = res->ai->ai_addrlen;
+ memcpy(&ss, res->ai->ai_addr, res->ai->ai_addrlen);
+ rb_freeaddrinfo(res);
+ break;
+ }
+ }
+
+ DATA_PTR(self) = rai = alloc_addrinfo();
+ init_addrinfo(self, rai, &ss.addr, len,
+ pfamily, socktype, protocol,
+ canonname, inspectname);
+ return self;
+}
+
+/*
+ * call-seq:
+ * addrinfo.afamily => integer
+ *
+ * returns the address family as an integer.
+ *
+ * Addrinfo.tcp("localhost", 80).afamily == Socket::AF_INET #=> true
+ *
+ */
+static VALUE
+addrinfo_afamily(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ return INT2NUM(ai_get_afamily(rai));
+}
+
+/*
+ * call-seq:
+ * addrinfo.pfamily => integer
+ *
+ * returns the protocol family as an integer.
+ *
+ * Addrinfo.tcp("localhost", 80).pfamily == Socket::PF_INET #=> true
+ *
+ */
+static VALUE
+addrinfo_pfamily(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ return INT2NUM(rai->pfamily);
+}
+
+/*
+ * call-seq:
+ * addrinfo.socktype => integer
+ *
+ * returns the socket type as an integer.
+ *
+ * Addrinfo.tcp("localhost", 80).socktype == Socket::SOCK_STREAM #=> true
+ *
+ */
+static VALUE
+addrinfo_socktype(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ return INT2NUM(rai->socktype);
+}
+
+/*
+ * call-seq:
+ * addrinfo.protocol => integer
+ *
+ * returns the socket type as an integer.
+ *
+ * Addrinfo.tcp("localhost", 80).protocol == Socket::IPPROTO_TCP #=> true
+ *
+ */
+static VALUE
+addrinfo_protocol(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ return INT2NUM(rai->protocol);
+}
+
+/*
+ * call-seq:
+ * addrinfo.to_sockaddr => string
+ * addrinfo.to_s => string
+ *
+ * returns the socket address as packed struct sockaddr string.
+ *
+ * Addrinfo.tcp("localhost", 80).to_sockaddr
+ * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
+ *
+ */
+static VALUE
+addrinfo_to_sockaddr(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ VALUE ret;
+ ret = rb_str_new((char*)&rai->addr, rai->sockaddr_len);
+ return ret;
+}
+
+/*
+ * call-seq:
+ * addrinfo.canonname => string or nil
+ *
+ * returns the canonical name as a string.
+ *
+ * nil is returned if no canonical name.
+ *
+ * The canonical name is set by Addrinfo.getaddrinfo when AI_CANONNAME is specified.
+ *
+ * list = Addrinfo.getaddrinfo("www.ruby-lang.org", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME)
+ * p list[0] #=> #<Addrinfo: 221.186.184.68:80 TCP carbon.ruby-lang.org (www.ruby-lang.org)>
+ * p list[0].canonname #=> "carbon.ruby-lang.org"
+ *
+ */
+static VALUE
+addrinfo_canonname(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ return rai->canonname;
+}
+
+/*
+ * call-seq:
+ * addrinfo.ip? => true or false
+ *
+ * returns true if addrinfo is internet (IPv4/IPv6) address.
+ * returns false otherwise.
+ *
+ * Addrinfo.tcp("127.0.0.1", 80).ip? #=> true
+ * Addrinfo.tcp("::1", 80).ip? #=> true
+ * Addrinfo.unix("/tmp/sock").ip? #=> false
+ *
+ */
+static VALUE
+addrinfo_ip_p(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ int family = ai_get_afamily(rai);
+ return IS_IP_FAMILY(family) ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * addrinfo.ipv4? => true or false
+ *
+ * returns true if addrinfo is IPv4 address.
+ * returns false otherwise.
+ *
+ * Addrinfo.tcp("127.0.0.1", 80).ipv4? #=> true
+ * Addrinfo.tcp("::1", 80).ipv4? #=> false
+ * Addrinfo.unix("/tmp/sock").ipv4? #=> false
+ *
+ */
+static VALUE
+addrinfo_ipv4_p(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ return ai_get_afamily(rai) == AF_INET ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * addrinfo.ipv6? => true or false
+ *
+ * returns true if addrinfo is IPv6 address.
+ * returns false otherwise.
+ *
+ * Addrinfo.tcp("127.0.0.1", 80).ipv6? #=> false
+ * Addrinfo.tcp("::1", 80).ipv6? #=> true
+ * Addrinfo.unix("/tmp/sock").ipv6? #=> false
+ *
+ */
+static VALUE
+addrinfo_ipv6_p(VALUE self)
+{
+#ifdef AF_INET6
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ return ai_get_afamily(rai) == AF_INET6 ? Qtrue : Qfalse;
+#else
+ return Qfalse;
+#endif
+}
+
+/*
+ * call-seq:
+ * addrinfo.unix? => true or false
+ *
+ * returns true if addrinfo is UNIX address.
+ * returns false otherwise.
+ *
+ * Addrinfo.tcp("127.0.0.1", 80).unix? #=> false
+ * Addrinfo.tcp("::1", 80).unix? #=> false
+ * Addrinfo.unix("/tmp/sock").unix? #=> true
+ *
+ */
+static VALUE
+addrinfo_unix_p(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+#ifdef AF_UNIX
+ return ai_get_afamily(rai) == AF_UNIX ? Qtrue : Qfalse;
+#else
+ return Qfalse;
+#endif
+}
+
+/*
+ * call-seq:
+ * addrinfo.getnameinfo => [nodename, service]
+ * addrinfo.getnameinfo(flags) => [nodename, service]
+ *
+ * returns nodename and service as a pair of strings.
+ * This converts struct sockaddr in addrinfo to textual representation.
+ *
+ * flags should be bitwise OR of Socket::NI_??? constants.
+ *
+ * Addrinfo.tcp("127.0.0.1", 80).getnameinfo #=> ["localhost", "www"]
+ *
+ * Addrinfo.tcp("127.0.0.1", 80).getnameinfo(Socket::NI_NUMERICSERV)
+ * #=> ["localhost", "80"]
+ */
+static VALUE
+addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ VALUE vflags;
+ char hbuf[1024], pbuf[1024];
+ int flags, error;
+
+ rb_scan_args(argc, argv, "01", &vflags);
+
+ flags = NIL_P(vflags) ? 0 : NUM2INT(vflags);
+
+ if (rai->socktype == SOCK_DGRAM)
+ flags |= NI_DGRAM;
+
+ error = rb_getnameinfo(&rai->addr.addr, rai->sockaddr_len,
+ hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
+ flags);
+ if (error) {
+ rsock_raise_resolution_error("getnameinfo", error);
+ }
+
+ return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
+}
+
+/*
+ * call-seq:
+ * addrinfo.ip_unpack => [addr, port]
+ *
+ * Returns the IP address and port number as 2-element array.
+ *
+ * Addrinfo.tcp("127.0.0.1", 80).ip_unpack #=> ["127.0.0.1", 80]
+ * Addrinfo.tcp("::1", 80).ip_unpack #=> ["::1", 80]
+ */
+static VALUE
+addrinfo_ip_unpack(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ int family = ai_get_afamily(rai);
+ VALUE vflags;
+ VALUE ret, portstr;
+
+ if (!IS_IP_FAMILY(family))
+ rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
+
+ vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV);
+ ret = addrinfo_getnameinfo(1, &vflags, self);
+ portstr = rb_ary_entry(ret, 1);
+ rb_ary_store(ret, 1, INT2NUM(atoi(StringValueCStr(portstr))));
+ return ret;
+}
+
+/*
+ * call-seq:
+ * addrinfo.ip_address => string
+ *
+ * Returns the IP address as a string.
+ *
+ * Addrinfo.tcp("127.0.0.1", 80).ip_address #=> "127.0.0.1"
+ * Addrinfo.tcp("::1", 80).ip_address #=> "::1"
+ */
+static VALUE
+addrinfo_ip_address(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ int family = ai_get_afamily(rai);
+ VALUE vflags;
+ VALUE ret;
+
+ if (!IS_IP_FAMILY(family))
+ rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
+
+ vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV);
+ ret = addrinfo_getnameinfo(1, &vflags, self);
+ return rb_ary_entry(ret, 0);
+}
+
+/*
+ * call-seq:
+ * addrinfo.ip_port => port
+ *
+ * Returns the port number as an integer.
+ *
+ * Addrinfo.tcp("127.0.0.1", 80).ip_port #=> 80
+ * Addrinfo.tcp("::1", 80).ip_port #=> 80
+ */
+static VALUE
+addrinfo_ip_port(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ int family = ai_get_afamily(rai);
+ int port;
+
+ if (!IS_IP_FAMILY(family)) {
+ bad_family:
+#ifdef AF_INET6
+ rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
+#else
+ rb_raise(rb_eSocket, "need IPv4 address");
+#endif
+ }
+
+ switch (family) {
+ case AF_INET:
+ if (rai->sockaddr_len != sizeof(struct sockaddr_in))
+ rb_raise(rb_eSocket, "unexpected sockaddr size for IPv4");
+ port = ntohs(rai->addr.in.sin_port);
+ break;
+
+#ifdef AF_INET6
+ case AF_INET6:
+ if (rai->sockaddr_len != sizeof(struct sockaddr_in6))
+ rb_raise(rb_eSocket, "unexpected sockaddr size for IPv6");
+ port = ntohs(rai->addr.in6.sin6_port);
+ break;
+#endif
+
+ default:
+ goto bad_family;
+ }
+
+ return INT2NUM(port);
+}
+
+static int
+extract_in_addr(VALUE self, uint32_t *addrp)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ int family = ai_get_afamily(rai);
+ if (family != AF_INET) return 0;
+ *addrp = ntohl(rai->addr.in.sin_addr.s_addr);
+ return 1;
+}
+
+/*
+ * Returns true for IPv4 private address (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv4_private_p(VALUE self)
+{
+ uint32_t a;
+ if (!extract_in_addr(self, &a)) return Qfalse;
+ if ((a & 0xff000000) == 0x0a000000 || /* 10.0.0.0/8 */
+ (a & 0xfff00000) == 0xac100000 || /* 172.16.0.0/12 */
+ (a & 0xffff0000) == 0xc0a80000) /* 192.168.0.0/16 */
+ return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv4 loopback address (127.0.0.0/8).
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv4_loopback_p(VALUE self)
+{
+ uint32_t a;
+ if (!extract_in_addr(self, &a)) return Qfalse;
+ if ((a & 0xff000000) == 0x7f000000) /* 127.0.0.0/8 */
+ return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv4 multicast address (224.0.0.0/4).
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv4_multicast_p(VALUE self)
+{
+ uint32_t a;
+ if (!extract_in_addr(self, &a)) return Qfalse;
+ if ((a & 0xf0000000) == 0xe0000000) /* 224.0.0.0/4 */
+ return Qtrue;
+ return Qfalse;
+}
+
+#ifdef INET6
+
+static struct in6_addr *
+extract_in6_addr(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ int family = ai_get_afamily(rai);
+ if (family != AF_INET6) return NULL;
+ return &rai->addr.in6.sin6_addr;
+}
+
+/*
+ * Returns true for IPv6 unspecified address (::).
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_unspecified_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_UNSPECIFIED(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv6 loopback address (::1).
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_loopback_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_LOOPBACK(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv6 multicast address (ff00::/8).
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_multicast_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_MULTICAST(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv6 link local address (fe80::/10).
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_linklocal_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_LINKLOCAL(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv6 site local address (fec0::/10).
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_sitelocal_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_SITELOCAL(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv6 unique local address (fc00::/7, RFC4193).
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_unique_local_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_UNIQUE_LOCAL(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv4-mapped IPv6 address (::ffff:0:0/80).
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_v4mapped_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_V4MAPPED(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv4-compatible IPv6 address (::/80).
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_v4compat_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_V4COMPAT(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv6 multicast node-local scope address.
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_mc_nodelocal_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_MC_NODELOCAL(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv6 multicast link-local scope address.
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_mc_linklocal_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_MC_LINKLOCAL(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv6 multicast site-local scope address.
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_mc_sitelocal_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_MC_SITELOCAL(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv6 multicast organization-local scope address.
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_mc_orglocal_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_MC_ORGLOCAL(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns true for IPv6 multicast global scope address.
+ * It returns false otherwise.
+ */
+static VALUE
+addrinfo_ipv6_mc_global_p(VALUE self)
+{
+ struct in6_addr *addr = extract_in6_addr(self);
+ if (addr && IN6_IS_ADDR_MC_GLOBAL(addr)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * Returns IPv4 address of IPv4 mapped/compatible IPv6 address.
+ * It returns nil if +self+ is not IPv4 mapped/compatible IPv6 address.
+ *
+ * Addrinfo.ip("::192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
+ * Addrinfo.ip("::ffff:192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
+ * Addrinfo.ip("::1").ipv6_to_ipv4 #=> nil
+ * Addrinfo.ip("192.0.2.3").ipv6_to_ipv4 #=> nil
+ * Addrinfo.unix("/tmp/sock").ipv6_to_ipv4 #=> nil
+ */
+static VALUE
+addrinfo_ipv6_to_ipv4(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ struct in6_addr *addr;
+ int family = ai_get_afamily(rai);
+ if (family != AF_INET6) return Qnil;
+ addr = &rai->addr.in6.sin6_addr;
+ if (IN6_IS_ADDR_V4MAPPED(addr) || IN6_IS_ADDR_V4COMPAT(addr)) {
+ struct sockaddr_in sin4;
+ INIT_SOCKADDR_IN(&sin4, sizeof(sin4));
+ memcpy(&sin4.sin_addr, (char*)addr + sizeof(*addr) - sizeof(sin4.sin_addr), sizeof(sin4.sin_addr));
+ return rsock_addrinfo_new((struct sockaddr *)&sin4, (socklen_t)sizeof(sin4),
+ PF_INET, rai->socktype, rai->protocol,
+ rai->canonname, rai->inspectname);
+ }
+ else {
+ return Qnil;
+ }
+}
+
+#endif
+
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+/*
+ * call-seq:
+ * addrinfo.unix_path => path
+ *
+ * Returns the socket path as a string.
+ *
+ * Addrinfo.unix("/tmp/sock").unix_path #=> "/tmp/sock"
+ */
+static VALUE
+addrinfo_unix_path(VALUE self)
+{
+ rb_addrinfo_t *rai = get_addrinfo(self);
+ int family = ai_get_afamily(rai);
+ struct sockaddr_un *addr;
+ long n;
+
+ if (family != AF_UNIX)
+ rb_raise(rb_eSocket, "need AF_UNIX address");
+
+ addr = &rai->addr.un;
+
+ n = rai_unixsocket_len(rai);
+ if (n < 0)
+ rb_raise(rb_eSocket, "too short AF_UNIX address: %"PRIuSIZE" bytes given for minimum %"PRIuSIZE" bytes.",
+ (size_t)rai->sockaddr_len, offsetof(struct sockaddr_un, sun_path));
+ if ((long)sizeof(addr->sun_path) < n)
+ rb_raise(rb_eSocket,
+ "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
+ (size_t)n, sizeof(addr->sun_path));
+ return rb_str_new(addr->sun_path, n);
+}
+#endif
+
+static ID id_timeout;
+
+/*
+ * call-seq:
+ * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags) => [addrinfo, ...]
+ * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol) => [addrinfo, ...]
+ * Addrinfo.getaddrinfo(nodename, service, family, socktype) => [addrinfo, ...]
+ * Addrinfo.getaddrinfo(nodename, service, family) => [addrinfo, ...]
+ * Addrinfo.getaddrinfo(nodename, service) => [addrinfo, ...]
+ *
+ * returns a list of addrinfo objects as an array.
+ *
+ * This method converts nodename (hostname) and service (port) to addrinfo.
+ * Since the conversion is not unique, the result is a list of addrinfo objects.
+ *
+ * nodename or service can be nil if no conversion intended.
+ *
+ * family, socktype and protocol are hint for preferred protocol.
+ * If the result will be used for a socket with SOCK_STREAM,
+ * SOCK_STREAM should be specified as socktype.
+ * If so, Addrinfo.getaddrinfo returns addrinfo list appropriate for SOCK_STREAM.
+ * If they are omitted or nil is given, the result is not restricted.
+ *
+ * Similarly, PF_INET6 as family restricts for IPv6.
+ *
+ * flags should be bitwise OR of Socket::AI_??? constants such as follows.
+ * Note that the exact list of the constants depends on OS.
+ *
+ * AI_PASSIVE Get address to use with bind()
+ * AI_CANONNAME Fill in the canonical name
+ * AI_NUMERICHOST Prevent host name resolution
+ * AI_NUMERICSERV Prevent service name resolution
+ * AI_V4MAPPED Accept IPv4-mapped IPv6 addresses
+ * AI_ALL Allow all addresses
+ * AI_ADDRCONFIG Accept only if any address is assigned
+ *
+ * Note that socktype should be specified whenever application knows the usage of the address.
+ * Some platform causes an error when socktype is omitted and servname is specified as an integer
+ * because some port numbers, 512 for example, are ambiguous without socktype.
+ *
+ * Addrinfo.getaddrinfo("www.kame.net", 80, nil, :STREAM)
+ * #=> [#<Addrinfo: 203.178.141.194:80 TCP (www.kame.net)>,
+ * # #<Addrinfo: [2001:200:dff:fff1:216:3eff:feb1:44d7]:80 TCP (www.kame.net)>]
+ *
+ */
+static VALUE
+addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self)
+{
+ VALUE node, service, family, socktype, protocol, flags, opts, timeout;
+
+ rb_scan_args(argc, argv, "24:", &node, &service, &family, &socktype,
+ &protocol, &flags, &opts);
+ rb_get_kwargs(opts, &id_timeout, 0, 1, &timeout);
+ if (timeout == Qundef) {
+ timeout = Qnil;
+ }
+
+ return addrinfo_list_new(node, service, family, socktype, protocol, flags, timeout);
+}
+
+/*
+ * call-seq:
+ * Addrinfo.ip(host) => addrinfo
+ *
+ * returns an addrinfo object for IP address.
+ *
+ * The port, socktype, protocol of the result is filled by zero.
+ * So, it is not appropriate to create a socket.
+ *
+ * Addrinfo.ip("localhost") #=> #<Addrinfo: 127.0.0.1 (localhost)>
+ */
+static VALUE
+addrinfo_s_ip(VALUE self, VALUE host)
+{
+ VALUE ret;
+ rb_addrinfo_t *rai;
+ ret = addrinfo_firstonly_new(host, Qnil,
+ INT2NUM(PF_UNSPEC), INT2FIX(0), INT2FIX(0), INT2FIX(0));
+ rai = get_addrinfo(ret);
+ rai->socktype = 0;
+ rai->protocol = 0;
+ return ret;
+}
+
+/*
+ * call-seq:
+ * Addrinfo.tcp(host, port) => addrinfo
+ *
+ * returns an addrinfo object for TCP address.
+ *
+ * Addrinfo.tcp("localhost", "smtp") #=> #<Addrinfo: 127.0.0.1:25 TCP (localhost:smtp)>
+ */
+static VALUE
+addrinfo_s_tcp(VALUE self, VALUE host, VALUE port)
+{
+ return addrinfo_firstonly_new(host, port,
+ INT2NUM(PF_UNSPEC), INT2NUM(SOCK_STREAM), INT2NUM(IPPROTO_TCP), INT2FIX(0));
+}
+
+/*
+ * call-seq:
+ * Addrinfo.udp(host, port) => addrinfo
+ *
+ * returns an addrinfo object for UDP address.
+ *
+ * Addrinfo.udp("localhost", "daytime") #=> #<Addrinfo: 127.0.0.1:13 UDP (localhost:daytime)>
+ */
+static VALUE
+addrinfo_s_udp(VALUE self, VALUE host, VALUE port)
+{
+ return addrinfo_firstonly_new(host, port,
+ INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0));
+}
+
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+
+/*
+ * call-seq:
+ * Addrinfo.unix(path [, socktype]) => addrinfo
+ *
+ * returns an addrinfo object for UNIX socket address.
+ *
+ * _socktype_ specifies the socket type.
+ * If it is omitted, :STREAM is used.
+ *
+ * Addrinfo.unix("/tmp/sock") #=> #<Addrinfo: /tmp/sock SOCK_STREAM>
+ * Addrinfo.unix("/tmp/sock", :DGRAM) #=> #<Addrinfo: /tmp/sock SOCK_DGRAM>
+ */
+static VALUE
+addrinfo_s_unix(int argc, VALUE *argv, VALUE self)
+{
+ VALUE path, vsocktype, addr;
+ int socktype;
+ rb_addrinfo_t *rai;
+
+ rb_scan_args(argc, argv, "11", &path, &vsocktype);
+
+ if (NIL_P(vsocktype))
+ socktype = SOCK_STREAM;
+ else
+ socktype = rsock_socktype_arg(vsocktype);
+
+ addr = addrinfo_s_allocate(rb_cAddrinfo);
+ DATA_PTR(addr) = rai = alloc_addrinfo();
+ init_unix_addrinfo(self, rai, path, socktype);
+ return addr;
+}
+
+#endif
+
+VALUE
+rsock_sockaddr_string_value(volatile VALUE *v)
+{
+ VALUE val = *v;
+ if (IS_ADDRINFO(val)) {
+ *v = addrinfo_to_sockaddr(val);
+ }
+ StringValue(*v);
+ return *v;
+}
+
+VALUE
+rsock_sockaddr_string_value_with_addrinfo(volatile VALUE *v, VALUE *rai_ret)
+{
+ VALUE val = *v;
+ *rai_ret = Qnil;
+ if (IS_ADDRINFO(val)) {
+ *v = addrinfo_to_sockaddr(val);
+ *rai_ret = val;
+ }
+ StringValue(*v);
+ return *v;
+}
+
+char *
+rsock_sockaddr_string_value_ptr(volatile VALUE *v)
+{
+ rsock_sockaddr_string_value(v);
+ return RSTRING_PTR(*v);
+}
+
+VALUE
+rb_check_sockaddr_string_type(VALUE val)
+{
+ if (IS_ADDRINFO(val))
+ return addrinfo_to_sockaddr(val);
+ return rb_check_string_type(val);
+}
+
+VALUE
+rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len)
+{
+ int family;
+ int socktype;
+ int ret;
+ socklen_t optlen = (socklen_t)sizeof(socktype);
+
+ /* assumes protocol family and address family are identical */
+ family = get_afamily(addr, len);
+
+ ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen);
+ if (ret == -1) {
+ rb_sys_fail("getsockopt(SO_TYPE)");
+ }
+
+ return rsock_addrinfo_new(addr, len, family, socktype, 0, Qnil, Qnil);
+}
+
+VALUE
+rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
+{
+ rb_io_t *fptr;
+
+ switch (TYPE(io)) {
+ case T_FIXNUM:
+ return rsock_fd_socket_addrinfo(FIX2INT(io), addr, len);
+
+ case T_BIGNUM:
+ return rsock_fd_socket_addrinfo(NUM2INT(io), addr, len);
+
+ case T_FILE:
+ GetOpenFile(io, fptr);
+ return rsock_fd_socket_addrinfo(fptr->fd, addr, len);
+
+ default:
+ rb_raise(rb_eTypeError, "neither IO nor file descriptor");
+ }
+
+ UNREACHABLE_RETURN(Qnil);
+}
+
+#if FAST_FALLBACK_INIT_INETSOCK_IMPL == 1
+
+void
+free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shared **shared)
+{
+ xfree((*shared)->node);
+ (*shared)->node = NULL;
+ xfree((*shared)->service);
+ (*shared)->service = NULL;
+ rb_nativethread_lock_destroy(&(*shared)->lock);
+ free(*shared);
+ *shared = NULL;
+}
+
+static void *
+do_fast_fallback_getaddrinfo(void *ptr)
+{
+ struct fast_fallback_getaddrinfo_entry *entry = (struct fast_fallback_getaddrinfo_entry *)ptr;
+ struct fast_fallback_getaddrinfo_shared *shared = entry->shared;
+ int err = 0, shared_need_free = 0;
+ struct addrinfo *ai = NULL;
+
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, SIGPIPE);
+ pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+ err = numeric_getaddrinfo(shared->node, shared->service, &entry->hints, &entry->ai);
+
+ if (err != 0) {
+ err = getaddrinfo(shared->node, shared->service, &entry->hints, &entry->ai);
+ #ifdef __linux__
+ /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and
+ * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420]
+ */
+ if (err == EAI_SYSTEM && errno == ENOENT)
+ err = EAI_NONAME;
+ #endif
+ }
+
+ /* for testing HEv2 */
+ if (entry->test_sleep_ms > 0) {
+ struct timespec sleep_ts;
+ sleep_ts.tv_sec = entry->test_sleep_ms / 1000;
+ sleep_ts.tv_nsec = (entry->test_sleep_ms % 1000) * 1000000L;
+ if (sleep_ts.tv_nsec >= 1000000000L) {
+ sleep_ts.tv_sec += sleep_ts.tv_nsec / 1000000000L;
+ sleep_ts.tv_nsec = sleep_ts.tv_nsec % 1000000000L;
+ }
+ nanosleep(&sleep_ts, NULL);
+ }
+ if (entry->test_ecode != 0) {
+ err = entry->test_ecode;
+ if (entry->ai) {
+ freeaddrinfo(entry->ai);
+ entry->ai = NULL;
+ }
+ }
+
+ rb_nativethread_lock_lock(&shared->lock);
+ {
+ entry->err = err;
+ const char notification = entry->family == AF_INET6 ?
+ IPV6_HOSTNAME_RESOLVED : IPV4_HOSTNAME_RESOLVED;
+
+ if (shared->notify != -1 && (write(shared->notify, &notification, 1)) < 0) {
+ entry->err = errno;
+ entry->has_syserr = true;
+ }
+ if (--(entry->refcount) == 0) {
+ ai = entry->ai;
+ entry->ai = NULL;
+ }
+ if (--(shared->refcount) == 0) shared_need_free = 1;
+ }
+ rb_nativethread_lock_unlock(&shared->lock);
+
+ if (ai) freeaddrinfo(ai);
+ if (shared_need_free && shared) {
+ free_fast_fallback_getaddrinfo_shared(&shared);
+ }
+
+ return 0;
+}
+
+void *
+fork_safe_do_fast_fallback_getaddrinfo(void *ptr)
+{
+ return rb_thread_prevent_fork(do_fast_fallback_getaddrinfo, ptr);
+}
+
+#endif
+
+/*
+ * Addrinfo class
+ */
+void
+rsock_init_addrinfo(void)
+{
+ id_timeout = rb_intern("timeout");
+
+ /*
+ * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This
+ * structure identifies an Internet host and a service.
+ */
+ rb_cAddrinfo = rb_define_class("Addrinfo", rb_cObject);
+ rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate);
+ rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1);
+ rb_define_method(rb_cAddrinfo, "inspect", addrinfo_inspect, 0);
+ rb_define_method(rb_cAddrinfo, "inspect_sockaddr", rsock_addrinfo_inspect_sockaddr, 0);
+ rb_define_singleton_method(rb_cAddrinfo, "getaddrinfo", addrinfo_s_getaddrinfo, -1);
+ rb_define_singleton_method(rb_cAddrinfo, "ip", addrinfo_s_ip, 1);
+ rb_define_singleton_method(rb_cAddrinfo, "tcp", addrinfo_s_tcp, 2);
+ rb_define_singleton_method(rb_cAddrinfo, "udp", addrinfo_s_udp, 2);
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1);
+#endif
+
+ rb_define_method(rb_cAddrinfo, "afamily", addrinfo_afamily, 0);
+ rb_define_method(rb_cAddrinfo, "pfamily", addrinfo_pfamily, 0);
+ rb_define_method(rb_cAddrinfo, "socktype", addrinfo_socktype, 0);
+ rb_define_method(rb_cAddrinfo, "protocol", addrinfo_protocol, 0);
+ rb_define_method(rb_cAddrinfo, "canonname", addrinfo_canonname, 0);
+
+ rb_define_method(rb_cAddrinfo, "ipv4?", addrinfo_ipv4_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6?", addrinfo_ipv6_p, 0);
+ rb_define_method(rb_cAddrinfo, "unix?", addrinfo_unix_p, 0);
+
+ rb_define_method(rb_cAddrinfo, "ip?", addrinfo_ip_p, 0);
+ rb_define_method(rb_cAddrinfo, "ip_unpack", addrinfo_ip_unpack, 0);
+ rb_define_method(rb_cAddrinfo, "ip_address", addrinfo_ip_address, 0);
+ rb_define_method(rb_cAddrinfo, "ip_port", addrinfo_ip_port, 0);
+
+ rb_define_method(rb_cAddrinfo, "ipv4_private?", addrinfo_ipv4_private_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv4_loopback?", addrinfo_ipv4_loopback_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv4_multicast?", addrinfo_ipv4_multicast_p, 0);
+
+#ifdef INET6
+ rb_define_method(rb_cAddrinfo, "ipv6_unspecified?", addrinfo_ipv6_unspecified_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6_loopback?", addrinfo_ipv6_loopback_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6_multicast?", addrinfo_ipv6_multicast_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6_linklocal?", addrinfo_ipv6_linklocal_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6_sitelocal?", addrinfo_ipv6_sitelocal_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6_unique_local?", addrinfo_ipv6_unique_local_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6_v4mapped?", addrinfo_ipv6_v4mapped_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6_v4compat?", addrinfo_ipv6_v4compat_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6_mc_nodelocal?", addrinfo_ipv6_mc_nodelocal_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6_mc_linklocal?", addrinfo_ipv6_mc_linklocal_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6_mc_sitelocal?", addrinfo_ipv6_mc_sitelocal_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6_mc_orglocal?", addrinfo_ipv6_mc_orglocal_p, 0);
+ rb_define_method(rb_cAddrinfo, "ipv6_mc_global?", addrinfo_ipv6_mc_global_p, 0);
+
+ rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0);
+#endif
+
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0);
+#endif
+
+ rb_define_method(rb_cAddrinfo, "to_sockaddr", addrinfo_to_sockaddr, 0);
+ rb_define_method(rb_cAddrinfo, "to_s", addrinfo_to_sockaddr, 0); /* compatibility for ruby before 1.9.2 */
+
+ rb_define_method(rb_cAddrinfo, "getnameinfo", addrinfo_getnameinfo, -1);
+
+ rb_define_method(rb_cAddrinfo, "marshal_dump", addrinfo_mdump, 0);
+ rb_define_method(rb_cAddrinfo, "marshal_load", addrinfo_mload, 1);
+}
diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h
new file mode 100644
index 0000000000..2ec3ab335a
--- /dev/null
+++ b/ext/socket/rubysocket.h
@@ -0,0 +1,514 @@
+#ifndef RUBY_SOCKET_H
+#define RUBY_SOCKET_H 1
+
+#include "ruby/config.h"
+#include RUBY_EXTCONF_H
+
+#if defined(__sun) || defined(_AIX)
+/* (Recent?) Solaris' <nfs/nfs.h> have conflicting definition of T_DATA. Let
+ * us honour system definition by undefining ours.
+ *
+ * See also [ruby-core:4261]
+ */
+# include "ruby/ruby.h"
+# undef T_DATA
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_UIO_H
+# include <sys/uio.h>
+#endif
+
+#ifdef HAVE_XTI_H
+# include <xti.h>
+#endif
+
+#ifdef _WIN32
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# include <mswsock.h>
+# include <iphlpapi.h>
+# if defined(_MSC_VER)
+# undef HAVE_TYPE_STRUCT_SOCKADDR_DL
+# endif
+#else
+# include <sys/socket.h>
+# include <netinet/in.h>
+# ifdef HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+# endif
+# ifdef HAVE_NETINET_TCP_H
+# include <netinet/tcp.h>
+# endif
+# ifdef HAVE_NETINET_TCP_FSM_H
+# include <netinet/tcp_fsm.h>
+# endif
+# ifdef HAVE_NETINET_UDP_H
+# include <netinet/udp.h>
+# endif
+# ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+# endif
+# include <netdb.h>
+#endif
+
+#ifdef HAVE_NETPACKET_PACKET_H
+# include <netpacket/packet.h>
+#endif
+
+#ifdef HAVE_NET_ETHERNET_H
+# include <net/ethernet.h>
+#endif
+
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+
+#ifdef HAVE_AFUNIX_H
+// Windows doesn't have sys/un.h, but it does have afunix.h just to be special:
+# include <afunix.h>
+#endif
+
+#if defined(HAVE_FCNTL)
+# ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# endif
+# ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+# endif
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
+# ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+# endif
+#endif
+
+#ifdef HAVE_IFADDRS_H
+# ifdef __HAIKU__
+# define _BSD_SOURCE
+# endif
+# include <ifaddrs.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+#endif
+
+#ifdef HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_UCRED_H
+# include <sys/ucred.h>
+#endif
+
+#ifdef HAVE_UCRED_H
+# include <ucred.h>
+#endif
+
+#ifdef HAVE_NET_IF_DL_H
+# include <net/if_dl.h>
+#endif
+
+#ifdef SOCKS5
+# include <socks.h>
+#endif
+
+#ifndef HAVE_GETADDRINFO
+# include "addrinfo.h"
+#endif
+
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/compilers.h"
+#include "internal/error.h"
+#include "internal/gc.h"
+#include "internal/io.h"
+#include "internal/thread.h"
+#include "internal/vm.h"
+#include "ruby/io.h"
+#include "ruby/ruby.h"
+#include "ruby/thread.h"
+#include "ruby/util.h"
+#include "sockport.h"
+#include "ruby/fiber/scheduler.h"
+
+#ifndef HAVE_TYPE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
+#ifdef NEED_IF_INDEXTONAME_DECL
+char *if_indextoname(unsigned int, char *);
+#endif
+#ifdef NEED_IF_NAMETOINDEX_DECL
+unsigned int if_nametoindex(const char *);
+#endif
+
+#define SOCKLEN_MAX \
+ (0 < (socklen_t)-1 ? \
+ ~(socklen_t)0 : \
+ (((((socklen_t)1) << (sizeof(socklen_t) * CHAR_BIT - 2)) - 1) * 2 + 1))
+
+#ifndef RSTRING_SOCKLEN
+# define RSTRING_SOCKLEN (socklen_t)RSTRING_LENINT
+#endif
+
+#ifndef EWOULDBLOCK
+# define EWOULDBLOCK EAGAIN
+#endif
+
+/*
+ * workaround for NetBSD, OpenBSD and etc.
+ * The problem is since 4.4BSD-Lite.
+ * FreeBSD fix the problem at FreeBSD 2.2.0.
+ * NetBSD fix the problem at NetBSD 3.0 by kern/29624.
+ * OpenBSD fix the problem at OpenBSD 3.8.
+ */
+#define pseudo_AF_FTIP pseudo_AF_RTIP
+
+
+#ifndef NI_MAXHOST
+# define NI_MAXHOST 1025
+#endif
+#ifndef NI_MAXSERV
+# define NI_MAXSERV 32
+#endif
+
+#ifdef AF_INET6
+# define IS_IP_FAMILY(af) ((af) == AF_INET || (af) == AF_INET6)
+#else
+# define IS_IP_FAMILY(af) ((af) == AF_INET)
+#endif
+
+#ifndef IN6_IS_ADDR_UNIQUE_LOCAL
+# define IN6_IS_ADDR_UNIQUE_LOCAL(a) (((a)->s6_addr[0] == 0xfc) || ((a)->s6_addr[0] == 0xfd))
+#endif
+
+#ifndef HAVE_TYPE_STRUCT_SOCKADDR_STORAGE
+/*
+ * RFC 2553: protocol-independent placeholder for socket addresses
+ */
+# define _SS_MAXSIZE 128
+# define _SS_ALIGNSIZE (sizeof(double))
+# define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(unsigned char) * 2)
+# define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(unsigned char) * 2 - \
+ _SS_PAD1SIZE - _SS_ALIGNSIZE)
+
+struct sockaddr_storage {
+# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ unsigned char ss_len; /* address length */
+ unsigned char ss_family; /* address family */
+# else
+ unsigned short ss_family;
+# endif
+ char __ss_pad1[_SS_PAD1SIZE];
+ double __ss_align; /* force desired structure storage alignment */
+ char __ss_pad2[_SS_PAD2SIZE];
+};
+#endif
+
+typedef union {
+ struct sockaddr addr;
+ struct sockaddr_in in;
+#ifdef AF_INET6
+ struct sockaddr_in6 in6;
+#endif
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ struct sockaddr_un un;
+#endif
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_DL
+ struct sockaddr_dl dl; /* AF_LINK */
+#endif
+ struct sockaddr_storage storage;
+ char place_holder[2048]; /* sockaddr_storage is not enough for Unix domain sockets on SunOS and Darwin. */
+} union_sockaddr;
+
+#ifdef __APPLE__
+/*
+ * CMSG_ macros are broken on 64bit darwin, because __DARWIN_ALIGN
+ * aligns up to __darwin_size_t which is 64bit, but CMSG_DATA is
+ * 32bit-aligned.
+ */
+# undef __DARWIN_ALIGNBYTES
+# define __DARWIN_ALIGNBYTES (sizeof(unsigned int) - 1)
+#endif
+
+#if defined(_AIX)
+# ifndef CMSG_SPACE
+# define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
+# endif
+# ifndef CMSG_LEN
+# define CMSG_LEN(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
+# endif
+#endif
+
+#define INET_CLIENT 0
+#define INET_SERVER 1
+#define INET_SOCKS 2
+
+extern int rsock_do_not_reverse_lookup;
+#define FMODE_NOREVLOOKUP 0x100
+
+/* common socket families only */
+#define FMODE_UNIX 0x00200000
+#define FMODE_INET 0x00400000
+#define FMODE_INET6 0x00800000
+#define FMODE_SOCK (FMODE_UNIX|FMODE_INET|FMODE_INET6)
+
+extern VALUE rb_cBasicSocket;
+extern VALUE rb_cIPSocket;
+extern VALUE rb_cTCPSocket;
+extern VALUE rb_cTCPServer;
+extern VALUE rb_cUDPSocket;
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+extern VALUE rb_cUNIXSocket;
+extern VALUE rb_cUNIXServer;
+#endif
+extern VALUE rb_cSocket;
+extern VALUE rb_cAddrinfo;
+extern VALUE rb_cSockOpt;
+
+extern VALUE rb_eSocket;
+extern VALUE rb_eResolution;
+
+#ifdef SOCKS
+extern VALUE rb_cSOCKSSocket;
+# ifndef SOCKS5
+void SOCKSinit(char *);
+int Rconnect(int, const struct sockaddr *, socklen_t);
+# endif
+#endif
+
+#include "constdefs.h"
+
+#define SockAddrStringValue(v) rsock_sockaddr_string_value(&(v))
+#define SockAddrStringValuePtr(v) rsock_sockaddr_string_value_ptr(&(v))
+#define SockAddrStringValueWithAddrinfo(v, rai_ret) rsock_sockaddr_string_value_with_addrinfo(&(v), &(rai_ret))
+VALUE rsock_sockaddr_string_value(volatile VALUE *);
+char *rsock_sockaddr_string_value_ptr(volatile VALUE *);
+VALUE rsock_sockaddr_string_value_with_addrinfo(volatile VALUE *v, VALUE *ai_ret);
+
+VALUE rb_check_sockaddr_string_type(VALUE);
+
+NORETURN(void rsock_raise_resolution_error(const char *, int));
+
+int rsock_family_arg(VALUE domain);
+int rsock_socktype_arg(VALUE type);
+int rsock_level_arg(int family, VALUE level);
+int rsock_optname_arg(int family, int level, VALUE optname);
+int rsock_cmsg_type_arg(int family, int level, VALUE type);
+int rsock_shutdown_how_arg(VALUE how);
+
+int rsock_getfamily(rb_io_t *fptr);
+
+struct rb_addrinfo {
+ struct addrinfo *ai;
+ int allocated_by_malloc;
+};
+void rb_freeaddrinfo(struct rb_addrinfo *ai);
+VALUE rsock_freeaddrinfo(VALUE arg);
+int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);
+int rsock_fd_family(int fd);
+struct rb_addrinfo *rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags, VALUE timeout);
+struct rb_addrinfo *rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout);
+
+VALUE rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len);
+VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len);
+
+VALUE rsock_addrinfo_new(struct sockaddr *addr, socklen_t len, int family, int socktype, int protocol, VALUE canonname, VALUE inspectname);
+VALUE rsock_addrinfo_inspect_sockaddr(VALUE rai);
+
+VALUE rsock_make_ipaddr(struct sockaddr *addr, socklen_t addrlen);
+VALUE rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup);
+VALUE rsock_make_hostent(VALUE host, struct rb_addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, socklen_t));
+VALUE rsock_inspect_sockaddr(struct sockaddr *addr, socklen_t socklen, VALUE ret);
+socklen_t rsock_sockaddr_len(struct sockaddr *addr);
+VALUE rsock_sockaddr_obj(struct sockaddr *addr, socklen_t len);
+
+int rsock_revlookup_flag(VALUE revlookup, int *norevlookup);
+
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+VALUE rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len);
+VALUE rsock_unixaddr(struct sockaddr_un *sockaddr, socklen_t len);
+socklen_t rsock_unix_sockaddr_len(VALUE path);
+#endif
+
+int rsock_socket(int domain, int type, int proto);
+int rsock_detect_cloexec(int fd);
+VALUE rsock_init_sock(VALUE sock, int fd);
+VALUE rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass);
+VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type, VALUE resolv_timeout, VALUE connect_timeout, VALUE open_timeout, VALUE fast_fallback, VALUE test_mode_settings);
+VALUE rsock_init_unixsock(VALUE sock, VALUE path, int server);
+
+struct rsock_send_arg {
+ int fd, flags;
+ VALUE mesg;
+ struct sockaddr *to;
+ socklen_t tolen;
+};
+
+VALUE rsock_sendto_blocking(void *data);
+VALUE rsock_send_blocking(void *data);
+VALUE rsock_bsock_send(int argc, VALUE *argv, VALUE sock);
+
+enum sock_recv_type {
+ RECV_RECV, /* BasicSocket#recv(no from) */
+ RECV_IP, /* IPSocket#recvfrom */
+ RECV_UNIX, /* UNIXSocket#recvfrom */
+ RECV_SOCKET /* Socket#recvfrom */
+};
+
+VALUE rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str,
+ VALUE ex, enum sock_recv_type from);
+VALUE rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from);
+
+int rsock_connect(VALUE self, const struct sockaddr *sockaddr, int len, int socks, VALUE timeout);
+
+VALUE rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len);
+VALUE rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr,
+ struct sockaddr *sockaddr, socklen_t *len);
+VALUE rsock_sock_listen(VALUE sock, VALUE log);
+
+VALUE rsock_sockopt_new(int family, int level, int optname, VALUE data);
+
+#if defined(HAVE_SENDMSG)
+VALUE rsock_bsock_sendmsg(VALUE sock, VALUE data, VALUE flags,
+ VALUE dest_sockaddr, VALUE controls);
+VALUE rsock_bsock_sendmsg_nonblock(VALUE sock, VALUE data, VALUE flags,
+ VALUE dest_sockaddr, VALUE controls, VALUE ex);
+#else
+#define rsock_bsock_sendmsg rb_f_notimplement
+#define rsock_bsock_sendmsg_nonblock rb_f_notimplement
+#endif
+
+#if defined(HAVE_RECVMSG)
+VALUE rsock_bsock_recvmsg(VALUE sock, VALUE dlen, VALUE clen, VALUE flags,
+ VALUE scm_rights);
+VALUE rsock_bsock_recvmsg_nonblock(VALUE sock, VALUE dlen, VALUE clen,
+ VALUE flags, VALUE scm_rights, VALUE ex);
+ssize_t rsock_recvmsg(int socket, struct msghdr *message, int flags);
+#else
+#define rsock_bsock_recvmsg rb_f_notimplement
+#define rsock_bsock_recvmsg_nonblock rb_f_notimplement
+#endif
+
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+void rsock_discard_cmsg_resource(struct msghdr *mh, int msg_peek_p);
+#endif
+
+char *raddrinfo_host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr);
+char *raddrinfo_port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr);
+
+#ifndef FAST_FALLBACK_INIT_INETSOCK_IMPL
+# if !defined(HAVE_PTHREAD_CREATE) || !defined(HAVE_PTHREAD_DETACH) || defined(__MINGW32__) || defined(__MINGW64__)
+# define FAST_FALLBACK_INIT_INETSOCK_IMPL 0
+# else
+# include "ruby/thread_native.h"
+# define FAST_FALLBACK_INIT_INETSOCK_IMPL 1
+# define IPV6_HOSTNAME_RESOLVED '1'
+# define IPV4_HOSTNAME_RESOLVED '2'
+# define SELECT_CANCELLED '3'
+
+struct fast_fallback_getaddrinfo_entry
+{
+ int family, err, refcount;
+ struct addrinfo hints;
+ struct addrinfo *ai;
+ struct fast_fallback_getaddrinfo_shared *shared;
+ int has_syserr;
+ long test_sleep_ms;
+ int test_ecode;
+};
+
+struct fast_fallback_getaddrinfo_shared
+{
+ int notify, refcount;
+ char *node, *service;
+ rb_nativethread_lock_t lock;
+ struct fast_fallback_getaddrinfo_entry getaddrinfo_entries[FLEX_ARY_LEN];
+};
+
+int raddrinfo_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg);
+void *fork_safe_do_fast_fallback_getaddrinfo(void *ptr);
+void free_fast_fallback_getaddrinfo_entry(struct fast_fallback_getaddrinfo_entry **entry);
+void free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shared **shared);
+# endif
+#endif
+
+NORETURN(void rsock_raise_user_specified_timeout(struct addrinfo *ai, VALUE host, VALUE port));
+
+void rsock_init_basicsocket(void);
+void rsock_init_ipsocket(void);
+void rsock_init_tcpsocket(void);
+void rsock_init_tcpserver(void);
+void rsock_init_sockssocket(void);
+void rsock_init_udpsocket(void);
+void rsock_init_unixsocket(void);
+void rsock_init_unixserver(void);
+void rsock_init_socket_constants(void);
+void rsock_init_ancdata(void);
+void rsock_init_addrinfo(void);
+void rsock_init_sockopt(void);
+void rsock_init_sockifaddr(void);
+void rsock_init_socket_init(void);
+
+NORETURN(void rsock_syserr_fail_host_port(int err, const char *, VALUE, VALUE));
+NORETURN(void rsock_syserr_fail_path(int err, const char *, VALUE));
+NORETURN(void rsock_syserr_fail_sockaddr(int err, const char *mesg, struct sockaddr *addr, socklen_t len));
+NORETURN(void rsock_syserr_fail_raddrinfo(int err, const char *mesg, VALUE rai));
+NORETURN(void rsock_syserr_fail_raddrinfo_or_sockaddr(int err, const char *mesg, VALUE addr, VALUE rai));
+
+NORETURN(void rsock_sys_fail_host_port(const char *, VALUE, VALUE));
+NORETURN(void rsock_sys_fail_path(const char *, VALUE));
+NORETURN(void rsock_sys_fail_sockaddr(const char *, struct sockaddr *addr, socklen_t len));
+NORETURN(void rsock_sys_fail_raddrinfo(const char *, VALUE rai));
+NORETURN(void rsock_sys_fail_raddrinfo_or_sockaddr(const char *, VALUE addr, VALUE rai));
+
+#if defined(__MINGW32__) || defined(_WIN32)
+#define RSOCK_WAIT_BEFORE_BLOCKING
+#endif
+
+/*
+ * some OSes may support MSG_DONTWAIT inconsistently depending on socket
+ * type, we only expect Linux to support it consistently for all socket types.
+ */
+#if defined(MSG_DONTWAIT) && defined(__linux__)
+# define MSG_DONTWAIT_RELIABLE 1
+#else
+# define MSG_DONTWAIT_RELIABLE 0
+#endif
+
+VALUE rsock_read_nonblock(VALUE sock, VALUE length, VALUE buf, VALUE ex);
+VALUE rsock_write_nonblock(VALUE sock, VALUE buf, VALUE ex);
+
+void rsock_make_fd_nonblock(int fd);
+
+int rsock_is_dgram(rb_io_t *fptr);
+
+extern ID tcp_fast_fallback;
+
+#if !defined HAVE_INET_NTOP && ! defined _WIN32
+const char *inet_ntop(int, const void *, char *, size_t);
+#elif defined __MINGW32__
+# define inet_ntop(f,a,n,l) rb_w32_inet_ntop(f,a,n,l)
+#endif
+
+#endif
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index b4f44c9247..a8e5ae8119 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -2,2384 +2,310 @@
socket.c -
- $Author$
- $Date$
created at: Thu Mar 31 12:21:29 JST 1994
- Copyright (C) 1993-2001 Yukihiro Matsumoto
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
************************************************/
-#include "ruby.h"
-#include "rubyio.h"
-#include "rubysig.h"
-#include "util.h"
-#include <stdio.h>
-#include <sys/types.h>
+#include "rubysocket.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
-
-#ifndef _WIN32
-#if defined(__BEOS__)
-# include <net/socket.h>
-#else
-# include <sys/socket.h>
-# define pseudo_AF_FTIP pseudo_AF_RTIP /* workaround for NetBSD and etc. */
-#endif
-#include <netinet/in.h>
-#ifdef HAVE_NETINET_IN_SYSTM_H
-# include <netinet/in_systm.h>
-#endif
-#ifdef HAVE_NETINET_TCP_H
-# include <netinet/tcp.h>
-#endif
-#ifdef HAVE_NETINET_UDP_H
-# include <netinet/udp.h>
-#endif
-#include <netdb.h>
-#endif
-#include <errno.h>
-#ifdef HAVE_SYS_UN_H
-#include <sys/un.h>
-#endif
-
-#if defined(HAVE_FCNTL)
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#endif
-#ifndef EWOULDBLOCK
-#define EWOULDBLOCK EAGAIN
-#endif
-#ifndef HAVE_GETADDRINFO
-# include "addrinfo.h"
-#endif
-#include "sockport.h"
-
-#if defined(__vms)
-#include <tcp.h>
-#endif
-
-static int do_not_reverse_lookup = 0;
-
-VALUE rb_cBasicSocket;
-VALUE rb_cIPSocket;
-VALUE rb_cTCPSocket;
-VALUE rb_cTCPServer;
-VALUE rb_cUDPSocket;
-#ifdef AF_UNIX
-VALUE rb_cUNIXSocket;
-VALUE rb_cUNIXServer;
-#endif
-VALUE rb_cSocket;
-
-static VALUE rb_eSocket;
-
-#ifdef SOCKS
-VALUE rb_cSOCKSSocket;
-#ifdef SOCKS5
-#include <socks.h>
-#else
-void SOCKSinit();
-int Rconnect();
-#endif
-#endif
-
-#define INET_CLIENT 0
-#define INET_SERVER 1
-#define INET_SOCKS 2
-
-#ifndef HAVE_SOCKADDR_STORAGE
-/*
- * RFC 2553: protocol-independent placeholder for socket addresses
- */
-#define _SS_MAXSIZE 128
-#define _SS_ALIGNSIZE (sizeof(double))
-#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(unsigned char) * 2)
-#define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(unsigned char) * 2 - \
- _SS_PAD1SIZE - _SS_ALIGNSIZE)
-
-struct sockaddr_storage {
-#ifdef HAVE_SA_LEN
- unsigned char ss_len; /* address length */
- unsigned char ss_family; /* address family */
-#else
- unsigned short ss_family;
-#endif
- char __ss_pad1[_SS_PAD1SIZE];
- double __ss_align; /* force desired structure storage alignment */
- char __ss_pad2[_SS_PAD2SIZE];
-};
-#endif
-
-#if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6))
-#define LOOKUP_ORDERS 3
-static int lookup_order_table[LOOKUP_ORDERS] = {
-#if defined(LOOKUP_ORDER_HACK_INET)
- PF_INET, PF_INET6, PF_UNSPEC,
-#elif defined(LOOKUP_ORDER_HACK_INET6)
- PF_INET6, PF_INET, PF_UNSPEC,
-#else
- /* should not happen */
-#endif
-};
-
-static int
-ruby_getaddrinfo(nodename, servname, hints, res)
- char *nodename;
- char *servname;
- struct addrinfo *hints;
- struct addrinfo **res;
-{
- struct addrinfo tmp_hints;
- int i, af, error;
-
- if (hints->ai_family != PF_UNSPEC) {
- return getaddrinfo(nodename, servname, hints, res);
- }
+static VALUE sym_wait_writable;
- for (i = 0; i < LOOKUP_ORDERS; i++) {
- af = lookup_order_table[i];
- MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
- tmp_hints.ai_family = af;
- error = getaddrinfo(nodename, servname, &tmp_hints, res);
- if (error) {
- if (tmp_hints.ai_family == PF_UNSPEC) {
- break;
- }
- }
- else {
- break;
- }
- }
+static VALUE sock_s_unpack_sockaddr_in(VALUE, VALUE);
- return error;
-}
-#define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res))
-#endif
+ID tcp_fast_fallback;
-#if defined(_AIX)
-static int
-ruby_getaddrinfo__aix(nodename, servname, hints, res)
- char *nodename;
- char *servname;
- struct addrinfo *hints;
- struct addrinfo **res;
-{
- int error = getaddrinfo(nodename, servname, hints, res);
- struct addrinfo *r;
- if (error)
- return error;
- for (r = *res; r != NULL; r = r->ai_next) {
- if (r->ai_addr->sa_family == 0)
- r->ai_addr->sa_family = r->ai_family;
- if (r->ai_addr->sa_len == 0)
- r->ai_addr->sa_len = r->ai_addrlen;
- }
- return 0;
-}
-#undef getaddrinfo
-#define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res))
-#ifndef CMSG_SPACE
-# define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
-#endif
-#ifndef CMSG_LEN
-# define CMSG_LEN(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
-#endif
-#endif
-
-#ifdef HAVE_CLOSESOCKET
-#undef close
-#define close closesocket
-#endif
-
-static VALUE
-init_sock(sock, fd)
- VALUE sock;
- int fd;
+void
+rsock_sys_fail_host_port(const char *mesg, VALUE host, VALUE port)
{
- OpenFile *fp;
-
- MakeOpenFile(sock, fp);
- fp->f = rb_fdopen(fd, "r");
- fp->f2 = rb_fdopen(fd, "w");
- fp->mode = FMODE_READWRITE;
- rb_io_synchronized(fp);
-
- return sock;
+ rsock_syserr_fail_host_port(errno, mesg, host, port);
}
-static VALUE
-bsock_s_for_fd(klass, fd)
- VALUE klass, fd;
+void
+rsock_syserr_fail_host_port(int err, const char *mesg, VALUE host, VALUE port)
{
- OpenFile *fptr;
- VALUE sock = init_sock(rb_obj_alloc(klass), NUM2INT(fd));
-
- GetOpenFile(sock, fptr);
-
- return sock;
-}
+ VALUE message;
-static VALUE
-bsock_shutdown(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
-{
- VALUE howto;
- int how;
- OpenFile *fptr;
+ message = rb_sprintf("%s for %+"PRIsVALUE" port % "PRIsVALUE"",
+ mesg, host, port);
- if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
- rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
- }
- rb_scan_args(argc, argv, "01", &howto);
- if (howto == Qnil)
- how = 2;
- else {
- how = NUM2INT(howto);
- if (how < 0 || 2 < how) {
- rb_raise(rb_eArgError, "`how' should be either 0, 1, 2");
- }
+ if (err == ETIMEDOUT) {
+ rb_exc_raise(rb_exc_new3(rb_eIOTimeoutError, message));
}
- GetOpenFile(sock, fptr);
- if (shutdown(fileno(fptr->f), how) == -1)
- rb_sys_fail(0);
- return INT2FIX(0);
+ rb_syserr_fail_str(err, message);
}
-static VALUE
-bsock_close_read(sock)
- VALUE sock;
+void
+rsock_sys_fail_path(const char *mesg, VALUE path)
{
- OpenFile *fptr;
-
- if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
- rb_raise(rb_eSecurityError, "Insecure: can't close socket");
- }
- GetOpenFile(sock, fptr);
- shutdown(fileno(fptr->f), 0);
- if (!(fptr->mode & FMODE_WRITABLE)) {
- return rb_io_close(sock);
- }
- fptr->mode &= ~FMODE_READABLE;
-
- return Qnil;
+ rsock_syserr_fail_path(errno, mesg, path);
}
-static VALUE
-bsock_close_write(sock)
- VALUE sock;
+void
+rsock_syserr_fail_path(int err, const char *mesg, VALUE path)
{
- OpenFile *fptr;
+ VALUE message;
- if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
- rb_raise(rb_eSecurityError, "Insecure: can't close socket");
+ if (RB_TYPE_P(path, T_STRING)) {
+ message = rb_sprintf("%s for % "PRIsVALUE"", mesg, path);
+ rb_syserr_fail_str(err, message);
}
- GetOpenFile(sock, fptr);
- if (!(fptr->mode & FMODE_READABLE)) {
- return rb_io_close(sock);
+ else {
+ rb_syserr_fail(err, mesg);
}
- shutdown(fileno(fptr->f2), 1);
- fptr->mode &= ~FMODE_WRITABLE;
-
- return Qnil;
}
-/*
- * Document-method: setsockopt
- * call-seq: setsockopt(level, optname, optval)
- *
- * Sets a socket option. These are protocol and system specific, see your
- * local sytem documentation for details.
- *
- * === Parameters
- * * +level+ is an integer, usually one of the SOL_ constants such as
- * Socket::SOL_SOCKET, or a protocol level.
- * * +optname+ is an integer, usually one of the SO_ constants, such
- * as Socket::SO_REUSEADDR.
- * * +optval+ is the value of the option, it is passed to the underlying
- * setsockopt() as a pointer to a certain number of bytes. How this is
- * done depends on the type:
- * - Fixnum: value is assigned to an int, and a pointer to the int is
- * passed, with length of sizeof(int).
- * - true or false: 1 or 0 (respectively) is assigned to an int, and the
- * int is passed as for a Fixnum. Note that +false+ must be passed,
- * not +nil+.
- * - String: the string's data and length is passed to the socket.
- *
- * === Examples
- *
- * Some socket options are integers with boolean values, in this case
- * #setsockopt could be called like this:
- * sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
- *
- * Some socket options are integers with numeric values, in this case
- * #setsockopt could be called like this:
- * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
- *
- * Option values may be structs. Passing them can be complex as it involves
- * examining your system headers to determine the correct definition. An
- * example is an +ip_mreq+, which may be defined in your system headers as:
- * struct ip_mreq {
- * struct in_addr imr_multiaddr;
- * struct in_addr imr_interface;
- * };
- *
- * In this case #setsockopt could be called like this:
- * optval = IPAddr.new("224.0.0.251") + Socket::INADDR_ANY
- * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)
- *
-*/
-static VALUE
-bsock_setsockopt(sock, lev, optname, val)
- VALUE sock, lev, optname, val;
+void
+rsock_sys_fail_sockaddr(const char *mesg, struct sockaddr *addr, socklen_t len)
{
- int level, option;
- OpenFile *fptr;
- int i;
- char *v;
- int vlen;
-
- rb_secure(2);
- level = NUM2INT(lev);
- option = NUM2INT(optname);
-
- switch (TYPE(val)) {
- case T_FIXNUM:
- i = FIX2INT(val);
- goto numval;
- case T_FALSE:
- i = 0;
- goto numval;
- case T_TRUE:
- i = 1;
- numval:
- v = (char*)&i; vlen = sizeof(i);
- break;
- default:
- StringValue(val);
- v = RSTRING(val)->ptr;
- vlen = RSTRING(val)->len;
- break;
- }
-
- GetOpenFile(sock, fptr);
- if (setsockopt(fileno(fptr->f), level, option, v, vlen) < 0)
- rb_sys_fail(fptr->path);
-
- return INT2FIX(0);
+ rsock_syserr_fail_sockaddr(errno, mesg, addr, len);
}
-/*
- * Document-method: getsockopt
- * call-seq: getsockopt(level, optname)
- *
- * Gets a socket option. These are protocol and system specific, see your
- * local sytem documentation for details. The option is returned as
- * a String with the data being the binary value of the socket option.
- *
- * === Parameters
- * * +level+ is an integer, usually one of the SOL_ constants such as
- * Socket::SOL_SOCKET, or a protocol level.
- * * +optname+ is an integer, usually one of the SO_ constants, such
- * as Socket::SO_REUSEADDR.
- *
- * === Examples
- *
- * Some socket options are integers with boolean values, in this case
- * #getsockopt could be called like this:
- * optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR)
- * optval = optval.unpack "i"
- * reuseaddr = optval[0] == 0 ? false : true
- *
- * Some socket options are integers with numeric values, in this case
- * #getsockopt could be called like this:
- * optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
- * ipttl = optval.unpack("i")[0]
- *
- * Option values may be structs. Decoding them can be complex as it involves
- * examining your system headers to determine the correct definition. An
- * example is a +struct linger+, which may be defined in your system headers
- * as:
- * struct linger {
- * int l_onoff;
- * int l_linger;
- * };
- *
- * In this case #getsockopt could be called like this:
- * optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER)
- * onoff, linger = optval.unpack "ii"
-*/
-static VALUE
-bsock_getsockopt(sock, lev, optname)
- VALUE sock, lev, optname;
+void
+rsock_syserr_fail_sockaddr(int err, const char *mesg, struct sockaddr *addr, socklen_t len)
{
-#if !defined(__BEOS__)
- int level, option;
- socklen_t len;
- char *buf;
- OpenFile *fptr;
-
- level = NUM2INT(lev);
- option = NUM2INT(optname);
- len = 256;
- buf = ALLOCA_N(char,len);
- GetOpenFile(sock, fptr);
-
- GetOpenFile(sock, fptr);
- if (getsockopt(fileno(fptr->f), level, option, buf, &len) < 0)
- rb_sys_fail(fptr->path);
-
- return rb_str_new(buf, len);
-#else
- rb_notimplement();
-#endif
-}
+ VALUE rai;
-static VALUE
-bsock_getsockname(sock)
- VALUE sock;
-{
- char buf[1024];
- socklen_t len = sizeof buf;
- OpenFile *fptr;
+ rai = rsock_addrinfo_new(addr, len, PF_UNSPEC, 0, 0, Qnil, Qnil);
- GetOpenFile(sock, fptr);
- if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
- rb_sys_fail("getsockname(2)");
- return rb_str_new(buf, len);
+ rsock_syserr_fail_raddrinfo(err, mesg, rai);
}
-static VALUE
-bsock_getpeername(sock)
- VALUE sock;
+void
+rsock_sys_fail_raddrinfo(const char *mesg, VALUE rai)
{
- char buf[1024];
- socklen_t len = sizeof buf;
- OpenFile *fptr;
-
- GetOpenFile(sock, fptr);
- if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
- rb_sys_fail("getpeername(2)");
- return rb_str_new(buf, len);
+ rsock_syserr_fail_raddrinfo(errno, mesg, rai);
}
-static VALUE
-bsock_send(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
+void
+rsock_syserr_fail_raddrinfo(int err, const char *mesg, VALUE rai)
{
- VALUE mesg, to;
- VALUE flags;
- OpenFile *fptr;
- FILE *f;
- int fd, n;
+ VALUE str, message;
- rb_secure(4);
- rb_scan_args(argc, argv, "21", &mesg, &flags, &to);
+ str = rsock_addrinfo_inspect_sockaddr(rai);
+ message = rb_sprintf("%s for %"PRIsVALUE"", mesg, str);
- StringValue(mesg);
- if (!NIL_P(to)) StringValue(to);
- GetOpenFile(sock, fptr);
- f = GetWriteFile(fptr);
- fd = fileno(f);
- rb_thread_fd_writable(fd);
- retry:
- if (!NIL_P(to)) {
- TRAP_BEG;
- n = sendto(fd, RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags),
- (struct sockaddr*)RSTRING(to)->ptr, RSTRING(to)->len);
- TRAP_END;
- }
- else {
- TRAP_BEG;
- n = send(fd, RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags));
- TRAP_END;
- }
- if (n < 0) {
- if (rb_io_wait_writable(fd)) {
- goto retry;
- }
- rb_sys_fail("send(2)");
- }
- return INT2FIX(n);
+ rb_syserr_fail_str(err, message);
}
-static VALUE ipaddr _((struct sockaddr*));
-#ifdef HAVE_SYS_UN_H
-static VALUE unixaddr _((struct sockaddr_un*, socklen_t));
-#endif
-
-enum sock_recv_type {
- RECV_RECV, /* BasicSocket#recv(no from) */
- RECV_IP, /* IPSocket#recvfrom */
- RECV_UNIX, /* UNIXSocket#recvfrom */
- RECV_SOCKET /* Socket#recvfrom */
-};
-
-static VALUE
-s_recvfrom(sock, argc, argv, from)
- VALUE sock;
- int argc;
- VALUE *argv;
- enum sock_recv_type from;
+void
+rsock_sys_fail_raddrinfo_or_sockaddr(const char *mesg, VALUE addr, VALUE rai)
{
- OpenFile *fptr;
- VALUE str;
- char buf[1024];
- socklen_t alen = sizeof buf;
- VALUE len, flg;
- long buflen;
- long slen;
- int fd, flags;
-
- rb_scan_args(argc, argv, "11", &len, &flg);
-
- if (flg == Qnil) flags = 0;
- else flags = NUM2INT(flg);
- buflen = NUM2INT(len);
-
- GetOpenFile(sock, fptr);
- if (rb_read_pending(fptr->f)) {
- rb_raise(rb_eIOError, "recv for buffered IO");
- }
- fd = fileno(fptr->f);
-
- str = rb_tainted_str_new(0, buflen);
-
- retry:
- rb_str_locktmp(str);
- rb_thread_wait_fd(fd);
- TRAP_BEG;
- slen = recvfrom(fd, RSTRING(str)->ptr, buflen, flags, (struct sockaddr*)buf, &alen);
- TRAP_END;
- rb_str_unlocktmp(str);
-
- if (slen < 0) {
- if (rb_io_wait_readable(fd)) {
- goto retry;
- }
- rb_sys_fail("recvfrom(2)");
- }
- if (slen < RSTRING(str)->len) {
- RSTRING(str)->len = slen;
- RSTRING(str)->ptr[slen] = '\0';
- }
- rb_obj_taint(str);
- switch (from) {
- case RECV_RECV:
- return (VALUE)str;
- case RECV_IP:
-#if 0
- if (alen != sizeof(struct sockaddr_in)) {
- rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
- }
-#endif
- if (alen) /* OSX doesn't return a 'from' result from recvfrom for connection-oriented sockets */
- return rb_assoc_new(str, ipaddr((struct sockaddr*)buf));
- else
- return rb_assoc_new(str, Qnil);
-
-#ifdef HAVE_SYS_UN_H
- case RECV_UNIX:
- return rb_assoc_new(str, unixaddr((struct sockaddr_un*)buf, alen));
-#endif
- case RECV_SOCKET:
- return rb_assoc_new(str, rb_str_new(buf, alen));
- default:
- rb_bug("s_recvfrom called with bad value");
- }
+ rsock_syserr_fail_raddrinfo_or_sockaddr(errno, mesg, addr, rai);
}
-static VALUE
-s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
+void
+rsock_syserr_fail_raddrinfo_or_sockaddr(int err, const char *mesg, VALUE addr, VALUE rai)
{
- OpenFile *fptr;
- VALUE str;
- char buf[1024];
- socklen_t alen = sizeof buf;
- VALUE len, flg;
- long buflen;
- long slen;
- int fd, flags;
- VALUE addr = Qnil;
-
- rb_scan_args(argc, argv, "11", &len, &flg);
-
- if (flg == Qnil) flags = 0;
- else flags = NUM2INT(flg);
- buflen = NUM2INT(len);
-
-#ifdef MSG_DONTWAIT
- /* MSG_DONTWAIT avoids the race condition between fcntl and recvfrom.
- It is not portable, though. */
- flags |= MSG_DONTWAIT;
-#endif
+ if (NIL_P(rai)) {
+ StringValue(addr);
- GetOpenFile(sock, fptr);
- if (rb_read_pending(fptr->f)) {
- rb_raise(rb_eIOError, "recvfrom for buffered IO");
+ rsock_syserr_fail_sockaddr(err, mesg,
+ (struct sockaddr *)RSTRING_PTR(addr),
+ (socklen_t)RSTRING_LEN(addr)); /* overflow should be checked already */
}
- fd = fileno(fptr->f);
-
- str = rb_tainted_str_new(0, buflen);
-
- rb_io_check_closed(fptr);
- rb_io_set_nonblock(fptr);
- slen = recvfrom(fd, RSTRING(str)->ptr, buflen, flags, (struct sockaddr*)buf, &alen);
-
- if (slen < 0) {
- rb_sys_fail("recvfrom(2)");
- }
- if (slen < RSTRING(str)->len) {
- RSTRING(str)->len = slen;
- RSTRING(str)->ptr[slen] = '\0';
- }
- rb_obj_taint(str);
- switch (from) {
- case RECV_RECV:
- return str;
-
- case RECV_IP:
- if (alen) /* connection-oriented socket may not return a from result */
- addr = ipaddr((struct sockaddr*)buf);
- break;
-
- case RECV_SOCKET:
- addr = rb_str_new(buf, alen);
- break;
-
- default:
- rb_bug("s_recvfrom_nonblock called with bad value");
- }
- return rb_assoc_new(str, addr);
+ else
+ rsock_syserr_fail_raddrinfo(err, mesg, rai);
}
-static VALUE
-bsock_recv(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
+static void
+setup_domain_and_type(VALUE domain, int *dv, VALUE type, int *tv)
{
- return s_recvfrom(sock, argc, argv, RECV_RECV);
+ *dv = rsock_family_arg(domain);
+ *tv = rsock_socktype_arg(type);
}
/*
* call-seq:
- * basicsocket.recv_nonblock(maxlen) => mesg
- * basicsocket.recv_nonblock(maxlen, flags) => mesg
- *
- * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
- * O_NONBLOCK is set for the underlying file descriptor.
- * _flags_ is zero or more of the +MSG_+ options.
- * The result, _mesg_, is the data received.
+ * Socket.new(domain, socktype [, protocol]) => socket
*
- * When recvfrom(2) returns 0, Socket#recv_nonblock returns
- * an empty string as data.
- * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
- *
- * === Parameters
- * * +maxlen+ - the number of bytes to receive from the socket
- * * +flags+ - zero or more of the +MSG_+ options
- *
- * === Example
- * serv = TCPServer.new("127.0.0.1", 0)
- * af, port, host, addr = serv.addr
- * c = TCPSocket.new(addr, port)
- * s = serv.accept
- * c.send "aaa", 0
- * IO.select([s])
- * p s.recv_nonblock(10) #=> "aaa"
+ * Creates a new socket object.
*
- * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
- * to _recv_nonblock_ fails.
+ * _domain_ should be a communications domain such as: :INET, :INET6, :UNIX, etc.
*
- * BasicSocket#recv_nonblock may raise any error corresponding to recvfrom(2) failure,
- * including Errno::EAGAIN.
+ * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc.
*
- * === See
- * * Socket#recvfrom
+ * _protocol_ is optional and should be a protocol defined in the domain.
+ * If protocol is not given, 0 is used internally.
+ *
+ * Socket.new(:INET, :STREAM) # TCP socket
+ * Socket.new(:INET, :DGRAM) # UDP socket
+ * Socket.new(:UNIX, :STREAM) # UNIX stream socket
+ * Socket.new(:UNIX, :DGRAM) # UNIX datagram socket
*/
-
-static VALUE
-bsock_recv_nonblock(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
-{
- return s_recvfrom_nonblock(sock, argc, argv, RECV_RECV);
-}
-
static VALUE
-bsock_do_not_rev_lookup()
+sock_initialize(int argc, VALUE *argv, VALUE sock)
{
- return do_not_reverse_lookup?Qtrue:Qfalse;
-}
+ VALUE domain, type, protocol;
+ int fd;
+ int d, t;
-static VALUE
-bsock_do_not_rev_lookup_set(self, val)
- VALUE self, val;
-{
- rb_secure(4);
- do_not_reverse_lookup = RTEST(val);
- return val;
-}
+ rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
+ if (NIL_P(protocol))
+ protocol = INT2FIX(0);
-static void
-make_ipaddr0(addr, buf, len)
- struct sockaddr *addr;
- char *buf;
- size_t len;
-{
- int error;
+ setup_domain_and_type(domain, &d, type, &t);
+ fd = rsock_socket(d, t, NUM2INT(protocol));
+ if (fd < 0) rb_sys_fail("socket(2)");
- error = getnameinfo(addr, SA_LEN(addr), buf, len, NULL, 0, NI_NUMERICHOST);
- if (error) {
- rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
- }
+ return rsock_init_sock(sock, fd);
}
+#if defined HAVE_SOCKETPAIR
static VALUE
-make_ipaddr(addr)
- struct sockaddr *addr;
-{
- char buf[1024];
-
- make_ipaddr0(addr, buf, sizeof(buf));
- return rb_str_new2(buf);
-}
-
-static void
-make_inetaddr(host, buf, len)
- long host;
- char *buf;
- size_t len;
-{
- struct sockaddr_in sin;
-
- MEMZERO(&sin, struct sockaddr_in, 1);
- sin.sin_family = AF_INET;
- SET_SIN_LEN(&sin, sizeof(sin));
- sin.sin_addr.s_addr = host;
- make_ipaddr0((struct sockaddr*)&sin, buf, len);
-}
-
-static int
-str_isnumber(p)
- const char *p;
+io_call_close(VALUE io)
{
- char *ep;
-
- if (!p || *p == '\0')
- return 0;
- ep = NULL;
- (void)strtoul(p, &ep, 10);
- if (ep && *ep == '\0')
- return 1;
- else
- return 0;
-}
-
-static char *
-host_str(host, hbuf, len)
- VALUE host;
- char *hbuf;
- size_t len;
-{
- if (NIL_P(host)) {
- return NULL;
- }
- else if (rb_obj_is_kind_of(host, rb_cInteger)) {
- long i = NUM2LONG(host);
-
- make_inetaddr(htonl(i), hbuf, len);
- return hbuf;
- }
- else {
- char *name;
-
- SafeStringValue(host);
- name = RSTRING(host)->ptr;
- if (!name || *name == 0 || (name[0] == '<' && strcmp(name, "<any>") == 0)) {
- make_inetaddr(INADDR_ANY, hbuf, len);
- }
- else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
- make_inetaddr(INADDR_BROADCAST, hbuf, len);
- }
- else if (strlen(name) >= len) {
- rb_raise(rb_eArgError, "hostname too long (%d)", strlen(name));
- }
- else {
- strcpy(hbuf, name);
- }
- return hbuf;
- }
-}
-
-static char *
-port_str(port, pbuf, len)
- VALUE port;
- char *pbuf;
- size_t len;
-{
- if (NIL_P(port)) {
- return 0;
- }
- else if (FIXNUM_P(port)) {
- snprintf(pbuf, len, "%ld", FIX2LONG(port));
- return pbuf;
- }
- else {
- char *serv;
-
- SafeStringValue(port);
- serv = RSTRING(port)->ptr;
- if (strlen(serv) >= len) {
- rb_raise(rb_eArgError, "service name too long (%d)", strlen(serv));
- }
- strcpy(pbuf, serv);
- return pbuf;
- }
-}
-
-#ifndef NI_MAXHOST
-# define 1025
-#endif
-#ifndef NI_MAXSERV
-# define 32
-#endif
-
-static struct addrinfo*
-sock_addrinfo(host, port, socktype, flags)
- VALUE host, port;
- int socktype, flags;
-{
- struct addrinfo hints;
- struct addrinfo* res = NULL;
- char *hostp, *portp;
- int error;
- char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
-
- hostp = host_str(host, hbuf, sizeof(hbuf));
- portp = port_str(port, pbuf, sizeof(pbuf));
-
- if (socktype == 0 && flags == 0 && str_isnumber(portp)) {
- socktype = SOCK_DGRAM;
- }
-
- MEMZERO(&hints, struct addrinfo, 1);
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = socktype;
- hints.ai_flags = flags;
- error = getaddrinfo(hostp, portp, &hints, &res);
- if (error) {
- if (hostp && hostp[strlen(hostp)-1] == '\n') {
- rb_raise(rb_eSocket, "newline at the end of hostname");
- }
- rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
- }
-
-#if defined(__APPLE__) && defined(__MACH__)
- {
- struct addrinfo *r;
- r = res;
- while (r) {
- if (! r->ai_socktype) r->ai_socktype = hints.ai_socktype;
- if (! r->ai_protocol) {
- if (r->ai_socktype == SOCK_DGRAM) {
- r->ai_protocol = IPPROTO_UDP;
- } else if (r->ai_socktype == SOCK_STREAM) {
- r->ai_protocol = IPPROTO_TCP;
- }
- }
- r = r->ai_next;
- }
- }
-#endif
- return res;
+ return rb_funcallv(io, rb_intern("close"), 0, 0);
}
static VALUE
-ipaddr(sockaddr)
- struct sockaddr *sockaddr;
+io_close(VALUE io)
{
- VALUE family, port, addr1, addr2;
- VALUE ary;
- int error;
- char hbuf[1024], pbuf[1024];
-
- switch (sockaddr->sa_family) {
- case AF_UNSPEC:
- family = rb_str_new2("AF_UNSPEC");
- break;
- case AF_INET:
- family = rb_str_new2("AF_INET");
- break;
-#ifdef INET6
- case AF_INET6:
- family = rb_str_new2("AF_INET6");
- break;
-#endif
-#ifdef AF_LOCAL
- case AF_LOCAL:
- family = rb_str_new2("AF_LOCAL");
- break;
-#elif AF_UNIX
- case AF_UNIX:
- family = rb_str_new2("AF_UNIX");
- break;
-#endif
- default:
- sprintf(pbuf, "unknown:%d", sockaddr->sa_family);
- family = rb_str_new2(pbuf);
- break;
- }
- addr1 = Qnil;
- if (!do_not_reverse_lookup) {
- error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
- NULL, 0, 0);
- if (! error) {
- addr1 = rb_str_new2(hbuf);
- }
- }
- error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
- pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
- if (error) {
- rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
- }
- addr2 = rb_str_new2(hbuf);
- if (addr1 == Qnil) {
- addr1 = addr2;
- }
- port = INT2FIX(atoi(pbuf));
- ary = rb_ary_new3(4, family, port, addr1, addr2);
-
- return ary;
+ return rb_rescue(io_call_close, io, 0, 0);
}
-static int
-ruby_socket(domain, type, proto)
- int domain, type, proto;
-{
- int fd;
-
- fd = socket(domain, type, proto);
- if (fd < 0) {
- if (errno == EMFILE || errno == ENFILE) {
- rb_gc();
- fd = socket(domain, type, proto);
- }
- }
- return fd;
-}
-
-static int
-wait_connectable(fd)
- int fd;
+static VALUE
+pair_yield(VALUE pair)
{
- int sockerr;
- socklen_t sockerrlen;
- fd_set fds_w;
- fd_set fds_e;
-
- for (;;) {
- FD_ZERO(&fds_w);
- FD_ZERO(&fds_e);
-
- FD_SET(fd, &fds_w);
- FD_SET(fd, &fds_e);
-
- rb_thread_select(fd+1, 0, &fds_w, &fds_e, 0);
-
- if (FD_ISSET(fd, &fds_w)) {
- return 0;
- }
- else if (FD_ISSET(fd, &fds_e)) {
- sockerrlen = sizeof(sockerr);
- if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr,
- &sockerrlen) == 0) {
- if (sockerr == 0)
- continue; /* workaround for winsock */
- errno = sockerr;
- }
- return -1;
- }
- }
-
- return 0;
+ return rb_ensure(rb_yield, pair, io_close, rb_ary_entry(pair, 1));
}
-
-#ifdef __CYGWIN__
-#define WAIT_IN_PROGRESS 10
-#endif
-#ifdef __APPLE__
-#define WAIT_IN_PROGRESS 10
-#endif
-#ifdef __linux__
-/* returns correct error */
-#define WAIT_IN_PROGRESS 0
-#endif
-#ifndef WAIT_IN_PROGRESS
-/* BSD origin code apparently has a problem */
-#define WAIT_IN_PROGRESS 1
#endif
+#if defined HAVE_SOCKETPAIR
static int
-ruby_connect(fd, sockaddr, len, socks)
- int fd;
- struct sockaddr *sockaddr;
- int len;
- int socks;
+rsock_socketpair0(int domain, int type, int protocol, int descriptors[2])
{
- int status;
- int mode;
-#if WAIT_IN_PROGRESS > 0
- int wait_in_progress = -1;
- int sockerr, sockerrlen;
+#ifdef SOCK_CLOEXEC
+ type |= SOCK_CLOEXEC;
#endif
-#if defined(HAVE_FCNTL)
-# if defined(F_GETFL)
- mode = fcntl(fd, F_GETFL, 0);
-# else
- mode = 0;
-# endif
-
-#ifdef O_NDELAY
-# define NONBLOCKING O_NDELAY
-#else
-#ifdef O_NBIO
-# define NONBLOCKING O_NBIO
-#else
-# define NONBLOCKING O_NONBLOCK
-#endif
-#endif
-#ifdef SOCKS5
- if (!socks)
-#endif
- fcntl(fd, F_SETFL, mode|NONBLOCKING);
-#endif /* HAVE_FCNTL */
-
- for (;;) {
-#if defined(SOCKS) && !defined(SOCKS5)
- if (socks) {
- status = Rconnect(fd, sockaddr, len);
- }
- else
-#endif
- {
- status = connect(fd, sockaddr, len);
- }
- if (status < 0) {
- switch (errno) {
- case EAGAIN:
-#ifdef EINPROGRESS
- case EINPROGRESS:
-#endif
-#if WAIT_IN_PROGRESS > 0
- sockerrlen = sizeof(sockerr);
- status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
- if (status) break;
- if (sockerr) {
- status = -1;
- errno = sockerr;
- break;
- }
-#endif
-#ifdef EALREADY
- case EALREADY:
-#endif
-#if WAIT_IN_PROGRESS > 0
- wait_in_progress = WAIT_IN_PROGRESS;
-#endif
- status = wait_connectable(fd);
- if (status) {
- break;
- }
- errno = 0;
- continue;
-
-#if WAIT_IN_PROGRESS > 0
- case EINVAL:
- if (wait_in_progress-- > 0) {
- /*
- * connect() after EINPROGRESS returns EINVAL on
- * some platforms, need to check true error
- * status.
- */
- sockerrlen = sizeof(sockerr);
- status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
- if (!status && !sockerr) {
- struct timeval tv = {0, 100000};
- rb_thread_wait_for(tv);
- continue;
- }
- status = -1;
- errno = sockerr;
- }
- break;
+#ifdef SOCK_NONBLOCK
+ type |= SOCK_NONBLOCK;
#endif
-#ifdef EISCONN
- case EISCONN:
- status = 0;
- errno = 0;
- break;
-#endif
- default:
- break;
- }
- }
-#ifdef HAVE_FCNTL
- fcntl(fd, F_SETFL, mode);
-#endif
- return status;
- }
-}
-
-struct inetsock_arg
-{
- VALUE sock;
- struct {
- VALUE host, serv;
- struct addrinfo *res;
- } remote, local;
- int type;
- int fd;
-};
-
-static VALUE
-inetsock_cleanup(arg)
- struct inetsock_arg *arg;
-{
- if (arg->remote.res) {
- freeaddrinfo(arg->remote.res);
- arg->remote.res = 0;
- }
- if (arg->local.res) {
- freeaddrinfo(arg->local.res);
- arg->local.res = 0;
- }
- if (arg->fd >= 0) {
- close(arg->fd);
- }
- return Qnil;
-}
-
-static VALUE
-init_inetsock_internal(arg)
- struct inetsock_arg *arg;
-{
- int type = arg->type;
- struct addrinfo *res;
- int fd, status = 0;
- char *syscall;
-
- arg->remote.res = sock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM,
- (type == INET_SERVER) ? AI_PASSIVE : 0);
- /*
- * Maybe also accept a local address
- */
+ int result = socketpair(domain, type, protocol, descriptors);
- if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) {
- arg->local.res = sock_addrinfo(arg->local.host, arg->local.serv, SOCK_STREAM, 0);
- }
+ if (result == -1)
+ return -1;
- arg->fd = fd = -1;
- for (res = arg->remote.res; res; res = res->ai_next) {
- status = ruby_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
- syscall = "socket(2)";
- fd = status;
- if (fd < 0) {
- continue;
- }
- arg->fd = fd;
- if (type == INET_SERVER) {
-#if !defined(_WIN32) && !defined(__CYGWIN__)
- status = 1;
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (char*)&status, sizeof(status));
+#ifndef SOCK_CLOEXEC
+ rb_fd_fix_cloexec(descriptors[0]);
+ rb_fd_fix_cloexec(descriptors[1]);
#endif
- status = bind(fd, res->ai_addr, res->ai_addrlen);
- syscall = "bind(2)";
- }
- else {
- if (arg->local.res) {
- status = bind(fd, arg->local.res->ai_addr, arg->local.res->ai_addrlen);
- syscall = "bind(2)";
- }
-
- if (status >= 0) {
- status = ruby_connect(fd, res->ai_addr, res->ai_addrlen,
- (type == INET_SOCKS));
- syscall = "connect(2)";
- }
- }
-
- if (status < 0) {
- close(fd);
- arg->fd = fd = -1;
- continue;
- } else
- break;
- }
- if (status < 0) {
- rb_sys_fail(syscall);
- }
-
- arg->fd = -1;
-
- if (type == INET_SERVER)
- listen(fd, 5);
-
- /* create new instance */
- return init_sock(arg->sock, fd);
-}
-
-static VALUE
-init_inetsock(sock, remote_host, remote_serv, local_host, local_serv, type)
- VALUE sock, remote_host, remote_serv, local_host, local_serv;
- int type;
-{
- struct inetsock_arg arg;
- arg.sock = sock;
- arg.remote.host = remote_host;
- arg.remote.serv = remote_serv;
- arg.remote.res = 0;
- arg.local.host = local_host;
- arg.local.serv = local_serv;
- arg.local.res = 0;
- arg.type = type;
- arg.fd = -1;
- return rb_ensure(init_inetsock_internal, (VALUE)&arg,
- inetsock_cleanup, (VALUE)&arg);
-}
-
-static VALUE
-tcp_init(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
-{
- VALUE remote_host, remote_serv;
- VALUE local_host, local_serv;
-
- rb_scan_args(argc, argv, "22", &remote_host, &remote_serv,
- &local_host, &local_serv);
-
- return init_inetsock(sock, remote_host, remote_serv,
- local_host, local_serv, INET_CLIENT);
-}
-
-#ifdef SOCKS
-static VALUE
-socks_init(sock, host, serv)
- VALUE sock, host, serv;
-{
- static init = 0;
- if (init == 0) {
- SOCKSinit("ruby");
- init = 1;
- }
-
- return init_inetsock(sock, host, serv, Qnil, Qnil, INET_SOCKS);
-}
-
-#ifdef SOCKS5
-static VALUE
-socks_s_close(sock)
- VALUE sock;
-{
- OpenFile *fptr;
-
- if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
- rb_raise(rb_eSecurityError, "Insecure: can't close socket");
- }
- GetOpenFile(sock, fptr);
- shutdown(fileno(fptr->f), 2);
- shutdown(fileno(fptr->f2), 2);
- return rb_io_close(sock);
-}
-#endif
+#ifndef SOCK_NONBLOCK
+ rsock_make_fd_nonblock(descriptors[0]);
+ rsock_make_fd_nonblock(descriptors[1]);
#endif
-struct hostent_arg {
- VALUE host;
- struct addrinfo* addr;
- VALUE (*ipaddr)_((struct sockaddr*, size_t));
-};
-
-static VALUE
-make_hostent_internal(arg)
- struct hostent_arg *arg;
-{
- VALUE host = arg->host;
- struct addrinfo* addr = arg->addr;
- VALUE (*ipaddr)_((struct sockaddr*, size_t)) = arg->ipaddr;
-
- struct addrinfo *ai;
- struct hostent *h;
- VALUE ary, names;
- char **pch;
- const char* hostp;
- char hbuf[NI_MAXHOST];
-
- ary = rb_ary_new();
- if (addr->ai_canonname) {
- hostp = addr->ai_canonname;
- }
- else {
- hostp = host_str(host, hbuf, sizeof(hbuf));
- }
- rb_ary_push(ary, rb_str_new2(hostp));
-
- if (addr->ai_canonname && (h = gethostbyname(addr->ai_canonname))) {
- names = rb_ary_new();
- if (h->h_aliases != NULL) {
- for (pch = h->h_aliases; *pch; pch++) {
- rb_ary_push(names, rb_str_new2(*pch));
- }
- }
- }
- else {
- names = rb_ary_new2(0);
- }
- rb_ary_push(ary, names);
- rb_ary_push(ary, INT2NUM(addr->ai_family));
- for (ai = addr; ai; ai = ai->ai_next) {
- /* Pushing all addresses regardless of address family is not the
- * behaviour expected of gethostbyname(). All the addresses in struct
- * hostent->h_addr_list must be of the same family.
- */
- if(ai->ai_family == addr->ai_family) {
- rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen));
- }
- }
-
- return ary;
-}
-
-static VALUE
-make_hostent(host, addr, ipaddr)
- VALUE host;
- struct addrinfo* addr;
- VALUE (*ipaddr)_((struct sockaddr*, size_t));
-{
- struct hostent_arg arg;
-
- arg.host = host;
- arg.addr = addr;
- arg.ipaddr = ipaddr;
- return rb_ensure(make_hostent_internal, (VALUE)&arg,
- RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)addr);
-}
-
-VALUE
-tcp_sockaddr(addr, len)
- struct sockaddr *addr;
- size_t len;
-{
- return make_ipaddr(addr);
-}
-
-static VALUE
-tcp_s_gethostbyname(obj, host)
- VALUE obj, host;
-{
- rb_secure(3);
- return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), tcp_sockaddr);
+ return result;
}
-static VALUE
-tcp_svr_init(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
+static int
+rsock_socketpair(int domain, int type, int protocol, int descriptors[2])
{
- VALUE arg1, arg2;
+ int result;
- if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2)
- return init_inetsock(sock, arg1, arg2, Qnil, Qnil, INET_SERVER);
- else
- return init_inetsock(sock, Qnil, arg1, Qnil, Qnil, INET_SERVER);
-}
-
-static VALUE
-s_accept_nonblock(VALUE klass, OpenFile *fptr, struct sockaddr *sockaddr, socklen_t *len)
-{
- int fd2;
+ result = rsock_socketpair0(domain, type, protocol, descriptors);
- rb_secure(3);
- rb_io_set_nonblock(fptr);
- fd2 = accept(fileno(fptr->f), (struct sockaddr*)sockaddr, len);
- if (fd2 < 0) {
- rb_sys_fail("accept(2)");
+ if (result < 0 && rb_gc_for_fd(errno)) {
+ result = rsock_socketpair0(domain, type, protocol, descriptors);
}
- return init_sock(rb_obj_alloc(klass), fd2);
-}
-
-static VALUE
-s_accept(klass, fd, sockaddr, len)
- VALUE klass;
- int fd;
- struct sockaddr *sockaddr;
- socklen_t *len;
-{
- int fd2;
- int retry = 0;
- rb_secure(3);
- retry:
- rb_thread_wait_fd(fd);
-#if defined(_nec_ews)
- fd2 = accept(fd, sockaddr, len);
-#else
- TRAP_BEG;
- fd2 = accept(fd, sockaddr, len);
- TRAP_END;
-#endif
- if (fd2 < 0) {
- switch (errno) {
- case EMFILE:
- case ENFILE:
- if (retry) break;
- rb_gc();
- retry = 1;
- goto retry;
- case EWOULDBLOCK:
- break;
- default:
- if (!rb_io_wait_readable(fd)) break;
- retry = 0;
- goto retry;
- }
- rb_sys_fail(0);
- }
- if (!klass) return INT2NUM(fd2);
- return init_sock(rb_obj_alloc(klass), fd2);
-}
-
-static VALUE
-tcp_accept(sock)
- VALUE sock;
-{
- OpenFile *fptr;
- struct sockaddr_storage from;
- socklen_t fromlen;
-
- GetOpenFile(sock, fptr);
- fromlen = sizeof(from);
- return s_accept(rb_cTCPSocket, fileno(fptr->f),
- (struct sockaddr*)&from, &fromlen);
+ return result;
}
/*
* call-seq:
- * tcpserver.accept_nonblock => tcpsocket
- *
- * Accepts an incoming connection using accept(2) after
- * O_NONBLOCK is set for the underlying file descriptor.
- * It returns an accepted TCPSocket for the incoming connection.
- *
- * === Example
- * require 'socket'
- * serv = TCPServer.new(2202)
- * begin
- * sock = serv.accept_nonblock
- * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
- * IO.select([serv])
- * retry
- * end
- * # sock is an accepted socket.
- *
- * Refer to Socket#accept for the exceptions that may be thrown if the call
- * to TCPServer#accept_nonblock fails.
+ * Socket.pair(domain, type, protocol) => [socket1, socket2]
+ * Socket.socketpair(domain, type, protocol) => [socket1, socket2]
*
- * TCPServer#accept_nonblock may raise any error corresponding to accept(2) failure,
- * including Errno::EAGAIN.
- *
- * === See
- * * TCPServer#accept
- * * Socket#accept
- */
-static VALUE
-tcp_accept_nonblock(sock)
- VALUE sock;
-{
- OpenFile *fptr;
- struct sockaddr_storage from;
- socklen_t fromlen;
-
- GetOpenFile(sock, fptr);
- fromlen = sizeof(from);
- return s_accept_nonblock(rb_cTCPSocket, fptr,
- (struct sockaddr *)&from, &fromlen);
-}
-
-static VALUE
-tcp_sysaccept(sock)
- VALUE sock;
-{
- OpenFile *fptr;
- struct sockaddr_storage from;
- socklen_t fromlen;
-
- GetOpenFile(sock, fptr);
- fromlen = sizeof(from);
- return s_accept(0, fileno(fptr->f), (struct sockaddr*)&from, &fromlen);
-}
-
-#ifdef HAVE_SYS_UN_H
-struct unixsock_arg {
- struct sockaddr_un *sockaddr;
- int fd;
-};
-
-static VALUE
-unixsock_connect_internal(arg)
- struct unixsock_arg *arg;
-{
- return (VALUE)ruby_connect(arg->fd, arg->sockaddr, sizeof(*arg->sockaddr),
- 0);
-}
-
-static VALUE
-init_unixsock(sock, path, server)
- VALUE sock;
- VALUE path;
- int server;
-{
- struct sockaddr_un sockaddr;
- int fd, status;
- OpenFile *fptr;
-
- SafeStringValue(path);
- fd = ruby_socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0) {
- rb_sys_fail("socket(2)");
- }
-
- MEMZERO(&sockaddr, struct sockaddr_un, 1);
- sockaddr.sun_family = AF_UNIX;
- if (sizeof(sockaddr.sun_path) <= RSTRING(path)->len) {
- rb_raise(rb_eArgError, "too long unix socket path (max: %dbytes)",
- (int)sizeof(sockaddr.sun_path)-1);
- }
- strcpy(sockaddr.sun_path, StringValueCStr(path));
-
- if (server) {
- status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
- }
- else {
- int prot;
- struct unixsock_arg arg;
- arg.sockaddr = &sockaddr;
- arg.fd = fd;
- status = rb_protect(unixsock_connect_internal, (VALUE)&arg, &prot);
- if (prot) {
- close(fd);
- rb_jump_tag(prot);
- }
- }
-
- if (status < 0) {
- close(fd);
- rb_sys_fail(sockaddr.sun_path);
- }
-
- if (server) listen(fd, 5);
-
- init_sock(sock, fd);
- GetOpenFile(sock, fptr);
- if (server) {
- fptr->path = strdup(RSTRING(path)->ptr);
- }
-
- return sock;
-}
-#endif
-
-static VALUE
-ip_addr(sock)
- VALUE sock;
-{
- OpenFile *fptr;
- struct sockaddr_storage addr;
- socklen_t len = sizeof addr;
-
- GetOpenFile(sock, fptr);
-
- if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
- rb_sys_fail("getsockname(2)");
- return ipaddr((struct sockaddr*)&addr);
-}
-
-static VALUE
-ip_peeraddr(sock)
- VALUE sock;
-{
- OpenFile *fptr;
- struct sockaddr_storage addr;
- socklen_t len = sizeof addr;
-
- GetOpenFile(sock, fptr);
-
- if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
- rb_sys_fail("getpeername(2)");
- return ipaddr((struct sockaddr*)&addr);
-}
-
-static VALUE
-ip_recvfrom(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
-{
- return s_recvfrom(sock, argc, argv, RECV_IP);
-}
-
-static VALUE
-ip_s_getaddress(obj, host)
- VALUE obj, host;
-{
- struct sockaddr_storage addr;
- struct addrinfo *res = sock_addrinfo(host, Qnil, SOCK_STREAM, 0);
-
- /* just take the first one */
- memcpy(&addr, res->ai_addr, res->ai_addrlen);
- freeaddrinfo(res);
-
- return make_ipaddr((struct sockaddr*)&addr);
-}
-
-static VALUE
-udp_init(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
-{
- VALUE arg;
- int socktype = AF_INET;
- int fd;
-
- rb_secure(3);
- if (rb_scan_args(argc, argv, "01", &arg) == 1) {
- socktype = NUM2INT(arg);
- }
- fd = ruby_socket(socktype, SOCK_DGRAM, 0);
- if (fd < 0) {
- rb_sys_fail("socket(2) - udp");
- }
-
- return init_sock(sock, fd);
-}
-
-struct udp_arg
-{
- struct addrinfo *res;
- int fd;
-};
-
-static VALUE
-udp_connect_internal(arg)
- struct udp_arg *arg;
-{
- int fd = arg->fd;
- struct addrinfo *res;
-
- for (res = arg->res; res; res = res->ai_next) {
- if (ruby_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) {
- return Qtrue;
- }
- }
- return Qfalse;
-}
-
-static VALUE
-udp_connect(sock, host, port)
- VALUE sock, host, port;
-{
- OpenFile *fptr;
- struct udp_arg arg;
- VALUE ret;
-
- rb_secure(3);
- arg.res = sock_addrinfo(host, port, SOCK_DGRAM, 0);
- GetOpenFile(sock, fptr);
- arg.fd = fileno(fptr->f);
- ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
- RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)arg.res);
- if (!ret) rb_sys_fail("connect(2)");
- return INT2FIX(0);
-}
-
-static VALUE
-udp_bind(sock, host, port)
- VALUE sock, host, port;
-{
- OpenFile *fptr;
- struct addrinfo *res0, *res;
-
- rb_secure(3);
- res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0);
- GetOpenFile(sock, fptr);
- for (res = res0; res; res = res->ai_next) {
- if (bind(fileno(fptr->f), res->ai_addr, res->ai_addrlen) < 0) {
- continue;
- }
- freeaddrinfo(res0);
- return INT2FIX(0);
- }
- freeaddrinfo(res0);
- rb_sys_fail("bind(2)");
- return INT2FIX(0);
-}
-
-static VALUE
-udp_send(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
-{
- VALUE mesg, flags, host, port;
- OpenFile *fptr;
- FILE *f;
- int n;
- struct addrinfo *res0, *res;
-
- if (argc == 2 || argc == 3) {
- return bsock_send(argc, argv, sock);
- }
- rb_secure(4);
- rb_scan_args(argc, argv, "4", &mesg, &flags, &host, &port);
-
- StringValue(mesg);
- res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0);
- GetOpenFile(sock, fptr);
- f = GetWriteFile(fptr);
- for (res = res0; res; res = res->ai_next) {
- retry:
- n = sendto(fileno(f), RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags),
- res->ai_addr, res->ai_addrlen);
- if (n >= 0) {
- freeaddrinfo(res0);
- return INT2FIX(n);
- }
- if (rb_io_wait_writable(fileno(f))) {
- goto retry;
- }
- }
- freeaddrinfo(res0);
- rb_sys_fail("sendto(2)");
- return INT2FIX(n);
-}
-
-/*
- * call-seq:
- * udpsocket.recvfrom_nonblock(maxlen) => [mesg, sender_inet_addr]
- * udpsocket.recvfrom_nonblock(maxlen, flags) => [mesg, sender_inet_addr]
- *
- * Receives up to _maxlen_ bytes from +udpsocket+ using recvfrom(2) after
- * O_NONBLOCK is set for the underlying file descriptor.
- * _flags_ is zero or more of the +MSG_+ options.
- * The first element of the results, _mesg_, is the data received.
- * The second element, _sender_inet_addr_, is an array to represent the sender address.
+ * Creates a pair of sockets connected each other.
*
- * When recvfrom(2) returns 0,
- * Socket#recvfrom_nonblock returns an empty string as data.
- * It means an empty packet.
- *
- * === Parameters
- * * +maxlen+ - the number of bytes to receive from the socket
- * * +flags+ - zero or more of the +MSG_+ options
- *
- * === Example
- * require 'socket'
- * s1 = UDPSocket.new
- * s1.bind("127.0.0.1", 0)
- * s2 = UDPSocket.new
- * s2.bind("127.0.0.1", 0)
- * s2.connect(*s1.addr.values_at(3,1))
- * s1.connect(*s2.addr.values_at(3,1))
- * s1.send "aaa", 0
- * IO.select([s2])
- * p s2.recvfrom_nonblock(10) #=> ["aaa", ["AF_INET", 33302, "localhost.localdomain", "127.0.0.1"]]
+ * _domain_ should be a communications domain such as: :INET, :INET6, :UNIX, etc.
*
- * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
- * to _recvfrom_nonblock_ fails.
+ * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc.
*
- * UDPSocket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
- * including Errno::EAGAIN.
+ * _protocol_ should be a protocol defined in the domain,
+ * defaults to 0 for the domain.
*
- * === See
- * * Socket#recvfrom
- */
-static VALUE
-udp_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
-{
- return s_recvfrom_nonblock(sock, argc, argv, RECV_IP);
-}
-
-#ifdef HAVE_SYS_UN_H
-static VALUE
-unix_init(sock, path)
- VALUE sock, path;
-{
- return init_unixsock(sock, path, 0);
-}
-
-static char *
-unixpath(struct sockaddr_un *sockaddr, socklen_t len)
-{
- if (sockaddr->sun_path < (char*)sockaddr + len)
- return sockaddr->sun_path;
- else
- return "";
-}
-
-static VALUE
-unix_path(sock)
- VALUE sock;
-{
- OpenFile *fptr;
-
- GetOpenFile(sock, fptr);
- if (fptr->path == 0) {
- struct sockaddr_un addr;
- socklen_t len = sizeof(addr);
- if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
- rb_sys_fail(0);
- fptr->path = strdup(unixpath(&addr, len));
- }
- return rb_str_new2(fptr->path);
-}
-
-static VALUE
-unix_svr_init(sock, path)
- VALUE sock, path;
-{
- return init_unixsock(sock, path, 1);
-}
-
-static VALUE
-unix_recvfrom(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
-{
- return s_recvfrom(sock, argc, argv, RECV_UNIX);
-}
-
-#if defined(HAVE_ST_MSG_CONTROL) && defined(SCM_RIGHTS)
-#define FD_PASSING_BY_MSG_CONTROL 1
-#else
-#define FD_PASSING_BY_MSG_CONTROL 0
-#endif
-
-#if defined(HAVE_ST_MSG_ACCRIGHTS)
-#define FD_PASSING_BY_MSG_ACCRIGHTS 1
-#else
-#define FD_PASSING_BY_MSG_ACCRIGHTS 0
-#endif
-
-static VALUE
-unix_send_io(sock, val)
- VALUE sock, val;
-{
-#if defined(HAVE_SENDMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
- int fd;
- OpenFile *fptr;
- struct msghdr msg;
- struct iovec vec[1];
- char buf[1];
-
-#if FD_PASSING_BY_MSG_CONTROL
- struct {
- struct cmsghdr hdr;
- int fd;
- } cmsg;
-#endif
-
- if (rb_obj_is_kind_of(val, rb_cIO)) {
- OpenFile *valfptr;
- GetOpenFile(val, valfptr);
- fd = fileno(valfptr->f);
- }
- else if (FIXNUM_P(val)) {
- fd = FIX2INT(val);
- }
- else {
- rb_raise(rb_eTypeError, "neither IO nor file descriptor");
- }
-
- GetOpenFile(sock, fptr);
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
-
- /* Linux and Solaris doesn't work if msg_iov is NULL. */
- buf[0] = '\0';
- vec[0].iov_base = buf;
- vec[0].iov_len = 1;
- msg.msg_iov = vec;
- msg.msg_iovlen = 1;
-
-#if FD_PASSING_BY_MSG_CONTROL
- msg.msg_control = (caddr_t)&cmsg;
- msg.msg_controllen = CMSG_SPACE(sizeof(int));
- msg.msg_flags = 0;
- cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
- cmsg.hdr.cmsg_level = SOL_SOCKET;
- cmsg.hdr.cmsg_type = SCM_RIGHTS;
- cmsg.fd = fd;
-#else
- msg.msg_accrights = (caddr_t)&fd;
- msg.msg_accrightslen = sizeof(fd);
-#endif
-
- if (sendmsg(fileno(fptr->f), &msg, 0) == -1)
- rb_sys_fail("sendmsg(2)");
-
- return Qnil;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-#if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
-static void
-thread_read_select(fd)
- int fd;
-{
- fd_set fds;
-
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- rb_thread_select(fd+1, &fds, 0, 0, 0);
-}
-#endif
-
-static VALUE
-unix_recv_io(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
-{
-#if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
- VALUE klass, mode;
- OpenFile *fptr;
- struct msghdr msg;
- struct iovec vec[2];
- char buf[1];
-
- int fd;
-#if FD_PASSING_BY_MSG_CONTROL
- struct {
- struct cmsghdr hdr;
- int fd;
- } cmsg;
-#endif
-
- rb_scan_args(argc, argv, "02", &klass, &mode);
- if (argc == 0)
- klass = rb_cIO;
- if (argc <= 1)
- mode = Qnil;
-
- GetOpenFile(sock, fptr);
-
- thread_read_select(fileno(fptr->f));
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
-
- vec[0].iov_base = buf;
- vec[0].iov_len = sizeof(buf);
- msg.msg_iov = vec;
- msg.msg_iovlen = 1;
-
-#if FD_PASSING_BY_MSG_CONTROL
- msg.msg_control = (caddr_t)&cmsg;
- msg.msg_controllen = CMSG_SPACE(sizeof(int));
- msg.msg_flags = 0;
- cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
- cmsg.hdr.cmsg_level = SOL_SOCKET;
- cmsg.hdr.cmsg_type = SCM_RIGHTS;
- cmsg.fd = -1;
-#else
- msg.msg_accrights = (caddr_t)&fd;
- msg.msg_accrightslen = sizeof(fd);
- fd = -1;
-#endif
-
- if (recvmsg(fileno(fptr->f), &msg, 0) == -1)
- rb_sys_fail("recvmsg(2)");
-
-#if FD_PASSING_BY_MSG_CONTROL
- if (msg.msg_controllen != CMSG_SPACE(sizeof(int))) {
- rb_raise(rb_eSocket,
- "file descriptor was not passed (msg_controllen : %d != %d)",
- msg.msg_controllen, CMSG_SPACE(sizeof(int)));
- }
- if (cmsg.hdr.cmsg_len != CMSG_SPACE(0) + sizeof(int)) {
- rb_raise(rb_eSocket,
- "file descriptor was not passed (cmsg_len : %d != %d)",
- cmsg.hdr.cmsg_len, CMSG_SPACE(0) + sizeof(int));
- }
- if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
- rb_raise(rb_eSocket,
- "file descriptor was not passed (cmsg_level : %d != %d)",
- cmsg.hdr.cmsg_level, SOL_SOCKET);
- }
- if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
- rb_raise(rb_eSocket,
- "file descriptor was not passed (cmsg_type : %d != %d)",
- cmsg.hdr.cmsg_type, SCM_RIGHTS);
- }
-#else
- if (msg.msg_accrightslen != sizeof(fd)) {
- rb_raise(rb_eSocket,
- "file descriptor was not passed (accrightslen) : %d != %d",
- msg.msg_accrightslen, sizeof(fd));
- }
-#endif
-
-#if FD_PASSING_BY_MSG_CONTROL
- fd = cmsg.fd;
-#endif
-
- if (klass == Qnil)
- return INT2FIX(fd);
- else {
- static ID for_fd = 0;
- int ff_argc;
- VALUE ff_argv[2];
- if (!for_fd)
- for_fd = rb_intern("for_fd");
- ff_argc = mode == Qnil ? 1 : 2;
- ff_argv[0] = INT2FIX(fd);
- ff_argv[1] = mode;
- return rb_funcall2(klass, for_fd, ff_argc, ff_argv);
- }
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-static VALUE
-unix_accept(sock)
- VALUE sock;
-{
- OpenFile *fptr;
- struct sockaddr_un from;
- socklen_t fromlen;
-
- GetOpenFile(sock, fptr);
- fromlen = sizeof(struct sockaddr_un);
- return s_accept(rb_cUNIXSocket, fileno(fptr->f),
- (struct sockaddr*)&from, &fromlen);
-}
-
-/*
- * call-seq:
- * unixserver.accept_nonblock => unixsocket
- *
- * Accepts an incoming connection using accept(2) after
- * O_NONBLOCK is set for the underlying file descriptor.
- * It returns an accepted UNIXSocket for the incoming connection.
- *
- * === Example
- * require 'socket'
- * serv = UNIXServer.new("/tmp/sock")
- * begin
- * sock = serv.accept_nonblock
- * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
- * IO.select([serv])
- * retry
- * end
- * # sock is an accepted socket.
- *
- * Refer to Socket#accept for the exceptions that may be thrown if the call
- * to UNIXServer#accept_nonblock fails.
+ * s1, s2 = Socket.pair(:UNIX, :STREAM, 0)
+ * s1.send "a", 0
+ * s1.send "b", 0
+ * s1.close
+ * p s2.recv(10) #=> "ab"
+ * p s2.recv(10) #=> ""
+ * p s2.recv(10) #=> ""
+ *
+ * s1, s2 = Socket.pair(:UNIX, :DGRAM, 0)
+ * s1.send "a", 0
+ * s1.send "b", 0
+ * p s2.recv(10) #=> "a"
+ * p s2.recv(10) #=> "b"
*
- * UNIXServer#accept_nonblock may raise any error corresponding to accept(2) failure,
- * including Errno::EAGAIN.
- *
- * === See
- * * UNIXServer#accept
- * * Socket#accept
*/
-static VALUE
-unix_accept_nonblock(sock)
- VALUE sock;
-{
- OpenFile *fptr;
- struct sockaddr_un from;
- socklen_t fromlen;
-
- GetOpenFile(sock, fptr);
- fromlen = sizeof(from);
- return s_accept_nonblock(rb_cUNIXSocket, fptr,
- (struct sockaddr *)&from, &fromlen);
-}
-
-static VALUE
-unix_sysaccept(sock)
- VALUE sock;
-{
- OpenFile *fptr;
- struct sockaddr_un from;
- socklen_t fromlen;
-
- GetOpenFile(sock, fptr);
- fromlen = sizeof(struct sockaddr_un);
- return s_accept(0, fileno(fptr->f), (struct sockaddr*)&from, &fromlen);
-}
-
-static VALUE
-unixaddr(sockaddr, len)
- struct sockaddr_un *sockaddr;
- socklen_t len;
-{
- return rb_assoc_new(rb_str_new2("AF_UNIX"),
- rb_str_new2(unixpath(sockaddr, len)));
-}
-
-static VALUE
-unix_addr(sock)
- VALUE sock;
-{
- OpenFile *fptr;
- struct sockaddr_un addr;
- socklen_t len = sizeof addr;
-
- GetOpenFile(sock, fptr);
-
- if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
- rb_sys_fail("getsockname(2)");
- return unixaddr(&addr, len);
-}
-
-static VALUE
-unix_peeraddr(sock)
- VALUE sock;
-{
- OpenFile *fptr;
- struct sockaddr_un addr;
- socklen_t len = sizeof addr;
-
- GetOpenFile(sock, fptr);
-
- if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
- rb_sys_fail("getsockname(2)");
- return unixaddr(&addr, len);
-}
-#endif
-
-static void
-setup_domain_and_type(domain, dv, type, tv)
- VALUE domain, type;
- int *dv, *tv;
-{
- VALUE tmp;
- char *ptr;
-
- tmp = rb_check_string_type(domain);
- if (!NIL_P(tmp)) {
- domain = tmp;
- rb_check_safe_obj(domain);
- ptr = RSTRING(domain)->ptr;
- if (strcmp(ptr, "AF_INET") == 0)
- *dv = AF_INET;
-#ifdef AF_UNIX
- else if (strcmp(ptr, "AF_UNIX") == 0)
- *dv = AF_UNIX;
-#endif
-#ifdef AF_ISO
- else if (strcmp(ptr, "AF_ISO") == 0)
- *dv = AF_ISO;
-#endif
-#ifdef AF_NS
- else if (strcmp(ptr, "AF_NS") == 0)
- *dv = AF_NS;
-#endif
-#ifdef AF_IMPLINK
- else if (strcmp(ptr, "AF_IMPLINK") == 0)
- *dv = AF_IMPLINK;
-#endif
-#ifdef PF_INET
- else if (strcmp(ptr, "PF_INET") == 0)
- *dv = PF_INET;
-#endif
-#ifdef PF_UNIX
- else if (strcmp(ptr, "PF_UNIX") == 0)
- *dv = PF_UNIX;
-#endif
-#ifdef PF_IMPLINK
- else if (strcmp(ptr, "PF_IMPLINK") == 0)
- *dv = PF_IMPLINK;
- else if (strcmp(ptr, "AF_IMPLINK") == 0)
- *dv = AF_IMPLINK;
-#endif
-#ifdef PF_AX25
- else if (strcmp(ptr, "PF_AX25") == 0)
- *dv = PF_AX25;
-#endif
-#ifdef PF_IPX
- else if (strcmp(ptr, "PF_IPX") == 0)
- *dv = PF_IPX;
-#endif
- else
- rb_raise(rb_eSocket, "unknown socket domain %s", ptr);
- }
- else {
- *dv = NUM2INT(domain);
- }
- tmp = rb_check_string_type(type);
- if (!NIL_P(tmp)) {
- type = tmp;
- rb_check_safe_obj(type);
- ptr = RSTRING(type)->ptr;
- if (strcmp(ptr, "SOCK_STREAM") == 0)
- *tv = SOCK_STREAM;
- else if (strcmp(ptr, "SOCK_DGRAM") == 0)
- *tv = SOCK_DGRAM;
-#ifdef SOCK_RAW
- else if (strcmp(ptr, "SOCK_RAW") == 0)
- *tv = SOCK_RAW;
-#endif
-#ifdef SOCK_SEQPACKET
- else if (strcmp(ptr, "SOCK_SEQPACKET") == 0)
- *tv = SOCK_SEQPACKET;
-#endif
-#ifdef SOCK_RDM
- else if (strcmp(ptr, "SOCK_RDM") == 0)
- *tv = SOCK_RDM;
-#endif
-#ifdef SOCK_PACKET
- else if (strcmp(ptr, "SOCK_PACKET") == 0)
- *tv = SOCK_PACKET;
-#endif
- else
- rb_raise(rb_eSocket, "unknown socket type %s", ptr);
- }
- else {
- *tv = NUM2INT(type);
- }
-}
-
-static VALUE
-sock_initialize(sock, domain, type, protocol)
- VALUE sock, domain, type, protocol;
-{
- int fd;
- int d, t;
-
- rb_secure(3);
- setup_domain_and_type(domain, &d, type, &t);
- fd = ruby_socket(d, t, NUM2INT(protocol));
- if (fd < 0) rb_sys_fail("socket(2)");
-
- return init_sock(sock, fd);
-}
-
-static VALUE
-sock_s_socketpair(klass, domain, type, protocol)
- VALUE klass, domain, type, protocol;
+VALUE
+rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass)
{
-#if defined HAVE_SOCKETPAIR
+ VALUE domain, type, protocol;
int d, t, p, sp[2];
int ret;
+ VALUE s1, s2, r;
+
+ rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
+ if (NIL_P(protocol))
+ protocol = INT2FIX(0);
setup_domain_and_type(domain, &d, type, &t);
p = NUM2INT(protocol);
- ret = socketpair(d, t, p, sp);
- if (ret < 0 && (errno == EMFILE || errno == ENFILE)) {
- rb_gc();
- ret = socketpair(d, t, p, sp);
- }
+ ret = rsock_socketpair(d, t, p, sp);
if (ret < 0) {
- rb_sys_fail("socketpair(2)");
+ rb_sys_fail("socketpair(2)");
}
- return rb_assoc_new(init_sock(rb_obj_alloc(klass), sp[0]),
- init_sock(rb_obj_alloc(klass), sp[1]));
-#else
- rb_notimplement();
-#endif
-}
-
-#ifdef HAVE_SYS_UN_H
-static VALUE
-unix_s_socketpair(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE domain, type, protocol;
- domain = INT2FIX(PF_UNIX);
-
- rb_scan_args(argc, argv, "02", &type, &protocol);
- if (argc == 0)
- type = INT2FIX(SOCK_STREAM);
- if (argc <= 1)
- protocol = INT2FIX(0);
-
- return sock_s_socketpair(klass, domain, type, protocol);
+ s1 = rsock_init_sock(rb_obj_alloc(klass), sp[0]);
+ s2 = rsock_init_sock(rb_obj_alloc(klass), sp[1]);
+ r = rb_assoc_new(s1, s2);
+ if (rb_block_given_p()) {
+ return rb_ensure(pair_yield, r, io_close, s1);
+ }
+ return r;
}
+#else
+#define rsock_sock_s_socketpair rb_f_notimplement
#endif
/*
* call-seq:
- * socket.connect(server_sockaddr) => 0
- *
- * Requests a connection to be made on the given +server_sockaddr+. Returns 0 if
+ * socket.connect(remote_sockaddr) => 0
+ *
+ * Requests a connection to be made on the given +remote_sockaddr+. Returns 0 if
* successful, otherwise an exception is raised.
- *
+ *
* === Parameter
- * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
- *
+ * * +remote_sockaddr+ - the +struct+ sockaddr contained in a string or Addrinfo object
+ *
* === Example:
- * # Pull down Google's web page
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
- * sockaddr = Socket.pack_sockaddr_in( 80, 'www.google.com' )
- * socket.connect( sockaddr )
- * socket.write( "GET / HTTP/1.0\r\n\r\n" )
- * results = socket.read
- *
+ * # Pull down Google's web page
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 80, 'www.google.com' )
+ * socket.connect( sockaddr )
+ * socket.write( "GET / HTTP/1.0\r\n\r\n" )
+ * results = socket.read
+ *
* === Unix-based Exceptions
- * On unix-based systems the following system exceptions may be raised if
+ * On unix-based systems the following system exceptions may be raised if
* the call to _connect_ fails:
* * Errno::EACCES - search permission is denied for a component of the prefix
- * path or write access to the +socket+ is denided
+ * path or write access to the +socket+ is denied
* * Errno::EADDRINUSE - the _sockaddr_ is already in use
* * Errno::EADDRNOTAVAIL - the specified _sockaddr_ is not available from the
* local machine
- * * Errno::EAFNOSUPPORT - the specified _sockaddr_ is not a valid address for
+ * * Errno::EAFNOSUPPORT - the specified _sockaddr_ is not a valid address for
* the address family of the specified +socket+
* * Errno::EALREADY - a connection is already in progress for the specified
* socket
@@ -2388,56 +314,56 @@ unix_s_socketpair(argc, argv, klass)
* refused the connection request
* * Errno::ECONNRESET - the remote host reset the connection request
* * Errno::EFAULT - the _sockaddr_ cannot be accessed
- * * Errno::EHOSTUNREACH - the destination host cannot be reached (probably
+ * * Errno::EHOSTUNREACH - the destination host cannot be reached (probably
* because the host is down or a remote router cannot reach it)
* * Errno::EINPROGRESS - the O_NONBLOCK is set for the +socket+ and the
- * connection cnanot be immediately established; the connection will be
+ * connection cannot be immediately established; the connection will be
* established asynchronously
* * Errno::EINTR - the attempt to establish the connection was interrupted by
* delivery of a signal that was caught; the connection will be established
* asynchronously
* * Errno::EISCONN - the specified +socket+ is already connected
* * Errno::EINVAL - the address length used for the _sockaddr_ is not a valid
- * length for the address family or there is an invalid family in _sockaddr_
+ * length for the address family or there is an invalid family in _sockaddr_
* * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
* PATH_MAX
* * Errno::ENETDOWN - the local interface used to reach the destination is down
* * Errno::ENETUNREACH - no route to the network is present
* * Errno::ENOBUFS - no buffer space is available
- * * Errno::ENOSR - there were insufficient STREAMS resources available to
+ * * Errno::ENOSR - there were insufficient STREAMS resources available to
* complete the operation
* * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
* * Errno::EOPNOTSUPP - the calling +socket+ is listening and cannot be connected
- * * Errno::EPROTOTYPE - the _sockaddr_ has a different type than the socket
+ * * Errno::EPROTOTYPE - the _sockaddr_ has a different type than the socket
* bound to the specified peer address
- * * Errno::ETIMEDOUT - the attempt to connect time out before a connection
+ * * Errno::ETIMEDOUT - the attempt to connect timed out before a connection
* was made.
- *
+ *
* On unix-based systems if the address family of the calling +socket+ is
* AF_UNIX the follow exceptions may be raised if the call to _connect_
* fails:
- * * Errno::EIO - an i/o error occured while reading from or writing to the
+ * * Errno::EIO - an i/o error occurred while reading from or writing to the
* file system
* * Errno::ELOOP - too many symbolic links were encountered in translating
* the pathname in _sockaddr_
- * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX
- * characters, or an entired pathname exceeded PATH_MAX characters
+ * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX
+ * characters, or an entire pathname exceeded PATH_MAX characters
* * Errno::ENOENT - a component of the pathname does not name an existing file
* or the pathname is an empty string
* * Errno::ENOTDIR - a component of the path prefix of the pathname in _sockaddr_
- * is not a directory
- *
+ * is not a directory
+ *
* === Windows Exceptions
- * On Windows systems the following system exceptions may be raised if
+ * On Windows systems the following system exceptions may be raised if
* the call to _connect_ fails:
* * Errno::ENETDOWN - the network is down
* * Errno::EADDRINUSE - the socket's local address is already in use
* * Errno::EINTR - the socket was cancelled
* * Errno::EINPROGRESS - a blocking socket is in progress or the service provider
- * is still processing a callback function. Or a nonblocking connect call is
+ * is still processing a callback function. Or a nonblocking connect call is
* in progress on the +socket+.
* * Errno::EALREADY - see Errno::EINVAL
- * * Errno::EADDRNOTAVAIL - the remote address is not a valid address, such as
+ * * Errno::EADDRNOTAVAIL - the remote address is not a valid address, such as
* ADDR_ANY TODO check ADDRANY TO INADDR_ANY
* * Errno::EAFNOSUPPORT - addresses in the specified family cannot be used with
* with this +socket+
@@ -2451,87 +377,61 @@ unix_s_socketpair(argc, argv, klass)
* * Errno::EHOSTUNREACH - no route to the network is present
* * Errno::ENOBUFS - no buffer space is available
* * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
- * * Errno::ETIMEDOUT - the attempt to connect time out before a connection
+ * * Errno::ETIMEDOUT - the attempt to connect timed out before a connection
* was made.
- * * Errno::EWOULDBLOCK - the socket is marked as nonblocking and the
+ * * Errno::EWOULDBLOCK - the socket is marked as nonblocking and the
* connection cannot be completed immediately
- * * Errno::EACCES - the attempt to connect the datagram socket to the
+ * * Errno::EACCES - the attempt to connect the datagram socket to the
* broadcast address failed
- *
+ *
* === See
* * connect manual pages on unix-based systems
* * connect function in Microsoft's Winsock functions reference
*/
static VALUE
-sock_connect(sock, addr)
- VALUE sock, addr;
+sock_connect(VALUE self, VALUE addr)
{
- OpenFile *fptr;
- int fd;
+ VALUE rai;
- StringValue(addr);
+ SockAddrStringValueWithAddrinfo(addr, rai);
addr = rb_str_new4(addr);
- GetOpenFile(sock, fptr);
- fd = fileno(fptr->f);
- if (ruby_connect(fd, (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len, 0) < 0) {
- rb_sys_fail("connect(2)");
+
+ int result = rsock_connect(self, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0, RUBY_IO_TIMEOUT_DEFAULT);
+
+ if (result < 0) {
+ rsock_sys_fail_raddrinfo_or_sockaddr("connect(2)", addr, rai);
}
- return INT2FIX(0);
+ return INT2FIX(result);
}
-/*
- * call-seq:
- * socket.connect_nonblock(server_sockaddr) => 0
- *
- * Requests a connection to be made on the given +server_sockaddr+ after
- * O_NONBLOCK is set for the underlying file descriptor.
- * Returns 0 if successful, otherwise an exception is raised.
- *
- * === Parameter
- * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
- *
- * === Example:
- * # Pull down Google's web page
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
- * sockaddr = Socket.sockaddr_in(80, 'www.google.com')
- * begin
- * socket.connect_nonblock(sockaddr)
- * rescue Errno::EINPROGRESS
- * IO.select(nil, [socket])
- * begin
- * socket.connect_nonblock(sockaddr)
- * rescue Errno::EISCONN
- * end
- * end
- * socket.write("GET / HTTP/1.0\r\n\r\n")
- * results = socket.read
- *
- * Refer to Socket#connect for the exceptions that may be thrown if the call
- * to _connect_nonblock_ fails.
- *
- * Socket#connect_nonblock may raise any error corresponding to connect(2) failure,
- * including Errno::EINPROGRESS.
- *
- * === See
- * * Socket#connect
- */
+/* :nodoc: */
static VALUE
-sock_connect_nonblock(sock, addr)
- VALUE sock, addr;
+sock_connect_nonblock(VALUE sock, VALUE addr, VALUE ex)
{
- OpenFile *fptr;
+ VALUE rai;
+ rb_io_t *fptr;
int n;
- StringValue(addr);
+ SockAddrStringValueWithAddrinfo(addr, rai);
addr = rb_str_new4(addr);
GetOpenFile(sock, fptr);
rb_io_set_nonblock(fptr);
- n = connect(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len);
+ n = connect(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr));
if (n < 0) {
- rb_sys_fail("connect(2)");
+ int e = errno;
+ if (e == EINPROGRESS) {
+ if (ex == Qfalse) {
+ return sym_wait_writable;
+ }
+ rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "connect(2) would block");
+ }
+ if (e == EISCONN) {
+ if (ex == Qfalse) {
+ return INT2FIX(0);
+ }
+ }
+ rsock_syserr_fail_raddrinfo_or_sockaddr(e, "connect(2)", addr, rai);
}
return INT2FIX(n);
@@ -2539,33 +439,40 @@ sock_connect_nonblock(sock, addr)
/*
* call-seq:
- * socket.bind(server_sockaddr) => 0
- *
- * Binds to the given +struct+ sockaddr.
- *
+ * socket.bind(local_sockaddr) => 0
+ *
+ * Binds to the given local address.
+ *
* === Parameter
- * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
+ * * +local_sockaddr+ - the +struct+ sockaddr contained in a string or an Addrinfo object
*
* === Example
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
- * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
- * socket.bind( sockaddr )
- *
+ * require 'socket'
+ *
+ * # use Addrinfo
+ * socket = Socket.new(:INET, :STREAM, 0)
+ * socket.bind(Addrinfo.tcp("127.0.0.1", 2222))
+ * p socket.local_address #=> #<Addrinfo: 127.0.0.1:2222 TCP>
+ *
+ * # use struct sockaddr
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.bind( sockaddr )
+ *
* === Unix-based Exceptions
- * On unix-based based systems the following system exceptions may be raised if
+ * On unix-based based systems the following system exceptions may be raised if
* the call to _bind_ fails:
* * Errno::EACCES - the specified _sockaddr_ is protected and the current
* user does not have permission to bind to it
* * Errno::EADDRINUSE - the specified _sockaddr_ is already in use
* * Errno::EADDRNOTAVAIL - the specified _sockaddr_ is not available from the
* local machine
- * * Errno::EAFNOSUPPORT - the specified _sockaddr_ isnot a valid address for
+ * * Errno::EAFNOSUPPORT - the specified _sockaddr_ is not a valid address for
* the family of the calling +socket+
* * Errno::EBADF - the _sockaddr_ specified is not a valid file descriptor
* * Errno::EFAULT - the _sockaddr_ argument cannot be accessed
- * * Errno::EINVAL - the +socket+ is already bound to an address, and the
+ * * Errno::EINVAL - the +socket+ is already bound to an address, and the
* protocol does not support binding to the new _sockaddr_ or the +socket+
* has been shut down.
* * Errno::EINVAL - the address length is not a valid length for the address
@@ -2573,35 +480,35 @@ sock_connect_nonblock(sock, addr)
* * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
* PATH_MAX
* * Errno::ENOBUFS - no buffer space is available
- * * Errno::ENOSR - there were insufficient STREAMS resources available to
+ * * Errno::ENOSR - there were insufficient STREAMS resources available to
* complete the operation
* * Errno::ENOTSOCK - the +socket+ does not refer to a socket
- * * Errno::EOPNOTSUPP - the socket type of the +socket+ does not support
+ * * Errno::EOPNOTSUPP - the socket type of the +socket+ does not support
* binding to an address
- *
+ *
* On unix-based based systems if the address family of the calling +socket+ is
* Socket::AF_UNIX the follow exceptions may be raised if the call to _bind_
* fails:
* * Errno::EACCES - search permission is denied for a component of the prefix
- * path or write access to the +socket+ is denided
+ * path or write access to the +socket+ is denied
* * Errno::EDESTADDRREQ - the _sockaddr_ argument is a null pointer
* * Errno::EISDIR - same as Errno::EDESTADDRREQ
* * Errno::EIO - an i/o error occurred
* * Errno::ELOOP - too many symbolic links were encountered in translating
* the pathname in _sockaddr_
- * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX
- * characters, or an entired pathname exceeded PATH_MAX characters
+ * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX
+ * characters, or an entire pathname exceeded PATH_MAX characters
* * Errno::ENOENT - a component of the pathname does not name an existing file
* or the pathname is an empty string
* * Errno::ENOTDIR - a component of the path prefix of the pathname in _sockaddr_
* is not a directory
* * Errno::EROFS - the name would reside on a read only filesystem
- *
+ *
* === Windows Exceptions
- * On Windows systems the following system exceptions may be raised if
+ * On Windows systems the following system exceptions may be raised if
* the call to _bind_ fails:
* * Errno::ENETDOWN-- the network is down
- * * Errno::EACCES - the attempt to connect the datagram socket to the
+ * * Errno::EACCES - the attempt to connect the datagram socket to the
* broadcast address failed
* * Errno::EADDRINUSE - the socket's local address is already in use
* * Errno::EADDRNOTAVAIL - the specified address is not a valid address for this
@@ -2611,80 +518,80 @@ sock_connect_nonblock(sock, addr)
* * Errno::EINVAL - the +socket+ is already bound to an address
* * Errno::ENOBUFS - no buffer space is available
* * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
- *
+ *
* === See
* * bind manual pages on unix-based systems
* * bind function in Microsoft's Winsock functions reference
- */
+ */
static VALUE
-sock_bind(sock, addr)
- VALUE sock, addr;
+sock_bind(VALUE sock, VALUE addr)
{
- OpenFile *fptr;
+ VALUE rai;
+ rb_io_t *fptr;
- StringValue(addr);
+ SockAddrStringValueWithAddrinfo(addr, rai);
GetOpenFile(sock, fptr);
- if (bind(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0)
- rb_sys_fail("bind(2)");
+ if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0)
+ rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai);
return INT2FIX(0);
}
/*
* call-seq:
- * socket.listen( int ) => 0
- *
+ * socket.listen( int ) => 0
+ *
* Listens for connections, using the specified +int+ as the backlog. A call
- * to _listen_ only applies if the +socket+ is of type SOCK_STREAM or
+ * to _listen_ only applies if the +socket+ is of type SOCK_STREAM or
* SOCK_SEQPACKET.
- *
+ *
* === Parameter
* * +backlog+ - the maximum length of the queue for pending connections.
- *
+ *
* === Example 1
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
- * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
- * socket.bind( sockaddr )
- * socket.listen( 5 )
- *
- * === Example 2 (listening on an arbitary port, unix-based systems only):
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
- * socket.listen( 1 )
- *
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.bind( sockaddr )
+ * socket.listen( 5 )
+ *
+ * === Example 2 (listening on an arbitrary port, unix-based systems only):
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * socket.listen( 1 )
+ *
* === Unix-based Exceptions
* On unix based systems the above will work because a new +sockaddr+ struct
* is created on the address ADDR_ANY, for an arbitrary port number as handed
* off by the kernel. It will not work on Windows, because Windows requires that
* the +socket+ is bound by calling _bind_ before it can _listen_.
- *
+ *
* If the _backlog_ amount exceeds the implementation-dependent maximum
* queue length, the implementation's maximum queue length will be used.
- *
+ *
* On unix-based based systems the following system exceptions may be raised if the
* call to _listen_ fails:
* * Errno::EBADF - the _socket_ argument is not a valid file descriptor
- * * Errno::EDESTADDRREQ - the _socket_ is not bound to a local address, and
+ * * Errno::EDESTADDRREQ - the _socket_ is not bound to a local address, and
* the protocol does not support listening on an unbound socket
* * Errno::EINVAL - the _socket_ is already connected
* * Errno::ENOTSOCK - the _socket_ argument does not refer to a socket
* * Errno::EOPNOTSUPP - the _socket_ protocol does not support listen
- * * Errno::EACCES - the calling process does not have approriate privileges
+ * * Errno::EACCES - the calling process does not have appropriate privileges
* * Errno::EINVAL - the _socket_ has been shut down
- * * Errno::ENOBUFS - insufficient resources are available in the system to
+ * * Errno::ENOBUFS - insufficient resources are available in the system to
* complete the call
- *
+ *
* === Windows Exceptions
- * On Windows systems the following system exceptions may be raised if
+ * On Windows systems the following system exceptions may be raised if
* the call to _listen_ fails:
* * Errno::ENETDOWN - the network is down
- * * Errno::EADDRINUSE - the socket's local address is already in use. This
+ * * Errno::EADDRINUSE - the socket's local address is already in use. This
* usually occurs during the execution of _bind_ but could be delayed
* if the call to _bind_ was to a partially wildcard address (involving
- * ADDR_ANY) and if a specific address needs to be commmitted at the
+ * ADDR_ANY) and if a specific address needs to be committed at the
* time of the call to _listen_
* * Errno::EINPROGRESS - a Windows Sockets 1.1 call is in progress or the
* service provider is still processing a callback function
@@ -2695,85 +602,83 @@ sock_bind(sock, addr)
* * Errno::ENOTSOC - +socket+ is not a socket
* * Errno::EOPNOTSUPP - the referenced +socket+ is not a type that supports
* the _listen_ method
- *
+ *
* === See
* * listen manual pages on unix-based systems
* * listen function in Microsoft's Winsock functions reference
*/
-static VALUE
-sock_listen(sock, log)
- VALUE sock, log;
+VALUE
+rsock_sock_listen(VALUE sock, VALUE log)
{
- OpenFile *fptr;
+ rb_io_t *fptr;
int backlog;
- rb_secure(4);
backlog = NUM2INT(log);
GetOpenFile(sock, fptr);
- if (listen(fileno(fptr->f), backlog) < 0)
- rb_sys_fail("listen(2)");
+ if (listen(fptr->fd, backlog) < 0)
+ rb_sys_fail("listen(2)");
return INT2FIX(0);
}
/*
* call-seq:
- * socket.recvfrom(maxlen) => [mesg, sender_sockaddr]
- * socket.recvfrom(maxlen, flags) => [mesg, sender_sockaddr]
- *
+ * socket.recvfrom(maxlen) => [mesg, sender_addrinfo]
+ * socket.recvfrom(maxlen, flags) => [mesg, sender_addrinfo]
+ *
* Receives up to _maxlen_ bytes from +socket+. _flags_ is zero or more
* of the +MSG_+ options. The first element of the results, _mesg_, is the data
- * received. The second element, _sender_sockaddr_, contains protocol-specific information
- * on the sender.
- *
+ * received. The second element, _sender_addrinfo_, contains protocol-specific
+ * address information of the sender.
+ *
* === Parameters
- * * +maxlen+ - the number of bytes to receive from the socket
- * * +flags+ - zero or more of the +MSG_+ options
- *
+ * * +maxlen+ - the maximum number of bytes to receive from the socket
+ * * +flags+ - zero or more of the +MSG_+ options
+ *
* === Example
- * # In one file, start this first
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
- * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
- * socket.bind( sockaddr )
- * socket.listen( 5 )
- * client, client_sockaddr = socket.accept
- * data = client.recvfrom( 20 )[0].chomp
- * puts "I only received 20 bytes '#{data}'"
- * sleep 1
- * socket.close
- *
- * # In another file, start this second
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
- * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
- * socket.connect( sockaddr )
- * socket.puts "Watch this get cut short!"
- * socket.close
- *
+ * # In one file, start this first
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.bind( sockaddr )
+ * socket.listen( 5 )
+ * client, client_addrinfo = socket.accept
+ * data = client.recvfrom( 20 )[0].chomp
+ * puts "I only received 20 bytes '#{data}'"
+ * sleep 1
+ * socket.close
+ *
+ * # In another file, start this second
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.connect( sockaddr )
+ * socket.puts "Watch this get cut short!"
+ * socket.close
+ *
* === Unix-based Exceptions
* On unix-based based systems the following system exceptions may be raised if the
* call to _recvfrom_ fails:
* * Errno::EAGAIN - the +socket+ file descriptor is marked as O_NONBLOCK and no
* data is waiting to be received; or MSG_OOB is set and no out-of-band data
- * is available and either the +socket+ file descriptor is marked as
- * O_NONBLOCK or the +socket+ does not support blocking to wait for
+ * is available and either the +socket+ file descriptor is marked as
+ * O_NONBLOCK or the +socket+ does not support blocking to wait for
* out-of-band-data
* * Errno::EWOULDBLOCK - see Errno::EAGAIN
* * Errno::EBADF - the +socket+ is not a valid file descriptor
* * Errno::ECONNRESET - a connection was forcibly closed by a peer
- * * Errno::EFAULT - the socket's internal buffer, address or address length
+ * * Errno::EFAULT - the socket's internal buffer, address or address length
* cannot be accessed or written
- * * Errno::EINTR - a signal interupted _recvfrom_ before any data was available
+ * * Errno::EINTR - a signal interrupted _recvfrom_ before any data was available
* * Errno::EINVAL - the MSG_OOB flag is set and no out-of-band data is available
- * * Errno::EIO - an i/o error occurred while reading from or writing to the
+ * * Errno::EIO - an i/o error occurred while reading from or writing to the
* filesystem
- * * Errno::ENOBUFS - insufficient resources were available in the system to
+ * * Errno::ENOBUFS - insufficient resources were available in the system to
* perform the operation
* * Errno::ENOMEM - insufficient memory was available to fulfill the request
- * * Errno::ENOSR - there were insufficient STREAMS resources available to
+ * * Errno::ENOSR - there were insufficient STREAMS resources available to
* complete the operation
* * Errno::ENOTCONN - a receive is attempted on a connection-mode socket that
* is not connected
@@ -2781,345 +686,195 @@ sock_listen(sock, log)
* * Errno::EOPNOTSUPP - the specified flags are not supported for this socket type
* * Errno::ETIMEDOUT - the connection timed out during connection establishment
* or due to a transmission timeout on an active connection
- *
+ *
* === Windows Exceptions
- * On Windows systems the following system exceptions may be raised if
+ * On Windows systems the following system exceptions may be raised if
* the call to _recvfrom_ fails:
* * Errno::ENETDOWN - the network is down
* * Errno::EFAULT - the internal buffer and from parameters on +socket+ are not
* part of the user address space, or the internal fromlen parameter is
- * too small to accomodate the peer address
+ * too small to accommodate the peer address
* * Errno::EINTR - the (blocking) call was cancelled by an internal call to
* the WinSock function WSACancelBlockingCall
- * * Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or
+ * * Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or
* the service provider is still processing a callback function
* * Errno::EINVAL - +socket+ has not been bound with a call to _bind_, or an
* unknown flag was specified, or MSG_OOB was specified for a socket with
* SO_OOBINLINE enabled, or (for byte stream-style sockets only) the internal
* len parameter on +socket+ was zero or negative
* * Errno::EISCONN - +socket+ is already connected. The call to _recvfrom_ is
- * not permitted with a connected socket on a socket that is connetion
+ * not permitted with a connected socket on a socket that is connection
* oriented or connectionless.
- * * Errno::ENETRESET - the connection has been broken due to the keep-alive
+ * * Errno::ENETRESET - the connection has been broken due to the keep-alive
* activity detecting a failure while the operation was in progress.
* * Errno::EOPNOTSUPP - MSG_OOB was specified, but +socket+ is not stream-style
* such as type SOCK_STREAM. OOB data is not supported in the communication
- * domain associated with +socket+, or +socket+ is unidirectional and
+ * domain associated with +socket+, or +socket+ is unidirectional and
* supports only send operations
- * * Errno::ESHUTDOWN - +socket+ has been shutdown. It is not possible to
+ * * Errno::ESHUTDOWN - +socket+ has been shutdown. It is not possible to
* call _recvfrom_ on a socket after _shutdown_ has been invoked.
- * * Errno::EWOULDBLOCK - +socket+ is marked as nonblocking and a call to
+ * * Errno::EWOULDBLOCK - +socket+ is marked as nonblocking and a call to
* _recvfrom_ would block.
* * Errno::EMSGSIZE - the message was too large to fit into the specified buffer
* and was truncated.
* * Errno::ETIMEDOUT - the connection has been dropped, because of a network
* failure or because the system on the other end went down without
* notice
- * * Errno::ECONNRESET - the virtual circuit was reset by the remote side
+ * * Errno::ECONNRESET - the virtual circuit was reset by the remote side
* executing a hard or abortive close. The application should close the
* socket; it is no longer usable. On a UDP-datagram socket this error
* indicates a previous send operation resulted in an ICMP Port Unreachable
* message.
*/
static VALUE
-sock_recvfrom(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
+sock_recvfrom(int argc, VALUE *argv, VALUE sock)
{
- return s_recvfrom(sock, argc, argv, RECV_SOCKET);
+ return rsock_s_recvfrom(sock, argc, argv, RECV_SOCKET);
}
-/*
- * call-seq:
- * socket.recvfrom_nonblock(maxlen) => [mesg, sender_sockaddr]
- * socket.recvfrom_nonblock(maxlen, flags) => [mesg, sender_sockaddr]
- *
- * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
- * O_NONBLOCK is set for the underlying file descriptor.
- * _flags_ is zero or more of the +MSG_+ options.
- * The first element of the results, _mesg_, is the data received.
- * The second element, _sender_sockaddr_, contains protocol-specific information
- * on the sender.
- *
- * When recvfrom(2) returns 0, Socket#recvfrom_nonblock returns
- * an empty string as data.
- * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
- *
- * === Parameters
- * * +maxlen+ - the number of bytes to receive from the socket
- * * +flags+ - zero or more of the +MSG_+ options
- *
- * === Example
- * # In one file, start this first
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
- * sockaddr = Socket.sockaddr_in(2200, 'localhost')
- * socket.bind(sockaddr)
- * socket.listen(5)
- * client, client_sockaddr = socket.accept
- * begin
- * pair = client.recvfrom_nonblock(20)
- * rescue Errno::EAGAIN
- * IO.select([client])
- * retry
- * end
- * data = pair[0].chomp
- * puts "I only received 20 bytes '#{data}'"
- * sleep 1
- * socket.close
- *
- * # In another file, start this second
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
- * sockaddr = Socket.sockaddr_in(2200, 'localhost')
- * socket.connect(sockaddr)
- * socket.puts "Watch this get cut short!"
- * socket.close
- *
- * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
- * to _recvfrom_nonblock_ fails.
- *
- * Socket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
- * including Errno::EAGAIN.
- *
- * === See
- * * Socket#recvfrom
- */
+/* :nodoc: */
static VALUE
-sock_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
+sock_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, VALUE ex)
{
- return s_recvfrom_nonblock(sock, argc, argv, RECV_SOCKET);
+ return rsock_s_recvfrom_nonblock(sock, len, flg, str, ex, RECV_SOCKET);
}
/*
* call-seq:
- * socket.accept => [ socket, string ]
- *
- * Accepts an incoming connection returning an array containing a new
- * Socket object and a string holding the +struct+ sockaddr information about
- * the caller.
- *
- * === Example
- * # In one script, start this first
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
- * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
- * socket.bind( sockaddr )
- * socket.listen( 5 )
- * client, client_sockaddr = socket.accept
- * puts "The client said, '#{socket.readline.chomp}'"
- * client.puts "Hello from script one!"
- * socket.close
- *
- * # In another script, start this second
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
- * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
- * socket.connect( sockaddr )
- * socket.puts "Hello from script 2."
- * puts "The server said, '#{socket.readline.chomp}'"
- * socket.close
- *
- * === Unix-based Exceptions
- * On unix-based based systems the following system exceptions may be raised if the
- * call to _accept_ fails:
- * * Errno::EAGAIN - O_NONBLOCK is set for the +socket+ file descriptor and no
- * connections are parent to be accepted
- * * Errno::EWOULDBLOCK - same as Errno::EAGAIN
- * * Errno::EBADF - the +socket+ is not a valid file descriptor
- * * Errno::ECONNABORTED - a connection has been aborted
- * * Errno::EFAULT - the socket's internal address or address length parameter
- * cannot be access or written
- * * Errno::EINTR - the _accept_ method was interrupted by a signal that was
- * caught before a valid connection arrived
- * * Errno::EINVAL - the +socket+ is not accepting connections
- * * Errno::EMFILE - OPEN_MAX file descriptors are currently open in the calling
- * process
- * * Errno::ENOBUFS - no buffer space is available
- * * Errno::ENOMEM - there was insufficient memory available to complete the
- * operation
- * * Errno::ENOSR - there was insufficient STREAMS resources available to
- * complete the operation
- * * Errno::ENFILE - the maximum number of file descriptors in the system are
- * already open
- * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
- * * Errno::EOPNOTSUPP - the socket type for the calling +socket+ does not
- * support accept connections
- * * Errno::EPROTO - a protocol error has occurred
- *
- * === Windows Exceptions
- * On Windows systems the following system exceptions may be raised if
- * the call to _accept_ fails:
- * * Errno::ECONNRESET - an incoming connection was indicated, but was
- * terminated by the remote peer prior to accepting the connection
- * * Errno::EFAULT - the socket's internal address or address length parameter
- * is too small or is not a valid part of the user space address
- * * Errno::EINVAL - the _listen_ method was not invoked prior to calling _accept_
- * * Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or
- * the service provider is still processing a callback function
- * * Errno::EMFILE - the queue is not empty, upong etry to _accept_ and there are
- * no socket descriptors available
- * * Errno::ENETDOWN - the network is down
- * * Errno::ENOBUFS - no buffer space is available
- * * Errno::ENOTSOCK - +socket+ is not a socket
- * * Errno::EOPNOTSUPP - +socket+ is not a type that supports connection-oriented
- * service.
- * * Errno::EWOULDBLOCK - +socket+ is marked as nonblocking and no connections are
- * present to be accepted
- *
- * === See
- * * accept manual pages on unix-based systems
- * * accept function in Microsoft's Winsock functions reference
+ * socket.accept => [client_socket, client_addrinfo]
+ *
+ * Accepts a next connection.
+ * Returns a new Socket object and Addrinfo object.
+ *
+ * serv = Socket.new(:INET, :STREAM, 0)
+ * serv.listen(5)
+ * c = Socket.new(:INET, :STREAM, 0)
+ * c.connect(serv.connect_address)
+ * p serv.accept #=> [#<Socket:fd 6>, #<Addrinfo: 127.0.0.1:48555 TCP>]
+ *
*/
static VALUE
-sock_accept(sock)
- VALUE sock;
+sock_accept(VALUE server)
{
- OpenFile *fptr;
- VALUE sock2;
- char buf[1024];
- socklen_t len = sizeof buf;
+ union_sockaddr buffer;
+ socklen_t length = (socklen_t)sizeof(buffer);
- GetOpenFile(sock, fptr);
- sock2 = s_accept(rb_cSocket,fileno(fptr->f),(struct sockaddr*)buf,&len);
+ VALUE peer = rsock_s_accept(rb_cSocket, server, &buffer.addr, &length);
- return rb_assoc_new(sock2, rb_str_new(buf, len));
+ return rb_assoc_new(peer, rsock_io_socket_addrinfo(peer, &buffer.addr, length));
}
-/*
- * call-seq:
- * socket.accept_nonblock => [client_socket, client_sockaddr]
- *
- * Accepts an incoming connection using accept(2) after
- * O_NONBLOCK is set for the underlying file descriptor.
- * It returns an array containg the accpeted socket
- * for the incoming connection, _client_socket_,
- * and a string that contains the +struct+ sockaddr information
- * about the caller, _client_sockaddr_.
- *
- * === Example
- * # In one script, start this first
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
- * sockaddr = Socket.sockaddr_in(2200, 'localhost')
- * socket.bind(sockaddr)
- * socket.listen(5)
- * begin
- * client_socket, client_sockaddr = socket.accept_nonblock
- * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
- * IO.select([socket])
- * retry
- * end
- * puts "The client said, '#{socket.readline.chomp}'"
- * client_socket.puts "Hello from script one!"
- * socket.close
- *
- * # In another script, start this second
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
- * sockaddr = Socket.sockaddr_in(2200, 'localhost')
- * socket.connect(sockaddr)
- * socket.puts "Hello from script 2."
- * puts "The server said, '#{socket.readline.chomp}'"
- * socket.close
- *
- * Refer to Socket#accept for the exceptions that may be thrown if the call
- * to _accept_nonblock_ fails.
- *
- * Socket#accept_nonblock may raise any error corresponding to accept(2) failure,
- * including Errno::EAGAIN.
- *
- * === See
- * * Socket#accept
- */
+/* :nodoc: */
static VALUE
-sock_accept_nonblock(sock)
- VALUE sock;
+sock_accept_nonblock(VALUE sock, VALUE ex)
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE sock2;
- char buf[1024];
- socklen_t len = sizeof buf;
+ union_sockaddr buf;
+ struct sockaddr *addr = &buf.addr;
+ socklen_t len = (socklen_t)sizeof buf;
GetOpenFile(sock, fptr);
- sock2 = s_accept_nonblock(rb_cSocket, fptr, (struct sockaddr *)buf, &len);
- return rb_assoc_new(sock2, rb_str_new(buf, len));
+ sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len);
+
+ if (SYMBOL_P(sock2)) /* :wait_readable */
+ return sock2;
+ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len));
}
/*
* call-seq:
- * socket.sysaccept => [client_socket_fd, client_sockaddr]
- *
- * Accepts an incoming connection returnings an array containg the (integer)
+ * socket.sysaccept => [client_socket_fd, client_addrinfo]
+ *
+ * Accepts an incoming connection returning an array containing the (integer)
* file descriptor for the incoming connection, _client_socket_fd_,
- * and a string that contains the +struct+ sockaddr information
- * about the caller, _client_sockaddr_.
- *
+ * and an Addrinfo, _client_addrinfo_.
+ *
* === Example
- * # In one script, start this first
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
- * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
- * socket.bind( sockaddr )
- * socket.listen( 5 )
- * client_fd, client_sockaddr = socket.sysaccept
- * puts "The client said, '#{socket.readline.chomp}'"
- * client_socket = Socket.for_fd( client_fd )
- * client_socket.puts "Hello from script one!"
- * socket.close
- *
- * # In another script, start this second
- * require 'socket'
- * include Socket::Constants
- * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
- * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
- * socket.connect( sockaddr )
- * socket.puts "Hello from script 2."
- * puts "The server said, '#{socket.readline.chomp}'"
- * socket.close
- *
+ * # In one script, start this first
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.bind( sockaddr )
+ * socket.listen( 5 )
+ * client_fd, client_addrinfo = socket.sysaccept
+ * client_socket = Socket.for_fd( client_fd )
+ * puts "The client said, '#{client_socket.readline.chomp}'"
+ * client_socket.puts "Hello from script one!"
+ * socket.close
+ *
+ * # In another script, start this second
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.connect( sockaddr )
+ * socket.puts "Hello from script 2."
+ * puts "The server said, '#{socket.readline.chomp}'"
+ * socket.close
+ *
* Refer to Socket#accept for the exceptions that may be thrown if the call
- * to _sysaccept_ fails.
- *
+ * to _sysaccept_ fails.
+ *
* === See
* * Socket#accept
*/
static VALUE
-sock_sysaccept(sock)
- VALUE sock;
+sock_sysaccept(VALUE server)
{
- OpenFile *fptr;
- VALUE sock2;
- char buf[1024];
- socklen_t len = sizeof buf;
+ union_sockaddr buffer;
+ socklen_t length = (socklen_t)sizeof(buffer);
- GetOpenFile(sock, fptr);
- sock2 = s_accept(0,fileno(fptr->f),(struct sockaddr*)buf,&len);
+ VALUE peer = rsock_s_accept(0, server, &buffer.addr, &length);
- return rb_assoc_new(sock2, rb_str_new(buf, len));
+ return rb_assoc_new(peer, rsock_io_socket_addrinfo(peer, &buffer.addr, length));
}
#ifdef HAVE_GETHOSTNAME
+/*
+ * call-seq:
+ * Socket.gethostname => hostname
+ *
+ * Returns the hostname.
+ *
+ * p Socket.gethostname #=> "hal"
+ *
+ * Note that it is not guaranteed to be able to convert to IP address using gethostbyname, getaddrinfo, etc.
+ * If you need local IP address, use Socket.ip_address_list.
+ */
static VALUE
-sock_gethostname(obj)
- VALUE obj;
+sock_gethostname(VALUE obj)
{
- char buf[1024];
+#if defined(NI_MAXHOST)
+# define RUBY_MAX_HOST_NAME_LEN NI_MAXHOST
+#elif defined(HOST_NAME_MAX)
+# define RUBY_MAX_HOST_NAME_LEN HOST_NAME_MAX
+#else
+# define RUBY_MAX_HOST_NAME_LEN 1024
+#endif
- rb_secure(3);
- if (gethostname(buf, (int)sizeof buf - 1) < 0)
- rb_sys_fail("gethostname");
+ long len = RUBY_MAX_HOST_NAME_LEN;
+ VALUE name;
- buf[sizeof buf - 1] = '\0';
- return rb_str_new2(buf);
+ name = rb_str_new(0, len);
+ while (gethostname(RSTRING_PTR(name), len) < 0) {
+ int e = errno;
+ switch (e) {
+ case ENAMETOOLONG:
+#ifdef __linux__
+ case EINVAL:
+ /* glibc before version 2.1 uses EINVAL instead of ENAMETOOLONG */
+#endif
+ break;
+ default:
+ rb_syserr_fail(e, "gethostname(3)");
+ }
+ rb_str_modify_expand(name, len);
+ len += len;
+ }
+ rb_str_resize(name, strlen(RSTRING_PTR(name)));
+ return name;
}
#else
#ifdef HAVE_UNAME
@@ -3127,205 +882,146 @@ sock_gethostname(obj)
#include <sys/utsname.h>
static VALUE
-sock_gethostname(obj)
- VALUE obj;
+sock_gethostname(VALUE obj)
{
struct utsname un;
- rb_secure(3);
uname(&un);
return rb_str_new2(un.nodename);
}
#else
-static VALUE
-sock_gethostname(obj)
- VALUE obj;
-{
- rb_notimplement();
-}
+#define sock_gethostname rb_f_notimplement
#endif
#endif
static VALUE
-make_addrinfo(res0)
- struct addrinfo *res0;
+make_addrinfo(struct rb_addrinfo *res0, int norevlookup)
{
VALUE base, ary;
struct addrinfo *res;
if (res0 == NULL) {
- rb_raise(rb_eSocket, "host not found");
+ rb_raise(rb_eSocket, "host not found");
}
base = rb_ary_new();
- for (res = res0; res; res = res->ai_next) {
- ary = ipaddr(res->ai_addr);
- rb_ary_push(ary, INT2FIX(res->ai_family));
- rb_ary_push(ary, INT2FIX(res->ai_socktype));
- rb_ary_push(ary, INT2FIX(res->ai_protocol));
- rb_ary_push(base, ary);
+ for (res = res0->ai; res; res = res->ai_next) {
+ ary = rsock_ipaddr(res->ai_addr, res->ai_addrlen, norevlookup);
+ if (res->ai_canonname) {
+ RARRAY_ASET(ary, 2, rb_str_new2(res->ai_canonname));
+ }
+ rb_ary_push(ary, INT2FIX(res->ai_family));
+ rb_ary_push(ary, INT2FIX(res->ai_socktype));
+ rb_ary_push(ary, INT2FIX(res->ai_protocol));
+ rb_ary_push(base, ary);
}
return base;
}
-/* Returns a String containing the binary value of a struct sockaddr. */
-VALUE
-sock_sockaddr(addr, len)
- struct sockaddr *addr;
- size_t len;
+static VALUE
+sock_sockaddr(struct sockaddr *addr, socklen_t len)
{
char *ptr;
switch (addr->sa_family) {
case AF_INET:
- ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr;
- len = sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr);
- break;
-#ifdef INET6
+ ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr;
+ len = (socklen_t)sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr);
+ break;
+#ifdef AF_INET6
case AF_INET6:
- ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr;
- len = sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr);
- break;
+ ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr;
+ len = (socklen_t)sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr);
+ break;
#endif
default:
rb_raise(rb_eSocket, "unknown socket family:%d", addr->sa_family);
- break;
+ break;
}
return rb_str_new(ptr, len);
}
/*
- * Document-class: IPSocket
+ * call-seq:
+ * Socket.gethostbyname(hostname) => [official_hostname, alias_hostnames, address_family, *address_list]
*
- * IPSocket is the parent of TCPSocket and UDPSocket and implements
- * functionality common to them.
+ * Use Addrinfo.getaddrinfo instead.
+ * This method is deprecated for the following reasons:
*
- * A number of APIs in IPSocket, Socket, and their descendants return an
- * address as an array. The members of that array are:
- * - address family: A string like "AF_INET" or "AF_INET6" if it is one of the
- * commonly used families, the string "unknown:#" (where `#' is the address
- * family number) if it is not one of the common ones. The strings map to
- * the Socket::AF_* constants.
- * - port: The port number.
- * - name: Either the canonical name from looking the address up in the DNS, or
- * the address in presentation format
- * - address: The address in presentation format (a dotted decimal string for
- * IPv4, a hex string for IPv6).
+ * - The 3rd element of the result is the address family of the first address.
+ * The address families of the rest of the addresses are not returned.
+ * - Uncommon address representation:
+ * 4/16-bytes binary string to represent IPv4/IPv6 address.
+ * - gethostbyname() may take a long time and it may block other threads.
+ * (GVL cannot be released since gethostbyname() is not thread safe.)
+ * - This method uses gethostbyname() function already removed from POSIX.
*
- * The address and port can be used directly to create sockets and to bind or
- * connect them to the address.
- */
-
-/*
- * Document-class: Socket
+ * This method obtains the host information for _hostname_.
+ *
+ * p Socket.gethostbyname("hal") #=> ["localhost", ["hal"], 2, "\x7F\x00\x00\x01"]
*
- * Socket contains a number of generally useful singleton methods and
- * constants, as well as offering low-level interfaces that can be used to
- * develop socket applications using protocols other than TCP, UDP, and UNIX
- * domain sockets.
*/
+static VALUE
+sock_s_gethostbyname(VALUE obj, VALUE host)
+{
+ rb_warn("Socket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead.");
+ struct rb_addrinfo *res =
+ rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME, Qnil);
+ return rsock_make_hostent(host, res, sock_sockaddr);
+}
/*
- * Document-method: gethostbyname
- * call-seq: Socket.gethostbyname(host) => hostent
- *
- * Resolve +host+ and return name and address information for it, similarly to
- * gethostbyname(3). +host+ can be a domain name or the presentation format of
- * an address.
- *
- * Returns an array of information similar to that found in a +struct hostent+:
- * - cannonical name: the cannonical name for host in the DNS, or a
- * string representing the address
- * - aliases: an array of aliases for the canonical name, there may be no aliases
- * - address family: usually one of Socket::AF_INET or Socket::AF_INET6
- * - address: a string, the binary value of the +struct sockaddr+ for this name, in
- * the indicated address family
- * - ...: if there are multiple addresses for this host, a series of
- * strings/+struct sockaddr+s may follow, not all necessarily in the same
- * address family. Note that the fact that they may not be all in the same
- * address family is a departure from the behaviour of gethostbyname(3).
- *
- * Note: I believe that the fact that the multiple addresses returned are not
- * necessarily in the same address family may be a bug, since if this function
- * actually called gethostbyname(3), ALL the addresses returned in the trailing
- * address list (h_addr_list from struct hostent) would be of the same address
- * family! Examples from my system, OS X 10.3:
- *
- * ["localhost", [], 30, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", "\177\000\000\001"]
- * and
- * ["ensemble.local", [], 30, "\376\200\000\004\000\000\000\000\002\003\223\377\376\255\010\214", "\300\250{\232" ]
- *
- * Similar information can be returned by Socket.getaddrinfo if called as:
- *
- * Socket.getaddrinfo(+host+, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)
+ * call-seq:
+ * Socket.gethostbyaddr(address_string [, address_family]) => hostent
*
- * == Examples
- *
- * Socket.gethostbyname "example.com"
- * => ["example.com", [], 2, "\300\000\"\246"]
- *
- * This name has no DNS aliases, and a single IPv4 address.
- *
- * Socket.gethostbyname "smtp.telus.net"
- * => ["smtp.svc.telus.net", ["smtp.telus.net"], 2, "\307\271\334\371"]
- *
- * This name is an an alias so the canonical name is returned, as well as the
- * alias and a single IPv4 address.
- *
- * Socket.gethostbyname "localhost"
- * => ["localhost", [], 30, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", "\177\000\000\001"]
- *
- * This machine has no aliases, returns an IPv6 address, and has an additional IPv4 address.
+ * Use Addrinfo#getnameinfo instead.
+ * This method is deprecated for the following reasons:
*
- * +host+ can also be an IP address in presentation format, in which case a
- * reverse lookup is done on the address:
+ * - Uncommon address representation:
+ * 4/16-bytes binary string to represent IPv4/IPv6 address.
+ * - gethostbyaddr() may take a long time and it may block other threads.
+ * (GVL cannot be released since gethostbyname() is not thread safe.)
+ * - This method uses gethostbyname() function already removed from POSIX.
*
- * Socket.gethostbyname("127.0.0.1")
- * => ["localhost", [], 2, "\177\000\000\001"]
+ * This method obtains the host information for _address_.
*
- * Socket.gethostbyname("192.0.34.166")
- * => ["www.example.com", [], 2, "\300\000\"\246"]
+ * p Socket.gethostbyaddr([221,186,184,68].pack("CCCC"))
+ * #=> ["carbon.ruby-lang.org", [], 2, "\xDD\xBA\xB8D"]
*
+ * p Socket.gethostbyaddr([127,0,0,1].pack("CCCC"))
+ * ["localhost", [], 2, "\x7F\x00\x00\x01"]
+ * p Socket.gethostbyaddr(([0]*15+[1]).pack("C"*16))
+ * #=> ["localhost", ["ip6-localhost", "ip6-loopback"], 10,
+ * "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"]
*
- * == See
- * See: Socket.getaddrinfo
*/
static VALUE
-sock_s_gethostbyname(obj, host)
- VALUE obj, host;
-{
- rb_secure(3);
- return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr);
-}
-
-static VALUE
-sock_s_gethostbyaddr(argc, argv)
- int argc;
- VALUE *argv;
+sock_s_gethostbyaddr(int argc, VALUE *argv, VALUE _)
{
- VALUE addr, type;
+ VALUE addr, family;
struct hostent *h;
- struct sockaddr *sa;
char **pch;
VALUE ary, names;
int t = AF_INET;
- rb_scan_args(argc, argv, "11", &addr, &type);
- sa = (struct sockaddr*)StringValuePtr(addr);
- if (!NIL_P(type)) {
- t = NUM2INT(type);
+ rb_warn("Socket.gethostbyaddr is deprecated; use Addrinfo#getnameinfo instead.");
+
+ rb_scan_args(argc, argv, "11", &addr, &family);
+ StringValue(addr);
+ if (!NIL_P(family)) {
+ t = rsock_family_arg(family);
}
-#ifdef INET6
- else if (RSTRING(addr)->len == 16) {
- t = AF_INET6;
+#ifdef AF_INET6
+ else if (RSTRING_LEN(addr) == 16) {
+ t = AF_INET6;
}
#endif
- h = gethostbyaddr(RSTRING(addr)->ptr, RSTRING(addr)->len, t);
+ h = gethostbyaddr(RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), t);
if (h == NULL) {
#ifdef HAVE_HSTRERROR
- extern int h_errno;
- rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
+ extern int h_errno;
+ rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
#else
- rb_raise(rb_eSocket, "host not found");
+ rb_raise(rb_eSocket, "host not found");
#endif
}
ary = rb_ary_new();
@@ -3333,14 +1029,14 @@ sock_s_gethostbyaddr(argc, argv)
names = rb_ary_new();
rb_ary_push(ary, names);
if (h->h_aliases != NULL) {
- for (pch = h->h_aliases; *pch; pch++) {
- rb_ary_push(names, rb_str_new2(*pch));
- }
+ for (pch = h->h_aliases; *pch; pch++) {
+ rb_ary_push(names, rb_str_new2(*pch));
+ }
}
rb_ary_push(ary, INT2NUM(h->h_addrtype));
#ifdef h_addr
for (pch = h->h_addr_list; *pch; pch++) {
- rb_ary_push(ary, rb_str_new(*pch, h->h_length));
+ rb_ary_push(ary, rb_str_new(*pch, h->h_length));
}
#else
rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length));
@@ -3350,398 +1046,328 @@ sock_s_gethostbyaddr(argc, argv)
}
/*
- * Document-method: getservbyname
- * call-seq: Socket.getservbyname(name, proto="tcp") => port
+ * call-seq:
+ * Socket.getservbyname(service_name) => port_number
+ * Socket.getservbyname(service_name, protocol_name) => port_number
+ *
+ * Obtains the port number for _service_name_.
*
- * +name+ is a service name ("ftp", "telnet", ...) and proto is a protocol name
- * ("udp", "tcp", ...). '/etc/services' (or your system's equivalent) is
- * searched for a service for +name+ and +proto+, and the port number is
- * returned.
+ * If _protocol_name_ is not given, "tcp" is assumed.
*
- * Note that unlike Socket.getaddrinfo, +proto+ may not be specified using the
- * Socket::SOCK_* constants, a string must must be used.
+ * Socket.getservbyname("smtp") #=> 25
+ * Socket.getservbyname("shell") #=> 514
+ * Socket.getservbyname("syslog", "udp") #=> 514
*/
static VALUE
-sock_s_getservbyaname(argc, argv)
- int argc;
- VALUE *argv;
+sock_s_getservbyname(int argc, VALUE *argv, VALUE _)
{
VALUE service, proto;
struct servent *sp;
- int port;
+ long port;
+ const char *servicename, *protoname = "tcp";
rb_scan_args(argc, argv, "11", &service, &proto);
- if (NIL_P(proto)) proto = rb_str_new2("tcp");
StringValue(service);
- StringValue(proto);
-
- sp = getservbyname(StringValueCStr(service), StringValueCStr(proto));
+ if (!NIL_P(proto)) StringValue(proto);
+ servicename = StringValueCStr(service);
+ if (!NIL_P(proto)) protoname = StringValueCStr(proto);
+ sp = getservbyname(servicename, protoname);
if (sp) {
- port = ntohs(sp->s_port);
+ port = ntohs(sp->s_port);
}
else {
- char *s = RSTRING(service)->ptr;
- char *end;
+ char *end;
- port = strtoul(s, &end, 0);
- if (*end != '\0') {
- rb_raise(rb_eSocket, "no such service %s/%s", s, RSTRING(proto)->ptr);
- }
+ port = STRTOUL(servicename, &end, 0);
+ if (*end != '\0') {
+ rb_raise(rb_eSocket, "no such service %s/%s", servicename, protoname);
+ }
}
return INT2FIX(port);
}
/*
-Documentation should explain the following:
-
- $ pp Socket.getaddrinfo("", 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
- [["AF_INET", 1, "0.0.0.0", "0.0.0.0", 2, 1, 6]]
-
- $ pp Socket.getaddrinfo(nil, 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
- [["AF_INET6", 1, "::", "::", 30, 1, 6],
- ["AF_INET", 1, "0.0.0.0", "0.0.0.0", 2, 1, 6]]
-
- $ pp Socket.getaddrinfo("localhost", 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
- [["AF_INET6", 1, "localhost", "::1", 30, 1, 6],
- ["AF_INET", 1, "localhost", "127.0.0.1", 2, 1, 6]]
-
- $ pp Socket.getaddrinfo("ensemble.local.", 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
- [["AF_INET", 1, "localhost", "192.168.123.154", 2, 1, 6]]
+ * call-seq:
+ * Socket.getservbyport(port [, protocol_name]) => service
+ *
+ * Obtains the port number for _port_.
+ *
+ * If _protocol_name_ is not given, "tcp" is assumed.
+ *
+ * Socket.getservbyport(80) #=> "www"
+ * Socket.getservbyport(514, "tcp") #=> "shell"
+ * Socket.getservbyport(514, "udp") #=> "syslog"
+ *
+ */
+static VALUE
+sock_s_getservbyport(int argc, VALUE *argv, VALUE _)
+{
+ VALUE port, proto;
+ struct servent *sp;
+ long portnum;
+ const char *protoname = "tcp";
-Does it?
+ rb_scan_args(argc, argv, "11", &port, &proto);
+ portnum = NUM2LONG(port);
+ if (portnum != (uint16_t)portnum) {
+ const char *s = portnum > 0 ? "big" : "small";
+ rb_raise(rb_eRangeError, "integer %ld too %s to convert into `int16_t'", portnum, s);
+ }
+ if (!NIL_P(proto)) protoname = StringValueCStr(proto);
-API suggestion: this method has too many arguments, it would be backwards compatible and easier
-to understand if limit args were accepted as :family=>..., :flags=>...
-*/
+ sp = getservbyport((int)htons((uint16_t)portnum), protoname);
+ if (!sp) {
+ rb_raise(rb_eSocket, "no such service for port %d/%s", (int)portnum, protoname);
+ }
+ return rb_str_new2(sp->s_name);
+}
/*
- * Document-method: getaddrinfo
- * call-seq: Socket.getaddrinfo(host, service, family=nil, socktype=nil, protocol=nil, flags=nil) => addrinfo
- *
- * Return address information for +host+ and +port+. The remaining arguments
- * are hints that limit the address information returned.
- *
- * This method corresponds closely to the POSIX.1g getaddrinfo() definition.
+ * call-seq:
+ * Socket.getaddrinfo(nodename, servname[, family[, socktype[, protocol[, flags[, reverse_lookup]]]]]) => array
*
- * === Parameters
- * - +host+ is a host name or an address string (dotted decimal for IPv4, or a hex string
- * for IPv6) for which to return information. A nil is also allowed, its meaning
- * depends on +flags+, see below.
- * - +service+ is a service name ("http", "ssh", ...), or
- * a port number (80, 22, ...), see Socket.getservbyname for more
- * information. A nil is also allowed, meaning zero.
- * - +family+ limits the output to a specific address family, one of the
- * Socket::AF_* constants. Socket::AF_INET (IPv4) and Socket::AF_INET6 (IPv6)
- * are the most commonly used families. You will usually pass either nil or
- * Socket::AF_UNSPEC, allowing the IPv6 information to be returned first if
- * +host+ is reachable via IPv6, and IPv4 information otherwise. The two
- * strings "AF_INET" or "AF_INET6" are also allowed, they are converted to
- * their respective Socket::AF_* constants.
- * - +socktype+ limits the output to a specific type of socket, one of the
- * Socket::SOCK_* constants. Socket::SOCK_STREAM (for TCP) and
- * Socket::SOCK_DGRAM (for UDP) are the most commonly used socket types. If
- * nil, then information for all types of sockets supported by +service+ will
- * be returned. You will usually know what type of socket you intend to
- * create, and should pass that socket type in.
- * - +protocol+ limits the output to a specific protocol numpber, one of the
- * Socket::IPPROTO_* constants. It is usually implied by the socket type
- * (Socket::SOCK_STREAM => Socket::IPPROTO_TCP, ...), if you pass other than
- * nil you already know what this is for.
- * - +flags+ is one of the Socket::AI_* constants. They mean:
- * - Socket::AI_PASSIVE: when set, if +host+ is nil the 'any' address will be
- * returned, Socket::INADDR_ANY or 0 for IPv4, "0::0" or "::" for IPv6. This
- * address is suitable for use by servers that will bind their socket and do
- * a passive listen, thus the name of the flag. Otherwise the local or
- * loopback address will be returned, this is "127.0.0.1" for IPv4 and "::1'
- * for IPv6.
- * - ...
+ * Obtains address information for _nodename_:_servname_.
*
+ * Note that Addrinfo.getaddrinfo provides the same functionality in
+ * an object oriented style.
*
- * === Returns
+ * _family_ should be an address family such as: :INET, :INET6, etc.
*
- * Returns an array of arrays, where each subarray contains:
- * - address family, a string like "AF_INET" or "AF_INET6"
- * - port number, the port number for +service+
- * - host name, either a canonical name for +host+, or it's address in presentation
- * format if the address could not be looked up.
- * - host IP, the address of +host+ in presentation format
- * - address family, as a numeric value (one of the Socket::AF_* constants).
- * - socket type, as a numeric value (one of the Socket::SOCK_* constants).
- * - protocol number, as a numeric value (one of the Socket::IPPROTO_* constants).
+ * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc.
*
- * The first four values are identical to what is commonly returned as an
- * address array, see IPSocket for more information.
+ * _protocol_ should be a protocol defined in the family,
+ * and defaults to 0 for the family.
*
- * === Examples
+ * _flags_ should be bitwise OR of Socket::AI_* constants.
*
- * Not all input combinations are valid, and while there are many combinations,
- * only a few cases are common.
+ * Socket.getaddrinfo("www.ruby-lang.org", "http", nil, :STREAM)
+ * #=> [["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68", 2, 1, 6]] # PF_INET/SOCK_STREAM/IPPROTO_TCP
*
- * A typical client will call getaddrinfo with the +host+ and +service+ it
- * wants to connect to. It knows that it will attempt to connect with either
- * TCP or UDP, and specifies +socktype+ accordingly. It loops through all
- * returned addresses, and try to connect to them in turn:
+ * Socket.getaddrinfo("localhost", nil)
+ * #=> [["AF_INET", 0, "localhost", "127.0.0.1", 2, 1, 6], # PF_INET/SOCK_STREAM/IPPROTO_TCP
+ * # ["AF_INET", 0, "localhost", "127.0.0.1", 2, 2, 17], # PF_INET/SOCK_DGRAM/IPPROTO_UDP
+ * # ["AF_INET", 0, "localhost", "127.0.0.1", 2, 3, 0]] # PF_INET/SOCK_RAW/IPPROTO_IP
*
- * addrinfo = Socket::getaddrinfo('www.example.com', 'www', nil, Socket::SOCK_STREAM)
- * addrinfo.each do |af, port, name, addr|
- * begin
- * sock = TCPSocket.new(addr, port)
- * # ...
- * exit 1
- * rescue
- * end
- * end
+ * _reverse_lookup_ directs the form of the third element, and has to
+ * be one of below. If _reverse_lookup_ is omitted, the default value is +nil+.
*
- * With UDP you don't know if connect suceeded, but if communication fails,
- * the next address can be tried.
+ * +true+, +:hostname+: hostname is obtained from numeric address using reverse lookup, which may take a time.
+ * +false+, +:numeric+: hostname is the same as numeric address.
+ * +nil+: obey to the current +do_not_reverse_lookup+ flag.
*
- * A typical server will call getaddrinfo with a +host+ of nil, the +service+
- * it listens to, and a +flags+ of Socket::AI_PASSIVE. It will listen for
- * connections on the first returned address:
- * addrinfo = Socket::getaddrinfo(nil, 'www', nil, Socket::SOCK_STREAM, nil, Socket::AI_PASSIVE)
- * af, port, name, addr = addrinfo.first
- * sock = TCPServer(addr, port)
- * while( client = s.accept )
- * # ...
- * end
+ * If Addrinfo object is preferred, use Addrinfo.getaddrinfo.
*/
static VALUE
-sock_s_getaddrinfo(argc, argv)
- int argc;
- VALUE *argv;
+sock_s_getaddrinfo(int argc, VALUE *argv, VALUE _)
{
- VALUE host, port, family, socktype, protocol, flags, ret;
- char hbuf[1024], pbuf[1024];
- char *hptr, *pptr, *ap;
- struct addrinfo hints, *res;
- int error;
-
- host = port = family = socktype = protocol = flags = Qnil;
- rb_scan_args(argc, argv, "24", &host, &port, &family, &socktype, &protocol, &flags);
- if (NIL_P(host)) {
- hptr = NULL;
- }
- else {
- strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
- hbuf[sizeof(hbuf) - 1] = '\0';
- hptr = hbuf;
- }
- if (NIL_P(port)) {
- pptr = NULL;
- }
- else if (FIXNUM_P(port)) {
- snprintf(pbuf, sizeof(pbuf), "%ld", FIX2LONG(port));
- pptr = pbuf;
- }
- else {
- strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
- pbuf[sizeof(pbuf) - 1] = '\0';
- pptr = pbuf;
- }
+ VALUE host, port, family, socktype, protocol, flags, ret, revlookup;
+ struct addrinfo hints;
+ struct rb_addrinfo *res;
+ int norevlookup;
+
+ rb_scan_args(argc, argv, "25", &host, &port, &family, &socktype, &protocol, &flags, &revlookup);
MEMZERO(&hints, struct addrinfo, 1);
- if (NIL_P(family)) {
- hints.ai_family = PF_UNSPEC;
- }
- else if (FIXNUM_P(family)) {
- hints.ai_family = FIX2INT(family);
- }
- else if ((ap = StringValuePtr(family)) != 0) {
- if (strcmp(ap, "AF_INET") == 0) {
- hints.ai_family = PF_INET;
- }
-#ifdef INET6
- else if (strcmp(ap, "AF_INET6") == 0) {
- hints.ai_family = PF_INET6;
- }
-#endif
- }
+ hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
if (!NIL_P(socktype)) {
- hints.ai_socktype = NUM2INT(socktype);
+ hints.ai_socktype = rsock_socktype_arg(socktype);
}
if (!NIL_P(protocol)) {
- hints.ai_protocol = NUM2INT(protocol);
+ hints.ai_protocol = NUM2INT(protocol);
}
if (!NIL_P(flags)) {
- hints.ai_flags = NUM2INT(flags);
+ hints.ai_flags = NUM2INT(flags);
}
- error = getaddrinfo(hptr, pptr, &hints, &res);
- if (error) {
- rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
+ if (NIL_P(revlookup) || !rsock_revlookup_flag(revlookup, &norevlookup)) {
+ norevlookup = rsock_do_not_reverse_lookup;
}
- ret = make_addrinfo(res);
- freeaddrinfo(res);
+ res = rsock_getaddrinfo(host, port, &hints, 0, Qnil);
+
+ ret = make_addrinfo(res, norevlookup);
+ rb_freeaddrinfo(res);
return ret;
}
+/*
+ * call-seq:
+ * Socket.getnameinfo(sockaddr [, flags]) => [hostname, servicename]
+ *
+ * Obtains name information for _sockaddr_.
+ *
+ * _sockaddr_ should be one of follows.
+ * - packed sockaddr string such as Socket.sockaddr_in(80, "127.0.0.1")
+ * - 3-elements array such as ["AF_INET", 80, "127.0.0.1"]
+ * - 4-elements array such as ["AF_INET", 80, ignored, "127.0.0.1"]
+ *
+ * _flags_ should be bitwise OR of Socket::NI_* constants.
+ *
+ * Note:
+ * The last form is compatible with IPSocket#addr and IPSocket#peeraddr.
+ *
+ * Socket.getnameinfo(Socket.sockaddr_in(80, "127.0.0.1")) #=> ["localhost", "www"]
+ * Socket.getnameinfo(["AF_INET", 80, "127.0.0.1"]) #=> ["localhost", "www"]
+ * Socket.getnameinfo(["AF_INET", 80, "localhost", "127.0.0.1"]) #=> ["localhost", "www"]
+ *
+ * If Addrinfo object is preferred, use Addrinfo#getnameinfo.
+ */
static VALUE
-sock_s_getnameinfo(argc, argv)
- int argc;
- VALUE *argv;
+sock_s_getnameinfo(int argc, VALUE *argv, VALUE _)
{
VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags, tmp;
- char *hptr, *pptr;
char hbuf[1024], pbuf[1024];
int fl;
- struct addrinfo hints, *res = NULL, *r;
- int error;
- struct sockaddr_storage ss;
+ struct rb_addrinfo *res = NULL;
+ struct addrinfo hints, *r;
+ int error, saved_errno;
+ union_sockaddr ss;
struct sockaddr *sap;
- char *ap;
+ socklen_t salen;
sa = flags = Qnil;
rb_scan_args(argc, argv, "11", &sa, &flags);
fl = 0;
if (!NIL_P(flags)) {
- fl = NUM2INT(flags);
+ fl = NUM2INT(flags);
}
- tmp = rb_check_string_type(sa);
+ tmp = rb_check_sockaddr_string_type(sa);
if (!NIL_P(tmp)) {
- sa = tmp;
- if (sizeof(ss) < RSTRING(sa)->len) {
- rb_raise(rb_eTypeError, "sockaddr length too big");
- }
- memcpy(&ss, RSTRING(sa)->ptr, RSTRING(sa)->len);
- if (RSTRING(sa)->len != SA_LEN((struct sockaddr*)&ss)) {
- rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
- }
- sap = (struct sockaddr*)&ss;
- goto call_nameinfo;
+ sa = tmp;
+ if (sizeof(ss) < (size_t)RSTRING_LEN(sa)) {
+ rb_raise(rb_eTypeError, "sockaddr length too big");
+ }
+ memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa));
+ if (!VALIDATE_SOCKLEN(&ss.addr, RSTRING_LEN(sa))) {
+ rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
+ }
+ sap = &ss.addr;
+ salen = RSTRING_SOCKLEN(sa);
+ goto call_nameinfo;
}
tmp = rb_check_array_type(sa);
if (!NIL_P(tmp)) {
- sa = tmp;
- MEMZERO(&hints, struct addrinfo, 1);
- if (RARRAY(sa)->len == 3) {
- af = RARRAY(sa)->ptr[0];
- port = RARRAY(sa)->ptr[1];
- host = RARRAY(sa)->ptr[2];
- }
- else if (RARRAY(sa)->len >= 4) {
- af = RARRAY(sa)->ptr[0];
- port = RARRAY(sa)->ptr[1];
- host = RARRAY(sa)->ptr[3];
- if (NIL_P(host)) {
- host = RARRAY(sa)->ptr[2];
- }
- else {
- /*
- * 4th element holds numeric form, don't resolve.
- * see ipaddr().
- */
+ sa = tmp;
+ MEMZERO(&hints, struct addrinfo, 1);
+ if (RARRAY_LEN(sa) == 3) {
+ af = RARRAY_AREF(sa, 0);
+ port = RARRAY_AREF(sa, 1);
+ host = RARRAY_AREF(sa, 2);
+ }
+ else if (RARRAY_LEN(sa) >= 4) {
+ af = RARRAY_AREF(sa, 0);
+ port = RARRAY_AREF(sa, 1);
+ host = RARRAY_AREF(sa, 3);
+ if (NIL_P(host)) {
+ host = RARRAY_AREF(sa, 2);
+ }
+ else {
+ /*
+ * 4th element holds numeric form, don't resolve.
+ * see rsock_ipaddr().
+ */
#ifdef AI_NUMERICHOST /* AIX 4.3.3 doesn't have AI_NUMERICHOST. */
- hints.ai_flags |= AI_NUMERICHOST;
-#endif
- }
- }
- else {
- rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
- RARRAY(sa)->len);
- }
- /* host */
- if (NIL_P(host)) {
- hptr = NULL;
- }
- else {
- strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
- hbuf[sizeof(hbuf) - 1] = '\0';
- hptr = hbuf;
- }
- /* port */
- if (NIL_P(port)) {
- strcpy(pbuf, "0");
- pptr = NULL;
- }
- else if (FIXNUM_P(port)) {
- snprintf(pbuf, sizeof(pbuf), "%ld", NUM2LONG(port));
- pptr = pbuf;
- }
- else {
- strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
- pbuf[sizeof(pbuf) - 1] = '\0';
- pptr = pbuf;
- }
- hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
- /* af */
- if (NIL_P(af)) {
- hints.ai_family = PF_UNSPEC;
- }
- else if (FIXNUM_P(af)) {
- hints.ai_family = FIX2INT(af);
- }
- else if ((ap = StringValuePtr(af)) != 0) {
- if (strcmp(ap, "AF_INET") == 0) {
- hints.ai_family = PF_INET;
- }
-#ifdef INET6
- else if (strcmp(ap, "AF_INET6") == 0) {
- hints.ai_family = PF_INET6;
- }
+ hints.ai_flags |= AI_NUMERICHOST;
#endif
- }
- error = getaddrinfo(hptr, pptr, &hints, &res);
- if (error) goto error_exit_addr;
- sap = res->ai_addr;
+ }
+ }
+ else {
+ rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
+ RARRAY_LEN(sa));
+ }
+ hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
+ /* af */
+ hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af);
+ res = rsock_getaddrinfo(host, port, &hints, 0, Qnil);
+ sap = res->ai->ai_addr;
+ salen = res->ai->ai_addrlen;
}
else {
- rb_raise(rb_eTypeError, "expecting String or Array");
+ rb_raise(rb_eTypeError, "expecting String or Array");
}
call_nameinfo:
- error = getnameinfo(sap, SA_LEN(sap), hbuf, sizeof(hbuf),
- pbuf, sizeof(pbuf), fl);
+ error = rb_getnameinfo(sap, salen, hbuf, sizeof(hbuf),
+ pbuf, sizeof(pbuf), fl);
if (error) goto error_exit_name;
if (res) {
- for (r = res->ai_next; r; r = r->ai_next) {
- char hbuf2[1024], pbuf2[1024];
-
- sap = r->ai_addr;
- error = getnameinfo(sap, SA_LEN(sap), hbuf2, sizeof(hbuf2),
- pbuf2, sizeof(pbuf2), fl);
- if (error) goto error_exit_name;
- if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
- freeaddrinfo(res);
- rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
- }
- }
- freeaddrinfo(res);
+ for (r = res->ai->ai_next; r; r = r->ai_next) {
+ char hbuf2[1024], pbuf2[1024];
+
+ sap = r->ai_addr;
+ salen = r->ai_addrlen;
+ error = rb_getnameinfo(sap, salen, hbuf2, sizeof(hbuf2),
+ pbuf2, sizeof(pbuf2), fl);
+ if (error) goto error_exit_name;
+ if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
+ rb_freeaddrinfo(res);
+ rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
+ }
+ }
+ rb_freeaddrinfo(res);
}
return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
- error_exit_addr:
- if (res) freeaddrinfo(res);
- rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
-
error_exit_name:
- if (res) freeaddrinfo(res);
- rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
+ saved_errno = errno;
+ if (res) rb_freeaddrinfo(res);
+ errno = saved_errno;
+ rsock_raise_resolution_error("getnameinfo", error);
+
+ UNREACHABLE_RETURN(Qnil);
}
+/*
+ * call-seq:
+ * Socket.sockaddr_in(port, host) => sockaddr
+ * Socket.pack_sockaddr_in(port, host) => sockaddr
+ *
+ * Packs _port_ and _host_ as an AF_INET/AF_INET6 sockaddr string.
+ *
+ * Socket.sockaddr_in(80, "127.0.0.1")
+ * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
+ *
+ * Socket.sockaddr_in(80, "::1")
+ * #=> "\n\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00"
+ *
+ */
static VALUE
-sock_s_pack_sockaddr_in(self, port, host)
- VALUE self, port, host;
+sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host)
{
- struct addrinfo *res = sock_addrinfo(host, port, 0, 0);
- VALUE addr = rb_str_new((char*)res->ai_addr, res->ai_addrlen);
+ struct rb_addrinfo *res = rsock_addrinfo(host, port, AF_UNSPEC, 0, 0, Qnil);
+ VALUE addr = rb_str_new((char*)res->ai->ai_addr, res->ai->ai_addrlen);
- freeaddrinfo(res);
- OBJ_INFECT(addr, port);
- OBJ_INFECT(addr, host);
+ rb_freeaddrinfo(res);
return addr;
}
+/*
+ * call-seq:
+ * Socket.unpack_sockaddr_in(sockaddr) => [port, ip_address]
+ *
+ * Unpacks _sockaddr_ into port and ip_address.
+ *
+ * _sockaddr_ should be a string or an addrinfo for AF_INET/AF_INET6.
+ *
+ * sockaddr = Socket.sockaddr_in(80, "127.0.0.1")
+ * p sockaddr #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
+ * p Socket.unpack_sockaddr_in(sockaddr) #=> [80, "127.0.0.1"]
+ *
+ */
static VALUE
-sock_s_unpack_sockaddr_in(self, addr)
- VALUE self, addr;
+sock_s_unpack_sockaddr_in(VALUE self, VALUE addr)
{
struct sockaddr_in * sockaddr;
VALUE host;
- sockaddr = (struct sockaddr_in*)StringValuePtr(addr);
+ sockaddr = (struct sockaddr_in*)SockAddrStringValuePtr(addr);
+ if (RSTRING_LEN(addr) <
+ (char*)&((struct sockaddr *)sockaddr)->sa_family +
+ sizeof(((struct sockaddr *)sockaddr)->sa_family) -
+ (char*)sockaddr)
+ rb_raise(rb_eArgError, "too short sockaddr");
if (((struct sockaddr *)sockaddr)->sa_family != AF_INET
#ifdef INET6
&& ((struct sockaddr *)sockaddr)->sa_family != AF_INET6
@@ -3753,909 +1379,728 @@ sock_s_unpack_sockaddr_in(self, addr)
rb_raise(rb_eArgError, "not an AF_INET sockaddr");
#endif
}
- host = make_ipaddr((struct sockaddr*)sockaddr);
- OBJ_INFECT(host, addr);
+ host = rsock_make_ipaddr((struct sockaddr*)sockaddr, RSTRING_SOCKLEN(addr));
return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host);
}
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+
+/*
+ * call-seq:
+ * Socket.sockaddr_un(path) => sockaddr
+ * Socket.pack_sockaddr_un(path) => sockaddr
+ *
+ * Packs _path_ as an AF_UNIX sockaddr string.
+ *
+ * Socket.sockaddr_un("/tmp/sock") #=> "\x01\x00/tmp/sock\x00\x00..."
+ *
+ */
static VALUE
-sock_s_pack_sockaddr_un(self, path)
- VALUE self, path;
+sock_s_pack_sockaddr_un(VALUE self, VALUE path)
{
struct sockaddr_un sockaddr;
- char *sun_path;
VALUE addr;
- MEMZERO(&sockaddr, struct sockaddr_un, 1);
- sockaddr.sun_family = AF_UNIX;
- sun_path = StringValueCStr(path);
- if (sizeof(sockaddr.sun_path) <= strlen(sun_path)) {
- rb_raise(rb_eArgError, "too long unix socket path (max: %dbytes)",
- (int)sizeof(sockaddr.sun_path)-1);
+ StringValue(path);
+ INIT_SOCKADDR_UN(&sockaddr, sizeof(struct sockaddr_un));
+ if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) {
+ rb_raise(rb_eArgError, "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
+ (size_t)RSTRING_LEN(path), sizeof(sockaddr.sun_path));
}
- strncpy(sockaddr.sun_path, sun_path, sizeof(sockaddr.sun_path)-1);
- addr = rb_str_new((char*)&sockaddr, sizeof(sockaddr));
- OBJ_INFECT(addr, path);
+ memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
+ addr = rb_str_new((char*)&sockaddr, rsock_unix_sockaddr_len(path));
return addr;
}
+/*
+ * call-seq:
+ * Socket.unpack_sockaddr_un(sockaddr) => path
+ *
+ * Unpacks _sockaddr_ into path.
+ *
+ * _sockaddr_ should be a string or an addrinfo for AF_UNIX.
+ *
+ * sockaddr = Socket.sockaddr_un("/tmp/sock")
+ * p Socket.unpack_sockaddr_un(sockaddr) #=> "/tmp/sock"
+ *
+ */
static VALUE
-sock_s_unpack_sockaddr_un(self, addr)
- VALUE self, addr;
+sock_s_unpack_sockaddr_un(VALUE self, VALUE addr)
{
struct sockaddr_un * sockaddr;
- char *sun_path;
VALUE path;
- sockaddr = (struct sockaddr_un*)StringValuePtr(addr);
+ sockaddr = (struct sockaddr_un*)SockAddrStringValuePtr(addr);
+ if (RSTRING_LEN(addr) <
+ (char*)&((struct sockaddr *)sockaddr)->sa_family +
+ sizeof(((struct sockaddr *)sockaddr)->sa_family) -
+ (char*)sockaddr)
+ rb_raise(rb_eArgError, "too short sockaddr");
if (((struct sockaddr *)sockaddr)->sa_family != AF_UNIX) {
rb_raise(rb_eArgError, "not an AF_UNIX sockaddr");
}
- if (sizeof(struct sockaddr_un) < RSTRING(addr)->len) {
+ if (sizeof(struct sockaddr_un) < (size_t)RSTRING_LEN(addr)) {
rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d",
- RSTRING(addr)->len, sizeof(struct sockaddr_un));
+ RSTRING_LEN(addr), (int)sizeof(struct sockaddr_un));
}
- sun_path = unixpath(sockaddr, RSTRING(addr)->len);
- if (sizeof(struct sockaddr_un) == RSTRING(addr)->len &&
- sun_path == sockaddr->sun_path &&
- sun_path + strlen(sun_path) == RSTRING(addr)->ptr + RSTRING(addr)->len) {
- rb_raise(rb_eArgError, "sockaddr_un.sun_path not NUL terminated");
- }
- path = rb_str_new2(sun_path);
- OBJ_INFECT(path, addr);
+ path = rsock_unixpath_str(sockaddr, RSTRING_SOCKLEN(addr));
return path;
}
#endif
-static VALUE mConst;
+#if defined(HAVE_GETIFADDRS) || defined(SIOCGLIFCONF) || defined(SIOCGIFCONF) || defined(_WIN32)
-static void
-sock_define_const(name, value)
- char *name;
- int value;
+static socklen_t
+sockaddr_len(struct sockaddr *addr)
{
- rb_define_const(rb_cSocket, name, INT2FIX(value));
- rb_define_const(mConst, name, INT2FIX(value));
-}
+ if (addr == NULL)
+ return 0;
-/*
- * Class +Socket+ provides access to the underlying operating system
- * socket implementations. It can be used to provide more operating system
- * specific functionality than the protocol-specific socket classes but at the
- * expense of greater complexity. In particular, the class handles addresses
- * using +struct sockaddr+ structures packed into Ruby strings, which can be
- * a joy to manipulate.
- *
- * === Exception Handling
- * Ruby's implementation of +Socket+ causes an exception to be raised
- * based on the error generated by the system dependent implementation.
- * This is why the methods are documented in a way that isolate
- * Unix-based system exceptions from Windows based exceptions. If more
- * information on particular exception is needed please refer to the
- * Unix manual pages or the Windows WinSock reference.
- *
- *
- * === Documentation by
- * * Zach Dennis
- * * Sam Roberts
- * * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
- *
- * Much material in this documentation is taken with permission from
- * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
- */
-void
-Init_socket()
-{
- rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
-
- rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
- rb_undef_method(rb_cBasicSocket, "initialize");
-
- rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
- bsock_do_not_rev_lookup, 0);
- rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
- bsock_do_not_rev_lookup_set, 1);
- rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1);
-
- rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
- rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
- rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
- rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, 3);
- rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2);
- rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0);
- rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
- rb_define_method(rb_cBasicSocket, "send", bsock_send, -1);
- rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
- rb_define_method(rb_cBasicSocket, "recv_nonblock", bsock_recv_nonblock, -1);
-
- rb_cIPSocket = rb_define_class("IPSocket", rb_cBasicSocket);
- rb_define_global_const("IPsocket", rb_cIPSocket);
- rb_define_method(rb_cIPSocket, "addr", ip_addr, 0);
- rb_define_method(rb_cIPSocket, "peeraddr", ip_peeraddr, 0);
- rb_define_method(rb_cIPSocket, "recvfrom", ip_recvfrom, -1);
- rb_define_singleton_method(rb_cIPSocket, "getaddress", ip_s_getaddress, 1);
-
- rb_cTCPSocket = rb_define_class("TCPSocket", rb_cIPSocket);
- rb_define_global_const("TCPsocket", rb_cTCPSocket);
- rb_define_singleton_method(rb_cTCPSocket, "gethostbyname", tcp_s_gethostbyname, 1);
- rb_define_method(rb_cTCPSocket, "initialize", tcp_init, -1);
-
-#ifdef SOCKS
- rb_cSOCKSSocket = rb_define_class("SOCKSSocket", rb_cTCPSocket);
- rb_define_global_const("SOCKSsocket", rb_cSOCKSSocket);
- rb_define_method(rb_cSOCKSSocket, "initialize", socks_init, 2);
-#ifdef SOCKS5
- rb_define_method(rb_cSOCKSSocket, "close", socks_s_close, 0);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ if (addr->sa_len != 0)
+ return addr->sa_len;
#endif
+
+ switch (addr->sa_family) {
+ case AF_INET:
+ return (socklen_t)sizeof(struct sockaddr_in);
+
+#ifdef AF_INET6
+ case AF_INET6:
+ return (socklen_t)sizeof(struct sockaddr_in6);
#endif
- rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
- rb_define_global_const("TCPserver", rb_cTCPServer);
- rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
- rb_define_method(rb_cTCPServer, "accept_nonblock", tcp_accept_nonblock, 0);
- rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
- rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
- rb_define_method(rb_cTCPServer, "listen", sock_listen, 1);
-
- rb_cUDPSocket = rb_define_class("UDPSocket", rb_cIPSocket);
- rb_define_global_const("UDPsocket", rb_cUDPSocket);
- rb_define_method(rb_cUDPSocket, "initialize", udp_init, -1);
- rb_define_method(rb_cUDPSocket, "connect", udp_connect, 2);
- rb_define_method(rb_cUDPSocket, "bind", udp_bind, 2);
- rb_define_method(rb_cUDPSocket, "send", udp_send, -1);
- rb_define_method(rb_cUDPSocket, "recvfrom_nonblock", udp_recvfrom_nonblock, -1);
-
-#ifdef HAVE_SYS_UN_H
- rb_cUNIXSocket = rb_define_class("UNIXSocket", rb_cBasicSocket);
- rb_define_global_const("UNIXsocket", rb_cUNIXSocket);
- rb_define_method(rb_cUNIXSocket, "initialize", unix_init, 1);
- rb_define_method(rb_cUNIXSocket, "path", unix_path, 0);
- rb_define_method(rb_cUNIXSocket, "addr", unix_addr, 0);
- rb_define_method(rb_cUNIXSocket, "peeraddr", unix_peeraddr, 0);
- rb_define_method(rb_cUNIXSocket, "recvfrom", unix_recvfrom, -1);
- rb_define_method(rb_cUNIXSocket, "send_io", unix_send_io, 1);
- rb_define_method(rb_cUNIXSocket, "recv_io", unix_recv_io, -1);
- rb_define_singleton_method(rb_cUNIXSocket, "socketpair", unix_s_socketpair, -1);
- rb_define_singleton_method(rb_cUNIXSocket, "pair", unix_s_socketpair, -1);
-
- rb_cUNIXServer = rb_define_class("UNIXServer", rb_cUNIXSocket);
- rb_define_global_const("UNIXserver", rb_cUNIXServer);
- rb_define_method(rb_cUNIXServer, "initialize", unix_svr_init, 1);
- rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0);
- rb_define_method(rb_cUNIXServer, "accept_nonblock", unix_accept_nonblock, 0);
- rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0);
- rb_define_method(rb_cUNIXServer, "listen", sock_listen, 1);
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ case AF_UNIX:
+ return (socklen_t)sizeof(struct sockaddr_un);
#endif
- rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
+#ifdef AF_PACKET
+ case AF_PACKET:
+ return (socklen_t)(offsetof(struct sockaddr_ll, sll_addr) + ((struct sockaddr_ll *)addr)->sll_halen);
+#endif
- rb_define_method(rb_cSocket, "initialize", sock_initialize, 3);
- rb_define_method(rb_cSocket, "connect", sock_connect, 1);
- rb_define_method(rb_cSocket, "connect_nonblock", sock_connect_nonblock, 1);
- rb_define_method(rb_cSocket, "bind", sock_bind, 1);
- rb_define_method(rb_cSocket, "listen", sock_listen, 1);
- rb_define_method(rb_cSocket, "accept", sock_accept, 0);
- rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, 0);
- rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
+ default:
+ return (socklen_t)(offsetof(struct sockaddr, sa_family) + sizeof(addr->sa_family));
+ }
+}
- rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
- rb_define_method(rb_cSocket, "recvfrom_nonblock", sock_recvfrom_nonblock, -1);
+socklen_t
+rsock_sockaddr_len(struct sockaddr *addr)
+{
+ return sockaddr_len(addr);
+}
- rb_define_singleton_method(rb_cSocket, "socketpair", sock_s_socketpair, 3);
- rb_define_singleton_method(rb_cSocket, "pair", sock_s_socketpair, 3);
- rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0);
- rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
- rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
- rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyaname, -1);
- rb_define_singleton_method(rb_cSocket, "getaddrinfo", sock_s_getaddrinfo, -1);
- rb_define_singleton_method(rb_cSocket, "getnameinfo", sock_s_getnameinfo, -1);
- rb_define_singleton_method(rb_cSocket, "sockaddr_in", sock_s_pack_sockaddr_in, 2);
- rb_define_singleton_method(rb_cSocket, "pack_sockaddr_in", sock_s_pack_sockaddr_in, 2);
- rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_in", sock_s_unpack_sockaddr_in, 1);
-#ifdef HAVE_SYS_UN_H
- rb_define_singleton_method(rb_cSocket, "sockaddr_un", sock_s_pack_sockaddr_un, 1);
- rb_define_singleton_method(rb_cSocket, "pack_sockaddr_un", sock_s_pack_sockaddr_un, 1);
- rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_un", sock_s_unpack_sockaddr_un, 1);
+static VALUE
+sockaddr_obj(struct sockaddr *addr, socklen_t len)
+{
+#if defined(AF_INET6) && defined(__KAME__)
+ struct sockaddr_in6 addr6;
#endif
- /* constants */
- mConst = rb_define_module_under(rb_cSocket, "Constants");
- sock_define_const("SOCK_STREAM", SOCK_STREAM);
- sock_define_const("SOCK_DGRAM", SOCK_DGRAM);
-#ifdef SOCK_RAW
- sock_define_const("SOCK_RAW", SOCK_RAW);
-#endif
-#ifdef SOCK_RDM
- sock_define_const("SOCK_RDM", SOCK_RDM);
-#endif
-#ifdef SOCK_SEQPACKET
- sock_define_const("SOCK_SEQPACKET", SOCK_SEQPACKET);
-#endif
-#ifdef SOCK_PACKET
- sock_define_const("SOCK_PACKET", SOCK_PACKET);
-#endif
+ if (addr == NULL)
+ return Qnil;
- sock_define_const("AF_INET", AF_INET);
-#ifdef PF_INET
- sock_define_const("PF_INET", PF_INET);
-#endif
-#ifdef AF_UNIX
- sock_define_const("AF_UNIX", AF_UNIX);
- sock_define_const("PF_UNIX", PF_UNIX);
-#endif
-#ifdef AF_AX25
- sock_define_const("AF_AX25", AF_AX25);
- sock_define_const("PF_AX25", PF_AX25);
-#endif
-#ifdef AF_IPX
- sock_define_const("AF_IPX", AF_IPX);
- sock_define_const("PF_IPX", PF_IPX);
-#endif
-#ifdef AF_APPLETALK
- sock_define_const("AF_APPLETALK", AF_APPLETALK);
- sock_define_const("PF_APPLETALK", PF_APPLETALK);
-#endif
-#ifdef AF_UNSPEC
- sock_define_const("AF_UNSPEC", AF_UNSPEC);
- sock_define_const("PF_UNSPEC", PF_UNSPEC);
-#endif
-#ifdef INET6
- sock_define_const("AF_INET6", AF_INET6);
-#endif
-#ifdef INET6
- sock_define_const("PF_INET6", PF_INET6);
-#endif
-#ifdef AF_LOCAL
- sock_define_const("AF_LOCAL", AF_LOCAL);
-#endif
-#ifdef PF_LOCAL
- sock_define_const("PF_LOCAL", PF_LOCAL);
-#endif
-#ifdef AF_IMPLINK
- sock_define_const("AF_IMPLINK", AF_IMPLINK);
-#endif
-#ifdef PF_IMPLINK
- sock_define_const("PF_IMPLINK", PF_IMPLINK);
-#endif
-#ifdef AF_PUP
- sock_define_const("AF_PUP", AF_PUP);
-#endif
-#ifdef PF_PUP
- sock_define_const("PF_PUP", PF_PUP);
-#endif
-#ifdef AF_CHAOS
- sock_define_const("AF_CHAOS", AF_CHAOS);
-#endif
-#ifdef PF_CHAOS
- sock_define_const("PF_CHAOS", PF_CHAOS);
-#endif
-#ifdef AF_NS
- sock_define_const("AF_NS", AF_NS);
-#endif
-#ifdef PF_NS
- sock_define_const("PF_NS", PF_NS);
-#endif
-#ifdef AF_ISO
- sock_define_const("AF_ISO", AF_ISO);
-#endif
-#ifdef PF_ISO
- sock_define_const("PF_ISO", PF_ISO);
-#endif
-#ifdef AF_OSI
- sock_define_const("AF_OSI", AF_OSI);
-#endif
-#ifdef PF_OSI
- sock_define_const("PF_OSI", PF_OSI);
-#endif
-#ifdef AF_ECMA
- sock_define_const("AF_ECMA", AF_ECMA);
-#endif
-#ifdef PF_ECMA
- sock_define_const("PF_ECMA", PF_ECMA);
-#endif
-#ifdef AF_DATAKIT
- sock_define_const("AF_DATAKIT", AF_DATAKIT);
-#endif
-#ifdef PF_DATAKIT
- sock_define_const("PF_DATAKIT", PF_DATAKIT);
-#endif
-#ifdef AF_CCITT
- sock_define_const("AF_CCITT", AF_CCITT);
-#endif
-#ifdef PF_CCITT
- sock_define_const("PF_CCITT", PF_CCITT);
-#endif
-#ifdef AF_SNA
- sock_define_const("AF_SNA", AF_SNA);
-#endif
-#ifdef PF_SNA
- sock_define_const("PF_SNA", PF_SNA);
-#endif
-#ifdef AF_DEC
- sock_define_const("AF_DEC", AF_DEC);
-#endif
-#ifdef PF_DEC
- sock_define_const("PF_DEC", PF_DEC);
-#endif
-#ifdef AF_DLI
- sock_define_const("AF_DLI", AF_DLI);
-#endif
-#ifdef PF_DLI
- sock_define_const("PF_DLI", PF_DLI);
-#endif
-#ifdef AF_LAT
- sock_define_const("AF_LAT", AF_LAT);
-#endif
-#ifdef PF_LAT
- sock_define_const("PF_LAT", PF_LAT);
-#endif
-#ifdef AF_HYLINK
- sock_define_const("AF_HYLINK", AF_HYLINK);
-#endif
-#ifdef PF_HYLINK
- sock_define_const("PF_HYLINK", PF_HYLINK);
-#endif
-#ifdef AF_ROUTE
- sock_define_const("AF_ROUTE", AF_ROUTE);
-#endif
-#ifdef PF_ROUTE
- sock_define_const("PF_ROUTE", PF_ROUTE);
-#endif
-#ifdef AF_LINK
- sock_define_const("AF_LINK", AF_LINK);
-#endif
-#ifdef PF_LINK
- sock_define_const("PF_LINK", PF_LINK);
-#endif
-#ifdef AF_COIP
- sock_define_const("AF_COIP", AF_COIP);
-#endif
-#ifdef PF_COIP
- sock_define_const("PF_COIP", PF_COIP);
-#endif
-#ifdef AF_CNT
- sock_define_const("AF_CNT", AF_CNT);
-#endif
-#ifdef PF_CNT
- sock_define_const("PF_CNT", PF_CNT);
-#endif
-#ifdef AF_SIP
- sock_define_const("AF_SIP", AF_SIP);
-#endif
-#ifdef PF_SIP
- sock_define_const("PF_SIP", PF_SIP);
-#endif
-#ifdef AF_NDRV
- sock_define_const("AF_NDRV", AF_NDRV);
-#endif
-#ifdef PF_NDRV
- sock_define_const("PF_NDRV", PF_NDRV);
-#endif
-#ifdef AF_ISDN
- sock_define_const("AF_ISDN", AF_ISDN);
-#endif
-#ifdef PF_ISDN
- sock_define_const("PF_ISDN", PF_ISDN);
-#endif
-#ifdef AF_NATM
- sock_define_const("AF_NATM", AF_NATM);
-#endif
-#ifdef PF_NATM
- sock_define_const("PF_NATM", PF_NATM);
-#endif
-#ifdef AF_SYSTEM
- sock_define_const("AF_SYSTEM", AF_SYSTEM);
-#endif
-#ifdef PF_SYSTEM
- sock_define_const("PF_SYSTEM", PF_SYSTEM);
-#endif
-#ifdef AF_NETBIOS
- sock_define_const("AF_NETBIOS", AF_NETBIOS);
-#endif
-#ifdef PF_NETBIOS
- sock_define_const("PF_NETBIOS", PF_NETBIOS);
-#endif
-#ifdef AF_PPP
- sock_define_const("AF_PPP", AF_PPP);
-#endif
-#ifdef PF_PPP
- sock_define_const("PF_PPP", PF_PPP);
-#endif
-#ifdef AF_ATM
- sock_define_const("AF_ATM", AF_ATM);
-#endif
-#ifdef PF_ATM
- sock_define_const("PF_ATM", PF_ATM);
-#endif
-#ifdef AF_NETGRAPH
- sock_define_const("AF_NETGRAPH", AF_NETGRAPH);
-#endif
-#ifdef PF_NETGRAPH
- sock_define_const("PF_NETGRAPH", PF_NETGRAPH);
-#endif
-#ifdef AF_MAX
- sock_define_const("AF_MAX", AF_MAX);
-#endif
-#ifdef PF_MAX
- sock_define_const("PF_MAX", PF_MAX);
-#endif
-#ifdef AF_E164
- sock_define_const("AF_E164", AF_E164);
-#endif
-#ifdef PF_XTP
- sock_define_const("PF_XTP", PF_XTP);
-#endif
-#ifdef PF_RTIP
- sock_define_const("PF_RTIP", PF_RTIP);
-#endif
-#ifdef PF_PIP
- sock_define_const("PF_PIP", PF_PIP);
-#endif
-#ifdef PF_KEY
- sock_define_const("PF_KEY", PF_KEY);
-#endif
+ len = sockaddr_len(addr);
- sock_define_const("MSG_OOB", MSG_OOB);
-#ifdef MSG_PEEK
- sock_define_const("MSG_PEEK", MSG_PEEK);
-#endif
-#ifdef MSG_DONTROUTE
- sock_define_const("MSG_DONTROUTE", MSG_DONTROUTE);
-#endif
-#ifdef MSG_EOR
- sock_define_const("MSG_EOR", MSG_EOR);
-#endif
-#ifdef MSG_TRUNC
- sock_define_const("MSG_TRUNC", MSG_TRUNC);
-#endif
-#ifdef MSG_CTRUNC
- sock_define_const("MSG_CTRUNC", MSG_CTRUNC);
-#endif
-#ifdef MSG_WAITALL
- sock_define_const("MSG_WAITALL", MSG_WAITALL);
-#endif
-#ifdef MSG_DONTWAIT
- sock_define_const("MSG_DONTWAIT", MSG_DONTWAIT);
-#endif
-#ifdef MSG_EOF
- sock_define_const("MSG_EOF", MSG_EOF);
-#endif
-#ifdef MSG_FLUSH
- sock_define_const("MSG_FLUSH", MSG_FLUSH);
-#endif
-#ifdef MSG_HOLD
- sock_define_const("MSG_HOLD", MSG_HOLD);
-#endif
-#ifdef MSG_SEND
- sock_define_const("MSG_SEND", MSG_SEND);
-#endif
-#ifdef MSG_HAVEMORE
- sock_define_const("MSG_HAVEMORE", MSG_HAVEMORE);
-#endif
-#ifdef MSG_RCVMORE
- sock_define_const("MSG_RCVMORE", MSG_RCVMORE);
-#endif
-#ifdef MSG_COMPAT
- sock_define_const("MSG_COMPAT", MSG_COMPAT);
+#if defined(__KAME__) && defined(AF_INET6)
+ if (addr->sa_family == AF_INET6) {
+ /* KAME uses the 2nd 16bit word of link local IPv6 address as interface index internally */
+ /* http://orange.kame.net/dev/cvsweb.cgi/kame/IMPLEMENTATION */
+ /* convert fe80:1::1 to fe80::1%1 */
+ len = (socklen_t)sizeof(struct sockaddr_in6);
+ memcpy(&addr6, addr, len);
+ addr = (struct sockaddr *)&addr6;
+ if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) &&
+ addr6.sin6_scope_id == 0 &&
+ (addr6.sin6_addr.s6_addr[2] || addr6.sin6_addr.s6_addr[3])) {
+ addr6.sin6_scope_id = (addr6.sin6_addr.s6_addr[2] << 8) | addr6.sin6_addr.s6_addr[3];
+ addr6.sin6_addr.s6_addr[2] = 0;
+ addr6.sin6_addr.s6_addr[3] = 0;
+ }
+ }
#endif
- sock_define_const("SOL_SOCKET", SOL_SOCKET);
-#ifdef SOL_IP
- sock_define_const("SOL_IP", SOL_IP);
-#endif
-#ifdef SOL_IPX
- sock_define_const("SOL_IPX", SOL_IPX);
-#endif
-#ifdef SOL_AX25
- sock_define_const("SOL_AX25", SOL_AX25);
-#endif
-#ifdef SOL_ATALK
- sock_define_const("SOL_ATALK", SOL_ATALK);
-#endif
-#ifdef SOL_TCP
- sock_define_const("SOL_TCP", SOL_TCP);
-#endif
-#ifdef SOL_UDP
- sock_define_const("SOL_UDP", SOL_UDP);
-#endif
+ return rsock_addrinfo_new(addr, len, addr->sa_family, 0, 0, Qnil, Qnil);
+}
-#ifdef IPPROTO_IP
- sock_define_const("IPPROTO_IP", IPPROTO_IP);
-#else
- sock_define_const("IPPROTO_IP", 0);
-#endif
-#ifdef IPPROTO_ICMP
- sock_define_const("IPPROTO_ICMP", IPPROTO_ICMP);
-#else
- sock_define_const("IPPROTO_ICMP", 1);
-#endif
-#ifdef IPPROTO_IGMP
- sock_define_const("IPPROTO_IGMP", IPPROTO_IGMP);
-#endif
-#ifdef IPPROTO_GGP
- sock_define_const("IPPROTO_GGP", IPPROTO_GGP);
-#endif
-#ifdef IPPROTO_TCP
- sock_define_const("IPPROTO_TCP", IPPROTO_TCP);
-#else
- sock_define_const("IPPROTO_TCP", 6);
-#endif
-#ifdef IPPROTO_EGP
- sock_define_const("IPPROTO_EGP", IPPROTO_EGP);
-#endif
-#ifdef IPPROTO_PUP
- sock_define_const("IPPROTO_PUP", IPPROTO_PUP);
-#endif
-#ifdef IPPROTO_UDP
- sock_define_const("IPPROTO_UDP", IPPROTO_UDP);
-#else
- sock_define_const("IPPROTO_UDP", 17);
-#endif
-#ifdef IPPROTO_IDP
- sock_define_const("IPPROTO_IDP", IPPROTO_IDP);
-#endif
-#ifdef IPPROTO_HELLO
- sock_define_const("IPPROTO_HELLO", IPPROTO_HELLO);
-#endif
-#ifdef IPPROTO_ND
- sock_define_const("IPPROTO_ND", IPPROTO_ND);
-#endif
-#ifdef IPPROTO_TP
- sock_define_const("IPPROTO_TP", IPPROTO_TP);
-#endif
-#ifdef IPPROTO_XTP
- sock_define_const("IPPROTO_XTP", IPPROTO_XTP);
-#endif
-#ifdef IPPROTO_EON
- sock_define_const("IPPROTO_EON", IPPROTO_EON);
-#endif
-#ifdef IPPROTO_BIP
- sock_define_const("IPPROTO_BIP", IPPROTO_BIP);
-#endif
-/**/
-#ifdef IPPROTO_RAW
- sock_define_const("IPPROTO_RAW", IPPROTO_RAW);
-#else
- sock_define_const("IPPROTO_RAW", 255);
-#endif
-#ifdef IPPROTO_MAX
- sock_define_const("IPPROTO_MAX", IPPROTO_MAX);
-#endif
+VALUE
+rsock_sockaddr_obj(struct sockaddr *addr, socklen_t len)
+{
+ return sockaddr_obj(addr, len);
+}
- /* Some port configuration */
-#ifdef IPPORT_RESERVED
- sock_define_const("IPPORT_RESERVED", IPPORT_RESERVED);
-#else
- sock_define_const("IPPORT_RESERVED", 1024);
-#endif
-#ifdef IPPORT_USERRESERVED
- sock_define_const("IPPORT_USERRESERVED", IPPORT_USERRESERVED);
-#else
- sock_define_const("IPPORT_USERRESERVED", 5000);
-#endif
- /* Some reserved IP v.4 addresses */
-#ifdef INADDR_ANY
- sock_define_const("INADDR_ANY", INADDR_ANY);
-#else
- sock_define_const("INADDR_ANY", 0x00000000);
#endif
-#ifdef INADDR_BROADCAST
- sock_define_const("INADDR_BROADCAST", INADDR_BROADCAST);
-#else
- sock_define_const("INADDR_BROADCAST", 0xffffffff);
+
+#if defined(HAVE_GETIFADDRS) || (defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM)) || defined(SIOCGIFCONF) || defined(_WIN32)
+/*
+ * call-seq:
+ * Socket.ip_address_list => array
+ *
+ * Returns local IP addresses as an array.
+ *
+ * The array contains Addrinfo objects.
+ *
+ * pp Socket.ip_address_list
+ * #=> [#<Addrinfo: 127.0.0.1>,
+ * #<Addrinfo: 192.168.0.128>,
+ * #<Addrinfo: ::1>,
+ * ...]
+ *
+ */
+static VALUE
+socket_s_ip_address_list(VALUE self)
+{
+#if defined(HAVE_GETIFADDRS)
+ struct ifaddrs *ifp = NULL;
+ struct ifaddrs *p;
+ int ret;
+ VALUE list;
+
+ ret = getifaddrs(&ifp);
+ if (ret == -1) {
+ rb_sys_fail("getifaddrs");
+ }
+
+ list = rb_ary_new();
+ for (p = ifp; p; p = p->ifa_next) {
+ if (p->ifa_addr != NULL && IS_IP_FAMILY(p->ifa_addr->sa_family)) {
+ struct sockaddr *addr = p->ifa_addr;
+#if defined(AF_INET6) && defined(__sun)
+ /*
+ * OpenIndiana SunOS 5.11 getifaddrs() returns IPv6 link local
+ * address with sin6_scope_id == 0.
+ * So fill it from the interface name (ifa_name).
+ */
+ struct sockaddr_in6 addr6;
+ if (addr->sa_family == AF_INET6) {
+ socklen_t len = (socklen_t)sizeof(struct sockaddr_in6);
+ memcpy(&addr6, addr, len);
+ addr = (struct sockaddr *)&addr6;
+ if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) &&
+ addr6.sin6_scope_id == 0) {
+ unsigned int ifindex = if_nametoindex(p->ifa_name);
+ if (ifindex != 0) {
+ addr6.sin6_scope_id = ifindex;
+ }
+ }
+ }
#endif
-#ifdef INADDR_LOOPBACK
- sock_define_const("INADDR_LOOPBACK", INADDR_LOOPBACK);
+ rb_ary_push(list, sockaddr_obj(addr, sockaddr_len(addr)));
+ }
+ }
+
+ freeifaddrs(ifp);
+
+ return list;
+#elif defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM)
+ /* Solaris if_tcp(7P) */
+ int fd = -1;
+ int ret;
+ struct lifnum ln;
+ struct lifconf lc;
+ const char *reason = NULL;
+ int save_errno;
+ int i;
+ VALUE list = Qnil;
+
+ lc.lifc_buf = NULL;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd == -1)
+ rb_sys_fail("socket(2)");
+
+ memset(&ln, 0, sizeof(ln));
+ ln.lifn_family = AF_UNSPEC;
+
+ ret = ioctl(fd, SIOCGLIFNUM, &ln);
+ if (ret == -1) {
+ reason = "SIOCGLIFNUM";
+ goto finish;
+ }
+
+ memset(&lc, 0, sizeof(lc));
+ lc.lifc_family = AF_UNSPEC;
+ lc.lifc_flags = 0;
+ lc.lifc_len = sizeof(struct lifreq) * ln.lifn_count;
+ lc.lifc_req = xmalloc(lc.lifc_len);
+
+ ret = ioctl(fd, SIOCGLIFCONF, &lc);
+ if (ret == -1) {
+ reason = "SIOCGLIFCONF";
+ goto finish;
+ }
+
+ list = rb_ary_new();
+ for (i = 0; i < ln.lifn_count; i++) {
+ struct lifreq *req = &lc.lifc_req[i];
+ if (IS_IP_FAMILY(req->lifr_addr.ss_family)) {
+ if (req->lifr_addr.ss_family == AF_INET6 &&
+ IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_addr) &&
+ ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id == 0) {
+ struct lifreq req2;
+ memcpy(req2.lifr_name, req->lifr_name, LIFNAMSIZ);
+ ret = ioctl(fd, SIOCGLIFINDEX, &req2);
+ if (ret == -1) {
+ reason = "SIOCGLIFINDEX";
+ goto finish;
+ }
+ ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id = req2.lifr_index;
+ }
+ rb_ary_push(list, sockaddr_obj((struct sockaddr *)&req->lifr_addr, req->lifr_addrlen));
+ }
+ }
+
+ finish:
+ save_errno = errno;
+ xfree(lc.lifc_req);
+ if (fd != -1)
+ close(fd);
+ errno = save_errno;
+
+ if (reason)
+ rb_syserr_fail(save_errno, reason);
+ return list;
+
+#elif defined(SIOCGIFCONF)
+ int fd = -1;
+ int ret;
+#define EXTRA_SPACE ((int)(sizeof(struct ifconf) + sizeof(union_sockaddr)))
+ char initbuf[4096+EXTRA_SPACE];
+ char *buf = initbuf;
+ int bufsize;
+ struct ifconf conf;
+ struct ifreq *req;
+ VALUE list = Qnil;
+ const char *reason = NULL;
+ int save_errno;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd == -1)
+ rb_sys_fail("socket(2)");
+
+ bufsize = sizeof(initbuf);
+ buf = initbuf;
+
+ retry:
+ conf.ifc_len = bufsize;
+ conf.ifc_req = (struct ifreq *)buf;
+
+ /* fprintf(stderr, "bufsize: %d\n", bufsize); */
+
+ ret = ioctl(fd, SIOCGIFCONF, &conf);
+ if (ret == -1) {
+ reason = "SIOCGIFCONF";
+ goto finish;
+ }
+
+ /* fprintf(stderr, "conf.ifc_len: %d\n", conf.ifc_len); */
+
+ if (bufsize - EXTRA_SPACE < conf.ifc_len) {
+ if (bufsize < conf.ifc_len) {
+ /* NetBSD returns required size for all interfaces. */
+ bufsize = conf.ifc_len + EXTRA_SPACE;
+ }
+ else {
+ bufsize = bufsize << 1;
+ }
+ if (buf == initbuf)
+ buf = NULL;
+ buf = xrealloc(buf, bufsize);
+ goto retry;
+ }
+
+ close(fd);
+ fd = -1;
+
+ list = rb_ary_new();
+ req = conf.ifc_req;
+ while ((char*)req < (char*)conf.ifc_req + conf.ifc_len) {
+ struct sockaddr *addr = &req->ifr_addr;
+ if (IS_IP_FAMILY(addr->sa_family)) {
+ rb_ary_push(list, sockaddr_obj(addr, sockaddr_len(addr)));
+ }
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+# ifndef _SIZEOF_ADDR_IFREQ
+# define _SIZEOF_ADDR_IFREQ(r) \
+ (sizeof(struct ifreq) + \
+ (sizeof(struct sockaddr) < (r).ifr_addr.sa_len ? \
+ (r).ifr_addr.sa_len - sizeof(struct sockaddr) : \
+ 0))
+# endif
+ req = (struct ifreq *)((char*)req + _SIZEOF_ADDR_IFREQ(*req));
#else
- sock_define_const("INADDR_LOOPBACK", 0x7F000001);
-#endif
-#ifdef INADDR_UNSPEC_GROUP
- sock_define_const("INADDR_UNSPEC_GROUP", INADDR_UNSPEC_GROUP);
+ req = (struct ifreq *)((char*)req + sizeof(struct ifreq));
+#endif
+ }
+
+ finish:
+
+ save_errno = errno;
+ if (buf != initbuf)
+ xfree(buf);
+ if (fd != -1)
+ close(fd);
+ errno = save_errno;
+
+ if (reason)
+ rb_syserr_fail(save_errno, reason);
+ return list;
+
+#undef EXTRA_SPACE
+#elif defined(_WIN32)
+ typedef struct ip_adapter_unicast_address_st {
+ unsigned LONG_LONG dummy0;
+ struct ip_adapter_unicast_address_st *Next;
+ struct {
+ struct sockaddr *lpSockaddr;
+ int iSockaddrLength;
+ } Address;
+ int dummy1;
+ int dummy2;
+ int dummy3;
+ long dummy4;
+ long dummy5;
+ long dummy6;
+ } ip_adapter_unicast_address_t;
+ typedef struct ip_adapter_anycast_address_st {
+ unsigned LONG_LONG dummy0;
+ struct ip_adapter_anycast_address_st *Next;
+ struct {
+ struct sockaddr *lpSockaddr;
+ int iSockaddrLength;
+ } Address;
+ } ip_adapter_anycast_address_t;
+ typedef struct ip_adapter_addresses_st {
+ unsigned LONG_LONG dummy0;
+ struct ip_adapter_addresses_st *Next;
+ void *dummy1;
+ ip_adapter_unicast_address_t *FirstUnicastAddress;
+ ip_adapter_anycast_address_t *FirstAnycastAddress;
+ void *dummy2;
+ void *dummy3;
+ void *dummy4;
+ void *dummy5;
+ void *dummy6;
+ BYTE dummy7[8];
+ DWORD dummy8;
+ DWORD dummy9;
+ DWORD dummy10;
+ DWORD IfType;
+ int OperStatus;
+ DWORD dummy12;
+ DWORD dummy13[16];
+ void *dummy14;
+ } ip_adapter_addresses_t;
+ typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG, ULONG, PVOID, ip_adapter_addresses_t *, PULONG);
+ HMODULE h;
+ GetAdaptersAddresses_t pGetAdaptersAddresses;
+ ULONG len;
+ DWORD ret;
+ ip_adapter_addresses_t *adapters;
+ VALUE list;
+
+ h = LoadLibrary("iphlpapi.dll");
+ if (!h)
+ rb_notimplement();
+ pGetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress(h, "GetAdaptersAddresses");
+ if (!pGetAdaptersAddresses) {
+ FreeLibrary(h);
+ rb_notimplement();
+ }
+
+ ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len);
+ if (ret != ERROR_SUCCESS && ret != ERROR_BUFFER_OVERFLOW) {
+ errno = rb_w32_map_errno(ret);
+ FreeLibrary(h);
+ rb_sys_fail("GetAdaptersAddresses");
+ }
+ adapters = (ip_adapter_addresses_t *)ALLOCA_N(BYTE, len);
+ ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
+ if (ret != ERROR_SUCCESS) {
+ errno = rb_w32_map_errno(ret);
+ FreeLibrary(h);
+ rb_sys_fail("GetAdaptersAddresses");
+ }
+
+ list = rb_ary_new();
+ for (; adapters; adapters = adapters->Next) {
+ ip_adapter_unicast_address_t *uni;
+ ip_adapter_anycast_address_t *any;
+ if (adapters->OperStatus != 1) /* 1 means IfOperStatusUp */
+ continue;
+ for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) {
+#ifndef INET6
+ if (uni->Address.lpSockaddr->sa_family == AF_INET)
#else
- sock_define_const("INADDR_UNSPEC_GROUP", 0xe0000000);
+ if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family))
#endif
-#ifdef INADDR_ALLHOSTS_GROUP
- sock_define_const("INADDR_ALLHOSTS_GROUP", INADDR_ALLHOSTS_GROUP);
+ rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr, uni->Address.iSockaddrLength));
+ }
+ for (any = adapters->FirstAnycastAddress; any; any = any->Next) {
+#ifndef INET6
+ if (any->Address.lpSockaddr->sa_family == AF_INET)
#else
- sock_define_const("INADDR_ALLHOSTS_GROUP", 0xe0000001);
+ if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family))
#endif
-#ifdef INADDR_MAX_LOCAL_GROUP
- sock_define_const("INADDR_MAX_LOCAL_GROUP", INADDR_MAX_LOCAL_GROUP);
-#else
- sock_define_const("INADDR_MAX_LOCAL_GROUP", 0xe00000ff);
+ rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr, any->Address.iSockaddrLength));
+ }
+ }
+
+ FreeLibrary(h);
+ return list;
#endif
-#ifdef INADDR_NONE
- sock_define_const("INADDR_NONE", INADDR_NONE);
+}
#else
- sock_define_const("INADDR_NONE", 0xffffffff);
-#endif
- /* IP [gs]etsockopt options */
-#ifdef IP_OPTIONS
- sock_define_const("IP_OPTIONS", IP_OPTIONS);
-#endif
-#ifdef IP_HDRINCL
- sock_define_const("IP_HDRINCL", IP_HDRINCL);
-#endif
-#ifdef IP_TOS
- sock_define_const("IP_TOS", IP_TOS);
-#endif
-#ifdef IP_TTL
- sock_define_const("IP_TTL", IP_TTL);
-#endif
-#ifdef IP_RECVOPTS
- sock_define_const("IP_RECVOPTS", IP_RECVOPTS);
-#endif
-#ifdef IP_RECVRETOPTS
- sock_define_const("IP_RECVRETOPTS", IP_RECVRETOPTS);
-#endif
-#ifdef IP_RECVDSTADDR
- sock_define_const("IP_RECVDSTADDR", IP_RECVDSTADDR);
-#endif
-#ifdef IP_RETOPTS
- sock_define_const("IP_RETOPTS", IP_RETOPTS);
-#endif
-#ifdef IP_MULTICAST_IF
- sock_define_const("IP_MULTICAST_IF", IP_MULTICAST_IF);
-#endif
-#ifdef IP_MULTICAST_TTL
- sock_define_const("IP_MULTICAST_TTL", IP_MULTICAST_TTL);
-#endif
-#ifdef IP_MULTICAST_LOOP
- sock_define_const("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP);
-#endif
-#ifdef IP_ADD_MEMBERSHIP
- sock_define_const("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP);
-#endif
-#ifdef IP_DROP_MEMBERSHIP
- sock_define_const("IP_DROP_MEMBERSHIP", IP_DROP_MEMBERSHIP);
-#endif
-#ifdef IP_DEFAULT_MULTICAST_TTL
- sock_define_const("IP_DEFAULT_MULTICAST_TTL", IP_DEFAULT_MULTICAST_TTL);
-#endif
-#ifdef IP_DEFAULT_MULTICAST_LOOP
- sock_define_const("IP_DEFAULT_MULTICAST_LOOP", IP_DEFAULT_MULTICAST_LOOP);
-#endif
-#ifdef IP_MAX_MEMBERSHIPS
- sock_define_const("IP_MAX_MEMBERSHIPS", IP_MAX_MEMBERSHIPS);
-#endif
-#ifdef SO_DEBUG
- sock_define_const("SO_DEBUG", SO_DEBUG);
-#endif
- sock_define_const("SO_REUSEADDR", SO_REUSEADDR);
-#ifdef SO_REUSEPORT
- sock_define_const("SO_REUSEPORT", SO_REUSEPORT);
-#endif
-#ifdef SO_TYPE
- sock_define_const("SO_TYPE", SO_TYPE);
-#endif
-#ifdef SO_ERROR
- sock_define_const("SO_ERROR", SO_ERROR);
-#endif
-#ifdef SO_DONTROUTE
- sock_define_const("SO_DONTROUTE", SO_DONTROUTE);
-#endif
-#ifdef SO_BROADCAST
- sock_define_const("SO_BROADCAST", SO_BROADCAST);
-#endif
-#ifdef SO_SNDBUF
- sock_define_const("SO_SNDBUF", SO_SNDBUF);
-#endif
-#ifdef SO_RCVBUF
- sock_define_const("SO_RCVBUF", SO_RCVBUF);
-#endif
-#ifdef SO_KEEPALIVE
- sock_define_const("SO_KEEPALIVE", SO_KEEPALIVE);
-#endif
-#ifdef SO_OOBINLINE
- sock_define_const("SO_OOBINLINE", SO_OOBINLINE);
-#endif
-#ifdef SO_NO_CHECK
- sock_define_const("SO_NO_CHECK", SO_NO_CHECK);
-#endif
-#ifdef SO_PRIORITY
- sock_define_const("SO_PRIORITY", SO_PRIORITY);
-#endif
-#ifdef SO_LINGER
- sock_define_const("SO_LINGER", SO_LINGER);
-#endif
-#ifdef SO_PASSCRED
- sock_define_const("SO_PASSCRED", SO_PASSCRED);
-#endif
-#ifdef SO_PEERCRED
- sock_define_const("SO_PEERCRED", SO_PEERCRED);
-#endif
-#ifdef SO_RCVLOWAT
- sock_define_const("SO_RCVLOWAT", SO_RCVLOWAT);
-#endif
-#ifdef SO_SNDLOWAT
- sock_define_const("SO_SNDLOWAT", SO_SNDLOWAT);
-#endif
-#ifdef SO_RCVTIMEO
- sock_define_const("SO_RCVTIMEO", SO_RCVTIMEO);
-#endif
-#ifdef SO_SNDTIMEO
- sock_define_const("SO_SNDTIMEO", SO_SNDTIMEO);
-#endif
-#ifdef SO_ACCEPTCONN
- sock_define_const("SO_ACCEPTCONN", SO_ACCEPTCONN);
-#endif
-#ifdef SO_USELOOPBACK
- sock_define_const("SO_USELOOPBACK", SO_USELOOPBACK);
-#endif
-#ifdef SO_ACCEPTFILTER
- sock_define_const("SO_ACCEPTFILTER", SO_ACCEPTFILTER);
-#endif
-#ifdef SO_DONTTRUNC
- sock_define_const("SO_DONTTRUNC", SO_DONTTRUNC);
-#endif
-#ifdef SO_WANTMORE
- sock_define_const("SO_WANTMORE", SO_WANTMORE);
-#endif
-#ifdef SO_WANTOOBFLAG
- sock_define_const("SO_WANTOOBFLAG", SO_WANTOOBFLAG);
-#endif
-#ifdef SO_NREAD
- sock_define_const("SO_NREAD", SO_NREAD);
-#endif
-#ifdef SO_NKE
- sock_define_const("SO_NKE", SO_NKE);
-#endif
-#ifdef SO_NOSIGPIPE
- sock_define_const("SO_NOSIGPIPE", SO_NOSIGPIPE);
+#define socket_s_ip_address_list rb_f_notimplement
#endif
-#ifdef SO_SECURITY_AUTHENTICATION
- sock_define_const("SO_SECURITY_AUTHENTICATION", SO_SECURITY_AUTHENTICATION);
-#endif
-#ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
- sock_define_const("SO_SECURITY_ENCRYPTION_TRANSPORT", SO_SECURITY_ENCRYPTION_TRANSPORT);
-#endif
-#ifdef SO_SECURITY_ENCRYPTION_NETWORK
- sock_define_const("SO_SECURITY_ENCRYPTION_NETWORK", SO_SECURITY_ENCRYPTION_NETWORK);
-#endif
+/*
+ * call-seq:
+ * Socket.tcp_fast_fallback -> true or false
+ *
+ * Returns whether Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305]),
+ * which is provided starting from Ruby 3.4 when using TCPSocket.new and Socket.tcp,
+ * is enabled or disabled.
+ *
+ * If true, it is enabled for TCPSocket.new and Socket.tcp.
+ * (Note: Happy Eyeballs Version 2 is not provided when using TCPSocket.new on Windows.)
+ *
+ * If false, Happy Eyeballs Version 2 is disabled.
+ *
+ * For details on Happy Eyeballs Version 2,
+ * see {Socket.tcp_fast_fallback=}[rdoc-ref:Socket.tcp_fast_fallback=].
+ */
+VALUE socket_s_tcp_fast_fallback(VALUE self) {
+ return rb_ivar_get(rb_cSocket, tcp_fast_fallback);
+}
-#ifdef SO_BINDTODEVICE
- sock_define_const("SO_BINDTODEVICE", SO_BINDTODEVICE);
-#endif
-#ifdef SO_ATTACH_FILTER
- sock_define_const("SO_ATTACH_FILTER", SO_ATTACH_FILTER);
-#endif
-#ifdef SO_DETACH_FILTER
- sock_define_const("SO_DETACH_FILTER", SO_DETACH_FILTER);
-#endif
-#ifdef SO_PEERNAME
- sock_define_const("SO_PEERNAME", SO_PEERNAME);
-#endif
-#ifdef SO_TIMESTAMP
- sock_define_const("SO_TIMESTAMP", SO_TIMESTAMP);
-#endif
+/*
+ * call-seq:
+ * Socket.tcp_fast_fallback= -> true or false
+ *
+ * Enable or disable Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305])
+ * globally, which is provided starting from Ruby 3.4 when using TCPSocket.new and Socket.tcp.
+ *
+ * When set to true, the feature is enabled for both `TCPSocket.new` and `Socket.tcp`.
+ * (Note: This feature is not available when using TCPSocket.new on Windows.)
+ *
+ * When set to false, the behavior reverts to that of Ruby 3.3 or earlier.
+ *
+ * The default value is true if no value is explicitly set by calling this method.
+ * However, when the environment variable RUBY_TCP_NO_FAST_FALLBACK=1 is set,
+ * the default is false.
+ *
+ * To control the setting on a per-method basis, use the fast_fallback keyword argument for each method.
+ *
+ * === Happy Eyeballs Version 2
+ * Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305])
+ * is an algorithm designed to improve client socket connectivity.<br>
+ * It aims for more reliable and efficient connections by performing hostname resolution
+ * and connection attempts in parallel, instead of serially.
+ *
+ * Starting from Ruby 3.4, this method operates as follows with this algorithm:
+ *
+ * 1. Start resolving both IPv6 and IPv4 addresses concurrently.
+ * 2. Start connecting to the one of the addresses that are obtained first.<br>If IPv4 addresses are obtained first,
+ * the method waits 50 ms for IPv6 name resolution to prioritize IPv6 connections.
+ * 3. After starting a connection attempt, wait 250 ms for the connection to be established.<br>
+ * If no connection is established within this time, a new connection is started every 250 ms<br>
+ * until a connection is established or there are no more candidate addresses.<br>
+ * (Although RFC 8305 strictly specifies sorting addresses,<br>
+ * this method only alternates between IPv6 / IPv4 addresses due to the performance concerns)
+ * 4. Once a connection is established, all remaining connection attempts are canceled.
+ */
+VALUE socket_s_tcp_fast_fallback_set(VALUE self, VALUE value) {
+ rb_ivar_set(rb_cSocket, tcp_fast_fallback, value);
+ return value;
+}
-#ifdef SOPRI_INTERACTIVE
- sock_define_const("SOPRI_INTERACTIVE", SOPRI_INTERACTIVE);
-#endif
-#ifdef SOPRI_NORMAL
- sock_define_const("SOPRI_NORMAL", SOPRI_NORMAL);
-#endif
-#ifdef SOPRI_BACKGROUND
- sock_define_const("SOPRI_BACKGROUND", SOPRI_BACKGROUND);
-#endif
+void
+Init_socket(void)
+{
+ rb_ext_ractor_safe(true);
-#ifdef IPX_TYPE
- sock_define_const("IPX_TYPE", IPX_TYPE);
-#endif
+ rsock_init_basicsocket();
-#ifdef TCP_NODELAY
- sock_define_const("TCP_NODELAY", TCP_NODELAY);
-#endif
-#ifdef TCP_MAXSEG
- sock_define_const("TCP_MAXSEG", TCP_MAXSEG);
-#endif
+ /*
+ * Document-class: Socket < BasicSocket
+ *
+ * Class +Socket+ provides access to the underlying operating system
+ * socket implementations. It can be used to provide more operating system
+ * specific functionality than the protocol-specific socket classes.
+ *
+ * The constants defined under Socket::Constants are also defined under
+ * Socket. For example, Socket::AF_INET is usable as well as
+ * Socket::Constants::AF_INET. See Socket::Constants for the list of
+ * constants.
+ *
+ * === What's a socket?
+ *
+ * Sockets are endpoints of a bidirectional communication channel.
+ * Sockets can communicate within a process, between processes on the same
+ * machine or between different machines. There are many types of socket:
+ * TCPSocket, UDPSocket or UNIXSocket for example.
+ *
+ * Sockets have their own vocabulary:
+ *
+ * *domain:*
+ * The family of protocols:
+ * * Socket::PF_INET
+ * * Socket::PF_INET6
+ * * Socket::PF_UNIX
+ * * etc.
+ *
+ * *type:*
+ * The type of communications between the two endpoints, typically
+ * * Socket::SOCK_STREAM
+ * * Socket::SOCK_DGRAM.
+ *
+ * *protocol:*
+ * Typically _zero_.
+ * This may be used to identify a variant of a protocol.
+ *
+ * *hostname:*
+ * The identifier of a network interface:
+ * * a string (hostname, IPv4 or IPv6 address or +broadcast+
+ * which specifies a broadcast address)
+ * * a zero-length string which specifies INADDR_ANY
+ * * an integer (interpreted as binary address in host byte order).
+ *
+ * === Quick start
+ *
+ * Many of the classes, such as TCPSocket, UDPSocket or UNIXSocket,
+ * ease the use of sockets comparatively to the equivalent C programming interface.
+ *
+ * Let's create an internet socket using the IPv4 protocol in a C-like manner:
+ *
+ * require 'socket'
+ *
+ * s = Socket.new Socket::AF_INET, Socket::SOCK_STREAM
+ * s.connect Socket.pack_sockaddr_in(80, 'example.com')
+ *
+ * You could also use the TCPSocket class:
+ *
+ * s = TCPSocket.new 'example.com', 80
+ *
+ * A simple server might look like this:
+ *
+ * require 'socket'
+ *
+ * server = TCPServer.new 2000 # Server bound to port 2000
+ *
+ * loop do
+ * client = server.accept # Wait for a client to connect
+ * client.puts "Hello !"
+ * client.puts "Time is #{Time.now}"
+ * client.close
+ * end
+ *
+ * A simple client may look like this:
+ *
+ * require 'socket'
+ *
+ * s = TCPSocket.new 'localhost', 2000
+ *
+ * while line = s.gets # Read lines from socket
+ * puts line # and print them
+ * end
+ *
+ * s.close # close socket when done
+ *
+ * === Exception Handling
+ *
+ * Ruby's Socket implementation raises exceptions based on the error
+ * generated by the system dependent implementation. This is why the
+ * methods are documented in a way that isolate Unix-based system
+ * exceptions from Windows based exceptions. If more information on a
+ * particular exception is needed, please refer to the Unix manual pages or
+ * the Windows WinSock reference.
+ *
+ * === Convenience methods
+ *
+ * Although the general way to create socket is Socket.new,
+ * there are several methods of socket creation for most cases.
+ *
+ * TCP client socket::
+ * Socket.tcp, TCPSocket.open
+ * TCP server socket::
+ * Socket.tcp_server_loop, TCPServer.open
+ * UNIX client socket::
+ * Socket.unix, UNIXSocket.open
+ * UNIX server socket::
+ * Socket.unix_server_loop, UNIXServer.open
+ *
+ * === Documentation by
+ *
+ * * Zach Dennis
+ * * Sam Roberts
+ * * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
+ *
+ * Much material in this documentation is taken with permission from
+ * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
+ */
+ rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
-#ifdef EAI_ADDRFAMILY
- sock_define_const("EAI_ADDRFAMILY", EAI_ADDRFAMILY);
-#endif
-#ifdef EAI_AGAIN
- sock_define_const("EAI_AGAIN", EAI_AGAIN);
-#endif
-#ifdef EAI_BADFLAGS
- sock_define_const("EAI_BADFLAGS", EAI_BADFLAGS);
-#endif
-#ifdef EAI_FAIL
- sock_define_const("EAI_FAIL", EAI_FAIL);
-#endif
-#ifdef EAI_FAMILY
- sock_define_const("EAI_FAMILY", EAI_FAMILY);
-#endif
-#ifdef EAI_MEMORY
- sock_define_const("EAI_MEMORY", EAI_MEMORY);
-#endif
-#ifdef EAI_NODATA
- sock_define_const("EAI_NODATA", EAI_NODATA);
-#endif
-#ifdef EAI_NONAME
- sock_define_const("EAI_NONAME", EAI_NONAME);
-#endif
-#ifdef EAI_SERVICE
- sock_define_const("EAI_SERVICE", EAI_SERVICE);
-#endif
-#ifdef EAI_SOCKTYPE
- sock_define_const("EAI_SOCKTYPE", EAI_SOCKTYPE);
-#endif
-#ifdef EAI_SYSTEM
- sock_define_const("EAI_SYSTEM", EAI_SYSTEM);
-#endif
-#ifdef EAI_BADHINTS
- sock_define_const("EAI_BADHINTS", EAI_BADHINTS);
-#endif
-#ifdef EAI_PROTOCOL
- sock_define_const("EAI_PROTOCOL", EAI_PROTOCOL);
-#endif
-#ifdef EAI_MAX
- sock_define_const("EAI_MAX", EAI_MAX);
-#endif
-#ifdef AI_PASSIVE
- sock_define_const("AI_PASSIVE", AI_PASSIVE);
-#endif
-#ifdef AI_CANONNAME
- sock_define_const("AI_CANONNAME", AI_CANONNAME);
-#endif
-#ifdef AI_NUMERICHOST
- sock_define_const("AI_NUMERICHOST", AI_NUMERICHOST);
-#endif
-#ifdef AI_MASK
- sock_define_const("AI_MASK", AI_MASK);
-#endif
-#ifdef AI_ALL
- sock_define_const("AI_ALL", AI_ALL);
-#endif
-#ifdef AI_V4MAPPED_CFG
- sock_define_const("AI_V4MAPPED_CFG", AI_V4MAPPED_CFG);
-#endif
-#ifdef AI_ADDRCONFIG
- sock_define_const("AI_ADDRCONFIG", AI_ADDRCONFIG);
-#endif
-#ifdef AI_V4MAPPED
- sock_define_const("AI_V4MAPPED", AI_V4MAPPED);
-#endif
-#ifdef AI_DEFAULT
- sock_define_const("AI_DEFAULT", AI_DEFAULT);
-#endif
-#ifdef NI_MAXHOST
- sock_define_const("NI_MAXHOST", NI_MAXHOST);
-#endif
-#ifdef NI_MAXSERV
- sock_define_const("NI_MAXSERV", NI_MAXSERV);
-#endif
-#ifdef NI_NOFQDN
- sock_define_const("NI_NOFQDN", NI_NOFQDN);
-#endif
-#ifdef NI_NUMERICHOST
- sock_define_const("NI_NUMERICHOST", NI_NUMERICHOST);
-#endif
-#ifdef NI_NAMEREQD
- sock_define_const("NI_NAMEREQD", NI_NAMEREQD);
-#endif
-#ifdef NI_NUMERICSERV
- sock_define_const("NI_NUMERICSERV", NI_NUMERICSERV);
-#endif
-#ifdef NI_DGRAM
- sock_define_const("NI_DGRAM", NI_DGRAM);
-#endif
-#ifdef SHUT_RD
- sock_define_const("SHUT_RD", SHUT_RD);
-#else
- sock_define_const("SHUT_RD", 0);
-#endif
-#ifdef SHUT_WR
- sock_define_const("SHUT_WR", SHUT_WR);
-#else
- sock_define_const("SHUT_WR", 1);
-#endif
-#ifdef SHUT_RDWR
- sock_define_const("SHUT_RDWR", SHUT_RDWR);
-#else
- sock_define_const("SHUT_RDWR", 2);
+ rsock_init_socket_init();
+
+ const char *tcp_no_fast_fallback_config = getenv("RUBY_TCP_NO_FAST_FALLBACK");
+ VALUE fast_fallback_default;
+ if (tcp_no_fast_fallback_config == NULL || strcmp(tcp_no_fast_fallback_config, "0") == 0) {
+ fast_fallback_default = Qtrue;
+ } else {
+ fast_fallback_default = Qfalse;
+ }
+ tcp_fast_fallback = rb_intern_const("tcp_fast_fallback");
+ rb_ivar_set(rb_cSocket, tcp_fast_fallback, fast_fallback_default);
+
+ rb_define_method(rb_cSocket, "initialize", sock_initialize, -1);
+ rb_define_method(rb_cSocket, "connect", sock_connect, 1);
+
+ /* for ext/socket/lib/socket.rb use only: */
+ rb_define_private_method(rb_cSocket,
+ "__connect_nonblock", sock_connect_nonblock, 2);
+
+ rb_define_method(rb_cSocket, "bind", sock_bind, 1);
+ rb_define_method(rb_cSocket, "listen", rsock_sock_listen, 1);
+ rb_define_method(rb_cSocket, "accept", sock_accept, 0);
+
+ /* for ext/socket/lib/socket.rb use only: */
+ rb_define_private_method(rb_cSocket,
+ "__accept_nonblock", sock_accept_nonblock, 1);
+
+ rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
+
+ rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
+
+ /* for ext/socket/lib/socket.rb use only: */
+ rb_define_private_method(rb_cSocket,
+ "__recvfrom_nonblock", sock_recvfrom_nonblock, 4);
+
+ rb_define_singleton_method(rb_cSocket, "socketpair", rsock_sock_s_socketpair, -1);
+ rb_define_singleton_method(rb_cSocket, "pair", rsock_sock_s_socketpair, -1);
+ rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0);
+ rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
+ rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
+ rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyname, -1);
+ rb_define_singleton_method(rb_cSocket, "getservbyport", sock_s_getservbyport, -1);
+ rb_define_singleton_method(rb_cSocket, "getaddrinfo", sock_s_getaddrinfo, -1);
+ rb_define_singleton_method(rb_cSocket, "getnameinfo", sock_s_getnameinfo, -1);
+ rb_define_singleton_method(rb_cSocket, "sockaddr_in", sock_s_pack_sockaddr_in, 2);
+ rb_define_singleton_method(rb_cSocket, "pack_sockaddr_in", sock_s_pack_sockaddr_in, 2);
+ rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_in", sock_s_unpack_sockaddr_in, 1);
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ rb_define_singleton_method(rb_cSocket, "sockaddr_un", sock_s_pack_sockaddr_un, 1);
+ rb_define_singleton_method(rb_cSocket, "pack_sockaddr_un", sock_s_pack_sockaddr_un, 1);
+ rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_un", sock_s_unpack_sockaddr_un, 1);
#endif
+
+ rb_define_singleton_method(rb_cSocket, "ip_address_list", socket_s_ip_address_list, 0);
+
+ rb_define_singleton_method(rb_cSocket, "tcp_fast_fallback", socket_s_tcp_fast_fallback, 0);
+ rb_define_singleton_method(rb_cSocket, "tcp_fast_fallback=", socket_s_tcp_fast_fallback_set, 1);
+
+#undef rb_intern
+ sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
}
diff --git a/ext/socket/sockport.h b/ext/socket/sockport.h
index e1cddf53f4..2b58958ae7 100644
--- a/ext/socket/sockport.h
+++ b/ext/socket/sockport.h
@@ -3,7 +3,6 @@
sockport.h -
$Author$
- $Date$
created at: Fri Apr 30 23:19:34 JST 1999
************************************************/
@@ -11,33 +10,74 @@
#ifndef SOCKPORT_H
#define SOCKPORT_H
-#ifndef SA_LEN
-# ifdef HAVE_SA_LEN
-# define SA_LEN(sa) (sa)->sa_len
-# else
-# ifdef INET6
-# define SA_LEN(sa) \
- (((sa)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) \
- : sizeof(struct sockaddr))
-# else
- /* by tradition, sizeof(struct sockaddr) covers most of the sockaddrs */
-# define SA_LEN(sa) (sizeof(struct sockaddr))
-# endif
-# endif
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+# define VALIDATE_SOCKLEN(addr, len) ((addr)->sa_len == (len))
+#else
+# define VALIDATE_SOCKLEN(addr, len) ((void)(addr), (void)(len), 1)
+#endif
+
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+# define SET_SA_LEN(sa, len) (void)((sa)->sa_len = (len))
+#else
+# define SET_SA_LEN(sa, len) (void)(len)
#endif
-#ifdef HAVE_SA_LEN
-# define SET_SA_LEN(sa, len) (sa)->sa_len = (len)
+/* for strict-aliasing rule */
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+# define SET_SIN_LEN(sa, len) (void)((sa)->sin_len = (len))
#else
-# define SET_SA_LEN(sa, len) (len)
+# define SET_SIN_LEN(sa, len) SET_SA_LEN((struct sockaddr *)(sa), (len))
#endif
-#ifdef HAVE_SIN_LEN
-# define SIN_LEN(si) (si)->sin_len
-# define SET_SIN_LEN(si,len) (si)->sin_len = (len)
+#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
+# define SET_SIN6_LEN(sa, len) (void)((sa)->sin6_len = (len))
#else
-# define SIN_LEN(si) sizeof(struct sockaddr_in)
-# define SET_SIN_LEN(si,len)
+# define SET_SIN6_LEN(sa, len) SET_SA_LEN((struct sockaddr *)(sa), (len))
+#endif
+
+#define INIT_SOCKADDR(addr, family, len) \
+ do { \
+ struct sockaddr *init_sockaddr_ptr = (addr); \
+ socklen_t init_sockaddr_len = (len); \
+ memset(init_sockaddr_ptr, 0, init_sockaddr_len); \
+ init_sockaddr_ptr->sa_family = (family); \
+ SET_SA_LEN(init_sockaddr_ptr, init_sockaddr_len); \
+ } while (0)
+
+#define INIT_SOCKADDR_IN(addr, len) \
+ do { \
+ struct sockaddr_in *init_sockaddr_ptr = (addr); \
+ socklen_t init_sockaddr_len = (len); \
+ memset(init_sockaddr_ptr, 0, init_sockaddr_len); \
+ init_sockaddr_ptr->sin_family = AF_INET; \
+ SET_SIN_LEN(init_sockaddr_ptr, init_sockaddr_len); \
+ } while (0)
+
+#define INIT_SOCKADDR_IN6(addr, len) \
+ do { \
+ struct sockaddr_in6 *init_sockaddr_ptr = (addr); \
+ socklen_t init_sockaddr_len = (len); \
+ memset(init_sockaddr_ptr, 0, init_sockaddr_len); \
+ init_sockaddr_ptr->sin6_family = AF_INET6; \
+ SET_SIN6_LEN(init_sockaddr_ptr, init_sockaddr_len); \
+ } while (0)
+
+
+/* for strict-aliasing rule */
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+# ifdef HAVE_STRUCT_SOCKADDR_IN_SUN_LEN
+# define SET_SUN_LEN(sa, len) (void)((sa)->sun_len = (len))
+# else
+# define SET_SUN_LEN(sa, len) SET_SA_LEN((struct sockaddr *)(sa), (len))
+# endif
+# define INIT_SOCKADDR_UN(addr, len) \
+ do { \
+ struct sockaddr_un *init_sockaddr_ptr = (addr); \
+ socklen_t init_sockaddr_len = (len); \
+ memset(init_sockaddr_ptr, 0, init_sockaddr_len); \
+ init_sockaddr_ptr->sun_family = AF_UNIX; \
+ SET_SUN_LEN(init_sockaddr_ptr, init_sockaddr_len); \
+ } while (0)
#endif
#ifndef IN_MULTICAST
diff --git a/ext/socket/sockssocket.c b/ext/socket/sockssocket.c
new file mode 100644
index 0000000000..30860ea257
--- /dev/null
+++ b/ext/socket/sockssocket.c
@@ -0,0 +1,75 @@
+/************************************************
+
+ sockssocket.c -
+
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
+
+************************************************/
+
+#include "rubysocket.h"
+
+#ifdef SOCKS
+/*
+ * call-seq:
+ * SOCKSSocket.new(host, port) => socket
+ *
+ * Opens a SOCKS connection to +host+ via the SOCKS server.
+ *
+ * The SOCKS server configuration varies by implementation
+ *
+ * When using the Dante libsocks/libsocksd implementation it is configured as SOCKS_SERVER env var.
+ *
+ * See: https://manpages.debian.org/testing/dante-client/socksify.1.en.html for full env variable support.
+ *
+ */
+static VALUE
+socks_init(VALUE sock, VALUE host, VALUE port)
+{
+ static int init = 0;
+
+ if (init == 0) {
+ char progname[] = "ruby";
+ SOCKSinit(progname);
+ init = 1;
+ }
+
+ return rsock_init_inetsock(sock, host, port, Qnil, Qnil, INET_SOCKS, Qnil, Qnil, Qnil, Qfalse, Qnil);
+}
+
+#ifdef SOCKS5
+/*
+ * Closes the SOCKS connection.
+ *
+ */
+static VALUE
+socks_s_close(VALUE sock)
+{
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ shutdown(fptr->fd, SHUT_RDWR);
+ return rb_io_close(sock);
+}
+#endif
+#endif
+
+void
+rsock_init_sockssocket(void)
+{
+#ifdef SOCKS
+ /*
+ * Document-class: SOCKSSocket < TCPSocket
+ *
+ * SOCKS is an Internet protocol that routes packets between a client and
+ * a server through a proxy server. SOCKS5, if supported, additionally
+ * provides authentication so only authorized users may access a server.
+ */
+ rb_cSOCKSSocket = rb_define_class("SOCKSSocket", rb_cTCPSocket);
+ rb_define_method(rb_cSOCKSSocket, "initialize", socks_init, 2);
+#ifdef SOCKS5
+ rb_define_method(rb_cSOCKSSocket, "close", socks_s_close, 0);
+#endif
+#endif
+}
diff --git a/ext/socket/tcpserver.c b/ext/socket/tcpserver.c
new file mode 100644
index 0000000000..0069f3c703
--- /dev/null
+++ b/ext/socket/tcpserver.c
@@ -0,0 +1,140 @@
+/************************************************
+
+ tcpserver.c -
+
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
+
+************************************************/
+
+#include "rubysocket.h"
+
+/*
+ * call-seq:
+ * TCPServer.new([hostname,] port) => tcpserver
+ *
+ * Creates a new server socket bound to _port_.
+ *
+ * If _hostname_ is given, the socket is bound to it.
+ *
+ * serv = TCPServer.new("127.0.0.1", 28561)
+ * s = serv.accept
+ * s.puts Time.now
+ * s.close
+ *
+ * Internally, TCPServer.new calls getaddrinfo() function to
+ * obtain addresses.
+ * If getaddrinfo() returns multiple addresses,
+ * TCPServer.new tries to create a server socket for each address
+ * and returns first one that is successful.
+ *
+ */
+static VALUE
+tcp_svr_init(int argc, VALUE *argv, VALUE sock)
+{
+ VALUE hostname, port;
+
+ rb_scan_args(argc, argv, "011", &hostname, &port);
+ return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER, Qnil, Qnil, Qnil, Qfalse, Qnil);
+}
+
+/*
+ * call-seq:
+ * tcpserver.accept => tcpsocket
+ *
+ * Accepts an incoming connection. It returns a new TCPSocket object.
+ *
+ * TCPServer.open("127.0.0.1", 14641) {|serv|
+ * s = serv.accept
+ * s.puts Time.now
+ * s.close
+ * }
+ *
+ */
+static VALUE
+tcp_accept(VALUE server)
+{
+ union_sockaddr buffer;
+ socklen_t length = sizeof(buffer);
+
+ return rsock_s_accept(rb_cTCPSocket, server, &buffer.addr, &length);
+}
+
+/* :nodoc: */
+static VALUE
+tcp_accept_nonblock(VALUE sock, VALUE ex)
+{
+ rb_io_t *fptr;
+ union_sockaddr from;
+ socklen_t len = (socklen_t)sizeof(from);
+
+ GetOpenFile(sock, fptr);
+ return rsock_s_accept_nonblock(rb_cTCPSocket, ex, fptr, &from.addr, &len);
+}
+
+/*
+ * call-seq:
+ * tcpserver.sysaccept => file_descriptor
+ *
+ * Returns a file descriptor of a accepted connection.
+ *
+ * TCPServer.open("127.0.0.1", 28561) {|serv|
+ * fd = serv.sysaccept
+ * s = IO.for_fd(fd)
+ * s.puts Time.now
+ * s.close
+ * }
+ *
+ */
+static VALUE
+tcp_sysaccept(VALUE server)
+{
+ union_sockaddr buffer;
+ socklen_t length = sizeof(buffer);
+
+ return rsock_s_accept(0, server, &buffer.addr, &length);
+}
+
+void
+rsock_init_tcpserver(void)
+{
+ /*
+ * Document-class: TCPServer < TCPSocket
+ *
+ * TCPServer represents a TCP/IP server socket.
+ *
+ * A simple TCP server may look like:
+ *
+ * require 'socket'
+ *
+ * server = TCPServer.new 2000 # Server bind to port 2000
+ * loop do
+ * client = server.accept # Wait for a client to connect
+ * client.puts "Hello !"
+ * client.puts "Time is #{Time.now}"
+ * client.close
+ * end
+ *
+ * A more usable server (serving multiple clients):
+ *
+ * require 'socket'
+ *
+ * server = TCPServer.new 2000
+ * loop do
+ * Thread.start(server.accept) do |client|
+ * client.puts "Hello !"
+ * client.puts "Time is #{Time.now}"
+ * client.close
+ * end
+ * end
+ *
+ */
+ rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
+ rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
+ rb_define_private_method(rb_cTCPServer,
+ "__accept_nonblock", tcp_accept_nonblock, 1);
+ rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
+ rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
+ rb_define_method(rb_cTCPServer, "listen", rsock_sock_listen, 1); /* in socket.c */
+}
diff --git a/ext/socket/tcpsocket.c b/ext/socket/tcpsocket.c
new file mode 100644
index 0000000000..7ce536e0af
--- /dev/null
+++ b/ext/socket/tcpsocket.c
@@ -0,0 +1,144 @@
+/************************************************
+
+ tcpsocket.c -
+
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
+
+************************************************/
+
+#include "rubysocket.h"
+
+/*
+ * call-seq:
+ * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil, resolv_timeout: nil, connect_timeout: nil, open_timeout: nil, fast_fallback: true)
+ *
+ * Opens a TCP connection to +remote_host+ on +remote_port+. If +local_host+
+ * and +local_port+ are specified, then those parameters are used on the local
+ * end to establish the connection.
+ *
+ * Starting from Ruby 3.4, this method operates according to the
+ * Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305])
+ * algorithm by default, except on Windows.
+ *
+ * For details on Happy Eyeballs Version 2,
+ * see {Socket.tcp_fast_fallback=}[rdoc-ref:Socket.tcp_fast_fallback=].
+ *
+ * To make it behave the same as in Ruby 3.3 and earlier,
+ * explicitly specify the option fast_fallback:false.
+ * Or, setting Socket.tcp_fast_fallback=false will disable
+ * Happy Eyeballs Version 2 not only for this method but for all Socket globally.
+ *
+ * When using TCPSocket.new on Windows, Happy Eyeballs Version 2 is not provided,
+ * and it behaves the same as in Ruby 3.3 and earlier.
+ *
+ * [:resolv_timeout] Specifies the timeout in seconds from when the hostname resolution starts.
+ * [:connect_timeout] This method sequentially attempts connecting to all candidate destination addresses.<br>The +connect_timeout+ specifies the timeout in seconds from the start of the connection attempt to the last candidate.<br>By default, all connection attempts continue until the timeout occurs.<br>When +fast_fallback:false+ is explicitly specified,<br>a timeout is set for each connection attempt and any connection attempt that exceeds its timeout will be canceled.
+ * [:open_timeout] Specifies the timeout in seconds from the start of the method execution.<br>If this timeout is reached while there are still addresses that have not yet been attempted for connection, no further attempts will be made.<br>If this option is specified together with other timeout options, an +ArgumentError+ will be raised.
+ * [:fast_fallback] Enables the Happy Eyeballs Version 2 algorithm (enabled by default).
+ */
+static VALUE
+tcp_init(int argc, VALUE *argv, VALUE sock)
+{
+ VALUE remote_host, remote_serv;
+ VALUE local_host, local_serv;
+ VALUE opt;
+ static ID keyword_ids[5];
+ VALUE kwargs[5];
+ VALUE resolv_timeout = Qnil;
+ VALUE connect_timeout = Qnil;
+ VALUE open_timeout = Qnil;
+ VALUE fast_fallback = Qnil;
+ VALUE test_mode_settings = Qnil;
+
+ if (!keyword_ids[0]) {
+ CONST_ID(keyword_ids[0], "resolv_timeout");
+ CONST_ID(keyword_ids[1], "connect_timeout");
+ CONST_ID(keyword_ids[2], "open_timeout");
+ CONST_ID(keyword_ids[3], "fast_fallback");
+ CONST_ID(keyword_ids[4], "test_mode_settings");
+ }
+
+ rb_scan_args(argc, argv, "22:", &remote_host, &remote_serv,
+ &local_host, &local_serv, &opt);
+
+ if (!NIL_P(opt)) {
+ rb_get_kwargs(opt, keyword_ids, 0, 5, kwargs);
+ if (kwargs[0] != Qundef) { resolv_timeout = kwargs[0]; }
+ if (kwargs[1] != Qundef) { connect_timeout = kwargs[1]; }
+ if (kwargs[2] != Qundef) { open_timeout = kwargs[2]; }
+ if (kwargs[3] != Qundef) { fast_fallback = kwargs[3]; }
+ if (kwargs[4] != Qundef) { test_mode_settings = kwargs[4]; }
+ }
+
+ if (fast_fallback == Qnil) {
+ fast_fallback = rb_ivar_get(rb_cSocket, tcp_fast_fallback);
+ if (fast_fallback == Qnil) fast_fallback = Qtrue;
+ }
+
+ return rsock_init_inetsock(sock, remote_host, remote_serv,
+ local_host, local_serv, INET_CLIENT,
+ resolv_timeout, connect_timeout, open_timeout,
+ fast_fallback, test_mode_settings);
+}
+
+static VALUE
+tcp_sockaddr(struct sockaddr *addr, socklen_t len)
+{
+ return rsock_make_ipaddr(addr, len);
+}
+
+/*
+ * call-seq:
+ * TCPSocket.gethostbyname(hostname) => [official_hostname, alias_hostnames, address_family, *address_list]
+ *
+ * Use Addrinfo.getaddrinfo instead.
+ * This method is deprecated for the following reasons:
+ *
+ * - The 3rd element of the result is the address family of the first address.
+ * The address families of the rest of the addresses are not returned.
+ * - gethostbyname() may take a long time and it may block other threads.
+ * (GVL cannot be released since gethostbyname() is not thread safe.)
+ * - This method uses gethostbyname() function already removed from POSIX.
+ *
+ * This method lookups host information by _hostname_.
+ *
+ * TCPSocket.gethostbyname("localhost")
+ * #=> ["localhost", ["hal"], 2, "127.0.0.1"]
+ *
+ */
+static VALUE
+tcp_s_gethostbyname(VALUE obj, VALUE host)
+{
+ rb_warn("TCPSocket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead.");
+ struct rb_addrinfo *res =
+ rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME, Qnil);
+ return rsock_make_hostent(host, res, tcp_sockaddr);
+}
+
+void
+rsock_init_tcpsocket(void)
+{
+ /*
+ * Document-class: TCPSocket < IPSocket
+ *
+ * TCPSocket represents a TCP/IP client socket.
+ *
+ * A simple client may look like:
+ *
+ * require 'socket'
+ *
+ * s = TCPSocket.new 'localhost', 2000
+ *
+ * while line = s.gets # Read lines from socket
+ * puts line # and print them
+ * end
+ *
+ * s.close # close socket when done
+ *
+ */
+ rb_cTCPSocket = rb_define_class("TCPSocket", rb_cIPSocket);
+ rb_define_singleton_method(rb_cTCPSocket, "gethostbyname", tcp_s_gethostbyname, 1);
+ rb_define_method(rb_cTCPSocket, "initialize", tcp_init, -1);
+}
diff --git a/ext/socket/udpsocket.c b/ext/socket/udpsocket.c
new file mode 100644
index 0000000000..b2bc925538
--- /dev/null
+++ b/ext/socket/udpsocket.c
@@ -0,0 +1,247 @@
+/************************************************
+
+ udpsocket.c -
+
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
+
+************************************************/
+
+#include "rubysocket.h"
+
+/*
+ * call-seq:
+ * UDPSocket.new([address_family]) => socket
+ *
+ * Creates a new UDPSocket object.
+ *
+ * _address_family_ should be an integer, a string or a symbol:
+ * Socket::AF_INET, "AF_INET", :INET, etc.
+ *
+ * require 'socket'
+ *
+ * UDPSocket.new #=> #<UDPSocket:fd 3>
+ * UDPSocket.new(Socket::AF_INET6) #=> #<UDPSocket:fd 4>
+ *
+ */
+static VALUE
+udp_init(int argc, VALUE *argv, VALUE sock)
+{
+ VALUE arg;
+ int family = AF_INET;
+ int fd;
+
+ if (rb_scan_args(argc, argv, "01", &arg) == 1) {
+ family = rsock_family_arg(arg);
+ }
+ fd = rsock_socket(family, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ rb_sys_fail("socket(2) - udp");
+ }
+
+ return rsock_init_sock(sock, fd);
+}
+
+struct udp_arg
+{
+ VALUE io;
+ struct rb_addrinfo *res;
+};
+
+static VALUE
+udp_connect_internal(VALUE v)
+{
+ struct udp_arg *arg = (void *)v;
+ struct addrinfo *res;
+
+ for (res = arg->res->ai; res; res = res->ai_next) {
+ if (rsock_connect(arg->io, res->ai_addr, res->ai_addrlen, 0, RUBY_IO_TIMEOUT_DEFAULT) >= 0) {
+ return Qtrue;
+ }
+ }
+ return Qfalse;
+}
+
+/*
+ * call-seq:
+ * udpsocket.connect(host, port) => 0
+ *
+ * Connects _udpsocket_ to _host_:_port_.
+ *
+ * This makes possible to send without destination address.
+ *
+ * u1 = UDPSocket.new
+ * u1.bind("127.0.0.1", 4913)
+ * u2 = UDPSocket.new
+ * u2.connect("127.0.0.1", 4913)
+ * u2.send "uuuu", 0
+ * p u1.recvfrom(10) #=> ["uuuu", ["AF_INET", 33230, "localhost", "127.0.0.1"]]
+ *
+ */
+static VALUE
+udp_connect(VALUE self, VALUE host, VALUE port)
+{
+ struct udp_arg arg = {.io = self};
+
+ arg.res = rsock_addrinfo(host, port, rsock_fd_family(rb_io_descriptor(self)), SOCK_DGRAM, 0, Qnil);
+
+ int result = (int)rb_ensure(udp_connect_internal, (VALUE)&arg, rsock_freeaddrinfo, (VALUE)arg.res);
+ if (!result) {
+ rsock_sys_fail_host_port("connect(2)", host, port);
+ }
+
+ return INT2FIX(0);
+}
+
+static VALUE
+udp_bind_internal(VALUE v)
+{
+ struct udp_arg *arg = (void *)v;
+ struct addrinfo *res;
+
+ rb_io_t *fptr;
+ RB_IO_POINTER(arg->io, fptr);
+
+ for (res = arg->res->ai; res; res = res->ai_next) {
+ if (bind(fptr->fd, res->ai_addr, res->ai_addrlen) < 0) {
+ continue;
+ }
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+/*
+ * call-seq:
+ * udpsocket.bind(host, port) #=> 0
+ *
+ * Binds _udpsocket_ to _host_:_port_.
+ *
+ * u1 = UDPSocket.new
+ * u1.bind("127.0.0.1", 4913)
+ * u1.send "message-to-self", 0, "127.0.0.1", 4913
+ * p u1.recvfrom(10) #=> ["message-to", ["AF_INET", 4913, "localhost", "127.0.0.1"]]
+ *
+ */
+static VALUE
+udp_bind(VALUE self, VALUE host, VALUE port)
+{
+ struct udp_arg arg = {.io = self};
+
+ arg.res = rsock_addrinfo(host, port, rsock_fd_family(rb_io_descriptor(self)), SOCK_DGRAM, 0, Qnil);
+
+ VALUE result = rb_ensure(udp_bind_internal, (VALUE)&arg, rsock_freeaddrinfo, (VALUE)arg.res);
+ if (!result) {
+ rsock_sys_fail_host_port("bind(2)", host, port);
+ }
+
+ return INT2FIX(0);
+}
+
+struct udp_send_arg {
+ rb_io_t *fptr;
+ struct rb_addrinfo *res;
+ struct rsock_send_arg sarg;
+};
+
+static VALUE
+udp_send_internal(VALUE v)
+{
+ struct udp_send_arg *arg = (void *)v;
+ rb_io_t *fptr;
+ struct addrinfo *res;
+
+ rb_io_check_closed(fptr = arg->fptr);
+ for (res = arg->res->ai; res; res = res->ai_next) {
+ retry:
+ arg->sarg.fd = fptr->fd;
+ arg->sarg.to = res->ai_addr;
+ arg->sarg.tolen = res->ai_addrlen;
+
+#ifdef RSOCK_WAIT_BEFORE_BLOCKING
+ rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_WRITABLE), Qnil);
+#endif
+
+ ssize_t n = (ssize_t)rb_io_blocking_region(fptr, rsock_sendto_blocking, &arg->sarg);
+
+ if (n >= 0) return RB_SSIZE2NUM(n);
+
+ if (rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) {
+ goto retry;
+ }
+ }
+ return Qfalse;
+}
+
+/*
+ * call-seq:
+ * udpsocket.send(mesg, flags, host, port) => numbytes_sent
+ * udpsocket.send(mesg, flags, sockaddr_to) => numbytes_sent
+ * udpsocket.send(mesg, flags) => numbytes_sent
+ *
+ * Sends _mesg_ via _udpsocket_.
+ *
+ * _flags_ should be a bitwise OR of Socket::MSG_* constants.
+ *
+ * u1 = UDPSocket.new
+ * u1.bind("127.0.0.1", 4913)
+ *
+ * u2 = UDPSocket.new
+ * u2.send "hi", 0, "127.0.0.1", 4913
+ *
+ * mesg, addr = u1.recvfrom(10)
+ * u1.send mesg, 0, addr[3], addr[1]
+ *
+ * p u2.recv(100) #=> "hi"
+ *
+ */
+static VALUE
+udp_send(int argc, VALUE *argv, VALUE sock)
+{
+ VALUE flags, host, port;
+ struct udp_send_arg arg;
+ VALUE ret;
+
+ if (argc == 2 || argc == 3) {
+ return rsock_bsock_send(argc, argv, sock);
+ }
+ rb_scan_args(argc, argv, "4", &arg.sarg.mesg, &flags, &host, &port);
+
+ StringValue(arg.sarg.mesg);
+ GetOpenFile(sock, arg.fptr);
+ arg.sarg.fd = arg.fptr->fd;
+ arg.sarg.flags = NUM2INT(flags);
+ arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0, Qnil);
+ ret = rb_ensure(udp_send_internal, (VALUE)&arg,
+ rsock_freeaddrinfo, (VALUE)arg.res);
+ if (!ret) rsock_sys_fail_host_port("sendto(2)", host, port);
+ return ret;
+}
+
+/* :nodoc: */
+static VALUE
+udp_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, VALUE ex)
+{
+ return rsock_s_recvfrom_nonblock(sock, len, flg, str, ex, RECV_IP);
+}
+
+void
+rsock_init_udpsocket(void)
+{
+ /*
+ * Document-class: UDPSocket < IPSocket
+ *
+ * UDPSocket represents a UDP/IP socket.
+ *
+ */
+ rb_cUDPSocket = rb_define_class("UDPSocket", rb_cIPSocket);
+ rb_define_method(rb_cUDPSocket, "initialize", udp_init, -1);
+ rb_define_method(rb_cUDPSocket, "connect", udp_connect, 2);
+ rb_define_method(rb_cUDPSocket, "bind", udp_bind, 2);
+ rb_define_method(rb_cUDPSocket, "send", udp_send, -1);
+
+ /* for ext/socket/lib/socket.rb use only: */
+ rb_define_private_method(rb_cUDPSocket,
+ "__recvfrom_nonblock", udp_recvfrom_nonblock, 4);
+}
diff --git a/ext/socket/unixserver.c b/ext/socket/unixserver.c
new file mode 100644
index 0000000000..0ea5ac083c
--- /dev/null
+++ b/ext/socket/unixserver.c
@@ -0,0 +1,121 @@
+/************************************************
+
+ unixserver.c -
+
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
+
+************************************************/
+
+#include "rubysocket.h"
+
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+/*
+ * call-seq:
+ * UNIXServer.new(path) => unixserver
+ *
+ * Creates a new UNIX server socket bound to _path_.
+ *
+ * require 'socket'
+ *
+ * serv = UNIXServer.new("/tmp/sock")
+ * s = serv.accept
+ * p s.read
+ */
+static VALUE
+unix_svr_init(VALUE sock, VALUE path)
+{
+ return rsock_init_unixsock(sock, path, 1);
+}
+
+/*
+ * call-seq:
+ * unixserver.accept => unixsocket
+ *
+ * Accepts an incoming connection.
+ * It returns a new UNIXSocket object.
+ *
+ * UNIXServer.open("/tmp/sock") {|serv|
+ * UNIXSocket.open("/tmp/sock") {|c|
+ * s = serv.accept
+ * s.puts "hi"
+ * s.close
+ * p c.read #=> "hi\n"
+ * }
+ * }
+ *
+ */
+static VALUE
+unix_accept(VALUE server)
+{
+ struct sockaddr_un buffer;
+ socklen_t length = sizeof(buffer);
+
+ return rsock_s_accept(rb_cUNIXSocket, server, (struct sockaddr*)&buffer, &length);
+}
+
+/* :nodoc: */
+static VALUE
+unix_accept_nonblock(VALUE sock, VALUE ex)
+{
+ rb_io_t *fptr;
+ struct sockaddr_un from;
+ socklen_t fromlen;
+
+ GetOpenFile(sock, fptr);
+ fromlen = (socklen_t)sizeof(from);
+ return rsock_s_accept_nonblock(rb_cUNIXSocket, ex, fptr,
+ (struct sockaddr *)&from, &fromlen);
+}
+
+/*
+ * call-seq:
+ * unixserver.sysaccept => file_descriptor
+ *
+ * Accepts a new connection.
+ * It returns the new file descriptor which is an integer.
+ *
+ * UNIXServer.open("/tmp/sock") {|serv|
+ * UNIXSocket.open("/tmp/sock") {|c|
+ * fd = serv.sysaccept
+ * s = IO.new(fd)
+ * s.puts "hi"
+ * s.close
+ * p c.read #=> "hi\n"
+ * }
+ * }
+ *
+ */
+static VALUE
+unix_sysaccept(VALUE server)
+{
+ struct sockaddr_un buffer;
+ socklen_t length = sizeof(buffer);
+
+ return rsock_s_accept(0, server, (struct sockaddr*)&buffer, &length);
+}
+
+#endif
+
+void
+rsock_init_unixserver(void)
+{
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ /*
+ * Document-class: UNIXServer < UNIXSocket
+ *
+ * UNIXServer represents a UNIX domain stream server socket.
+ *
+ */
+ rb_cUNIXServer = rb_define_class("UNIXServer", rb_cUNIXSocket);
+ rb_define_method(rb_cUNIXServer, "initialize", unix_svr_init, 1);
+ rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0);
+
+ rb_define_private_method(rb_cUNIXServer,
+ "__accept_nonblock", unix_accept_nonblock, 1);
+
+ rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0);
+ rb_define_method(rb_cUNIXServer, "listen", rsock_sock_listen, 1); /* in socket.c */
+#endif
+}
diff --git a/ext/socket/unixsocket.c b/ext/socket/unixsocket.c
new file mode 100644
index 0000000000..2ec9376074
--- /dev/null
+++ b/ext/socket/unixsocket.c
@@ -0,0 +1,598 @@
+/************************************************
+
+ unixsocket.c -
+
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
+
+************************************************/
+
+#include "rubysocket.h"
+
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+struct unixsock_arg {
+ struct sockaddr_un *sockaddr;
+ socklen_t sockaddrlen;
+ VALUE io;
+};
+
+static VALUE
+unixsock_connect_internal(VALUE a)
+{
+ struct unixsock_arg *arg = (struct unixsock_arg *)a;
+ return (VALUE)rsock_connect(arg->io, (struct sockaddr*)arg->sockaddr, arg->sockaddrlen, 0, RUBY_IO_TIMEOUT_DEFAULT);
+}
+
+static VALUE
+unixsock_path_value(VALUE path)
+{
+#ifdef __linux__
+#define TO_STR_FOR_LINUX_ABSTRACT_NAMESPACE 0
+
+ VALUE name = path;
+#if TO_STR_FOR_LINUX_ABSTRACT_NAMESPACE
+ const int isstr = !NIL_P(name = rb_check_string_type(name));
+#else
+ const int isstr = RB_TYPE_P(name, T_STRING);
+#endif
+ if (isstr) {
+ if (RSTRING_LEN(name) == 0 || RSTRING_PTR(name)[0] == '\0') {
+ return name; /* ignore encoding */
+ }
+ }
+#endif
+ path = rb_get_path(path);
+#ifdef _WIN32
+ /* UNIXSocket requires UTF-8 per spec. */
+ path = rb_str_export_to_enc(path, rb_utf8_encoding());
+#endif
+ return path;
+}
+
+VALUE
+rsock_init_unixsock(VALUE self, VALUE path, int server)
+{
+ struct sockaddr_un sockaddr;
+ socklen_t sockaddrlen;
+ int fd, status;
+ rb_io_t *fptr;
+
+ path = unixsock_path_value(path);
+
+ INIT_SOCKADDR_UN(&sockaddr, sizeof(struct sockaddr_un));
+ if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) {
+ rb_raise(rb_eArgError, "too long unix socket path (%ldbytes given but %dbytes max)",
+ RSTRING_LEN(path), (int)sizeof(sockaddr.sun_path));
+ }
+ memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
+ sockaddrlen = rsock_unix_sockaddr_len(path);
+
+ fd = rsock_socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ rsock_sys_fail_path("socket(2)", path);
+ }
+
+ VALUE io = rsock_init_sock(self, fd);
+ RB_IO_POINTER(io, fptr);
+
+ if (server) {
+ status = bind(fd, (struct sockaddr*)&sockaddr, sockaddrlen);
+ }
+ else {
+ int error_tag;
+ struct unixsock_arg arg;
+ arg.sockaddr = &sockaddr;
+ arg.sockaddrlen = sockaddrlen;
+ arg.io = io;
+
+ status = (int)rb_protect(unixsock_connect_internal, (VALUE)&arg, &error_tag);
+
+ if (error_tag) {
+ rb_io_close(io);
+ rb_jump_tag(error_tag);
+ }
+ }
+
+ if (status < 0) {
+ int e = errno;
+ rb_io_close(io);
+ rsock_syserr_fail_path(e, "connect(2)", path);
+ }
+
+ if (server) {
+ if (listen(fd, SOMAXCONN) < 0) {
+ int e = errno;
+ rb_io_close(io);
+ rsock_syserr_fail_path(e, "listen(2)", path);
+ }
+ }
+
+ if (server) {
+ fptr->pathv = rb_str_new_frozen(path);
+ }
+
+ return io;
+}
+
+/*
+ * call-seq:
+ * UNIXSocket.new(path) => unixsocket
+ *
+ * Creates a new UNIX client socket connected to _path_.
+ *
+ * require 'socket'
+ *
+ * s = UNIXSocket.new("/tmp/sock")
+ * s.send "hello", 0
+ *
+ */
+static VALUE
+unix_init(VALUE self, VALUE path)
+{
+ return rsock_init_unixsock(self, path, 0);
+}
+
+/*
+ * call-seq:
+ * unixsocket.path => path
+ *
+ * Returns the path of the local address of unixsocket.
+ *
+ * s = UNIXServer.new("/tmp/sock")
+ * p s.path #=> "/tmp/sock"
+ *
+ */
+static VALUE
+unix_path(VALUE sock)
+{
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (NIL_P(fptr->pathv)) {
+ struct sockaddr_un addr;
+ socklen_t len = (socklen_t)sizeof(addr);
+ socklen_t len0 = len;
+ if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
+ rsock_sys_fail_path("getsockname(2)", fptr->pathv);
+ if (len0 < len) len = len0;
+ fptr->pathv = rb_obj_freeze(rsock_unixpath_str(&addr, len));
+ }
+ return rb_str_dup(fptr->pathv);
+}
+
+/*
+ * call-seq:
+ * unixsocket.recvfrom(maxlen [, flags[, outbuf]]) => [mesg, unixaddress]
+ *
+ * Receives a message via _unixsocket_.
+ *
+ * _maxlen_ is the maximum number of bytes to receive.
+ *
+ * _flags_ should be a bitwise OR of Socket::MSG_* constants.
+ *
+ * _outbuf_ will contain only the received data after the method call
+ * even if it is not empty at the beginning.
+ *
+ * s1 = Socket.new(:UNIX, :DGRAM, 0)
+ * s1_ai = Addrinfo.unix("/tmp/sock1")
+ * s1.bind(s1_ai)
+ *
+ * s2 = Socket.new(:UNIX, :DGRAM, 0)
+ * s2_ai = Addrinfo.unix("/tmp/sock2")
+ * s2.bind(s2_ai)
+ * s3 = UNIXSocket.for_fd(s2.fileno)
+ *
+ * s1.send "a", 0, s2_ai
+ * p s3.recvfrom(10) #=> ["a", ["AF_UNIX", "/tmp/sock1"]]
+ *
+ */
+static VALUE
+unix_recvfrom(int argc, VALUE *argv, VALUE sock)
+{
+ return rsock_s_recvfrom(sock, argc, argv, RECV_UNIX);
+}
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && defined(SCM_RIGHTS)
+#define FD_PASSING_BY_MSG_CONTROL 1
+#else
+#define FD_PASSING_BY_MSG_CONTROL 0
+#endif
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS)
+#define FD_PASSING_BY_MSG_ACCRIGHTS 1
+#else
+#define FD_PASSING_BY_MSG_ACCRIGHTS 0
+#endif
+
+struct iomsg_arg {
+ int fd;
+ struct msghdr msg;
+};
+
+#if defined(HAVE_SENDMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
+static VALUE
+sendmsg_blocking(void *data)
+{
+ struct iomsg_arg *arg = data;
+ return sendmsg(arg->fd, &arg->msg, 0);
+}
+
+/*
+ * call-seq:
+ * unixsocket.send_io(io) => nil
+ *
+ * Sends _io_ as file descriptor passing.
+ *
+ * s1, s2 = UNIXSocket.pair
+ *
+ * s1.send_io STDOUT
+ * stdout = s2.recv_io
+ *
+ * p STDOUT.fileno #=> 1
+ * p stdout.fileno #=> 6
+ *
+ * stdout.puts "hello" # outputs "hello\n" to standard output.
+ *
+ * _io_ may be any kind of IO object or integer file descriptor.
+ */
+static VALUE
+unix_send_io(VALUE sock, VALUE val)
+{
+ int fd;
+ rb_io_t *fptr;
+ struct iomsg_arg arg;
+ struct iovec vec[1];
+ char buf[1];
+
+#if FD_PASSING_BY_MSG_CONTROL
+ union {
+ struct cmsghdr hdr;
+ char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8];
+ } cmsg;
+#endif
+
+ if (rb_obj_is_kind_of(val, rb_cIO)) {
+ rb_io_t *valfptr;
+ GetOpenFile(val, valfptr);
+ fd = valfptr->fd;
+ }
+ else if (FIXNUM_P(val)) {
+ fd = FIX2INT(val);
+ }
+ else {
+ rb_raise(rb_eTypeError, "neither IO nor file descriptor");
+ }
+
+ GetOpenFile(sock, fptr);
+
+ arg.msg.msg_name = NULL;
+ arg.msg.msg_namelen = 0;
+
+ /* Linux and Solaris doesn't work if msg_iov is NULL. */
+ buf[0] = '\0';
+ vec[0].iov_base = buf;
+ vec[0].iov_len = 1;
+ arg.msg.msg_iov = vec;
+ arg.msg.msg_iovlen = 1;
+
+#if FD_PASSING_BY_MSG_CONTROL
+ arg.msg.msg_control = (caddr_t)&cmsg;
+ arg.msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof(int));
+ arg.msg.msg_flags = 0;
+ MEMZERO((char*)&cmsg, char, sizeof(cmsg));
+ cmsg.hdr.cmsg_len = (socklen_t)CMSG_LEN(sizeof(int));
+ cmsg.hdr.cmsg_level = SOL_SOCKET;
+ cmsg.hdr.cmsg_type = SCM_RIGHTS;
+ memcpy(CMSG_DATA(&cmsg.hdr), &fd, sizeof(int));
+#else
+ arg.msg.msg_accrights = (caddr_t)&fd;
+ arg.msg.msg_accrightslen = sizeof(fd);
+#endif
+
+ arg.fd = fptr->fd;
+ while ((int)rb_io_blocking_region(fptr, sendmsg_blocking, &arg) == -1) {
+ if (!rb_io_wait_writable(arg.fd))
+ rsock_sys_fail_path("sendmsg(2)", fptr->pathv);
+ }
+
+ return Qnil;
+}
+#else
+#define unix_send_io rb_f_notimplement
+#endif
+
+#if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
+static VALUE
+recvmsg_blocking(void *data)
+{
+ struct iomsg_arg *arg = data;
+ int flags = 0;
+ return rsock_recvmsg(arg->fd, &arg->msg, flags);
+}
+
+/*
+ * call-seq:
+ * unixsocket.recv_io([klass [, mode]]) => io
+ *
+ * Example
+ *
+ * UNIXServer.open("/tmp/sock") {|serv|
+ * UNIXSocket.open("/tmp/sock") {|c|
+ * s = serv.accept
+ *
+ * c.send_io STDOUT
+ * stdout = s.recv_io
+ *
+ * p STDOUT.fileno #=> 1
+ * p stdout.fileno #=> 7
+ *
+ * stdout.puts "hello" # outputs "hello\n" to standard output.
+ * }
+ * }
+ *
+ * _klass_ will determine the class of _io_ returned (using the
+ * IO.for_fd singleton method or similar).
+ * If _klass_ is +nil+, an integer file descriptor is returned.
+ *
+ * _mode_ is the same as the argument passed to IO.for_fd
+ */
+static VALUE
+unix_recv_io(int argc, VALUE *argv, VALUE sock)
+{
+ VALUE klass, mode;
+ rb_io_t *fptr;
+ struct iomsg_arg arg;
+ struct iovec vec[2];
+ char buf[1];
+ unsigned int gc_reason = 0;
+ enum {
+ GC_REASON_EMSGSIZE = 0x1,
+ GC_REASON_TRUNCATE = 0x2,
+ GC_REASON_ENOMEM = 0x4
+ };
+
+ int fd;
+#if FD_PASSING_BY_MSG_CONTROL
+ union {
+ struct cmsghdr hdr;
+ char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8];
+ } cmsg;
+#endif
+
+ rb_scan_args(argc, argv, "02", &klass, &mode);
+ if (argc == 0)
+ klass = rb_cIO;
+ if (argc <= 1)
+ mode = Qnil;
+
+retry:
+ GetOpenFile(sock, fptr);
+
+ arg.msg.msg_name = NULL;
+ arg.msg.msg_namelen = 0;
+
+ vec[0].iov_base = buf;
+ vec[0].iov_len = sizeof(buf);
+ arg.msg.msg_iov = vec;
+ arg.msg.msg_iovlen = 1;
+
+#if FD_PASSING_BY_MSG_CONTROL
+ arg.msg.msg_control = (caddr_t)&cmsg;
+ arg.msg.msg_controllen = (socklen_t)CMSG_SPACE(sizeof(int));
+ arg.msg.msg_flags = 0;
+ cmsg.hdr.cmsg_len = (socklen_t)CMSG_LEN(sizeof(int));
+ cmsg.hdr.cmsg_level = SOL_SOCKET;
+ cmsg.hdr.cmsg_type = SCM_RIGHTS;
+ fd = -1;
+ memcpy(CMSG_DATA(&cmsg.hdr), &fd, sizeof(int));
+#else
+ arg.msg.msg_accrights = (caddr_t)&fd;
+ arg.msg.msg_accrightslen = sizeof(fd);
+ fd = -1;
+#endif
+
+ arg.fd = fptr->fd;
+ while ((int)rb_io_blocking_region(fptr, recvmsg_blocking, &arg) == -1) {
+ int e = errno;
+ if (e == EMSGSIZE && !(gc_reason & GC_REASON_EMSGSIZE)) {
+ /* FreeBSD gets here when we're out of FDs */
+ gc_reason |= GC_REASON_EMSGSIZE;
+ rb_gc_for_fd(EMFILE);
+ goto retry;
+ }
+ else if (e == ENOMEM && !(gc_reason & GC_REASON_ENOMEM)) {
+ /* ENOMEM is documented in recvmsg manpages */
+ gc_reason |= GC_REASON_ENOMEM;
+ rb_gc_for_fd(e);
+ goto retry;
+ }
+ if (!rb_io_wait_readable(arg.fd))
+ rsock_syserr_fail_path(e, "recvmsg(2)", fptr->pathv);
+ }
+
+#if FD_PASSING_BY_MSG_CONTROL
+ if (arg.msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr)) {
+ /* FreeBSD and Linux both get here when we're out of FDs */
+ if (!(gc_reason & GC_REASON_TRUNCATE)) {
+ gc_reason |= GC_REASON_TRUNCATE;
+ rb_gc_for_fd(EMFILE);
+ goto retry;
+ }
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (msg_controllen=%d smaller than sizeof(struct cmsghdr)=%d)",
+ (int)arg.msg.msg_controllen, (int)sizeof(struct cmsghdr));
+ }
+ if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (cmsg_level=%d, %d expected)",
+ cmsg.hdr.cmsg_level, SOL_SOCKET);
+ }
+ if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (cmsg_type=%d, %d expected)",
+ cmsg.hdr.cmsg_type, SCM_RIGHTS);
+ }
+ if (arg.msg.msg_controllen < (socklen_t)CMSG_LEN(sizeof(int))) {
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (msg_controllen=%d smaller than CMSG_LEN(sizeof(int))=%d)",
+ (int)arg.msg.msg_controllen, (int)CMSG_LEN(sizeof(int)));
+ }
+ if ((socklen_t)CMSG_SPACE(sizeof(int)) < arg.msg.msg_controllen) {
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (msg_controllen=%d bigger than CMSG_SPACE(sizeof(int))=%d)",
+ (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int)));
+ }
+ if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
+ rsock_discard_cmsg_resource(&arg.msg, 0);
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (cmsg_len=%d, %d expected)",
+ (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int)));
+ }
+#else
+ if (arg.msg.msg_accrightslen != sizeof(fd)) {
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (accrightslen=%d, %d expected)",
+ arg.msg.msg_accrightslen, (int)sizeof(fd));
+ }
+#endif
+
+#if FD_PASSING_BY_MSG_CONTROL
+ memcpy(&fd, CMSG_DATA(&cmsg.hdr), sizeof(int));
+#endif
+
+ rb_update_max_fd(fd);
+ rb_maygvl_fd_fix_cloexec(fd);
+
+ if (klass == Qnil)
+ return INT2FIX(fd);
+ else {
+ ID for_fd;
+ int ff_argc;
+ VALUE ff_argv[2];
+ CONST_ID(for_fd, "for_fd");
+ ff_argc = mode == Qnil ? 1 : 2;
+ ff_argv[0] = INT2FIX(fd);
+ ff_argv[1] = mode;
+ return rb_funcallv(klass, for_fd, ff_argc, ff_argv);
+ }
+}
+#else
+#define unix_recv_io rb_f_notimplement
+#endif
+
+/*
+ * call-seq:
+ * unixsocket.addr => [address_family, unix_path]
+ *
+ * Returns the local address as an array which contains
+ * address_family and unix_path.
+ *
+ * Example
+ * serv = UNIXServer.new("/tmp/sock")
+ * p serv.addr #=> ["AF_UNIX", "/tmp/sock"]
+ */
+static VALUE
+unix_addr(VALUE sock)
+{
+ rb_io_t *fptr;
+ struct sockaddr_un addr;
+ socklen_t len = (socklen_t)sizeof addr;
+ socklen_t len0 = len;
+
+ GetOpenFile(sock, fptr);
+
+ if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
+ rsock_sys_fail_path("getsockname(2)", fptr->pathv);
+ if (len0 < len) len = len0;
+ return rsock_unixaddr(&addr, len);
+}
+
+/*
+ * call-seq:
+ * unixsocket.peeraddr => [address_family, unix_path]
+ *
+ * Returns the remote address as an array which contains
+ * address_family and unix_path.
+ *
+ * Example
+ * serv = UNIXServer.new("/tmp/sock")
+ * c = UNIXSocket.new("/tmp/sock")
+ * p c.peeraddr #=> ["AF_UNIX", "/tmp/sock"]
+ */
+static VALUE
+unix_peeraddr(VALUE sock)
+{
+ rb_io_t *fptr;
+ struct sockaddr_un addr;
+ socklen_t len = (socklen_t)sizeof addr;
+ socklen_t len0 = len;
+
+ GetOpenFile(sock, fptr);
+
+ if (getpeername(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
+ rsock_sys_fail_path("getpeername(2)", fptr->pathv);
+ if (len0 < len) len = len0;
+ return rsock_unixaddr(&addr, len);
+}
+
+/*
+ * call-seq:
+ * UNIXSocket.pair([type [, protocol]]) => [unixsocket1, unixsocket2]
+ * UNIXSocket.socketpair([type [, protocol]]) => [unixsocket1, unixsocket2]
+ *
+ * Creates a pair of sockets connected to each other.
+ *
+ * _type_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc.
+ *
+ * _protocol_ should be a protocol defined in the domain.
+ * 0 is default protocol for the domain.
+ *
+ * s1, s2 = UNIXSocket.pair
+ * s1.send "a", 0
+ * s1.send "b", 0
+ * p s2.recv(10) #=> "ab"
+ *
+ */
+static VALUE
+unix_s_socketpair(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE domain, type, protocol;
+ VALUE args[3];
+
+ domain = INT2FIX(PF_UNIX);
+ rb_scan_args(argc, argv, "02", &type, &protocol);
+ if (argc == 0)
+ type = INT2FIX(SOCK_STREAM);
+ if (argc <= 1)
+ protocol = INT2FIX(0);
+
+ args[0] = domain;
+ args[1] = type;
+ args[2] = protocol;
+
+ return rsock_sock_s_socketpair(3, args, klass);
+}
+#endif
+
+void
+rsock_init_unixsocket(void)
+{
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
+ /*
+ * Document-class: UNIXSocket < BasicSocket
+ *
+ * UNIXSocket represents a UNIX domain stream client socket.
+ */
+ rb_cUNIXSocket = rb_define_class("UNIXSocket", rb_cBasicSocket);
+ rb_define_method(rb_cUNIXSocket, "initialize", unix_init, 1);
+ rb_define_method(rb_cUNIXSocket, "path", unix_path, 0);
+ rb_define_method(rb_cUNIXSocket, "addr", unix_addr, 0);
+ rb_define_method(rb_cUNIXSocket, "peeraddr", unix_peeraddr, 0);
+ rb_define_method(rb_cUNIXSocket, "recvfrom", unix_recvfrom, -1);
+ rb_define_method(rb_cUNIXSocket, "send_io", unix_send_io, 1);
+ rb_define_method(rb_cUNIXSocket, "recv_io", unix_recv_io, -1);
+ rb_define_singleton_method(rb_cUNIXSocket, "socketpair", unix_s_socketpair, -1);
+ rb_define_singleton_method(rb_cUNIXSocket, "pair", unix_s_socketpair, -1);
+#endif
+}
diff --git a/ext/stringio/.cvsignore b/ext/stringio/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/stringio/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/stringio/.document b/ext/stringio/.document
new file mode 100644
index 0000000000..decba0135a
--- /dev/null
+++ b/ext/stringio/.document
@@ -0,0 +1 @@
+*.[ch]
diff --git a/ext/stringio/README b/ext/stringio/README
deleted file mode 100644
index c4031f7e97..0000000000
--- a/ext/stringio/README
+++ /dev/null
@@ -1,19 +0,0 @@
--*- rd -*-
-$Author$
-$Date$
-
-=begin
-
-= StringIO
-Pseudo (({IO})) class from/to (({String})).
-
-This library is based on MoonWolf version written in Ruby. Thanks a lot.
-
-= Differences to (({IO}))
-
-* not implemented: (({fcntl})), (({reopen})).
-* (({fileno})) returns nil.
-* (({pos=})) returns new position, not 0.
-* (({ungetc})) does nothing at start of the string.
-
-=end
diff --git a/ext/stringio/README.md b/ext/stringio/README.md
new file mode 100644
index 0000000000..94532ed688
--- /dev/null
+++ b/ext/stringio/README.md
@@ -0,0 +1,10 @@
+# StringIO
+
+Pseudo `IO` class from/to `String`.
+
+This library is based on MoonWolf version written in Ruby. Thanks a lot.
+
+## Differences to `IO`
+
+* `fileno` raises `NotImplementedError`.
+* encoding conversion is not implemented, and ignored silently.
diff --git a/ext/stringio/depend b/ext/stringio/depend
index cc9eae3f55..3a82ad0a11 100644
--- a/ext/stringio/depend
+++ b/ext/stringio/depend
@@ -1,2 +1,177 @@
-stringio.o: stringio.c $(hdrdir)/ruby.h $(topdir)/config.h \
- $(hdrdir)/defines.h $(hdrdir)/intern.h $(hdrdir)/rubyio.h
+# AUTOGENERATED DEPENDENCIES START
+stringio.o: $(RUBY_EXTCONF_H)
+stringio.o: $(arch_hdrdir)/ruby/config.h
+stringio.o: $(hdrdir)/ruby.h
+stringio.o: $(hdrdir)/ruby/assert.h
+stringio.o: $(hdrdir)/ruby/backward.h
+stringio.o: $(hdrdir)/ruby/backward/2/assume.h
+stringio.o: $(hdrdir)/ruby/backward/2/attributes.h
+stringio.o: $(hdrdir)/ruby/backward/2/bool.h
+stringio.o: $(hdrdir)/ruby/backward/2/inttypes.h
+stringio.o: $(hdrdir)/ruby/backward/2/limits.h
+stringio.o: $(hdrdir)/ruby/backward/2/long_long.h
+stringio.o: $(hdrdir)/ruby/backward/2/stdalign.h
+stringio.o: $(hdrdir)/ruby/backward/2/stdarg.h
+stringio.o: $(hdrdir)/ruby/defines.h
+stringio.o: $(hdrdir)/ruby/encoding.h
+stringio.o: $(hdrdir)/ruby/intern.h
+stringio.o: $(hdrdir)/ruby/internal/abi.h
+stringio.o: $(hdrdir)/ruby/internal/anyargs.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+stringio.o: $(hdrdir)/ruby/internal/assume.h
+stringio.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+stringio.o: $(hdrdir)/ruby/internal/attr/artificial.h
+stringio.o: $(hdrdir)/ruby/internal/attr/cold.h
+stringio.o: $(hdrdir)/ruby/internal/attr/const.h
+stringio.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+stringio.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+stringio.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+stringio.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+stringio.o: $(hdrdir)/ruby/internal/attr/error.h
+stringio.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+stringio.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+stringio.o: $(hdrdir)/ruby/internal/attr/format.h
+stringio.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+stringio.o: $(hdrdir)/ruby/internal/attr/noalias.h
+stringio.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+stringio.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+stringio.o: $(hdrdir)/ruby/internal/attr/noinline.h
+stringio.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+stringio.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+stringio.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+stringio.o: $(hdrdir)/ruby/internal/attr/pure.h
+stringio.o: $(hdrdir)/ruby/internal/attr/restrict.h
+stringio.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+stringio.o: $(hdrdir)/ruby/internal/attr/warning.h
+stringio.o: $(hdrdir)/ruby/internal/attr/weakref.h
+stringio.o: $(hdrdir)/ruby/internal/cast.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_since.h
+stringio.o: $(hdrdir)/ruby/internal/config.h
+stringio.o: $(hdrdir)/ruby/internal/constant_p.h
+stringio.o: $(hdrdir)/ruby/internal/core.h
+stringio.o: $(hdrdir)/ruby/internal/core/rarray.h
+stringio.o: $(hdrdir)/ruby/internal/core/rbasic.h
+stringio.o: $(hdrdir)/ruby/internal/core/rbignum.h
+stringio.o: $(hdrdir)/ruby/internal/core/rclass.h
+stringio.o: $(hdrdir)/ruby/internal/core/rdata.h
+stringio.o: $(hdrdir)/ruby/internal/core/rfile.h
+stringio.o: $(hdrdir)/ruby/internal/core/rhash.h
+stringio.o: $(hdrdir)/ruby/internal/core/robject.h
+stringio.o: $(hdrdir)/ruby/internal/core/rregexp.h
+stringio.o: $(hdrdir)/ruby/internal/core/rstring.h
+stringio.o: $(hdrdir)/ruby/internal/core/rstruct.h
+stringio.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+stringio.o: $(hdrdir)/ruby/internal/ctype.h
+stringio.o: $(hdrdir)/ruby/internal/dllexport.h
+stringio.o: $(hdrdir)/ruby/internal/dosish.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/re.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/string.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+stringio.o: $(hdrdir)/ruby/internal/error.h
+stringio.o: $(hdrdir)/ruby/internal/eval.h
+stringio.o: $(hdrdir)/ruby/internal/event.h
+stringio.o: $(hdrdir)/ruby/internal/fl_type.h
+stringio.o: $(hdrdir)/ruby/internal/gc.h
+stringio.o: $(hdrdir)/ruby/internal/glob.h
+stringio.o: $(hdrdir)/ruby/internal/globals.h
+stringio.o: $(hdrdir)/ruby/internal/has/attribute.h
+stringio.o: $(hdrdir)/ruby/internal/has/builtin.h
+stringio.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+stringio.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+stringio.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+stringio.o: $(hdrdir)/ruby/internal/has/extension.h
+stringio.o: $(hdrdir)/ruby/internal/has/feature.h
+stringio.o: $(hdrdir)/ruby/internal/has/warning.h
+stringio.o: $(hdrdir)/ruby/internal/intern/array.h
+stringio.o: $(hdrdir)/ruby/internal/intern/bignum.h
+stringio.o: $(hdrdir)/ruby/internal/intern/class.h
+stringio.o: $(hdrdir)/ruby/internal/intern/compar.h
+stringio.o: $(hdrdir)/ruby/internal/intern/complex.h
+stringio.o: $(hdrdir)/ruby/internal/intern/cont.h
+stringio.o: $(hdrdir)/ruby/internal/intern/dir.h
+stringio.o: $(hdrdir)/ruby/internal/intern/enum.h
+stringio.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+stringio.o: $(hdrdir)/ruby/internal/intern/error.h
+stringio.o: $(hdrdir)/ruby/internal/intern/eval.h
+stringio.o: $(hdrdir)/ruby/internal/intern/file.h
+stringio.o: $(hdrdir)/ruby/internal/intern/hash.h
+stringio.o: $(hdrdir)/ruby/internal/intern/io.h
+stringio.o: $(hdrdir)/ruby/internal/intern/load.h
+stringio.o: $(hdrdir)/ruby/internal/intern/marshal.h
+stringio.o: $(hdrdir)/ruby/internal/intern/numeric.h
+stringio.o: $(hdrdir)/ruby/internal/intern/object.h
+stringio.o: $(hdrdir)/ruby/internal/intern/parse.h
+stringio.o: $(hdrdir)/ruby/internal/intern/proc.h
+stringio.o: $(hdrdir)/ruby/internal/intern/process.h
+stringio.o: $(hdrdir)/ruby/internal/intern/random.h
+stringio.o: $(hdrdir)/ruby/internal/intern/range.h
+stringio.o: $(hdrdir)/ruby/internal/intern/rational.h
+stringio.o: $(hdrdir)/ruby/internal/intern/re.h
+stringio.o: $(hdrdir)/ruby/internal/intern/ruby.h
+stringio.o: $(hdrdir)/ruby/internal/intern/select.h
+stringio.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+stringio.o: $(hdrdir)/ruby/internal/intern/set.h
+stringio.o: $(hdrdir)/ruby/internal/intern/signal.h
+stringio.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+stringio.o: $(hdrdir)/ruby/internal/intern/string.h
+stringio.o: $(hdrdir)/ruby/internal/intern/struct.h
+stringio.o: $(hdrdir)/ruby/internal/intern/thread.h
+stringio.o: $(hdrdir)/ruby/internal/intern/time.h
+stringio.o: $(hdrdir)/ruby/internal/intern/variable.h
+stringio.o: $(hdrdir)/ruby/internal/intern/vm.h
+stringio.o: $(hdrdir)/ruby/internal/interpreter.h
+stringio.o: $(hdrdir)/ruby/internal/iterator.h
+stringio.o: $(hdrdir)/ruby/internal/memory.h
+stringio.o: $(hdrdir)/ruby/internal/method.h
+stringio.o: $(hdrdir)/ruby/internal/module.h
+stringio.o: $(hdrdir)/ruby/internal/newobj.h
+stringio.o: $(hdrdir)/ruby/internal/scan_args.h
+stringio.o: $(hdrdir)/ruby/internal/special_consts.h
+stringio.o: $(hdrdir)/ruby/internal/static_assert.h
+stringio.o: $(hdrdir)/ruby/internal/stdalign.h
+stringio.o: $(hdrdir)/ruby/internal/stdbool.h
+stringio.o: $(hdrdir)/ruby/internal/stdckdint.h
+stringio.o: $(hdrdir)/ruby/internal/symbol.h
+stringio.o: $(hdrdir)/ruby/internal/value.h
+stringio.o: $(hdrdir)/ruby/internal/value_type.h
+stringio.o: $(hdrdir)/ruby/internal/variable.h
+stringio.o: $(hdrdir)/ruby/internal/warning_push.h
+stringio.o: $(hdrdir)/ruby/internal/xmalloc.h
+stringio.o: $(hdrdir)/ruby/io.h
+stringio.o: $(hdrdir)/ruby/missing.h
+stringio.o: $(hdrdir)/ruby/onigmo.h
+stringio.o: $(hdrdir)/ruby/oniguruma.h
+stringio.o: $(hdrdir)/ruby/ruby.h
+stringio.o: $(hdrdir)/ruby/st.h
+stringio.o: $(hdrdir)/ruby/subst.h
+stringio.o: $(hdrdir)/ruby/version.h
+stringio.o: stringio.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/stringio/extconf.rb b/ext/stringio/extconf.rb
index 8fc84b3735..0089766983 100644
--- a/ext/stringio/extconf.rb
+++ b/ext/stringio/extconf.rb
@@ -1,2 +1,9 @@
+# frozen_string_literal: false
require 'mkmf'
-create_makefile('stringio')
+if RUBY_ENGINE == 'ruby'
+ have_type("rb_io_mode_t", "ruby/io.h")
+
+ create_makefile('stringio')
+else
+ File.write('Makefile', dummy_makefile("").join)
+end
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index a64aaf837c..41aa71f893 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -1,9 +1,9 @@
+/* -*- mode: c; indent-tabs-mode: t -*- */
/**********************************************************************
stringio.c -
$Author$
- $Date$
$RoughId: stringio.c,v 1.13 2002/03/14 03:24:18 nobu Exp $
created at: Tue Feb 19 04:10:38 JST 2002
@@ -12,38 +12,73 @@
**********************************************************************/
+static const char *const
+STRINGIO_VERSION = "3.2.1.dev";
+
+#include <stdbool.h>
+
#include "ruby.h"
-#include "rubyio.h"
+#include "ruby/io.h"
+#include "ruby/encoding.h"
+#include "ruby/version.h"
#if defined(HAVE_FCNTL_H) || defined(_WIN32)
#include <fcntl.h>
#elif defined(HAVE_SYS_FCNTL_H)
#include <sys/fcntl.h>
#endif
-#define STRIO_EOF FMODE_SYNC
+#ifndef RB_INTEGER_TYPE_P
+# define RB_INTEGER_TYPE_P(c) (FIXNUM_P(c) || RB_TYPE_P(c, T_BIGNUM))
+#endif
+
+#ifndef RB_PASS_CALLED_KEYWORDS
+# define rb_funcallv_kw(recv, mid, arg, argv, kw_splat) rb_funcallv(recv, mid, arg, argv)
+# define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
+#endif
+
+static inline bool
+str_chilled_p(VALUE str)
+{
+#if (RUBY_API_VERSION_MAJOR == 3 && RUBY_API_VERSION_MINOR >= 4) || RUBY_API_VERSION_MAJOR >= 4
+ // Do not attempt to modify chilled strings on Ruby 3.4+
+ // RUBY_FL_USER2 == STR_CHILLED_LITERAL
+ // RUBY_FL_USER3 == STR_CHILLED_SYMBOL_TO_S
+ return FL_TEST_RAW(str, RUBY_FL_USER2 | RUBY_FL_USER3);
+#else
+ return false;
+#endif
+}
+
+#ifndef HAVE_TYPE_RB_IO_MODE_T
+typedef int rb_io_mode_t;
+#endif
struct StringIO {
VALUE string;
+ rb_encoding *enc;
long pos;
long lineno;
- int flags;
+ rb_io_mode_t flags;
int count;
};
-static struct StringIO* strio_alloc _((void));
-static void strio_mark _((struct StringIO *));
-static void strio_free _((struct StringIO *));
-static struct StringIO* check_strio _((VALUE));
-static struct StringIO* get_strio _((VALUE));
-static struct StringIO* readable _((struct StringIO *));
-static struct StringIO* writable _((struct StringIO *));
-static void check_modifiable _((struct StringIO *));
+static struct StringIO *get_strio_for_read(VALUE self);
+static VALUE strio_init(int, VALUE *, struct StringIO *, VALUE);
+static VALUE strio_unget_bytes(struct StringIO *, const char *, long);
+static long strio_write(VALUE self, VALUE str);
+
+#define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type))
+#define error_inval(msg) (rb_syserr_fail(EINVAL, msg))
+#define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : !NIL_P((ptr)->string) ? rb_enc_get((ptr)->string) : NULL)
-#define IS_STRIO(obj) (RDATA(obj)->dmark == (RUBY_DATA_FUNC)strio_mark)
-#define error_inval(msg) (errno = EINVAL, rb_sys_fail(msg))
+static bool
+readonly_string_p(VALUE string)
+{
+ return OBJ_FROZEN_RAW(string);
+}
static struct StringIO *
-strio_alloc()
+strio_alloc(void)
{
struct StringIO *ptr = ALLOC(struct StringIO);
ptr->string = Qnil;
@@ -55,260 +90,408 @@ strio_alloc()
}
static void
-strio_mark(ptr)
- struct StringIO *ptr;
+strio_mark(void *p)
{
- if (ptr) {
- rb_gc_mark(ptr->string);
- }
+ struct StringIO *ptr = p;
+
+ rb_gc_mark(ptr->string);
}
static void
-strio_free(ptr)
- struct StringIO *ptr;
+strio_free(void *p)
{
+ struct StringIO *ptr = p;
if (--ptr->count <= 0) {
xfree(ptr);
}
}
+static size_t
+strio_memsize(const void *p)
+{
+ return sizeof(struct StringIO);
+}
+
+static const rb_data_type_t strio_data_type = {
+ "strio",
+ {
+ strio_mark,
+ strio_free,
+ strio_memsize,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
+};
+
+#define check_strio(self) ((struct StringIO*)rb_check_typeddata((self), &strio_data_type))
+
static struct StringIO*
-check_strio(self)
- VALUE self;
+get_strio(VALUE self)
{
- Check_Type(self, T_DATA);
- if (!IS_STRIO(self)) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected StringIO)",
- rb_class2name(CLASS_OF(self)));
- }
- return DATA_PTR(self);
+ rb_check_frozen(self);
+ return get_strio_for_read(self);
}
static struct StringIO*
-get_strio(self)
- VALUE self;
+get_strio_for_read(VALUE self)
{
struct StringIO *ptr = check_strio(self);
-
if (!ptr) {
rb_raise(rb_eIOError, "uninitialized stream");
}
return ptr;
}
+static VALUE
+enc_subseq(VALUE str, long pos, long len, rb_encoding *enc)
+{
+ str = rb_str_subseq(str, pos, len);
+ rb_enc_associate(str, enc);
+ return str;
+}
+
+static VALUE
+strio_substr(struct StringIO *ptr, long pos, long len, rb_encoding *enc)
+{
+ VALUE str = ptr->string;
+ long rlen = RSTRING_LEN(str) - pos;
+
+ if (len > rlen) len = rlen;
+ if (len < 0) len = 0;
+ if (len == 0) return rb_enc_str_new(0, 0, enc);
+ return enc_subseq(str, pos, len, enc);
+}
+
+static VALUE
+strio_readbuf(struct StringIO *ptr, VALUE str)
+{
+ if (!NIL_P(str)) {
+ StringValue(str);
+ rb_str_modify(str);
+ if (str == ptr->string) {
+ rb_raise(rb_eArgError, "cannot read into the underlying string");
+ }
+ }
+ return str;
+}
+
#define StringIO(obj) get_strio(obj)
+#define StringIOForRead(obj) get_strio_for_read(obj)
+
+#define STRIO_READABLE FL_USER4
+#define STRIO_WRITABLE FL_USER5
+#define STRIO_READWRITE (STRIO_READABLE|STRIO_WRITABLE)
+typedef char strio_flags_check[(STRIO_READABLE/FMODE_READABLE == STRIO_WRITABLE/FMODE_WRITABLE) * 2 - 1];
+#ifndef RB_FL_TEST_RAW
+# define RB_FL_TEST_RAW(obj, bits) (RBASIC(obj)->flags & (bits))
+#endif
+#ifndef RB_FL_SET_RAW
+# define RB_FL_SET_RAW(obj, bits) (RBASIC(obj)->flags |= (bits))
+#endif
+#ifndef RB_FL_UNSET_RAW
+# define RB_FL_UNSET_RAW(obj, bits) (RBASIC(obj)->flags &= ~(bits))
+#endif
-#define CLOSED(ptr) (!((ptr)->flags & FMODE_READWRITE))
-#define READABLE(ptr) ((ptr)->flags & FMODE_READABLE)
-#define WRITABLE(ptr) ((ptr)->flags & FMODE_WRITABLE)
+#define STRIO_MODE_SET_P(strio, mode) \
+ (RB_FL_TEST_RAW(strio, STRIO_##mode) && \
+ ((struct StringIO*)DATA_PTR(strio))->flags & FMODE_##mode)
+#define CLOSED(strio) (!STRIO_MODE_SET_P(strio, READWRITE))
+#define READABLE(strio) STRIO_MODE_SET_P(strio, READABLE)
+#define WRITABLE(strio) STRIO_MODE_SET_P(strio, WRITABLE)
+
+static VALUE sym_exception;
static struct StringIO*
-readable(ptr)
- struct StringIO *ptr;
+readable(VALUE strio)
{
- if (!READABLE(ptr)) {
+ struct StringIO *ptr = StringIOForRead(strio);
+ if (!READABLE(strio)) {
rb_raise(rb_eIOError, "not opened for reading");
}
return ptr;
}
static struct StringIO*
-writable(ptr)
- struct StringIO *ptr;
+writable(VALUE strio)
{
- if (!WRITABLE(ptr)) {
+ struct StringIO *ptr = StringIO(strio);
+ if (!WRITABLE(strio)) {
rb_raise(rb_eIOError, "not opened for writing");
}
- if (!OBJ_TAINTED(ptr->string)) {
- rb_secure(4);
- }
return ptr;
}
static void
-check_modifiable(ptr)
- struct StringIO *ptr;
+check_modifiable(struct StringIO *ptr)
{
- if (OBJ_FROZEN(ptr->string)) {
+ if (NIL_P(ptr->string)) {
+ /* Null device StringIO */
+ }
+ else if (OBJ_FROZEN_RAW(ptr->string)) {
rb_raise(rb_eIOError, "not modifiable string");
}
+ else {
+ rb_str_modify(ptr->string);
+ }
}
-static VALUE strio_s_allocate _((VALUE));
-static VALUE strio_s_open _((int, VALUE *, VALUE));
-static VALUE strio_initialize _((int, VALUE *, VALUE));
-static VALUE strio_finalize _((VALUE));
-static VALUE strio_self _((VALUE));
-static VALUE strio_false _((VALUE));
-static VALUE strio_nil _((VALUE));
-static VALUE strio_0 _((VALUE));
-static VALUE strio_first _((VALUE, VALUE));
-static VALUE strio_unimpl _((int, VALUE *, VALUE));
-static VALUE strio_get_string _((VALUE));
-static VALUE strio_set_string _((VALUE, VALUE));
-static VALUE strio_close _((VALUE));
-static VALUE strio_close_read _((VALUE));
-static VALUE strio_close_write _((VALUE));
-static VALUE strio_closed _((VALUE));
-static VALUE strio_closed_read _((VALUE));
-static VALUE strio_closed_write _((VALUE));
-static VALUE strio_eof _((VALUE));
-static VALUE strio_get_lineno _((VALUE));
-static VALUE strio_set_lineno _((VALUE, VALUE));
-static VALUE strio_get_pos _((VALUE));
-static VALUE strio_set_pos _((VALUE, VALUE));
-static VALUE strio_rewind _((VALUE));
-static VALUE strio_seek _((int, VALUE *, VALUE));
-static VALUE strio_get_sync _((VALUE));
-static VALUE strio_each_byte _((VALUE));
-static VALUE strio_getc _((VALUE));
-static VALUE strio_ungetc _((VALUE, VALUE));
-static VALUE strio_readchar _((VALUE));
-static VALUE strio_getline _((int, VALUE *, struct StringIO *));
-static VALUE strio_gets _((int, VALUE *, VALUE));
-static VALUE strio_readline _((int, VALUE *, VALUE));
-static VALUE strio_each _((int, VALUE *, VALUE));
-static VALUE strio_readlines _((int, VALUE *, VALUE));
-static VALUE strio_write _((VALUE, VALUE));
-static VALUE strio_putc _((VALUE, VALUE));
-static VALUE strio_read _((int, VALUE *, VALUE));
-static VALUE strio_size _((VALUE));
-static VALUE strio_truncate _((VALUE, VALUE));
-void Init_stringio _((void));
-
-/* Boyer-Moore search: copied from regex.c */
-static void bm_init_skip _((long *, const char *, long));
-static long bm_search _((const char *, long, const char *, long, const long *));
+static inline bool
+outside_p(struct StringIO *ptr, long pos)
+{
+ return NIL_P(ptr->string) || pos >= RSTRING_LEN(ptr->string);
+}
-static VALUE
-strio_s_allocate(klass)
- VALUE klass;
+static inline bool
+eos_p(struct StringIO *ptr)
{
- return Data_Wrap_Struct(klass, strio_mark, strio_free, 0);
+ return outside_p(ptr, ptr->pos);
}
-/*
- * call-seq: StringIO.open(string=""[, mode]) {|strio| ...}
- *
- * Equivalent to StringIO.new except that when it is called with a block, it
- * yields with the new instance and closes it, and returns the result which
- * returned from the block.
- */
static VALUE
-strio_s_open(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
+strio_s_allocate(VALUE klass)
{
- VALUE obj = rb_class_new_instance(argc, argv, klass);
- if (!rb_block_given_p()) return obj;
- return rb_ensure(rb_yield, obj, strio_finalize, obj);
+ return TypedData_Wrap_Struct(klass, &strio_data_type, 0);
}
/*
- * call-seq: StringIO.new(string=""[, mode])
+ * call-seq:
+ * StringIO.new(string = '', mode = 'r+') -> new_stringio
+ *
+ * Returns a new \StringIO instance formed from +string+ and +mode+;
+ * the instance should be closed when no longer needed:
+ *
+ * strio = StringIO.new
+ * strio.string # => ""
+ * strio.closed_read? # => false
+ * strio.closed_write? # => false
+ * strio.close
+ *
+ * If +string+ is frozen, the default +mode+ is <tt>'r'</tt>:
*
- * Creates new StringIO instance from with _string_ and _mode_.
+ * strio = StringIO.new('foo'.freeze)
+ * strio.string # => "foo"
+ * strio.closed_read? # => false
+ * strio.closed_write? # => true
+ * strio.close
+ *
+ * Argument +mode+ must be a valid
+ * {Access Mode}[rdoc-ref:File@Access+Modes],
+ * which may be a string or an integer constant:
+ *
+ * StringIO.new('foo', 'w+')
+ * StringIO.new('foo', File::RDONLY)
+ *
+ * Related: StringIO.open
+ * (passes the \StringIO object to the block; closes the object automatically on block exit).
*/
static VALUE
-strio_initialize(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+strio_initialize(int argc, VALUE *argv, VALUE self)
{
struct StringIO *ptr = check_strio(self);
- VALUE string, mode;
- int trunc = Qfalse;
if (!ptr) {
DATA_PTR(self) = ptr = strio_alloc();
}
rb_call_super(0, 0);
- switch (rb_scan_args(argc, argv, "02", &string, &mode)) {
- case 2:
- if (FIXNUM_P(mode)) {
- int flags = FIX2INT(mode);
- ptr->flags = rb_io_modenum_flags(flags);
- trunc = flags & O_TRUNC;
- }
- else {
- const char *m = StringValueCStr(mode);
- ptr->flags = rb_io_mode_flags(m);
- trunc = *m == 'w';
- }
- StringValue(string);
- if ((ptr->flags & FMODE_WRITABLE) && OBJ_FROZEN(string)) {
- errno = EACCES;
- rb_sys_fail(0);
+ return strio_init(argc, argv, ptr, self);
+}
+
+static int
+detect_bom(VALUE str, int *bomlen)
+{
+ const char *p;
+ long len;
+
+ RSTRING_GETMEM(str, p, len);
+ if (len < 1) return 0;
+ switch ((unsigned char)p[0]) {
+ case 0xEF:
+ if (len < 2) break;
+ if ((unsigned char)p[1] == 0xBB && len > 2) {
+ if ((unsigned char)p[2] == 0xBF) {
+ *bomlen = 3;
+ return rb_utf8_encindex();
+ }
}
- if (trunc) {
- rb_str_resize(string, 0);
+ break;
+
+ case 0xFE:
+ if (len < 2) break;
+ if ((unsigned char)p[1] == 0xFF) {
+ *bomlen = 2;
+ return rb_enc_find_index("UTF-16BE");
}
break;
- case 1:
- StringValue(string);
- ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
+
+ case 0xFF:
+ if (len < 2) break;
+ if ((unsigned char)p[1] == 0xFE) {
+ if (len >= 4 && (unsigned char)p[2] == 0 && (unsigned char)p[3] == 0) {
+ *bomlen = 4;
+ return rb_enc_find_index("UTF-32LE");
+ }
+ *bomlen = 2;
+ return rb_enc_find_index("UTF-16LE");
+ }
break;
+
case 0:
- string = rb_str_new("", 0);
- ptr->flags = FMODE_READWRITE;
+ if (len < 4) break;
+ if ((unsigned char)p[1] == 0 && (unsigned char)p[2] == 0xFE && (unsigned char)p[3] == 0xFF) {
+ *bomlen = 4;
+ return rb_enc_find_index("UTF-32BE");
+ }
break;
}
- ptr->string = string;
+ return 0;
+}
+
+static rb_encoding *
+set_encoding_by_bom(struct StringIO *ptr)
+{
+ int bomlen, idx = detect_bom(ptr->string, &bomlen);
+ rb_encoding *extenc = NULL;
+
+ if (idx) {
+ extenc = rb_enc_from_index(idx);
+ ptr->pos = bomlen;
+ if (ptr->flags & FMODE_WRITABLE) {
+ rb_enc_associate_index(ptr->string, idx);
+ }
+ }
+ ptr->enc = extenc;
+ return extenc;
+}
+
+static VALUE
+strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
+{
+ VALUE string, vmode, opt;
+ int oflags;
+ rb_io_enc_t convconfig;
+
+ argc = rb_scan_args(argc, argv, "02:", &string, &vmode, &opt);
+ rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &ptr->flags, &convconfig);
+ if (!NIL_P(string)) {
+ StringValue(string);
+ }
+ else if (!argc) {
+ string = rb_enc_str_new("", 0, rb_default_external_encoding());
+ }
+
+ if (!NIL_P(string) && readonly_string_p(string)) {
+ if (ptr->flags & FMODE_WRITABLE) {
+ rb_syserr_fail(EACCES, 0);
+ }
+ }
+ else {
+ if (NIL_P(vmode)) {
+ ptr->flags |= FMODE_WRITABLE;
+ }
+ }
+ if (!NIL_P(string) && (ptr->flags & FMODE_TRUNC)) {
+ rb_str_resize(string, 0);
+ }
+ RB_OBJ_WRITE(self, &ptr->string, string);
+ if (argc == 1 && !NIL_P(string)) {
+ ptr->enc = rb_enc_get(string);
+ }
+ else {
+ ptr->enc = convconfig.enc;
+ }
+ ptr->pos = 0;
+ ptr->lineno = 0;
+ if (ptr->flags & FMODE_SETENC_BY_BOM) set_encoding_by_bom(ptr);
+ RB_FL_SET_RAW(self, (ptr->flags & FMODE_READWRITE) * (STRIO_READABLE / FMODE_READABLE));
return self;
}
static VALUE
-strio_finalize(self)
- VALUE self;
+strio_finalize(VALUE self)
{
- struct StringIO *ptr = StringIO(self);
- ptr->string = Qnil;
+ struct StringIO *ptr = check_strio(self);
+ if (!ptr) return Qnil;
+ RB_OBJ_WRITE(self, &ptr->string, Qnil);
ptr->flags &= ~FMODE_READWRITE;
return self;
}
/*
- * Returns +false+. Just for compatibility to IO.
+ * call-seq:
+ * StringIO.open(string = '', mode = 'r+') -> new_stringio
+ * StringIO.open(string = '', mode = 'r+') {|strio| ... } -> object
+ *
+ * Creates new \StringIO instance by calling <tt>StringIO.new(string, mode)</tt>.
+ *
+ * With no block given, returns the new instance:
+ *
+ * strio = StringIO.open # => #<StringIO>
+ *
+ * With a block given, calls the block with the new instance
+ * and returns the block's value;
+ * closes the instance on block exit:
+ *
+ * StringIO.open('foo') {|strio| strio.string.upcase } # => "FOO"
+ *
+ * Related: StringIO.new.
+ */
+static VALUE
+strio_s_open(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE obj = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
+ if (!rb_block_given_p()) return obj;
+ return rb_ensure(rb_yield, obj, strio_finalize, obj);
+}
+
+/* :nodoc: */
+static VALUE
+strio_s_new(int argc, VALUE *argv, VALUE klass)
+{
+ if (rb_block_given_p()) {
+ VALUE cname = rb_obj_as_string(klass);
+
+ rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
+ cname, cname);
+ }
+ return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
+}
+
+/*
+ * Returns +false+; for compatibility with IO.
*/
static VALUE
-strio_false(self)
- VALUE self;
+strio_false(VALUE self)
{
- StringIO(self);
+ StringIOForRead(self);
return Qfalse;
}
/*
- * Returns +nil+. Just for compatibility to IO.
+ * Returns +nil+; for compatibility with IO.
*/
static VALUE
-strio_nil(self)
- VALUE self;
+strio_nil(VALUE self)
{
- StringIO(self);
+ StringIOForRead(self);
return Qnil;
}
/*
- * Returns *strio* itself. Just for compatibility to IO.
+ * Returns +self+; for compatibility with IO.
*/
static VALUE
-strio_self(self)
- VALUE self;
+strio_self(VALUE self)
{
- StringIO(self);
+ StringIOForRead(self);
return self;
}
/*
- * Returns 0. Just for compatibility to IO.
+ * Returns 0; for compatibility with IO.
*/
static VALUE
-strio_0(self)
- VALUE self;
+strio_0(VALUE self)
{
- StringIO(self);
+ StringIOForRead(self);
return INT2FIX(0);
}
@@ -316,10 +499,9 @@ strio_0(self)
* Returns the argument unchanged. Just for compatibility to IO.
*/
static VALUE
-strio_first(self, arg)
- VALUE self, arg;
+strio_first(VALUE self, VALUE arg)
{
- StringIO(self);
+ StringIOForRead(self);
return arg;
}
@@ -327,276 +509,381 @@ strio_first(self, arg)
* Raises NotImplementedError.
*/
static VALUE
-strio_unimpl(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+strio_unimpl(int argc, VALUE *argv, VALUE self)
{
- StringIO(self);
+ StringIOForRead(self);
rb_notimplement();
- return Qnil; /* not reached */
+
+ UNREACHABLE;
}
/*
- * call-seq: strio.string -> string
+ * call-seq:
+ * string -> string
*
- * Returns underlying String object, the subject of IO.
+ * Returns underlying string:
+ *
+ * StringIO.open('foo') do |strio|
+ * p strio.string
+ * strio.string = 'bar'
+ * p strio.string
+ * end
+ *
+ * Output:
+ *
+ * "foo"
+ * "bar"
+ *
+ * Related: StringIO#string= (assigns the underlying string).
*/
static VALUE
-strio_get_string(self)
- VALUE self;
+strio_get_string(VALUE self)
{
- return StringIO(self)->string;
+ return StringIOForRead(self)->string;
}
/*
* call-seq:
- * strio.string = string -> string
+ * string = other_string -> other_string
+ *
+ * Replaces the stored string with +other_string+, and sets the position to zero;
+ * returns +other_string+:
+ *
+ * StringIO.open('foo') do |strio|
+ * p strio.string
+ * strio.string = 'bar'
+ * p strio.string
+ * end
+ *
+ * Output:
+ *
+ * "foo"
+ * "bar"
*
- * Changes underlying String object, the subject of IO.
+ * Related: StringIO#string (returns the stored string).
*/
static VALUE
-strio_set_string(self, string)
- VALUE self, string;
+strio_set_string(VALUE self, VALUE string)
{
struct StringIO *ptr = StringIO(self);
- if (!OBJ_TAINTED(self)) rb_secure(4);
+ rb_io_taint_check(self);
ptr->flags &= ~FMODE_READWRITE;
StringValue(string);
- ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
+ ptr->flags = readonly_string_p(string) ? FMODE_READABLE : FMODE_READWRITE;
ptr->pos = 0;
ptr->lineno = 0;
- return ptr->string = string;
+ RB_OBJ_WRITE(self, &ptr->string, string);
+ return string;
}
/*
* call-seq:
- * strio.close -> nil
+ * close -> nil
*
- * Closes strio. The *strio* is unavailable for any further data
- * operations; an +IOError+ is raised if such an attempt is made.
+ * Closes +self+ for both reading and writing; returns +nil+:
+ *
+ * strio = StringIO.new
+ * strio.closed? # => false
+ * strio.close # => nil
+ * strio.closed? # => true
+ * strio.read # Raises IOError: not opened for reading
+ * strio.write # Raises IOError: not opened for writing
+ *
+ * Related: StringIO#close_read, StringIO#close_write, StringIO.closed?.
*/
static VALUE
-strio_close(self)
- VALUE self;
+strio_close(VALUE self)
{
- struct StringIO *ptr = StringIO(self);
- if (CLOSED(ptr)) {
- rb_raise(rb_eIOError, "closed stream");
- }
- ptr->flags &= ~FMODE_READWRITE;
+ StringIO(self);
+ RB_FL_UNSET_RAW(self, STRIO_READWRITE);
return Qnil;
}
/*
* call-seq:
- * strio.close_read -> nil
+ * close_read -> nil
+ *
+ * Closes +self+ for reading;
+ * closed-write setting remains unchanged;
+ * returns +nil+:
*
- * Closes the read end of a StringIO. Will raise an +IOError+ if the
- * *strio* is not readable.
+ * strio = StringIO.new
+ * strio.closed_read? # => false
+ * strio.close_read # => nil
+ * strio.closed_read? # => true
+ * strio.closed_write? # => false
+ * strio.read # Raises IOError: not opened for reading
+ *
+ * Related: StringIO#close, StringIO#close_write.
*/
static VALUE
-strio_close_read(self)
- VALUE self;
+strio_close_read(VALUE self)
{
struct StringIO *ptr = StringIO(self);
- if (!READABLE(ptr)) {
+ if (!(ptr->flags & FMODE_READABLE)) {
rb_raise(rb_eIOError, "closing non-duplex IO for reading");
}
- ptr->flags &= ~FMODE_READABLE;
+ RB_FL_UNSET_RAW(self, STRIO_READABLE);
return Qnil;
}
/*
* call-seq:
- * strio.close_write -> nil
+ * close_write -> nil
+ *
+ * Closes +self+ for writing; closed-read setting remains unchanged; returns +nil+:
*
- * Closes the write end of a StringIO. Will raise an +IOError+ if the
- * *strio* is not writeable.
+ * strio = StringIO.new
+ * strio.closed_write? # => false
+ * strio.close_write # => nil
+ * strio.closed_write? # => true
+ * strio.closed_read? # => false
+ * strio.write('foo') # Raises IOError: not opened for writing
+ *
+ * Related: StringIO#close, StringIO#close_read, StringIO#closed_write?.
*/
static VALUE
-strio_close_write(self)
- VALUE self;
+strio_close_write(VALUE self)
{
struct StringIO *ptr = StringIO(self);
- if (!WRITABLE(ptr)) {
+ if (!(ptr->flags & FMODE_WRITABLE)) {
rb_raise(rb_eIOError, "closing non-duplex IO for writing");
}
- ptr->flags &= ~FMODE_WRITABLE;
+ RB_FL_UNSET_RAW(self, STRIO_WRITABLE);
return Qnil;
}
/*
* call-seq:
- * strio.closed? -> true or false
+ * closed? -> true or false
+ *
+ * Returns whether +self+ is closed for both reading and writing:
*
- * Returns +true+ if *strio* is completely closed, +false+ otherwise.
+ * strio = StringIO.new
+ * strio.closed? # => false # Open for reading and writing.
+ * strio.close_read
+ * strio.closed? # => false # Still open for writing.
+ * strio.close_write
+ * strio.closed? # => true # Now closed for both.
+ *
+ * Related: StringIO.closed_read?, StringIO.closed_write?.
*/
static VALUE
-strio_closed(self)
- VALUE self;
+strio_closed(VALUE self)
{
- struct StringIO *ptr = StringIO(self);
- if (!CLOSED(ptr)) return Qfalse;
+ StringIOForRead(self);
+ if (!CLOSED(self)) return Qfalse;
return Qtrue;
}
/*
* call-seq:
- * strio.closed_read? -> true or false
+ * closed_read? -> true or false
+ *
+ * Returns whether +self+ is closed for reading:
+ *
+ * strio = StringIO.new
+ * strio.closed_read? # => false
+ * strio.close_read
+ * strio.closed_read? # => true
*
- * Returns +true+ if *strio* is not readable, +false+ otherwise.
+ * Related: StringIO#closed?, StringIO#closed_write?, StringIO#close_read.
*/
static VALUE
-strio_closed_read(self)
- VALUE self;
+strio_closed_read(VALUE self)
{
- struct StringIO *ptr = StringIO(self);
- if (READABLE(ptr)) return Qfalse;
+ StringIOForRead(self);
+ if (READABLE(self)) return Qfalse;
return Qtrue;
}
/*
* call-seq:
- * strio.closed_write? -> true or false
+ * closed_write? -> true or false
+ *
+ * Returns whether +self+ is closed for writing:
*
- * Returns +true+ if *strio* is not writable, +false+ otherwise.
+ * strio = StringIO.new
+ * strio.closed_write? # => false
+ * strio.close_write
+ * strio.closed_write? # => true
+ *
+ * Related: StringIO#close_write, StringIO#closed?, StringIO#closed_read?.
*/
static VALUE
-strio_closed_write(self)
- VALUE self;
+strio_closed_write(VALUE self)
{
- struct StringIO *ptr = StringIO(self);
- if (WRITABLE(ptr)) return Qfalse;
+ StringIOForRead(self);
+ if (WRITABLE(self)) return Qfalse;
return Qtrue;
}
+static struct StringIO *
+strio_to_read(VALUE self)
+{
+ struct StringIO *ptr = readable(self);
+ if (eos_p(ptr)) return NULL;
+ return ptr;
+}
+
/*
* call-seq:
- * strio.eof -> true or false
- * strio.eof? -> true or false
+ * eof? -> true or false
+ *
+ * Returns whether +self+ is positioned at end-of-stream:
*
- * Returns true if *strio* is at end of file. The stringio must be
- * opened for reading or an +IOError+ will be raised.
+ * strio = StringIO.new('foo')
+ * strio.pos # => 0
+ * strio.eof? # => false
+ * strio.read # => "foo"
+ * strio.pos # => 3
+ * strio.eof? # => true
+ * strio.close_read
+ * strio.eof? # Raises IOError: not opened for reading
+ *
+ * Related: StringIO#pos.
*/
static VALUE
-strio_eof(self)
- VALUE self;
+strio_eof(VALUE self)
{
- struct StringIO *ptr = readable(StringIO(self));
- if (ptr->pos < RSTRING(ptr->string)->len) return Qfalse;
+ if (strio_to_read(self)) return Qfalse;
return Qtrue;
}
/* :nodoc: */
static VALUE
-strio_copy(copy, orig)
- VALUE copy, orig;
+strio_copy(VALUE copy, VALUE orig)
{
- struct StringIO *ptr;
+ struct StringIO *ptr, *old_ptr;
+ VALUE old_string = Qundef;
orig = rb_convert_type(orig, T_DATA, "StringIO", "to_strio");
if (copy == orig) return copy;
- ptr = StringIO(orig);
- if (check_strio(copy)) {
- strio_free(DATA_PTR(copy));
+ ptr = StringIOForRead(orig);
+ old_ptr = check_strio(copy);
+ if (old_ptr) {
+ old_string = old_ptr->string;
+ strio_free(old_ptr);
}
DATA_PTR(copy) = ptr;
- OBJ_INFECT(copy, orig);
+ RB_OBJ_WRITTEN(copy, old_string, ptr->string);
+ RB_FL_UNSET_RAW(copy, STRIO_READWRITE);
+ RB_FL_SET_RAW(copy, RB_FL_TEST_RAW(orig, STRIO_READWRITE));
++ptr->count;
return copy;
}
/*
* call-seq:
- * strio.lineno -> integer
+ * lineno -> current_line_number
*
- * Returns the current line number in *strio*. The stringio must be
- * opened for reading. +lineno+ counts the number of times +gets+ is
- * called, rather than the number of newlines encountered. The two
- * values will differ if +gets+ is called with a separator other than
- * newline. See also the <code>$.</code> variable.
+ * Returns the current line number in +self+;
+ * see {Line Number}[rdoc-ref:StringIO@Line+Number].
*/
static VALUE
-strio_get_lineno(self)
- VALUE self;
+strio_get_lineno(VALUE self)
{
- return LONG2NUM(StringIO(self)->lineno);
+ return LONG2NUM(StringIOForRead(self)->lineno);
}
/*
* call-seq:
- * strio.lineno = integer -> integer
+ * lineno = new_line_number -> new_line_number
*
- * Manually sets the current line number to the given value.
- * <code>$.</code> is updated only on the next read.
+ * Sets the current line number in +self+ to the given +new_line_number+;
+ * see {Line Number}[rdoc-ref:StringIO@Line+Number].
*/
static VALUE
-strio_set_lineno(self, lineno)
- VALUE self, lineno;
+strio_set_lineno(VALUE self, VALUE lineno)
{
StringIO(self)->lineno = NUM2LONG(lineno);
return lineno;
}
-/* call-seq: strio.binmode -> true */
-#define strio_binmode strio_self
+/*
+ * call-seq:
+ * binmode -> self
+ *
+ * Sets the data mode in +self+ to binary mode;
+ * see {Data Mode}[rdoc-ref:StringIO@Data+Mode].
+ *
+ */
+static VALUE
+strio_binmode(VALUE self)
+{
+ struct StringIO *ptr = StringIO(self);
+ rb_encoding *enc = rb_ascii8bit_encoding();
+
+ ptr->enc = enc;
+ if (WRITABLE(self)) {
+ rb_enc_associate(ptr->string, enc);
+ }
+ return self;
+}
-/* call-seq: strio.fcntl */
#define strio_fcntl strio_unimpl
-/* call-seq: strio.flush -> strio */
#define strio_flush strio_self
-/* call-seq: strio.fsync -> 0 */
#define strio_fsync strio_0
/*
* call-seq:
- * strio.reopen(other_StrIO) -> strio
- * strio.reopen(string, mode) -> strio
+ * reopen(other, mode = 'r+') -> self
+ *
+ * Reinitializes the stream with the given +other+ (string or StringIO) and +mode+;
+ * see IO.new:
+ *
+ * StringIO.open('foo') do |strio|
+ * p strio.string
+ * strio.reopen('bar')
+ * p strio.string
+ * other_strio = StringIO.new('baz')
+ * strio.reopen(other_strio)
+ * p strio.string
+ * other_strio.close
+ * end
+ *
+ * Output:
+ *
+ * "foo"
+ * "bar"
+ * "baz"
*
- * Reinitializes *strio* with the given <i>other_StrIO</i> or _string_
- * and _mode_ (see StringIO#new).
*/
static VALUE
-strio_reopen(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+strio_reopen(int argc, VALUE *argv, VALUE self)
{
- if (!OBJ_TAINTED(self)) rb_secure(4);
- if (argc == 1 && TYPE(*argv) != T_STRING) {
+ rb_io_taint_check(self);
+ if (argc == 1 && !RB_TYPE_P(*argv, T_STRING)) {
return strio_copy(self, *argv);
}
- return strio_initialize(argc, argv, self);
+ return strio_init(argc, argv, StringIO(self), self);
}
/*
* call-seq:
- * strio.pos -> integer
- * strio.tell -> integer
+ * pos -> stream_position
*
- * Returns the current offset (in bytes) of *strio*.
+ * Returns the current position (in bytes);
+ * see {Position}[rdoc-ref:StringIO@Position].
*/
static VALUE
-strio_get_pos(self)
- VALUE self;
+strio_get_pos(VALUE self)
{
- return LONG2NUM(StringIO(self)->pos);
+ return LONG2NUM(StringIOForRead(self)->pos);
}
/*
* call-seq:
- * strio.pos = integer -> integer
+ * pos = new_position -> new_position
*
- * Seeks to the given position (in bytes) in *strio*.
+ * Sets the current position (in bytes);
+ * see {Position}[rdoc-ref:StringIO@Position].
*/
static VALUE
-strio_set_pos(self, pos)
- VALUE self;
- VALUE pos;
+strio_set_pos(VALUE self, VALUE pos)
{
struct StringIO *ptr = StringIO(self);
long p = NUM2LONG(pos);
@@ -604,195 +891,367 @@ strio_set_pos(self, pos)
error_inval(0);
}
ptr->pos = p;
- ptr->flags &= ~STRIO_EOF;
return pos;
}
/*
* call-seq:
- * strio.rewind -> 0
+ * rewind -> 0
*
- * Positions *strio* to the beginning of input, resetting
- * +lineno+ to zero.
+ * Sets the current position and line number to zero;
+ * see {Position}[rdoc-ref:IO@Position]
+ * and {Line Number}[rdoc-ref:IO@Line+Number].
*/
static VALUE
-strio_rewind(self)
- VALUE self;
+strio_rewind(VALUE self)
{
struct StringIO *ptr = StringIO(self);
ptr->pos = 0;
ptr->lineno = 0;
- ptr->flags &= ~STRIO_EOF;
return INT2FIX(0);
}
/*
* call-seq:
- * strio.seek(amount, whence=SEEK_SET) -> 0
+ * seek(offset, whence = SEEK_SET) -> 0
*
- * Seeks to a given offset _amount_ in the stream according to
- * the value of _whence_ (see IO#seek).
+ * Sets the position to the given integer +offset+ (in bytes),
+ * with respect to a given constant +whence+;
+ * see {IO#seek}[rdoc-ref:IO#seek].
*/
static VALUE
-strio_seek(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+strio_seek(int argc, VALUE *argv, VALUE self)
{
VALUE whence;
struct StringIO *ptr = StringIO(self);
- long offset;
+ long amount, offset;
rb_scan_args(argc, argv, "11", NULL, &whence);
- offset = NUM2LONG(argv[0]);
+ amount = NUM2LONG(argv[0]);
+ if (CLOSED(self)) {
+ rb_raise(rb_eIOError, "closed stream");
+ }
switch (NIL_P(whence) ? 0 : NUM2LONG(whence)) {
case 0:
+ offset = 0;
break;
case 1:
- offset += ptr->pos;
+ offset = ptr->pos;
break;
case 2:
- offset += RSTRING(ptr->string)->len;
+ if (NIL_P(ptr->string)) {
+ offset = 0;
+ } else {
+ offset = RSTRING_LEN(ptr->string);
+ }
break;
default:
- rb_raise(rb_eArgError, "invalid whence %ld", NUM2LONG(whence));
+ error_inval("invalid whence");
}
- if (offset < 0) {
+ if (amount > LONG_MAX - offset || amount + offset < 0) {
error_inval(0);
}
- ptr->pos = offset;
- ptr->flags &= ~STRIO_EOF;
+ ptr->pos = amount + offset;
return INT2FIX(0);
}
/*
* call-seq:
- * strio.sync -> true
+ * sync -> true
*
- * Returns +true+ always.
+ * Returns +true+; implemented only for compatibility with other stream classes.
*/
static VALUE
-strio_get_sync(self)
- VALUE self;
+strio_get_sync(VALUE self)
{
- StringIO(self);
+ StringIOForRead(self);
return Qtrue;
}
-/* call-seq: strio.sync = boolean -> boolean */
#define strio_set_sync strio_first
#define strio_tell strio_get_pos
/*
* call-seq:
- * strio.each_byte {|byte| block } -> strio
+ * each_byte {|byte| ... } -> self
*
- * See IO#each_byte.
+ * :include: stringio/each_byte.rdoc
+ *
+ * Related: StringIO#each_char, StringIO#each_codepoint, StringIO#each_line.
*/
static VALUE
-strio_each_byte(self)
- VALUE self;
+strio_each_byte(VALUE self)
{
- struct StringIO *ptr = readable(StringIO(self));
- while (ptr->pos < RSTRING(ptr->string)->len) {
- char c = RSTRING(ptr->string)->ptr[ptr->pos++];
+ struct StringIO *ptr;
+
+ RETURN_ENUMERATOR(self, 0, 0);
+
+ while ((ptr = strio_to_read(self)) != NULL) {
+ char c = RSTRING_PTR(ptr->string)[ptr->pos++];
rb_yield(CHR2FIX(c));
}
- return Qnil;
+ return self;
}
/*
* call-seq:
- * strio.getc -> fixnum or nil
+ * getc -> character, byte, or nil
+ *
+ * :include: stringio/getc.rdoc
*
- * See IO#getc.
*/
static VALUE
-strio_getc(self)
- VALUE self;
+strio_getc(VALUE self)
{
- struct StringIO *ptr = readable(StringIO(self));
+ struct StringIO *ptr = readable(self);
+ rb_encoding *enc = get_enc(ptr);
+ VALUE str = ptr->string;
+ long pos = ptr->pos;
+ int len;
+ char *p;
+
+ if (eos_p(ptr)) {
+ return Qnil;
+ }
+ p = RSTRING_PTR(str)+pos;
+ len = rb_enc_mbclen(p, RSTRING_END(str), enc);
+ ptr->pos += len;
+ return enc_subseq(str, pos, len, enc);
+}
+
+/*
+ * call-seq:
+ * getbyte -> integer or nil
+ *
+ * :include: stringio/getbyte.rdoc
+ *
+ */
+static VALUE
+strio_getbyte(VALUE self)
+{
+ struct StringIO *ptr = readable(self);
int c;
- if (ptr->pos >= RSTRING(ptr->string)->len) {
- ptr->flags |= STRIO_EOF;
+ if (eos_p(ptr)) {
return Qnil;
}
- c = RSTRING(ptr->string)->ptr[ptr->pos++];
+ c = RSTRING_PTR(ptr->string)[ptr->pos++];
return CHR2FIX(c);
}
static void
-strio_extend(ptr, pos, len)
- struct StringIO *ptr;
- long pos, len;
+strio_extend(struct StringIO *ptr, long pos, long len)
{
long olen;
+ if (len > LONG_MAX - pos)
+ rb_raise(rb_eArgError, "string size too big");
+
check_modifiable(ptr);
- olen = RSTRING(ptr->string)->len;
+ olen = RSTRING_LEN(ptr->string);
if (pos + len > olen) {
rb_str_resize(ptr->string, pos + len);
if (pos > olen)
- MEMZERO(RSTRING(ptr->string)->ptr + olen, char, pos - olen);
+ MEMZERO(RSTRING_PTR(ptr->string) + olen, char, pos - olen);
+ }
+}
+
+static void
+strio_unget_string(struct StringIO *ptr, VALUE c)
+{
+ const char *cp = NULL;
+ long cl = RSTRING_LEN(c);
+ if (cl > 0) {
+ if (c != ptr->string) cp = RSTRING_PTR(c);
+ strio_unget_bytes(ptr, cp, cl);
+ RB_GC_GUARD(c);
+ }
+}
+
+/*
+ * call-seq:
+ * ungetc(character) -> nil
+ *
+ * Pushes back ("unshifts") a character or integer onto the stream;
+ * see {Character IO}[rdoc-ref:IO@Character+IO].
+ */
+static VALUE
+strio_ungetc(VALUE self, VALUE c)
+{
+ struct StringIO *ptr = readable(self);
+ rb_encoding *enc, *enc2;
+
+ check_modifiable(ptr);
+ if (NIL_P(ptr->string)) return Qnil;
+ if (NIL_P(c)) return Qnil;
+ if (RB_INTEGER_TYPE_P(c)) {
+ int len, cc = NUM2INT(c);
+ char buf[16];
+
+ enc = rb_enc_get(ptr->string);
+ len = rb_enc_codelen(cc, enc);
+ if (len <= 0) {
+ rb_enc_uint_chr(cc, enc); /* to raise an exception */
+ UNREACHABLE;
+ }
+ rb_enc_mbcput(cc, buf, enc);
+ return strio_unget_bytes(ptr, buf, len);
}
else {
- rb_str_modify(ptr->string);
+ StringValue(c);
+ if (RSTRING_LEN(c) == 0) return Qnil;
+ enc = rb_enc_get(ptr->string);
+ enc2 = rb_enc_get(c);
+ if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
+ c = rb_str_conv_enc(c, enc2, enc);
+ }
+ strio_unget_string(ptr, c);
+ return Qnil;
}
}
/*
* call-seq:
- * strio.ungetc(integer) -> nil
+ * ungetbyte(byte) -> nil
*
- * Pushes back one character (passed as a parameter) onto *strio*
- * such that a subsequent buffered read will return it. Pushing back
- * behind the beginning of the buffer string is not possible. Nothing
- * will be done if such an attempt is made.
- * In other case, there is no limitation for multiple pushbacks.
+ * Pushes back ("unshifts") an 8-bit byte onto the stream;
+ * see {Byte IO}[rdoc-ref:IO@Byte+IO].
*/
static VALUE
-strio_ungetc(self, ch)
- VALUE self, ch;
-{
- struct StringIO *ptr = readable(StringIO(self));
- int cc = NUM2INT(ch);
- long len, pos = ptr->pos;
-
- if (cc != EOF && pos > 0) {
- if ((len = RSTRING(ptr->string)->len) < pos-- ||
- (unsigned char)RSTRING(ptr->string)->ptr[pos] !=
- (unsigned char)cc) {
- strio_extend(ptr, pos, 1);
- RSTRING(ptr->string)->ptr[pos] = cc;
- OBJ_INFECT(ptr->string, self);
+strio_ungetbyte(VALUE self, VALUE c)
+{
+ struct StringIO *ptr = readable(self);
+
+ check_modifiable(ptr);
+ if (NIL_P(ptr->string)) return Qnil;
+ if (NIL_P(c)) return Qnil;
+ if (RB_INTEGER_TYPE_P(c)) {
+ /* rb_int_and() not visible from exts */
+ VALUE v = rb_funcall(c, '&', 1, INT2FIX(0xff));
+ const char cc = NUM2INT(v) & 0xFF;
+ strio_unget_bytes(ptr, &cc, 1);
+ }
+ else {
+ StringValue(c);
+ strio_unget_string(ptr, c);
+ }
+ return Qnil;
+}
+
+static VALUE
+strio_unget_bytes(struct StringIO *ptr, const char *cp, long cl)
+{
+ long pos = ptr->pos, len, rest;
+ VALUE str = ptr->string;
+ char *s;
+
+ len = RSTRING_LEN(str);
+ rest = pos - len;
+ if (cl > pos) {
+ long ex = cl - (rest < 0 ? pos : len);
+ rb_str_modify_expand(str, ex);
+ rb_str_set_len(str, len + ex);
+ s = RSTRING_PTR(str);
+ if (rest < 0) memmove(s + cl, s + pos, -rest);
+ pos = 0;
+ }
+ else {
+ if (rest > 0) {
+ rb_str_modify_expand(str, rest);
+ rb_str_set_len(str, len + rest);
}
- --ptr->pos;
- ptr->flags &= ~STRIO_EOF;
+ s = RSTRING_PTR(str);
+ if (rest > cl) memset(s + len, 0, rest - cl);
+ pos -= cl;
}
+ memcpy(s + pos, (cp ? cp : s), cl);
+ ptr->pos = pos;
return Qnil;
}
/*
* call-seq:
- * strio.readchar -> fixnum
+ * readchar -> string
+ *
+ * Like +getc+, but raises an exception if already at end-of-stream;
+ * see {Character IO}[rdoc-ref:IO@Character+IO].
+ */
+static VALUE
+strio_readchar(VALUE self)
+{
+ VALUE c = rb_funcallv(self, rb_intern("getc"), 0, 0);
+ if (NIL_P(c)) rb_eof_error();
+ return c;
+}
+
+/*
+ * call-seq:
+ * readbyte -> byte
*
- * See IO#readchar.
+ * Like +getbyte+, but raises an exception if already at end-of-stream;
+ * see {Byte IO}[rdoc-ref:IO@Byte+IO].
*/
static VALUE
-strio_readchar(self)
- VALUE self;
+strio_readbyte(VALUE self)
{
- VALUE c = strio_getc(self);
+ VALUE c = rb_funcallv(self, rb_intern("getbyte"), 0, 0);
if (NIL_P(c)) rb_eof_error();
return c;
}
+/*
+ * call-seq:
+ * each_char {|char| ... } -> self
+ *
+ * :include: stringio/each_char.rdoc
+ *
+ * Related: StringIO#each_byte, StringIO#each_codepoint, StringIO#each_line.
+ */
+static VALUE
+strio_each_char(VALUE self)
+{
+ VALUE c;
+
+ RETURN_ENUMERATOR(self, 0, 0);
+
+ while (!NIL_P(c = strio_getc(self))) {
+ rb_yield(c);
+ }
+ return self;
+}
+
+/*
+ * call-seq:
+ * each_codepoint {|codepoint| ... } -> self
+ *
+ * :include: stringio/each_codepoint.rdoc
+ *
+ * Related: StringIO#each_byte, StringIO#each_char, StringIO#each_line.
+ */
+static VALUE
+strio_each_codepoint(VALUE self)
+{
+ struct StringIO *ptr;
+ rb_encoding *enc;
+ unsigned int c;
+ int n;
+
+ RETURN_ENUMERATOR(self, 0, 0);
+
+ ptr = readable(self);
+ enc = get_enc(ptr);
+ while ((ptr = strio_to_read(self)) != NULL) {
+ c = rb_enc_codepoint_len(RSTRING_PTR(ptr->string)+ptr->pos,
+ RSTRING_END(ptr->string), &n, enc);
+ ptr->pos += n;
+ rb_yield(UINT2NUM(c));
+ }
+ return self;
+}
+
+/* Boyer-Moore search: copied from regex.c */
static void
-bm_init_skip(skip, pat, m)
- long *skip;
- const char *pat;
- long m;
+bm_init_skip(long *skip, const char *pat, long m)
{
int c;
@@ -805,12 +1264,7 @@ bm_init_skip(skip, pat, m)
}
static long
-bm_search(little, llen, big, blen, skip)
- const char *little;
- long llen;
- const char *big;
- long blen;
- const long *skip;
+bm_search(const char *little, long llen, const char *big, long blen, const long *skip)
{
long i, j, k;
@@ -828,135 +1282,246 @@ bm_search(little, llen, big, blen, skip)
return -1;
}
-static VALUE
-strio_getline(argc, argv, ptr)
- int argc;
- VALUE *argv;
- struct StringIO *ptr;
+struct getline_arg {
+ VALUE rs;
+ long limit;
+ unsigned int chomp: 1;
+};
+
+static struct getline_arg *
+prepare_getline_args(struct StringIO *ptr, struct getline_arg *arg, int argc, VALUE *argv)
{
- const char *s, *e, *p;
- long n;
- VALUE str;
+ VALUE rs, lim, opts;
+ long limit = -1;
+ int respect_chomp;
+
+ argc = rb_scan_args(argc, argv, "02:", &rs, &lim, &opts);
+ respect_chomp = argc == 0 || !NIL_P(rs);
+ switch (argc) {
+ case 0:
+ rs = rb_rs;
+ break;
- if (argc == 0) {
- str = rb_rs;
+ case 1:
+ if (!NIL_P(rs) && !RB_TYPE_P(rs, T_STRING)) {
+ VALUE tmp = rb_check_string_type(rs);
+ if (NIL_P(tmp)) {
+ limit = NUM2LONG(rs);
+ rs = rb_rs;
+ }
+ else {
+ rs = tmp;
+ }
+ }
+ break;
+
+ case 2:
+ if (!NIL_P(rs)) StringValue(rs);
+ if (!NIL_P(lim)) limit = NUM2LONG(lim);
+ break;
}
- else {
- rb_scan_args(argc, argv, "1", &str);
- if (!NIL_P(str)) StringValue(str);
+ if (!NIL_P(ptr->string) && !NIL_P(rs)) {
+ rb_encoding *enc_rs, *enc_io;
+ enc_rs = rb_enc_get(rs);
+ enc_io = get_enc(ptr);
+ if (enc_rs != enc_io &&
+ (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
+ (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
+ if (rs == rb_rs) {
+ rs = rb_enc_str_new(0, 0, enc_io);
+ rb_str_buf_cat_ascii(rs, "\n");
+ rs = rs;
+ }
+ else {
+ rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
+ rb_enc_name(enc_io),
+ rb_enc_name(enc_rs));
+ }
+ }
+ }
+ arg->rs = rs;
+ arg->limit = limit;
+ arg->chomp = 0;
+ if (!NIL_P(opts)) {
+ static ID keywords[1];
+ VALUE vchomp;
+ if (!keywords[0]) {
+ keywords[0] = rb_intern_const("chomp");
+ }
+ rb_get_kwargs(opts, keywords, 0, 1, &vchomp);
+ if (respect_chomp) {
+ arg->chomp = (vchomp != Qundef) && RTEST(vchomp);
+ }
+ }
+ return arg;
+}
+
+static inline int
+chomp_newline_width(const char *s, const char *e)
+{
+ if (e > s && *--e == '\n') {
+ if (e > s && *--e == '\r') return 2;
+ return 1;
}
+ return 0;
+}
+
+static VALUE
+strio_getline(struct getline_arg *arg, struct StringIO *ptr)
+{
+ const char *s, *e, *p;
+ long n, limit = arg->limit;
+ VALUE str = arg->rs;
+ long w = 0;
+ rb_encoding *enc = get_enc(ptr);
- if (ptr->pos >= (n = RSTRING(ptr->string)->len)) {
- ptr->flags |= STRIO_EOF;
+ if (NIL_P(ptr->string) || ptr->pos >= (n = RSTRING_LEN(ptr->string))) {
return Qnil;
}
- s = RSTRING(ptr->string)->ptr;
- e = s + RSTRING(ptr->string)->len;
+ s = RSTRING_PTR(ptr->string);
+ e = s + RSTRING_LEN(ptr->string);
s += ptr->pos;
+ if (limit > 0 && (size_t)limit < (size_t)(e - s)) {
+ e = rb_enc_right_char_head(s, s + limit, e, get_enc(ptr));
+ }
if (NIL_P(str)) {
- str = rb_str_substr(ptr->string, ptr->pos, e - s);
+ if (arg->chomp) {
+ w = chomp_newline_width(s, e);
+ }
+ str = strio_substr(ptr, ptr->pos, e - s - w, enc);
}
- else if ((n = RSTRING(str)->len) == 0) {
+ else if ((n = RSTRING_LEN(str)) == 0) {
+ const char *paragraph_end = NULL;
p = s;
- while (*p == '\n') {
+ while (p[(p + 1 < e) && (*p == '\r') && 0] == '\n') {
+ p += *p == '\r';
if (++p == e) {
- ptr->flags |= STRIO_EOF;
return Qnil;
}
}
s = p;
while ((p = memchr(p, '\n', e - p)) && (p != e)) {
- if (*++p == '\n') {
- e = p;
- break;
+ p++;
+ if (!((p < e && *p == '\n') ||
+ (p + 1 < e && *p == '\r' && *(p+1) == '\n'))) {
+ continue;
+ }
+ paragraph_end = p - ((*(p-2) == '\r') ? 2 : 1);
+ while ((p < e && *p == '\n') ||
+ (p + 1 < e && *p == '\r' && *(p+1) == '\n')) {
+ p += (*p == '\r') ? 2 : 1;
}
+ e = p;
+ break;
+ }
+ if (arg->chomp && paragraph_end) {
+ w = e - paragraph_end;
}
- str = rb_str_substr(ptr->string, s - RSTRING(ptr->string)->ptr, e - s);
+ str = strio_substr(ptr, s - RSTRING_PTR(ptr->string), e - s - w, enc);
}
else if (n == 1) {
- if ((p = memchr(s, RSTRING(str)->ptr[0], e - s)) != 0) {
+ if ((p = memchr(s, RSTRING_PTR(str)[0], e - s)) != 0) {
e = p + 1;
+ w = (arg->chomp ? (p > s && *(p-1) == '\r') + 1 : 0);
}
- str = rb_str_substr(ptr->string, ptr->pos, e - s);
+ str = strio_substr(ptr, ptr->pos, e - s - w, enc);
}
else {
- if (n < e - s) {
- if (e - s < 1024) {
+ if (n < e - s + arg->chomp) {
+ /* unless chomping, RS at the end does not matter */
+ if (e - s < 1024 || n == e - s) {
for (p = s; p + n <= e; ++p) {
- if (MEMCMP(p, RSTRING(str)->ptr, char, n) == 0) {
+ if (MEMCMP(p, RSTRING_PTR(str), char, n) == 0) {
e = p + n;
+ w = (arg->chomp ? n : 0);
break;
}
}
}
else {
long skip[1 << CHAR_BIT], pos;
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
bm_init_skip(skip, p, n);
if ((pos = bm_search(p, n, s, e - s, skip)) >= 0) {
- e = s + pos + n;
+ e = s + pos + (arg->chomp ? 0 : n);
}
}
}
- str = rb_str_substr(ptr->string, ptr->pos, e - s);
+ str = strio_substr(ptr, ptr->pos, e - s - w, enc);
}
- ptr->pos = e - RSTRING(ptr->string)->ptr;
+ ptr->pos = e - RSTRING_PTR(ptr->string);
ptr->lineno++;
return str;
}
/*
* call-seq:
- * strio.gets(sep_string=$/) -> string or nil
+ * gets(sep = $/, chomp: false) -> string or nil
+ * gets(limit, chomp: false) -> string or nil
+ * gets(sep, limit, chomp: false) -> string or nil
+ *
+ * :include: stringio/gets.rdoc
*
- * See IO#gets.
*/
static VALUE
-strio_gets(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+strio_gets(int argc, VALUE *argv, VALUE self)
{
- VALUE str = strio_getline(argc, argv, readable(StringIO(self)));
+ struct StringIO *ptr = readable(self);
+ struct getline_arg arg;
+ VALUE str;
+
+ if (prepare_getline_args(ptr, &arg, argc, argv)->limit == 0) {
+ if (NIL_P(ptr->string)) return Qnil;
+ return rb_enc_str_new(0, 0, get_enc(ptr));
+ }
+ str = strio_getline(&arg, ptr);
rb_lastline_set(str);
return str;
}
/*
* call-seq:
- * strio.readline(sep_string=$/) -> string
+ * readline(sep = $/, chomp: false) -> string
+ * readline(limit, chomp: false) -> string
+ * readline(sep, limit, chomp: false) -> string
*
- * See IO#readline.
+ * Reads a line as with IO#gets, but raises EOFError if already at end-of-file;
+ * see {Line IO}[rdoc-ref:IO@Line+IO].
*/
static VALUE
-strio_readline(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+strio_readline(int argc, VALUE *argv, VALUE self)
{
- VALUE line = strio_getline(argc, argv, readable(StringIO(self)));
+ VALUE line = rb_funcallv_kw(self, rb_intern("gets"), argc, argv, RB_PASS_CALLED_KEYWORDS);
if (NIL_P(line)) rb_eof_error();
return line;
}
/*
+ * :markup: markdown
+ *
* call-seq:
- * strio.each(sep_string=$/) {|line| block } -> strio
- * strio.each_line(sep_string=$/) {|line| block } -> strio
+ * each_line(sep = $/, chomp: false) {|line| ... } -> self
+ * each_line(limit, chomp: false) {|line| ... } -> self
+ * each_line(sep, limit, chomp: false) {|line| ... } -> self
+ *
+ * :include: stringio/each_line.md
*
- * See IO#each.
*/
static VALUE
-strio_each(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+strio_each(int argc, VALUE *argv, VALUE self)
{
- struct StringIO *ptr = StringIO(self);
VALUE line;
+ struct StringIO *ptr = readable(self);
+ struct getline_arg arg;
+
+ RETURN_ENUMERATOR(self, argc, argv);
- while (!NIL_P(line = strio_getline(argc, argv, readable(ptr)))) {
+ if (prepare_getline_args(ptr, &arg, argc, argv)->limit == 0) {
+ rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
+ }
+
+ while (!NIL_P(line = strio_getline(&arg, ptr))) {
rb_yield(line);
}
return self;
@@ -964,19 +1529,25 @@ strio_each(argc, argv, self)
/*
* call-seq:
- * strio.readlines(sep_string=$/) -> array
+ * strio.readlines(sep=$/, chomp: false) -> array
+ * strio.readlines(limit, chomp: false) -> array
+ * strio.readlines(sep, limit, chomp: false) -> array
*
* See IO#readlines.
*/
static VALUE
-strio_readlines(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+strio_readlines(int argc, VALUE *argv, VALUE self)
{
- struct StringIO *ptr = StringIO(self);
- VALUE ary = rb_ary_new(), line;
- while (!NIL_P(line = strio_getline(argc, argv, readable(ptr)))) {
+ VALUE ary, line;
+ struct StringIO *ptr = readable(self);
+ struct getline_arg arg;
+
+ if (prepare_getline_args(ptr, &arg, argc, argv)->limit == 0) {
+ rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
+ }
+
+ ary = rb_ary_new();
+ while (!NIL_P(line = strio_getline(&arg, ptr))) {
rb_ary_push(ary, line);
}
return ary;
@@ -984,40 +1555,69 @@ strio_readlines(argc, argv, self)
/*
* call-seq:
- * strio.write(string) -> integer
- * strio.syswrite(string) -> integer
+ * strio.write(string, ...) -> integer
+ * strio.syswrite(string) -> integer
*
- * Appends the given string to the underlying buffer string of *strio*.
+ * Appends the given string to the underlying buffer string.
* The stream must be opened for writing. If the argument is not a
* string, it will be converted to a string using <code>to_s</code>.
* Returns the number of bytes written. See IO#write.
*/
static VALUE
-strio_write(self, str)
- VALUE self, str;
+strio_write_m(int argc, VALUE *argv, VALUE self)
+{
+ long len = 0;
+ while (argc-- > 0) {
+ /* StringIO can't exceed long limit */
+ len += strio_write(self, *argv++);
+ }
+ return LONG2NUM(len);
+}
+
+static long
+strio_write(VALUE self, VALUE str)
{
- struct StringIO *ptr = writable(StringIO(self));
+ struct StringIO *ptr = writable(self);
long len, olen;
+ rb_encoding *enc, *enc2;
+ rb_encoding *const ascii8bit = rb_ascii8bit_encoding();
+ rb_encoding *usascii = 0;
- if (TYPE(str) != T_STRING)
+ if (!RB_TYPE_P(str, T_STRING))
str = rb_obj_as_string(str);
- len = RSTRING(str)->len;
- if (!len) return INT2FIX(0);
+ enc = get_enc(ptr);
+ if (!enc) return 0;
+ enc2 = rb_enc_get(str);
+ if (enc != enc2 && enc != ascii8bit && enc != (usascii = rb_usascii_encoding())) {
+ VALUE converted = rb_str_conv_enc(str, enc2, enc);
+ if (converted == str && enc2 != ascii8bit && enc2 != usascii) { /* conversion failed */
+ rb_enc_check(rb_enc_from_encoding(enc), str);
+ }
+ str = converted;
+ }
+ len = RSTRING_LEN(str);
+ if (len == 0) return 0;
check_modifiable(ptr);
- olen = RSTRING(ptr->string)->len;
+ olen = RSTRING_LEN(ptr->string);
if (ptr->flags & FMODE_APPEND) {
ptr->pos = olen;
}
if (ptr->pos == olen) {
- rb_str_cat(ptr->string, RSTRING(str)->ptr, len);
+ if (enc == ascii8bit || enc2 == ascii8bit) {
+ rb_enc_str_buf_cat(ptr->string, RSTRING_PTR(str), len, enc);
+ }
+ else {
+ rb_str_buf_append(ptr->string, str);
+ }
}
else {
strio_extend(ptr, ptr->pos, len);
- rb_str_update(ptr->string, ptr->pos, len, str);
+ rb_str_modify(ptr->string);
+ memmove(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_PTR(str), len);
}
- OBJ_INFECT(ptr->string, self);
+ RB_GC_GUARD(str);
ptr->pos += len;
- return LONG2NUM(len);
+ return len;
}
/*
@@ -1047,26 +1647,28 @@ strio_write(self, str)
/*
* call-seq:
- * strio.putc(obj) -> obj
+ * putc(object) -> object
+ *
+ * :include: stringio/putc.rdoc
*
- * See IO#putc.
*/
static VALUE
-strio_putc(self, ch)
- VALUE self, ch;
+strio_putc(VALUE self, VALUE ch)
{
- struct StringIO *ptr = writable(StringIO(self));
- int c = NUM2CHR(ch);
- long olen;
+ struct StringIO *ptr = writable(self);
+ VALUE str;
check_modifiable(ptr);
- olen = RSTRING(ptr->string)->len;
- if (ptr->flags & FMODE_APPEND) {
- ptr->pos = olen;
+ if (RB_TYPE_P(ch, T_STRING)) {
+ if (NIL_P(ptr->string)) return ch;
+ str = rb_str_substr(ch, 0, 1);
+ }
+ else {
+ char c = NUM2CHR(ch);
+ if (NIL_P(ptr->string)) return ch;
+ str = rb_str_new(&c, 1);
}
- strio_extend(ptr, ptr->pos, 1);
- RSTRING(ptr->string)->ptr[ptr->pos++] = c;
- OBJ_INFECT(ptr->string, self);
+ strio_write(self, str);
return ch;
}
@@ -1080,54 +1682,49 @@ strio_putc(self, ch)
/*
* call-seq:
- * strio.read([length [, buffer]]) -> string, buffer, or nil
+ * read(maxlen = nil, out_string = nil) → new_string, out_string, or nil
+ *
+ * :include: stringio/read.rdoc
*
- * See IO#read.
*/
static VALUE
-strio_read(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+strio_read(int argc, VALUE *argv, VALUE self)
{
- struct StringIO *ptr = readable(StringIO(self));
+ struct StringIO *ptr = readable(self);
VALUE str = Qnil;
- long len, olen;
+ long len;
+ int binary = 0;
switch (argc) {
case 2:
- str = argv[1];
- StringValue(str);
- rb_str_modify(str);
+ str = strio_readbuf(ptr, argv[1]);
+ /* fall through */
case 1:
if (!NIL_P(argv[0])) {
- len = olen = NUM2LONG(argv[0]);
+ len = NUM2LONG(argv[0]);
if (len < 0) {
rb_raise(rb_eArgError, "negative length %ld given", len);
}
- if (len > 0 && ptr->pos >= RSTRING(ptr->string)->len) {
- ptr->flags |= STRIO_EOF;
- if (!NIL_P(str)) rb_str_resize(str, 0);
- return Qnil;
- }
- else if (ptr->flags & STRIO_EOF) {
+ if (eos_p(ptr)) {
if (!NIL_P(str)) rb_str_resize(str, 0);
- return Qnil;
+ return len > 0 ? Qnil : rb_str_new(0, 0);
}
+ binary = 1;
break;
}
/* fall through */
case 0:
- olen = -1;
- len = RSTRING(ptr->string)->len;
+ if (NIL_P(ptr->string)) return Qnil;
+ len = RSTRING_LEN(ptr->string);
if (len <= ptr->pos) {
- ptr->flags |= STRIO_EOF;
+ rb_encoding *enc = get_enc(ptr);
if (NIL_P(str)) {
str = rb_str_new(0, 0);
}
else {
rb_str_resize(str, 0);
}
+ rb_enc_associate(str, enc);
return str;
}
else {
@@ -1135,118 +1732,311 @@ strio_read(argc, argv, self)
}
break;
default:
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
+ rb_error_arity(argc, 0, 2);
}
if (NIL_P(str)) {
- str = rb_str_substr(ptr->string, ptr->pos, len);
+ rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
+ str = strio_substr(ptr, ptr->pos, len, enc);
}
else {
- long rest = RSTRING(ptr->string)->len - ptr->pos;
+ long rest = RSTRING_LEN(ptr->string) - ptr->pos;
if (len > rest) len = rest;
rb_str_resize(str, len);
- MEMCPY(RSTRING(str)->ptr, RSTRING(ptr->string)->ptr + ptr->pos, char, len);
+ MEMCPY(RSTRING_PTR(str), RSTRING_PTR(ptr->string) + ptr->pos, char, len);
+ if (!binary) {
+ rb_enc_copy(str, ptr->string);
+ }
}
- if (NIL_P(str)) {
- if (!(ptr->flags & STRIO_EOF)) str = rb_str_new(0, 0);
- len = 0;
+ ptr->pos += RSTRING_LEN(str);
+ return str;
+}
+
+/*
+ * call-seq:
+ * pread(maxlen, offset, out_string = nil) -> new_string or out_string
+ *
+ * :include: stringio/pread.rdoc
+ *
+ */
+static VALUE
+strio_pread(int argc, VALUE *argv, VALUE self)
+{
+ VALUE rb_len, rb_offset, rb_buf;
+ struct StringIO *ptr = readable(self);
+
+ rb_scan_args(argc, argv, "21", &rb_len, &rb_offset, &rb_buf);
+ long len = NUM2LONG(rb_len);
+ long offset = NUM2LONG(rb_offset);
+
+ if (len < 0) {
+ rb_raise(rb_eArgError, "negative string size (or size too big): %" PRIsVALUE, rb_len);
}
- else {
- ptr->pos += len = RSTRING(str)->len;
+
+ if (offset < 0) {
+ rb_syserr_fail_str(EINVAL, rb_sprintf("pread: Invalid offset argument: %" PRIsVALUE, rb_offset));
}
- if (olen < 0 || olen > len) ptr->flags |= STRIO_EOF;
- return str;
+
+ rb_buf = strio_readbuf(ptr, rb_buf);
+
+ if (len == 0) {
+ if (NIL_P(rb_buf)) {
+ return rb_str_new("", 0);
+ }
+ return rb_buf;
+ }
+
+ if (outside_p(ptr, offset)) {
+ rb_eof_error();
+ }
+
+ if (NIL_P(rb_buf)) {
+ return strio_substr(ptr, offset, len, rb_ascii8bit_encoding());
+ }
+
+ long rest = RSTRING_LEN(ptr->string) - offset;
+ if (len > rest) len = rest;
+ rb_str_resize(rb_buf, len);
+ rb_enc_associate(rb_buf, rb_ascii8bit_encoding());
+ MEMCPY(RSTRING_PTR(rb_buf), RSTRING_PTR(ptr->string) + offset, char, len);
+ return rb_buf;
}
+
/*
* call-seq:
* strio.sysread(integer[, outbuf]) -> string
+ * strio.readpartial(integer[, outbuf]) -> string
*
* Similar to #read, but raises +EOFError+ at end of string instead of
* returning +nil+, as well as IO#sysread does.
*/
static VALUE
-strio_sysread(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+strio_sysread(int argc, VALUE *argv, VALUE self)
{
- VALUE val = strio_read(argc, argv, self);
- if (NIL_P(val) || RSTRING(val)->len == 0) {
+ VALUE val = rb_funcallv_kw(self, rb_intern("read"), argc, argv, RB_PASS_CALLED_KEYWORDS);
+ if (NIL_P(val)) {
rb_eof_error();
}
return val;
}
-#define strio_syswrite strio_write
-
-/* call-seq: strio.path -> nil */
-#define strio_path strio_nil
-
/*
* call-seq:
- * strio.isatty -> nil
- * strio.tty? -> nil
+ * strio.read_nonblock(integer[, outbuf [, opts]]) -> string
*
+ * Similar to #read, but raises +EOFError+ at end of string unless the
+ * +exception: false+ option is passed in.
+ */
+static VALUE
+strio_read_nonblock(int argc, VALUE *argv, VALUE self)
+{
+ VALUE opts = Qnil, val;
+
+ rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
+
+ if (!NIL_P(opts)) {
+ argc--;
+ }
+
+ val = strio_read(argc, argv, self);
+ if (NIL_P(val)) {
+ if (!NIL_P(opts) &&
+ rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse)
+ return Qnil;
+ else
+ rb_eof_error();
+ }
+
+ return val;
+}
+
+/*
+ * See IO#write
*/
+#define strio_syswrite rb_io_write
+
+/*
+ * See IO#write_nonblock
+ */
+static VALUE
+strio_syswrite_nonblock(int argc, VALUE *argv, VALUE self)
+{
+ VALUE str;
+
+ rb_scan_args(argc, argv, "10:", &str, NULL);
+ return strio_syswrite(self, str);
+}
+
#define strio_isatty strio_false
-/* call-seq: strio.pid -> nil */
#define strio_pid strio_nil
-/* call-seq: strio.fileno -> nil */
#define strio_fileno strio_nil
/*
* call-seq:
- * strio.size -> integer
+ * size -> integer
+ *
+ * :include: stringio/size.rdoc
*
- * Returns the size of the buffer string.
*/
static VALUE
-strio_size(self)
- VALUE self;
+strio_size(VALUE self)
{
- VALUE string = StringIO(self)->string;
+ VALUE string = StringIOForRead(self)->string;
if (NIL_P(string)) {
- rb_raise(rb_eIOError, "not opened");
+ return INT2FIX(0);
}
- return ULONG2NUM(RSTRING(string)->len);
+ return ULONG2NUM(RSTRING_LEN(string));
}
/*
* call-seq:
* strio.truncate(integer) -> 0
*
- * Truncates the buffer string to at most _integer_ bytes. The *strio*
+ * Truncates the buffer string to at most _integer_ bytes. The stream
* must be opened for writing.
*/
static VALUE
-strio_truncate(self, len)
- VALUE self, len;
+strio_truncate(VALUE self, VALUE len)
{
- VALUE string = writable(StringIO(self))->string;
+ VALUE string = writable(self)->string;
long l = NUM2LONG(len);
- long plen = RSTRING(string)->len;
+ long plen;
if (l < 0) {
- error_inval("negative legnth");
+ error_inval("negative length");
}
+ if (NIL_P(string)) return 0;
+ plen = RSTRING_LEN(string);
rb_str_resize(string, l);
if (plen < l) {
- MEMZERO(RSTRING(string)->ptr + plen, char, l - plen);
+ MEMZERO(RSTRING_PTR(string) + plen, char, l - plen);
}
- return len;
+ return INT2FIX(0);
+}
+
+/*
+ * call-seq:
+ * external_encoding -> encoding or nil
+ *
+ * Returns an Encoding object that represents the encoding of the string;
+ * see {Encodings}[rdoc-ref:StringIO@Encodings]:
+ *
+ * strio = StringIO.new('foo')
+ * strio.external_encoding # => #<Encoding:UTF-8>
+ *
+ * Returns +nil+ if +self+ has no string and is in write mode:
+ *
+ * strio = StringIO.new(nil, 'w+')
+ * strio.external_encoding # => nil
+ *
+ */
+
+static VALUE
+strio_external_encoding(VALUE self)
+{
+ struct StringIO *ptr = StringIOForRead(self);
+ return rb_enc_from_encoding(get_enc(ptr));
+}
+
+/*
+ * call-seq:
+ * internal_encoding -> nil
+ *
+ * Returns +nil+; for compatibility with IO.
+ */
+
+static VALUE
+strio_internal_encoding(VALUE self)
+{
+ return Qnil;
}
/*
- * Pseudo I/O on String object.
+ * call-seq:
+ * strio.set_encoding(ext_enc, [int_enc[, opt]]) => strio
+ *
+ * Specify the encoding of the StringIO as <i>ext_enc</i>.
+ * Use the default external encoding if <i>ext_enc</i> is nil.
+ * 2nd argument <i>int_enc</i> and optional hash <i>opt</i> argument
+ * are ignored; they are for API compatibility to IO.
+ */
+
+static VALUE
+strio_set_encoding(int argc, VALUE *argv, VALUE self)
+{
+ rb_encoding* enc;
+ struct StringIO *ptr = StringIO(self);
+ VALUE ext_enc, int_enc, opt;
+
+ argc = rb_scan_args(argc, argv, "11:", &ext_enc, &int_enc, &opt);
+
+ if (NIL_P(ext_enc)) {
+ enc = rb_default_external_encoding();
+ }
+ else {
+ enc = rb_find_encoding(ext_enc);
+ if (!enc) {
+ rb_io_enc_t convconfig;
+ int oflags;
+ rb_io_mode_t fmode;
+ VALUE vmode = rb_str_append(rb_str_new_cstr("r:"), ext_enc);
+ rb_io_extract_modeenc(&vmode, 0, Qnil, &oflags, &fmode, &convconfig);
+ enc = convconfig.enc2;
+ }
+ }
+ ptr->enc = enc;
+ if (!NIL_P(ptr->string) && WRITABLE(self) && !str_chilled_p(ptr->string)) {
+ rb_enc_associate(ptr->string, enc);
+ }
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * strio.set_encoding_by_bom => strio or nil
+ *
+ * Sets the encoding according to the BOM (Byte Order Mark) in the
+ * string.
+ *
+ * Returns +self+ if the BOM is found, otherwise +nil.
+ */
+static VALUE
+strio_set_encoding_by_bom(VALUE self)
+{
+ struct StringIO *ptr = StringIO(self);
+
+ if (!set_encoding_by_bom(ptr)) return Qnil;
+ return rb_enc_from_encoding(ptr->enc);
+}
+
+/*
+ * :markup: markdown
+ *
+ * :include: stringio/stringio.md
*/
void
-Init_stringio()
+Init_stringio(void)
{
- VALUE StringIO = rb_define_class("StringIO", rb_cData);
+#undef rb_intern
+
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
+ VALUE StringIO = rb_define_class("StringIO", rb_cObject);
+
+ /* The version string */
+ rb_define_const(StringIO, "VERSION", rb_str_new_cstr(STRINGIO_VERSION));
rb_include_module(StringIO, rb_mEnumerable);
rb_define_alloc_func(StringIO, strio_s_allocate);
+
+ /* Maximum length that a StringIO instance can hold */
+ rb_define_const(StringIO, "MAX_LENGTH", LONG2NUM(LONG_MAX));
+
+ rb_define_singleton_method(StringIO, "new", strio_s_new, -1);
rb_define_singleton_method(StringIO, "open", strio_s_open, -1);
rb_define_method(StringIO, "initialize", strio_initialize, -1);
rb_define_method(StringIO, "initialize_copy", strio_copy, 1);
@@ -1257,6 +2047,8 @@ Init_stringio()
rb_define_method(StringIO, "lineno", strio_get_lineno, 0);
rb_define_method(StringIO, "lineno=", strio_set_lineno, 1);
+
+ /* call-seq: strio.binmode -> true */
rb_define_method(StringIO, "binmode", strio_binmode, 0);
rb_define_method(StringIO, "close", strio_close, 0);
rb_define_method(StringIO, "close_read", strio_close_read, 0);
@@ -1266,43 +2058,85 @@ Init_stringio()
rb_define_method(StringIO, "closed_write?", strio_closed_write, 0);
rb_define_method(StringIO, "eof", strio_eof, 0);
rb_define_method(StringIO, "eof?", strio_eof, 0);
+ /* call-seq: strio.fcntl */
rb_define_method(StringIO, "fcntl", strio_fcntl, -1);
+ /* call-seq: strio.flush -> strio */
rb_define_method(StringIO, "flush", strio_flush, 0);
+ /* call-seq: strio.fsync -> 0 */
rb_define_method(StringIO, "fsync", strio_fsync, 0);
rb_define_method(StringIO, "pos", strio_get_pos, 0);
rb_define_method(StringIO, "pos=", strio_set_pos, 1);
rb_define_method(StringIO, "rewind", strio_rewind, 0);
rb_define_method(StringIO, "seek", strio_seek, -1);
rb_define_method(StringIO, "sync", strio_get_sync, 0);
+ /* call-seq: strio.sync = boolean -> boolean */
rb_define_method(StringIO, "sync=", strio_set_sync, 1);
rb_define_method(StringIO, "tell", strio_tell, 0);
- rb_define_method(StringIO, "path", strio_path, 0);
rb_define_method(StringIO, "each", strio_each, -1);
- rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
rb_define_method(StringIO, "each_line", strio_each, -1);
+ rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
+ rb_define_method(StringIO, "each_char", strio_each_char, 0);
+ rb_define_method(StringIO, "each_codepoint", strio_each_codepoint, 0);
rb_define_method(StringIO, "getc", strio_getc, 0);
rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
- rb_define_method(StringIO, "readchar", strio_readchar, 0);
+ rb_define_method(StringIO, "ungetbyte", strio_ungetbyte, 1);
+ rb_define_method(StringIO, "getbyte", strio_getbyte, 0);
rb_define_method(StringIO, "gets", strio_gets, -1);
- rb_define_method(StringIO, "readline", strio_readline, -1);
rb_define_method(StringIO, "readlines", strio_readlines, -1);
rb_define_method(StringIO, "read", strio_read, -1);
- rb_define_method(StringIO, "sysread", strio_sysread, -1);
+ rb_define_method(StringIO, "pread", strio_pread, -1);
- rb_define_method(StringIO, "write", strio_write, 1);
- rb_define_method(StringIO, "<<", strio_addstr, 1);
- rb_define_method(StringIO, "print", strio_print, -1);
- rb_define_method(StringIO, "printf", strio_printf, -1);
+ rb_define_method(StringIO, "write", strio_write_m, -1);
rb_define_method(StringIO, "putc", strio_putc, 1);
- rb_define_method(StringIO, "puts", strio_puts, -1);
- rb_define_method(StringIO, "syswrite", strio_syswrite, 1);
+ /*
+ * call-seq:
+ * strio.isatty -> nil
+ * strio.tty? -> nil
+ *
+ */
rb_define_method(StringIO, "isatty", strio_isatty, 0);
rb_define_method(StringIO, "tty?", strio_isatty, 0);
+
+ /* call-seq: strio.pid -> nil */
rb_define_method(StringIO, "pid", strio_pid, 0);
+
+ /* call-seq: strio.fileno -> nil */
rb_define_method(StringIO, "fileno", strio_fileno, 0);
rb_define_method(StringIO, "size", strio_size, 0);
rb_define_method(StringIO, "length", strio_size, 0);
rb_define_method(StringIO, "truncate", strio_truncate, 1);
+
+ rb_define_method(StringIO, "external_encoding", strio_external_encoding, 0);
+ rb_define_method(StringIO, "internal_encoding", strio_internal_encoding, 0);
+ rb_define_method(StringIO, "set_encoding", strio_set_encoding, -1);
+ rb_define_method(StringIO, "set_encoding_by_bom", strio_set_encoding_by_bom, 0);
+
+ {
+ /* :stopdoc: */
+ VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
+ /* :startdoc: */
+ rb_define_method(mReadable, "readchar", strio_readchar, 0);
+ rb_define_method(mReadable, "readbyte", strio_readbyte, 0);
+ rb_define_method(mReadable, "readline", strio_readline, -1);
+ rb_define_method(mReadable, "sysread", strio_sysread, -1);
+ rb_define_method(mReadable, "readpartial", strio_sysread, -1);
+ rb_define_method(mReadable, "read_nonblock", strio_read_nonblock, -1);
+ rb_include_module(StringIO, mReadable);
+ }
+ {
+ /* :stopdoc: */
+ VALUE mWritable = rb_define_module_under(rb_cIO, "generic_writable");
+ /* :startdoc: */
+ rb_define_method(mWritable, "<<", strio_addstr, 1);
+ rb_define_method(mWritable, "print", strio_print, -1);
+ rb_define_method(mWritable, "printf", strio_printf, -1);
+ rb_define_method(mWritable, "puts", strio_puts, -1);
+ rb_define_method(mWritable, "syswrite", strio_syswrite, 1);
+ rb_define_method(mWritable, "write_nonblock", strio_syswrite_nonblock, -1);
+ rb_include_module(StringIO, mWritable);
+ }
+
+ sym_exception = ID2SYM(rb_intern("exception"));
}
diff --git a/ext/stringio/stringio.gemspec b/ext/stringio/stringio.gemspec
new file mode 100644
index 0000000000..f9a0742049
--- /dev/null
+++ b/ext/stringio/stringio.gemspec
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+# frozen_string_literal: true
+
+source_version = ["", "ext/stringio/"].find do |dir|
+ begin
+ break File.open(File.join(__dir__, "#{dir}stringio.c")) {|f|
+ f.gets("\nSTRINGIO_VERSION ")
+ f.gets[/\s*"(.+)"/, 1]
+ }
+ rescue Errno::ENOENT
+ end
+end
+Gem::Specification.new do |s|
+ s.name = "stringio"
+ s.version = source_version
+
+ s.require_paths = ["lib"]
+ s.authors = ["Nobu Nakada", "Charles Oliver Nutter"]
+ s.description = "Pseudo `IO` class from/to `String`."
+ s.email = ["nobu@ruby-lang.org", "headius@headius.com"]
+ s.files = ["README.md"]
+ jruby = true if Gem::Platform.new('java') =~ s.platform or RUBY_ENGINE == 'jruby'
+ if jruby
+ s.require_paths = "lib/java"
+ s.files += ["lib/java/stringio.rb", "lib/java/stringio.jar"]
+ s.platform = "java"
+ else
+ s.extensions = ["ext/stringio/extconf.rb"]
+ s.files += ["ext/stringio/extconf.rb", "ext/stringio/stringio.c"]
+ end
+
+ s.extra_rdoc_files = [
+ ".document", ".rdoc_options", "COPYING", "LICENSE.txt",
+ "NEWS.md", "README.md", "docs/io.rb", "ext/stringio/.document",
+ ]
+
+ s.homepage = "https://github.com/ruby/stringio"
+ s.licenses = ["Ruby", "BSD-2-Clause"]
+ s.required_ruby_version = ">= 2.7"
+ s.summary = "Pseudo IO on String"
+
+ s.metadata["changelog_uri"] = "#{s.homepage}/releases/tag/v#{s.version}"
+
+ # s.cert_chain = %w[certs/nobu.pem]
+ # s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
+end
diff --git a/ext/strscan/.cvsignore b/ext/strscan/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/strscan/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/strscan/depend b/ext/strscan/depend
index 9199574c3f..b40a025230 100644
--- a/ext/strscan/depend
+++ b/ext/strscan/depend
@@ -1 +1,177 @@
-strscan.o: strscan.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
+# AUTOGENERATED DEPENDENCIES START
+strscan.o: $(RUBY_EXTCONF_H)
+strscan.o: $(arch_hdrdir)/ruby/config.h
+strscan.o: $(hdrdir)/ruby/assert.h
+strscan.o: $(hdrdir)/ruby/backward.h
+strscan.o: $(hdrdir)/ruby/backward/2/assume.h
+strscan.o: $(hdrdir)/ruby/backward/2/attributes.h
+strscan.o: $(hdrdir)/ruby/backward/2/bool.h
+strscan.o: $(hdrdir)/ruby/backward/2/inttypes.h
+strscan.o: $(hdrdir)/ruby/backward/2/limits.h
+strscan.o: $(hdrdir)/ruby/backward/2/long_long.h
+strscan.o: $(hdrdir)/ruby/backward/2/stdalign.h
+strscan.o: $(hdrdir)/ruby/backward/2/stdarg.h
+strscan.o: $(hdrdir)/ruby/defines.h
+strscan.o: $(hdrdir)/ruby/encoding.h
+strscan.o: $(hdrdir)/ruby/intern.h
+strscan.o: $(hdrdir)/ruby/internal/abi.h
+strscan.o: $(hdrdir)/ruby/internal/anyargs.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+strscan.o: $(hdrdir)/ruby/internal/assume.h
+strscan.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+strscan.o: $(hdrdir)/ruby/internal/attr/artificial.h
+strscan.o: $(hdrdir)/ruby/internal/attr/cold.h
+strscan.o: $(hdrdir)/ruby/internal/attr/const.h
+strscan.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+strscan.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+strscan.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+strscan.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+strscan.o: $(hdrdir)/ruby/internal/attr/error.h
+strscan.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+strscan.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+strscan.o: $(hdrdir)/ruby/internal/attr/format.h
+strscan.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+strscan.o: $(hdrdir)/ruby/internal/attr/noalias.h
+strscan.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+strscan.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+strscan.o: $(hdrdir)/ruby/internal/attr/noinline.h
+strscan.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+strscan.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+strscan.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+strscan.o: $(hdrdir)/ruby/internal/attr/pure.h
+strscan.o: $(hdrdir)/ruby/internal/attr/restrict.h
+strscan.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+strscan.o: $(hdrdir)/ruby/internal/attr/warning.h
+strscan.o: $(hdrdir)/ruby/internal/attr/weakref.h
+strscan.o: $(hdrdir)/ruby/internal/cast.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_since.h
+strscan.o: $(hdrdir)/ruby/internal/config.h
+strscan.o: $(hdrdir)/ruby/internal/constant_p.h
+strscan.o: $(hdrdir)/ruby/internal/core.h
+strscan.o: $(hdrdir)/ruby/internal/core/rarray.h
+strscan.o: $(hdrdir)/ruby/internal/core/rbasic.h
+strscan.o: $(hdrdir)/ruby/internal/core/rbignum.h
+strscan.o: $(hdrdir)/ruby/internal/core/rclass.h
+strscan.o: $(hdrdir)/ruby/internal/core/rdata.h
+strscan.o: $(hdrdir)/ruby/internal/core/rfile.h
+strscan.o: $(hdrdir)/ruby/internal/core/rhash.h
+strscan.o: $(hdrdir)/ruby/internal/core/rmatch.h
+strscan.o: $(hdrdir)/ruby/internal/core/robject.h
+strscan.o: $(hdrdir)/ruby/internal/core/rregexp.h
+strscan.o: $(hdrdir)/ruby/internal/core/rstring.h
+strscan.o: $(hdrdir)/ruby/internal/core/rstruct.h
+strscan.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+strscan.o: $(hdrdir)/ruby/internal/ctype.h
+strscan.o: $(hdrdir)/ruby/internal/dllexport.h
+strscan.o: $(hdrdir)/ruby/internal/dosish.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/re.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/string.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+strscan.o: $(hdrdir)/ruby/internal/error.h
+strscan.o: $(hdrdir)/ruby/internal/eval.h
+strscan.o: $(hdrdir)/ruby/internal/event.h
+strscan.o: $(hdrdir)/ruby/internal/fl_type.h
+strscan.o: $(hdrdir)/ruby/internal/gc.h
+strscan.o: $(hdrdir)/ruby/internal/glob.h
+strscan.o: $(hdrdir)/ruby/internal/globals.h
+strscan.o: $(hdrdir)/ruby/internal/has/attribute.h
+strscan.o: $(hdrdir)/ruby/internal/has/builtin.h
+strscan.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+strscan.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+strscan.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+strscan.o: $(hdrdir)/ruby/internal/has/extension.h
+strscan.o: $(hdrdir)/ruby/internal/has/feature.h
+strscan.o: $(hdrdir)/ruby/internal/has/warning.h
+strscan.o: $(hdrdir)/ruby/internal/intern/array.h
+strscan.o: $(hdrdir)/ruby/internal/intern/bignum.h
+strscan.o: $(hdrdir)/ruby/internal/intern/class.h
+strscan.o: $(hdrdir)/ruby/internal/intern/compar.h
+strscan.o: $(hdrdir)/ruby/internal/intern/complex.h
+strscan.o: $(hdrdir)/ruby/internal/intern/cont.h
+strscan.o: $(hdrdir)/ruby/internal/intern/dir.h
+strscan.o: $(hdrdir)/ruby/internal/intern/enum.h
+strscan.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+strscan.o: $(hdrdir)/ruby/internal/intern/error.h
+strscan.o: $(hdrdir)/ruby/internal/intern/eval.h
+strscan.o: $(hdrdir)/ruby/internal/intern/file.h
+strscan.o: $(hdrdir)/ruby/internal/intern/hash.h
+strscan.o: $(hdrdir)/ruby/internal/intern/io.h
+strscan.o: $(hdrdir)/ruby/internal/intern/load.h
+strscan.o: $(hdrdir)/ruby/internal/intern/marshal.h
+strscan.o: $(hdrdir)/ruby/internal/intern/numeric.h
+strscan.o: $(hdrdir)/ruby/internal/intern/object.h
+strscan.o: $(hdrdir)/ruby/internal/intern/parse.h
+strscan.o: $(hdrdir)/ruby/internal/intern/proc.h
+strscan.o: $(hdrdir)/ruby/internal/intern/process.h
+strscan.o: $(hdrdir)/ruby/internal/intern/random.h
+strscan.o: $(hdrdir)/ruby/internal/intern/range.h
+strscan.o: $(hdrdir)/ruby/internal/intern/rational.h
+strscan.o: $(hdrdir)/ruby/internal/intern/re.h
+strscan.o: $(hdrdir)/ruby/internal/intern/ruby.h
+strscan.o: $(hdrdir)/ruby/internal/intern/select.h
+strscan.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+strscan.o: $(hdrdir)/ruby/internal/intern/set.h
+strscan.o: $(hdrdir)/ruby/internal/intern/signal.h
+strscan.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+strscan.o: $(hdrdir)/ruby/internal/intern/string.h
+strscan.o: $(hdrdir)/ruby/internal/intern/struct.h
+strscan.o: $(hdrdir)/ruby/internal/intern/thread.h
+strscan.o: $(hdrdir)/ruby/internal/intern/time.h
+strscan.o: $(hdrdir)/ruby/internal/intern/variable.h
+strscan.o: $(hdrdir)/ruby/internal/intern/vm.h
+strscan.o: $(hdrdir)/ruby/internal/interpreter.h
+strscan.o: $(hdrdir)/ruby/internal/iterator.h
+strscan.o: $(hdrdir)/ruby/internal/memory.h
+strscan.o: $(hdrdir)/ruby/internal/method.h
+strscan.o: $(hdrdir)/ruby/internal/module.h
+strscan.o: $(hdrdir)/ruby/internal/newobj.h
+strscan.o: $(hdrdir)/ruby/internal/scan_args.h
+strscan.o: $(hdrdir)/ruby/internal/special_consts.h
+strscan.o: $(hdrdir)/ruby/internal/static_assert.h
+strscan.o: $(hdrdir)/ruby/internal/stdalign.h
+strscan.o: $(hdrdir)/ruby/internal/stdbool.h
+strscan.o: $(hdrdir)/ruby/internal/stdckdint.h
+strscan.o: $(hdrdir)/ruby/internal/symbol.h
+strscan.o: $(hdrdir)/ruby/internal/value.h
+strscan.o: $(hdrdir)/ruby/internal/value_type.h
+strscan.o: $(hdrdir)/ruby/internal/variable.h
+strscan.o: $(hdrdir)/ruby/internal/warning_push.h
+strscan.o: $(hdrdir)/ruby/internal/xmalloc.h
+strscan.o: $(hdrdir)/ruby/missing.h
+strscan.o: $(hdrdir)/ruby/onigmo.h
+strscan.o: $(hdrdir)/ruby/oniguruma.h
+strscan.o: $(hdrdir)/ruby/re.h
+strscan.o: $(hdrdir)/ruby/regex.h
+strscan.o: $(hdrdir)/ruby/ruby.h
+strscan.o: $(hdrdir)/ruby/st.h
+strscan.o: $(hdrdir)/ruby/subst.h
+strscan.o: strscan.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/strscan/extconf.rb b/ext/strscan/extconf.rb
index 0d21966fc2..4e8d851fdb 100644
--- a/ext/strscan/extconf.rb
+++ b/ext/strscan/extconf.rb
@@ -1,2 +1,14 @@
+# frozen_string_literal: true
require 'mkmf'
-create_makefile 'strscan'
+if RUBY_ENGINE == 'ruby'
+ $INCFLAGS << " -I$(top_srcdir)" if $extmk
+ have_func("onig_region_memsize(NULL)")
+ have_func("rb_reg_onig_match", "ruby/re.h")
+ have_func("rb_deprecate_constant")
+ have_func("rb_int_parse_cstr", "ruby.h") # RUBY_VERSION >= 2.5
+ have_func("rb_gc_location", "ruby.h") # RUBY_VERSION >= 2.7
+ have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3
+ create_makefile 'strscan'
+else
+ File.write('Makefile', dummy_makefile("").join)
+end
diff --git a/ext/strscan/lib/strscan.rb b/ext/strscan/lib/strscan.rb
new file mode 100644
index 0000000000..4e8910d141
--- /dev/null
+++ b/ext/strscan/lib/strscan.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+case RUBY_ENGINE
+when 'ruby'
+ require 'strscan.so'
+ require_relative 'strscan/strscan'
+when 'jruby'
+ require 'strscan.jar'
+ JRuby::Util.load_ext('org.jruby.ext.strscan.StringScannerLibrary')
+ require_relative 'strscan/strscan'
+when 'truffleruby'
+ if RUBY_ENGINE_VERSION.to_i >= 34
+ require 'strscan/truffleruby'
+ else
+ $LOAD_PATH.delete __dir__
+ require 'strscan'
+ end
+else
+ raise NotImplementedError, "Unknown Ruby: #{RUBY_ENGINE}"
+end
diff --git a/ext/strscan/lib/strscan/strscan.rb b/ext/strscan/lib/strscan/strscan.rb
new file mode 100644
index 0000000000..5e262f4007
--- /dev/null
+++ b/ext/strscan/lib/strscan/strscan.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+class StringScanner
+ unless method_defined?(:integer_at) # For JRuby
+ def integer_at(specifier, *to_i_args)
+ self[specifier]&.to_i(*to_i_args)
+ end
+ end
+
+ # :markup: markdown
+ #
+ # call-seq:
+ # scan_integer(base: 10) -> integer or nil
+ #
+ # Returns an integer scanned from `self`,
+ # beginning at the current position;
+ # returns `nil` if no such integer was available.
+ #
+ # When `base` is `10` (the default),
+ # equivalent to calling #scan with argument +pattern+
+ # as `'[+-]?\d+'`:
+ #
+ # ```ruby
+ # scanner = StringScanner.new('Form 27B/6')
+ # scanner.scan_integer # => nil # No integer at position 0.
+ # scanner.pos = 5
+ # scanner.scan_integer # => 27
+ # scanner.matched # => "27"
+ # scanner.pos # => 7
+ # ```
+ #
+ # When `base` is `16` (the only other value allowed),
+ # equivalent to calling #scan with argument `pattern`
+ # as `'[+-]?(0x)?[0-9a-fA-F]+'`:
+ #
+ # ```ruby
+ # scanner.pos = 5
+ # scanner.scan_integer(base: 16) # => 635
+ # scanner.matched # => "27B"
+ # scanner.pos # => 8
+ # ```
+ #
+ # Raises Encoding::CompatibilityError if `self` does not have
+ # an ASCII compatible encoding.
+ def scan_integer(base: 10)
+ case base
+ when 10
+ scan_base10_integer
+ when 16
+ scan_base16_integer
+ else
+ raise ArgumentError, "Unsupported integer base: #{base.inspect}, expected 10 or 16"
+ end
+ end
+end
diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c
index fdbfc79919..dede57218b 100644
--- a/ext/strscan/strscan.c
+++ b/ext/strscan/strscan.c
@@ -4,14 +4,33 @@
Copyright (c) 1999-2006 Minero Aoki
This program is free software.
- You can distribute/modify this program under the terms of
- the Ruby License. For details, see the file COPYING.
+ You can redistribute this program under the terms of the Ruby's or 2-clause
+ BSD License. For details, see the COPYING and LICENSE.txt files.
*/
-#include "ruby.h"
-#include "re.h"
+#include "ruby/ruby.h"
+#include "ruby/re.h"
+#include "ruby/encoding.h"
-#define STRSCAN_VERSION "0.7.0"
+#ifdef RUBY_EXTCONF_H
+# include RUBY_EXTCONF_H
+#endif
+
+#ifdef HAVE_ONIG_REGION_MEMSIZE
+extern size_t onig_region_memsize(const struct re_registers *regs);
+#endif
+
+#include <stdbool.h>
+
+#define STRSCAN_VERSION "3.1.9.dev"
+
+
+#ifdef HAVE_RB_DEPRECATE_CONSTANT
+/* In ruby 3.0, defined but exposed in external headers */
+extern void rb_deprecate_constant(VALUE mod, const char *name);
+#else
+# define rb_deprecate_constant(mod, name) ((void)0)
+#endif
/* =======================================================================
Data Type Definitions
@@ -20,6 +39,8 @@
static VALUE StringScanner;
static VALUE ScanError;
+static int usascii_encindex, utf8_encindex, binary_encindex;
+
struct strscanner
{
/* multi-purpose flags */
@@ -28,50 +49,61 @@ struct strscanner
/* the string to scan */
VALUE str;
-
+
/* scan pointers */
long prev; /* legal only when MATCHED_P(s) */
long curr; /* always legal */
/* the regexp register; legal only when MATCHED_P(s) */
struct re_registers regs;
+
+ /* regexp used for last scan */
+ VALUE regex;
+
+ /* anchor mode */
+ bool fixed_anchor_p;
};
#define MATCHED_P(s) ((s)->flags & FLAG_MATCHED)
-#define MATCHED(s) (s)->flags |= FLAG_MATCHED
-#define CLEAR_MATCH_STATUS(s) (s)->flags &= ~FLAG_MATCHED
+#define MATCHED(s) ((s)->flags |= FLAG_MATCHED)
+#define CLEAR_MATCHED(s) ((s)->flags &= ~FLAG_MATCHED)
+#define CLEAR_NAMED_CAPTURES(s) ((s)->regex = Qnil)
+#define CLEAR_MATCH_STATUS(s) do {\
+ CLEAR_MATCHED(s);\
+ CLEAR_NAMED_CAPTURES(s);\
+} while (0)
-#define S_PBEG(s) (RSTRING((s)->str)->ptr)
-#define S_LEN(s) (RSTRING((s)->str)->len)
+#define S_PBEG(s) (RSTRING_PTR((s)->str))
+#define S_LEN(s) (RSTRING_LEN((s)->str))
#define S_PEND(s) (S_PBEG(s) + S_LEN(s))
#define CURPTR(s) (S_PBEG(s) + (s)->curr)
#define S_RESTLEN(s) (S_LEN(s) - (s)->curr)
-#define EOS_P(s) ((s)->curr >= RSTRING(p->str)->len)
+#define EOS_P(s) ((s)->curr >= RSTRING_LEN(p->str))
#define GET_SCANNER(obj,var) do {\
- Data_Get_Struct(obj, struct strscanner, var);\
- if (NIL_P(var->str)) rb_raise(rb_eArgError, "uninitialized StringScanner object");\
+ (var) = check_strscan(obj);\
+ if (NIL_P((var)->str)) rb_raise(rb_eArgError, "uninitialized StringScanner object");\
} while (0)
/* =======================================================================
Function Prototypes
======================================================================= */
-static VALUE infect _((VALUE str, struct strscanner *p));
+static inline long minl _((const long n, const long x));
static VALUE extract_range _((struct strscanner *p, long beg_i, long end_i));
static VALUE extract_beg_len _((struct strscanner *p, long beg_i, long len));
-static void check_strscan _((VALUE obj));
-static void strscan_mark _((struct strscanner *p));
-static void strscan_free _((struct strscanner *p));
+static struct strscanner *check_strscan _((VALUE obj));
+static void strscan_mark _((void *p));
+static void strscan_free _((void *p));
+static size_t strscan_memsize _((const void *p));
static VALUE strscan_s_allocate _((VALUE klass));
static VALUE strscan_initialize _((int argc, VALUE *argv, VALUE self));
static VALUE strscan_init_copy _((VALUE vself, VALUE vorig));
static VALUE strscan_s_mustc _((VALUE self));
static VALUE strscan_terminate _((VALUE self));
-static VALUE strscan_clear _((VALUE self));
static VALUE strscan_get_string _((VALUE self));
static VALUE strscan_set_string _((VALUE self, VALUE str));
static VALUE strscan_concat _((VALUE self, VALUE str));
@@ -93,13 +125,11 @@ static VALUE strscan_search_full _((VALUE self, VALUE re,
static void adjust_registers_to_matched _((struct strscanner *p));
static VALUE strscan_getch _((VALUE self));
static VALUE strscan_get_byte _((VALUE self));
-static VALUE strscan_getbyte _((VALUE self));
static VALUE strscan_peek _((VALUE self, VALUE len));
-static VALUE strscan_peep _((VALUE self, VALUE len));
+static VALUE strscan_scan_base10_integer _((VALUE self));
static VALUE strscan_unscan _((VALUE self));
static VALUE strscan_bol_p _((VALUE self));
static VALUE strscan_eos_p _((VALUE self));
-static VALUE strscan_empty_p _((VALUE self));
static VALUE strscan_rest_p _((VALUE self));
static VALUE strscan_matched_p _((VALUE self));
static VALUE strscan_matched _((VALUE self));
@@ -119,112 +149,207 @@ static VALUE inspect2 _((struct strscanner *p));
======================================================================= */
static VALUE
-infect(VALUE str, struct strscanner *p)
+str_new(struct strscanner *p, const char *ptr, long len)
{
- OBJ_INFECT(str, p->str);
+ VALUE str = rb_str_new(ptr, len);
+ rb_enc_copy(str, p->str);
return str;
}
+static inline long
+minl(const long x, const long y)
+{
+ return (x < y) ? x : y;
+}
+
static VALUE
extract_range(struct strscanner *p, long beg_i, long end_i)
{
if (beg_i > S_LEN(p)) return Qnil;
- if (end_i > S_LEN(p))
- end_i = S_LEN(p);
- return infect(rb_str_new(S_PBEG(p) + beg_i, end_i - beg_i), p);
+ end_i = minl(end_i, S_LEN(p));
+ return str_new(p, S_PBEG(p) + beg_i, end_i - beg_i);
}
static VALUE
extract_beg_len(struct strscanner *p, long beg_i, long len)
{
if (beg_i > S_LEN(p)) return Qnil;
- if (beg_i + len > S_LEN(p))
- len = S_LEN(p) - beg_i;
- return infect(rb_str_new(S_PBEG(p) + beg_i, len), p);
+ len = minl(len, S_LEN(p) - beg_i);
+ return str_new(p, S_PBEG(p) + beg_i, len);
}
/* =======================================================================
Constructor
======================================================================= */
+#ifdef RUBY_TYPED_EMBEDDABLE
+# define HAVE_RUBY_TYPED_EMBEDDABLE 1
+#else
+# ifdef HAVE_CONST_RUBY_TYPED_EMBEDDABLE
+# define RUBY_TYPED_EMBEDDABLE RUBY_TYPED_EMBEDDABLE
+# define HAVE_RUBY_TYPED_EMBEDDABLE 1
+# else
+# define RUBY_TYPED_EMBEDDABLE 0
+# endif
+#endif
+
+#ifdef HAVE_RB_GC_LOCATION
+static void
+strscan_compact(void *ptr)
+{
+ struct strscanner *p = ptr;
+ p->str = rb_gc_location(p->str);
+ p->regex = rb_gc_location(p->regex);
+}
+#else
+#define rb_gc_mark_movable rb_gc_mark
+#endif
+
static void
-strscan_mark(struct strscanner *p)
+strscan_mark(void *ptr)
{
- rb_gc_mark(p->str);
+ struct strscanner *p = ptr;
+ rb_gc_mark_movable(p->str);
+ rb_gc_mark_movable(p->regex);
}
static void
-strscan_free(struct strscanner *p)
+strscan_free(void *ptr)
+{
+ struct strscanner *p = ptr;
+ onig_region_free(&(p->regs), 0);
+#ifndef HAVE_RUBY_TYPED_EMBEDDABLE
+ ruby_xfree(p);
+#endif
+}
+
+static size_t
+strscan_memsize(const void *ptr)
{
- re_free_registers(&(p->regs));
- free(p);
+ size_t size = 0;
+#ifndef HAVE_RUBY_TYPED_EMBEDDABLE
+ size += sizeof(struct strscanner);
+#endif
+
+#ifdef HAVE_ONIG_REGION_MEMSIZE
+ const struct strscanner *p = ptr;
+ size += onig_region_memsize(&p->regs) - sizeof(p->regs);
+#endif
+ return size;
}
+static const rb_data_type_t strscanner_type = {
+ .wrap_struct_name = "StringScanner",
+ .function = {
+ .dmark = strscan_mark,
+ .dfree = strscan_free,
+ .dsize = strscan_memsize,
+#ifdef HAVE_RB_GC_LOCATION
+ .dcompact = strscan_compact,
+#endif
+ },
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
+};
+
static VALUE
strscan_s_allocate(VALUE klass)
{
struct strscanner *p;
-
- p = ALLOC(struct strscanner);
- MEMZERO(p, struct strscanner, 1);
+ VALUE obj = TypedData_Make_Struct(klass, struct strscanner, &strscanner_type, p);
+
CLEAR_MATCH_STATUS(p);
- MEMZERO(&(p->regs), struct re_registers, 1);
+ onig_region_init(&(p->regs));
p->str = Qnil;
- return Data_Wrap_Struct(klass, strscan_mark, strscan_free, p);
+ return obj;
}
/*
- * call-seq: StringScanner.new(string, dup = false)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * StringScanner.new(string, fixed_anchor: false) -> string_scanner
+ *
+ * Returns a new `StringScanner` object whose [stored string][1]
+ * is the given `string`;
+ * sets the [fixed-anchor property][10]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.string # => "foobarbaz"
+ * scanner.fixed_anchor? # => false
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 0
+ * # charpos: 0
+ * # rest: "foobarbaz"
+ * # rest_size: 9
+ * ```
*
- * Creates a new StringScanner object to scan over the given +string+.
- * +dup+ argument is obsolete and not used now.
*/
static VALUE
strscan_initialize(int argc, VALUE *argv, VALUE self)
{
struct strscanner *p;
- VALUE str, need_dup;
-
- Data_Get_Struct(self, struct strscanner, p);
- rb_scan_args(argc, argv, "11", &str, &need_dup);
+ VALUE str, options;
+
+ p = check_strscan(self);
+ rb_scan_args(argc, argv, "11", &str, &options);
+ options = rb_check_hash_type(options);
+ if (!NIL_P(options)) {
+ VALUE fixed_anchor;
+ ID keyword_ids[1];
+ keyword_ids[0] = rb_intern("fixed_anchor");
+ rb_get_kwargs(options, keyword_ids, 0, 1, &fixed_anchor);
+ if (fixed_anchor == Qundef) {
+ p->fixed_anchor_p = false;
+ }
+ else {
+ p->fixed_anchor_p = RTEST(fixed_anchor);
+ }
+ }
+ else {
+ p->fixed_anchor_p = false;
+ }
StringValue(str);
- p->str = str;
+ RB_OBJ_WRITE(self, &p->str, str);
return self;
}
-static void
+static struct strscanner *
check_strscan(VALUE obj)
{
- if (TYPE(obj) != T_DATA || RDATA(obj)->dmark != (RUBY_DATA_FUNC)strscan_mark) {
- rb_raise(rb_eTypeError,
- "wrong argument type %s (expected StringScanner)",
- rb_obj_classname(obj));
- }
+ return rb_check_typeddata(obj, &strscanner_type);
}
/*
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
* call-seq:
- * dup
- * clone
+ * dup -> shallow_copy
*
- * Duplicates a StringScanner object.
+ * Returns a shallow copy of `self`;
+ * the [stored string][1] in the copy is the same string as in `self`.
*/
static VALUE
strscan_init_copy(VALUE vself, VALUE vorig)
{
struct strscanner *self, *orig;
- Data_Get_Struct(vself, struct strscanner, self);
- check_strscan(vorig);
- Data_Get_Struct(vorig, struct strscanner, orig);
+ self = check_strscan(vself);
+ orig = check_strscan(vorig);
if (self != orig) {
- self->flags = orig->flags;
- self->str = orig->str;
- self->prev = orig->prev;
- self->curr = orig->curr;
- re_copy_registers(&self->regs, &orig->regs);
+ self->flags = orig->flags;
+ RB_OBJ_WRITE(vself, &self->str, orig->str);
+ self->prev = orig->prev;
+ self->curr = orig->curr;
+ if (rb_reg_region_copy(&self->regs, &orig->regs))
+ rb_memerror();
+ RB_GC_GUARD(vorig);
}
+
return vself;
}
@@ -233,10 +358,13 @@ strscan_init_copy(VALUE vself, VALUE vorig)
======================================================================= */
/*
- * call-seq: StringScanner.must_C_version
+ * call-seq:
+ * StringScanner.must_C_version -> self
*
- * This method is defined for backward compatibility.
+ * Returns +self+; defined for backward compatibility.
*/
+
+ /* :nodoc: */
static VALUE
strscan_s_mustc(VALUE self)
{
@@ -244,7 +372,30 @@ strscan_s_mustc(VALUE self)
}
/*
- * Reset the scan pointer (index 0) and clear matching data.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * reset -> self
+ *
+ * Sets both [byte position][2] and [character position][7] to zero,
+ * and clears [match values][9];
+ * returns +self+:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.exist?(/bar/) # => 6
+ * scanner.reset # => #<StringScanner 0/9 @ "fooba...">
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 0
+ * # charpos: 0
+ * # rest: "foobarbaz"
+ * # rest_size: 9
+ * # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
+ *
*/
static VALUE
strscan_reset(VALUE self)
@@ -258,11 +409,12 @@ strscan_reset(VALUE self)
}
/*
- * call-seq:
- * terminate
- * clear
+ * :markup: markdown
+ * :call-seq:
+ * terminate -> self
*
- * Set the scan pointer to the end of the string and clear matching data.
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/terminate.md
*/
static VALUE
strscan_terminate(VALUE self)
@@ -276,18 +428,21 @@ strscan_terminate(VALUE self)
}
/*
- * Equivalent to #terminate.
- * This method is obsolete; use #terminate instead.
- */
-static VALUE
-strscan_clear(VALUE self)
-{
- rb_warning("StringScanner#clear is obsolete; use #terminate instead");
- return strscan_terminate(self);
-}
-
-/*
- * Returns the string being scanned.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * string -> stored_string
+ *
+ * Returns the [stored string][1]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobar')
+ * scanner.string # => "foobar"
+ * scanner.concat('baz')
+ * scanner.string # => "foobarbaz"
+ * ```
+ *
*/
static VALUE
strscan_get_string(VALUE self)
@@ -299,38 +454,80 @@ strscan_get_string(VALUE self)
}
/*
- * call-seq: string=(str)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * string = other_string -> other_string
+ *
+ * Replaces the [stored string][1] with the given `other_string`:
+ *
+ * - Sets both [positions][11] to zero.
+ * - Clears [match values][9].
+ * - Returns `other_string`.
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobar')
+ * scanner.scan(/foo/)
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "bar"
+ * # rest_size: 3
+ * match_values_cleared?(scanner) # => false
+ *
+ * scanner.string = 'baz' # => "baz"
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 0
+ * # charpos: 0
+ * # rest: "baz"
+ * # rest_size: 3
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * Changes the string being scanned to +str+ and resets the scanner.
- * Returns +str+.
*/
static VALUE
strscan_set_string(VALUE self, VALUE str)
{
- struct strscanner *p;
+ struct strscanner *p = check_strscan(self);
- Data_Get_Struct(self, struct strscanner, p);
StringValue(str);
- p->str = rb_str_dup(str);
- rb_obj_freeze(p->str);
+ RB_OBJ_WRITE(self, &p->str, str);
p->curr = 0;
CLEAR_MATCH_STATUS(p);
return str;
}
/*
- * call-seq:
- * concat(str)
- * <<(str)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Appends +str+ to the string being scanned.
- * This method does not affect scan pointer.
+ * call-seq:
+ * concat(more_string) -> self
+ *
+ * - Appends the given `more_string`
+ * to the [stored string][1].
+ * - Returns `self`.
+ * - Does not affect the [positions][11]
+ * or [match values][9].
+ *
+ *
+ * ```rb
+ * scanner = StringScanner.new('foo')
+ * scanner.string # => "foo"
+ * scanner.terminate
+ * scanner.concat('barbaz') # => #<StringScanner 3/9 "foo" @ "barba...">
+ * scanner.string # => "foobarbaz"
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "barbaz"
+ * # rest_size: 6
+ * ```
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan(/Fri /)
- * s << " +1000 GMT"
- * s.string # -> "Fri Dec 12 1975 14:39 +1000 GMT"
- * s.scan(/Dec/) # -> "Dec"
*/
static VALUE
strscan_concat(VALUE self, VALUE str)
@@ -344,18 +541,12 @@ strscan_concat(VALUE self, VALUE str)
}
/*
- * Returns the position of the scan pointer. In the 'reset' position, this
- * value is zero. In the 'terminated' position (i.e. the string is exhausted),
- * this value is the length of the string.
- *
- * In short, it's a 0-based index into the string.
+ * :markup: markdown
+ * :call-seq:
+ * pos -> byte_position
*
- * s = StringScanner.new('test string')
- * s.pos # -> 0
- * s.scan_until /str/ # -> "test str"
- * s.pos # -> 8
- * s.terminate # -> #<StringScanner fin>
- * s.pos # -> 11
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/get_pos.md
*/
static VALUE
strscan_get_pos(VALUE self)
@@ -363,17 +554,35 @@ strscan_get_pos(VALUE self)
struct strscanner *p;
GET_SCANNER(self, p);
- return INT2FIX(p->curr);
+ return LONG2NUM(p->curr);
}
/*
- * call-seq: pos=(n)
+ * :markup: markdown
+ * :call-seq:
+ * charpos -> character_position
*
- * Modify the scan pointer.
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/get_charpos.md
+ */
+static VALUE
+strscan_get_charpos(VALUE self)
+{
+ struct strscanner *p;
+
+ GET_SCANNER(self, p);
+
+ return LONG2NUM(rb_enc_strlen(S_PBEG(p), CURPTR(p), rb_enc_get(p->str)));
+}
+
+/*
+ * :markup: markdown
+ * :call-seq:
+ * pos = n -> n
+ * pointer = n -> n
*
- * s = StringScanner.new('test string')
- * s.pos = 7 # -> 7
- * s.rest # -> "ring"
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/set_pos.md
*/
static VALUE
strscan_set_pos(VALUE self, VALUE v)
@@ -382,74 +591,225 @@ strscan_set_pos(VALUE self, VALUE v)
long i;
GET_SCANNER(self, p);
- i = NUM2INT(v);
+ i = NUM2LONG(v);
if (i < 0) i += S_LEN(p);
if (i < 0) rb_raise(rb_eRangeError, "index out of range");
if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
p->curr = i;
- return INT2NUM(i);
+ return LONG2NUM(i);
+}
+
+static inline UChar *
+match_target(struct strscanner *p)
+{
+ if (p->fixed_anchor_p) {
+ return (UChar *)S_PBEG(p);
+ }
+ else
+ {
+ return (UChar *)CURPTR(p);
+ }
+}
+
+static inline void
+set_registers(struct strscanner *p, size_t pos, size_t length)
+{
+ const int at = 0;
+ OnigRegion *regs = &(p->regs);
+ onig_region_clear(regs);
+ if (onig_region_set(regs, at, 0, 0)) return;
+ if (p->fixed_anchor_p) {
+ regs->beg[at] = pos + p->curr;
+ regs->end[at] = pos + p->curr + length;
+ }
+ else
+ {
+ regs->beg[at] = pos;
+ regs->end[at] = pos + length;
+ }
+}
+
+static inline void
+succ(struct strscanner *p)
+{
+ if (p->fixed_anchor_p) {
+ p->curr = p->regs.end[0];
+ }
+ else
+ {
+ p->curr += p->regs.end[0];
+ }
+}
+
+static inline long
+last_match_length(struct strscanner *p)
+{
+ if (p->fixed_anchor_p) {
+ return p->regs.end[0] - p->prev;
+ }
+ else
+ {
+ return p->regs.end[0];
+ }
+}
+
+static inline long
+adjust_register_position(struct strscanner *p, long position)
+{
+ if (p->fixed_anchor_p) {
+ return position;
+ }
+ else {
+ return p->prev + position;
+ }
+}
+
+/* rb_reg_onig_match is available in Ruby 3.3 and later. */
+#ifndef HAVE_RB_REG_ONIG_MATCH
+static OnigPosition
+rb_reg_onig_match(VALUE re, VALUE str,
+ OnigPosition (*match)(regex_t *reg, VALUE str, struct re_registers *regs, void *args),
+ void *args, struct re_registers *regs)
+{
+ OnigPosition result;
+ regex_t *reg = rb_reg_prepare_re(re, str);
+
+ bool tmpreg = reg != RREGEXP_PTR(re);
+ if (!tmpreg) RREGEXP(re)->usecnt++;
+
+ result = match(reg, str, regs, args);
+
+ if (!tmpreg) RREGEXP(re)->usecnt--;
+ if (tmpreg) {
+ if (RREGEXP(re)->usecnt) {
+ onig_free(reg);
+ }
+ else {
+ onig_free(RREGEXP_PTR(re));
+ RREGEXP_PTR(re) = reg;
+ }
+ }
+
+ if (result < 0) {
+ if (result != ONIG_MISMATCH) {
+ rb_raise(ScanError, "regexp buffer overflow");
+ }
+ }
+
+ return result;
+}
+#endif
+
+static OnigPosition
+strscan_match(regex_t *reg, VALUE str, struct re_registers *regs, void *args_ptr)
+{
+ struct strscanner *p = (struct strscanner *)args_ptr;
+
+ return onig_match(reg,
+ match_target(p),
+ (UChar* )(CURPTR(p) + S_RESTLEN(p)),
+ (UChar* )CURPTR(p),
+ regs,
+ ONIG_OPTION_NONE);
+}
+
+static OnigPosition
+strscan_search(regex_t *reg, VALUE str, struct re_registers *regs, void *args_ptr)
+{
+ struct strscanner *p = (struct strscanner *)args_ptr;
+
+ return onig_search(reg,
+ match_target(p),
+ (UChar *)(CURPTR(p) + S_RESTLEN(p)),
+ (UChar *)CURPTR(p),
+ (UChar *)(CURPTR(p) + S_RESTLEN(p)),
+ regs,
+ ONIG_OPTION_NONE);
+}
+
+static void
+strscan_enc_check(VALUE str1, VALUE str2)
+{
+ if (RB_ENCODING_GET(str1) != RB_ENCODING_GET(str2)) {
+ rb_enc_check(str1, str2);
+ }
}
static VALUE
-strscan_do_scan(VALUE self, VALUE regex, int succptr, int getstr, int headonly)
+strscan_do_scan(VALUE self, VALUE pattern, int succptr, int getstr, int headonly)
{
struct strscanner *p;
- int ret;
- Check_Type(regex, T_REGEXP);
GET_SCANNER(self, p);
CLEAR_MATCH_STATUS(p);
if (S_RESTLEN(p) < 0) {
return Qnil;
}
- if (headonly) {
- ret = re_match(RREGEXP(regex)->ptr,
- CURPTR(p), S_RESTLEN(p),
- 0,
- &(p->regs));
+
+ if (RB_TYPE_P(pattern, T_REGEXP)) {
+ OnigPosition ret;
+ RB_OBJ_WRITE(self, &p->regex, pattern);
+ ret = rb_reg_onig_match(p->regex,
+ p->str,
+ headonly ? strscan_match : strscan_search,
+ (void *)p,
+ &(p->regs));
+
+ if (ret == ONIG_MISMATCH) {
+ return Qnil;
+ }
}
else {
- ret = re_search(RREGEXP(regex)->ptr,
- CURPTR(p), S_RESTLEN(p),
- 0,
- S_RESTLEN(p),
- &(p->regs));
- }
-
- if (ret == -2) rb_raise(ScanError, "regexp buffer overflow");
- if (ret < 0) {
- /* not matched */
- return Qnil;
+ StringValue(pattern);
+ if (S_RESTLEN(p) < RSTRING_LEN(pattern)) {
+ strscan_enc_check(p->str, pattern);
+ return Qnil;
+ }
+
+ if (headonly) {
+ strscan_enc_check(p->str, pattern);
+
+ if (memcmp(CURPTR(p), RSTRING_PTR(pattern), RSTRING_LEN(pattern)) != 0) {
+ return Qnil;
+ }
+ set_registers(p, 0, RSTRING_LEN(pattern));
+ }
+ else {
+ rb_encoding *enc = rb_enc_check(p->str, pattern);
+ long pos = rb_memsearch(RSTRING_PTR(pattern), RSTRING_LEN(pattern),
+ CURPTR(p), S_RESTLEN(p), enc);
+ if (pos == -1) {
+ return Qnil;
+ }
+ set_registers(p, pos, RSTRING_LEN(pattern));
+ }
}
MATCHED(p);
p->prev = p->curr;
+
if (succptr) {
- p->curr += p->regs.end[0];
- }
- if (getstr) {
- return extract_beg_len(p, p->prev, p->regs.end[0]);
+ succ(p);
}
- else {
- return INT2FIX(p->regs.end[0]);
+ {
+ const long length = last_match_length(p);
+ if (getstr) {
+ return extract_beg_len(p, p->prev, length);
+ }
+ else {
+ return INT2FIX(length);
+ }
}
}
/*
- * call-seq: scan(pattern) => String
- *
- * Tries to match with +pattern+ at the current position. If there's a match,
- * the scanner advances the "scan pointer" and returns the matched string.
- * Otherwise, the scanner returns +nil+.
- *
- * s = StringScanner.new('test string')
- * p s.scan(/\w+/) # -> "test"
- * p s.scan(/\w+/) # -> nil
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\w+/) # -> "string"
- * p s.scan(/./) # -> nil
+ * :markup: markdown
+ * :call-seq:
+ * scan(pattern) -> substring or nil
*
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/scan.md
*/
static VALUE
strscan_scan(VALUE self, VALUE re)
@@ -458,15 +818,60 @@ strscan_scan(VALUE self, VALUE re)
}
/*
- * call-seq: match?(pattern)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Tests whether the given +pattern+ is matched from the current scan pointer.
- * Returns the length of the match, or +nil+. The scan pointer is not advanced.
+ * call-seq:
+ * match?(pattern) -> match_size or nil
+ *
+ * Attempts to [match][17] the given `pattern`
+ * at the beginning of the [target substring][3];
+ * does not modify the [positions][11].
+ *
+ * If the match succeeds:
+ *
+ * - Sets [match values][9].
+ * - Returns the size in bytes of the matched substring.
+ *
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.pos = 3
+ * scanner.match?(/bar/) => 3
+ * put_match_values(scanner)
+ * # Basic match values:
+ * # matched?: true
+ * # matched_size: 3
+ * # pre_match: "foo"
+ * # matched : "bar"
+ * # post_match: "baz"
+ * # Captured match values:
+ * # size: 1
+ * # captures: []
+ * # named_captures: {}
+ * # values_at: ["bar", nil]
+ * # []:
+ * # [0]: "bar"
+ * # [1]: nil
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "barbaz"
+ * # rest_size: 6
+ * ```
+ *
+ * If the match fails:
+ *
+ * - Clears match values.
+ * - Returns `nil`.
+ * - Does not increment positions.
+ *
+ * ```rb
+ * scanner.match?(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * s = StringScanner.new('test string')
- * p s.match?(/\w+/) # -> 4
- * p s.match?(/\w+/) # -> 4
- * p s.match?(/\s+/) # -> nil
*/
static VALUE
strscan_match_p(VALUE self, VALUE re)
@@ -475,21 +880,12 @@ strscan_match_p(VALUE self, VALUE re)
}
/*
- * call-seq: skip(pattern)
- *
- * Attempts to skip over the given +pattern+ beginning with the scan pointer.
- * If it matches, the scan pointer is advanced to the end of the match, and the
- * length of the match is returned. Otherwise, +nil+ is returned.
- *
- * It's similar to #scan, but without returning the matched string.
- *
- * s = StringScanner.new('test string')
- * p s.skip(/\w+/) # -> 4
- * p s.skip(/\w+/) # -> nil
- * p s.skip(/\s+/) # -> 1
- * p s.skip(/\w+/) # -> 6
- * p s.skip(/./) # -> nil
+ * :markup: markdown
+ * call-seq:
+ * skip(pattern) -> match_size or nil
*
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/skip.md
*/
static VALUE
strscan_skip(VALUE self, VALUE re)
@@ -498,19 +894,59 @@ strscan_skip(VALUE self, VALUE re)
}
/*
- * call-seq: check(pattern)
- *
- * This returns the value that #scan would return, without advancing the scan
- * pointer. The match register is affected, though.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.check /Fri/ # -> "Fri"
- * s.pos # -> 0
- * s.matched # -> "Fri"
- * s.check /12/ # -> nil
- * s.matched # -> nil
+ * call-seq:
+ * check(pattern) -> matched_substring or nil
+ *
+ * Attempts to [match][17] the given `pattern`
+ * at the beginning of the [target substring][3];
+ * does not modify the [positions][11].
+ *
+ * If the match succeeds:
+ *
+ * - Returns the matched substring.
+ * - Sets all [match values][9].
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.pos = 3
+ * scanner.check('bar') # => "bar"
+ * put_match_values(scanner)
+ * # Basic match values:
+ * # matched?: true
+ * # matched_size: 3
+ * # pre_match: "foo"
+ * # matched : "bar"
+ * # post_match: "baz"
+ * # Captured match values:
+ * # size: 1
+ * # captures: []
+ * # named_captures: {}
+ * # values_at: ["bar", nil]
+ * # []:
+ * # [0]: "bar"
+ * # [1]: nil
+ * # => 0..1
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "barbaz"
+ * # rest_size: 6
+ * ```
+ *
+ * If the match fails:
+ *
+ * - Returns `nil`.
+ * - Clears all [match values][9].
+ *
+ * ```rb
+ * scanner.check(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * Mnemonic: it "checks" to see whether a #scan will return a value.
*/
static VALUE
strscan_check(VALUE self, VALUE re)
@@ -519,33 +955,37 @@ strscan_check(VALUE self, VALUE re)
}
/*
- * call-seq: scan_full(pattern, return_string_p, advance_pointer_p)
+ * call-seq:
+ * scan_full(pattern, advance_pointer_p, return_string_p) -> matched_substring or length or nil
+ *
+ * Equivalent to one of the following:
+ *
+ * - +advance_pointer_p+ +true+:
*
- * Tests whether the given +pattern+ is matched from the current scan pointer.
- * Returns the matched string if +return_string_p+ is true.
- * Advances the scan pointer if +advance_pointer_p+ is true.
- * The match register is affected.
+ * - +return_string_p+ +true+: StringScanner#scan(pattern).
+ * - +return_string_p+ +false+: StringScanner#skip(pattern).
+ *
+ * - +advance_pointer_p+ +false+:
+ *
+ * - +return_string_p+ +true+: StringScanner#check(pattern).
+ * - +return_string_p+ +false+: StringScanner#match?(pattern).
*
- * "full" means "#scan with full parameters".
*/
+
+ /* :nodoc: */
static VALUE
strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
return strscan_do_scan(self, re, RTEST(s), RTEST(f), 1);
}
-
/*
- * call-seq: scan_until(pattern)
+ * :markup: markdown
+ * :call-seq:
+ * scan_until(pattern) -> substring or nil
*
- * Scans the string _until_ the +pattern+ is matched. Returns the substring up
- * to and including the end of the match, advancing the scan pointer to that
- * location. If there is no match, +nil+ is returned.
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan_until(/1/) # -> "Fri Dec 1"
- * s.pre_match # -> "Fri Dec "
- * s.scan_until(/XYZ/) # -> nil
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/scan_until.md
*/
static VALUE
strscan_scan_until(VALUE self, VALUE re)
@@ -554,17 +994,61 @@ strscan_scan_until(VALUE self, VALUE re)
}
/*
- * call-seq: exist?(pattern)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Looks _ahead_ to see if the +pattern+ exists _anywhere_ in the string,
- * without advancing the scan pointer. This predicates whether a #scan_until
- * will return a value.
+ * call-seq:
+ * exist?(pattern) -> byte_offset or nil
+ *
+ * Attempts to [match][17] the given `pattern`
+ * anywhere (at any [position][2])
+ * n the [target substring][3];
+ * does not modify the [positions][11].
+ *
+ * If the match succeeds:
+ *
+ * - Returns a byte offset:
+ * the distance in bytes between the current [position][2]
+ * and the end of the matched substring.
+ * - Sets all [match values][9].
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbazbatbam')
+ * scanner.pos = 6
+ * scanner.exist?(/bat/) # => 6
+ * put_match_values(scanner)
+ * # Basic match values:
+ * # matched?: true
+ * # matched_size: 3
+ * # pre_match: "foobarbaz"
+ * # matched : "bat"
+ * # post_match: "bam"
+ * # Captured match values:
+ * # size: 1
+ * # captures: []
+ * # named_captures: {}
+ * # values_at: ["bat", nil]
+ * # []:
+ * # [0]: "bat"
+ * # [1]: nil
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 6
+ * # charpos: 6
+ * # rest: "bazbatbam"
+ * # rest_size: 9
+ * ```
+ *
+ * If the match fails:
+ *
+ * - Returns `nil`.
+ * - Clears all [match values][9].
+ *
+ * ```rb
+ * scanner.exist?(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * s = StringScanner.new('test string')
- * s.exist? /s/ # -> 3
- * s.scan /test/ # -> "test"
- * s.exist? /s/ # -> 6
- * s.exist? /e/ # -> nil
*/
static VALUE
strscan_exist_p(VALUE self, VALUE re)
@@ -573,20 +1057,12 @@ strscan_exist_p(VALUE self, VALUE re)
}
/*
- * call-seq: skip_until(pattern)
- *
- * Advances the scan pointer until +pattern+ is matched and consumed. Returns
- * the number of bytes advanced, or +nil+ if no match was found.
+ * :markup: markdown
+ * :call-seq:
+ * skip_until(pattern) -> matched_substring_size or nil
*
- * Look ahead to match +pattern+, and advance the scan pointer to the _end_
- * of the match. Return the number of characters advanced, or +nil+ if the
- * match was unsuccessful.
- *
- * It's similar to #scan_until, but without returning the intervening string.
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.skip_until /12/ # -> 10
- * s #
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/skip_until.md
*/
static VALUE
strscan_skip_until(VALUE self, VALUE re)
@@ -595,17 +1071,61 @@ strscan_skip_until(VALUE self, VALUE re)
}
/*
- * call-seq: check_until(pattern)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * This returns the value that #scan_until would return, without advancing the
- * scan pointer. The match register is affected, though.
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.check_until /12/ # -> "Fri Dec 12"
- * s.pos # -> 0
- * s.matched # -> 12
+ * call-seq:
+ * check_until(pattern) -> substring or nil
+ *
+ * Attempts to [match][17] the given `pattern`
+ * anywhere (at any [position][2])
+ * in the [target substring][3];
+ * does not modify the [positions][11].
+ *
+ * If the match succeeds:
+ *
+ * - Sets all [match values][9].
+ * - Returns the matched substring,
+ * which extends from the current [position][2]
+ * to the end of the matched substring.
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbazbatbam')
+ * scanner.pos = 6
+ * scanner.check_until(/bat/) # => "bazbat"
+ * put_match_values(scanner)
+ * # Basic match values:
+ * # matched?: true
+ * # matched_size: 3
+ * # pre_match: "foobarbaz"
+ * # matched : "bat"
+ * # post_match: "bam"
+ * # Captured match values:
+ * # size: 1
+ * # captures: []
+ * # named_captures: {}
+ * # values_at: ["bat", nil]
+ * # []:
+ * # [0]: "bat"
+ * # [1]: nil
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 6
+ * # charpos: 6
+ * # rest: "bazbatbam"
+ * # rest_size: 9
+ * ```
+ *
+ * If the match fails:
+ *
+ * - Clears all [match values][9].
+ * - Returns `nil`.
+ *
+ * ```rb
+ * scanner.check_until(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * Mnemonic: it "checks" to see whether a #scan_until will return a value.
*/
static VALUE
strscan_check_until(VALUE self, VALUE re)
@@ -614,48 +1134,49 @@ strscan_check_until(VALUE self, VALUE re)
}
/*
- * call-seq: search_full(pattern, return_string_p, advance_pointer_p)
+ * call-seq:
+ * search_full(pattern, advance_pointer_p, return_string_p) -> matched_substring or position_delta or nil
+ *
+ * Equivalent to one of the following:
+ *
+ * - +advance_pointer_p+ +true+:
+ *
+ * - +return_string_p+ +true+: StringScanner#scan_until(pattern).
+ * - +return_string_p+ +false+: StringScanner#skip_until(pattern).
+ *
+ * - +advance_pointer_p+ +false+:
+ *
+ * - +return_string_p+ +true+: StringScanner#check_until(pattern).
+ * - +return_string_p+ +false+: StringScanner#exist?(pattern).
*
- * Scans the string _until_ the +pattern+ is matched.
- * Returns the matched string if +return_string_p+ is true, otherwise
- * returns the number of bytes advanced.
- * Advances the scan pointer if +advance_pointer_p+, otherwise not.
- * This method does affect the match register.
*/
+
+ /* :nodoc: */
static VALUE
strscan_search_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
return strscan_do_scan(self, re, RTEST(s), RTEST(f), 0);
}
-/* DANGEROUS; need to synchronize with regex.c */
static void
adjust_registers_to_matched(struct strscanner *p)
{
- if (p->regs.allocated == 0) {
- p->regs.beg = ALLOC_N(int, RE_NREGS);
- p->regs.end = ALLOC_N(int, RE_NREGS);
- p->regs.allocated = RE_NREGS;
+ onig_region_clear(&(p->regs));
+ if (p->fixed_anchor_p) {
+ onig_region_set(&(p->regs), 0, (int)p->prev, (int)p->curr);
+ }
+ else {
+ onig_region_set(&(p->regs), 0, 0, (int)(p->curr - p->prev));
}
- p->regs.num_regs = 1;
- p->regs.beg[0] = 0;
- p->regs.end[0] = p->curr - p->prev;
}
/*
- * Scans one character and returns it.
- * This method is multi-byte character sensitive.
- * See also #get_byte.
+ * :markup: markdown
+ * :call-seq:
+ * getch -> character or nil
*
- * s = StringScanner.new('ab')
- * s.getch # => "a"
- * s.getch # => "b"
- * s.getch # => nil
- *
- * $KCODE = 'EUC'
- * s = StringScanner.new("\244\242")
- * s.getch # => "\244\242" # Japanese hira-kana "A" in EUC-JP
- * s.getch # => nil
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/getch.md
*/
static VALUE
strscan_getch(VALUE self)
@@ -667,71 +1188,108 @@ strscan_getch(VALUE self)
CLEAR_MATCH_STATUS(p);
if (EOS_P(p))
return Qnil;
- len = mbclen(*CURPTR(p));
- if (p->curr + len > S_LEN(p)) {
- len = S_LEN(p) - p->curr;
- }
+
+ len = rb_enc_mbclen(CURPTR(p), S_PEND(p), rb_enc_get(p->str));
+ len = minl(len, S_RESTLEN(p));
p->prev = p->curr;
p->curr += len;
MATCHED(p);
adjust_registers_to_matched(p);
- return extract_range(p, p->prev + p->regs.beg[0],
- p->prev + p->regs.end[0]);
+ return extract_range(p,
+ adjust_register_position(p, p->regs.beg[0]),
+ adjust_register_position(p, p->regs.end[0]));
}
/*
- * Scans one byte and returns it.
- * This method is NOT multi-byte character sensitive.
- * See also #getch.
+ * call-seq:
+ * scan_byte -> integer_byte or nil
+ *
+ * Scans one byte and returns it as an integer.
+ * This method is not multibyte character sensitive.
+ * See also: #getch.
*
- * s = StringScanner.new('ab')
- * s.get_byte # => "a"
- * s.get_byte # => "b"
- * s.get_byte # => nil
- *
- * s = StringScanner.new("\244\242")
- * s.get_byte # => "\244"
- * s.get_byte # => "\242"
- * s.get_byte # => nil
*/
static VALUE
-strscan_get_byte(VALUE self)
+strscan_scan_byte(VALUE self)
{
struct strscanner *p;
+ VALUE byte;
GET_SCANNER(self, p);
CLEAR_MATCH_STATUS(p);
- if (EOS_P(p)) {
+ if (EOS_P(p))
return Qnil;
- }
+
+ byte = INT2FIX((unsigned char)*CURPTR(p));
p->prev = p->curr;
p->curr++;
MATCHED(p);
adjust_registers_to_matched(p);
- return extract_range(p, p->prev + p->regs.beg[0],
- p->prev + p->regs.end[0]);
+ return byte;
}
/*
- * Equivalent to #get_byte.
- * This method is obsolete; use #get_byte instead.
+ * Peeks at the current byte and returns it as an integer.
+ *
+ * s = StringScanner.new('ab')
+ * s.peek_byte # => 97
*/
static VALUE
-strscan_getbyte(VALUE self)
+strscan_peek_byte(VALUE self)
{
- rb_warning("StringScanner#getbyte is obsolete; use #get_byte instead");
- return strscan_get_byte(self);
+ struct strscanner *p;
+
+ GET_SCANNER(self, p);
+ if (EOS_P(p))
+ return Qnil;
+
+ return INT2FIX((unsigned char)*CURPTR(p));
}
/*
- * call-seq: peek(len)
+ * :markup: markdown
+ * :call-seq:
+ * get_byte -> byte_as_character or nil
*
- * Extracts a string corresponding to <tt>string[pos,len]</tt>, without
- * advancing the scan pointer.
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/get_byte.md
+ */
+static VALUE
+strscan_get_byte(VALUE self)
+{
+ struct strscanner *p;
+
+ GET_SCANNER(self, p);
+ CLEAR_MATCH_STATUS(p);
+ if (EOS_P(p))
+ return Qnil;
+
+ p->prev = p->curr;
+ p->curr++;
+ MATCHED(p);
+ adjust_registers_to_matched(p);
+ return extract_range(p,
+ adjust_register_position(p, p->regs.beg[0]),
+ adjust_register_position(p, p->regs.end[0]));
+}
+
+/*
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * s = StringScanner.new('test string')
- * s.peek(7) # => "test st"
- * s.peek(7) # => "test st"
+ * call-seq:
+ * peek(length) -> substring
+ *
+ * Returns the substring `string[pos, length]`;
+ * does not update [match values][9] or [positions][11]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.pos = 3
+ * scanner.peek(3) # => "bar"
+ * scanner.terminate
+ * scanner.peek(3) # => ""
+ * ```
*
*/
static VALUE
@@ -741,37 +1299,170 @@ strscan_peek(VALUE self, VALUE vlen)
long len;
GET_SCANNER(self, p);
+
len = NUM2LONG(vlen);
- if (EOS_P(p)) {
- return infect(rb_str_new("", 0), p);
+ if (EOS_P(p))
+ return str_new(p, "", 0);
+
+ len = minl(len, S_RESTLEN(p));
+ return extract_beg_len(p, p->curr, len);
+}
+
+static VALUE
+strscan_parse_integer(struct strscanner *p, int base, long len)
+{
+ VALUE buffer_v, integer;
+
+ char *buffer = RB_ALLOCV_N(char, buffer_v, len + 1);
+
+ MEMCPY(buffer, CURPTR(p), char, len);
+ buffer[len] = '\0';
+ integer = rb_cstr2inum(buffer, base);
+ RB_ALLOCV_END(buffer_v);
+ p->curr += len;
+
+ MATCHED(p);
+ adjust_registers_to_matched(p);
+
+ return integer;
+}
+
+static inline bool
+strscan_ascii_compat_fastpath(VALUE str)
+{
+ int encindex = ENCODING_GET_INLINED(str);
+ /* The overwhelming majority of strings are in one of these 3 encodings. */
+ return encindex == utf8_encindex || encindex == binary_encindex || encindex == usascii_encindex;
+}
+
+static inline void
+strscan_must_ascii_compat(VALUE str)
+{
+ /* The overwhelming majority of strings are in one of these 3 encodings. */
+ if (RB_LIKELY(strscan_ascii_compat_fastpath(str))) {
+ return;
}
- if (p->curr + len > S_LEN(p)) {
- len = S_LEN(p) - p->curr;
+
+ rb_must_asciicompat(str);
+}
+
+/* :nodoc: */
+static VALUE
+strscan_scan_base10_integer(VALUE self)
+{
+ char *ptr;
+ long len = 0, remaining_len;
+ struct strscanner *p;
+
+ GET_SCANNER(self, p);
+ CLEAR_MATCH_STATUS(p);
+
+ strscan_must_ascii_compat(p->str);
+
+ ptr = CURPTR(p);
+
+ remaining_len = S_RESTLEN(p);
+
+ if (remaining_len <= 0) {
+ return Qnil;
}
- return extract_beg_len(p, p->curr, len);
+
+ if (ptr[len] == '-' || ptr[len] == '+') {
+ len++;
+ }
+
+ if (!rb_isdigit(ptr[len])) {
+ return Qnil;
+ }
+
+ p->prev = p->curr;
+
+ while (len < remaining_len && rb_isdigit(ptr[len])) {
+ len++;
+ }
+
+ return strscan_parse_integer(p, 10, len);
}
-/*
- * Equivalent to #peek.
- * This method is obsolete; use #peek instead.
- */
+/* :nodoc: */
static VALUE
-strscan_peep(VALUE self, VALUE vlen)
+strscan_scan_base16_integer(VALUE self)
{
- rb_warning("StringScanner#peep is obsolete; use #peek instead");
- return strscan_peek(self, vlen);
+ char *ptr;
+ long len = 0, remaining_len;
+ struct strscanner *p;
+
+ GET_SCANNER(self, p);
+ CLEAR_MATCH_STATUS(p);
+
+ strscan_must_ascii_compat(p->str);
+
+ ptr = CURPTR(p);
+
+ remaining_len = S_RESTLEN(p);
+
+ if (remaining_len <= 0) {
+ return Qnil;
+ }
+
+ if (ptr[len] == '-' || ptr[len] == '+') {
+ len++;
+ }
+
+ if ((remaining_len >= (len + 3)) && ptr[len] == '0' && ptr[len + 1] == 'x' && rb_isxdigit(ptr[len + 2])) {
+ len += 2;
+ }
+
+ if (len >= remaining_len || !rb_isxdigit(ptr[len])) {
+ return Qnil;
+ }
+
+ p->prev = p->curr;
+
+ while (len < remaining_len && rb_isxdigit(ptr[len])) {
+ len++;
+ }
+
+ return strscan_parse_integer(p, 16, len);
}
/*
- * Set the scan pointer to the previous position. Only one previous position is
- * remembered, and it changes with each scanning operation.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * unscan -> self
+ *
+ * Sets the [position][2] to its value previous to the recent successful
+ * [match][17] attempt:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.scan(/foo/)
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "barbaz"
+ * # rest_size: 6
+ * scanner.unscan
+ * # => #<StringScanner 0/9 @ "fooba...">
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 0
+ * # charpos: 0
+ * # rest: "foobarbaz"
+ * # rest_size: 9
+ * ```
+ *
+ * Raises an exception if match values are clear:
+ *
+ * ```rb
+ * scanner.scan(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * scanner.unscan # Raises StringScanner::Error.
+ * ```
*
- * s = StringScanner.new('test string')
- * s.scan(/\w+/) # => "test"
- * s.unscan
- * s.scan(/../) # => "te"
- * s.scan(/\d/) # => nil
- * s.unscan # ScanError: unscan failed: previous match had failed
*/
static VALUE
strscan_unscan(VALUE self)
@@ -779,25 +1470,45 @@ strscan_unscan(VALUE self)
struct strscanner *p;
GET_SCANNER(self, p);
- if (! MATCHED_P(p)) {
- rb_raise(ScanError, "unscan failed: previous match had failed");
- }
+ if (! MATCHED_P(p))
+ rb_raise(ScanError, "unscan failed: previous match record not exist");
p->curr = p->prev;
CLEAR_MATCH_STATUS(p);
return self;
}
/*
- * Returns +true+ iff the scan pointer is at the beginning of the line.
- *
- * s = StringScanner.new("test\ntest\n")
- * s.bol? # => true
- * s.scan(/te/)
- * s.bol? # => false
- * s.scan(/st\n/)
- * s.bol? # => true
- * s.terminate
- * s.bol? # => true
+ *
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * beginning_of_line? -> true or false
+ *
+ * Returns whether the [position][2] is at the beginning of a line;
+ * that is, at the beginning of the [stored string][1]
+ * or immediately after a newline:
+ *
+ * scanner = StringScanner.new(MULTILINE_TEXT)
+ * scanner.string
+ * # => "Go placidly amid the noise and haste,\nand remember what peace there may be in silence.\n"
+ * scanner.pos # => 0
+ * scanner.beginning_of_line? # => true
+ *
+ * scanner.scan_until(/,/) # => "Go placidly amid the noise and haste,"
+ * scanner.beginning_of_line? # => false
+ *
+ * scanner.scan(/\n/) # => "\n"
+ * scanner.beginning_of_line? # => true
+ *
+ * scanner.terminate
+ * scanner.beginning_of_line? # => true
+ *
+ * scanner.concat('x')
+ * scanner.terminate
+ * scanner.beginning_of_line? # => false
+ *
+ * StringScanner#bol? is an alias for StringScanner#beginning_of_line?.
*/
static VALUE
strscan_bol_p(VALUE self)
@@ -811,14 +1522,24 @@ strscan_bol_p(VALUE self)
}
/*
- * Returns +true+ if the scan pointer is at the end of the string.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * eos? -> true or false
+ *
+ * Returns whether the [position][2]
+ * is at the end of the [stored string][1]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.eos? # => false
+ * pos = 3
+ * scanner.eos? # => false
+ * scanner.terminate
+ * scanner.eos? # => true
+ * ```
*
- * s = StringScanner.new('test string')
- * p s.eos? # => false
- * s.scan(/test/)
- * p s.eos? # => false
- * s.terminate
- * p s.eos? # => true
*/
static VALUE
strscan_eos_p(VALUE self)
@@ -830,24 +1551,18 @@ strscan_eos_p(VALUE self)
}
/*
- * Equivalent to #eos?.
- * This method is obsolete, use #eos? instead.
- */
-static VALUE
-strscan_empty_p(VALUE self)
-{
- rb_warning("StringScanner#empty? is obsolete; use #eos? instead");
- return strscan_eos_p(self);
-}
-
-/*
- * Returns true iff there is more data in the string. See #eos?.
- * This method is obsolete; use #eos? instead.
+ * call-seq:
+ * rest?
+ *
+ * Returns true if and only if there is more data in the string. See #eos?.
*
* s = StringScanner.new('test string')
- * s.eos? # These two
- * s.rest? # are opposites.
+ * # These two are opposites
+ * s.eos? # => false
+ * s.rest? # => true
*/
+
+ /* :nodoc: */
static VALUE
strscan_rest_p(VALUE self)
{
@@ -858,13 +1573,26 @@ strscan_rest_p(VALUE self)
}
/*
- * Returns +true+ iff the last match was successful.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * matched? -> true or false
+ *
+ * Returns `true` of the most recent [match attempt][17] was successful,
+ * `false` otherwise;
+ * see [Basic Matched Values][18]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.matched? # => false
+ * scanner.pos = 3
+ * scanner.exist?(/baz/) # => 6
+ * scanner.matched? # => true
+ * scanner.exist?(/nope/) # => nil
+ * scanner.matched? # => false
+ * ```
*
- * s = StringScanner.new('test string')
- * s.match?(/\w+/) # => 4
- * s.matched? # => true
- * s.match?(/\d+/) # => nil
- * s.matched? # => false
*/
static VALUE
strscan_matched_p(VALUE self)
@@ -876,11 +1604,27 @@ strscan_matched_p(VALUE self)
}
/*
- * Returns the last matched string.
- *
- * s = StringScanner.new('test string')
- * s.match?(/\w+/) # -> 4
- * s.matched # -> "test"
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * matched -> matched_substring or nil
+ *
+ * Returns the matched substring from the most recent [match][17] attempt
+ * if it was successful,
+ * or `nil` otherwise;
+ * see [Basic Matched Values][18]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.matched # => nil
+ * scanner.pos = 3
+ * scanner.match?(/bar/) # => 3
+ * scanner.matched # => "bar"
+ * scanner.match?(/nope/) # => nil
+ * scanner.matched # => nil
+ * ```
+ *
*/
static VALUE
strscan_matched(VALUE self)
@@ -889,20 +1633,35 @@ strscan_matched(VALUE self)
GET_SCANNER(self, p);
if (! MATCHED_P(p)) return Qnil;
-
- return extract_range(p, p->prev + p->regs.beg[0],
- p->prev + p->regs.end[0]);
+ return extract_range(p,
+ adjust_register_position(p, p->regs.beg[0]),
+ adjust_register_position(p, p->regs.end[0]));
}
/*
- * Returns the size of the most recent match (see #matched), or +nil+ if there
- * was no recent match.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * matched_size -> substring_size or nil
+ *
+ * Returns the size (in bytes) of the matched substring
+ * from the most recent match [match attempt][17] if it was successful,
+ * or `nil` otherwise;
+ * see [Basic Matched Values][18]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.matched_size # => nil
+ *
+ * pos = 3
+ * scanner.exist?(/baz/) # => 9
+ * scanner.matched_size # => 3
+ *
+ * scanner.exist?(/nope/) # => nil
+ * scanner.matched_size # => nil
+ * ```
*
- * s = StringScanner.new('test string')
- * s.check /\w+/ # -> "test"
- * s.matched_size # -> 4
- * s.check /\d+/ # -> nil
- * s.matched_size # -> nil
*/
static VALUE
strscan_matched_size(VALUE self)
@@ -911,34 +1670,127 @@ strscan_matched_size(VALUE self)
GET_SCANNER(self, p);
if (! MATCHED_P(p)) return Qnil;
+ return LONG2NUM(p->regs.end[0] - p->regs.beg[0]);
+}
- return INT2NUM(p->regs.end[0] - p->regs.beg[0]);
+static int
+name_to_backref_number(struct re_registers *regs, VALUE regexp, const char* name, const char* name_end, rb_encoding *enc)
+{
+ if (RTEST(regexp)) {
+ int num = onig_name_to_backref_number(RREGEXP_PTR(regexp),
+ (const unsigned char* )name,
+ (const unsigned char* )name_end,
+ regs);
+ if (num >= 1) {
+ return num;
+ }
+ }
+ rb_enc_raise(enc, rb_eIndexError, "undefined group name reference: %.*s",
+ rb_long2int(name_end - name), name);
}
/*
- * Equivalent to #matched_size.
- * This method is obsolete; use #matched_size instead.
+ * Resolve capture group index from Integer, Symbol, or String.
+ * Returns the resolved register index, or -1 if unmatched/out of range.
+ * For Symbol/String specifiers, raises IndexError if the named group
+ * does not exist.
*/
-static VALUE
-strscan_matchedsize(VALUE self)
+static long
+resolve_capture_index(struct strscanner *p, VALUE specifier)
{
- rb_warning("StringScanner#matchedsize is obsolete; use #matched_size instead");
- return strscan_matched_size(self);
+ const char *name;
+ long i;
+ if (! MATCHED_P(p)) return -1;
+ switch (TYPE(specifier)) {
+ case T_SYMBOL:
+ specifier = rb_sym2str(specifier);
+ /* fall through */
+ case T_STRING:
+ RSTRING_GETMEM(specifier, name, i);
+ i = name_to_backref_number(&(p->regs), p->regex, name, name + i,
+ rb_enc_get(specifier));
+ break;
+ default:
+ i = NUM2LONG(specifier);
+ }
+ if (i < 0)
+ i += p->regs.num_regs;
+ if (i < 0) return -1;
+ if (i >= p->regs.num_regs) return -1;
+ if (p->regs.beg[i] == -1) return -1;
+ return i;
}
/*
- * call-seq: [](n)
- *
- * Return the n-th subgroup in the most recent match.
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
- * s[0] # -> "Fri Dec 12 "
- * s[1] # -> "Fri"
- * s[2] # -> "Dec"
- * s[3] # -> "12"
- * s.post_match # -> "1975 14:39"
- * s.pre_match # -> ""
+ *
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * [](specifier) -> substring or nil
+ *
+ * Returns a captured substring or `nil`;
+ * see [Captured Match Values][13].
+ *
+ * When there are captures:
+ *
+ * ```rb
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * scanner.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
+ * ```
+ *
+ * - `specifier` zero: returns the entire matched substring:
+ *
+ * ```rb
+ * scanner[0] # => "Fri Dec 12 "
+ * scanner.pre_match # => ""
+ * scanner.post_match # => "1975 14:39"
+ * ```
+ *
+ * - `specifier` positive integer. returns the `n`th capture, or `nil` if out of range:
+ *
+ * ```rb
+ * scanner[1] # => "Fri"
+ * scanner[2] # => "Dec"
+ * scanner[3] # => "12"
+ * scanner[4] # => nil
+ * ```
+ *
+ * - `specifier` negative integer. counts backward from the last subgroup:
+ *
+ * ```rb
+ * scanner[-1] # => "12"
+ * scanner[-4] # => "Fri Dec 12 "
+ * scanner[-5] # => nil
+ * ```
+ *
+ * - `specifier` symbol or string. returns the named subgroup, or `nil` if no such:
+ *
+ * ```rb
+ * scanner[:wday] # => "Fri"
+ * scanner['wday'] # => "Fri"
+ * scanner[:month] # => "Dec"
+ * scanner[:day] # => "12"
+ * scanner[:nope] # => nil
+ * ```
+ *
+ * When there are no captures, only `[0]` returns non-`nil`:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.exist?(/bar/)
+ * scanner[0] # => "bar"
+ * scanner[1] # => nil
+ * ```
+ *
+ * For a failed match, even `[0]` returns `nil`:
+ *
+ * ```rb
+ * scanner.scan(/nope/) # => nil
+ * scanner[0] # => nil
+ * scanner[1] # => nil
+ * ```
+ *
*/
static VALUE
strscan_aref(VALUE self, VALUE idx)
@@ -947,27 +1799,240 @@ strscan_aref(VALUE self, VALUE idx)
long i;
GET_SCANNER(self, p);
- if (! MATCHED_P(p)) return Qnil;
-
- i = NUM2LONG(idx);
+ i = resolve_capture_index(p, idx);
+ if (i < 0) return Qnil;
+
+ return extract_range(p,
+ adjust_register_position(p, p->regs.beg[i]),
+ adjust_register_position(p, p->regs.end[i]));
+}
+
+/*
+ * :markup: markdown
+ *
+ * call-seq:
+ * integer_at(specifier, base=10) -> integer or nil
+ *
+ * Returns the captured substring at the given `specifier` as an Integer,
+ * following the behavior of `String#to_i(base)`.
+ *
+ * `specifier` can be an Integer (positive, negative, or zero), a Symbol,
+ * or a String for named capture groups.
+ *
+ * Returns `nil` if:
+ * - No match has been performed or the last match failed
+ * - The `specifier` is an Integer and is out of range
+ * - The group at `specifier` did not participate in the match
+ *
+ * Raises IndexError if `specifier` is a Symbol or String that does not
+ * correspond to a named capture group, consistent with
+ * `StringScanner#[]`.
+ *
+ * This is semantically equivalent to `self[specifier]&.to_i(base)`
+ * but avoids the allocation of a temporary String when possible.
+ *
+ * ```rb
+ * scanner = StringScanner.new("2024-06-15")
+ * scanner.scan(/(\d{4})-(\d{2})-(\d{2})/)
+ * scanner.integer_at(1) # => 2024
+ * scanner.integer_at(1, 16) # => 8228
+ * ```
+ */
+static VALUE
+strscan_integer_at(int argc, VALUE *argv, VALUE self)
+{
+ struct strscanner *p;
+ long i;
+ long beg, end, len;
+ const char *ptr;
+ VALUE rb_specifier;
+ VALUE rb_base;
+ int base = 10;
+
+ GET_SCANNER(self, p);
+ rb_scan_args(argc, argv, "11", &rb_specifier, &rb_base);
+ if (argc > 1)
+ base = NUM2INT(rb_base);
+ i = resolve_capture_index(p, rb_specifier);
if (i < 0)
- i += p->regs.num_regs;
- if (i < 0) return Qnil;
- if (i >= p->regs.num_regs) return Qnil;
- if (p->regs.beg[i] == -1) return Qnil;
+ return Qnil;
- return extract_range(p, p->prev + p->regs.beg[i],
- p->prev + p->regs.end[i]);
+ beg = adjust_register_position(p, p->regs.beg[i]);
+ end = adjust_register_position(p, p->regs.end[i]);
+ len = end - beg;
+ ptr = S_PBEG(p) + beg;
+#ifdef HAVE_RB_INT_PARSE_CSTR
+ {
+ /*
+ * Ruby 2.5 or later export the rb_int_parse_cstr() symbol but
+ * prototype definition isn't provided. Ruby 4.1 or later
+ * provide prototype definition.
+ */
+# ifndef RB_INT_PARSE_DEFAULT
+ VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp,
+ size_t *ndigits, int base, int flags);
+# define RB_INT_PARSE_DEFAULT 0x07
+# endif
+ char *endp;
+ return rb_int_parse_cstr(ptr, len, &endp, NULL, base,
+ RB_INT_PARSE_DEFAULT);
+ }
+#else
+ return rb_str_to_inum(rb_str_new(ptr, len), base, 0);
+#endif
}
/*
- * Return the <i><b>pre</b>-match</i> (in the regular expression sense) of the last scan.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * size -> captures_count
+ *
+ * Returns the count of captures if the most recent match attempt succeeded, `nil` otherwise;
+ * see [Captures Match Values][13]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * scanner.size # => nil
+ *
+ * pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
+ * scanner.match?(pattern)
+ * scanner.values_at(*0..scanner.size) # => ["Fri Dec 12 ", "Fri", "Dec", "12", nil]
+ * scanner.size # => 4
+ *
+ * scanner.match?(/nope/) # => nil
+ * scanner.size # => nil
+ * ```
+ *
+ */
+static VALUE
+strscan_size(VALUE self)
+{
+ struct strscanner *p;
+
+ GET_SCANNER(self, p);
+ if (! MATCHED_P(p)) return Qnil;
+ return INT2FIX(p->regs.num_regs);
+}
+
+/*
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * captures -> substring_array or nil
+ *
+ * Returns the array of [captured match values][13] at indexes `(1..)`
+ * if the most recent match attempt succeeded, or `nil` otherwise:
+ *
+ * ```rb
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * scanner.captures # => nil
+ *
+ * scanner.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
+ * scanner.captures # => ["Fri", "Dec", "12"]
+ * scanner.values_at(*0..4) # => ["Fri Dec 12 ", "Fri", "Dec", "12", nil]
+ *
+ * scanner.exist?(/Fri/)
+ * scanner.captures # => []
+ *
+ * scanner.scan(/nope/)
+ * scanner.captures # => nil
+ * ```
+ *
+ */
+static VALUE
+strscan_captures(VALUE self)
+{
+ struct strscanner *p;
+ int i, num_regs;
+ VALUE new_ary;
+
+ GET_SCANNER(self, p);
+ if (! MATCHED_P(p)) return Qnil;
+
+ num_regs = p->regs.num_regs;
+ new_ary = rb_ary_new2(num_regs);
+
+ for (i = 1; i < num_regs; i++) {
+ VALUE str;
+ if (p->regs.beg[i] == -1)
+ str = Qnil;
+ else
+ str = extract_range(p,
+ adjust_register_position(p, p->regs.beg[i]),
+ adjust_register_position(p, p->regs.end[i]));
+ rb_ary_push(new_ary, str);
+ }
+
+ return new_ary;
+}
+
+/*
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * values_at(*specifiers) -> array_of_captures or nil
+ *
+ * Returns an array of captured substrings, or `nil` of none.
+ *
+ * For each `specifier`, the returned substring is `[specifier]`;
+ * see #[].
+ *
+ * ```rb
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
+ * scanner.match?(pattern)
+ * scanner.values_at(*0..3) # => ["Fri Dec 12 ", "Fri", "Dec", "12"]
+ * scanner.values_at(*%i[wday month day]) # => ["Fri", "Dec", "12"]
+ * ```
+ *
+ */
+
+static VALUE
+strscan_values_at(int argc, VALUE *argv, VALUE self)
+{
+ struct strscanner *p;
+ long i;
+ VALUE new_ary;
+
+ GET_SCANNER(self, p);
+ if (! MATCHED_P(p)) return Qnil;
+
+ new_ary = rb_ary_new2(argc);
+ for (i = 0; i<argc; i++) {
+ rb_ary_push(new_ary, strscan_aref(self, argv[i]));
+ }
+
+ return new_ary;
+}
+
+/*
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * pre_match -> substring
+ *
+ * Returns the substring that precedes the matched substring
+ * from the most recent match attempt if it was successful,
+ * or `nil` otherwise;
+ * see [Basic Match Values][18]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.pre_match # => nil
+ *
+ * scanner.pos = 3
+ * scanner.exist?(/baz/) # => 6
+ * scanner.pre_match # => "foobar" # Substring of entire string, not just target string.
+ *
+ * scanner.exist?(/nope/) # => nil
+ * scanner.pre_match # => nil
+ * ```
*
- * s = StringScanner.new('test string')
- * s.scan(/\w+/) # -> "test"
- * s.scan(/\s+/) # -> " "
- * s.pre_match # -> "test"
- * s.post_match # -> "string"
*/
static VALUE
strscan_pre_match(VALUE self)
@@ -976,18 +2041,35 @@ strscan_pre_match(VALUE self)
GET_SCANNER(self, p);
if (! MATCHED_P(p)) return Qnil;
-
- return extract_range(p, 0, p->prev + p->regs.beg[0]);
+ return extract_range(p,
+ 0,
+ adjust_register_position(p, p->regs.beg[0]));
}
/*
- * Return the <i><b>post</b>-match</i> (in the regular expression sense) of the last scan.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * post_match -> substring
+ *
+ * Returns the substring that follows the matched substring
+ * from the most recent match attempt if it was successful,
+ * or `nil` otherwise;
+ * see [Basic Match Values][18]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.post_match # => nil
+ *
+ * scanner.pos = 3
+ * scanner.match?(/bar/) # => 3
+ * scanner.post_match # => "baz"
+ *
+ * scanner.match?(/nope/) # => nil
+ * scanner.post_match # => nil
+ * ```
*
- * s = StringScanner.new('test string')
- * s.scan(/\w+/) # -> "test"
- * s.scan(/\s+/) # -> " "
- * s.pre_match # -> "test"
- * s.post_match # -> "string"
*/
static VALUE
strscan_post_match(VALUE self)
@@ -996,13 +2078,30 @@ strscan_post_match(VALUE self)
GET_SCANNER(self, p);
if (! MATCHED_P(p)) return Qnil;
-
- return extract_range(p, p->prev + p->regs.end[0], S_LEN(p));
+ return extract_range(p,
+ adjust_register_position(p, p->regs.end[0]),
+ S_LEN(p));
}
/*
- * Returns the "rest" of the string (i.e. everything after the scan pointer).
- * If there is no more data (eos? = true), it returns <tt>""</tt>.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * rest -> target_substring
+ *
+ * Returns the 'rest' of the [stored string][1] (all after the current [position][2]),
+ * which is the [target substring][3]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.rest # => "foobarbaz"
+ * scanner.pos = 3
+ * scanner.rest # => "barbaz"
+ * scanner.terminate
+ * scanner.rest # => ""
+ * ```
+ *
*/
static VALUE
strscan_rest(VALUE self)
@@ -1011,13 +2110,32 @@ strscan_rest(VALUE self)
GET_SCANNER(self, p);
if (EOS_P(p)) {
- return infect(rb_str_new("", 0), p);
+ return str_new(p, "", 0);
}
return extract_range(p, p->curr, S_LEN(p));
}
/*
- * <tt>s.rest_size</tt> is equivalent to <tt>s.rest.size</tt>.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * rest_size -> integer
+ *
+ * Returns the size (in bytes) of the #rest of the [stored string][1]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.rest # => "foobarbaz"
+ * scanner.rest_size # => 9
+ * scanner.pos = 3
+ * scanner.rest # => "barbaz"
+ * scanner.rest_size # => 6
+ * scanner.terminate
+ * scanner.rest # => ""
+ * scanner.rest_size # => 0
+ * ```
+ *
*/
static VALUE
strscan_rest_size(VALUE self)
@@ -1029,110 +2147,202 @@ strscan_rest_size(VALUE self)
if (EOS_P(p)) {
return INT2FIX(0);
}
-
- i = S_LEN(p) - p->curr;
+ i = S_RESTLEN(p);
return INT2FIX(i);
}
-/*
- * <tt>s.restsize</tt> is equivalent to <tt>s.rest_size</tt>.
- * This method is obsolete; use #rest_size instead.
- */
-static VALUE
-strscan_restsize(VALUE self)
-{
- rb_warning("StringScanner#restsize is obsolete; use #rest_size instead");
- return strscan_rest_size(self);
-}
-
#define INSPECT_LENGTH 5
-#define BUFSIZE 256
/*
- * Returns a string that represents the StringScanner object, showing:
- * - the current position
- * - the size of the string
- * - the characters surrounding the scan pointer
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.inspect # -> '#<StringScanner 0/21 @ "Fri D...">'
- * s.scan_until /12/ # -> "Fri Dec 12"
- * s.inspect # -> '#<StringScanner 10/21 "...ec 12" @ " 1975...">'
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * inspect -> string
+ *
+ * Returns a string representation of `self` that may show:
+ *
+ * 1. The current [position][2].
+ * 2. The size (in bytes) of the [stored string][1].
+ * 3. The substring preceding the current position.
+ * 4. The substring following the current position (which is also the [target substring][3]).
+ *
+ * ```rb
+ * scanner = StringScanner.new("Fri Dec 12 1975 14:39")
+ * scanner.pos = 11
+ * scanner.inspect # => "#<StringScanner 11/21 \"...c 12 \" @ \"1975 ...\">"
+ * ```
+ *
+ * If at beginning-of-string, item 4 above (following substring) is omitted:
+ *
+ * ```rb
+ * scanner.reset
+ * scanner.inspect # => "#<StringScanner 0/21 @ \"Fri D...\">"
+ * ```
+ *
+ * If at end-of-string, all items above are omitted:
+ *
+ * ```rb
+ * scanner.terminate
+ * scanner.inspect # => "#<StringScanner fin>"
+ * ```
+ *
*/
static VALUE
strscan_inspect(VALUE self)
{
struct strscanner *p;
- char buf[BUFSIZE];
- long len;
VALUE a, b;
- Data_Get_Struct(self, struct strscanner, p);
+ p = check_strscan(self);
if (NIL_P(p->str)) {
- len = snprintf(buf, BUFSIZE, "#<%s (uninitialized)>",
- rb_class2name(CLASS_OF(self)));
- return infect(rb_str_new(buf, len), p);
+ a = rb_sprintf("#<%"PRIsVALUE" (uninitialized)>", rb_obj_class(self));
+ return a;
}
if (EOS_P(p)) {
- len = snprintf(buf, BUFSIZE, "#<%s fin>",
- rb_class2name(CLASS_OF(self)));
- return infect(rb_str_new(buf, len), p);
+ a = rb_sprintf("#<%"PRIsVALUE" fin>", rb_obj_class(self));
+ return a;
}
if (p->curr == 0) {
- b = inspect2(p);
- len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld @ %s>",
- rb_class2name(CLASS_OF(self)),
- p->curr, S_LEN(p),
- RSTRING(b)->ptr);
- return infect(rb_str_new(buf, len), p);
+ b = inspect2(p);
+ a = rb_sprintf("#<%"PRIsVALUE" %ld/%ld @ %"PRIsVALUE">",
+ rb_obj_class(self),
+ p->curr, S_LEN(p),
+ b);
+ return a;
}
a = inspect1(p);
b = inspect2(p);
- len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld %s @ %s>",
- rb_class2name(CLASS_OF(self)),
- p->curr, S_LEN(p),
- RSTRING(a)->ptr,
- RSTRING(b)->ptr);
- return infect(rb_str_new(buf, len), p);
+ a = rb_sprintf("#<%"PRIsVALUE" %ld/%ld %"PRIsVALUE" @ %"PRIsVALUE">",
+ rb_obj_class(self),
+ p->curr, S_LEN(p),
+ a, b);
+ return a;
}
static VALUE
inspect1(struct strscanner *p)
{
- char buf[BUFSIZE];
- char *bp = buf;
+ VALUE str;
long len;
if (p->curr == 0) return rb_str_new2("");
if (p->curr > INSPECT_LENGTH) {
- strcpy(bp, "..."); bp += 3;
- len = INSPECT_LENGTH;
+ str = rb_str_new_cstr("...");
+ len = INSPECT_LENGTH;
}
else {
- len = p->curr;
+ str = rb_str_new(0, 0);
+ len = p->curr;
}
- memcpy(bp, CURPTR(p) - len, len); bp += len;
- return rb_str_dump(rb_str_new(buf, bp - buf));
+ rb_str_cat(str, CURPTR(p) - len, len);
+ return rb_str_dump(str);
}
static VALUE
inspect2(struct strscanner *p)
{
- char buf[BUFSIZE];
- char *bp = buf;
+ VALUE str;
long len;
if (EOS_P(p)) return rb_str_new2("");
- len = S_LEN(p) - p->curr;
+ len = S_RESTLEN(p);
if (len > INSPECT_LENGTH) {
- len = INSPECT_LENGTH;
- memcpy(bp, CURPTR(p), len); bp += len;
- strcpy(bp, "..."); bp += 3;
+ str = rb_str_new(CURPTR(p), INSPECT_LENGTH);
+ rb_str_cat2(str, "...");
}
else {
- memcpy(bp, CURPTR(p), len); bp += len;
+ str = rb_str_new(CURPTR(p), len);
+ }
+ return rb_str_dump(str);
+}
+
+/*
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * fixed_anchor? -> true or false
+ *
+ * Returns whether the [fixed-anchor property][10] is set.
+ */
+static VALUE
+strscan_fixed_anchor_p(VALUE self)
+{
+ struct strscanner *p;
+ p = check_strscan(self);
+ return p->fixed_anchor_p ? Qtrue : Qfalse;
+}
+
+typedef struct {
+ VALUE self;
+ VALUE captures;
+} named_captures_data;
+
+static int
+named_captures_iter(const OnigUChar *name,
+ const OnigUChar *name_end,
+ int back_num,
+ int *back_refs,
+ OnigRegex regex,
+ void *arg)
+{
+ named_captures_data *data = arg;
+
+ VALUE key = rb_str_new((const char *)name, name_end - name);
+ VALUE value = RUBY_Qnil;
+ int i;
+ for (i = 0; i < back_num; i++) {
+ VALUE v = strscan_aref(data->self, INT2NUM(back_refs[i]));
+ if (!RB_NIL_P(v)) {
+ value = v;
+ }
}
- return rb_str_dump(rb_str_new(buf, bp - buf));
+ rb_hash_aset(data->captures, key, value);
+ return 0;
+}
+
+/*
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * named_captures -> hash
+ *
+ * Returns a hash of named captures for the most recent regexp match,
+ * or an empty hash if there are no named captures;
+ * see [Captured Match Values][13]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * scanner.named_captures # => {}
+ *
+ * pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
+ * scanner.match?(pattern)
+ * scanner.named_captures # => {"wday"=>"Fri", "month"=>"Dec", "day"=>"12"}
+ *
+ * scanner.string = 'nope'
+ * scanner.match?(pattern)
+ * scanner.named_captures # => {"wday"=>nil, "month"=>nil, "day"=>nil}
+ *
+ * scanner.match?(/nosuch/)
+ * scanner.named_captures # => {}
+ * ```
+ *
+ */
+static VALUE
+strscan_named_captures(VALUE self)
+{
+ struct strscanner *p;
+ named_captures_data data;
+ GET_SCANNER(self, p);
+ data.self = self;
+ data.captures = rb_hash_new();
+ if (!RB_NIL_P(p->regex)) {
+ onig_foreach_name(RREGEXP_PTR(p->regex), named_captures_iter, &data);
+ }
+
+ return data.captures;
}
/* =======================================================================
@@ -1140,118 +2350,41 @@ inspect2(struct strscanner *p)
======================================================================= */
/*
+ * Document-class: StringScanner::Error
+ *
+ * The error class for StringScanner.
+ * See StringScanner#unscan.
+ */
+
+/*
* Document-class: StringScanner
- *
- * StringScanner provides for lexical scanning operations on a String. Here is
- * an example of its usage:
- *
- * s = StringScanner.new('This is an example string')
- * s.eos? # -> false
- *
- * p s.scan(/\w+/) # -> "This"
- * p s.scan(/\w+/) # -> nil
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\s+/) # -> nil
- * p s.scan(/\w+/) # -> "is"
- * s.eos? # -> false
- *
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\w+/) # -> "an"
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\w+/) # -> "example"
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\w+/) # -> "string"
- * s.eos? # -> true
- *
- * p s.scan(/\s+/) # -> nil
- * p s.scan(/\w+/) # -> nil
- *
- * Scanning a string means remembering the position of a <i>scan pointer</i>,
- * which is just an index. The point of scanning is to move forward a bit at
- * a time, so matches are sought after the scan pointer; usually immediately
- * after it.
- *
- * Given the string "test string", here are the pertinent scan pointer
- * positions:
- *
- * t e s t s t r i n g
- * 0 1 2 ... 1
- * 0
- *
- * When you #scan for a pattern (a regular expression), the match must occur
- * at the character after the scan pointer. If you use #scan_until, then the
- * match can occur anywhere after the scan pointer. In both cases, the scan
- * pointer moves <i>just beyond</i> the last character of the match, ready to
- * scan again from the next character onwards. This is demonstrated by the
- * example above.
- *
- * == Method Categories
- *
- * There are other methods besides the plain scanners. You can look ahead in
- * the string without actually scanning. You can access the most recent match.
- * You can modify the string being scanned, reset or terminate the scanner,
- * find out or change the position of the scan pointer, skip ahead, and so on.
- *
- * === Advancing the Scan Pointer
- *
- * - #getch
- * - #get_byte
- * - #scan
- * - #scan_until
- * - #skip
- * - #skip_until
- *
- * === Looking Ahead
- *
- * - #check
- * - #check_until
- * - #exist?
- * - #match?
- * - #peek
- *
- * === Finding Where we Are
- *
- * - #beginning_of_line? (#bol?)
- * - #eos?
- * - #rest?
- * - #rest_size
- * - #pos
- *
- * === Setting Where we Are
- *
- * - #reset
- * - #terminate
- * - #pos=
- *
- * === Match Data
- *
- * - #matched
- * - #matched?
- * - #matched_size
- * - []
- * - #pre_match
- * - #post_match
- *
- * === Miscellaneous
- *
- * - <<
- * - #concat
- * - #string
- * - #string=
- * - #unscan
- *
- * There are aliases to several of the methods.
+ *
+ * :markup: markdown
+ *
+ * :include: strscan/link_refs.txt
+ * :include: strscan/strscan.md
+ *
*/
void
Init_strscan(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
+#undef rb_intern
ID id_scanerr = rb_intern("ScanError");
VALUE tmp;
+ usascii_encindex = rb_usascii_encindex();
+ utf8_encindex = rb_utf8_encindex();
+ binary_encindex = rb_ascii8bit_encindex();
+
StringScanner = rb_define_class("StringScanner", rb_cObject);
ScanError = rb_define_class_under(StringScanner, "Error", rb_eStandardError);
if (!rb_const_defined(rb_cObject, id_scanerr)) {
rb_const_set(rb_cObject, id_scanerr, ScanError);
+ rb_deprecate_constant(rb_cObject, "ScanError");
}
tmp = rb_str_new2(STRSCAN_VERSION);
rb_obj_freeze(tmp);
@@ -1259,20 +2392,21 @@ Init_strscan(void)
tmp = rb_str_new2("$Id$");
rb_obj_freeze(tmp);
rb_const_set(StringScanner, rb_intern("Id"), tmp);
-
+ rb_deprecate_constant(StringScanner, "Id");
+
rb_define_alloc_func(StringScanner, strscan_s_allocate);
rb_define_private_method(StringScanner, "initialize", strscan_initialize, -1);
rb_define_private_method(StringScanner, "initialize_copy", strscan_init_copy, 1);
rb_define_singleton_method(StringScanner, "must_C_version", strscan_s_mustc, 0);
rb_define_method(StringScanner, "reset", strscan_reset, 0);
rb_define_method(StringScanner, "terminate", strscan_terminate, 0);
- rb_define_method(StringScanner, "clear", strscan_clear, 0);
rb_define_method(StringScanner, "string", strscan_get_string, 0);
rb_define_method(StringScanner, "string=", strscan_set_string, 1);
rb_define_method(StringScanner, "concat", strscan_concat, 1);
rb_define_method(StringScanner, "<<", strscan_concat, 1);
rb_define_method(StringScanner, "pos", strscan_get_pos, 0);
rb_define_method(StringScanner, "pos=", strscan_set_pos, 1);
+ rb_define_method(StringScanner, "charpos", strscan_get_charpos, 0);
rb_define_method(StringScanner, "pointer", strscan_get_pos, 0);
rb_define_method(StringScanner, "pointer=", strscan_set_pos, 1);
@@ -1290,29 +2424,37 @@ Init_strscan(void)
rb_define_method(StringScanner, "getch", strscan_getch, 0);
rb_define_method(StringScanner, "get_byte", strscan_get_byte, 0);
- rb_define_method(StringScanner, "getbyte", strscan_getbyte, 0);
+ rb_define_method(StringScanner, "scan_byte", strscan_scan_byte, 0);
rb_define_method(StringScanner, "peek", strscan_peek, 1);
- rb_define_method(StringScanner, "peep", strscan_peep, 1);
+ rb_define_method(StringScanner, "peek_byte", strscan_peek_byte, 0);
+
+ rb_define_private_method(StringScanner, "scan_base10_integer", strscan_scan_base10_integer, 0);
+ rb_define_private_method(StringScanner, "scan_base16_integer", strscan_scan_base16_integer, 0);
rb_define_method(StringScanner, "unscan", strscan_unscan, 0);
rb_define_method(StringScanner, "beginning_of_line?", strscan_bol_p, 0);
rb_alias(StringScanner, rb_intern("bol?"), rb_intern("beginning_of_line?"));
rb_define_method(StringScanner, "eos?", strscan_eos_p, 0);
- rb_define_method(StringScanner, "empty?", strscan_empty_p, 0);
rb_define_method(StringScanner, "rest?", strscan_rest_p, 0);
rb_define_method(StringScanner, "matched?", strscan_matched_p, 0);
rb_define_method(StringScanner, "matched", strscan_matched, 0);
rb_define_method(StringScanner, "matched_size", strscan_matched_size, 0);
- rb_define_method(StringScanner, "matchedsize", strscan_matchedsize, 0);
rb_define_method(StringScanner, "[]", strscan_aref, 1);
+ rb_define_method(StringScanner, "integer_at", strscan_integer_at, -1);
rb_define_method(StringScanner, "pre_match", strscan_pre_match, 0);
rb_define_method(StringScanner, "post_match", strscan_post_match, 0);
+ rb_define_method(StringScanner, "size", strscan_size, 0);
+ rb_define_method(StringScanner, "captures", strscan_captures, 0);
+ rb_define_method(StringScanner, "values_at", strscan_values_at, -1);
rb_define_method(StringScanner, "rest", strscan_rest, 0);
rb_define_method(StringScanner, "rest_size", strscan_rest_size, 0);
- rb_define_method(StringScanner, "restsize", strscan_restsize, 0);
rb_define_method(StringScanner, "inspect", strscan_inspect, 0);
+
+ rb_define_method(StringScanner, "fixed_anchor?", strscan_fixed_anchor_p, 0);
+
+ rb_define_method(StringScanner, "named_captures", strscan_named_captures, 0);
}
diff --git a/ext/strscan/strscan.gemspec b/ext/strscan/strscan.gemspec
new file mode 100644
index 0000000000..a51285fa7e
--- /dev/null
+++ b/ext/strscan/strscan.gemspec
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+#
+source_version = ["", "ext/strscan/"].find do |dir|
+ begin
+ break File.open(File.join(__dir__, "#{dir}strscan.c")) {|f|
+ f.gets("\n#define STRSCAN_VERSION ")
+ f.gets[/\s*"(.+)"/, 1]
+ }
+ rescue Errno::ENOENT
+ end
+end
+
+Gem::Specification.new do |s|
+ s.name = "strscan"
+ s.version = source_version
+ s.summary = "Provides lexical scanning operations on a String."
+ s.description = "Provides lexical scanning operations on a String."
+
+ files = %w[
+ COPYING
+ LICENSE.txt
+ lib/strscan.rb
+ lib/strscan/strscan.rb
+ lib/strscan/truffleruby.rb
+ ]
+
+ s.require_paths = %w{lib}
+
+ if RUBY_ENGINE == "jruby"
+ files << "lib/strscan.jar"
+ s.platform = "java"
+ else
+ files << "ext/strscan/extconf.rb"
+ files << "ext/strscan/strscan.c"
+ s.rdoc_options << "-idoc"
+ s.extra_rdoc_files = [
+ ".rdoc_options",
+ *Dir.glob("doc/strscan/**/*")
+ ]
+ s.extensions = %w{ext/strscan/extconf.rb}
+ end
+ s.files = files
+ s.required_ruby_version = ">= 2.4.0"
+
+ s.authors = ["Minero Aoki", "Sutou Kouhei", "Charles Oliver Nutter"]
+ s.email = [nil, "kou@cozmixng.org", "headius@headius.com"]
+ s.homepage = "https://github.com/ruby/strscan"
+ s.licenses = ["Ruby", "BSD-2-Clause"]
+end
diff --git a/ext/syck/.cvsignore b/ext/syck/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/syck/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/syck/bytecode.c b/ext/syck/bytecode.c
deleted file mode 100644
index 567aaf52a8..0000000000
--- a/ext/syck/bytecode.c
+++ /dev/null
@@ -1,1166 +0,0 @@
-/* Generated by re2c 0.9.10 on Mon Sep 19 23:21:26 2005 */
-#line 1 "bytecode.re"
-/*
- * bytecode.re
- *
- * $Author$
- * $Date$
- *
- * Copyright (C) 2003 why the lucky stiff
- */
-#include "ruby.h"
-#include "syck.h"
-#include "gram.h"
-
-#define QUOTELEN 128
-
-/*
- * They do my bidding...
- */
-#define YYCTYPE char
-#define YYCURSOR parser->cursor
-#define YYMARKER parser->marker
-#define YYLIMIT parser->limit
-#define YYTOKEN parser->token
-#define YYTOKTMP parser->toktmp
-#define YYLINEPTR parser->lineptr
-#define YYLINECTPTR parser->linectptr
-#define YYLINE parser->linect
-#define YYFILL(n) syck_parser_read(parser)
-
-extern SyckParser *syck_parser_ptr;
-
-char *get_inline( SyckParser *parser );
-
-/*
- * Repositions the cursor at `n' offset from the token start.
- * Only works in `Header' and `Document' sections.
- */
-#define YYPOS(n) YYCURSOR = YYTOKEN + n
-
-/*
- * Track line numbers
- */
-#define CHK_NL(ptr) if ( *( ptr - 1 ) == '\n' && ptr > YYLINECTPTR ) { YYLINEPTR = ptr; YYLINE++; YYLINECTPTR = YYLINEPTR; }
-
-/*
- * I like seeing the level operations as macros...
- */
-#define ADD_LEVEL(len, status) syck_parser_add_level( parser, len, status )
-#define POP_LEVEL() syck_parser_pop_level( parser )
-#define CURRENT_LEVEL() syck_parser_current_level( parser )
-
-/*
- * Force a token next time around sycklex()
- */
-#define FORCE_NEXT_TOKEN(tok) parser->force_token = tok;
-
-/*
- * Adding levels in bytecode requires us to make sure
- * we've got all our tokens worked out.
- */
-#define ADD_BYTE_LEVEL(lvl, len, s ) \
- switch ( lvl->status ) \
- { \
- case syck_lvl_seq: \
- lvl->ncount++; \
- ADD_LEVEL(len, syck_lvl_open); \
- YYPOS(0); \
- return '-'; \
- \
- case syck_lvl_map: \
- lvl->ncount++; \
- ADD_LEVEL(len, s); \
- break; \
- \
- case syck_lvl_open: \
- lvl->status = s; \
- break; \
- \
- default: \
- ADD_LEVEL(len, s); \
- break; \
- }
-
-/*
- * Nice little macro to ensure we're YAML_IOPENed to the current level.
- * * Only use this macro in the "Document" section *
- */
-#define ENSURE_YAML_IOPEN(last_lvl, lvl_type, to_len, reset) \
- if ( last_lvl->spaces < to_len ) \
- { \
- if ( last_lvl->status == syck_lvl_iseq || last_lvl->status == syck_lvl_imap ) \
- { \
- goto Document; \
- } \
- else \
- { \
- ADD_LEVEL( to_len, lvl_type ); \
- if ( reset == 1 ) YYPOS(0); \
- return YAML_IOPEN; \
- } \
- }
-
-/*
- * Nice little macro to ensure closure of levels.
- * * Only use this macro in the "Document" section *
- */
-#define ENSURE_YAML_IEND(last_lvl, to_len) \
- if ( last_lvl->spaces > to_len ) \
- { \
- syck_parser_pop_level( parser ); \
- YYPOS(0); \
- return YAML_IEND; \
- }
-
-/*
- * Concatenates string items and manages allocation
- * to the string
- */
-#define CAT(s, c, i, l) \
- { \
- if ( i + 1 >= c ) \
- { \
- c += QUOTELEN; \
- S_REALLOC_N( s, char, c ); \
- } \
- s[i++] = l; \
- s[i] = '\0'; \
- }
-
-/*
- * Parser for standard YAML Bytecode [UTF-8]
- */
-int
-sycklex_bytecode_utf8( YYSTYPE *sycklval, SyckParser *parser )
-{
- SyckLevel *lvl;
- syck_parser_ptr = parser;
- if ( YYCURSOR == NULL )
- {
- syck_parser_read( parser );
- }
-
- if ( parser->force_token != 0 )
- {
- int t = parser->force_token;
- parser->force_token = 0;
- return t;
- }
-
-#line 172 "bytecode.re"
-
-
- lvl = CURRENT_LEVEL();
- if ( lvl->status == syck_lvl_doc )
- {
- goto Document;
- }
-
-/* Header: */
-
- YYTOKEN = YYCURSOR;
-
-
-#line 165 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy0;
- ++YYCURSOR;
-yy0:
- if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy2;
- case 'D': goto yy3;
- default: goto yy5;
- }
-yy2: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy4;
- }
-yy3: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 0x0A: goto yy6;
- case 0x0D: goto yy8;
- default: goto yy4;
- }
-yy4:
-#line 199 "bytecode.re"
-{ YYPOS(0);
- goto Document;
- }
-#line 195 "<stdout>"
-yy5: yych = *++YYCURSOR;
- goto yy4;
-yy6: ++YYCURSOR;
- goto yy7;
-yy7:
-#line 186 "bytecode.re"
-{ if ( lvl->status == syck_lvl_header )
- {
- CHK_NL(YYCURSOR);
- goto Directive;
- }
- else
- {
- ENSURE_YAML_IEND(lvl, -1);
- YYPOS(0);
- return 0;
- }
- }
-#line 214 "<stdout>"
-yy8: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy6;
- default: goto yy2;
- }
-}
-#line 203 "bytecode.re"
-
-
-Document:
- {
- lvl = CURRENT_LEVEL();
- if ( lvl->status == syck_lvl_header )
- {
- lvl->status = syck_lvl_doc;
- }
-
- YYTOKEN = YYCURSOR;
-
-
-#line 235 "<stdout>"
-{
- YYCTYPE yych;
- goto yy9;
- ++YYCURSOR;
-yy9:
- if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy30;
- case 0x0A: goto yy27;
- case 0x0D: goto yy29;
- case 'A': goto yy19;
- case 'D': goto yy12;
- case 'E': goto yy16;
- case 'M': goto yy14;
- case 'P': goto yy13;
- case 'Q': goto yy15;
- case 'R': goto yy21;
- case 'S': goto yy17;
- case 'T': goto yy23;
- case 'c': goto yy25;
- default: goto yy11;
- }
-yy11:yy12: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy41;
- case 0x0D: goto yy44;
- default: goto yy11;
- }
-yy13: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy41;
- case 0x0D: goto yy43;
- default: goto yy11;
- }
-yy14: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy38;
- case 0x0D: goto yy40;
- default: goto yy11;
- }
-yy15: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy35;
- case 0x0D: goto yy37;
- default: goto yy11;
- }
-yy16: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy32;
- case 0x0D: goto yy34;
- default: goto yy11;
- }
-yy17: ++YYCURSOR;
- goto yy18;
-yy18:
-#line 288 "bytecode.re"
-{ ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_str);
- goto Scalar;
- }
-#line 296 "<stdout>"
-yy19: ++YYCURSOR;
- goto yy20;
-yy20:
-#line 292 "bytecode.re"
-{ ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_open);
- sycklval->name = get_inline( parser );
- syck_hdlr_remove_anchor( parser, sycklval->name );
- CHK_NL(YYCURSOR);
- return YAML_ANCHOR;
- }
-#line 307 "<stdout>"
-yy21: ++YYCURSOR;
- goto yy22;
-yy22:
-#line 299 "bytecode.re"
-{ ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_str);
- sycklval->name = get_inline( parser );
- POP_LEVEL();
- if ( *( YYCURSOR - 1 ) == '\n' ) YYCURSOR--;
- return YAML_ALIAS;
- }
-#line 318 "<stdout>"
-yy23: ++YYCURSOR;
- goto yy24;
-yy24:
-#line 306 "bytecode.re"
-{ char *qstr;
- ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_open);
- qstr = get_inline( parser );
- CHK_NL(YYCURSOR);
- if ( qstr[0] == '!' )
- {
- int qidx = strlen( qstr );
- if ( qstr[1] == '\0' )
- {
- free( qstr );
- return YAML_ITRANSFER;
- }
-
- lvl = CURRENT_LEVEL();
-
- /*
- * URL Prefixing
- */
- if ( qstr[1] == '^' )
- {
- sycklval->name = S_ALLOC_N( char, qidx + strlen( lvl->domain ) );
- sycklval->name[0] = '\0';
- strcat( sycklval->name, lvl->domain );
- strncat( sycklval->name, qstr + 2, qidx - 2 );
- free( qstr );
- }
- else
- {
- char *carat = qstr + 1;
- char *qend = qstr + qidx;
- while ( (++carat) < qend )
- {
- if ( *carat == '^' )
- break;
- }
-
- if ( carat < qend )
- {
- free( lvl->domain );
- lvl->domain = syck_strndup( qstr + 1, carat - ( qstr + 1 ) );
- sycklval->name = S_ALLOC_N( char, ( qend - carat ) + strlen( lvl->domain ) );
- sycklval->name[0] = '\0';
- strcat( sycklval->name, lvl->domain );
- strncat( sycklval->name, carat + 1, ( qend - carat ) - 1 );
- free( qstr );
- }
- else
- {
- sycklval->name = S_ALLOC_N( char, strlen( qstr ) );
- sycklval->name[0] = '\0';
- S_MEMCPY( sycklval->name, qstr + 1, char, strlen( qstr ) );
- free( qstr );
- }
- }
- return YAML_TRANSFER;
- }
- sycklval->name = qstr;
- return YAML_TAGURI;
- }
-#line 382 "<stdout>"
-yy25: ++YYCURSOR;
- goto yy26;
-yy26:
-#line 366 "bytecode.re"
-{ goto Comment; }
-#line 388 "<stdout>"
-yy27: ++YYCURSOR;
- goto yy28;
-yy28:
-#line 368 "bytecode.re"
-{ CHK_NL(YYCURSOR);
- if ( lvl->status == syck_lvl_seq )
- {
- return YAML_INDENT;
- }
- else if ( lvl->status == syck_lvl_map )
- {
- if ( lvl->ncount % 2 == 1 ) return ':';
- else return YAML_INDENT;
- }
- goto Document;
- }
-#line 405 "<stdout>"
-yy29: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy27;
- default: goto yy11;
- }
-yy30: ++YYCURSOR;
- goto yy31;
-yy31:
-#line 381 "bytecode.re"
-{ ENSURE_YAML_IEND(lvl, -1);
- YYPOS(0);
- return 0;
- }
-#line 419 "<stdout>"
-yy32: ++YYCURSOR;
- goto yy33;
-yy33:
-#line 252 "bytecode.re"
-{ if ( lvl->status == syck_lvl_seq && lvl->ncount == 0 )
- {
- lvl->ncount++;
- YYPOS(0);
- FORCE_NEXT_TOKEN( ']' );
- return '[';
- }
- else if ( lvl->status == syck_lvl_map && lvl->ncount == 0 )
- {
- lvl->ncount++;
- YYPOS(0);
- FORCE_NEXT_TOKEN( '}' );
- return '{';
- }
-
- POP_LEVEL();
- lvl = CURRENT_LEVEL();
- if ( lvl->status == syck_lvl_seq )
- {
- FORCE_NEXT_TOKEN(YAML_INDENT);
- }
- else if ( lvl->status == syck_lvl_map )
- {
- if ( lvl->ncount % 2 == 1 )
- {
- FORCE_NEXT_TOKEN(':');
- }
- else
- {
- FORCE_NEXT_TOKEN(YAML_INDENT);
- }
- }
- CHK_NL(YYCURSOR);
- return YAML_IEND;
- }
-#line 459 "<stdout>"
-yy34: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy32;
- default: goto yy11;
- }
-yy35: ++YYCURSOR;
- goto yy36;
-yy36:
-#line 237 "bytecode.re"
-{ int complex = 0;
- if ( lvl->ncount % 2 == 0 && ( lvl->status == syck_lvl_map || lvl->status == syck_lvl_seq ) )
- {
- complex = 1;
- }
- ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_seq);
- CHK_NL(YYCURSOR);
- if ( complex )
- {
- FORCE_NEXT_TOKEN( YAML_IOPEN );
- return '?';
- }
- return YAML_IOPEN;
- }
-#line 483 "<stdout>"
-yy37: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy35;
- default: goto yy11;
- }
-yy38: ++YYCURSOR;
- goto yy39;
-yy39:
-#line 222 "bytecode.re"
-{ int complex = 0;
- if ( lvl->ncount % 2 == 0 && ( lvl->status == syck_lvl_map || lvl->status == syck_lvl_seq ) )
- {
- complex = 1;
- }
- ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_map);
- CHK_NL(YYCURSOR);
- if ( complex )
- {
- FORCE_NEXT_TOKEN( YAML_IOPEN );
- return '?';
- }
- return YAML_IOPEN;
- }
-#line 507 "<stdout>"
-yy40: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy38;
- default: goto yy11;
- }
-yy41: ++YYCURSOR;
- goto yy42;
-yy42:
-#line 217 "bytecode.re"
-{ ENSURE_YAML_IEND(lvl, -1);
- YYPOS(0);
- return 0;
- }
-#line 521 "<stdout>"
-yy43: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy41;
- default: goto yy11;
- }
-yy44: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy41;
- default: goto yy11;
- }
-}
-#line 386 "bytecode.re"
-
-
- }
-
-Directive:
- {
- YYTOKEN = YYCURSOR;
-
-
-#line 543 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy45;
- ++YYCURSOR;
-yy45:
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy47;
- case 'V': goto yy48;
- default: goto yy50;
- }
-yy47: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy49;
- }
-yy48: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case '.':
- case '/':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case ':':
- case ';':
- case '<':
- case '=':
- case '>':
- case '?':
- case '@':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '[':
- case '\\':
- case ']':
- case '^':
- case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy51;
- default: goto yy49;
- }
-yy49:
-#line 399 "bytecode.re"
-{ YYCURSOR = YYTOKEN;
- return YAML_DOCSEP;
- }
-#line 646 "<stdout>"
-yy50: yych = *++YYCURSOR;
- goto yy49;
-yy51: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- goto yy52;
-yy52: switch(yych){
- case '.':
- case '/':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case ';':
- case '<':
- case '=':
- case '>':
- case '?':
- case '@':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '[':
- case '\\':
- case ']':
- case '^':
- case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy51;
- case ':': goto yy53;
- default: goto yy47;
- }
-yy53: yych = *++YYCURSOR;
- switch(yych){
- case '.':
- case '/':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case ':':
- case ';':
- case '<':
- case '=':
- case '>':
- case '?':
- case '@':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '[':
- case '\\':
- case ']':
- case '^':
- case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy54;
- default: goto yy47;
- }
-yy54: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- goto yy55;
-yy55: switch(yych){
- case 0x0A: goto yy56;
- case 0x0D: goto yy58;
- case '.':
- case '/':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case ':':
- case ';':
- case '<':
- case '=':
- case '>':
- case '?':
- case '@':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '[':
- case '\\':
- case ']':
- case '^':
- case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy54;
- default: goto yy47;
- }
-yy56: ++YYCURSOR;
- goto yy57;
-yy57:
-#line 396 "bytecode.re"
-{ CHK_NL(YYCURSOR);
- goto Directive; }
-#line 899 "<stdout>"
-yy58: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy56;
- default: goto yy47;
- }
-}
-#line 402 "bytecode.re"
-
-
- }
-
-Comment:
- {
- YYTOKEN = YYCURSOR;
-
-
-#line 916 "<stdout>"
-{
- YYCTYPE yych;
- goto yy59;
- ++YYCURSOR;
-yy59:
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy61;
- case 0x0A: goto yy62;
- case 0x0D: goto yy64;
- default: goto yy66;
- }
-yy61:yy62: ++YYCURSOR;
- goto yy63;
-yy63:
-#line 412 "bytecode.re"
-{ CHK_NL(YYCURSOR);
- goto Document; }
-#line 936 "<stdout>"
-yy64: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy67;
- default: goto yy65;
- }
-yy65:
-#line 415 "bytecode.re"
-{ goto Comment; }
-#line 945 "<stdout>"
-yy66: yych = *++YYCURSOR;
- goto yy65;
-yy67: ++YYCURSOR;
- yych = *YYCURSOR;
- goto yy63;
-}
-#line 417 "bytecode.re"
-
-
- }
-
-Scalar:
- {
- int idx = 0;
- int cap = 100;
- char *str = S_ALLOC_N( char, cap );
- char *tok;
-
- str[0] = '\0';
-
-Scalar2:
- tok = YYCURSOR;
-
-
-#line 970 "<stdout>"
-{
- YYCTYPE yych;
- goto yy68;
- ++YYCURSOR;
-yy68:
- if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy74;
- case 0x0A: goto yy70;
- case 0x0D: goto yy72;
- default: goto yy76;
- }
-yy70: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 'C': goto yy78;
- case 'N': goto yy80;
- case 'Z': goto yy83;
- default: goto yy71;
- }
-yy71:
-#line 461 "bytecode.re"
-{ YYCURSOR = tok;
- goto ScalarEnd;
- }
-#line 996 "<stdout>"
-yy72: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy77;
- default: goto yy73;
- }
-yy73:
-#line 469 "bytecode.re"
-{ CAT(str, cap, idx, tok[0]);
- goto Scalar2;
- }
-#line 1007 "<stdout>"
-yy74: ++YYCURSOR;
- goto yy75;
-yy75:
-#line 465 "bytecode.re"
-{ YYCURSOR = tok;
- goto ScalarEnd;
- }
-#line 1015 "<stdout>"
-yy76: yych = *++YYCURSOR;
- goto yy73;
-yy77: yych = *++YYCURSOR;
- switch(yych){
- case 'C': goto yy78;
- case 'N': goto yy80;
- case 'Z': goto yy83;
- default: goto yy71;
- }
-yy78: ++YYCURSOR;
- goto yy79;
-yy79:
-#line 435 "bytecode.re"
-{ CHK_NL(tok+1);
- goto Scalar2; }
-#line 1031 "<stdout>"
-yy80: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy81;
-yy81: switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy80;
- default: goto yy82;
- }
-yy82:
-#line 438 "bytecode.re"
-{ CHK_NL(tok+1);
- if ( tok + 2 < YYCURSOR )
- {
- char *count = tok + 2;
- int total = strtod( count, NULL );
- int i;
- for ( i = 0; i < total; i++ )
- {
- CAT(str, cap, idx, '\n');
- }
- }
- else
- {
- CAT(str, cap, idx, '\n');
- }
- goto Scalar2;
- }
-#line 1068 "<stdout>"
-yy83: ++YYCURSOR;
- goto yy84;
-yy84:
-#line 456 "bytecode.re"
-{ CHK_NL(tok+1);
- CAT(str, cap, idx, '\0');
- goto Scalar2;
- }
-#line 1077 "<stdout>"
-}
-#line 473 "bytecode.re"
-
-
-ScalarEnd:
- {
- SyckNode *n = syck_alloc_str();
- n->data.str->ptr = str;
- n->data.str->len = idx;
- sycklval->nodeData = n;
- POP_LEVEL();
- if ( parser->implicit_typing == 1 )
- {
- try_tag_implicit( sycklval->nodeData, parser->taguri_expansion );
- }
- return YAML_PLAIN;
- }
- }
-
-}
-
-char *
-get_inline( SyckParser *parser )
-{
- int idx = 0;
- int cap = 100;
- char *str = S_ALLOC_N( char, cap );
- char *tok;
-
- str[0] = '\0';
-
-Inline:
- {
- tok = YYCURSOR;
-
-
-#line 1114 "<stdout>"
-{
- YYCTYPE yych;
- goto yy85;
- ++YYCURSOR;
-yy85:
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy91;
- case 0x0A: goto yy87;
- case 0x0D: goto yy89;
- default: goto yy93;
- }
-yy87: ++YYCURSOR;
- goto yy88;
-yy88:
-#line 508 "bytecode.re"
-{ CHK_NL(YYCURSOR);
- return str; }
-#line 1134 "<stdout>"
-yy89: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy94;
- default: goto yy90;
- }
-yy90:
-#line 515 "bytecode.re"
-{ CAT(str, cap, idx, tok[0]);
- goto Inline;
- }
-#line 1145 "<stdout>"
-yy91: ++YYCURSOR;
- goto yy92;
-yy92:
-#line 511 "bytecode.re"
-{ YYCURSOR = tok;
- return str;
- }
-#line 1153 "<stdout>"
-yy93: yych = *++YYCURSOR;
- goto yy90;
-yy94: ++YYCURSOR;
- yych = *YYCURSOR;
- goto yy88;
-}
-#line 519 "bytecode.re"
-
-
- }
-
-}
-
diff --git a/ext/syck/depend b/ext/syck/depend
deleted file mode 100644
index 3eec4de72a..0000000000
--- a/ext/syck/depend
+++ /dev/null
@@ -1,12 +0,0 @@
-ruby_headers = $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h \
- $(hdrdir)/missing.h $(hdrdir)/intern.h $(hdrdir)/st.h
-bytecode.o: bytecode.c syck.h gram.h $(ruby_headers)
-emitter.o: emitter.c syck.h $(ruby_headers)
-gram.o: gram.c syck.h $(hdrdir)/st.h
-handler.o: handler.c syck.h $(ruby_headers)
-implicit.o: implicit.c syck.h $(ruby_headers)
-node.o: node.c syck.h $(ruby_headers)
-rubyext.o: rubyext.c syck.h $(ruby_headers)
-syck.o: syck.c syck.h $(ruby_headers)
-token.o: token.c syck.h gram.h $(ruby_headers)
-yaml2byte.o: yaml2byte.c syck.h yamlbyte.h $(ruby_headers)
diff --git a/ext/syck/emitter.c b/ext/syck/emitter.c
deleted file mode 100644
index 9c8ab8d49b..0000000000
--- a/ext/syck/emitter.c
+++ /dev/null
@@ -1,1242 +0,0 @@
-/*
- * emitter.c
- *
- * $Author$
- * $Date$
- *
- * Copyright (C) 2003 why the lucky stiff
- *
- * All Base64 code from Ruby's pack.c.
- * Ruby is Copyright (C) 1993-2003 Yukihiro Matsumoto
- */
-#include "ruby.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include "syck.h"
-
-#define DEFAULT_ANCHOR_FORMAT "id%03d"
-
-const char hex_table[] =
-"0123456789ABCDEF";
-static char b64_table[] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-/*
- * Built-in base64 (from Ruby's pack.c)
- */
-char *
-syck_base64enc( char *s, long len )
-{
- long i = 0;
- int padding = '=';
- char *buff = S_ALLOC_N(char, len * 4 / 3 + 6);
-
- while (len >= 3) {
- buff[i++] = b64_table[077 & (*s >> 2)];
- buff[i++] = b64_table[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
- buff[i++] = b64_table[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))];
- buff[i++] = b64_table[077 & s[2]];
- s += 3;
- len -= 3;
- }
- if (len == 2) {
- buff[i++] = b64_table[077 & (*s >> 2)];
- buff[i++] = b64_table[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
- buff[i++] = b64_table[077 & (((s[1] << 2) & 074) | (('\0' >> 6) & 03))];
- buff[i++] = padding;
- }
- else if (len == 1) {
- buff[i++] = b64_table[077 & (*s >> 2)];
- buff[i++] = b64_table[077 & (((*s << 4) & 060) | (('\0' >> 4) & 017))];
- buff[i++] = padding;
- buff[i++] = padding;
- }
- buff[i++] = '\n';
- return buff;
-}
-
-char *
-syck_base64dec( char *s, long len )
-{
- int a = -1,b = -1,c = 0,d;
- static int first = 1;
- static int b64_xtable[256];
- char *ptr = syck_strndup( s, len );
- char *end = ptr;
- char *send = s + len;
-
- if (first) {
- int i;
- first = 0;
-
- for (i = 0; i < 256; i++) {
- b64_xtable[i] = -1;
- }
- for (i = 0; i < 64; i++) {
- b64_xtable[(int)b64_table[i]] = i;
- }
- }
- while (s < send) {
- while (s[0] == '\r' || s[0] == '\n') { s++; }
- if ((a = b64_xtable[(int)s[0]]) == -1) break;
- if ((b = b64_xtable[(int)s[1]]) == -1) break;
- if ((c = b64_xtable[(int)s[2]]) == -1) break;
- if ((d = b64_xtable[(int)s[3]]) == -1) break;
- *end++ = a << 2 | b >> 4;
- *end++ = b << 4 | c >> 2;
- *end++ = c << 6 | d;
- s += 4;
- }
- if (a != -1 && b != -1) {
- if (s + 2 < send && s[2] == '=')
- *end++ = a << 2 | b >> 4;
- if (c != -1 && s + 3 < send && s[3] == '=') {
- *end++ = a << 2 | b >> 4;
- *end++ = b << 4 | c >> 2;
- }
- }
- *end = '\0';
- /*RSTRING(buf)->len = ptr - RSTRING(buf)->ptr;*/
- return ptr;
-}
-
-/*
- * Allocate an emitter
- */
-SyckEmitter *
-syck_new_emitter()
-{
- SyckEmitter *e;
- e = S_ALLOC( SyckEmitter );
- e->headless = 0;
- e->use_header = 0;
- e->use_version = 0;
- e->sort_keys = 0;
- e->anchor_format = NULL;
- e->explicit_typing = 0;
- e->best_width = 80;
- e->style = scalar_none;
- e->stage = doc_open;
- e->indent = 2;
- e->level = -1;
- e->anchors = NULL;
- e->markers = NULL;
- e->anchored = NULL;
- e->bufsize = SYCK_BUFFERSIZE;
- e->buffer = NULL;
- e->marker = NULL;
- e->bufpos = 0;
- e->emitter_handler = NULL;
- e->output_handler = NULL;
- e->lvl_idx = 0;
- e->lvl_capa = ALLOC_CT;
- e->levels = S_ALLOC_N( SyckLevel, e->lvl_capa );
- syck_emitter_reset_levels( e );
- e->bonus = NULL;
- return e;
-}
-
-int
-syck_st_free_anchors( char *key, char *name, char *arg )
-{
- S_FREE( name );
- return ST_CONTINUE;
-}
-
-void
-syck_emitter_st_free( SyckEmitter *e )
-{
- /*
- * Free the anchor tables
- */
- if ( e->anchors != NULL )
- {
- st_foreach( e->anchors, syck_st_free_anchors, 0 );
- st_free_table( e->anchors );
- e->anchors = NULL;
- }
-
- if ( e->anchored != NULL )
- {
- st_free_table( e->anchored );
- e->anchored = NULL;
- }
-
- /*
- * Free the markers tables
- */
- if ( e->markers != NULL )
- {
- st_free_table( e->markers );
- e->markers = NULL;
- }
-}
-
-SyckLevel *
-syck_emitter_current_level( SyckEmitter *e )
-{
- return &e->levels[e->lvl_idx-1];
-}
-
-SyckLevel *
-syck_emitter_parent_level( SyckEmitter *e )
-{
- return &e->levels[e->lvl_idx-2];
-}
-
-void
-syck_emitter_pop_level( SyckEmitter *e )
-{
- ASSERT( e != NULL );
-
- /* The root level should never be popped */
- if ( e->lvl_idx <= 1 ) return;
-
- e->lvl_idx -= 1;
- free( e->levels[e->lvl_idx].domain );
-}
-
-void
-syck_emitter_add_level( SyckEmitter *e, int len, enum syck_level_status status )
-{
- ASSERT( e != NULL );
- if ( e->lvl_idx + 1 > e->lvl_capa )
- {
- e->lvl_capa += ALLOC_CT;
- S_REALLOC_N( e->levels, SyckLevel, e->lvl_capa );
- }
-
- ASSERT( len > e->levels[e->lvl_idx-1].spaces );
- e->levels[e->lvl_idx].spaces = len;
- e->levels[e->lvl_idx].ncount = 0;
- e->levels[e->lvl_idx].domain = syck_strndup( e->levels[e->lvl_idx-1].domain, strlen( e->levels[e->lvl_idx-1].domain ) );
- e->levels[e->lvl_idx].status = status;
- e->levels[e->lvl_idx].anctag = 0;
- e->lvl_idx += 1;
-}
-
-void
-syck_emitter_reset_levels( SyckEmitter *e )
-{
- while ( e->lvl_idx > 1 )
- {
- syck_emitter_pop_level( e );
- }
-
- if ( e->lvl_idx < 1 )
- {
- e->lvl_idx = 1;
- e->levels[0].spaces = -1;
- e->levels[0].ncount = 0;
- e->levels[0].domain = syck_strndup( "", 0 );
- e->levels[0].anctag = 0;
- }
- e->levels[0].status = syck_lvl_header;
-}
-
-void
-syck_emitter_handler( SyckEmitter *e, SyckEmitterHandler hdlr )
-{
- e->emitter_handler = hdlr;
-}
-
-void
-syck_output_handler( SyckEmitter *e, SyckOutputHandler hdlr )
-{
- e->output_handler = hdlr;
-}
-
-void
-syck_free_emitter( SyckEmitter *e )
-{
- /*
- * Free tables
- */
- syck_emitter_st_free( e );
- syck_emitter_reset_levels( e );
- S_FREE( e->levels[0].domain );
- S_FREE( e->levels );
- if ( e->buffer != NULL )
- {
- S_FREE( e->buffer );
- }
- S_FREE( e );
-}
-
-void
-syck_emitter_clear( SyckEmitter *e )
-{
- if ( e->buffer == NULL )
- {
- e->buffer = S_ALLOC_N( char, e->bufsize );
- S_MEMZERO( e->buffer, char, e->bufsize );
- }
- e->buffer[0] = '\0';
- e->marker = e->buffer;
- e->bufpos = 0;
-}
-
-/*
- * Raw write to the emitter buffer.
- */
-void
-syck_emitter_write( SyckEmitter *e, char *str, long len )
-{
- long at;
- ASSERT( str != NULL )
- if ( e->buffer == NULL )
- {
- syck_emitter_clear( e );
- }
-
- /*
- * Flush if at end of buffer
- */
- at = e->marker - e->buffer;
- if ( len + at >= e->bufsize )
- {
- syck_emitter_flush( e, 0 );
- for (;;) {
- long rest = e->bufsize - (e->marker - e->buffer);
- if (len <= rest) break;
- S_MEMCPY( e->marker, str, char, rest );
- e->marker += rest;
- str += rest;
- len -= rest;
- syck_emitter_flush( e, 0 );
- }
- }
-
- /*
- * Write to buffer
- */
- S_MEMCPY( e->marker, str, char, len );
- e->marker += len;
-}
-
-/*
- * Write a chunk of data out.
- */
-void
-syck_emitter_flush( SyckEmitter *e, long check_room )
-{
- /*
- * Check for enough space in the buffer for check_room length.
- */
- if ( check_room > 0 )
- {
- if ( e->bufsize > ( e->marker - e->buffer ) + check_room )
- {
- return;
- }
- }
- else
- {
- check_room = e->bufsize;
- }
-
- /*
- * Commit buffer.
- */
- if ( check_room > e->marker - e->buffer )
- {
- check_room = e->marker - e->buffer;
- }
- (e->output_handler)( e, e->buffer, check_room );
- e->bufpos += check_room;
- e->marker -= check_room;
-}
-
-/*
- * Start emitting from the given node, check for anchoring and then
- * issue the callback to the emitter handler.
- */
-void
-syck_emit( SyckEmitter *e, st_data_t n )
-{
- SYMID oid;
- char *anchor_name = NULL;
- int indent = 0;
- long x = 0;
- SyckLevel *lvl = syck_emitter_current_level( e );
-
- /*
- * Determine headers.
- */
- if ( e->stage == doc_open && ( e->headless == 0 || e->use_header == 1 ) )
- {
- if ( e->use_version == 1 )
- {
- char *header = S_ALLOC_N( char, 64 );
- S_MEMZERO( header, char, 64 );
- sprintf( header, "--- %%YAML:%d.%d ", SYCK_YAML_MAJOR, SYCK_YAML_MINOR );
- syck_emitter_write( e, header, strlen( header ) );
- S_FREE( header );
- }
- else
- {
- syck_emitter_write( e, "--- ", 4 );
- }
- e->stage = doc_processing;
- }
-
- /* Add new level */
- if ( lvl->spaces >= 0 ) {
- indent = lvl->spaces + e->indent;
- }
- syck_emitter_add_level( e, indent, syck_lvl_open );
- lvl = syck_emitter_current_level( e );
-
- /* Look for anchor */
- if ( e->anchors != NULL &&
- st_lookup( e->markers, n, (st_data_t *)&oid ) &&
- st_lookup( e->anchors, (st_data_t)oid, (st_data_t *)&anchor_name ) )
- {
- if ( e->anchored == NULL )
- {
- e->anchored = st_init_numtable();
- }
-
- if ( ! st_lookup( e->anchored, (st_data_t)anchor_name, (st_data_t *)&x ) )
- {
- char *an = S_ALLOC_N( char, strlen( anchor_name ) + 3 );
- sprintf( an, "&%s ", anchor_name );
- syck_emitter_write( e, an, strlen( anchor_name ) + 2 );
- free( an );
-
- x = 1;
- st_insert( e->anchored, (st_data_t)anchor_name, (st_data_t)x );
- lvl->anctag = 1;
- }
- else
- {
- char *an = S_ALLOC_N( char, strlen( anchor_name ) + 2 );
- sprintf( an, "*%s", anchor_name );
- syck_emitter_write( e, an, strlen( anchor_name ) + 1 );
- free( an );
-
- goto end_emit;
- }
- }
-
- (e->emitter_handler)( e, n );
-
- /* Pop the level */
-end_emit:
- syck_emitter_pop_level( e );
- if ( e->lvl_idx == 1 ) {
- syck_emitter_write( e, "\n", 1 );
- e->headless = 0;
- e->stage = doc_open;
- }
-}
-
-/*
- * Determine what tag needs to be written, based on the taguri of the node
- * and the implicit tag which would be assigned to this node. If a tag is
- * required, write the tag.
- */
-void syck_emit_tag( SyckEmitter *e, char *tag, char *ignore )
-{
- SyckLevel *lvl;
- if ( tag == NULL ) return;
- if ( ignore != NULL && syck_tagcmp( tag, ignore ) == 0 && e->explicit_typing == 0 ) return;
- lvl = syck_emitter_current_level( e );
-
- /* implicit */
- if ( strlen( tag ) == 0 ) {
- syck_emitter_write( e, "! ", 2 );
-
- /* global types */
- } else if ( strncmp( tag, "tag:", 4 ) == 0 ) {
- int taglen = strlen( tag );
- syck_emitter_write( e, "!", 1 );
- if ( strncmp( tag + 4, YAML_DOMAIN, strlen( YAML_DOMAIN ) ) == 0 ) {
- int skip = 4 + strlen( YAML_DOMAIN ) + 1;
- syck_emitter_write( e, tag + skip, taglen - skip );
- } else {
- char *subd = tag + 4;
- while ( *subd != ':' && *subd != '\0' ) subd++;
- if ( *subd == ':' ) {
- if ( subd - tag > ( strlen( YAML_DOMAIN ) + 5 ) &&
- strncmp( subd - strlen( YAML_DOMAIN ), YAML_DOMAIN, strlen( YAML_DOMAIN ) ) == 0 ) {
- syck_emitter_write( e, tag + 4, subd - strlen( YAML_DOMAIN ) - ( tag + 4 ) - 1 );
- syck_emitter_write( e, "/", 1 );
- syck_emitter_write( e, subd + 1, ( tag + taglen ) - ( subd + 1 ) );
- } else {
- syck_emitter_write( e, tag + 4, subd - ( tag + 4 ) );
- syck_emitter_write( e, "/", 1 );
- syck_emitter_write( e, subd + 1, ( tag + taglen ) - ( subd + 1 ) );
- }
- } else {
- /* TODO: Invalid tag (no colon after domain) */
- return;
- }
- }
- syck_emitter_write( e, " ", 1 );
-
- /* private types */
- } else if ( strncmp( tag, "x-private:", 10 ) == 0 ) {
- syck_emitter_write( e, "!!", 2 );
- syck_emitter_write( e, tag + 10, strlen( tag ) - 10 );
- syck_emitter_write( e, " ", 1 );
- }
- lvl->anctag = 1;
-}
-
-/*
- * Emit a newline and an appropriately spaced indent.
- */
-void syck_emit_indent( SyckEmitter *e )
-{
- int i;
- SyckLevel *lvl = syck_emitter_current_level( e );
- if ( e->bufpos == 0 && ( e->marker - e->buffer ) == 0 ) return;
- if ( lvl->spaces >= 0 ) {
- char *spcs = S_ALLOC_N( char, lvl->spaces + 2 );
-
- spcs[0] = '\n'; spcs[lvl->spaces + 1] = '\0';
- for ( i = 0; i < lvl->spaces; i++ ) spcs[i+1] = ' ';
- syck_emitter_write( e, spcs, lvl->spaces + 1 );
- free( spcs );
- }
-}
-
-/* Clear the scan */
-#define SCAN_NONE 0
-/* All printable characters? */
-#define SCAN_NONPRINT 1
-/* Any indented lines? */
-#define SCAN_INDENTED 2
-/* Larger than the requested width? */
-#define SCAN_WIDE 4
-/* Opens or closes with whitespace? */
-#define SCAN_WHITEEDGE 8
-/* Contains a newline */
-#define SCAN_NEWLINE 16
-/* Contains a single quote */
-#define SCAN_SINGLEQ 32
-/* Contains a double quote */
-#define SCAN_DOUBLEQ 64
-/* Starts with a token */
-#define SCAN_INDIC_S 128
-/* Contains a flow indicator */
-#define SCAN_INDIC_C 256
-/* Ends without newlines */
-#define SCAN_NONL_E 512
-/* Ends with many newlines */
-#define SCAN_MANYNL_E 1024
-/* Contains flow map indicators */
-#define SCAN_FLOWMAP 2048
-/* Contains flow seq indicators */
-#define SCAN_FLOWSEQ 4096
-/* Contains a valid doc separator */
-#define SCAN_DOCSEP 8192
-
-/*
- * Basic printable test for LATIN-1 characters.
- */
-int
-syck_scan_scalar( int req_width, char *cursor, long len )
-{
- long i = 0, start = 0;
- int flags = SCAN_NONE;
-
- if ( len < 1 ) return flags;
-
- /* c-indicators from the spec */
- if ( cursor[0] == '[' || cursor[0] == ']' ||
- cursor[0] == '{' || cursor[0] == '}' ||
- cursor[0] == '!' || cursor[0] == '*' ||
- cursor[0] == '&' || cursor[0] == '|' ||
- cursor[0] == '>' || cursor[0] == '\'' ||
- cursor[0] == '"' || cursor[0] == '#' ||
- cursor[0] == '%' || cursor[0] == '@' ||
- cursor[0] == '&' ) {
- flags |= SCAN_INDIC_S;
- }
- if ( ( cursor[0] == '-' || cursor[0] == ':' ||
- cursor[0] == '?' || cursor[0] == ',' ) &&
- ( len == 1 || cursor[1] == ' ' || cursor[1] == '\n' ) )
- {
- flags |= SCAN_INDIC_S;
- }
-
- /* whitespace edges */
- if ( cursor[len-1] != '\n' ) {
- flags |= SCAN_NONL_E;
- } else if ( len > 1 && cursor[len-2] == '\n' ) {
- flags |= SCAN_MANYNL_E;
- }
- if (
- ( len > 0 && ( cursor[0] == ' ' || cursor[0] == '\t' ) ) ||
- ( len > 1 && ( cursor[len-1] == ' ' || cursor[len-1] == '\t' ) )
- ) {
- flags |= SCAN_WHITEEDGE;
- }
-
- /* opening doc sep */
- if ( len >= 3 && strncmp( cursor, "---", 3 ) == 0 )
- flags |= SCAN_DOCSEP;
-
- /* scan string */
- for ( i = 0; i < len; i++ ) {
-
- if ( ! ( cursor[i] == 0x9 ||
- cursor[i] == 0xA ||
- cursor[i] == 0xD ||
- ( cursor[i] >= 0x20 && cursor[i] <= 0x7E ) )
- ) {
- flags |= SCAN_NONPRINT;
- }
- else if ( cursor[i] == '\n' ) {
- flags |= SCAN_NEWLINE;
- if ( len - i >= 3 && strncmp( &cursor[i+1], "---", 3 ) == 0 )
- flags |= SCAN_DOCSEP;
- if ( cursor[i+1] == ' ' || cursor[i+1] == '\t' )
- flags |= SCAN_INDENTED;
- if ( req_width > 0 && i - start > req_width )
- flags |= SCAN_WIDE;
- start = i;
- }
- else if ( cursor[i] == '\'' )
- {
- flags |= SCAN_SINGLEQ;
- }
- else if ( cursor[i] == '"' )
- {
- flags |= SCAN_DOUBLEQ;
- }
- else if ( cursor[i] == ']' )
- {
- flags |= SCAN_FLOWSEQ;
- }
- else if ( cursor[i] == '}' )
- {
- flags |= SCAN_FLOWMAP;
- }
- /* remember, if plain collections get implemented, to add nb-plain-flow-char */
- else if ( ( cursor[i] == ' ' && cursor[i+1] == '#' ) ||
- ( cursor[i] == ':' &&
- ( cursor[i+1] == ' ' || cursor[i+1] == '\n' || i == len - 1 ) ) )
- {
- flags |= SCAN_INDIC_C;
- }
- else if ( cursor[i] == ',' &&
- ( cursor[i+1] == ' ' || cursor[i+1] == '\n' || i == len - 1 ) )
- {
- flags |= SCAN_FLOWMAP;
- flags |= SCAN_FLOWSEQ;
- }
- }
-
- /* printf( "---STR---\n%s\nFLAGS: %d\n", cursor, flags ); */
- return flags;
-}
-/*
- * All scalars should be emitted through this function, which determines an appropriate style,
- * tag and indent.
- */
-void syck_emit_scalar( SyckEmitter *e, char *tag, enum scalar_style force_style, int force_indent, int force_width,
- char keep_nl, char *str, long len )
-{
- enum scalar_style favor_style = scalar_literal;
- SyckLevel *parent = syck_emitter_parent_level( e );
- SyckLevel *lvl = syck_emitter_current_level( e );
- int scan = 0;
- char *implicit;
-
- if ( str == NULL ) str = "";
-
- /* No empty nulls as map keys */
- if ( len == 0 && ( parent->status == syck_lvl_map || parent->status == syck_lvl_imap ) &&
- parent->ncount % 2 == 1 && syck_tagcmp( tag, "tag:yaml.org,2002:null" ) == 0 )
- {
- str = "~";
- len = 1;
- }
-
- scan = syck_scan_scalar( force_width, str, len );
- implicit = syck_match_implicit( str, len );
-
- /* quote strings which default to implicits */
- implicit = syck_taguri( YAML_DOMAIN, implicit, strlen( implicit ) );
- if ( syck_tagcmp( tag, implicit ) != 0 && syck_tagcmp( tag, "tag:yaml.org,2002:str" ) == 0 ) {
- force_style = scalar_2quote;
- } else {
- /* complex key */
- if ( parent->status == syck_lvl_map && parent->ncount % 2 == 1 &&
- ( !( tag == NULL ||
- ( implicit != NULL && syck_tagcmp( tag, implicit ) == 0 && e->explicit_typing == 0 ) ) ) )
- {
- syck_emitter_write( e, "? ", 2 );
- parent->status = syck_lvl_mapx;
- }
- syck_emit_tag( e, tag, implicit );
- }
- S_FREE( implicit );
-
- /* if still arbitrary, sniff a good block style. */
- if ( force_style == scalar_none ) {
- if ( scan & SCAN_NEWLINE ) {
- force_style = scalar_literal;
- } else {
- force_style = scalar_plain;
- }
- }
-
- if ( e->style == scalar_fold ) {
- favor_style = scalar_fold;
- }
-
- /* Determine block style */
- if ( scan & SCAN_NONPRINT ) {
- force_style = scalar_2quote;
- } else if ( scan & SCAN_WHITEEDGE ) {
- force_style = scalar_2quote;
- } else if ( force_style != scalar_fold && ( scan & SCAN_INDENTED ) ) {
- force_style = scalar_literal;
- } else if ( force_style == scalar_plain && ( scan & SCAN_NEWLINE ) ) {
- force_style = favor_style;
- } else if ( force_style == scalar_plain && parent->status == syck_lvl_iseq && ( scan & SCAN_FLOWSEQ ) ) {
- force_style = scalar_2quote;
- } else if ( force_style == scalar_plain && parent->status == syck_lvl_imap && ( scan & SCAN_FLOWMAP ) ) {
- force_style = scalar_2quote;
- /* } else if ( force_style == scalar_fold && ( ! ( scan & SCAN_WIDE ) ) ) {
- force_style = scalar_literal; */
- } else if ( force_style == scalar_plain && ( scan & SCAN_INDIC_S || scan & SCAN_INDIC_C ) ) {
- if ( scan & SCAN_NEWLINE ) {
- force_style = favor_style;
- } else {
- force_style = scalar_2quote;
- }
- }
-
- if ( force_indent > 0 ) {
- lvl->spaces = parent->spaces + force_indent;
- } else if ( scan & SCAN_DOCSEP ) {
- lvl->spaces = parent->spaces + e->indent;
- }
-
- /* For now, all ambiguous keys are going to be double-quoted */
- if ( ( parent->status == syck_lvl_map || parent->status == syck_lvl_mapx ) && parent->ncount % 2 == 1 ) {
- if ( force_style != scalar_plain ) {
- force_style = scalar_2quote;
- }
- }
-
- /* If the parent is an inline, double quote anything complex */
- if ( parent->status == syck_lvl_imap || parent->status == syck_lvl_iseq ) {
- if ( force_style != scalar_plain && force_style != scalar_1quote ) {
- force_style = scalar_2quote;
- }
- }
-
- /* Fix the ending newlines */
- if ( scan & SCAN_NONL_E ) {
- keep_nl = NL_CHOMP;
- } else if ( scan & SCAN_MANYNL_E ) {
- keep_nl = NL_KEEP;
- }
-
- /* Write the text node */
- switch ( force_style )
- {
- case scalar_1quote:
- syck_emit_1quoted( e, force_width, str, len );
- break;
-
- case scalar_none:
- case scalar_2quote:
- syck_emit_2quoted( e, force_width, str, len );
- break;
-
- case scalar_fold:
- syck_emit_folded( e, force_width, keep_nl, str, len );
- break;
-
- case scalar_literal:
- syck_emit_literal( e, keep_nl, str, len );
- break;
-
- case scalar_plain:
- syck_emitter_write( e, str, len );
- break;
- }
-
- if ( parent->status == syck_lvl_mapx )
- {
- syck_emitter_write( e, "\n", 1 );
- }
-}
-
-void
-syck_emitter_escape( SyckEmitter *e, char *src, long len )
-{
- int i;
- for( i = 0; i < len; i++ )
- {
- if( (src[i] < 0x20) || (0x7E < src[i]) )
- {
- syck_emitter_write( e, "\\", 1 );
- if( '\0' == src[i] )
- syck_emitter_write( e, "0", 1 );
- else
- {
- syck_emitter_write( e, "x", 1 );
- syck_emitter_write( e, (char *)hex_table + ((src[i] & 0xF0) >> 4), 1 );
- syck_emitter_write( e, (char *)hex_table + (src[i] & 0x0F), 1 );
- }
- }
- else
- {
- syck_emitter_write( e, src + i, 1 );
- if( '\\' == src[i] )
- syck_emitter_write( e, "\\", 1 );
- }
- }
-}
-
-/*
- * Outputs a single-quoted block.
- */
-void syck_emit_1quoted( SyckEmitter *e, int width, char *str, long len )
-{
- char do_indent = 0;
- char *mark = str;
- char *start = str;
- char *end = str;
- syck_emitter_write( e, "'", 1 );
- while ( mark < str + len ) {
- if ( do_indent ) {
- syck_emit_indent( e );
- do_indent = 0;
- }
- switch ( *mark ) {
- case '\'': syck_emitter_write( e, "'", 1 ); break;
-
- case '\n':
- end = mark + 1;
- if ( *start != ' ' && *start != '\n' && *end != '\n' && *end != ' ' ) {
- syck_emitter_write( e, "\n\n", 2 );
- } else {
- syck_emitter_write( e, "\n", 1 );
- }
- do_indent = 1;
- start = mark + 1;
- break;
-
- case ' ':
- if ( width > 0 && *start != ' ' && mark - end > width ) {
- do_indent = 1;
- end = mark + 1;
- } else {
- syck_emitter_write( e, " ", 1 );
- }
- break;
-
- default:
- syck_emitter_write( e, mark, 1 );
- break;
- }
- mark++;
- }
- syck_emitter_write( e, "'", 1 );
-}
-
-/*
- * Outputs a double-quoted block.
- */
-void syck_emit_2quoted( SyckEmitter *e, int width, char *str, long len )
-{
- char do_indent = 0;
- char *mark = str;
- char *start = str;
- char *end = str;
- syck_emitter_write( e, "\"", 1 );
- while ( mark < str + len ) {
- if ( do_indent > 0 ) {
- if ( do_indent == 2 ) {
- syck_emitter_write( e, "\\", 1 );
- }
- syck_emit_indent( e );
- do_indent = 0;
- }
- switch ( *mark ) {
-
- /* Escape sequences allowed within double quotes. */
- case '"': syck_emitter_write( e, "\\\"", 2 ); break;
- case '\\': syck_emitter_write( e, "\\\\", 2 ); break;
- case '\0': syck_emitter_write( e, "\\0", 2 ); break;
- case '\a': syck_emitter_write( e, "\\a", 2 ); break;
- case '\b': syck_emitter_write( e, "\\b", 2 ); break;
- case '\f': syck_emitter_write( e, "\\f", 2 ); break;
- case '\r': syck_emitter_write( e, "\\r", 2 ); break;
- case '\t': syck_emitter_write( e, "\\t", 2 ); break;
- case '\v': syck_emitter_write( e, "\\v", 2 ); break;
- case 0x1b: syck_emitter_write( e, "\\e", 2 ); break;
-
- case '\n':
- end = mark + 1;
- syck_emitter_write( e, "\\n", 2 );
- do_indent = 2;
- start = mark + 1;
- if ( start < str + len && ( *start == ' ' || *start == '\n' ) ) {
- do_indent = 0;
- }
- break;
-
- case ' ':
- if ( width > 0 && *start != ' ' && mark - end > width ) {
- do_indent = 1;
- end = mark + 1;
- } else {
- syck_emitter_write( e, " ", 1 );
- }
- break;
-
- default:
- syck_emitter_escape( e, mark, 1 );
- break;
- }
- mark++;
- }
- syck_emitter_write( e, "\"", 1 );
-}
-
-/*
- * Outputs a literal block.
- */
-void syck_emit_literal( SyckEmitter *e, char keep_nl, char *str, long len )
-{
- char *mark = str;
- char *start = str;
- char *end = str;
- syck_emitter_write( e, "|", 1 );
- if ( keep_nl == NL_CHOMP ) {
- syck_emitter_write( e, "-", 1 );
- } else if ( keep_nl == NL_KEEP ) {
- syck_emitter_write( e, "+", 1 );
- }
- syck_emit_indent( e );
- while ( mark < str + len ) {
- if ( *mark == '\n' ) {
- end = mark;
- if ( *start != ' ' && *start != '\n' && *end != '\n' && *end != ' ' ) end += 1;
- syck_emitter_write( e, start, end - start );
- if ( mark + 1 == str + len ) {
- if ( keep_nl != NL_KEEP ) syck_emitter_write( e, "\n", 1 );
- } else {
- syck_emit_indent( e );
- }
- start = mark + 1;
- }
- mark++;
- }
- end = str + len;
- if ( start < end ) {
- syck_emitter_write( e, start, end - start );
- }
-}
-
-/*
- * Outputs a folded block.
- */
-void syck_emit_folded( SyckEmitter *e, int width, char keep_nl, char *str, long len )
-{
- char *mark = str;
- char *start = str;
- char *end = str;
- syck_emitter_write( e, ">", 1 );
- if ( keep_nl == NL_CHOMP ) {
- syck_emitter_write( e, "-", 1 );
- } else if ( keep_nl == NL_KEEP ) {
- syck_emitter_write( e, "+", 1 );
- }
- syck_emit_indent( e );
- if ( width <= 0 ) width = e->best_width;
- while ( mark < str + len ) {
- switch ( *mark ) {
- case '\n':
- syck_emitter_write( e, end, mark - end );
- end = mark + 1;
- if ( *start != ' ' && *start != '\n' && *end != '\n' && *end != ' ' ) {
- syck_emitter_write( e, "\n", 1 );
- }
- if ( mark + 1 == str + len ) {
- if ( keep_nl != NL_KEEP ) syck_emitter_write( e, "\n", 1 );
- } else {
- syck_emit_indent( e );
- }
- start = mark + 1;
- break;
-
- case ' ':
- if ( *start != ' ' ) {
- if ( mark - end > width ) {
- syck_emitter_write( e, end, mark - end );
- syck_emit_indent( e );
- end = mark + 1;
- }
- }
- break;
- }
- mark++;
- }
- if ( end < mark ) {
- syck_emitter_write( e, end, mark - end );
- }
-}
-
-/*
- * Begins emission of a sequence.
- */
-void syck_emit_seq( SyckEmitter *e, char *tag, enum seq_style style )
-{
- SyckLevel *parent = syck_emitter_parent_level( e );
- SyckLevel *lvl = syck_emitter_current_level( e );
- syck_emit_tag( e, tag, "tag:yaml.org,2002:seq" );
- if ( style == seq_inline || ( parent->status == syck_lvl_imap || parent->status == syck_lvl_iseq ) ) {
- syck_emitter_write( e, "[", 1 );
- lvl->status = syck_lvl_iseq;
- } else {
- /* complex key */
- if ( parent->status == syck_lvl_map && parent->ncount % 2 == 1 ) {
- syck_emitter_write( e, "? ", 2 );
- parent->status = syck_lvl_mapx;
- }
- lvl->status = syck_lvl_seq;
- }
-}
-
-/*
- * Begins emission of a mapping.
- */
-void syck_emit_map( SyckEmitter *e, char *tag, enum map_style style )
-{
- SyckLevel *parent = syck_emitter_parent_level( e );
- SyckLevel *lvl = syck_emitter_current_level( e );
- syck_emit_tag( e, tag, "tag:yaml.org,2002:map" );
- if ( style == map_inline || ( parent->status == syck_lvl_imap || parent->status == syck_lvl_iseq ) ) {
- syck_emitter_write( e, "{", 1 );
- lvl->status = syck_lvl_imap;
- } else {
- /* complex key */
- if ( parent->status == syck_lvl_map && parent->ncount % 2 == 1 ) {
- syck_emitter_write( e, "? ", 2 );
- parent->status = syck_lvl_mapx;
- }
- lvl->status = syck_lvl_map;
- }
-}
-
-/*
- * Handles emitting of a collection item (for both
- * sequences and maps)
- */
-void syck_emit_item( SyckEmitter *e, st_data_t n )
-{
- SyckLevel *lvl = syck_emitter_current_level( e );
- switch ( lvl->status )
- {
- case syck_lvl_seq:
- {
- SyckLevel *parent = syck_emitter_parent_level( e );
-
- /* seq-in-map shortcut -- the lvl->anctag check should be unneccesary but
- * there is a nasty shift/reduce in the parser on this point and
- * i'm not ready to tickle it. */
- if ( lvl->anctag == 0 && parent->status == syck_lvl_map && lvl->ncount == 0 ) {
- lvl->spaces = parent->spaces;
- }
-
- /* seq-in-seq shortcut */
- else if ( lvl->anctag == 0 && parent->status == syck_lvl_seq && lvl->ncount == 0 ) {
- int spcs = ( lvl->spaces - parent->spaces ) - 2;
- if ( spcs >= 0 ) {
- int i = 0;
- for ( i = 0; i < spcs; i++ ) {
- syck_emitter_write( e, " ", 1 );
- }
- syck_emitter_write( e, "- ", 2 );
- break;
- }
- }
-
- syck_emit_indent( e );
- syck_emitter_write( e, "- ", 2 );
- }
- break;
-
- case syck_lvl_iseq:
- {
- if ( lvl->ncount > 0 ) {
- syck_emitter_write( e, ", ", 2 );
- }
- }
- break;
-
- case syck_lvl_map:
- {
- SyckLevel *parent = syck_emitter_parent_level( e );
-
- /* map-in-seq shortcut */
- if ( lvl->anctag == 0 && parent->status == syck_lvl_seq && lvl->ncount == 0 ) {
- int spcs = ( lvl->spaces - parent->spaces ) - 2;
- if ( spcs >= 0 ) {
- int i = 0;
- for ( i = 0; i < spcs; i++ ) {
- syck_emitter_write( e, " ", 1 );
- }
- break;
- }
- }
-
- if ( lvl->ncount % 2 == 0 ) {
- syck_emit_indent( e );
- } else {
- syck_emitter_write( e, ": ", 2 );
- }
- }
- break;
-
- case syck_lvl_mapx:
- {
- if ( lvl->ncount % 2 == 0 ) {
- syck_emit_indent( e );
- lvl->status = syck_lvl_map;
- } else {
- int i;
- if ( lvl->spaces > 0 ) {
- char *spcs = S_ALLOC_N( char, lvl->spaces + 1 );
-
- spcs[lvl->spaces] = '\0';
- for ( i = 0; i < lvl->spaces; i++ ) spcs[i] = ' ';
- syck_emitter_write( e, spcs, lvl->spaces );
- S_FREE( spcs );
- }
- syck_emitter_write( e, ": ", 2 );
- }
- }
- break;
-
- case syck_lvl_imap:
- {
- if ( lvl->ncount > 0 ) {
- if ( lvl->ncount % 2 == 0 ) {
- syck_emitter_write( e, ", ", 2 );
- } else {
- syck_emitter_write( e, ": ", 2 );
- }
- }
- }
- break;
-
- default: break;
- }
- lvl->ncount++;
-
- syck_emit( e, n );
-}
-
-/*
- * Closes emission of a collection.
- */
-void syck_emit_end( SyckEmitter *e )
-{
- SyckLevel *lvl = syck_emitter_current_level( e );
- SyckLevel *parent = syck_emitter_parent_level( e );
- switch ( lvl->status )
- {
- case syck_lvl_seq:
- if ( lvl->ncount == 0 ) {
- syck_emitter_write( e, "[]\n", 3 );
- } else if ( parent->status == syck_lvl_mapx ) {
- syck_emitter_write( e, "\n", 1 );
- }
- break;
-
- case syck_lvl_iseq:
- syck_emitter_write( e, "]\n", 1 );
- break;
-
- case syck_lvl_map:
- if ( lvl->ncount == 0 ) {
- syck_emitter_write( e, "{}\n", 3 );
- } else if ( lvl->ncount % 2 == 1 ) {
- syck_emitter_write( e, ":\n", 1 );
- } else if ( parent->status == syck_lvl_mapx ) {
- syck_emitter_write( e, "\n", 1 );
- }
- break;
-
- case syck_lvl_imap:
- syck_emitter_write( e, "}\n", 1 );
- break;
-
- default: break;
- }
-}
-
-/*
- * Fill markers table with emitter nodes in the
- * soon-to-be-emitted tree.
- */
-SYMID
-syck_emitter_mark_node( SyckEmitter *e, st_data_t n )
-{
- SYMID oid = 0;
- char *anchor_name = NULL;
-
- /*
- * Ensure markers table is initialized.
- */
- if ( e->markers == NULL )
- {
- e->markers = st_init_numtable();
- }
-
- /*
- * Markers table initially marks the string position of the
- * object. Doesn't yet create an anchor, simply notes the
- * position.
- */
- if ( ! st_lookup( e->markers, n, (st_data_t *)&oid ) )
- {
- /*
- * Store all markers
- */
- oid = e->markers->num_entries + 1;
- st_insert( e->markers, n, (st_data_t)oid );
- }
- else
- {
- if ( e->anchors == NULL )
- {
- e->anchors = st_init_numtable();
- }
-
- if ( ! st_lookup( e->anchors, (st_data_t)oid, (st_data_t *)&anchor_name ) )
- {
- int idx = 0;
- char *anc = ( e->anchor_format == NULL ? DEFAULT_ANCHOR_FORMAT : e->anchor_format );
-
- /*
- * Second time hitting this object, let's give it an anchor
- */
- idx = e->anchors->num_entries + 1;
- anchor_name = S_ALLOC_N( char, strlen( anc ) + 10 );
- S_MEMZERO( anchor_name, char, strlen( anc ) + 10 );
- sprintf( anchor_name, anc, idx );
-
- /*
- * Insert into anchors table
- */
- st_insert( e->anchors, (st_data_t)oid, (st_data_t)anchor_name );
- }
- }
- return oid;
-}
-
diff --git a/ext/syck/extconf.rb b/ext/syck/extconf.rb
deleted file mode 100644
index 6c10448c70..0000000000
--- a/ext/syck/extconf.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'mkmf'
-
-have_header( "st.h" )
-create_makefile( "syck" )
-
diff --git a/ext/syck/gram.c b/ext/syck/gram.c
deleted file mode 100644
index 615a594f61..0000000000
--- a/ext/syck/gram.c
+++ /dev/null
@@ -1,1894 +0,0 @@
-/* A Bison parser, made by GNU Bison 1.875d. */
-
-/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
-
-/* Written by Richard Stallman by simplifying the original so called
- ``semantic'' parser. */
-
-/* All symbols defined below should begin with yy or YY, to avoid
- infringing on user name space. This should be done even for local
- variables, as they might otherwise be expanded by user macros.
- There are some unavoidable exceptions within include files to
- define necessary library symbols; they are noted "INFRINGES ON
- USER NAME SPACE" below. */
-
-/* Identify Bison output. */
-#define YYBISON 1
-
-/* Skeleton name. */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers. */
-#define YYPURE 1
-
-/* Using locations. */
-#define YYLSP_NEEDED 0
-
-/* If NAME_PREFIX is specified substitute the variables and functions
- names. */
-#define yyparse syckparse
-#define yylex sycklex
-#define yyerror syckerror
-#define yylval sycklval
-#define yychar syckchar
-#define yydebug syckdebug
-#define yynerrs sycknerrs
-
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- YAML_ANCHOR = 258,
- YAML_ALIAS = 259,
- YAML_TRANSFER = 260,
- YAML_TAGURI = 261,
- YAML_ITRANSFER = 262,
- YAML_WORD = 263,
- YAML_PLAIN = 264,
- YAML_BLOCK = 265,
- YAML_DOCSEP = 266,
- YAML_IOPEN = 267,
- YAML_INDENT = 268,
- YAML_IEND = 269
- };
-#endif
-#define YAML_ANCHOR 258
-#define YAML_ALIAS 259
-#define YAML_TRANSFER 260
-#define YAML_TAGURI 261
-#define YAML_ITRANSFER 262
-#define YAML_WORD 263
-#define YAML_PLAIN 264
-#define YAML_BLOCK 265
-#define YAML_DOCSEP 266
-#define YAML_IOPEN 267
-#define YAML_INDENT 268
-#define YAML_IEND 269
-
-
-
-
-/* Copy the first part of user declarations. */
-#line 14 "gram.y"
-
-
-#include "syck.h"
-
-void apply_seq_in_map( SyckParser *parser, SyckNode *n );
-
-#define YYPARSE_PARAM parser
-#define YYLEX_PARAM parser
-
-#define NULL_NODE(parser, node) \
- SyckNode *node = syck_new_str( "", scalar_plain ); \
- if ( ((SyckParser *)parser)->taguri_expansion == 1 ) \
- { \
- node->type_id = syck_taguri( YAML_DOMAIN, "null", 4 ); \
- } \
- else \
- { \
- node->type_id = syck_strndup( "null", 4 ); \
- }
-
-
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 1
-#endif
-
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-#line 35 "gram.y"
-typedef union YYSTYPE {
- SYMID nodeId;
- SyckNode *nodeData;
- char *name;
-} YYSTYPE;
-/* Line 191 of yacc.c. */
-#line 140 "gram.c"
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations. */
-
-
-/* Line 214 of yacc.c. */
-#line 152 "gram.c"
-
-#if ! defined (yyoverflow) || YYERROR_VERBOSE
-
-# ifndef YYFREE
-# define YYFREE free
-# endif
-# ifndef YYMALLOC
-# define YYMALLOC malloc
-# endif
-
-/* The parser invokes alloca or malloc; define the necessary symbols. */
-
-# ifdef YYSTACK_USE_ALLOCA
-# if YYSTACK_USE_ALLOCA
-# define YYSTACK_ALLOC alloca
-# endif
-# else
-# if defined (alloca) || defined (_ALLOCA_H)
-# define YYSTACK_ALLOC alloca
-# else
-# ifdef __GNUC__
-# define YYSTACK_ALLOC __builtin_alloca
-# endif
-# endif
-# endif
-
-# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-# else
-# if defined (__STDC__) || defined (__cplusplus)
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# endif
-# define YYSTACK_ALLOC YYMALLOC
-# define YYSTACK_FREE YYFREE
-# endif
-#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
-
-
-#if (! defined (yyoverflow) \
- && (! defined (__cplusplus) \
- || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member. */
-union yyalloc
-{
- short int yyss;
- YYSTYPE yyvs;
- };
-
-/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
- N elements. */
-# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
- + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined (__GNUC__) && 1 < __GNUC__
-# define YYCOPY(To, From, Count) \
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-# else
-# define YYCOPY(To, From, Count) \
- do \
- { \
- register YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
- } \
- while (0)
-# endif
-# endif
-
-/* Relocate STACK from its old location to the new one. The
- local variables YYSIZE and YYSTACKSIZE give the old and new number of
- elements in the stack, and YYPTR gives the new location of the
- stack. Advance YYPTR to a properly aligned location for the next
- stack. */
-# define YYSTACK_RELOCATE(Stack) \
- do \
- { \
- YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack, Stack, yysize); \
- Stack = &yyptr->Stack; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
- } \
- while (0)
-
-#endif
-
-#if defined (__STDC__) || defined (__cplusplus)
- typedef signed char yysigned_char;
-#else
- typedef short int yysigned_char;
-#endif
-
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 52
-/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 396
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 23
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 29
-/* YYNRULES -- Number of rules. */
-#define YYNRULES 79
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 128
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
-#define YYUNDEFTOK 2
-#define YYMAXUTOK 269
-
-#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const unsigned char yytranslate[] =
-{
- 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 21, 15, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 16, 2,
- 2, 2, 2, 22, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 17, 2, 18, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 19, 2, 20, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const unsigned char yyprhs[] =
-{
- 0, 0, 3, 5, 8, 9, 11, 13, 15, 18,
- 21, 24, 28, 30, 32, 36, 37, 40, 43, 46,
- 49, 51, 54, 56, 58, 60, 63, 66, 69, 72,
- 75, 77, 79, 81, 85, 87, 89, 91, 93, 95,
- 99, 103, 106, 110, 113, 117, 120, 124, 127, 129,
- 133, 136, 140, 143, 145, 149, 151, 153, 157, 161,
- 165, 168, 172, 175, 179, 182, 184, 188, 190, 194,
- 196, 200, 204, 207, 211, 215, 218, 220, 224, 226
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yysigned_char yyrhs[] =
-{
- 24, 0, -1, 25, -1, 11, 27, -1, -1, 33,
- -1, 26, -1, 34, -1, 5, 26, -1, 6, 26,
- -1, 3, 26, -1, 29, 26, 32, -1, 25, -1,
- 28, -1, 29, 28, 30, -1, -1, 7, 28, -1,
- 5, 28, -1, 6, 28, -1, 3, 28, -1, 12,
- -1, 29, 13, -1, 14, -1, 13, -1, 14, -1,
- 31, 32, -1, 5, 33, -1, 6, 33, -1, 7,
- 33, -1, 3, 33, -1, 4, -1, 8, -1, 9,
- -1, 29, 33, 32, -1, 10, -1, 35, -1, 39,
- -1, 42, -1, 49, -1, 29, 37, 30, -1, 29,
- 38, 30, -1, 15, 27, -1, 5, 31, 38, -1,
- 5, 37, -1, 6, 31, 38, -1, 6, 37, -1,
- 3, 31, 38, -1, 3, 37, -1, 36, -1, 38,
- 31, 36, -1, 38, 31, -1, 17, 40, 18, -1,
- 17, 18, -1, 41, -1, 40, 21, 41, -1, 25,
- -1, 48, -1, 29, 43, 30, -1, 29, 47, 30,
- -1, 5, 31, 47, -1, 5, 43, -1, 6, 31,
- 47, -1, 6, 43, -1, 3, 31, 47, -1, 3,
- 43, -1, 33, -1, 22, 25, 31, -1, 27, -1,
- 44, 16, 45, -1, 46, -1, 47, 31, 36, -1,
- 47, 31, 46, -1, 47, 31, -1, 25, 16, 27,
- -1, 19, 50, 20, -1, 19, 20, -1, 51, -1,
- 50, 21, 51, -1, 25, -1, 48, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const unsigned short int yyrline[] =
-{
- 0, 56, 56, 60, 65, 70, 71, 74, 75, 80,
- 85, 94, 100, 101, 104, 109, 113, 121, 126, 131,
- 145, 146, 149, 152, 155, 156, 164, 169, 174, 182,
- 186, 194, 207, 208, 218, 219, 220, 221, 222, 228,
- 232, 238, 244, 249, 254, 259, 264, 268, 274, 278,
- 283, 292, 296, 302, 306, 313, 314, 320, 325, 332,
- 337, 342, 347, 352, 356, 362, 363, 369, 379, 396,
- 397, 409, 417, 426, 434, 438, 444, 445, 454, 461
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE
-/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
-static const char *const yytname[] =
-{
- "$end", "error", "$undefined", "YAML_ANCHOR", "YAML_ALIAS",
- "YAML_TRANSFER", "YAML_TAGURI", "YAML_ITRANSFER", "YAML_WORD",
- "YAML_PLAIN", "YAML_BLOCK", "YAML_DOCSEP", "YAML_IOPEN", "YAML_INDENT",
- "YAML_IEND", "'-'", "':'", "'['", "']'", "'{'", "'}'", "','", "'?'",
- "$accept", "doc", "atom", "ind_rep", "atom_or_empty", "empty",
- "indent_open", "indent_end", "indent_sep", "indent_flex_end", "word_rep",
- "struct_rep", "implicit_seq", "basic_seq", "top_imp_seq",
- "in_implicit_seq", "inline_seq", "in_inline_seq", "inline_seq_atom",
- "implicit_map", "top_imp_map", "complex_key", "complex_value",
- "complex_mapping", "in_implicit_map", "basic_mapping", "inline_map",
- "in_inline_map", "inline_map_atom", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
-static const unsigned short int yytoknum[] =
-{
- 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
- 265, 266, 267, 268, 269, 45, 58, 91, 93, 123,
- 125, 44, 63
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const unsigned char yyr1[] =
-{
- 0, 23, 24, 24, 24, 25, 25, 26, 26, 26,
- 26, 26, 27, 27, 28, 28, 28, 28, 28, 28,
- 29, 29, 30, 31, 32, 32, 33, 33, 33, 33,
- 33, 33, 33, 33, 34, 34, 34, 34, 34, 35,
- 35, 36, 37, 37, 37, 37, 37, 37, 38, 38,
- 38, 39, 39, 40, 40, 41, 41, 42, 42, 43,
- 43, 43, 43, 43, 43, 44, 44, 45, 46, 47,
- 47, 47, 47, 48, 49, 49, 50, 50, 51, 51
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const unsigned char yyr2[] =
-{
- 0, 2, 1, 2, 0, 1, 1, 1, 2, 2,
- 2, 3, 1, 1, 3, 0, 2, 2, 2, 2,
- 1, 2, 1, 1, 1, 2, 2, 2, 2, 2,
- 1, 1, 1, 3, 1, 1, 1, 1, 1, 3,
- 3, 2, 3, 2, 3, 2, 3, 2, 1, 3,
- 2, 3, 2, 1, 3, 1, 1, 3, 3, 3,
- 2, 3, 2, 3, 2, 1, 3, 1, 3, 1,
- 3, 3, 2, 3, 3, 2, 1, 3, 1, 1
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
- STATE-NUM when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const unsigned char yydefact[] =
-{
- 4, 0, 30, 0, 0, 0, 31, 32, 34, 15,
- 20, 0, 0, 0, 2, 6, 0, 5, 7, 35,
- 36, 37, 38, 10, 29, 8, 26, 9, 27, 0,
- 0, 0, 0, 28, 15, 15, 15, 15, 12, 3,
- 13, 15, 52, 55, 0, 53, 56, 75, 78, 79,
- 0, 76, 1, 0, 0, 0, 21, 15, 0, 0,
- 65, 48, 0, 0, 0, 0, 69, 0, 0, 19,
- 17, 18, 15, 15, 15, 16, 15, 15, 15, 15,
- 0, 15, 51, 0, 74, 0, 23, 0, 47, 64,
- 0, 43, 60, 0, 45, 62, 41, 0, 24, 0,
- 11, 33, 22, 39, 40, 50, 57, 15, 58, 72,
- 14, 73, 54, 77, 65, 46, 63, 42, 59, 44,
- 61, 66, 25, 49, 67, 68, 70, 71
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yysigned_char yydefgoto[] =
-{
- -1, 13, 38, 15, 39, 40, 16, 103, 99, 101,
- 17, 18, 19, 61, 62, 63, 20, 44, 45, 21,
- 64, 65, 125, 66, 67, 46, 22, 50, 51
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -97
-static const short int yypact[] =
-{
- 250, 318, -97, 318, 318, 374, -97, -97, -97, 335,
- -97, 267, 232, 7, -97, -97, 192, -97, -97, -97,
- -97, -97, -97, -97, -97, -97, -97, -97, -97, 374,
- 374, 374, 352, -97, 335, 335, 335, 384, -97, -97,
- -97, 212, -97, 10, 0, -97, -97, -97, 10, -97,
- -4, -97, -97, 284, 284, 284, -97, 335, 318, 30,
- 30, -97, -2, 36, -2, 16, -97, 36, 30, -97,
- -97, -97, 384, 384, 384, -97, 363, 301, 301, 301,
- -2, 335, -97, 318, -97, 318, -97, 158, -97, -97,
- 158, -97, -97, 158, -97, -97, -97, 24, -97, 30,
- -97, -97, -97, -97, -97, 26, -97, 335, -97, 158,
- -97, -97, -97, -97, -97, 24, 24, 24, 24, 24,
- 24, -97, -97, -97, -97, -97, -97, -97
-};
-
-/* YYPGOTO[NTERM-NUM]. */
-static const yysigned_char yypgoto[] =
-{
- -97, -97, 8, 81, -56, 109, 33, -53, 74, -54,
- -1, -97, -97, -96, -31, -32, -97, -97, -44, -97,
- 77, -97, -97, -52, 9, -6, -97, -97, -29
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If zero, do what YYDEFACT says.
- If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -1
-static const unsigned char yytable[] =
-{
- 24, 96, 26, 28, 33, 100, 49, 52, 14, 123,
- 104, 106, 102, 126, 108, 60, 84, 85, 82, 43,
- 48, 83, 88, 91, 94, 111, 81, 110, 24, 26,
- 28, 68, 107, 24, 26, 28, 33, 86, 32, 112,
- 60, 57, 41, 86, 98, 122, 88, 91, 94, 86,
- 102, 124, 24, 26, 28, 115, 113, 127, 117, 0,
- 0, 119, 32, 32, 32, 32, 97, 41, 41, 41,
- 76, 24, 26, 28, 41, 68, 24, 26, 28, 49,
- 0, 0, 23, 0, 25, 27, 114, 0, 0, 114,
- 41, 43, 114, 48, 0, 0, 116, 59, 0, 118,
- 0, 0, 120, 0, 0, 76, 76, 76, 114, 76,
- 41, 41, 41, 0, 41, 23, 25, 27, 0, 0,
- 32, 0, 59, 32, 0, 0, 32, 87, 90, 93,
- 89, 92, 95, 0, 23, 25, 27, 105, 0, 0,
- 41, 109, 32, 69, 70, 71, 75, 0, 0, 0,
- 80, 87, 90, 93, 89, 92, 95, 0, 23, 25,
- 27, 29, 2, 30, 31, 5, 6, 7, 0, 0,
- 10, 121, 0, 57, 0, 0, 0, 0, 0, 0,
- 58, 69, 70, 71, 0, 80, 69, 70, 71, 105,
- 109, 105, 109, 105, 109, 53, 2, 54, 55, 5,
- 6, 7, 8, 0, 10, 56, 0, 57, 0, 11,
- 0, 12, 0, 0, 58, 77, 2, 78, 79, 37,
- 6, 7, 8, 0, 10, 56, 0, 57, 0, 11,
- 0, 12, 0, 0, 58, 1, 2, 3, 4, 5,
- 6, 7, 8, 0, 10, 0, 0, 0, 0, 11,
- 0, 12, 47, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 0, 0, 0, 0, 11, 0, 12,
- 1, 2, 3, 4, 5, 6, 7, 8, 0, 10,
- 0, 0, 0, 0, 11, 42, 12, 53, 2, 54,
- 55, 5, 6, 7, 8, 0, 10, 86, 0, 0,
- 0, 11, 0, 12, 77, 2, 78, 79, 37, 6,
- 7, 8, 0, 10, 86, 0, 0, 0, 11, 0,
- 12, 1, 2, 3, 4, 5, 6, 7, 8, 0,
- 10, 0, 0, 0, 0, 11, 0, 12, 34, 2,
- 35, 36, 37, 6, 7, 8, 0, 10, 0, 0,
- 0, 0, 11, 0, 12, 29, 2, 30, 31, 5,
- 6, 7, 0, 0, 10, 56, 72, 2, 73, 74,
- 37, 6, 7, 0, 0, 10, 56, 29, 2, 30,
- 31, 5, 6, 7, 0, 0, 10, 72, 2, 73,
- 74, 37, 6, 7, 0, 0, 10
-};
-
-static const yysigned_char yycheck[] =
-{
- 1, 57, 3, 4, 5, 59, 12, 0, 0, 105,
- 63, 64, 14, 109, 67, 16, 20, 21, 18, 11,
- 12, 21, 53, 54, 55, 81, 16, 80, 29, 30,
- 31, 32, 16, 34, 35, 36, 37, 13, 5, 83,
- 41, 15, 9, 13, 14, 99, 77, 78, 79, 13,
- 14, 107, 53, 54, 55, 87, 85, 109, 90, -1,
- -1, 93, 29, 30, 31, 32, 58, 34, 35, 36,
- 37, 72, 73, 74, 41, 76, 77, 78, 79, 85,
- -1, -1, 1, -1, 3, 4, 87, -1, -1, 90,
- 57, 83, 93, 85, -1, -1, 87, 16, -1, 90,
- -1, -1, 93, -1, -1, 72, 73, 74, 109, 76,
- 77, 78, 79, -1, 81, 34, 35, 36, -1, -1,
- 87, -1, 41, 90, -1, -1, 93, 53, 54, 55,
- 53, 54, 55, -1, 53, 54, 55, 63, -1, -1,
- 107, 67, 109, 34, 35, 36, 37, -1, -1, -1,
- 41, 77, 78, 79, 77, 78, 79, -1, 77, 78,
- 79, 3, 4, 5, 6, 7, 8, 9, -1, -1,
- 12, 97, -1, 15, -1, -1, -1, -1, -1, -1,
- 22, 72, 73, 74, -1, 76, 77, 78, 79, 115,
- 116, 117, 118, 119, 120, 3, 4, 5, 6, 7,
- 8, 9, 10, -1, 12, 13, -1, 15, -1, 17,
- -1, 19, -1, -1, 22, 3, 4, 5, 6, 7,
- 8, 9, 10, -1, 12, 13, -1, 15, -1, 17,
- -1, 19, -1, -1, 22, 3, 4, 5, 6, 7,
- 8, 9, 10, -1, 12, -1, -1, -1, -1, 17,
- -1, 19, 20, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, -1, -1, -1, -1, 17, -1, 19,
- 3, 4, 5, 6, 7, 8, 9, 10, -1, 12,
- -1, -1, -1, -1, 17, 18, 19, 3, 4, 5,
- 6, 7, 8, 9, 10, -1, 12, 13, -1, -1,
- -1, 17, -1, 19, 3, 4, 5, 6, 7, 8,
- 9, 10, -1, 12, 13, -1, -1, -1, 17, -1,
- 19, 3, 4, 5, 6, 7, 8, 9, 10, -1,
- 12, -1, -1, -1, -1, 17, -1, 19, 3, 4,
- 5, 6, 7, 8, 9, 10, -1, 12, -1, -1,
- -1, -1, 17, -1, 19, 3, 4, 5, 6, 7,
- 8, 9, -1, -1, 12, 13, 3, 4, 5, 6,
- 7, 8, 9, -1, -1, 12, 13, 3, 4, 5,
- 6, 7, 8, 9, -1, -1, 12, 3, 4, 5,
- 6, 7, 8, 9, -1, -1, 12
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const unsigned char yystos[] =
-{
- 0, 3, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 17, 19, 24, 25, 26, 29, 33, 34, 35,
- 39, 42, 49, 26, 33, 26, 33, 26, 33, 3,
- 5, 6, 29, 33, 3, 5, 6, 7, 25, 27,
- 28, 29, 18, 25, 40, 41, 48, 20, 25, 48,
- 50, 51, 0, 3, 5, 6, 13, 15, 22, 26,
- 33, 36, 37, 38, 43, 44, 46, 47, 33, 28,
- 28, 28, 3, 5, 6, 28, 29, 3, 5, 6,
- 28, 16, 18, 21, 20, 21, 13, 31, 37, 43,
- 31, 37, 43, 31, 37, 43, 27, 25, 14, 31,
- 32, 32, 14, 30, 30, 31, 30, 16, 30, 31,
- 30, 27, 41, 51, 33, 38, 47, 38, 47, 38,
- 47, 31, 32, 36, 27, 45, 36, 46
-};
-
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
-# define YYSIZE_T __SIZE_TYPE__
-#endif
-#if ! defined (YYSIZE_T) && defined (size_t)
-# define YYSIZE_T size_t
-#endif
-#if ! defined (YYSIZE_T)
-# if defined (__STDC__) || defined (__cplusplus)
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# endif
-#endif
-#if ! defined (YYSIZE_T)
-# define YYSIZE_T unsigned int
-#endif
-
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
-
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
-
-#define YYFAIL goto yyerrlab
-
-#define YYRECOVERING() (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY && yylen == 1) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- yytoken = YYTRANSLATE (yychar); \
- YYPOPSTACK; \
- goto yybackup; \
- } \
- else \
- { \
- yyerror ("syntax error: cannot back up");\
- YYERROR; \
- } \
-while (0)
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-/* YYLLOC_DEFAULT -- Compute the default location (before the actions
- are run). */
-
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- ((Current).first_line = (Rhs)[1].first_line, \
- (Current).first_column = (Rhs)[1].first_column, \
- (Current).last_line = (Rhs)[N].last_line, \
- (Current).last_column = (Rhs)[N].last_column)
-#endif
-
-/* YYLEX -- calling `yylex' with the right arguments. */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval)
-#endif
-
-/* Enable debugging if requested. */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-# define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
-} while (0)
-
-# define YYDSYMPRINT(Args) \
-do { \
- if (yydebug) \
- yysymprint Args; \
-} while (0)
-
-# define YYDSYMPRINTF(Title, Token, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yysymprint (stderr, \
- Token, Value); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (0)
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included). |
-`------------------------------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_stack_print (short int *bottom, short int *top)
-#else
-static void
-yy_stack_print (bottom, top)
- short int *bottom;
- short int *top;
-#endif
-{
- YYFPRINTF (stderr, "Stack now");
- for (/* Nothing. */; bottom <= top; ++bottom)
- YYFPRINTF (stderr, " %d", *bottom);
- YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
-} while (0)
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced. |
-`------------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_reduce_print (int yyrule)
-#else
-static void
-yy_reduce_print (yyrule)
- int yyrule;
-#endif
-{
- int yyi;
- unsigned int yylno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
- yyrule - 1, yylno);
- /* Print the symbols being reduced, and their result. */
- for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
- YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
- YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
-}
-
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (Rule); \
-} while (0)
-
-/* Nonzero means print parse trace. It is left uninitialized so that
- multiple parsers can coexist. */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YYDSYMPRINT(Args)
-# define YYDSYMPRINTF(Title, Token, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
- if the built-in stack extension method is used).
-
- Do not make this value too large; the results are undefined if
- SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
- evaluated with infinite-precision integer arithmetic. */
-
-#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
-# undef YYMAXDEPTH
-#endif
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-# if defined (__GLIBC__) && defined (_STRING_H)
-# define yystrlen strlen
-# else
-/* Return the length of YYSTR. */
-static YYSIZE_T
-# if defined (__STDC__) || defined (__cplusplus)
-yystrlen (const char *yystr)
-# else
-yystrlen (yystr)
- const char *yystr;
-# endif
-{
- register const char *yys = yystr;
-
- while (*yys++ != '\0')
- continue;
-
- return yys - yystr - 1;
-}
-# endif
-# endif
-
-# ifndef yystpcpy
-# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
-# define yystpcpy stpcpy
-# else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
- YYDEST. */
-static char *
-# if defined (__STDC__) || defined (__cplusplus)
-yystpcpy (char *yydest, const char *yysrc)
-# else
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-# endif
-{
- register char *yyd = yydest;
- register const char *yys = yysrc;
-
- while ((*yyd++ = *yys++) != '\0')
- continue;
-
- return yyd - 1;
-}
-# endif
-# endif
-
-#endif /* !YYERROR_VERBOSE */
-
-
-
-#if YYDEBUG
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yysymprint (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
-{
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
-
- if (yytype < YYNTOKENS)
- {
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-# ifdef YYPRINT
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
- }
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
- switch (yytype)
- {
- default:
- break;
- }
- YYFPRINTF (yyoutput, ")");
-}
-
-#endif /* ! YYDEBUG */
-/*-----------------------------------------------.
-| Release the memory associated to this symbol. |
-`-----------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yydestruct (int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yytype, yyvaluep)
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
-{
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
-
- switch (yytype)
- {
-
- default:
- break;
- }
-}
-
-
-/* Prevent warnings from -Wmissing-prototypes. */
-
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM);
-# else
-int yyparse ();
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-
-
-
-/*----------.
-| yyparse. |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM)
-# else
-int yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
- /* The lookahead symbol. */
-int yychar;
-
-/* The semantic value of the lookahead symbol. */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far. */
-int yynerrs;
-
- register int yystate;
- register int yyn;
- int yyresult;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
- /* Lookahead token as an internal (translated) token number. */
- int yytoken = 0;
-
- /* Three stacks and their tools:
- `yyss': related to states,
- `yyvs': related to semantic values,
- `yyls': related to locations.
-
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
-
- /* The state stack. */
- short int yyssa[YYINITDEPTH];
- short int *yyss = yyssa;
- register short int *yyssp;
-
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- register YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK (yyvsp--, yyssp--)
-
- YYSIZE_T yystacksize = YYINITDEPTH;
-
- /* The variables used to return semantic value and location from the
- action routines. */
- YYSTYPE yyval;
-
-
- /* When reducing, the number of symbols on the RHS of the reduced
- rule. */
- int yylen;
-
- YYDPRINTF ((stderr, "Starting parse\n"));
-
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
-
- yyssp = yyss;
- yyvsp = yyvs;
-
-
- goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate. |
-`------------------------------------------------------------*/
- yynewstate:
- /* In all cases, when you get here, the value and location stacks
- have just been pushed. so pushing a state here evens the stacks.
- */
- yyssp++;
-
- yysetstate:
- *yyssp = yystate;
-
- if (yyss + yystacksize - 1 <= yyssp)
- {
- /* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
- {
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- YYSTYPE *yyvs1 = yyvs;
- short int *yyss1 = yyss;
-
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow ("parser stack overflow",
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
-
- &yystacksize);
-
- yyss = yyss1;
- yyvs = yyvs1;
- }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyoverflowlab;
-# else
- /* Extend the stack our own way. */
- if (YYMAXDEPTH <= yystacksize)
- goto yyoverflowlab;
- yystacksize *= 2;
- if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
-
- {
- short int *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyoverflowlab;
- YYSTACK_RELOCATE (yyss);
- YYSTACK_RELOCATE (yyvs);
-
-# undef YYSTACK_RELOCATE
- if (yyss1 != yyssa)
- YYSTACK_FREE (yyss1);
- }
-# endif
-#endif /* no yyoverflow */
-
- yyssp = yyss + yysize - 1;
- yyvsp = yyvs + yysize - 1;
-
-
- YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
-
- if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
- }
-
- YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
- goto yybackup;
-
-/*-----------.
-| yybackup. |
-`-----------*/
-yybackup:
-
-/* Do appropriate processing given the current state. */
-/* Read a lookahead token if we need one and don't already have one. */
-/* yyresume: */
-
- /* First try to decide what to do without reference to lookahead token. */
-
- yyn = yypact[yystate];
- if (yyn == YYPACT_NINF)
- goto yydefault;
-
- /* Not known => get a lookahead token if don't already have one. */
-
- /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
- if (yychar == YYEMPTY)
- {
- YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
- }
-
- if (yychar <= YYEOF)
- {
- yychar = yytoken = YYEOF;
- YYDPRINTF ((stderr, "Now at end of input.\n"));
- }
- else
- {
- yytoken = YYTRANSLATE (yychar);
- YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
- }
-
- /* If the proper action on seeing token YYTOKEN is to reduce or to
- detect an error, take that action. */
- yyn += yytoken;
- if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
- goto yydefault;
- yyn = yytable[yyn];
- if (yyn <= 0)
- {
- if (yyn == 0 || yyn == YYTABLE_NINF)
- goto yyerrlab;
- yyn = -yyn;
- goto yyreduce;
- }
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- /* Shift the lookahead token. */
- YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
-
- /* Discard the token being shifted unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
-
- *++yyvsp = yylval;
-
-
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
-
- yystate = yyn;
- goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state. |
-`-----------------------------------------------------------*/
-yydefault:
- yyn = yydefact[yystate];
- if (yyn == 0)
- goto yyerrlab;
- goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction. |
-`-----------------------------*/
-yyreduce:
- /* yyn is the number of a rule to reduce with. */
- yylen = yyr2[yyn];
-
- /* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
-
- Otherwise, the following line sets YYVAL to garbage.
- This behavior is undocumented and Bison
- users should not rely upon it. Assigning to YYVAL
- unconditionally makes the parser a bit smaller, and it avoids a
- GCC warning that YYVAL may be used uninitialized. */
- yyval = yyvsp[1-yylen];
-
-
- YY_REDUCE_PRINT (yyn);
- switch (yyn)
- {
- case 2:
-#line 57 "gram.y"
- {
- ((SyckParser *)parser)->root = syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData );
- }
- break;
-
- case 3:
-#line 61 "gram.y"
- {
- ((SyckParser *)parser)->root = syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData );
- }
- break;
-
- case 4:
-#line 65 "gram.y"
- {
- ((SyckParser *)parser)->eof = 1;
- }
- break;
-
- case 8:
-#line 76 "gram.y"
- {
- syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 9:
-#line 81 "gram.y"
- {
- syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, 0 );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 10:
-#line 86 "gram.y"
- {
- /*
- * _Anchors_: The language binding must keep a separate symbol table
- * for anchors. The actual ID in the symbol table is returned to the
- * higher nodes, though.
- */
- yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-1].name, yyvsp[0].nodeData );
- }
- break;
-
- case 11:
-#line 95 "gram.y"
- {
- yyval.nodeData = yyvsp[-1].nodeData;
- }
- break;
-
- case 14:
-#line 105 "gram.y"
- {
- yyval.nodeData = yyvsp[-1].nodeData;
- }
- break;
-
- case 15:
-#line 109 "gram.y"
- {
- NULL_NODE( parser, n );
- yyval.nodeData = n;
- }
- break;
-
- case 16:
-#line 114 "gram.y"
- {
- if ( ((SyckParser *)parser)->implicit_typing == 1 )
- {
- try_tag_implicit( yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
- }
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 17:
-#line 122 "gram.y"
- {
- syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 18:
-#line 127 "gram.y"
- {
- syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, 0 );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 19:
-#line 132 "gram.y"
- {
- /*
- * _Anchors_: The language binding must keep a separate symbol table
- * for anchors. The actual ID in the symbol table is returned to the
- * higher nodes, though.
- */
- yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-1].name, yyvsp[0].nodeData );
- }
- break;
-
- case 26:
-#line 165 "gram.y"
- {
- syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 27:
-#line 170 "gram.y"
- {
- syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, 0 );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 28:
-#line 175 "gram.y"
- {
- if ( ((SyckParser *)parser)->implicit_typing == 1 )
- {
- try_tag_implicit( yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
- }
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 29:
-#line 183 "gram.y"
- {
- yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-1].name, yyvsp[0].nodeData );
- }
- break;
-
- case 30:
-#line 187 "gram.y"
- {
- /*
- * _Aliases_: The anchor symbol table is scanned for the anchor name.
- * The anchor's ID in the language's symbol table is returned.
- */
- yyval.nodeData = syck_hdlr_get_anchor( (SyckParser *)parser, yyvsp[0].name );
- }
- break;
-
- case 31:
-#line 195 "gram.y"
- {
- SyckNode *n = yyvsp[0].nodeData;
- if ( ((SyckParser *)parser)->taguri_expansion == 1 )
- {
- n->type_id = syck_taguri( YAML_DOMAIN, "str", 3 );
- }
- else
- {
- n->type_id = syck_strndup( "str", 3 );
- }
- yyval.nodeData = n;
- }
- break;
-
- case 33:
-#line 209 "gram.y"
- {
- yyval.nodeData = yyvsp[-1].nodeData;
- }
- break;
-
- case 39:
-#line 229 "gram.y"
- {
- yyval.nodeData = yyvsp[-1].nodeData;
- }
- break;
-
- case 40:
-#line 233 "gram.y"
- {
- yyval.nodeData = yyvsp[-1].nodeData;
- }
- break;
-
- case 41:
-#line 239 "gram.y"
- {
- yyval.nodeId = syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData );
- }
- break;
-
- case 42:
-#line 245 "gram.y"
- {
- syck_add_transfer( yyvsp[-2].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 43:
-#line 250 "gram.y"
- {
- syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 44:
-#line 255 "gram.y"
- {
- syck_add_transfer( yyvsp[-2].name, yyvsp[0].nodeData, 0 );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 45:
-#line 260 "gram.y"
- {
- syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, 0 );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 46:
-#line 265 "gram.y"
- {
- yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-2].name, yyvsp[0].nodeData );
- }
- break;
-
- case 47:
-#line 269 "gram.y"
- {
- yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-1].name, yyvsp[0].nodeData );
- }
- break;
-
- case 48:
-#line 275 "gram.y"
- {
- yyval.nodeData = syck_new_seq( yyvsp[0].nodeId );
- }
- break;
-
- case 49:
-#line 279 "gram.y"
- {
- syck_seq_add( yyvsp[-2].nodeData, yyvsp[0].nodeId );
- yyval.nodeData = yyvsp[-2].nodeData;
- }
- break;
-
- case 50:
-#line 284 "gram.y"
- {
- yyval.nodeData = yyvsp[-1].nodeData;
- }
- break;
-
- case 51:
-#line 293 "gram.y"
- {
- yyval.nodeData = yyvsp[-1].nodeData;
- }
- break;
-
- case 52:
-#line 297 "gram.y"
- {
- yyval.nodeData = syck_alloc_seq();
- }
- break;
-
- case 53:
-#line 303 "gram.y"
- {
- yyval.nodeData = syck_new_seq( syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData ) );
- }
- break;
-
- case 54:
-#line 307 "gram.y"
- {
- syck_seq_add( yyvsp[-2].nodeData, syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData ) );
- yyval.nodeData = yyvsp[-2].nodeData;
- }
- break;
-
- case 57:
-#line 321 "gram.y"
- {
- apply_seq_in_map( (SyckParser *)parser, yyvsp[-1].nodeData );
- yyval.nodeData = yyvsp[-1].nodeData;
- }
- break;
-
- case 58:
-#line 326 "gram.y"
- {
- apply_seq_in_map( (SyckParser *)parser, yyvsp[-1].nodeData );
- yyval.nodeData = yyvsp[-1].nodeData;
- }
- break;
-
- case 59:
-#line 333 "gram.y"
- {
- syck_add_transfer( yyvsp[-2].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 60:
-#line 338 "gram.y"
- {
- syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 61:
-#line 343 "gram.y"
- {
- syck_add_transfer( yyvsp[-2].name, yyvsp[0].nodeData, 0 );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 62:
-#line 348 "gram.y"
- {
- syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, 0 );
- yyval.nodeData = yyvsp[0].nodeData;
- }
- break;
-
- case 63:
-#line 353 "gram.y"
- {
- yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-2].name, yyvsp[0].nodeData );
- }
- break;
-
- case 64:
-#line 357 "gram.y"
- {
- yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-1].name, yyvsp[0].nodeData );
- }
- break;
-
- case 66:
-#line 364 "gram.y"
- {
- yyval.nodeData = yyvsp[-1].nodeData;
- }
- break;
-
- case 68:
-#line 380 "gram.y"
- {
- yyval.nodeData = syck_new_map(
- syck_hdlr_add_node( (SyckParser *)parser, yyvsp[-2].nodeData ),
- syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData ) );
- }
- break;
-
- case 70:
-#line 398 "gram.y"
- {
- if ( yyvsp[-2].nodeData->shortcut == NULL )
- {
- yyvsp[-2].nodeData->shortcut = syck_new_seq( yyvsp[0].nodeId );
- }
- else
- {
- syck_seq_add( yyvsp[-2].nodeData->shortcut, yyvsp[0].nodeId );
- }
- yyval.nodeData = yyvsp[-2].nodeData;
- }
- break;
-
- case 71:
-#line 410 "gram.y"
- {
- apply_seq_in_map( (SyckParser *)parser, yyvsp[-2].nodeData );
- syck_map_update( yyvsp[-2].nodeData, yyvsp[0].nodeData );
- syck_free_node( yyvsp[0].nodeData );
- yyvsp[0].nodeData = NULL;
- yyval.nodeData = yyvsp[-2].nodeData;
- }
- break;
-
- case 72:
-#line 418 "gram.y"
- {
- yyval.nodeData = yyvsp[-1].nodeData;
- }
- break;
-
- case 73:
-#line 427 "gram.y"
- {
- yyval.nodeData = syck_new_map(
- syck_hdlr_add_node( (SyckParser *)parser, yyvsp[-2].nodeData ),
- syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData ) );
- }
- break;
-
- case 74:
-#line 435 "gram.y"
- {
- yyval.nodeData = yyvsp[-1].nodeData;
- }
- break;
-
- case 75:
-#line 439 "gram.y"
- {
- yyval.nodeData = syck_alloc_map();
- }
- break;
-
- case 77:
-#line 446 "gram.y"
- {
- syck_map_update( yyvsp[-2].nodeData, yyvsp[0].nodeData );
- syck_free_node( yyvsp[0].nodeData );
- yyvsp[0].nodeData = NULL;
- yyval.nodeData = yyvsp[-2].nodeData;
- }
- break;
-
- case 78:
-#line 455 "gram.y"
- {
- NULL_NODE( parser, n );
- yyval.nodeData = syck_new_map(
- syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData ),
- syck_hdlr_add_node( (SyckParser *)parser, n ) );
- }
- break;
-
-
- }
-
-/* Line 1010 of yacc.c. */
-#line 1651 "gram.c"
-
- yyvsp -= yylen;
- yyssp -= yylen;
-
-
- YY_STACK_PRINT (yyss, yyssp);
-
- *++yyvsp = yyval;
-
-
- /* Now `shift' the result of the reduction. Determine what state
- that goes to, based on the state we popped back to and the rule
- number reduced by. */
-
- yyn = yyr1[yyn];
-
- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTOKENS];
-
- goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
- /* If not already recovering from an error, report this error. */
- if (!yyerrstatus)
- {
- ++yynerrs;
-#if YYERROR_VERBOSE
- yyn = yypact[yystate];
-
- if (YYPACT_NINF < yyn && yyn < YYLAST)
- {
- YYSIZE_T yysize = 0;
- int yytype = YYTRANSLATE (yychar);
- const char* yyprefix;
- char *yymsg;
- int yyx;
-
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 0;
-
- yyprefix = ", expecting ";
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
- yycount += 1;
- if (yycount == 5)
- {
- yysize = 0;
- break;
- }
- }
- yysize += (sizeof ("syntax error, unexpected ")
- + yystrlen (yytname[yytype]));
- yymsg = (char *) YYSTACK_ALLOC (yysize);
- if (yymsg != 0)
- {
- char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
- yyp = yystpcpy (yyp, yytname[yytype]);
-
- if (yycount < 5)
- {
- yyprefix = ", expecting ";
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- yyp = yystpcpy (yyp, yyprefix);
- yyp = yystpcpy (yyp, yytname[yyx]);
- yyprefix = " or ";
- }
- }
- yyerror (yymsg);
- YYSTACK_FREE (yymsg);
- }
- else
- yyerror ("syntax error; also virtual memory exhausted");
- }
- else
-#endif /* YYERROR_VERBOSE */
- yyerror ("syntax error");
- }
-
-
-
- if (yyerrstatus == 3)
- {
- /* If just tried and failed to reuse lookahead token after an
- error, discard it. */
-
- if (yychar <= YYEOF)
- {
- /* If at end of input, pop the error token,
- then the rest of the stack, then return failure. */
- if (yychar == YYEOF)
- for (;;)
- {
- YYPOPSTACK;
- if (yyssp == yyss)
- YYABORT;
- YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
- yydestruct (yystos[*yyssp], yyvsp);
- }
- }
- else
- {
- YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
- yydestruct (yytoken, &yylval);
- yychar = YYEMPTY;
-
- }
- }
-
- /* Else will try to reuse lookahead token after shifting the error
- token. */
- goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR. |
-`---------------------------------------------------*/
-yyerrorlab:
-
-#ifdef __GNUC__
- /* Pacify GCC when the user code never invokes YYERROR and the label
- yyerrorlab therefore never appears in user code. */
- if (0)
- goto yyerrorlab;
-#endif
-
- yyvsp -= yylen;
- yyssp -= yylen;
- yystate = *yyssp;
- goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR. |
-`-------------------------------------------------------------*/
-yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
-
- for (;;)
- {
- yyn = yypact[yystate];
- if (yyn != YYPACT_NINF)
- {
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
-
- /* Pop the current state because it cannot handle the error token. */
- if (yyssp == yyss)
- YYABORT;
-
- YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
- yydestruct (yystos[yystate], yyvsp);
- YYPOPSTACK;
- yystate = *yyssp;
- YY_STACK_PRINT (yyss, yyssp);
- }
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- YYDPRINTF ((stderr, "Shifting error token, "));
-
- *++yyvsp = yylval;
-
-
- yystate = yyn;
- goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here. |
-`-------------------------------------*/
-yyacceptlab:
- yyresult = 0;
- goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here. |
-`-----------------------------------*/
-yyabortlab:
- yyresult = 1;
- goto yyreturn;
-
-#ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here. |
-`----------------------------------------------*/
-yyoverflowlab:
- yyerror ("parser stack overflow");
- yyresult = 2;
- /* Fall through. */
-#endif
-
-yyreturn:
-#ifndef yyoverflow
- if (yyss != yyssa)
- YYSTACK_FREE (yyss);
-#endif
- return yyresult;
-}
-
-
-#line 464 "gram.y"
-
-
-void
-apply_seq_in_map( SyckParser *parser, SyckNode *n )
-{
- long map_len;
- if ( n->shortcut == NULL )
- {
- return;
- }
-
- map_len = syck_map_count( n );
- syck_map_assign( n, map_value, map_len - 1,
- syck_hdlr_add_node( parser, n->shortcut ) );
-
- n->shortcut = NULL;
-}
-
-
diff --git a/ext/syck/gram.h b/ext/syck/gram.h
deleted file mode 100644
index 547149ab4b..0000000000
--- a/ext/syck/gram.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* A Bison parser, made by GNU Bison 1.875d. */
-
-/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- YAML_ANCHOR = 258,
- YAML_ALIAS = 259,
- YAML_TRANSFER = 260,
- YAML_TAGURI = 261,
- YAML_ITRANSFER = 262,
- YAML_WORD = 263,
- YAML_PLAIN = 264,
- YAML_BLOCK = 265,
- YAML_DOCSEP = 266,
- YAML_IOPEN = 267,
- YAML_INDENT = 268,
- YAML_IEND = 269
- };
-#endif
-#define YAML_ANCHOR 258
-#define YAML_ALIAS 259
-#define YAML_TRANSFER 260
-#define YAML_TAGURI 261
-#define YAML_ITRANSFER 262
-#define YAML_WORD 263
-#define YAML_PLAIN 264
-#define YAML_BLOCK 265
-#define YAML_DOCSEP 266
-#define YAML_IOPEN 267
-#define YAML_INDENT 268
-#define YAML_IEND 269
-
-
-
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-#line 35 "gram.y"
-typedef union YYSTYPE {
- SYMID nodeId;
- SyckNode *nodeData;
- char *name;
-} YYSTYPE;
-/* Line 1285 of yacc.c. */
-#line 71 "gram.h"
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-
-
diff --git a/ext/syck/handler.c b/ext/syck/handler.c
deleted file mode 100644
index 56fe838fbd..0000000000
--- a/ext/syck/handler.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * handler.c
- *
- * $Author$
- * $Date$
- *
- * Copyright (C) 2003 why the lucky stiff
- */
-
-#include "ruby.h"
-#include "syck.h"
-
-SYMID
-syck_hdlr_add_node( SyckParser *p, SyckNode *n )
-{
- SYMID id;
-
- if ( ! n->id )
- {
- n->id = (p->handler)( p, n );
- }
- id = n->id;
-
- if ( n->anchor == NULL )
- {
- syck_free_node( n );
- }
- return id;
-}
-
-SyckNode *
-syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n )
-{
- SyckNode *ntmp = NULL;
-
- n->anchor = a;
- if ( p->bad_anchors != NULL )
- {
- SyckNode *bad;
- if ( st_lookup( p->bad_anchors, (st_data_t)a, (st_data_t *)&bad ) )
- {
- if ( n->kind != syck_str_kind )
- {
- n->id = bad->id;
- (p->handler)( p, n );
- }
- }
- }
- if ( p->anchors == NULL )
- {
- p->anchors = st_init_strtable();
- }
- if ( st_lookup( p->anchors, (st_data_t)a, (st_data_t *)&ntmp ) )
- {
- if ( ntmp != (void *)1 )
- {
- syck_free_node( ntmp );
- }
- }
- st_insert( p->anchors, (st_data_t)a, (st_data_t)n );
- return n;
-}
-
-void
-syck_hdlr_remove_anchor( SyckParser *p, char *a )
-{
- char *atmp = a;
- SyckNode *ntmp;
- if ( p->anchors == NULL )
- {
- p->anchors = st_init_strtable();
- }
- if ( st_delete( p->anchors, (st_data_t *)&atmp, (st_data_t *)&ntmp ) )
- {
- if ( ntmp != (void *)1 )
- {
- syck_free_node( ntmp );
- }
- }
- st_insert( p->anchors, (st_data_t)a, (st_data_t)1 );
-}
-
-SyckNode *
-syck_hdlr_get_anchor( SyckParser *p, char *a )
-{
- SyckNode *n = NULL;
-
- if ( p->anchors != NULL )
- {
- if ( st_lookup( p->anchors, (st_data_t)a, (st_data_t *)&n ) )
- {
- if ( n != (void *)1 )
- {
- S_FREE( a );
- return n;
- }
- else
- {
- if ( p->bad_anchors == NULL )
- {
- p->bad_anchors = st_init_strtable();
- }
- if ( ! st_lookup( p->bad_anchors, (st_data_t)a, (st_data_t *)&n ) )
- {
- n = (p->bad_anchor_handler)( p, a );
- st_insert( p->bad_anchors, (st_data_t)a, (st_data_t)n );
- }
- }
- }
- }
-
- if ( n == NULL )
- {
- n = (p->bad_anchor_handler)( p, a );
- }
-
- if ( n->anchor )
- {
- S_FREE( a );
- }
- else
- {
- n->anchor = a;
- }
-
- return n;
-}
-
-void
-syck_add_transfer( char *uri, SyckNode *n, int taguri )
-{
- if ( n->type_id != NULL )
- {
- S_FREE( n->type_id );
- }
-
- if ( taguri == 0 )
- {
- n->type_id = uri;
- return;
- }
-
- n->type_id = syck_type_id_to_uri( uri );
- S_FREE( uri );
-}
-
-char *
-syck_xprivate( char *type_id, int type_len )
-{
- char *uri = S_ALLOC_N( char, type_len + 14 );
- uri[0] = '\0';
- strcat( uri, "x-private:" );
- strncat( uri, type_id, type_len );
- return uri;
-}
-
-char *
-syck_taguri( char *domain, char *type_id, int type_len )
-{
- char *uri = S_ALLOC_N( char, strlen( domain ) + type_len + 14 );
- uri[0] = '\0';
- strcat( uri, "tag:" );
- strcat( uri, domain );
- strcat( uri, ":" );
- strncat( uri, type_id, type_len );
- return uri;
-}
-
-int
-syck_try_implicit( SyckNode *n )
-{
- return 1;
-}
-
diff --git a/ext/syck/implicit.c b/ext/syck/implicit.c
deleted file mode 100644
index d356faf7d9..0000000000
--- a/ext/syck/implicit.c
+++ /dev/null
@@ -1,2990 +0,0 @@
-/* Generated by re2c 0.9.10 on Mon Sep 19 21:46:50 2005 */
-#line 1 "implicit.re"
-/*
- * implicit.re
- *
- * $Author$
- * $Date$
- *
- * Copyright (C) 2003 why the lucky stiff
- */
-
-#include "ruby.h"
-#include "syck.h"
-
-#define YYCTYPE char
-#define YYCURSOR cursor
-#define YYMARKER marker
-#define YYLIMIT limit
-#define YYFILL(n)
-
-void
-try_tag_implicit( SyckNode *n, int taguri )
-{
- char *tid = "";
- switch ( n->kind )
- {
- case syck_str_kind:
- tid = syck_match_implicit( n->data.str->ptr, n->data.str->len );
- break;
-
- case syck_seq_kind:
- tid = "seq";
- break;
-
- case syck_map_kind:
- tid = "map";
- break;
- }
- if ( n->type_id != NULL ) S_FREE( n->type_id );
- if ( taguri == 1 )
- {
- n->type_id = syck_taguri( YAML_DOMAIN, tid, strlen( tid ) );
- } else {
- n->type_id = syck_strndup( tid, strlen( tid ) );
- }
-}
-
-char *syck_match_implicit( char *str, size_t len )
-{
- char *cursor, *limit, *marker;
- cursor = str;
- limit = str + len;
-
-
-#line 55 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy0;
- ++YYCURSOR;
-yy0:
- if((YYLIMIT - YYCURSOR) < 26) YYFILL(26);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy6;
- case '+': goto yy16;
- case '-': goto yy17;
- case '.': goto yy20;
- case '0': goto yy18;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy19;
- case '<': goto yy22;
- case '=': goto yy21;
- case 'F': goto yy15;
- case 'N': goto yy5;
- case 'O': goto yy13;
- case 'T': goto yy11;
- case 'Y': goto yy9;
- case 'f': goto yy14;
- case 'n': goto yy4;
- case 'o': goto yy12;
- case 't': goto yy10;
- case 'y': goto yy8;
- case '~': goto yy2;
- default: goto yy23;
- }
-yy2: ++YYCURSOR;
- if((yych = *YYCURSOR) <= 0x00) goto yy6;
- goto yy3;
-yy3:
-#line 123 "implicit.re"
-{ return "str"; }
-#line 100 "<stdout>"
-yy4: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 'o': goto yy172;
- case 'u': goto yy200;
- default: goto yy3;
- }
-yy5: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 'O': case 'o': goto yy172;
- case 'U': goto yy195;
- case 'u': goto yy196;
- default: goto yy3;
- }
-yy6: ++YYCURSOR;
- goto yy7;
-yy7:
-#line 85 "implicit.re"
-{ return "null"; }
-#line 121 "<stdout>"
-yy8: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 'e': goto yy194;
- default: goto yy3;
- }
-yy9: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 'E': goto yy192;
- case 'e': goto yy193;
- default: goto yy3;
- }
-yy10: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 'r': goto yy190;
- default: goto yy3;
- }
-yy11: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 'R': goto yy186;
- case 'r': goto yy187;
- default: goto yy3;
- }
-yy12: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 'f': goto yy185;
- case 'n': goto yy182;
- default: goto yy3;
- }
-yy13: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 'F': goto yy180;
- case 'N': case 'n': goto yy182;
- case 'f': goto yy181;
- default: goto yy3;
- }
-yy14: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 'a': goto yy177;
- default: goto yy3;
- }
-yy15: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 'A': goto yy168;
- case 'a': goto yy169;
- default: goto yy3;
- }
-yy16: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case '.': goto yy167;
- case '0': goto yy158;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy47;
- default: goto yy3;
- }
-yy17: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case '.': goto yy157;
- case '0': goto yy158;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy47;
- default: goto yy3;
- }
-yy18: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 0x00: goto yy52;
- case ',': goto yy142;
- case '.': goto yy50;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': goto yy140;
- case '8':
- case '9': goto yy141;
- case ':': goto yy49;
- case 'x': goto yy144;
- default: goto yy3;
- }
-yy19: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 0x00: goto yy52;
- case ',': goto yy47;
- case '.': goto yy50;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy46;
- case ':': goto yy49;
- default: goto yy3;
- }
-yy20: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 'I': goto yy33;
- case 'N': goto yy31;
- case 'i': goto yy32;
- case 'n': goto yy30;
- default: goto yy3;
- }
-yy21: yych = *++YYCURSOR;
- if(yych <= 0x00) goto yy28;
- goto yy3;
-yy22: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case '<': goto yy24;
- default: goto yy3;
- }
-yy23: yych = *++YYCURSOR;
- goto yy3;
-yy24: yych = *++YYCURSOR;
- if(yych <= 0x00) goto yy26;
- goto yy25;
-yy25: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy3;
- }
-yy26: ++YYCURSOR;
- goto yy27;
-yy27:
-#line 121 "implicit.re"
-{ return "merge"; }
-#line 279 "<stdout>"
-yy28: ++YYCURSOR;
- goto yy29;
-yy29:
-#line 119 "implicit.re"
-{ return "default"; }
-#line 285 "<stdout>"
-yy30: yych = *++YYCURSOR;
- switch(yych){
- case 'a': goto yy45;
- default: goto yy25;
- }
-yy31: yych = *++YYCURSOR;
- switch(yych){
- case 'A': goto yy40;
- case 'a': goto yy41;
- default: goto yy25;
- }
-yy32: yych = *++YYCURSOR;
- switch(yych){
- case 'n': goto yy39;
- default: goto yy25;
- }
-yy33: yych = *++YYCURSOR;
- switch(yych){
- case 'N': goto yy34;
- case 'n': goto yy35;
- default: goto yy25;
- }
-yy34: yych = *++YYCURSOR;
- switch(yych){
- case 'F': goto yy36;
- default: goto yy25;
- }
-yy35: yych = *++YYCURSOR;
- switch(yych){
- case 'f': goto yy36;
- default: goto yy25;
- }
-yy36: yych = *++YYCURSOR;
- if(yych >= 0x01) goto yy25;
- goto yy37;
-yy37: ++YYCURSOR;
- goto yy38;
-yy38:
-#line 105 "implicit.re"
-{ return "float#inf"; }
-#line 326 "<stdout>"
-yy39: yych = *++YYCURSOR;
- switch(yych){
- case 'f': goto yy36;
- default: goto yy25;
- }
-yy40: yych = *++YYCURSOR;
- switch(yych){
- case 'N': goto yy42;
- default: goto yy25;
- }
-yy41: yych = *++YYCURSOR;
- switch(yych){
- case 'N': goto yy42;
- default: goto yy25;
- }
-yy42: yych = *++YYCURSOR;
- if(yych >= 0x01) goto yy25;
- goto yy43;
-yy43: ++YYCURSOR;
- goto yy44;
-yy44:
-#line 109 "implicit.re"
-{ return "float#nan"; }
-#line 350 "<stdout>"
-yy45: yych = *++YYCURSOR;
- switch(yych){
- case 'n': goto yy42;
- default: goto yy25;
- }
-yy46: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy74;
- default: goto yy48;
- }
-yy47: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy48;
-yy48: switch(yych){
- case 0x00: goto yy52;
- case ',': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy47;
- case '.': goto yy50;
- case ':': goto yy49;
- default: goto yy25;
- }
-yy49: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5': goto yy66;
- case '6':
- case '7':
- case '8':
- case '9': goto yy67;
- default: goto yy25;
- }
-yy50: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
- yych = *YYCURSOR;
- goto yy51;
-yy51: switch(yych){
- case 0x00: goto yy56;
- case ',': goto yy54;
- case '.': goto yy58;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy50;
- case 'E': case 'e': goto yy60;
- default: goto yy25;
- }
-yy52: ++YYCURSOR;
- goto yy53;
-yy53:
-#line 97 "implicit.re"
-{ return "int"; }
-#line 432 "<stdout>"
-yy54: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy55;
-yy55: switch(yych){
- case 0x00: goto yy56;
- case ',': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy54;
- default: goto yy25;
- }
-yy56: ++YYCURSOR;
- goto yy57;
-yy57:
-#line 99 "implicit.re"
-{ return "float#fix"; }
-#line 456 "<stdout>"
-yy58: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
- yych = *YYCURSOR;
- goto yy59;
-yy59: switch(yych){
- case '.': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy58;
- case 'E': case 'e': goto yy60;
- default: goto yy25;
- }
-yy60: yych = *++YYCURSOR;
- switch(yych){
- case '+': case '-': goto yy61;
- default: goto yy25;
- }
-yy61: yych = *++YYCURSOR;
- if(yych <= 0x00) goto yy25;
- goto yy63;
-yy62: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy63;
-yy63: switch(yych){
- case 0x00: goto yy64;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy62;
- default: goto yy25;
- }
-yy64: ++YYCURSOR;
- goto yy65;
-yy65:
-#line 101 "implicit.re"
-{ return "float#exp"; }
-#line 506 "<stdout>"
-yy66: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy70;
- case '.': goto yy68;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy67;
- case ':': goto yy49;
- default: goto yy25;
- }
-yy67: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy70;
- case '.': goto yy68;
- case ':': goto yy49;
- default: goto yy25;
- }
-yy68: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy69;
-yy69: switch(yych){
- case 0x00: goto yy72;
- case ',': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy68;
- default: goto yy25;
- }
-yy70: ++YYCURSOR;
- goto yy71;
-yy71:
-#line 95 "implicit.re"
-{ return "int#base60"; }
-#line 558 "<stdout>"
-yy72: ++YYCURSOR;
- goto yy73;
-yy73:
-#line 103 "implicit.re"
-{ return "float#base60"; }
-#line 564 "<stdout>"
-yy74: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy75;
- default: goto yy48;
- }
-yy75: yych = *++YYCURSOR;
- switch(yych){
- case '-': goto yy76;
- default: goto yy48;
- }
-yy76: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy77;
- default: goto yy25;
- }
-yy77: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy78;
- default: goto yy25;
- }
-yy78: yych = *++YYCURSOR;
- switch(yych){
- case '-': goto yy79;
- default: goto yy25;
- }
-yy79: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy80;
- default: goto yy25;
- }
-yy80: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy81;
- default: goto yy25;
- }
-yy81: yych = *++YYCURSOR;
- switch(yych){
- case 0x00: goto yy82;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy25;
- case 'T': goto yy84;
- case 't': goto yy85;
- default: goto yy87;
- }
-yy82: ++YYCURSOR;
- goto yy83;
-yy83:
-#line 111 "implicit.re"
-{ return "timestamp#ymd"; }
-#line 667 "<stdout>"
-yy84: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy126;
- default: goto yy25;
- }
-yy85: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy108;
- default: goto yy25;
- }
-yy86: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 9) YYFILL(9);
- yych = *YYCURSOR;
- goto yy87;
-yy87: switch(yych){
- case 0x09: case ' ': goto yy86;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy88;
- default: goto yy25;
- }
-yy88: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy89;
- default: goto yy25;
- }
-yy89: yych = *++YYCURSOR;
- switch(yych){
- case ':': goto yy90;
- default: goto yy25;
- }
-yy90: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy91;
- default: goto yy25;
- }
-yy91: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy92;
- default: goto yy25;
- }
-yy92: yych = *++YYCURSOR;
- switch(yych){
- case ':': goto yy93;
- default: goto yy25;
- }
-yy93: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy94;
- default: goto yy25;
- }
-yy94: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy95;
- default: goto yy25;
- }
-yy95: yych = *++YYCURSOR;
- switch(yych){
- case 0x09: case ' ': goto yy98;
- case '.': goto yy96;
- default: goto yy25;
- }
-yy96: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy97;
-yy97: switch(yych){
- case 0x09: case ' ': goto yy98;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy96;
- default: goto yy25;
- }
-yy98: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
- yych = *YYCURSOR;
- goto yy99;
-yy99: switch(yych){
- case 0x09: case ' ': goto yy98;
- case '+': case '-': goto yy101;
- case 'Z': goto yy100;
- default: goto yy25;
- }
-yy100: yych = *++YYCURSOR;
- if(yych <= 0x00) goto yy105;
- goto yy25;
-yy101: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy102;
- default: goto yy25;
- }
-yy102: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy103;
- default: goto yy25;
- }
-yy103: yych = *++YYCURSOR;
- switch(yych){
- case 0x00: goto yy105;
- case ':': goto yy104;
- default: goto yy25;
- }
-yy104: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy107;
- default: goto yy25;
- }
-yy105: ++YYCURSOR;
- goto yy106;
-yy106:
-#line 115 "implicit.re"
-{ return "timestamp#spaced"; }
-#line 884 "<stdout>"
-yy107: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy100;
- default: goto yy25;
- }
-yy108: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy109;
- default: goto yy25;
- }
-yy109: yych = *++YYCURSOR;
- switch(yych){
- case ':': goto yy110;
- default: goto yy25;
- }
-yy110: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy111;
- default: goto yy25;
- }
-yy111: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy112;
- default: goto yy25;
- }
-yy112: yych = *++YYCURSOR;
- switch(yych){
- case ':': goto yy113;
- default: goto yy25;
- }
-yy113: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy114;
- default: goto yy25;
- }
-yy114: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy115;
- default: goto yy25;
- }
-yy115: yych = *++YYCURSOR;
- switch(yych){
- case '.': goto yy116;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy25;
- default: goto yy117;
- }
-yy116: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
- yych = *YYCURSOR;
- goto yy117;
-yy117: switch(yych){
- case '+': case '-': goto yy119;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy116;
- case 'Z': goto yy118;
- default: goto yy25;
- }
-yy118: yych = *++YYCURSOR;
- if(yych <= 0x00) goto yy123;
- goto yy25;
-yy119: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy120;
- default: goto yy25;
- }
-yy120: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy121;
- default: goto yy25;
- }
-yy121: yych = *++YYCURSOR;
- switch(yych){
- case 0x00: goto yy123;
- case ':': goto yy122;
- default: goto yy25;
- }
-yy122: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy125;
- default: goto yy25;
- }
-yy123: ++YYCURSOR;
- goto yy124;
-yy124:
-#line 113 "implicit.re"
-{ return "timestamp#iso8601"; }
-#line 1069 "<stdout>"
-yy125: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy118;
- default: goto yy25;
- }
-yy126: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy127;
- default: goto yy25;
- }
-yy127: yych = *++YYCURSOR;
- switch(yych){
- case ':': goto yy128;
- default: goto yy25;
- }
-yy128: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy129;
- default: goto yy25;
- }
-yy129: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy130;
- default: goto yy25;
- }
-yy130: yych = *++YYCURSOR;
- switch(yych){
- case ':': goto yy131;
- default: goto yy25;
- }
-yy131: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy132;
- default: goto yy25;
- }
-yy132: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy133;
- default: goto yy25;
- }
-yy133: yych = *++YYCURSOR;
- switch(yych){
- case '.': goto yy134;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy25;
- case 'Z': goto yy136;
- default: goto yy135;
- }
-yy134: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
- yych = *YYCURSOR;
- goto yy135;
-yy135: switch(yych){
- case '+': case '-': goto yy119;
- case '0': goto yy134;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy138;
- case 'Z': goto yy118;
- default: goto yy25;
- }
-yy136: yych = *++YYCURSOR;
- if(yych >= 0x01) goto yy25;
- goto yy137;
-yy137: yych = *++YYCURSOR;
- goto yy124;
-yy138: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
- yych = *YYCURSOR;
- goto yy139;
-yy139: switch(yych){
- case '+': case '-': goto yy119;
- case '0': goto yy134;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy138;
- case 'Z': goto yy136;
- default: goto yy25;
- }
-yy140: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': goto yy155;
- case '8':
- case '9': goto yy153;
- default: goto yy143;
- }
-yy141: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy153;
- default: goto yy152;
- }
-yy142: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy143;
-yy143: switch(yych){
- case 0x00: goto yy149;
- case ',': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': goto yy142;
- case '.': goto yy50;
- case '8':
- case '9': goto yy151;
- case ':': goto yy49;
- default: goto yy25;
- }
-yy144: yych = *++YYCURSOR;
- if(yych <= 0x00) goto yy25;
- goto yy146;
-yy145: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy146;
-yy146: switch(yych){
- case 0x00: goto yy147;
- case ',': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f': goto yy145;
- default: goto yy25;
- }
-yy147: ++YYCURSOR;
- goto yy148;
-yy148:
-#line 91 "implicit.re"
-{ return "int#hex"; }
-#line 1307 "<stdout>"
-yy149: ++YYCURSOR;
- goto yy150;
-yy150:
-#line 93 "implicit.re"
-{ return "int#oct"; }
-#line 1313 "<stdout>"
-yy151: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy152;
-yy152: switch(yych){
- case ',': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy151;
- case '.': goto yy50;
- case ':': goto yy49;
- default: goto yy25;
- }
-yy153: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy154;
- default: goto yy152;
- }
-yy154: yych = *++YYCURSOR;
- switch(yych){
- case '-': goto yy76;
- default: goto yy152;
- }
-yy155: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': goto yy156;
- case '8':
- case '9': goto yy154;
- default: goto yy143;
- }
-yy156: yych = *++YYCURSOR;
- switch(yych){
- case '-': goto yy76;
- default: goto yy143;
- }
-yy157: yych = *++YYCURSOR;
- switch(yych){
- case 'I': goto yy160;
- case 'i': goto yy159;
- default: goto yy25;
- }
-yy158: yych = *++YYCURSOR;
- switch(yych){
- case 0x00: goto yy52;
- case 'x': goto yy144;
- default: goto yy143;
- }
-yy159: yych = *++YYCURSOR;
- switch(yych){
- case 'n': goto yy166;
- default: goto yy25;
- }
-yy160: yych = *++YYCURSOR;
- switch(yych){
- case 'N': goto yy161;
- case 'n': goto yy162;
- default: goto yy25;
- }
-yy161: yych = *++YYCURSOR;
- switch(yych){
- case 'F': goto yy163;
- default: goto yy25;
- }
-yy162: yych = *++YYCURSOR;
- switch(yych){
- case 'f': goto yy163;
- default: goto yy25;
- }
-yy163: yych = *++YYCURSOR;
- if(yych >= 0x01) goto yy25;
- goto yy164;
-yy164: ++YYCURSOR;
- goto yy165;
-yy165:
-#line 107 "implicit.re"
-{ return "float#neginf"; }
-#line 1412 "<stdout>"
-yy166: yych = *++YYCURSOR;
- switch(yych){
- case 'f': goto yy163;
- default: goto yy25;
- }
-yy167: yych = *++YYCURSOR;
- switch(yych){
- case 'I': goto yy33;
- case 'i': goto yy32;
- default: goto yy25;
- }
-yy168: yych = *++YYCURSOR;
- switch(yych){
- case 'L': goto yy175;
- default: goto yy25;
- }
-yy169: yych = *++YYCURSOR;
- switch(yych){
- case 'l': goto yy170;
- default: goto yy25;
- }
-yy170: yych = *++YYCURSOR;
- switch(yych){
- case 's': goto yy171;
- default: goto yy25;
- }
-yy171: yych = *++YYCURSOR;
- switch(yych){
- case 'e': goto yy172;
- default: goto yy25;
- }
-yy172: yych = *++YYCURSOR;
- if(yych >= 0x01) goto yy25;
- goto yy173;
-yy173: ++YYCURSOR;
- goto yy174;
-yy174:
-#line 89 "implicit.re"
-{ return "bool#no"; }
-#line 1452 "<stdout>"
-yy175: yych = *++YYCURSOR;
- switch(yych){
- case 'S': goto yy176;
- default: goto yy25;
- }
-yy176: yych = *++YYCURSOR;
- switch(yych){
- case 'E': goto yy172;
- default: goto yy25;
- }
-yy177: yych = *++YYCURSOR;
- switch(yych){
- case 'l': goto yy178;
- default: goto yy25;
- }
-yy178: yych = *++YYCURSOR;
- switch(yych){
- case 's': goto yy179;
- default: goto yy25;
- }
-yy179: yych = *++YYCURSOR;
- switch(yych){
- case 'e': goto yy172;
- default: goto yy25;
- }
-yy180: yych = *++YYCURSOR;
- switch(yych){
- case 'F': goto yy172;
- default: goto yy25;
- }
-yy181: yych = *++YYCURSOR;
- switch(yych){
- case 'f': goto yy172;
- default: goto yy25;
- }
-yy182: yych = *++YYCURSOR;
- if(yych >= 0x01) goto yy25;
- goto yy183;
-yy183: ++YYCURSOR;
- goto yy184;
-yy184:
-#line 87 "implicit.re"
-{ return "bool#yes"; }
-#line 1496 "<stdout>"
-yy185: yych = *++YYCURSOR;
- switch(yych){
- case 'f': goto yy172;
- default: goto yy25;
- }
-yy186: yych = *++YYCURSOR;
- switch(yych){
- case 'U': goto yy189;
- default: goto yy25;
- }
-yy187: yych = *++YYCURSOR;
- switch(yych){
- case 'u': goto yy188;
- default: goto yy25;
- }
-yy188: yych = *++YYCURSOR;
- switch(yych){
- case 'e': goto yy182;
- default: goto yy25;
- }
-yy189: yych = *++YYCURSOR;
- switch(yych){
- case 'E': goto yy182;
- default: goto yy25;
- }
-yy190: yych = *++YYCURSOR;
- switch(yych){
- case 'u': goto yy191;
- default: goto yy25;
- }
-yy191: yych = *++YYCURSOR;
- switch(yych){
- case 'e': goto yy182;
- default: goto yy25;
- }
-yy192: yych = *++YYCURSOR;
- switch(yych){
- case 'S': goto yy182;
- default: goto yy25;
- }
-yy193: yych = *++YYCURSOR;
- switch(yych){
- case 's': goto yy182;
- default: goto yy25;
- }
-yy194: yych = *++YYCURSOR;
- switch(yych){
- case 's': goto yy182;
- default: goto yy25;
- }
-yy195: yych = *++YYCURSOR;
- switch(yych){
- case 'L': goto yy199;
- default: goto yy25;
- }
-yy196: yych = *++YYCURSOR;
- switch(yych){
- case 'l': goto yy197;
- default: goto yy25;
- }
-yy197: yych = *++YYCURSOR;
- switch(yych){
- case 'l': goto yy198;
- default: goto yy25;
- }
-yy198: yych = *++YYCURSOR;
- if(yych <= 0x00) goto yy6;
- goto yy25;
-yy199: yych = *++YYCURSOR;
- switch(yych){
- case 'L': goto yy198;
- default: goto yy25;
- }
-yy200: yych = *++YYCURSOR;
- switch(yych){
- case 'l': goto yy201;
- default: goto yy25;
- }
-yy201: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 'l': goto yy198;
- default: goto yy25;
- }
-}
-#line 125 "implicit.re"
-
-
-}
-
-/* Remove ending fragment and compare types */
-int
-syck_tagcmp( char *tag1, char *tag2 )
-{
- if ( tag1 == tag2 ) return 1;
- if ( tag1 == NULL || tag2 == NULL ) return 0;
- else {
- int i;
- char *othorpe;
- char *tmp1 = syck_strndup( tag1, strlen( tag1 ) );
- char *tmp2 = syck_strndup( tag2, strlen( tag2 ) );
- othorpe = strstr( tmp1, "#" );
- if ( othorpe != NULL ) {
- othorpe[0] = '\0';
- }
- othorpe = strstr( tmp2, "#" );
- if ( othorpe != NULL ) {
- othorpe[0] = '\0';
- }
- i = strcmp( tmp1, tmp2 );
- S_FREE( tmp1 ); S_FREE( tmp2 );
- return i;
- }
-}
-
-char *
-syck_type_id_to_uri( char *type_id )
-{
- char *cursor, *limit, *marker;
-
- cursor = type_id;
- limit = type_id + strlen( type_id );
-
-
-#line 1620 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy202;
- ++YYCURSOR;
-yy202:
- if((YYLIMIT - YYCURSOR) < 11) YYFILL(11);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy204;
- case '!': goto yy208;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's': case 'u':
- case 'v':
- case 'w': case 'y':
- case 'z': goto yy210;
- case 't': goto yy205;
- case 'x': goto yy207;
- default: goto yy211;
- }
-yy204: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy206;
- }
-yy205: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case ',': goto yy216;
- case '-': goto yy212;
- case '.': goto yy217;
- case '/': goto yy218;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy214;
- case 'a': goto yy246;
- default: goto yy206;
- }
-yy206:
-#line 202 "implicit.re"
-{ return syck_taguri( YAML_DOMAIN, type_id, strlen( type_id ) ); }
-#line 1768 "<stdout>"
-yy207: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case ',': case '.':
- case '/':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy215;
- case '-': goto yy236;
- default: goto yy206;
- }
-yy208: ++YYCURSOR;
- goto yy209;
-yy209:
-#line 176 "implicit.re"
-{ return syck_xprivate( type_id + 1, strlen( type_id ) - 1 ); }
-#line 1842 "<stdout>"
-yy210: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case ',': goto yy216;
- case '-': goto yy212;
- case '.': goto yy217;
- case '/': goto yy218;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy214;
- default: goto yy206;
- }
-yy211: yych = *++YYCURSOR;
- goto yy206;
-yy212: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy213;
-yy213: switch(yych){
- case '-': goto yy212;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy214;
- default: goto yy204;
- }
-yy214: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- goto yy215;
-yy215: switch(yych){
- case ',': goto yy216;
- case '-': goto yy212;
- case '.': goto yy217;
- case '/': goto yy218;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy214;
- default: goto yy204;
- }
-yy216: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy224;
- default: goto yy204;
- }
-yy217: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy220;
- default: goto yy204;
- }
-yy218: ++YYCURSOR;
- goto yy219;
-yy219:
-#line 178 "implicit.re"
-{ char *domain = S_ALLOC_N( char, ( YYCURSOR - type_id ) + 15 );
- char *uri;
-
- domain[0] = '\0';
- strncat( domain, type_id, ( YYCURSOR - type_id ) - 1 );
- strcat( domain, "." );
- strcat( domain, YAML_DOMAIN );
- uri = syck_taguri( domain, YYCURSOR, YYLIMIT - YYCURSOR );
-
- S_FREE( domain );
- return uri;
- }
-#line 2149 "<stdout>"
-yy220: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 12) YYFILL(12);
- yych = *YYCURSOR;
- goto yy221;
-yy221: switch(yych){
- case ',': goto yy216;
- case '-': goto yy222;
- case '.': goto yy217;
- case '/': goto yy218;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy220;
- default: goto yy204;
- }
-yy222: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy223;
-yy223: switch(yych){
- case '-': goto yy222;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy220;
- default: goto yy204;
- }
-yy224: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy225;
- default: goto yy204;
- }
-yy225: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy226;
- default: goto yy204;
- }
-yy226: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy227;
- default: goto yy204;
- }
-yy227: yych = *++YYCURSOR;
- switch(yych){
- case '-': goto yy228;
- case '/': goto yy229;
- default: goto yy204;
- }
-yy228: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy231;
- default: goto yy204;
- }
-yy229: ++YYCURSOR;
- goto yy230;
-yy230:
-#line 191 "implicit.re"
-{ char *domain = S_ALLOC_N( char, YYCURSOR - type_id );
- char *uri;
-
- domain[0] = '\0';
- strncat( domain, type_id, ( YYCURSOR - type_id ) - 1 );
- uri = syck_taguri( domain, YYCURSOR, YYLIMIT - YYCURSOR );
-
- S_FREE( domain );
- return uri;
- }
-#line 2365 "<stdout>"
-yy231: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy232;
- default: goto yy204;
- }
-yy232: yych = *++YYCURSOR;
- switch(yych){
- case '-': goto yy233;
- case '/': goto yy229;
- default: goto yy204;
- }
-yy233: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy234;
- default: goto yy204;
- }
-yy234: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy235;
- default: goto yy204;
- }
-yy235: yych = *++YYCURSOR;
- switch(yych){
- case '/': goto yy229;
- default: goto yy204;
- }
-yy236: yych = *++YYCURSOR;
- switch(yych){
- case 'p': goto yy237;
- default: goto yy213;
- }
-yy237: yych = *++YYCURSOR;
- switch(yych){
- case ',': goto yy216;
- case '.': goto yy217;
- case '/': goto yy218;
- case 'r': goto yy238;
- default: goto yy213;
- }
-yy238: yych = *++YYCURSOR;
- switch(yych){
- case ',': goto yy216;
- case '.': goto yy217;
- case '/': goto yy218;
- case 'i': goto yy239;
- default: goto yy213;
- }
-yy239: yych = *++YYCURSOR;
- switch(yych){
- case ',': goto yy216;
- case '.': goto yy217;
- case '/': goto yy218;
- case 'v': goto yy240;
- default: goto yy213;
- }
-yy240: yych = *++YYCURSOR;
- switch(yych){
- case ',': goto yy216;
- case '.': goto yy217;
- case '/': goto yy218;
- case 'a': goto yy241;
- default: goto yy213;
- }
-yy241: yych = *++YYCURSOR;
- switch(yych){
- case ',': goto yy216;
- case '.': goto yy217;
- case '/': goto yy218;
- case 't': goto yy242;
- default: goto yy213;
- }
-yy242: yych = *++YYCURSOR;
- switch(yych){
- case ',': goto yy216;
- case '.': goto yy217;
- case '/': goto yy218;
- case 'e': goto yy243;
- default: goto yy213;
- }
-yy243: yych = *++YYCURSOR;
- switch(yych){
- case ',': goto yy216;
- case '.': goto yy217;
- case '/': goto yy218;
- case ':': goto yy244;
- default: goto yy213;
- }
-yy244: ++YYCURSOR;
- goto yy245;
-yy245:
-#line 174 "implicit.re"
-{ return syck_strndup( type_id, strlen( type_id ) ); }
-#line 2485 "<stdout>"
-yy246: yych = *++YYCURSOR;
- switch(yych){
- case ',': goto yy216;
- case '.': goto yy217;
- case '/': goto yy218;
- case 'g': goto yy247;
- default: goto yy213;
- }
-yy247: yych = *++YYCURSOR;
- switch(yych){
- case ',': goto yy216;
- case '.': goto yy217;
- case '/': goto yy218;
- case ':': goto yy248;
- default: goto yy213;
- }
-yy248: yych = *++YYCURSOR;
- switch(yych){
- case ',':
- case '-':
- case '.': goto yy204;
- default: goto yy250;
- }
-yy249: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- goto yy250;
-yy250: switch(yych){
- case ',': goto yy253;
- case '-': goto yy251;
- case '.': goto yy254;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy249;
- default: goto yy204;
- }
-yy251: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy252;
-yy252: switch(yych){
- case '-': goto yy251;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy249;
- default: goto yy204;
- }
-yy253: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy259;
- default: goto yy204;
- }
-yy254: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy255;
- default: goto yy204;
- }
-yy255: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 12) YYFILL(12);
- yych = *YYCURSOR;
- goto yy256;
-yy256: switch(yych){
- case ',': goto yy253;
- case '-': goto yy257;
- case '.': goto yy254;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy255;
- default: goto yy204;
- }
-yy257: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy258;
-yy258: switch(yych){
- case '-': goto yy257;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy255;
- default: goto yy204;
- }
-yy259: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy260;
- default: goto yy204;
- }
-yy260: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy261;
- default: goto yy204;
- }
-yy261: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy262;
- default: goto yy204;
- }
-yy262: yych = *++YYCURSOR;
- switch(yych){
- case '-': goto yy263;
- case ':': goto yy264;
- default: goto yy204;
- }
-yy263: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy266;
- default: goto yy204;
- }
-yy264: ++YYCURSOR;
- goto yy265;
-yy265:
-#line 172 "implicit.re"
-{ return syck_strndup( type_id, strlen( type_id ) ); }
-#line 2932 "<stdout>"
-yy266: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy267;
- default: goto yy204;
- }
-yy267: yych = *++YYCURSOR;
- switch(yych){
- case '-': goto yy268;
- case ':': goto yy264;
- default: goto yy204;
- }
-yy268: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy269;
- default: goto yy204;
- }
-yy269: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy270;
- default: goto yy204;
- }
-yy270: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case ':': goto yy264;
- default: goto yy204;
- }
-}
-#line 204 "implicit.re"
-
-
-}
diff --git a/ext/syck/node.c b/ext/syck/node.c
deleted file mode 100644
index 28fc78c077..0000000000
--- a/ext/syck/node.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * node.c
- *
- * $Author$
- * $Date$
- *
- * Copyright (C) 2003 why the lucky stiff
- */
-
-#include "ruby.h"
-#include "syck.h"
-
-/*
- * Node allocation functions
- */
-SyckNode *
-syck_alloc_node( enum syck_kind_tag type )
-{
- SyckNode *s;
-
- s = S_ALLOC( SyckNode );
- s->kind = type;
- s->id = 0;
- s->type_id = NULL;
- s->anchor = NULL;
- s->shortcut = NULL;
-
- return s;
-}
-
-void
-syck_free_node( SyckNode *n )
-{
- syck_free_members( n );
- if ( n->type_id != NULL )
- {
- S_FREE( n->type_id );
- n->type_id = NULL;
- }
- if ( n->anchor != NULL )
- {
- S_FREE( n->anchor );
- n->anchor = NULL;
- }
- S_FREE( n );
-}
-
-SyckNode *
-syck_alloc_map()
-{
- SyckNode *n;
- struct SyckMap *m;
-
- m = S_ALLOC( struct SyckMap );
- m->style = map_none;
- m->idx = 0;
- m->capa = ALLOC_CT;
- m->keys = S_ALLOC_N( SYMID, m->capa );
- m->values = S_ALLOC_N( SYMID, m->capa );
-
- n = syck_alloc_node( syck_map_kind );
- n->data.pairs = m;
-
- return n;
-}
-
-SyckNode *
-syck_alloc_seq()
-{
- SyckNode *n;
- struct SyckSeq *s;
-
- s = S_ALLOC( struct SyckSeq );
- s->style = seq_none;
- s->idx = 0;
- s->capa = ALLOC_CT;
- s->items = S_ALLOC_N( SYMID, s->capa );
-
- n = syck_alloc_node( syck_seq_kind );
- n->data.list = s;
-
- return n;
-}
-
-SyckNode *
-syck_alloc_str()
-{
- SyckNode *n;
- struct SyckStr *s;
-
- s = S_ALLOC( struct SyckStr );
- s->len = 0;
- s->ptr = NULL;
- s->style = scalar_none;
-
- n = syck_alloc_node( syck_str_kind );
- n->data.str = s;
-
- return n;
-}
-
-SyckNode *
-syck_new_str( char *str, enum scalar_style style )
-{
- return syck_new_str2( str, strlen( str ), style );
-}
-
-SyckNode *
-syck_new_str2( char *str, long len, enum scalar_style style )
-{
- SyckNode *n;
-
- n = syck_alloc_str();
- n->data.str->ptr = S_ALLOC_N( char, len + 1 );
- n->data.str->len = len;
- n->data.str->style = style;
- memcpy( n->data.str->ptr, str, len );
- n->data.str->ptr[len] = '\0';
-
- return n;
-}
-
-void
-syck_replace_str( SyckNode *n, char *str, enum scalar_style style )
-{
- syck_replace_str2( n, str, strlen( str ), style );
-}
-
-void
-syck_replace_str2( SyckNode *n, char *str, long len, enum scalar_style style )
-{
- if ( n->data.str != NULL )
- {
- S_FREE( n->data.str->ptr );
- n->data.str->ptr = NULL;
- n->data.str->len = 0;
- }
- n->data.str->ptr = S_ALLOC_N( char, len + 1 );
- n->data.str->len = len;
- n->data.str->style = style;
- memcpy( n->data.str->ptr, str, len );
- n->data.str->ptr[len] = '\0';
-}
-
-void
-syck_str_blow_away_commas( SyckNode *n )
-{
- char *go, *end;
-
- go = n->data.str->ptr;
- end = go + n->data.str->len;
- while ( *(++go) != '\0' )
- {
- if ( *go == ',' )
- {
- n->data.str->len -= 1;
- memmove( go, go + 1, end - go );
- end -= 1;
- }
- }
-}
-
-char *
-syck_str_read( SyckNode *n )
-{
- ASSERT( n != NULL );
- return n->data.str->ptr;
-}
-
-SyckNode *
-syck_new_map( SYMID key, SYMID value )
-{
- SyckNode *n;
-
- n = syck_alloc_map();
- syck_map_add( n, key, value );
-
- return n;
-}
-
-void
-syck_map_empty( SyckNode *n )
-{
- struct SyckMap *m;
- ASSERT( n != NULL );
- ASSERT( n->data.list != NULL );
-
- S_FREE( n->data.pairs->keys );
- S_FREE( n->data.pairs->values );
- m = n->data.pairs;
- m->idx = 0;
- m->capa = ALLOC_CT;
- m->keys = S_ALLOC_N( SYMID, m->capa );
- m->values = S_ALLOC_N( SYMID, m->capa );
-}
-
-void
-syck_map_add( SyckNode *map, SYMID key, SYMID value )
-{
- struct SyckMap *m;
- long idx;
-
- ASSERT( map != NULL );
- ASSERT( map->data.pairs != NULL );
-
- m = map->data.pairs;
- idx = m->idx;
- m->idx += 1;
- if ( m->idx > m->capa )
- {
- m->capa += ALLOC_CT;
- S_REALLOC_N( m->keys, SYMID, m->capa );
- S_REALLOC_N( m->values, SYMID, m->capa );
- }
- m->keys[idx] = key;
- m->values[idx] = value;
-}
-
-void
-syck_map_update( SyckNode *map1, SyckNode *map2 )
-{
- struct SyckMap *m1, *m2;
- long new_idx, new_capa;
- ASSERT( map1 != NULL );
- ASSERT( map2 != NULL );
-
- m1 = map1->data.pairs;
- m2 = map2->data.pairs;
- if ( m2->idx < 1 ) return;
-
- new_idx = m1->idx;
- new_idx += m2->idx;
- new_capa = m1->capa;
- while ( new_idx > new_capa )
- {
- new_capa += ALLOC_CT;
- }
- if ( new_capa > m1->capa )
- {
- m1->capa = new_capa;
- S_REALLOC_N( m1->keys, SYMID, m1->capa );
- S_REALLOC_N( m1->values, SYMID, m1->capa );
- }
- for ( new_idx = 0; new_idx < m2->idx; m1->idx++, new_idx++ )
- {
- m1->keys[m1->idx] = m2->keys[new_idx];
- m1->values[m1->idx] = m2->values[new_idx];
- }
-}
-
-long
-syck_map_count( SyckNode *map )
-{
- ASSERT( map != NULL );
- ASSERT( map->data.pairs != NULL );
- return map->data.pairs->idx;
-}
-
-void
-syck_map_assign( SyckNode *map, enum map_part p, long idx, SYMID id )
-{
- struct SyckMap *m;
-
- ASSERT( map != NULL );
- m = map->data.pairs;
- ASSERT( m != NULL );
- if ( p == map_key )
- {
- m->keys[idx] = id;
- }
- else
- {
- m->values[idx] = id;
- }
-}
-
-SYMID
-syck_map_read( SyckNode *map, enum map_part p, long idx )
-{
- struct SyckMap *m;
-
- ASSERT( map != NULL );
- m = map->data.pairs;
- ASSERT( m != NULL );
- if ( p == map_key )
- {
- return m->keys[idx];
- }
- else
- {
- return m->values[idx];
- }
-}
-
-SyckNode *
-syck_new_seq( SYMID value )
-{
- SyckNode *n;
-
- n = syck_alloc_seq();
- syck_seq_add( n, value );
-
- return n;
-}
-
-void
-syck_seq_empty( SyckNode *n )
-{
- struct SyckSeq *s;
- ASSERT( n != NULL );
- ASSERT( n->data.list != NULL );
-
- S_FREE( n->data.list->items );
- s = n->data.list;
- s->idx = 0;
- s->capa = ALLOC_CT;
- s->items = S_ALLOC_N( SYMID, s->capa );
-}
-
-void
-syck_seq_add( SyckNode *arr, SYMID value )
-{
- struct SyckSeq *s;
- long idx;
-
- ASSERT( arr != NULL );
- ASSERT( arr->data.list != NULL );
-
- s = arr->data.list;
- idx = s->idx;
- s->idx += 1;
- if ( s->idx > s->capa )
- {
- s->capa += ALLOC_CT;
- S_REALLOC_N( s->items, SYMID, s->capa );
- }
- s->items[idx] = value;
-}
-
-long
-syck_seq_count( SyckNode *seq )
-{
- ASSERT( seq != NULL );
- ASSERT( seq->data.list != NULL );
- return seq->data.list->idx;
-}
-
-void
-syck_seq_assign( SyckNode *seq, long idx, SYMID id )
-{
- struct SyckSeq *s;
-
- ASSERT( map != NULL );
- s = seq->data.list;
- ASSERT( m != NULL );
- s->items[idx] = id;
-}
-
-SYMID
-syck_seq_read( SyckNode *seq, long idx )
-{
- struct SyckSeq *s;
-
- ASSERT( seq != NULL );
- s = seq->data.list;
- ASSERT( s != NULL );
- return s->items[idx];
-}
-
-void
-syck_free_members( SyckNode *n )
-{
- if ( n == NULL ) return;
-
- switch ( n->kind )
- {
- case syck_str_kind:
- if ( n->data.str != NULL )
- {
- S_FREE( n->data.str->ptr );
- n->data.str->ptr = NULL;
- n->data.str->len = 0;
- S_FREE( n->data.str );
- n->data.str = NULL;
- }
- break;
-
- case syck_seq_kind:
- if ( n->data.list != NULL )
- {
- S_FREE( n->data.list->items );
- S_FREE( n->data.list );
- n->data.list = NULL;
- }
- break;
-
- case syck_map_kind:
- if ( n->data.pairs != NULL )
- {
- S_FREE( n->data.pairs->keys );
- S_FREE( n->data.pairs->values );
- S_FREE( n->data.pairs );
- n->data.pairs = NULL;
- }
- break;
- }
-}
-
diff --git a/ext/syck/rubyext.c b/ext/syck/rubyext.c
deleted file mode 100644
index 078de4f78d..0000000000
--- a/ext/syck/rubyext.c
+++ /dev/null
@@ -1,2367 +0,0 @@
-/* -*- indent-tabs-mode: nil -*- */
-/*
- * rubyext.c
- *
- * $Author$
- * $Date$
- *
- * Copyright (C) 2003-2005 why the lucky stiff
- */
-
-#include "ruby.h"
-#include "syck.h"
-#include <sys/types.h>
-#include <time.h>
-
-typedef struct RVALUE {
- union {
-#if 0
- struct {
- unsigned long flags; /* always 0 for freed obj */
- struct RVALUE *next;
- } free;
-#endif
- struct RBasic basic;
- struct RObject object;
- struct RClass klass;
- /*struct RFloat flonum;*/
- /*struct RString string;*/
- struct RArray array;
- /*struct RRegexp regexp;*/
- struct RHash hash;
- /*struct RData data;*/
- struct RStruct rstruct;
- /*struct RBignum bignum;*/
- /*struct RFile file;*/
- } as;
-} RVALUE;
-
-typedef struct {
- long hash;
- char *buffer;
- long length;
- long remaining;
- int printed;
-} bytestring_t;
-
-#define RUBY_DOMAIN "ruby.yaml.org,2002"
-
-/*
- * symbols and constants
- */
-static ID s_new, s_utc, s_at, s_to_f, s_to_i, s_read, s_binmode, s_call, s_cmp, s_transfer, s_update, s_dup, s_haskey, s_match, s_keys, s_unpack, s_tr_bang, s_default_set, s_tag_read_class, s_tag_subclasses, s_resolver, s_push, s_emitter, s_level, s_detect_implicit, s_node_import, s_out, s_input, s_intern, s_transform, s_yaml_new, s_yaml_initialize, s_node_export, s_to_yaml, s_write, s_set_resolver;
-static ID s_tags, s_domain, s_kind, s_name, s_options, s_type_id, s_type_id_set, s_style, s_style_set, s_value, s_value_set;
-static VALUE sym_model, sym_generic, sym_input, sym_bytecode;
-static VALUE sym_scalar, sym_seq, sym_map;
-static VALUE sym_1quote, sym_2quote, sym_fold, sym_literal, sym_plain, sym_inline;
-static VALUE cDate, cNode, cMap, cSeq, cScalar, cOut, cParser, cResolver, cPrivateType, cDomainType, cYObject, cBadAlias, cDefaultKey, cMergeKey, cEmitter;
-static VALUE oDefaultResolver, oGenericResolver;
-
-/*
- * my private collection of numerical oddities.
- */
-static double S_zero() { return 0.0; }
-static double S_one() { return 1.0; }
-static double S_inf() { return S_one() / S_zero(); }
-static double S_nan() { return S_zero() / S_zero(); }
-
-static VALUE syck_node_transform( VALUE );
-
-/*
- * handler prototypes
- */
-SYMID rb_syck_load_handler _((SyckParser *, SyckNode *));
-void rb_syck_err_handler _((SyckParser *, char *));
-SyckNode * rb_syck_bad_anchor_handler _((SyckParser *, char *));
-void rb_syck_output_handler _((SyckEmitter *, char *, long));
-void rb_syck_emitter_handler _((SyckEmitter *, st_data_t));
-int syck_parser_assign_io _((SyckParser *, VALUE *));
-VALUE syck_scalar_alloc _((VALUE class));
-VALUE syck_seq_alloc _((VALUE class));
-VALUE syck_map_alloc _((VALUE class));
-
-struct parser_xtra {
- VALUE data; /* Borrowed this idea from marshal.c to fix [ruby-core:8067] problem */
- VALUE proc;
- VALUE resolver;
- int taint;
-};
-
-struct emitter_xtra {
- VALUE oid;
- VALUE data;
- VALUE port;
-};
-
-/*
- * Convert YAML to bytecode
- */
-VALUE
-rb_syck_compile(self, port)
- VALUE self, port;
-{
- SYMID oid;
- int taint;
- char *ret;
- VALUE bc;
- bytestring_t *sav;
-
- SyckParser *parser = syck_new_parser();
- taint = syck_parser_assign_io(parser, &port);
- syck_parser_handler( parser, syck_yaml2byte_handler );
- syck_parser_error_handler( parser, NULL );
- syck_parser_implicit_typing( parser, 0 );
- syck_parser_taguri_expansion( parser, 0 );
- oid = syck_parse( parser );
- syck_lookup_sym( parser, oid, (char **)&sav );
-
- ret = S_ALLOCA_N( char, strlen( sav->buffer ) + 3 );
- ret[0] = '\0';
- strcat( ret, "D\n" );
- strcat( ret, sav->buffer );
-
- syck_free_parser( parser );
-
- bc = rb_str_new2( ret );
- if ( taint ) OBJ_TAINT( bc );
- return bc;
-}
-
-/*
- * read from io.
- */
-long
-rb_syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
-{
- long len = 0;
-
- ASSERT( str != NULL );
- max_size -= skip;
-
- if ( max_size <= 0 ) max_size = 0;
- else
- {
- /*
- * call io#read.
- */
- VALUE src = (VALUE)str->ptr;
- VALUE n = LONG2NUM(max_size);
- VALUE str2 = rb_funcall2(src, s_read, 1, &n);
- if (!NIL_P(str2))
- {
- StringValue(str2);
- len = RSTRING(str2)->len;
- memcpy( buf + skip, RSTRING(str2)->ptr, len );
- }
- }
- len += skip;
- buf[len] = '\0';
- return len;
-}
-
-/*
- * determine: are we reading from a string or io?
- * (returns tainted? boolean)
- */
-int
-syck_parser_assign_io(parser, pport)
- SyckParser *parser;
- VALUE *pport;
-{
- int taint = Qtrue;
- VALUE tmp, port = *pport;
- if (!NIL_P(tmp = rb_check_string_type(port))) {
- taint = OBJ_TAINTED(port); /* original taintedness */
- port = tmp;
- syck_parser_str( parser, RSTRING(port)->ptr, RSTRING(port)->len, NULL );
- }
- else if (rb_respond_to(port, s_read)) {
- if (rb_respond_to(port, s_binmode)) {
- rb_funcall2(port, s_binmode, 0, 0);
- }
- syck_parser_str( parser, (char *)port, 0, rb_syck_io_str_read );
- }
- else {
- rb_raise(rb_eTypeError, "instance of IO needed");
- }
- *pport = port;
- return taint;
-}
-
-/*
- * Get value in hash by key, forcing an empty hash if nil.
- */
-VALUE
-syck_get_hash_aref(hsh, key)
- VALUE hsh, key;
-{
- VALUE val = rb_hash_aref( hsh, key );
- if ( NIL_P( val ) )
- {
- val = rb_hash_new();
- rb_hash_aset(hsh, key, val);
- }
- return val;
-}
-
-/*
- * creating timestamps
- */
-SYMID
-rb_syck_mktime(str, len)
- char *str;
- long len;
-{
- VALUE time;
- char *ptr = str;
- VALUE year = INT2FIX(0);
- VALUE mon = INT2FIX(0);
- VALUE day = INT2FIX(0);
- VALUE hour = INT2FIX(0);
- VALUE min = INT2FIX(0);
- VALUE sec = INT2FIX(0);
- long usec;
-
- /* Year*/
- if ( ptr[0] != '\0' && len > 0 ) {
- year = INT2FIX(strtol(ptr, NULL, 10));
- }
-
- /* Month*/
- ptr += 4;
- if ( ptr[0] != '\0' && len > ptr - str ) {
- while ( !ISDIGIT( *ptr ) ) ptr++;
- mon = INT2FIX(strtol(ptr, NULL, 10));
- }
-
- /* Day*/
- ptr += 2;
- if ( ptr[0] != '\0' && len > ptr - str ) {
- while ( !ISDIGIT( *ptr ) ) ptr++;
- day = INT2FIX(strtol(ptr, NULL, 10));
- }
-
- /* Hour*/
- ptr += 2;
- if ( ptr[0] != '\0' && len > ptr - str ) {
- while ( !ISDIGIT( *ptr ) ) ptr++;
- hour = INT2FIX(strtol(ptr, NULL, 10));
- }
-
- /* Minute */
- ptr += 2;
- if ( ptr[0] != '\0' && len > ptr - str ) {
- while ( !ISDIGIT( *ptr ) ) ptr++;
- min = INT2FIX(strtol(ptr, NULL, 10));
- }
-
- /* Second */
- ptr += 2;
- if ( ptr[0] != '\0' && len > ptr - str ) {
- while ( !ISDIGIT( *ptr ) ) ptr++;
- sec = INT2FIX(strtol(ptr, NULL, 10));
- }
-
- /* Millisecond */
- ptr += 2;
- if ( len > ptr - str && *ptr == '.' )
- {
- char padded[] = "000000";
- char *end = ptr + 1;
- while ( isdigit( *end ) ) end++;
- MEMCPY(padded, ptr + 1, char, end - (ptr + 1));
- usec = strtol(padded, NULL, 10);
- }
- else
- {
- usec = 0;
- }
-
- /* Time Zone*/
- while ( len > ptr - str && *ptr != 'Z' && *ptr != '+' && *ptr != '-' && *ptr != '\0' ) ptr++;
- if ( len > ptr - str && ( *ptr == '-' || *ptr == '+' ) )
- {
- time_t tz_offset = strtol(ptr, NULL, 10) * 3600;
- time_t tmp;
-
- while ( *ptr != ':' && *ptr != '\0' ) ptr++;
- if ( *ptr == ':' )
- {
- ptr += 1;
- if ( tz_offset < 0 )
- {
- tz_offset -= strtol(ptr, NULL, 10) * 60;
- }
- else
- {
- tz_offset += strtol(ptr, NULL, 10) * 60;
- }
- }
-
- /* Make TZ time*/
- time = rb_funcall(rb_cTime, s_utc, 6, year, mon, day, hour, min, sec);
- tmp = NUM2LONG(rb_funcall(time, s_to_i, 0)) - tz_offset;
- return rb_funcall(rb_cTime, s_at, 2, LONG2NUM(tmp), LONG2NUM(usec));
- }
- else
- {
- /* Make UTC time*/
- return rb_funcall(rb_cTime, s_utc, 7, year, mon, day, hour, min, sec, LONG2NUM(usec));
- }
-}
-
-/*
- * handles merging of an array of hashes
- * (see http://www.yaml.org/type/merge/)
- */
-VALUE
-syck_merge_i( entry, hsh )
- VALUE entry, hsh;
-{
- VALUE tmp;
- if ( !NIL_P(tmp = rb_check_convert_type(entry, T_HASH, "Hash", "to_hash")) )
- {
- entry = tmp;
- rb_funcall( hsh, s_update, 1, entry );
- }
- return Qnil;
-}
-
-/*
- * default handler for ruby.yaml.org types
- */
-int
-yaml_org_handler( n, ref )
- SyckNode *n;
- VALUE *ref;
-{
- char *type_id = n->type_id;
- int transferred = 0;
- long i = 0;
- VALUE obj = Qnil;
-
- if ( type_id != NULL && strncmp( type_id, "tag:yaml.org,2002:", 18 ) == 0 )
- {
- type_id += 18;
- }
-
- switch (n->kind)
- {
- case syck_str_kind:
- transferred = 1;
- if ( type_id == NULL )
- {
- obj = rb_str_new( n->data.str->ptr, n->data.str->len );
- }
- else if ( strcmp( type_id, "null" ) == 0 )
- {
- obj = Qnil;
- }
- else if ( strcmp( type_id, "binary" ) == 0 )
- {
- VALUE arr;
- obj = rb_str_new( n->data.str->ptr, n->data.str->len );
- rb_funcall( obj, s_tr_bang, 2, rb_str_new2( "\n\t " ), rb_str_new2( "" ) );
- arr = rb_funcall( obj, s_unpack, 1, rb_str_new2( "m" ) );
- obj = rb_ary_shift( arr );
- }
- else if ( strcmp( type_id, "bool#yes" ) == 0 )
- {
- obj = Qtrue;
- }
- else if ( strcmp( type_id, "bool#no" ) == 0 )
- {
- obj = Qfalse;
- }
- else if ( strcmp( type_id, "int#hex" ) == 0 )
- {
- syck_str_blow_away_commas( n );
- obj = rb_cstr2inum( n->data.str->ptr, 16 );
- }
- else if ( strcmp( type_id, "int#oct" ) == 0 )
- {
- syck_str_blow_away_commas( n );
- obj = rb_cstr2inum( n->data.str->ptr, 8 );
- }
- else if ( strcmp( type_id, "int#base60" ) == 0 )
- {
- char *ptr, *end;
- long sixty = 1;
- long total = 0;
- syck_str_blow_away_commas( n );
- ptr = n->data.str->ptr;
- end = n->data.str->ptr + n->data.str->len;
- while ( end > ptr )
- {
- long bnum = 0;
- char *colon = end - 1;
- while ( colon >= ptr && *colon != ':' )
- {
- colon--;
- }
- if ( colon >= ptr && *colon == ':' ) *colon = '\0';
-
- bnum = strtol( colon + 1, NULL, 10 );
- total += bnum * sixty;
- sixty *= 60;
- end = colon;
- }
- obj = INT2FIX(total);
- }
- else if ( strncmp( type_id, "int", 3 ) == 0 )
- {
- syck_str_blow_away_commas( n );
- obj = rb_cstr2inum( n->data.str->ptr, 10 );
- }
- else if ( strcmp( type_id, "float#base60" ) == 0 )
- {
- char *ptr, *end;
- long sixty = 1;
- double total = 0.0;
- syck_str_blow_away_commas( n );
- ptr = n->data.str->ptr;
- end = n->data.str->ptr + n->data.str->len;
- while ( end > ptr )
- {
- double bnum = 0;
- char *colon = end - 1;
- while ( colon >= ptr && *colon != ':' )
- {
- colon--;
- }
- if ( colon >= ptr && *colon == ':' ) *colon = '\0';
-
- bnum = strtod( colon + 1, NULL );
- total += bnum * sixty;
- sixty *= 60;
- end = colon;
- }
- obj = rb_float_new( total );
- }
- else if ( strcmp( type_id, "float#nan" ) == 0 )
- {
- obj = rb_float_new( S_nan() );
- }
- else if ( strcmp( type_id, "float#inf" ) == 0 )
- {
- obj = rb_float_new( S_inf() );
- }
- else if ( strcmp( type_id, "float#neginf" ) == 0 )
- {
- obj = rb_float_new( -S_inf() );
- }
- else if ( strncmp( type_id, "float", 5 ) == 0 )
- {
- double f;
- syck_str_blow_away_commas( n );
- f = strtod( n->data.str->ptr, NULL );
- obj = rb_float_new( f );
- }
- else if ( strcmp( type_id, "timestamp#iso8601" ) == 0 )
- {
- obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
- }
- else if ( strcmp( type_id, "timestamp#spaced" ) == 0 )
- {
- obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
- }
- else if ( strcmp( type_id, "timestamp#ymd" ) == 0 )
- {
- char *ptr = n->data.str->ptr;
- VALUE year, mon, day;
-
- /* Year*/
- ptr[4] = '\0';
- year = INT2FIX(strtol(ptr, NULL, 10));
-
- /* Month*/
- ptr += 4;
- while ( !ISDIGIT( *ptr ) ) ptr++;
- mon = INT2FIX(strtol(ptr, NULL, 10));
-
- /* Day*/
- ptr += 2;
- while ( !ISDIGIT( *ptr ) ) ptr++;
- day = INT2FIX(strtol(ptr, NULL, 10));
-
- if ( !cDate ) {
- /*
- * Load Date module
- */
- rb_require( "date" );
- cDate = rb_const_get( rb_cObject, rb_intern("Date") );
- }
-
- obj = rb_funcall( cDate, s_new, 3, year, mon, day );
- }
- else if ( strncmp( type_id, "timestamp", 9 ) == 0 )
- {
- obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
- }
- else if ( strncmp( type_id, "merge", 5 ) == 0 )
- {
- obj = rb_funcall( cMergeKey, s_new, 0 );
- }
- else if ( strncmp( type_id, "default", 7 ) == 0 )
- {
- obj = rb_funcall( cDefaultKey, s_new, 0 );
- }
- else if ( n->data.str->style == scalar_plain &&
- n->data.str->len > 1 &&
- strncmp( n->data.str->ptr, ":", 1 ) == 0 )
- {
- obj = rb_funcall( oDefaultResolver, s_transfer, 2,
- rb_str_new2( "tag:ruby.yaml.org,2002:sym" ),
- rb_str_new( n->data.str->ptr + 1, n->data.str->len - 1 ) );
- }
- else if ( strcmp( type_id, "str" ) == 0 )
- {
- obj = rb_str_new( n->data.str->ptr, n->data.str->len );
- }
- else
- {
- transferred = 0;
- obj = rb_str_new( n->data.str->ptr, n->data.str->len );
- }
- break;
-
- case syck_seq_kind:
- if ( type_id == NULL || strcmp( type_id, "seq" ) == 0 )
- {
- transferred = 1;
- }
- obj = rb_ary_new2( n->data.list->idx );
- for ( i = 0; i < n->data.list->idx; i++ )
- {
- rb_ary_store( obj, i, syck_seq_read( n, i ) );
- }
- break;
-
- case syck_map_kind:
- if ( type_id == NULL || strcmp( type_id, "map" ) == 0 )
- {
- transferred = 1;
- }
- obj = rb_hash_new();
- for ( i = 0; i < n->data.pairs->idx; i++ )
- {
- VALUE k = syck_map_read( n, map_key, i );
- VALUE v = syck_map_read( n, map_value, i );
- int skip_aset = 0;
-
- /*
- * Handle merge keys
- */
- if ( rb_obj_is_kind_of( k, cMergeKey ) )
- {
- VALUE tmp;
- if ( !NIL_P(tmp = rb_check_convert_type(v, T_HASH, "Hash", "to_hash")) )
- {
- VALUE dup = rb_funcall( tmp, s_dup, 0 );
- rb_funcall( dup, s_update, 1, obj );
- obj = dup;
- skip_aset = 1;
- }
- else if ( !NIL_P(tmp = rb_check_array_type(v)) )
- {
- VALUE end = rb_ary_pop( tmp );
- VALUE tmph = rb_check_convert_type(end, T_HASH, "Hash", "to_hash");
- if ( !NIL_P(tmph) )
- {
- VALUE dup = rb_funcall( tmph, s_dup, 0 );
- tmp = rb_ary_reverse( tmp );
- rb_ary_push( tmp, obj );
- rb_iterate( rb_each, tmp, syck_merge_i, dup );
- obj = dup;
- skip_aset = 1;
- }
- }
- }
- else if ( rb_obj_is_kind_of( k, cDefaultKey ) )
- {
- rb_funcall( obj, s_default_set, 1, v );
- skip_aset = 1;
- }
-
- if ( ! skip_aset )
- {
- rb_hash_aset( obj, k, v );
- }
- }
- break;
- }
-
- *ref = obj;
- return transferred;
-}
-
-static void syck_node_mark( SyckNode *n );
-
-/*
- * {native mode} node handler
- * - Converts data into native Ruby types
- */
-SYMID
-rb_syck_load_handler(p, n)
- SyckParser *p;
- SyckNode *n;
-{
- VALUE obj = Qnil;
- struct parser_xtra *bonus = (struct parser_xtra *)p->bonus;
- VALUE resolver = bonus->resolver;
- if ( NIL_P( resolver ) )
- {
- resolver = oDefaultResolver;
- }
-
- /*
- * Create node,
- */
- obj = rb_funcall( resolver, s_node_import, 1, Data_Wrap_Struct( cNode, NULL, NULL, n ) );
-
- /*
- * ID already set, let's alter the symbol table to accept the new object
- */
- if (n->id > 0 && !NIL_P(obj))
- {
- MEMCPY((void *)n->id, (void *)obj, RVALUE, 1);
- MEMZERO((void *)obj, RVALUE, 1);
- obj = n->id;
- }
-
- if ( bonus->taint) OBJ_TAINT( obj );
- if ( bonus->proc != 0 ) rb_funcall(bonus->proc, s_call, 1, obj);
-
- rb_hash_aset(bonus->data, INT2FIX(RHASH(bonus->data)->tbl->num_entries), obj);
- return obj;
-}
-
-/*
- * friendly errors.
- */
-void
-rb_syck_err_handler(p, msg)
- SyckParser *p;
- char *msg;
-{
- char *endl = p->cursor;
-
- while ( *endl != '\0' && *endl != '\n' )
- endl++;
-
- endl[0] = '\0';
- rb_raise(rb_eArgError, "%s on line %d, col %d: `%s'",
- msg,
- p->linect,
- p->cursor - p->lineptr,
- p->lineptr);
-}
-
-/*
- * provide bad anchor object to the parser.
- */
-SyckNode *
-rb_syck_bad_anchor_handler(p, a)
- SyckParser *p;
- char *a;
-{
- VALUE anchor_name = rb_str_new2( a );
- SyckNode *badanc = syck_new_map( rb_str_new2( "name" ), anchor_name );
- badanc->type_id = syck_strndup( "tag:ruby.yaml.org,2002:object:YAML::Syck::BadAlias", 53 );
- return badanc;
-}
-
-/*
- * data loaded based on the model requested.
- */
-void
-syck_set_model( p, input, model )
- VALUE p, input, model;
-{
- SyckParser *parser;
- Data_Get_Struct(p, SyckParser, parser);
- syck_parser_handler( parser, rb_syck_load_handler );
- /* WARN: gonna be obsoleted soon!! */
- if ( model == sym_generic )
- {
- rb_funcall( p, s_set_resolver, 1, oGenericResolver );
- }
- syck_parser_implicit_typing( parser, 1 );
- syck_parser_taguri_expansion( parser, 1 );
-
- if ( NIL_P( input ) )
- {
- input = rb_ivar_get( p, s_input );
- }
- if ( input == sym_bytecode )
- {
- syck_parser_set_input_type( parser, syck_bytecode_utf8 );
- }
- else
- {
- syck_parser_set_input_type( parser, syck_yaml_utf8 );
- }
- syck_parser_error_handler( parser, rb_syck_err_handler );
- syck_parser_bad_anchor_handler( parser, rb_syck_bad_anchor_handler );
-}
-
-static int
-syck_st_mark_nodes( char *key, SyckNode *n, char *arg )
-{
- if ( n != (void *)1 ) syck_node_mark( n );
- return ST_CONTINUE;
-}
-
-/*
- * mark parser nodes
- */
-static void
-syck_mark_parser(parser)
- SyckParser *parser;
-{
- struct parser_xtra *bonus = (struct parser_xtra *)parser->bonus;
- rb_gc_mark_maybe(parser->root);
- rb_gc_mark_maybe(parser->root_on_error);
- rb_gc_mark( bonus->data );
- rb_gc_mark( bonus->proc );
- rb_gc_mark( bonus->resolver );
-
- if ( parser->anchors != NULL )
- {
- st_foreach( parser->anchors, syck_st_mark_nodes, 0 );
- }
- if ( parser->bad_anchors != NULL )
- {
- st_foreach( parser->bad_anchors, syck_st_mark_nodes, 0 );
- }
-}
-
-/*
- * Free the parser and any bonus attachment.
- */
-void
-rb_syck_free_parser(p)
- SyckParser *p;
-{
- S_FREE( p->bonus );
- syck_free_parser(p);
-}
-
-/*
- * YAML::Syck::Parser.allocate
- */
-VALUE syck_parser_s_alloc _((VALUE));
-VALUE
-syck_parser_s_alloc(class)
- VALUE class;
-{
- VALUE pobj;
- SyckParser *parser = syck_new_parser();
-
- parser->bonus = S_ALLOC( struct parser_xtra );
- S_MEMZERO( parser->bonus, struct parser_xtra, 1 );
-
- pobj = Data_Wrap_Struct( class, syck_mark_parser, rb_syck_free_parser, parser );
-
- syck_parser_set_root_on_error( parser, Qnil );
-
- return pobj;
-}
-
-/*
- * YAML::Syck::Parser.initialize( resolver, options )
- */
-static VALUE
-syck_parser_initialize(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE options;
- if (rb_scan_args(argc, argv, "01", &options) == 0)
- {
- options = rb_hash_new();
- }
- else
- {
- Check_Type(options, T_HASH);
- }
- rb_ivar_set(self, s_options, options);
- rb_ivar_set(self, s_input, Qnil);
- return self;
-}
-
-/*
- * YAML::Syck::Parser.bufsize = Integer
- */
-static VALUE
-syck_parser_bufsize_set( self, size )
- VALUE self, size;
-{
- SyckParser *parser;
-
- if ( rb_respond_to( size, s_to_i ) ) {
- int n = NUM2INT(rb_funcall(size, s_to_i, 0));
- Data_Get_Struct(self, SyckParser, parser);
- parser->bufsize = n;
- }
- return self;
-}
-
-/*
- * YAML::Syck::Parser.bufsize => Integer
- */
-static VALUE
-syck_parser_bufsize_get( self )
- VALUE self;
-{
- SyckParser *parser;
-
- Data_Get_Struct(self, SyckParser, parser);
- return INT2FIX( parser->bufsize );
-}
-
-/*
- * YAML::Syck::Parser.load( IO or String )
- */
-VALUE
-syck_parser_load(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE port, proc, model, input;
- SyckParser *parser;
- struct parser_xtra *bonus;
-
- rb_scan_args(argc, argv, "11", &port, &proc);
-
- input = rb_hash_aref( rb_attr_get( self, s_options ), sym_input );
- model = rb_hash_aref( rb_attr_get( self, s_options ), sym_model );
- Data_Get_Struct(self, SyckParser, parser);
- syck_set_model( self, input, model );
-
- bonus = (struct parser_xtra *)parser->bonus;
- bonus->taint = syck_parser_assign_io(parser, &port);
- bonus->data = rb_hash_new();
- bonus->resolver = rb_attr_get( self, s_resolver );
- if ( NIL_P( proc ) ) bonus->proc = 0;
- else bonus->proc = proc;
-
- return syck_parse( parser );
-}
-
-/*
- * YAML::Syck::Parser.load_documents( IO or String ) { |doc| }
- */
-VALUE
-syck_parser_load_documents(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE port, proc, v, input, model;
- SyckParser *parser;
- struct parser_xtra *bonus;
-
- rb_scan_args(argc, argv, "1&", &port, &proc);
-
- input = rb_hash_aref( rb_attr_get( self, s_options ), sym_input );
- model = rb_hash_aref( rb_attr_get( self, s_options ), sym_model );
- Data_Get_Struct(self, SyckParser, parser);
- syck_set_model( self, input, model );
-
- bonus = (struct parser_xtra *)parser->bonus;
- bonus->taint = syck_parser_assign_io(parser, &port);
- bonus->resolver = rb_attr_get( self, s_resolver );
- bonus->proc = 0;
-
- while ( 1 )
- {
- /* Reset hash for tracking nodes */
- bonus->data = rb_hash_new();
-
- /* Parse a document */
- v = syck_parse( parser );
- if ( parser->eof == 1 )
- {
- break;
- }
-
- /* Pass document to block */
- rb_funcall( proc, s_call, 1, v );
- }
-
- return Qnil;
-}
-
-/*
- * YAML::Syck::Parser#set_resolver
- */
-VALUE
-syck_parser_set_resolver( self, resolver )
- VALUE self, resolver;
-{
- rb_ivar_set( self, s_resolver, resolver );
- return self;
-}
-
-/*
- * YAML::Syck::Resolver.initialize
- */
-static VALUE
-syck_resolver_initialize( self )
- VALUE self;
-{
- VALUE tags = rb_hash_new();
- rb_ivar_set(self, s_tags, rb_hash_new());
- return self;
-}
-
-/*
- * YAML::Syck::Resolver#add_type
- */
-VALUE
-syck_resolver_add_type( self, taguri, cls )
- VALUE self, taguri, cls;
-{
- VALUE tags = rb_attr_get(self, s_tags);
- rb_hash_aset( tags, taguri, cls );
- return Qnil;
-}
-
-/*
- * YAML::Syck::Resolver#use_types_at
- */
-VALUE
-syck_resolver_use_types_at( self, hsh )
- VALUE self, hsh;
-{
- rb_ivar_set( self, s_tags, hsh );
- return Qnil;
-}
-
-/*
- * YAML::Syck::Resolver#detect_implicit
- */
-VALUE
-syck_resolver_detect_implicit( self, val )
- VALUE self, val;
-{
- char *type_id;
- return rb_str_new2( "" );
-}
-
-/*
- * YAML::Syck::Resolver#node_import
- */
-VALUE
-syck_resolver_node_import( self, node )
- VALUE self, node;
-{
- SyckNode *n;
- VALUE obj;
- int i = 0;
- Data_Get_Struct(node, SyckNode, n);
-
- switch (n->kind)
- {
- case syck_str_kind:
- obj = rb_str_new( n->data.str->ptr, n->data.str->len );
- break;
-
- case syck_seq_kind:
- obj = rb_ary_new2( n->data.list->idx );
- for ( i = 0; i < n->data.list->idx; i++ )
- {
- rb_ary_store( obj, i, syck_seq_read( n, i ) );
- }
- break;
-
- case syck_map_kind:
- obj = rb_hash_new();
- for ( i = 0; i < n->data.pairs->idx; i++ )
- {
- VALUE k = syck_map_read( n, map_key, i );
- VALUE v = syck_map_read( n, map_value, i );
- int skip_aset = 0;
-
- /*
- * Handle merge keys
- */
- if ( rb_obj_is_kind_of( k, cMergeKey ) )
- {
- if ( rb_obj_is_kind_of( v, rb_cHash ) )
- {
- VALUE dup = rb_funcall( v, s_dup, 0 );
- rb_funcall( dup, s_update, 1, obj );
- obj = dup;
- skip_aset = 1;
- }
- else if ( rb_obj_is_kind_of( v, rb_cArray ) )
- {
- VALUE end = rb_ary_pop( v );
- if ( rb_obj_is_kind_of( end, rb_cHash ) )
- {
- VALUE dup = rb_funcall( end, s_dup, 0 );
- v = rb_ary_reverse( v );
- rb_ary_push( v, obj );
- rb_iterate( rb_each, v, syck_merge_i, dup );
- obj = dup;
- skip_aset = 1;
- }
- }
- }
- else if ( rb_obj_is_kind_of( k, cDefaultKey ) )
- {
- rb_funcall( obj, s_default_set, 1, v );
- skip_aset = 1;
- }
-
- if ( ! skip_aset )
- {
- rb_hash_aset( obj, k, v );
- }
- }
- break;
- }
-
- if ( n->type_id != NULL )
- {
- obj = rb_funcall( self, s_transfer, 2, rb_str_new2( n->type_id ), obj );
- }
- return obj;
-}
-
-/*
- * Set instance variables
- */
-VALUE
-syck_set_ivars( vars, obj )
- VALUE vars, obj;
-{
- VALUE ivname = rb_ary_entry( vars, 0 );
- char *ivn;
- StringValue( ivname );
- ivn = S_ALLOCA_N( char, RSTRING(ivname)->len + 2 );
- ivn[0] = '@';
- ivn[1] = '\0';
- strncat( ivn, RSTRING(ivname)->ptr, RSTRING(ivname)->len );
- rb_iv_set( obj, ivn, rb_ary_entry( vars, 1 ) );
- return Qnil;
-}
-
-/*
- * YAML::Syck::Resolver#const_find
- */
-VALUE
-syck_const_find( const_name )
- VALUE const_name;
-{
- VALUE tclass = rb_cObject;
- VALUE tparts = rb_str_split( const_name, "::" );
- int i = 0;
- for ( i = 0; i < RARRAY(tparts)->len; i++ ) {
- VALUE tpart = rb_to_id( rb_ary_entry( tparts, i ) );
- if ( !rb_const_defined( tclass, tpart ) ) return Qnil;
- tclass = rb_const_get( tclass, tpart );
- }
- return tclass;
-}
-
-/*
- * YAML::Syck::Resolver#transfer
- */
-VALUE
-syck_resolver_transfer( self, type, val )
- VALUE self, type, val;
-{
- if (NIL_P(type) || RSTRING(StringValue(type))->len == 0)
- {
- type = rb_funcall( self, s_detect_implicit, 1, val );
- }
-
- if ( ! (NIL_P(type) || RSTRING(StringValue(type))->len == 0) )
- {
- VALUE str_xprivate = rb_str_new2( "x-private" );
- VALUE colon = rb_str_new2( ":" );
- VALUE tags = rb_attr_get(self, s_tags);
- VALUE target_class = rb_hash_aref( tags, type );
- VALUE subclass = target_class;
- VALUE obj = Qnil;
-
- /*
- * Should no tag match exactly, check for subclass format
- */
- if ( NIL_P( target_class ) )
- {
- VALUE subclass_parts = rb_ary_new();
- VALUE parts = rb_str_split( type, ":" );
-
- while ( RARRAY(parts)->len > 1 )
- {
- VALUE partial;
- rb_ary_unshift( subclass_parts, rb_ary_pop( parts ) );
- partial = rb_ary_join( parts, colon );
- target_class = rb_hash_aref( tags, partial );
- if ( NIL_P( target_class ) )
- {
- rb_str_append( partial, colon );
- target_class = rb_hash_aref( tags, partial );
- }
-
- /*
- * Possible subclass found, see if it supports subclassing
- */
- if ( ! NIL_P( target_class ) )
- {
- subclass = target_class;
- if ( RARRAY(subclass_parts)->len > 0 && rb_respond_to( target_class, s_tag_subclasses ) &&
- RTEST( rb_funcall( target_class, s_tag_subclasses, 0 ) ) )
- {
- VALUE subclass_v;
- subclass = rb_ary_join( subclass_parts, colon );
- subclass = rb_funcall( target_class, s_tag_read_class, 1, subclass );
- subclass_v = syck_const_find( subclass );
-
- if ( subclass_v != Qnil )
- {
- subclass = subclass_v;
- }
- else if ( rb_cObject == target_class && subclass_v == Qnil )
- {
- target_class = cYObject;
- type = subclass;
- subclass = cYObject;
- }
- else /* workaround for SEGV. real fix please */
- {
- rb_raise( rb_eTypeError, "invalid subclass" );
- }
- }
- break;
- }
- }
- }
-
- /* rb_raise(rb_eTypeError, "invalid typing scheme: %s given",
- * scheme);
- */
-
- if ( rb_respond_to( target_class, s_call ) )
- {
- obj = rb_funcall( target_class, s_call, 2, type, val );
- }
- else
- {
- if ( rb_respond_to( target_class, s_yaml_new ) )
- {
- obj = rb_funcall( target_class, s_yaml_new, 3, subclass, type, val );
- }
- else if ( !NIL_P( target_class ) )
- {
- if ( subclass == rb_cBignum )
- {
- obj = rb_str2inum( val, 10 ); /* for yaml dumped by 1.8.3 [ruby-core:6159] */
- }
- else
- {
- obj = rb_obj_alloc( subclass );
- }
-
- if ( rb_respond_to( obj, s_yaml_initialize ) )
- {
- rb_funcall( obj, s_yaml_initialize, 2, type, val );
- }
- else if ( !NIL_P( obj ) && rb_obj_is_instance_of( val, rb_cHash ) )
- {
- rb_iterate( rb_each, val, syck_set_ivars, obj );
- }
- }
- else
- {
- VALUE parts = rb_str_split( type, ":" );
- VALUE scheme = rb_ary_shift( parts );
- if ( rb_str_cmp( scheme, str_xprivate ) == 0 )
- {
- VALUE name = rb_ary_join( parts, colon );
- obj = rb_funcall( cPrivateType, s_new, 2, name, val );
- }
- else
- {
- VALUE domain = rb_ary_shift( parts );
- VALUE name = rb_ary_join( parts, colon );
- obj = rb_funcall( cDomainType, s_new, 3, domain, name, val );
- }
- }
- }
- val = obj;
- }
-
- return val;
-}
-
-/*
- * YAML::Syck::Resolver#tagurize
- */
-VALUE
-syck_resolver_tagurize( self, val )
- VALUE self, val;
-{
- VALUE tmp = rb_check_string_type(val);
-
- if ( !NIL_P(tmp) )
- {
- char *taguri = syck_type_id_to_uri( RSTRING(tmp)->ptr );
- val = rb_str_new2( taguri );
- S_FREE( taguri );
- }
-
- return val;
-}
-
-/*
- * YAML::Syck::DefaultResolver#detect_implicit
- */
-VALUE
-syck_defaultresolver_detect_implicit( self, val )
- VALUE self, val;
-{
- char *type_id;
- VALUE tmp = rb_check_string_type(val);
-
- if ( !NIL_P(tmp) )
- {
- val = tmp;
- type_id = syck_match_implicit( RSTRING(val)->ptr, RSTRING(val)->len );
- return rb_str_new2( type_id );
- }
-
- return rb_str_new2( "" );
-}
-
-/*
- * YAML::Syck::DefaultResolver#node_import
- */
-VALUE
-syck_defaultresolver_node_import( self, node )
- VALUE self, node;
-{
- SyckNode *n;
- VALUE obj;
- Data_Get_Struct( node, SyckNode, n );
- if ( !yaml_org_handler( n, &obj ) )
- {
- obj = rb_funcall( self, s_transfer, 2, rb_str_new2( n->type_id ), obj );
- }
- return obj;
-}
-
-/*
- * YAML::Syck::GenericResolver#node_import
- */
-VALUE
-syck_genericresolver_node_import( self, node )
- VALUE self, node;
-{
- SyckNode *n;
- int i = 0;
- VALUE t = Qnil, obj = Qnil, v = Qnil, style = Qnil;
- Data_Get_Struct(node, SyckNode, n);
-
- if ( n->type_id != NULL )
- {
- t = rb_str_new2(n->type_id);
- }
-
- switch (n->kind)
- {
- case syck_str_kind:
- {
- v = rb_str_new( n->data.str->ptr, n->data.str->len );
- if ( n->data.str->style == scalar_1quote )
- {
- style = sym_1quote;
- }
- else if ( n->data.str->style == scalar_2quote )
- {
- style = sym_2quote;
- }
- else if ( n->data.str->style == scalar_fold )
- {
- style = sym_fold;
- }
- else if ( n->data.str->style == scalar_literal )
- {
- style = sym_literal;
- }
- else if ( n->data.str->style == scalar_plain )
- {
- style = sym_plain;
- }
- obj = rb_funcall( cScalar, s_new, 3, t, v, style );
- }
- break;
-
- case syck_seq_kind:
- rb_iv_set(obj, "@kind", sym_seq);
- v = rb_ary_new2( syck_seq_count( n ) );
- for ( i = 0; i < syck_seq_count( n ); i++ )
- {
- rb_ary_store( v, i, syck_seq_read( n, i ) );
- }
- if ( n->data.list->style == seq_inline )
- {
- style = sym_inline;
- }
- obj = rb_funcall( cSeq, s_new, 3, t, v, style );
- break;
-
- case syck_map_kind:
- rb_iv_set(obj, "@kind", sym_map);
- v = rb_hash_new();
- for ( i = 0; i < syck_map_count( n ); i++ )
- {
- rb_hash_aset( v, syck_map_read( n, map_key, i ), syck_map_read( n, map_value, i ) );
- }
- if ( n->data.pairs->style == map_inline )
- {
- style = sym_inline;
- }
- obj = rb_funcall( cMap, s_new, 3, t, v, style );
- break;
- }
-
- return obj;
-}
-
-/*
- * YAML::Syck::BadAlias.initialize
- */
-VALUE
-syck_badalias_initialize( self, val )
- VALUE self, val;
-{
- rb_iv_set( self, "@name", val );
- return self;
-}
-
-/*
- * YAML::Syck::BadAlias.<=>
- */
-VALUE
-syck_badalias_cmp( alias1, alias2 )
- VALUE alias1, alias2;
-{
- VALUE str1 = rb_ivar_get( alias1, s_name );
- VALUE str2 = rb_ivar_get( alias2, s_name );
- VALUE val = rb_funcall( str1, s_cmp, 1, str2 );
- return val;
-}
-
-/*
- * YAML::DomainType.initialize
- */
-VALUE
-syck_domaintype_initialize( self, domain, type_id, val )
- VALUE self, domain, type_id, val;
-{
- rb_iv_set( self, "@domain", domain );
- rb_iv_set( self, "@type_id", type_id );
- rb_iv_set( self, "@value", val );
- return self;
-}
-
-/*
- * YAML::Object.initialize
- */
-VALUE
-syck_yobject_initialize( self, klass, ivars )
- VALUE self, klass, ivars;
-{
- rb_iv_set( self, "@class", klass );
- rb_iv_set( self, "@ivars", ivars );
- return self;
-}
-
-/*
- * YAML::PrivateType.initialize
- */
-VALUE
-syck_privatetype_initialize( self, type_id, val )
- VALUE self, type_id, val;
-{
- rb_iv_set( self, "@type_id", type_id );
- rb_iv_set( self, "@value", val );
- return self;
-}
-
-/*
- * Mark node contents.
- */
-static void
-syck_node_mark( n )
- SyckNode *n;
-{
- int i;
- rb_gc_mark_maybe( n->id );
- switch ( n->kind )
- {
- case syck_seq_kind:
- for ( i = 0; i < n->data.list->idx; i++ )
- {
- rb_gc_mark( syck_seq_read( n, i ) );
- }
- break;
-
- case syck_map_kind:
- for ( i = 0; i < n->data.pairs->idx; i++ )
- {
- rb_gc_mark( syck_map_read( n, map_key, i ) );
- rb_gc_mark( syck_map_read( n, map_value, i ) );
- }
- break;
- }
-#if 0 /* maybe needed */
- if ( n->shortcut ) syck_node_mark( n->shortcut ); /* caution: maybe cyclic */
-#endif
-}
-
-/*
- * YAML::Syck::Scalar.allocate
- */
-VALUE
-syck_scalar_alloc( class )
- VALUE class;
-{
- SyckNode *node = syck_alloc_str();
- VALUE obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
- node->id = obj;
- return obj;
-}
-
-/*
- * YAML::Syck::Scalar.initialize
- */
-VALUE
-syck_scalar_initialize( self, type_id, val, style )
- VALUE self, type_id, val, style;
-{
- rb_iv_set( self, "@kind", sym_scalar );
- rb_funcall( self, s_type_id_set, 1, type_id );
- rb_funcall( self, s_value_set, 1, val );
- rb_funcall( self, s_style_set, 1, style );
- return self;
-}
-
-/*
- * YAML::Syck::Scalar.style=
- */
-VALUE
-syck_scalar_style_set( self, style )
- VALUE self, style;
-{
- SyckNode *node;
- Data_Get_Struct( self, SyckNode, node );
-
- if ( NIL_P( style ) )
- {
- node->data.str->style = scalar_none;
- }
- else if ( style == sym_1quote )
- {
- node->data.str->style = scalar_1quote;
- }
- else if ( style == sym_2quote )
- {
- node->data.str->style = scalar_2quote;
- }
- else if ( style == sym_fold )
- {
- node->data.str->style = scalar_fold;
- }
- else if ( style == sym_literal )
- {
- node->data.str->style = scalar_literal;
- }
- else if ( style == sym_plain )
- {
- node->data.str->style = scalar_plain;
- }
-
- rb_iv_set( self, "@style", style );
- return self;
-}
-
-/*
- * YAML::Syck::Scalar.value=
- */
-VALUE
-syck_scalar_value_set( self, val )
- VALUE self, val;
-{
- SyckNode *node;
- Data_Get_Struct( self, SyckNode, node );
-
- StringValue( val );
- node->data.str->ptr = syck_strndup( RSTRING(val)->ptr, RSTRING(val)->len );
- node->data.str->len = RSTRING(val)->len;
- node->data.str->style = scalar_none;
-
- rb_iv_set( self, "@value", val );
- return val;
-}
-
-/*
- * YAML::Syck::Seq.allocate
- */
-VALUE
-syck_seq_alloc( class )
- VALUE class;
-{
- SyckNode *node;
- VALUE obj;
- node = syck_alloc_seq();
- obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
- node->id = obj;
- return obj;
-}
-
-/*
- * YAML::Syck::Seq.initialize
- */
-VALUE
-syck_seq_initialize( self, type_id, val, style )
- VALUE self, type_id, val, style;
-{
- SyckNode *node;
- Data_Get_Struct( self, SyckNode, node );
-
- rb_iv_set( self, "@kind", sym_seq );
- rb_funcall( self, s_type_id_set, 1, type_id );
- rb_funcall( self, s_value_set, 1, val );
- rb_funcall( self, s_style_set, 1, style );
- return self;
-}
-
-/*
- * YAML::Syck::Seq.value=
- */
-VALUE
-syck_seq_value_set( self, val )
- VALUE self, val;
-{
- SyckNode *node;
- Data_Get_Struct( self, SyckNode, node );
-
- val = rb_check_array_type( val );
- if ( !NIL_P( val ) ) {
- int i;
- syck_seq_empty( node );
- for ( i = 0; i < RARRAY( val )->len; i++ )
- {
- syck_seq_add( node, rb_ary_entry(val, i) );
- }
- }
-
- rb_iv_set( self, "@value", val );
- return val;
-}
-
-/*
- * YAML::Syck::Seq.add
- */
-VALUE
-syck_seq_add_m( self, val )
- VALUE self, val;
-{
- SyckNode *node;
- VALUE emitter = rb_ivar_get( self, s_emitter );
- Data_Get_Struct( self, SyckNode, node );
-
- if ( rb_respond_to( emitter, s_node_export ) ) {
- val = rb_funcall( emitter, s_node_export, 1, val );
- }
- syck_seq_add( node, val );
- rb_ary_push( rb_ivar_get( self, s_value ), val );
-
- return self;
-}
-
-/*
- * YAML::Syck::Seq.style=
- */
-VALUE
-syck_seq_style_set( self, style )
- VALUE self, style;
-{
- SyckNode *node;
- Data_Get_Struct( self, SyckNode, node );
-
- if ( style == sym_inline )
- {
- node->data.list->style = seq_inline;
- }
- else
- {
- node->data.list->style = seq_none;
- }
-
- rb_iv_set( self, "@style", style );
- return self;
-}
-
-/*
- * YAML::Syck::Map.allocate
- */
-VALUE
-syck_map_alloc( class )
- VALUE class;
-{
- SyckNode *node;
- VALUE obj;
- node = syck_alloc_map();
- obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
- node->id = obj;
- return obj;
-}
-
-/*
- * YAML::Syck::Map.initialize
- */
-VALUE
-syck_map_initialize( self, type_id, val, style )
- VALUE self, type_id, val, style;
-{
- SyckNode *node;
- Data_Get_Struct( self, SyckNode, node );
-
- if ( !NIL_P( val ) )
- {
- VALUE hsh = rb_check_convert_type(val, T_HASH, "Hash", "to_hash");
- VALUE keys;
- int i;
- if ( NIL_P(hsh) )
- {
- rb_raise( rb_eTypeError, "wrong argument type" );
- }
-
- keys = rb_funcall( hsh, s_keys, 0 );
- for ( i = 0; i < RARRAY(keys)->len; i++ )
- {
- VALUE key = rb_ary_entry(keys, i);
- syck_map_add( node, key, rb_hash_aref(hsh, key) );
- }
- }
-
- rb_iv_set( self, "@kind", sym_seq );
- rb_funcall( self, s_type_id_set, 1, type_id );
- rb_funcall( self, s_value_set, 1, val );
- rb_funcall( self, s_style_set, 1, style );
- return self;
-}
-
-/*
- * YAML::Syck::Map.value=
- */
-VALUE
-syck_map_value_set( self, val )
- VALUE self, val;
-{
- SyckNode *node;
- Data_Get_Struct( self, SyckNode, node );
-
- if ( !NIL_P( val ) )
- {
- VALUE hsh = rb_check_convert_type(val, T_HASH, "Hash", "to_hash");
- VALUE keys;
- int i;
- if ( NIL_P(hsh) )
- {
- rb_raise( rb_eTypeError, "wrong argument type" );
- }
-
- syck_map_empty( node );
- keys = rb_funcall( hsh, s_keys, 0 );
- for ( i = 0; i < RARRAY(keys)->len; i++ )
- {
- VALUE key = rb_ary_entry(keys, i);
- syck_map_add( node, key, rb_hash_aref(hsh, key) );
- }
- }
-
- rb_iv_set( self, "@value", val );
- return val;
-}
-
-/*
- * YAML::Syck::Map.add
- */
-VALUE
-syck_map_add_m( self, key, val )
- VALUE self, key, val;
-{
- SyckNode *node;
- VALUE emitter = rb_ivar_get( self, s_emitter );
- Data_Get_Struct( self, SyckNode, node );
-
- if ( rb_respond_to( emitter, s_node_export ) ) {
- key = rb_funcall( emitter, s_node_export, 1, key );
- val = rb_funcall( emitter, s_node_export, 1, val );
- }
- syck_map_add( node, key, val );
- rb_hash_aset( rb_ivar_get( self, s_value ), key, val );
-
- return self;
-}
-
-/*
- * YAML::Syck::Map.style=
- */
-VALUE
-syck_map_style_set( self, style )
- VALUE self, style;
-{
- SyckNode *node;
- Data_Get_Struct( self, SyckNode, node );
-
- if ( style == sym_inline )
- {
- node->data.pairs->style = map_inline;
- }
- else
- {
- node->data.pairs->style = map_none;
- }
-
- rb_iv_set( self, "@style", style );
- return self;
-}
-
-/*
- * Cloning method for all node types
- */
-VALUE
-syck_node_init_copy( copy, orig )
- VALUE copy, orig;
-{
- SyckNode *copy_n;
- SyckNode *orig_n;
-
- if ( copy == orig )
- return copy;
-
- if ( TYPE( orig ) != T_DATA )
- {
- rb_raise( rb_eTypeError, "wrong argument type" );
- }
-
- Data_Get_Struct( orig, SyckNode, orig_n );
- Data_Get_Struct( copy, SyckNode, copy_n );
- MEMCPY( copy_n, orig_n, SyckNode, 1 );
- return copy;
-}
-
-/*
- * YAML::Syck::Node#type_id=
- */
-VALUE
-syck_node_type_id_set( self, type_id )
- VALUE self, type_id;
-{
- SyckNode *node;
- Data_Get_Struct( self, SyckNode, node );
-
- S_FREE( node->type_id );
-
- if ( !NIL_P( type_id ) ) {
- StringValue( type_id );
- node->type_id = syck_strndup( RSTRING(type_id)->ptr, RSTRING(type_id)->len );
- }
-
- rb_iv_set( self, "@type_id", type_id );
- return type_id;
-}
-
-/*
- * YAML::Syck::Node.transform
- */
-VALUE
-syck_node_transform( self )
- VALUE self;
-{
- VALUE t;
- SyckNode *n;
- SyckNode *orig_n;
- Data_Get_Struct(self, SyckNode, orig_n);
- t = Data_Wrap_Struct( cNode, syck_node_mark, syck_free_node, 0 );
-
- switch (orig_n->kind)
- {
- case syck_map_kind:
- {
- int i;
- DATA_PTR(t) = n = syck_alloc_map();
- for ( i = 0; i < orig_n->data.pairs->idx; i++ )
- {
- syck_map_add( n, rb_funcall( syck_map_read( orig_n, map_key, i ), s_transform, 0 ),
- rb_funcall( syck_map_read( orig_n, map_value, i ), s_transform, 0 ) );
- }
- }
- break;
-
- case syck_seq_kind:
- {
- int i;
- DATA_PTR(t) = n = syck_alloc_seq();
- for ( i = 0; i < orig_n->data.list->idx; i++ )
- {
- syck_seq_add( n, rb_funcall( syck_seq_read( orig_n, i ), s_transform, 0 ) );
- }
- }
- break;
-
- case syck_str_kind:
- DATA_PTR(t) = n = syck_new_str2( orig_n->data.str->ptr, orig_n->data.str->len, orig_n->data.str->style );
- break;
- }
-
- if ( orig_n->type_id != NULL )
- {
- n->type_id = syck_strndup( orig_n->type_id, strlen( orig_n->type_id ) );
- }
- if ( orig_n->anchor != NULL )
- {
- n->anchor = syck_strndup( orig_n->anchor, strlen( orig_n->anchor ) );
- }
- n->id = t;
- return rb_funcall( oDefaultResolver, s_node_import, 1, t );
-}
-
-/*
- * Emitter callback: assembles YAML document events from
- * Ruby symbols. This is a brilliant way to do it.
- * No one could possibly object.
- */
-void
-rb_syck_emitter_handler(e, data)
- SyckEmitter *e;
- st_data_t data;
-{
- SyckNode *n;
- Data_Get_Struct((VALUE)data, SyckNode, n);
-
- switch (n->kind)
- {
- case syck_map_kind:
- {
- int i;
- syck_emit_map( e, n->type_id, n->data.pairs->style );
- for ( i = 0; i < n->data.pairs->idx; i++ )
- {
- syck_emit_item( e, syck_map_read( n, map_key, i ) );
- syck_emit_item( e, syck_map_read( n, map_value, i ) );
- }
- syck_emit_end( e );
- }
- break;
-
- case syck_seq_kind:
- {
- int i;
- syck_emit_seq( e, n->type_id, n->data.list->style );
- for ( i = 0; i < n->data.list->idx; i++ )
- {
- syck_emit_item( e, syck_seq_read( n, i ) );
- }
- syck_emit_end( e );
- }
- break;
-
- case syck_str_kind:
- {
- syck_emit_scalar( e, n->type_id, n->data.str->style, 0, 0, 0, n->data.str->ptr, n->data.str->len );
- }
- break;
- }
-}
-
-/*
- * Handle output from the emitter
- */
-void
-rb_syck_output_handler( emitter, str, len )
- SyckEmitter *emitter;
- char *str;
- long len;
-{
- struct emitter_xtra *bonus = (struct emitter_xtra *)emitter->bonus;
- VALUE dest = bonus->port;
- if (TYPE(dest) == T_STRING) {
- rb_str_cat( dest, str, len );
- } else {
- rb_io_write( dest, rb_str_new( str, len ) );
- }
-}
-
-/*
- * Helper function for marking nodes in the anchor
- * symbol table.
- */
-void
-syck_out_mark( emitter, node )
- VALUE emitter, node;
-{
- SyckEmitter *emitterPtr;
- struct emitter_xtra *bonus;
- Data_Get_Struct(emitter, SyckEmitter, emitterPtr);
- bonus = (struct emitter_xtra *)emitterPtr->bonus;
- rb_ivar_set( node, s_emitter, emitter );
- /* syck_emitter_mark_node( emitterPtr, (st_data_t)node ); */
- if ( !NIL_P( bonus->oid ) ) {
- rb_hash_aset( bonus->data, bonus->oid, node );
- }
-}
-
-/*
- * Mark emitter values.
- */
-static void
-syck_mark_emitter(emitter)
- SyckEmitter *emitter;
-{
- struct emitter_xtra *bonus = (struct emitter_xtra *)emitter->bonus;
- rb_gc_mark( bonus->oid );
- rb_gc_mark( bonus->data );
- rb_gc_mark( bonus->port );
-}
-
-/*
- * Free the emitter and any bonus attachment.
- */
-void
-rb_syck_free_emitter(e)
- SyckEmitter *e;
-{
- S_FREE( e->bonus );
- syck_free_emitter(e);
-}
-
-/*
- * YAML::Syck::Emitter.allocate
- */
-VALUE syck_emitter_s_alloc _((VALUE));
-VALUE
-syck_emitter_s_alloc(class)
- VALUE class;
-{
- VALUE pobj;
- SyckEmitter *emitter = syck_new_emitter();
-
- emitter->bonus = S_ALLOC( struct emitter_xtra );
- S_MEMZERO( emitter->bonus, struct emitter_xtra, 1 );
-
- pobj = Data_Wrap_Struct( class, syck_mark_emitter, rb_syck_free_emitter, emitter );
- syck_emitter_handler( emitter, rb_syck_emitter_handler );
- syck_output_handler( emitter, rb_syck_output_handler );
-
- rb_ivar_set( pobj, s_out, rb_funcall( cOut, s_new, 1, pobj ) );
- return pobj;
-}
-
-/*
- * YAML::Syck::Emitter.reset( options )
- */
-VALUE
-syck_emitter_reset( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE options, tmp;
- SyckEmitter *emitter;
- struct emitter_xtra *bonus;
-
- Data_Get_Struct(self, SyckEmitter, emitter);
- bonus = (struct emitter_xtra *)emitter->bonus;
-
- bonus->oid = Qnil;
- bonus->port = rb_str_new2( "" );
- bonus->data = rb_hash_new();
-
- if (rb_scan_args(argc, argv, "01", &options) == 0)
- {
- options = rb_hash_new();
- rb_ivar_set(self, s_options, options);
- }
- else if ( !NIL_P(tmp = rb_check_string_type(options)) )
- {
- bonus->port = tmp;
- }
- else if ( rb_respond_to( options, s_write ) )
- {
- bonus->port = options;
- }
- else
- {
- Check_Type(options, T_HASH);
- rb_ivar_set(self, s_options, options);
- }
-
- emitter->headless = 0;
- rb_ivar_set(self, s_level, INT2FIX(0));
- rb_ivar_set(self, s_resolver, Qnil);
- return self;
-}
-
-/*
- * YAML::Syck::Emitter.emit( object_id ) { |out| ... }
- */
-VALUE
-syck_emitter_emit( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE oid, proc;
- char *anchor_name;
- SyckEmitter *emitter;
- struct emitter_xtra *bonus;
- SYMID symple;
- int level = FIX2INT(rb_ivar_get(self, s_level)) + 1;
- rb_ivar_set(self, s_level, INT2FIX(level));
-
- rb_scan_args(argc, argv, "1&", &oid, &proc);
- Data_Get_Struct(self, SyckEmitter, emitter);
- bonus = (struct emitter_xtra *)emitter->bonus;
-
- /* Calculate anchors, normalize nodes, build a simpler symbol table */
- bonus->oid = oid;
- if ( !NIL_P( oid ) && RTEST( rb_funcall( bonus->data, s_haskey, 1, oid ) ) ) {
- symple = rb_hash_aref( bonus->data, oid );
- } else {
- symple = rb_funcall( proc, s_call, 1, rb_ivar_get( self, s_out ) );
- }
- syck_emitter_mark_node( emitter, (st_data_t)symple );
-
- /* Second pass, build emitted string */
- level -= 1;
- rb_ivar_set(self, s_level, INT2FIX(level));
- if ( level == 0 )
- {
- syck_emit(emitter, (st_data_t)symple);
- syck_emitter_flush(emitter, 0);
-
- return bonus->port;
- }
-
- return symple;
-}
-
-/*
- * YAML::Syck::Emitter#node_export
- */
-VALUE
-syck_emitter_node_export( self, node )
- VALUE self, node;
-{
- return rb_funcall( node, s_to_yaml, 1, self );
-}
-
-/*
- * YAML::Syck::Emitter#set_resolver
- */
-VALUE
-syck_emitter_set_resolver( self, resolver )
- VALUE self, resolver;
-{
- rb_ivar_set( self, s_resolver, resolver );
- return self;
-}
-
-/*
- * YAML::Syck::Out::initialize
- */
-VALUE
-syck_out_initialize( self, emitter )
- VALUE self, emitter;
-{
- rb_ivar_set( self, s_emitter, emitter );
- return self;
-}
-
-/*
- * YAML::Syck::Out::map
- */
-VALUE
-syck_out_map( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE type_id, style, map;
- if (rb_scan_args(argc, argv, "11", &type_id, &style) == 1) {
- style = Qnil;
- }
- map = rb_funcall( cMap, s_new, 3, type_id, rb_hash_new(), style );
- syck_out_mark( rb_ivar_get( self, s_emitter ), map );
- rb_yield( map );
- return map;
-}
-
-/*
- * YAML::Syck::Out::seq
- */
-VALUE
-syck_out_seq( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE type_id, style, seq;
- if (rb_scan_args(argc, argv, "11", &type_id, &style) == 1) {
- style = Qnil;
- }
- seq = rb_funcall( cSeq, s_new, 3, type_id, rb_ary_new(), style );
- syck_out_mark( rb_ivar_get( self, s_emitter ), seq );
- rb_yield( seq );
- return seq;
-}
-
-/*
- * YAML::Syck::Out::scalar
-syck_out_scalar( self, type_id, str, style )
- VALUE self, type_id, str, style;
- */
-VALUE
-syck_out_scalar( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE type_id, str, style, scalar;
- if (rb_scan_args(argc, argv, "21", &type_id, &str, &style) == 2) {
- style = Qnil;
- }
- scalar = rb_funcall( cScalar, s_new, 3, type_id, str, style );
- syck_out_mark( rb_ivar_get( self, s_emitter ), scalar );
- return scalar;
-}
-
-/*
- * Initialize Syck extension
- */
-void
-Init_syck()
-{
- VALUE rb_yaml = rb_define_module( "YAML" );
- VALUE rb_syck = rb_define_module_under( rb_yaml, "Syck" );
- rb_define_const( rb_syck, "VERSION", rb_str_new2( SYCK_VERSION ) );
- rb_define_module_function( rb_syck, "compile", rb_syck_compile, 1 );
-
- /*
- * Global symbols
- */
- s_new = rb_intern("new");
- s_utc = rb_intern("utc");
- s_at = rb_intern("at");
- s_to_f = rb_intern("to_f");
- s_to_i = rb_intern("to_i");
- s_read = rb_intern("read");
- s_binmode = rb_intern("binmode");
- s_transfer = rb_intern("transfer");
- s_call = rb_intern("call");
- s_cmp = rb_intern("<=>");
- s_intern = rb_intern("intern");
- s_update = rb_intern("update");
- s_detect_implicit = rb_intern("detect_implicit");
- s_dup = rb_intern("dup");
- s_default_set = rb_intern("default=");
- s_match = rb_intern("match");
- s_push = rb_intern("push");
- s_haskey = rb_intern("has_key?");
- s_keys = rb_intern("keys");
- s_node_import = rb_intern("node_import");
- s_tr_bang = rb_intern("tr!");
- s_unpack = rb_intern("unpack");
- s_write = rb_intern("write");
- s_tag_read_class = rb_intern( "yaml_tag_read_class" );
- s_tag_subclasses = rb_intern( "yaml_tag_subclasses?" );
- s_emitter = rb_intern( "emitter" );
- s_set_resolver = rb_intern( "set_resolver" );
- s_node_export = rb_intern( "node_export" );
- s_to_yaml = rb_intern( "to_yaml" );
- s_transform = rb_intern( "transform" );
- s_yaml_new = rb_intern("yaml_new");
- s_yaml_initialize = rb_intern("yaml_initialize");
-
- s_tags = rb_intern("@tags");
- s_name = rb_intern("@name");
- s_options = rb_intern("@options");
- s_kind = rb_intern("@kind");
- s_type_id = rb_intern("@type_id");
- s_type_id_set = rb_intern("type_id=");
- s_resolver = rb_intern("@resolver");
- s_level = rb_intern( "@level" );
- s_style = rb_intern("@style");
- s_style_set = rb_intern("style=");
- s_value = rb_intern("@value");
- s_value_set = rb_intern("value=");
- s_out = rb_intern("@out");
- s_input = rb_intern("@input");
-
- sym_model = ID2SYM(rb_intern("Model"));
- sym_generic = ID2SYM(rb_intern("Generic"));
- sym_bytecode = ID2SYM(rb_intern("bytecode"));
- sym_map = ID2SYM(rb_intern("map"));
- sym_scalar = ID2SYM(rb_intern("scalar"));
- sym_seq = ID2SYM(rb_intern("seq"));
- sym_1quote = ID2SYM(rb_intern("quote1"));
- sym_2quote = ID2SYM(rb_intern("quote2"));
- sym_fold = ID2SYM(rb_intern("fold"));
- sym_literal = ID2SYM(rb_intern("literal"));
- sym_plain = ID2SYM(rb_intern("plain"));
- sym_inline = ID2SYM(rb_intern("inline"));
-
- /*
- * Define YAML::Syck::Resolver class
- */
- cResolver = rb_define_class_under( rb_syck, "Resolver", rb_cObject );
- rb_define_attr( cResolver, "tags", 1, 1 );
- rb_define_method( cResolver, "initialize", syck_resolver_initialize, 0 );
- rb_define_method( cResolver, "add_type", syck_resolver_add_type, 2 );
- rb_define_method( cResolver, "use_types_at", syck_resolver_use_types_at, 1 );
- rb_define_method( cResolver, "detect_implicit", syck_resolver_detect_implicit, 1 );
- rb_define_method( cResolver, "transfer", syck_resolver_transfer, 2 );
- rb_define_method( cResolver, "node_import", syck_resolver_node_import, 1 );
- rb_define_method( cResolver, "tagurize", syck_resolver_tagurize, 1 );
-
- rb_global_variable( &oDefaultResolver );
- oDefaultResolver = rb_funcall( cResolver, rb_intern( "new" ), 0 );
- rb_define_singleton_method( oDefaultResolver, "node_import", syck_defaultresolver_node_import, 1 );
- rb_define_singleton_method( oDefaultResolver, "detect_implicit", syck_defaultresolver_detect_implicit, 1 );
- rb_define_const( rb_syck, "DefaultResolver", oDefaultResolver );
- rb_global_variable( &oGenericResolver );
- oGenericResolver = rb_funcall( cResolver, rb_intern( "new" ), 0 );
- rb_define_singleton_method( oGenericResolver, "node_import", syck_genericresolver_node_import, 1 );
- rb_define_const( rb_syck, "GenericResolver", oGenericResolver );
-
- /*
- * Define YAML::Syck::Parser class
- */
- cParser = rb_define_class_under( rb_syck, "Parser", rb_cObject );
- rb_define_attr( cParser, "options", 1, 1 );
- rb_define_attr( cParser, "resolver", 1, 1 );
- rb_define_attr( cParser, "input", 1, 1 );
- rb_define_alloc_func( cParser, syck_parser_s_alloc );
- rb_define_method(cParser, "initialize", syck_parser_initialize, -1 );
- rb_define_method(cParser, "bufsize=", syck_parser_bufsize_set, 1 );
- rb_define_method(cParser, "bufsize", syck_parser_bufsize_get, 0 );
- rb_define_method(cParser, "load", syck_parser_load, -1);
- rb_define_method(cParser, "load_documents", syck_parser_load_documents, -1);
- rb_define_method(cParser, "set_resolver", syck_parser_set_resolver, 1);
-
- /*
- * Define YAML::Syck::Node class
- */
- cNode = rb_define_class_under( rb_syck, "Node", rb_cObject );
- rb_define_method( cNode, "initialize_copy", syck_node_init_copy, 1 );
- rb_define_attr( cNode, "emitter", 1, 1 );
- rb_define_attr( cNode, "resolver", 1, 1 );
- rb_define_attr( cNode, "kind", 1, 0 );
- rb_define_attr( cNode, "type_id", 1, 0 );
- rb_define_attr( cNode, "value", 1, 0 );
- rb_define_method( cNode, "type_id=", syck_node_type_id_set, 1 );
- rb_define_method( cNode, "transform", syck_node_transform, 0);
-
- /*
- * Define YAML::Syck::Scalar, YAML::Syck::Seq, YAML::Syck::Map --
- * all are the publicly usable variants of YAML::Syck::Node
- */
- cScalar = rb_define_class_under( rb_syck, "Scalar", cNode );
- rb_define_alloc_func( cScalar, syck_scalar_alloc );
- rb_define_attr( cNode, "value", 1, 0 );
- rb_define_method( cScalar, "initialize", syck_scalar_initialize, 3 );
- rb_define_method( cScalar, "value=", syck_scalar_value_set, 1 );
- rb_define_method( cScalar, "style=", syck_scalar_style_set, 1 );
- cSeq = rb_define_class_under( rb_syck, "Seq", cNode );
- rb_define_alloc_func( cSeq, syck_seq_alloc );
- rb_define_method( cSeq, "initialize", syck_seq_initialize, 3 );
- rb_define_method( cSeq, "value=", syck_seq_value_set, 1 );
- rb_define_method( cSeq, "add", syck_seq_add_m, 1 );
- rb_define_method( cSeq, "style=", syck_seq_style_set, 1 );
- cMap = rb_define_class_under( rb_syck, "Map", cNode );
- rb_define_alloc_func( cMap, syck_map_alloc );
- rb_define_method( cMap, "initialize", syck_map_initialize, 3 );
- rb_define_method( cMap, "value=", syck_map_value_set, 1 );
- rb_define_method( cMap, "add", syck_map_add_m, 2 );
- rb_define_method( cMap, "style=", syck_map_style_set, 1 );
-
- /*
- * Define YAML::PrivateType class
- */
- cPrivateType = rb_define_class_under( rb_yaml, "PrivateType", rb_cObject );
- rb_define_attr( cPrivateType, "type_id", 1, 1 );
- rb_define_attr( cPrivateType, "value", 1, 1 );
- rb_define_method( cPrivateType, "initialize", syck_privatetype_initialize, 2);
-
- /*
- * Define YAML::DomainType class
- */
- cDomainType = rb_define_class_under( rb_yaml, "DomainType", rb_cObject );
- rb_define_attr( cDomainType, "domain", 1, 1 );
- rb_define_attr( cDomainType, "type_id", 1, 1 );
- rb_define_attr( cDomainType, "value", 1, 1 );
- rb_define_method( cDomainType, "initialize", syck_domaintype_initialize, 3);
-
- /*
- * Define YAML::Object class
- */
- cYObject = rb_define_class_under( rb_yaml, "Object", rb_cObject );
- rb_define_attr( cYObject, "class", 1, 1 );
- rb_define_attr( cYObject, "ivars", 1, 1 );
- rb_define_method( cYObject, "initialize", syck_yobject_initialize, 2);
- rb_define_method( cYObject, "yaml_initialize", syck_yobject_initialize, 2);
-
- /*
- * Define YAML::Syck::BadAlias class
- */
- cBadAlias = rb_define_class_under( rb_syck, "BadAlias", rb_cObject );
- rb_define_attr( cBadAlias, "name", 1, 1 );
- rb_define_method( cBadAlias, "initialize", syck_badalias_initialize, 1);
- rb_define_method( cBadAlias, "<=>", syck_badalias_cmp, 1);
- rb_include_module( cBadAlias, rb_const_get( rb_cObject, rb_intern("Comparable") ) );
-
- /*
- * Define YAML::Syck::MergeKey class
- */
- cMergeKey = rb_define_class_under( rb_syck, "MergeKey", rb_cObject );
-
- /*
- * Define YAML::Syck::DefaultKey class
- */
- cDefaultKey = rb_define_class_under( rb_syck, "DefaultKey", rb_cObject );
-
- /*
- * Define YAML::Syck::Out classes
- */
- cOut = rb_define_class_under( rb_syck, "Out", rb_cObject );
- rb_define_attr( cOut, "emitter", 1, 1 );
- rb_define_method( cOut, "initialize", syck_out_initialize, 1 );
- rb_define_method( cOut, "map", syck_out_map, -1 );
- rb_define_method( cOut, "seq", syck_out_seq, -1 );
- rb_define_method( cOut, "scalar", syck_out_scalar, -1 );
-
- /*
- * Define YAML::Syck::Emitter class
- */
- cEmitter = rb_define_class_under( rb_syck, "Emitter", rb_cObject );
- rb_define_attr( cEmitter, "level", 1, 1 );
- rb_define_alloc_func( cEmitter, syck_emitter_s_alloc );
- rb_define_method( cEmitter, "initialize", syck_emitter_reset, -1 );
- rb_define_method( cEmitter, "reset", syck_emitter_reset, -1 );
- rb_define_method( cEmitter, "emit", syck_emitter_emit, -1 );
- rb_define_method( cEmitter, "set_resolver", syck_emitter_set_resolver, 1);
- rb_define_method( cEmitter, "node_export", syck_emitter_node_export, 1);
-}
-
diff --git a/ext/syck/syck.c b/ext/syck/syck.c
deleted file mode 100644
index a83c8813c1..0000000000
--- a/ext/syck/syck.c
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * syck.c
- *
- * $Author$
- * $Date$
- *
- * Copyright (C) 2003 why the lucky stiff
- */
-#include "ruby.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include "syck.h"
-
-void syck_parser_pop_level( SyckParser * );
-
-/*
- * Custom assert
- */
-void
-syck_assert( char *file_name, unsigned line_num )
-{
- fflush( NULL );
- fprintf( stderr, "\nAssertion failed: %s, line %u\n",
- file_name, line_num );
- fflush( stderr );
- abort();
-}
-
-/*
- * Allocates and copies a string
- */
-char *
-syck_strndup( char *buf, long len )
-{
- char *new = S_ALLOC_N( char, len + 1 );
- S_MEMZERO( new, char, len + 1 );
- S_MEMCPY( new, buf, char, len );
- return new;
-}
-
-/*
- * Default FILE IO function
- */
-long
-syck_io_file_read( char *buf, SyckIoFile *file, long max_size, long skip )
-{
- long len = 0;
-
- ASSERT( file != NULL );
-
- max_size -= skip;
- len = fread( buf + skip, sizeof( char ), max_size, file->ptr );
- len += skip;
- buf[len] = '\0';
-
- return len;
-}
-
-/*
- * Default string IO function
- */
-long
-syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
-{
- char *beg;
- long len = 0;
-
- ASSERT( str != NULL );
- beg = str->ptr;
- if ( max_size >= 0 )
- {
- max_size -= skip;
- if ( max_size <= 0 ) max_size = 0;
- else str->ptr += max_size;
-
- if ( str->ptr > str->end )
- {
- str->ptr = str->end;
- }
- }
- else
- {
- /* Use exact string length */
- while ( str->ptr < str->end ) {
- if (*(str->ptr++) == '\n') break;
- }
- }
- if ( beg < str->ptr )
- {
- len = ( str->ptr - beg );
- S_MEMCPY( buf + skip, beg, char, len );
- }
- len += skip;
- buf[len] = '\0';
-
- return len;
-}
-
-void
-syck_parser_reset_levels( SyckParser *p )
-{
- while ( p->lvl_idx > 1 )
- {
- syck_parser_pop_level( p );
- }
-
- if ( p->lvl_idx < 1 )
- {
- p->lvl_idx = 1;
- p->levels[0].spaces = -1;
- p->levels[0].ncount = 0;
- p->levels[0].domain = syck_strndup( "", 0 );
- }
- p->levels[0].status = syck_lvl_header;
-}
-
-void
-syck_parser_reset_cursor( SyckParser *p )
-{
- if ( p->buffer == NULL )
- {
- p->buffer = S_ALLOC_N( char, p->bufsize );
- S_MEMZERO( p->buffer, char, p->bufsize );
- }
- p->buffer[0] = '\0';
-
- p->cursor = NULL;
- p->lineptr = NULL;
- p->linectptr = NULL;
- p->token = NULL;
- p->toktmp = NULL;
- p->marker = NULL;
- p->limit = NULL;
-
- p->root = 0;
- p->root_on_error = 0;
- p->linect = 0;
- p->eof = 0;
- p->last_token = 0;
- p->force_token = 0;
-}
-
-/*
- * Value to return on a parse error
- */
-void
-syck_parser_set_root_on_error( SyckParser *p, SYMID roer )
-{
- p->root_on_error = roer;
-}
-
-/*
- * Allocate the parser
- */
-SyckParser *
-syck_new_parser()
-{
- SyckParser *p;
- p = S_ALLOC( SyckParser );
- S_MEMZERO( p, SyckParser, 1 );
- p->lvl_capa = ALLOC_CT;
- p->levels = S_ALLOC_N( SyckLevel, p->lvl_capa );
- p->input_type = syck_yaml_utf8;
- p->io_type = syck_io_str;
- p->io.str = NULL;
- p->syms = NULL;
- p->anchors = NULL;
- p->bad_anchors = NULL;
- p->implicit_typing = 1;
- p->taguri_expansion = 0;
- p->bufsize = SYCK_BUFFERSIZE;
- p->buffer = NULL;
- p->lvl_idx = 0;
- syck_parser_reset_levels( p );
- return p;
-}
-
-int
-syck_add_sym( SyckParser *p, char *data )
-{
- SYMID id = 0;
- if ( p->syms == NULL )
- {
- p->syms = st_init_numtable();
- }
- id = p->syms->num_entries + 1;
- st_insert( p->syms, id, (st_data_t)data );
- return id;
-}
-
-int
-syck_lookup_sym( SyckParser *p, SYMID id, char **data )
-{
- if ( p->syms == NULL ) return 0;
- return st_lookup( p->syms, id, (st_data_t *)data );
-}
-
-int
-syck_st_free_nodes( char *key, SyckNode *n, char *arg )
-{
- if ( n != (void *)1 ) syck_free_node( n );
- n = NULL;
- return ST_CONTINUE;
-}
-
-void
-syck_st_free( SyckParser *p )
-{
- /*
- * Free the anchor tables
- */
- if ( p->anchors != NULL )
- {
- st_foreach( p->anchors, syck_st_free_nodes, 0 );
- st_free_table( p->anchors );
- p->anchors = NULL;
- }
-
- if ( p->bad_anchors != NULL )
- {
- st_foreach( p->bad_anchors, syck_st_free_nodes, 0 );
- st_free_table( p->bad_anchors );
- p->bad_anchors = NULL;
- }
-}
-
-void
-syck_free_parser( SyckParser *p )
-{
- /*
- * Free the adhoc symbol table
- */
- if ( p->syms != NULL )
- {
- st_free_table( p->syms );
- p->syms = NULL;
- }
-
- /*
- * Free tables, levels
- */
- syck_st_free( p );
- syck_parser_reset_levels( p );
- S_FREE( p->levels[0].domain );
- S_FREE( p->levels );
-
- if ( p->buffer != NULL )
- {
- S_FREE( p->buffer );
- }
- free_any_io( p );
- S_FREE( p );
-}
-
-void
-syck_parser_handler( SyckParser *p, SyckNodeHandler hdlr )
-{
- ASSERT( p != NULL );
- p->handler = hdlr;
-}
-
-void
-syck_parser_implicit_typing( SyckParser *p, int flag )
-{
- p->implicit_typing = ( flag == 0 ? 0 : 1 );
-}
-
-void
-syck_parser_taguri_expansion( SyckParser *p, int flag )
-{
- p->taguri_expansion = ( flag == 0 ? 0 : 1 );
-}
-
-void
-syck_parser_error_handler( SyckParser *p, SyckErrorHandler hdlr )
-{
- ASSERT( p != NULL );
- p->error_handler = hdlr;
-}
-
-void
-syck_parser_bad_anchor_handler( SyckParser *p, SyckBadAnchorHandler hdlr )
-{
- ASSERT( p != NULL );
- p->bad_anchor_handler = hdlr;
-}
-
-void
-syck_parser_set_input_type( SyckParser *p, enum syck_parser_input input_type )
-{
- ASSERT( p != NULL );
- p->input_type = input_type;
-}
-
-void
-syck_parser_file( SyckParser *p, FILE *fp, SyckIoFileRead read )
-{
- ASSERT( p != NULL );
- free_any_io( p );
- syck_parser_reset_cursor( p );
- p->io_type = syck_io_file;
- p->io.file = S_ALLOC( SyckIoFile );
- p->io.file->ptr = fp;
- if ( read != NULL )
- {
- p->io.file->read = read;
- }
- else
- {
- p->io.file->read = syck_io_file_read;
- }
-}
-
-void
-syck_parser_str( SyckParser *p, char *ptr, long len, SyckIoStrRead read )
-{
- ASSERT( p != NULL );
- free_any_io( p );
- syck_parser_reset_cursor( p );
- p->io_type = syck_io_str;
- p->io.str = S_ALLOC( SyckIoStr );
- p->io.str->beg = ptr;
- p->io.str->ptr = ptr;
- p->io.str->end = ptr + len;
- if ( read != NULL )
- {
- p->io.str->read = read;
- }
- else
- {
- p->io.str->read = syck_io_str_read;
- }
-}
-
-void
-syck_parser_str_auto( SyckParser *p, char *ptr, SyckIoStrRead read )
-{
- syck_parser_str( p, ptr, strlen( ptr ), read );
-}
-
-SyckLevel *
-syck_parser_current_level( SyckParser *p )
-{
- return &p->levels[p->lvl_idx-1];
-}
-
-void
-syck_parser_pop_level( SyckParser *p )
-{
- ASSERT( p != NULL );
-
- /* The root level should never be popped */
- if ( p->lvl_idx <= 1 ) return;
-
- p->lvl_idx -= 1;
- free( p->levels[p->lvl_idx].domain );
-}
-
-void
-syck_parser_add_level( SyckParser *p, int len, enum syck_level_status status )
-{
- ASSERT( p != NULL );
- if ( p->lvl_idx + 1 > p->lvl_capa )
- {
- p->lvl_capa += ALLOC_CT;
- S_REALLOC_N( p->levels, SyckLevel, p->lvl_capa );
- }
-
- ASSERT( len > p->levels[p->lvl_idx-1].spaces );
- p->levels[p->lvl_idx].spaces = len;
- p->levels[p->lvl_idx].ncount = 0;
- p->levels[p->lvl_idx].domain = syck_strndup( p->levels[p->lvl_idx-1].domain, strlen( p->levels[p->lvl_idx-1].domain ) );
- p->levels[p->lvl_idx].status = status;
- p->lvl_idx += 1;
-}
-
-void
-free_any_io( SyckParser *p )
-{
- ASSERT( p != NULL );
- switch ( p->io_type )
- {
- case syck_io_str:
- if ( p->io.str != NULL )
- {
- S_FREE( p->io.str );
- p->io.str = NULL;
- }
- break;
-
- case syck_io_file:
- if ( p->io.file != NULL )
- {
- S_FREE( p->io.file );
- p->io.file = NULL;
- }
- break;
- }
-}
-
-long
-syck_move_tokens( SyckParser *p )
-{
- long count, skip;
- ASSERT( p->buffer != NULL );
-
- if ( p->token == NULL )
- return 0;
-
- skip = p->limit - p->token;
- if ( ( count = p->token - p->buffer ) )
- {
- if (skip > 0)
- S_MEMMOVE( p->buffer, p->token, char, skip );
- p->token = p->buffer;
- p->marker -= count;
- p->cursor -= count;
- p->toktmp -= count;
- p->limit -= count;
- p->lineptr -= count;
- p->linectptr -= count;
- }
- return skip;
-}
-
-void
-syck_check_limit( SyckParser *p, long len )
-{
- if ( p->cursor == NULL )
- {
- p->cursor = p->buffer;
- p->lineptr = p->buffer;
- p->linectptr = p->buffer;
- p->marker = p->buffer;
- }
- p->limit = p->buffer + len;
-}
-
-long
-syck_parser_read( SyckParser *p )
-{
- long len = 0;
- long skip = 0;
- ASSERT( p != NULL );
- switch ( p->io_type )
- {
- case syck_io_str:
- skip = syck_move_tokens( p );
- len = (p->io.str->read)( p->buffer, p->io.str, SYCK_BUFFERSIZE - 1, skip );
- break;
-
- case syck_io_file:
- skip = syck_move_tokens( p );
- len = (p->io.file->read)( p->buffer, p->io.file, SYCK_BUFFERSIZE - 1, skip );
- break;
- }
- syck_check_limit( p, len );
- return len;
-}
-
-long
-syck_parser_readlen( SyckParser *p, long max_size )
-{
- long len = 0;
- long skip = 0;
- ASSERT( p != NULL );
- switch ( p->io_type )
- {
- case syck_io_str:
- skip = syck_move_tokens( p );
- len = (p->io.str->read)( p->buffer, p->io.str, max_size, skip );
- break;
-
- case syck_io_file:
- skip = syck_move_tokens( p );
- len = (p->io.file->read)( p->buffer, p->io.file, max_size, skip );
- break;
- }
- syck_check_limit( p, len );
- return len;
-}
-
-SYMID
-syck_parse( SyckParser *p )
-{
- ASSERT( p != NULL );
-
- syck_st_free( p );
- syck_parser_reset_levels( p );
- syckparse( p );
- return p->root;
-}
-
-void
-syck_default_error_handler( SyckParser *p, char *msg )
-{
- printf( "Error at [Line %d, Col %d]: %s\n",
- p->linect,
- p->cursor - p->lineptr,
- msg );
-}
-
diff --git a/ext/syck/syck.h b/ext/syck/syck.h
deleted file mode 100644
index c49f740173..0000000000
--- a/ext/syck/syck.h
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * syck.h
- *
- * $Author$
- * $Date$
- *
- * Copyright (C) 2003 why the lucky stiff
- */
-
-#ifndef SYCK_H
-#define SYCK_H
-
-#define SYCK_YAML_MAJOR 1
-#define SYCK_YAML_MINOR 0
-
-#define SYCK_VERSION "0.60"
-#define YAML_DOMAIN "yaml.org,2002"
-
-#include <stdio.h>
-#include <ctype.h>
-#include "st.h"
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/*
- * Memory Allocation
- */
-#if defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
-#include <alloca.h>
-#endif
-
-#if DEBUG
- void syck_assert( char *, unsigned );
-# define ASSERT(f) \
- if ( f ) \
- {} \
- else \
- syck_assert( __FILE__, __LINE__ )
-#else
-# define ASSERT(f)
-#endif
-
-#ifndef NULL
-# define NULL (void *)0
-#endif
-
-#define ALLOC_CT 8
-#define SYCK_BUFFERSIZE 4096
-#define S_ALLOC_N(type,n) (type*)malloc(sizeof(type)*(n))
-#define S_ALLOC(type) (type*)malloc(sizeof(type))
-#define S_REALLOC_N(var,type,n) (var)=(type*)realloc((char*)(var),sizeof(type)*(n))
-#define S_FREE(n) if (n) { free(n); n = NULL; }
-
-#define S_ALLOCA_N(type,n) (type*)alloca(sizeof(type)*(n))
-
-#define S_MEMZERO(p,type,n) memset((p), 0, sizeof(type)*(n))
-#define S_MEMCPY(p1,p2,type,n) memcpy((p1), (p2), sizeof(type)*(n))
-#define S_MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(n))
-#define S_MEMCMP(p1,p2,type,n) memcmp((p1), (p2), sizeof(type)*(n))
-
-#define BLOCK_FOLD 10
-#define BLOCK_LIT 20
-#define BLOCK_PLAIN 30
-#define NL_CHOMP 40
-#define NL_KEEP 50
-
-/*
- * Node definitions
- */
-#ifndef ST_DATA_T_DEFINED
-typedef long st_data_t;
-#endif
-
-#define SYMID unsigned long
-
-typedef struct _syck_node SyckNode;
-
-enum syck_kind_tag {
- syck_map_kind,
- syck_seq_kind,
- syck_str_kind
-};
-
-enum map_part {
- map_key,
- map_value
-};
-
-enum map_style {
- map_none,
- map_inline
-};
-
-enum seq_style {
- seq_none,
- seq_inline
-};
-
-enum scalar_style {
- scalar_none,
- scalar_1quote,
- scalar_2quote,
- scalar_fold,
- scalar_literal,
- scalar_plain
-};
-
-/*
- * Node metadata struct
- */
-struct _syck_node {
- /* Symbol table ID */
- SYMID id;
- /* Underlying kind */
- enum syck_kind_tag kind;
- /* Fully qualified tag-uri for type */
- char *type_id;
- /* Anchor name */
- char *anchor;
- union {
- /* Storage for map data */
- struct SyckMap {
- enum map_style style;
- SYMID *keys;
- SYMID *values;
- long capa;
- long idx;
- } *pairs;
- /* Storage for sequence data */
- struct SyckSeq {
- enum seq_style style;
- SYMID *items;
- long capa;
- long idx;
- } *list;
- /* Storage for string data */
- struct SyckStr {
- enum scalar_style style;
- char *ptr;
- long len;
- } *str;
- } data;
- /* Shortcut node */
- void *shortcut;
-};
-
-/*
- * Parser definitions
- */
-typedef struct _syck_parser SyckParser;
-typedef struct _syck_file SyckIoFile;
-typedef struct _syck_str SyckIoStr;
-typedef struct _syck_level SyckLevel;
-
-typedef SYMID (*SyckNodeHandler)(SyckParser *, SyckNode *);
-typedef void (*SyckErrorHandler)(SyckParser *, char *);
-typedef SyckNode * (*SyckBadAnchorHandler)(SyckParser *, char *);
-typedef long (*SyckIoFileRead)(char *, SyckIoFile *, long, long);
-typedef long (*SyckIoStrRead)(char *, SyckIoStr *, long, long);
-
-enum syck_io_type {
- syck_io_str,
- syck_io_file
-};
-
-enum syck_parser_input {
- syck_yaml_utf8,
- syck_yaml_utf16,
- syck_yaml_utf32,
- syck_bytecode_utf8
-};
-
-enum syck_level_status {
- syck_lvl_header,
- syck_lvl_doc,
- syck_lvl_open,
- syck_lvl_seq,
- syck_lvl_map,
- syck_lvl_block,
- syck_lvl_str,
- syck_lvl_iseq,
- syck_lvl_imap,
- syck_lvl_end,
- syck_lvl_pause,
- syck_lvl_anctag,
- syck_lvl_mapx,
- syck_lvl_seqx
-};
-
-/*
- * Parser structs
- */
-struct _syck_file {
- /* File pointer */
- FILE *ptr;
- /* Function which FILE -> buffer */
- SyckIoFileRead read;
-};
-
-struct _syck_str {
- /* String buffer pointers */
- char *beg, *ptr, *end;
- /* Function which string -> buffer */
- SyckIoStrRead read;
-};
-
-struct _syck_level {
- /* Indent */
- int spaces;
- /* Counts nodes emitted at this level, useful for parsing
- * keys and pairs in bytecode */
- int ncount;
- /* Does node have anchors or tags? */
- int anctag;
- /* Domain prefixing at the given level */
- char *domain;
- /* Keeps a node status */
- enum syck_level_status status;
-};
-
-struct _syck_parser {
- /* Root node */
- SYMID root, root_on_error;
- /* Implicit typing flag */
- int implicit_typing, taguri_expansion;
- /* Scripting language function to handle nodes */
- SyckNodeHandler handler;
- /* Error handler */
- SyckErrorHandler error_handler;
- /* InvalidAnchor handler */
- SyckBadAnchorHandler bad_anchor_handler;
- /* Parser input type */
- enum syck_parser_input input_type;
- /* IO type */
- enum syck_io_type io_type;
- /* Custom buffer size */
- size_t bufsize;
- /* Buffer pointers */
- char *buffer, *linectptr, *lineptr, *toktmp, *token, *cursor, *marker, *limit;
- /* Line counter */
- int linect;
- /* Last token from yylex() */
- int last_token;
- /* Force a token upon next call to yylex() */
- int force_token;
- /* EOF flag */
- int eof;
- union {
- SyckIoFile *file;
- SyckIoStr *str;
- } io;
- /* Symbol table for anchors */
- st_table *anchors, *bad_anchors;
- /* Optional symbol table for SYMIDs */
- st_table *syms;
- /* Levels of indentation */
- SyckLevel *levels;
- int lvl_idx;
- int lvl_capa;
- /* Pointer for extension's use */
- void *bonus;
-};
-
-/*
- * Emitter definitions
- */
-typedef struct _syck_emitter SyckEmitter;
-typedef struct _syck_emitter_node SyckEmitterNode;
-
-typedef void (*SyckOutputHandler)(SyckEmitter *, char *, long);
-typedef void (*SyckEmitterHandler)(SyckEmitter *, st_data_t);
-
-enum doc_stage {
- doc_open,
- doc_processing
-};
-
-/*
- * Emitter struct
- */
-struct _syck_emitter {
- /* Headerless doc flag */
- int headless;
- /* Force header? */
- int use_header;
- /* Force version? */
- int use_version;
- /* Sort hash keys */
- int sort_keys;
- /* Anchor format */
- char *anchor_format;
- /* Explicit typing on all collections? */
- int explicit_typing;
- /* Best width on folded scalars */
- int best_width;
- /* Use literal[1] or folded[2] blocks on all text? */
- enum scalar_style style;
- /* Stage of written document */
- enum doc_stage stage;
- /* Level counter */
- int level;
- /* Default indentation */
- int indent;
- /* Object ignore ID */
- SYMID ignore_id;
- /* Symbol table for anchors */
- st_table *markers, *anchors, *anchored;
- /* Custom buffer size */
- size_t bufsize;
- /* Buffer */
- char *buffer, *marker;
- /* Absolute position of the buffer */
- long bufpos;
- /* Handler for emitter nodes */
- SyckEmitterHandler emitter_handler;
- /* Handler for output */
- SyckOutputHandler output_handler;
- /* Levels of indentation */
- SyckLevel *levels;
- int lvl_idx;
- int lvl_capa;
- /* Pointer for extension's use */
- void *bonus;
-};
-
-/*
- * Emitter node metadata struct
- */
-struct _syck_emitter_node {
- /* Node buffer position */
- long pos;
- /* Current indent */
- long indent;
- /* Collection? */
- int is_shortcut;
-};
-
-/*
- * Handler prototypes
- */
-SYMID syck_hdlr_add_node( SyckParser *, SyckNode * );
-SyckNode *syck_hdlr_add_anchor( SyckParser *, char *, SyckNode * );
-void syck_hdlr_remove_anchor( SyckParser *, char * );
-SyckNode *syck_hdlr_get_anchor( SyckParser *, char * );
-void syck_add_transfer( char *, SyckNode *, int );
-char *syck_xprivate( char *, int );
-char *syck_taguri( char *, char *, int );
-int syck_tagcmp( char *, char * );
-int syck_add_sym( SyckParser *, char * );
-int syck_lookup_sym( SyckParser *, SYMID, char ** );
-int syck_try_implicit( SyckNode * );
-char *syck_type_id_to_uri( char * );
-void try_tag_implicit( SyckNode *, int );
-char *syck_match_implicit( char *, size_t );
-
-/*
- * API prototypes
- */
-char *syck_strndup( char *, long );
-long syck_io_file_read( char *, SyckIoFile *, long, long );
-long syck_io_str_read( char *, SyckIoStr *, long, long );
-char *syck_base64enc( char *, long );
-char *syck_base64dec( char *, long );
-SyckEmitter *syck_new_emitter();
-SYMID syck_emitter_mark_node( SyckEmitter *, st_data_t );
-void syck_emitter_ignore_id( SyckEmitter *, SYMID );
-void syck_output_handler( SyckEmitter *, SyckOutputHandler );
-void syck_emitter_handler( SyckEmitter *, SyckEmitterHandler );
-void syck_free_emitter( SyckEmitter * );
-void syck_emitter_clear( SyckEmitter * );
-void syck_emitter_write( SyckEmitter *, char *, long );
-void syck_emitter_escape( SyckEmitter *, char *, long );
-void syck_emitter_flush( SyckEmitter *, long );
-void syck_emit( SyckEmitter *, st_data_t );
-void syck_emit_scalar( SyckEmitter *, char *, enum scalar_style, int, int, char, char *, long );
-void syck_emit_1quoted( SyckEmitter *, int, char *, long );
-void syck_emit_2quoted( SyckEmitter *, int, char *, long );
-void syck_emit_folded( SyckEmitter *, int, char, char *, long );
-void syck_emit_literal( SyckEmitter *, char, char *, long );
-void syck_emit_seq( SyckEmitter *, char *, enum seq_style );
-void syck_emit_item( SyckEmitter *, st_data_t );
-void syck_emit_map( SyckEmitter *, char *, enum map_style );
-void syck_emit_end( SyckEmitter * );
-void syck_emit_tag( SyckEmitter *, char *, char * );
-void syck_emit_indent( SyckEmitter * );
-SyckLevel *syck_emitter_current_level( SyckEmitter * );
-SyckLevel *syck_emitter_parent_level( SyckEmitter * );
-void syck_emitter_pop_level( SyckEmitter * );
-void syck_emitter_add_level( SyckEmitter *, int, enum syck_level_status );
-void syck_emitter_reset_levels( SyckEmitter * );
-SyckParser *syck_new_parser();
-void syck_free_parser( SyckParser * );
-void syck_parser_set_root_on_error( SyckParser *, SYMID );
-void syck_parser_implicit_typing( SyckParser *, int );
-void syck_parser_taguri_expansion( SyckParser *, int );
-int syck_scan_scalar( int, char *, long );
-void syck_parser_handler( SyckParser *, SyckNodeHandler );
-void syck_parser_error_handler( SyckParser *, SyckErrorHandler );
-void syck_parser_bad_anchor_handler( SyckParser *, SyckBadAnchorHandler );
-void syck_parser_file( SyckParser *, FILE *, SyckIoFileRead );
-void syck_parser_str( SyckParser *, char *, long, SyckIoStrRead );
-void syck_parser_str_auto( SyckParser *, char *, SyckIoStrRead );
-SyckLevel *syck_parser_current_level( SyckParser * );
-void syck_parser_add_level( SyckParser *, int, enum syck_level_status );
-void syck_parser_pop_level( SyckParser * );
-void free_any_io( SyckParser * );
-long syck_parser_read( SyckParser * );
-long syck_parser_readlen( SyckParser *, long );
-SYMID syck_parse( SyckParser * );
-void syck_default_error_handler( SyckParser *, char * );
-SYMID syck_yaml2byte_handler( SyckParser *, SyckNode * );
-char *syck_yaml2byte( char * );
-
-/*
- * Allocation prototypes
- */
-SyckNode *syck_alloc_map();
-SyckNode *syck_alloc_seq();
-SyckNode *syck_alloc_str();
-void syck_free_node( SyckNode * );
-void syck_free_members( SyckNode * );
-SyckNode *syck_new_str( char *, enum scalar_style );
-SyckNode *syck_new_str2( char *, long, enum scalar_style );
-void syck_replace_str( SyckNode *, char *, enum scalar_style );
-void syck_replace_str2( SyckNode *, char *, long, enum scalar_style );
-void syck_str_blow_away_commas( SyckNode * );
-char *syck_str_read( SyckNode * );
-SyckNode *syck_new_map( SYMID, SYMID );
-void syck_map_empty( SyckNode * );
-void syck_map_add( SyckNode *, SYMID, SYMID );
-SYMID syck_map_read( SyckNode *, enum map_part, long );
-void syck_map_assign( SyckNode *, enum map_part, long, SYMID );
-long syck_map_count( SyckNode * );
-void syck_map_update( SyckNode *, SyckNode * );
-SyckNode *syck_new_seq( SYMID );
-void syck_seq_empty( SyckNode * );
-void syck_seq_add( SyckNode *, SYMID );
-void syck_seq_assign( SyckNode *, long, SYMID );
-SYMID syck_seq_read( SyckNode *, long );
-long syck_seq_count( SyckNode * );
-
-/*
- * Lexer prototypes
- */
-void syckerror( char * );
-int syckparse( void * );
-union YYSTYPE;
-int sycklex( union YYSTYPE *, SyckParser * );
-
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
-
-#endif /* ifndef SYCK_H */
diff --git a/ext/syck/token.c b/ext/syck/token.c
deleted file mode 100644
index 3c6cd1a9cf..0000000000
--- a/ext/syck/token.c
+++ /dev/null
@@ -1,2725 +0,0 @@
-/* Generated by re2c 0.9.10 on Tue Sep 20 17:46:17 2005 */
-#line 1 "token.re"
-/*
- * token.re
- *
- * $Author$
- * $Date$
- *
- * Copyright (C) 2003 why the lucky stiff
- */
-#include "ruby.h"
-#include "syck.h"
-#include "gram.h"
-
-/*
- * Allocate quoted strings in chunks
- */
-#define QUOTELEN 1024
-
-/*
- * They do my bidding...
- */
-#define YYCTYPE char
-#define YYCURSOR parser->cursor
-#define YYMARKER parser->marker
-#define YYLIMIT parser->limit
-#define YYTOKEN parser->token
-#define YYTOKTMP parser->toktmp
-#define YYLINEPTR parser->lineptr
-#define YYLINECTPTR parser->linectptr
-#define YYLINE parser->linect
-#define YYFILL(n) syck_parser_read(parser)
-
-/*
- * Repositions the cursor at `n' offset from the token start.
- * Only works in `Header' and `Document' sections.
- */
-#define YYPOS(n) YYCURSOR = YYTOKEN + n
-
-/*
- * Track line numbers
- */
-#define NEWLINE(ptr) YYLINEPTR = ptr + newline_len(ptr); if ( YYLINEPTR > YYLINECTPTR ) { YYLINE++; YYLINECTPTR = YYLINEPTR; }
-
-/*
- * I like seeing the level operations as macros...
- */
-#define ADD_LEVEL(len, status) syck_parser_add_level( parser, len, status )
-#define POP_LEVEL() syck_parser_pop_level( parser )
-#define CURRENT_LEVEL() syck_parser_current_level( parser )
-
-/*
- * Force a token next time around sycklex()
- */
-#define FORCE_NEXT_TOKEN(tok) parser->force_token = tok;
-
-/*
- * Nice little macro to ensure we're YAML_IOPENed to the current level.
- * * Only use this macro in the "Document" section *
- */
-#define ENSURE_YAML_IOPEN(last_lvl, to_len, reset) \
- if ( last_lvl->spaces < to_len ) \
- { \
- if ( last_lvl->status == syck_lvl_iseq || last_lvl->status == syck_lvl_imap ) \
- { \
- goto Document; \
- } \
- else \
- { \
- ADD_LEVEL( to_len, syck_lvl_doc ); \
- if ( reset == 1 ) YYPOS(0); \
- return YAML_IOPEN; \
- } \
- }
-
-/*
- * Nice little macro to ensure closure of levels.
- * * Only use this macro in the "Document" section *
- */
-#define ENSURE_YAML_IEND(last_lvl, to_len) \
- if ( last_lvl->spaces > to_len ) \
- { \
- syck_parser_pop_level( parser ); \
- YYPOS(0); \
- return YAML_IEND; \
- }
-
-/*
- * Concatenates quoted string items and manages allocation
- * to the quoted string
- */
-#define QUOTECAT(s, c, i, l) \
- { \
- if ( i + 1 >= c ) \
- { \
- c += QUOTELEN; \
- S_REALLOC_N( s, char, c ); \
- } \
- s[i++] = l; \
- s[i] = '\0'; \
- }
-
-#define QUOTECATS(s, c, i, cs, cl) \
- { \
- while ( i + cl >= c ) \
- { \
- c += QUOTELEN; \
- S_REALLOC_N( s, char, c ); \
- } \
- S_MEMCPY( s + i, cs, char, cl ); \
- i += cl; \
- s[i] = '\0'; \
- }
-
-/*
- * Tags a plain scalar with a transfer method
- * * Use only in "Plain" section *
- */
-#define RETURN_IMPLICIT() \
- { \
- SyckNode *n = syck_alloc_str(); \
- YYCURSOR = YYTOKEN; \
- n->data.str->ptr = qstr; \
- n->data.str->len = qidx; \
- n->data.str->style = scalar_plain; \
- sycklval->nodeData = n; \
- if ( parser->implicit_typing == 1 ) \
- { \
- try_tag_implicit( sycklval->nodeData, parser->taguri_expansion ); \
- } \
- return YAML_PLAIN; \
- }
-
-/* concat the inline characters to the plain scalar */
-#define PLAIN_NOT_INL() \
- if ( *(YYCURSOR - 1) == ' ' || is_newline( YYCURSOR - 1 ) ) \
- { \
- YYCURSOR--; \
- } \
- QUOTECATS(qstr, qcapa, qidx, YYTOKEN, YYCURSOR - YYTOKEN); \
- goto Plain2;
-
-/* trim spaces off the end in case of indent */
-#define PLAIN_IS_INL() \
- char *walker = qstr + qidx - 1; \
- while ( walker > qstr && ( *walker == '\n' || *walker == ' ' || *walker == '\t' ) ) \
- { \
- qidx--; \
- walker[0] = '\0'; \
- walker--; \
- }
-
-/*
- * Keep or chomp block?
- * * Use only in "ScalarBlock" section *
- */
-#define RETURN_YAML_BLOCK() \
- { \
- SyckNode *n = syck_alloc_str(); \
- if ( ((SyckParser *)parser)->taguri_expansion == 1 ) \
- { \
- n->type_id = syck_taguri( YAML_DOMAIN, "str", 3 ); \
- } \
- else \
- { \
- n->type_id = syck_strndup( "str", 3 ); \
- } \
- n->data.str->ptr = qstr; \
- n->data.str->len = qidx; \
- if ( blockType == BLOCK_LIT ) { \
- n->data.str->style = scalar_literal; \
- } else { \
- n->data.str->style = scalar_fold; \
- } \
- if ( qidx > 0 ) \
- { \
- if ( nlDoWhat != NL_KEEP ) \
- { \
- char *fc = n->data.str->ptr + n->data.str->len - 1; \
- while ( is_newline( fc ) ) fc--; \
- if ( nlDoWhat != NL_CHOMP && fc < n->data.str->ptr + n->data.str->len - 1 ) \
- fc += 1; \
- n->data.str->len = fc - n->data.str->ptr + 1; \
- } \
- } \
- sycklval->nodeData = n; \
- return YAML_BLOCK; \
- }
-
-/*
- * Handles newlines, calculates indent
- */
-#define GOBBLE_UP_YAML_INDENT( ict, start ) \
- char *indent = start; \
- NEWLINE(indent); \
- while ( indent < YYCURSOR ) \
- { \
- if ( is_newline( ++indent ) ) \
- { \
- NEWLINE(indent); \
- } \
- } \
- ict = 0; \
- if ( *YYCURSOR == '\0' ) \
- { \
- ict = -1; \
- start = YYCURSOR - 1; \
- } \
- else if ( *YYLINEPTR == ' ' ) \
- { \
- ict = YYCURSOR - YYLINEPTR; \
- }
-
-/*
- * If an indent exists at the current level, back up.
- */
-#define GET_TRUE_YAML_INDENT(indt_len) \
- { \
- SyckLevel *lvl_deep = CURRENT_LEVEL(); \
- indt_len = lvl_deep->spaces; \
- if ( lvl_deep->status == syck_lvl_seq || ( indt_len == YYCURSOR - YYLINEPTR && lvl_deep->status != syck_lvl_map ) ) \
- { \
- SyckLevel *lvl_over; \
- parser->lvl_idx--; \
- lvl_over = CURRENT_LEVEL(); \
- indt_len = lvl_over->spaces; \
- parser->lvl_idx++; \
- } \
- }
-
-/*
- * Argjh! I hate globals! Here for syckerror() only!
- */
-SyckParser *syck_parser_ptr = NULL;
-
-/*
- * Accessory funcs later in this file.
- */
-void eat_comments( SyckParser * );
-char escape_seq( char );
-int is_newline( char *ptr );
-int newline_len( char *ptr );
-int sycklex_yaml_utf8( YYSTYPE *, SyckParser * );
-int sycklex_bytecode_utf8( YYSTYPE *, SyckParser * );
-int syckwrap();
-
-/*
- * My own re-entrant sycklex() using re2c.
- * You really get used to the limited regexp.
- * It's really nice to not rely on backtracking and such.
- */
-int
-sycklex( YYSTYPE *sycklval, SyckParser *parser )
-{
- switch ( parser->input_type )
- {
- case syck_yaml_utf8:
- return sycklex_yaml_utf8( sycklval, parser );
-
- case syck_yaml_utf16:
- syckerror( "UTF-16 is not currently supported in Syck.\nPlease contribute code to help this happen!" );
- break;
-
- case syck_yaml_utf32:
- syckerror( "UTF-32 is not currently supported in Syck.\nPlease contribute code to help this happen!" );
- break;
-
- case syck_bytecode_utf8:
- return sycklex_bytecode_utf8( sycklval, parser );
- }
- return YAML_DOCSEP;
-}
-
-/*
- * Parser for standard YAML [UTF-8]
- */
-int
-sycklex_yaml_utf8( YYSTYPE *sycklval, SyckParser *parser )
-{
- int doc_level = 0;
- syck_parser_ptr = parser;
- if ( YYCURSOR == NULL )
- {
- syck_parser_read( parser );
- }
-
- if ( parser->force_token != 0 )
- {
- int t = parser->force_token;
- parser->force_token = 0;
- return t;
- }
-
-#line 315 "token.re"
-
-
- if ( YYLINEPTR != YYCURSOR )
- {
- goto Document;
- }
-
-Header:
-
- YYTOKEN = YYCURSOR;
-
-
-#line 307 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy0;
- ++YYCURSOR;
-yy0:
- if((YYLIMIT - YYCURSOR) < 5) YYFILL(5);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy7;
- case 0x09: case ' ': goto yy12;
- case 0x0A: goto yy9;
- case 0x0D: goto yy11;
- case '#': goto yy5;
- case '-': goto yy2;
- case '.': goto yy4;
- default: goto yy14;
- }
-yy2: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case '-': goto yy28;
- default: goto yy3;
- }
-yy3:
-#line 374 "token.re"
-{ YYPOS(0);
- goto Document;
- }
-#line 337 "<stdout>"
-yy4: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case '.': goto yy21;
- default: goto yy3;
- }
-yy5: ++YYCURSOR;
- goto yy6;
-yy6:
-#line 356 "token.re"
-{ eat_comments( parser );
- goto Header;
- }
-#line 351 "<stdout>"
-yy7: ++YYCURSOR;
- goto yy8;
-yy8:
-#line 360 "token.re"
-{ SyckLevel *lvl = CURRENT_LEVEL();
- ENSURE_YAML_IEND(lvl, -1);
- YYPOS(0);
- return 0;
- }
-#line 361 "<stdout>"
-yy9: yyaccept = 1;
- yych = *(YYMARKER = ++YYCURSOR);
- goto yy18;
-yy10:
-#line 366 "token.re"
-{ GOBBLE_UP_YAML_INDENT( doc_level, YYTOKEN );
- goto Header;
- }
-#line 370 "<stdout>"
-yy11: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy17;
- default: goto yy3;
- }
-yy12: ++YYCURSOR;
- yych = *YYCURSOR;
- goto yy16;
-yy13:
-#line 370 "token.re"
-{ doc_level = YYCURSOR - YYLINEPTR;
- goto Header;
- }
-#line 384 "<stdout>"
-yy14: yych = *++YYCURSOR;
- goto yy3;
-yy15: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy16;
-yy16: switch(yych){
- case 0x09: case ' ': goto yy15;
- default: goto yy13;
- }
-yy17: yyaccept = 1;
- YYMARKER = ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy18;
-yy18: switch(yych){
- case 0x0A: case ' ': goto yy17;
- case 0x0D: goto yy19;
- default: goto yy10;
- }
-yy19: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- switch(yych){
- case 0x0A: goto yy17;
- default: goto yy20;
- }
-yy20: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 1: goto yy10;
- case 0: goto yy3;
- }
-yy21: yych = *++YYCURSOR;
- switch(yych){
- case '.': goto yy22;
- default: goto yy20;
- }
-yy22: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy23;
- case 0x0D: goto yy27;
- case ' ': goto yy25;
- default: goto yy20;
- }
-yy23: ++YYCURSOR;
- goto yy24;
-yy24:
-#line 342 "token.re"
-{ SyckLevel *lvl = CURRENT_LEVEL();
- if ( lvl->status == syck_lvl_header )
- {
- goto Header;
- }
- else
- {
- ENSURE_YAML_IEND(lvl, -1);
- YYPOS(0);
- return 0;
- }
- return 0;
- }
-#line 446 "<stdout>"
-yy25: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy26;
-yy26: switch(yych){
- case ' ': goto yy25;
- default: goto yy24;
- }
-yy27: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy23;
- default: goto yy20;
- }
-yy28: yych = *++YYCURSOR;
- switch(yych){
- case '-': goto yy29;
- default: goto yy20;
- }
-yy29: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy30;
- case 0x0D: goto yy34;
- case ' ': goto yy32;
- default: goto yy20;
- }
-yy30: ++YYCURSOR;
- goto yy31;
-yy31:
-#line 328 "token.re"
-{ SyckLevel *lvl = CURRENT_LEVEL();
- if ( lvl->status == syck_lvl_header )
- {
- YYPOS(3);
- goto Directive;
- }
- else
- {
- ENSURE_YAML_IEND(lvl, -1);
- YYPOS(0);
- return 0;
- }
- }
-#line 489 "<stdout>"
-yy32: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy33;
-yy33: switch(yych){
- case ' ': goto yy32;
- default: goto yy31;
- }
-yy34: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy30;
- default: goto yy20;
- }
-}
-#line 378 "token.re"
-
-
-Document:
- {
- SyckLevel *lvl = CURRENT_LEVEL();
- if ( lvl->status == syck_lvl_header )
- {
- lvl->status = syck_lvl_doc;
- }
-
- YYTOKEN = YYCURSOR;
-
-
-#line 518 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy35;
- ++YYCURSOR;
-yy35:
- if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy62;
- case 0x09: case ' ': goto yy60;
- case 0x0A: goto yy37;
- case 0x0D: goto yy39;
- case '!': goto yy51;
- case '"': goto yy55;
- case '#': goto yy58;
- case '&': goto yy49;
- case '\'': goto yy53;
- case '*': goto yy50;
- case ',': case ':': goto yy47;
- case '-': case '?': goto yy48;
- case '>': case '|': goto yy57;
- case '[': goto yy41;
- case ']': case '}': goto yy45;
- case '{': goto yy43;
- default: goto yy64;
- }
-yy37: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- goto yy92;
-yy38:
-#line 392 "token.re"
-{ /* Isolate spaces */
- int indt_len;
- GOBBLE_UP_YAML_INDENT( indt_len, YYTOKEN );
- lvl = CURRENT_LEVEL();
- doc_level = 0;
-
- /* XXX: Comment lookahead */
- if ( *YYCURSOR == '#' )
- {
- goto Document;
- }
-
- /* Ignore indentation inside inlines */
- if ( lvl->status == syck_lvl_iseq || lvl->status == syck_lvl_imap )
- {
- goto Document;
- }
-
- /* Check for open indent */
- ENSURE_YAML_IEND(lvl, indt_len);
- ENSURE_YAML_IOPEN(lvl, indt_len, 0);
- if ( indt_len == -1 )
- {
- return 0;
- }
- return YAML_INDENT;
- }
-#line 578 "<stdout>"
-yy39: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy91;
- default: goto yy40;
- }
-yy40:
-#line 497 "token.re"
-{ ENSURE_YAML_IOPEN(lvl, doc_level, 1);
- goto Plain;
- }
-#line 589 "<stdout>"
-yy41: ++YYCURSOR;
- goto yy42;
-yy42:
-#line 420 "token.re"
-{ ENSURE_YAML_IOPEN(lvl, doc_level, 1);
- lvl = CURRENT_LEVEL();
- ADD_LEVEL(lvl->spaces + 1, syck_lvl_iseq);
- return YYTOKEN[0];
- }
-#line 599 "<stdout>"
-yy43: ++YYCURSOR;
- goto yy44;
-yy44:
-#line 426 "token.re"
-{ ENSURE_YAML_IOPEN(lvl, doc_level, 1);
- lvl = CURRENT_LEVEL();
- ADD_LEVEL(lvl->spaces + 1, syck_lvl_imap);
- return YYTOKEN[0];
- }
-#line 609 "<stdout>"
-yy45: ++YYCURSOR;
- goto yy46;
-yy46:
-#line 432 "token.re"
-{ POP_LEVEL();
- return YYTOKEN[0];
- }
-#line 617 "<stdout>"
-yy47: yyaccept = 1;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 0x0A: goto yy86;
- case 0x0D: goto yy90;
- case ' ': goto yy88;
- default: goto yy40;
- }
-yy48: yyaccept = 1;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 0x0A: goto yy81;
- case 0x0D: goto yy85;
- case ' ': goto yy83;
- default: goto yy40;
- }
-yy49: yych = *++YYCURSOR;
- switch(yych){
- case '-': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy78;
- default: goto yy40;
- }
-yy50: yych = *++YYCURSOR;
- switch(yych){
- case '-': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy75;
- default: goto yy40;
- }
-yy51: ++YYCURSOR;
- goto yy52;
-yy52:
-#line 471 "token.re"
-{ goto TransferMethod; }
-#line 767 "<stdout>"
-yy53: ++YYCURSOR;
- goto yy54;
-yy54:
-#line 473 "token.re"
-{ ENSURE_YAML_IOPEN(lvl, doc_level, 1);
- goto SingleQuote; }
-#line 774 "<stdout>"
-yy55: ++YYCURSOR;
- goto yy56;
-yy56:
-#line 476 "token.re"
-{ ENSURE_YAML_IOPEN(lvl, doc_level, 1);
- goto DoubleQuote; }
-#line 781 "<stdout>"
-yy57: yyaccept = 1;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 0x0A: goto yy70;
- case 0x0D: goto yy74;
- case ' ': goto yy72;
- case '+': case '-': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy67;
- default: goto yy40;
- }
-yy58: ++YYCURSOR;
- goto yy59;
-yy59:
-#line 486 "token.re"
-{ eat_comments( parser );
- goto Document;
- }
-#line 807 "<stdout>"
-yy60: ++YYCURSOR;
- yych = *YYCURSOR;
- goto yy66;
-yy61:
-#line 490 "token.re"
-{ goto Document; }
-#line 814 "<stdout>"
-yy62: ++YYCURSOR;
- goto yy63;
-yy63:
-#line 492 "token.re"
-{ ENSURE_YAML_IEND(lvl, -1);
- YYPOS(0);
- return 0;
- }
-#line 823 "<stdout>"
-yy64: yych = *++YYCURSOR;
- goto yy40;
-yy65: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy66;
-yy66: switch(yych){
- case 0x09: case ' ': goto yy65;
- default: goto yy61;
- }
-yy67: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- goto yy68;
-yy68: switch(yych){
- case 0x0A: goto yy70;
- case 0x0D: goto yy74;
- case ' ': goto yy72;
- case '+': case '-': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': goto yy67;
- default: goto yy69;
- }
-yy69: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy38;
- case 1: goto yy40;
- }
-yy70: ++YYCURSOR;
- goto yy71;
-yy71:
-#line 479 "token.re"
-{ if ( is_newline( YYCURSOR - 1 ) )
- {
- YYCURSOR--;
- }
- goto ScalarBlock;
- }
-#line 869 "<stdout>"
-yy72: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy73;
-yy73: switch(yych){
- case ' ': goto yy72;
- default: goto yy71;
- }
-yy74: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy70;
- default: goto yy69;
- }
-yy75: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy76;
-yy76: switch(yych){
- case '-': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy75;
- default: goto yy77;
- }
-yy77:
-#line 466 "token.re"
-{ ENSURE_YAML_IOPEN(lvl, doc_level, 1);
- sycklval->name = syck_strndup( YYTOKEN + 1, YYCURSOR - YYTOKEN - 1 );
- return YAML_ALIAS;
- }
-#line 956 "<stdout>"
-yy78: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy79;
-yy79: switch(yych){
- case '-': case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z': case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy78;
- default: goto yy80;
- }
-yy80:
-#line 455 "token.re"
-{ sycklval->name = syck_strndup( YYTOKEN + 1, YYCURSOR - YYTOKEN - 1 );
-
- /*
- * Remove previous anchors of the same name. Since the parser will likely
- * construct deeper nodes first, we want those nodes to be placed in the
- * queue for matching at a higher level of indentation.
- */
- syck_hdlr_remove_anchor(parser, sycklval->name);
- return YAML_ANCHOR;
- }
-#line 1036 "<stdout>"
-yy81: ++YYCURSOR;
- goto yy82;
-yy82:
-#line 441 "token.re"
-{ ENSURE_YAML_IOPEN(lvl, YYTOKEN - YYLINEPTR, 1);
- FORCE_NEXT_TOKEN(YAML_IOPEN);
- if ( *YYCURSOR == '#' || is_newline( YYCURSOR ) || is_newline( YYCURSOR - 1 ) )
- {
- YYCURSOR--;
- ADD_LEVEL((YYTOKEN + 1) - YYLINEPTR, syck_lvl_seq);
- }
- else /* spaces followed by content uses the space as indentation */
- {
- ADD_LEVEL(YYCURSOR - YYLINEPTR, syck_lvl_seq);
- }
- return YYTOKEN[0];
- }
-#line 1054 "<stdout>"
-yy83: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy84;
-yy84: switch(yych){
- case ' ': goto yy83;
- default: goto yy82;
- }
-yy85: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy81;
- default: goto yy69;
- }
-yy86: ++YYCURSOR;
- goto yy87;
-yy87:
-#line 436 "token.re"
-{ if ( *YYTOKEN == ':' && lvl->status != syck_lvl_imap ) lvl->status = syck_lvl_map;
- YYPOS(1);
- return YYTOKEN[0];
- }
-#line 1076 "<stdout>"
-yy88: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy89;
-yy89: switch(yych){
- case ' ': goto yy88;
- default: goto yy87;
- }
-yy90: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy86;
- default: goto yy69;
- }
-yy91: yyaccept = 0;
- YYMARKER = ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy92;
-yy92: switch(yych){
- case 0x0A: case ' ': goto yy91;
- case 0x0D: goto yy93;
- default: goto yy38;
- }
-yy93: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- switch(yych){
- case 0x0A: goto yy91;
- default: goto yy69;
- }
-}
-#line 501 "token.re"
-
- }
-
-Directive:
- {
- YYTOKTMP = YYCURSOR;
-
-
-#line 1117 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy94;
- ++YYCURSOR;
-yy94:
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy96;
- case 0x09: case ' ': goto yy99;
- case '%': goto yy97;
- default: goto yy101;
- }
-yy96: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy98;
- }
-yy97: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case '.':
- case '/':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case ':':
- case ';':
- case '<':
- case '=':
- case '>':
- case '?':
- case '@':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '[':
- case '\\':
- case ']':
- case '^':
- case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy104;
- default: goto yy98;
- }
-yy98:
-#line 514 "token.re"
-{ YYCURSOR = YYTOKTMP;
- return YAML_DOCSEP;
- }
-#line 1221 "<stdout>"
-yy99: ++YYCURSOR;
- yych = *YYCURSOR;
- goto yy103;
-yy100:
-#line 512 "token.re"
-{ goto Directive; }
-#line 1228 "<stdout>"
-yy101: yych = *++YYCURSOR;
- goto yy98;
-yy102: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy103;
-yy103: switch(yych){
- case 0x09: case ' ': goto yy102;
- default: goto yy100;
- }
-yy104: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- goto yy105;
-yy105: switch(yych){
- case '.':
- case '/':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case ';':
- case '<':
- case '=':
- case '>':
- case '?':
- case '@':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '[':
- case '\\':
- case ']':
- case '^':
- case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy104;
- case ':': goto yy106;
- default: goto yy96;
- }
-yy106: yych = *++YYCURSOR;
- switch(yych){
- case '.':
- case '/':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case ':':
- case ';':
- case '<':
- case '=':
- case '>':
- case '?':
- case '@':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '[':
- case '\\':
- case ']':
- case '^':
- case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy107;
- default: goto yy96;
- }
-yy107: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy108;
-yy108: switch(yych){
- case '.':
- case '/':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case ':':
- case ';':
- case '<':
- case '=':
- case '>':
- case '?':
- case '@':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '[':
- case '\\':
- case ']':
- case '^':
- case '_': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z': goto yy107;
- default: goto yy109;
- }
-yy109:
-#line 510 "token.re"
-{ goto Directive; }
-#line 1484 "<stdout>"
-}
-#line 517 "token.re"
-
-
- }
-
-Plain:
- {
- int qidx = 0;
- int qcapa = 100;
- char *qstr = S_ALLOC_N( char, qcapa );
- SyckLevel *plvl;
- int parentIndent;
-
- YYCURSOR = YYTOKEN;
- plvl = CURRENT_LEVEL();
- GET_TRUE_YAML_INDENT(parentIndent);
-
-Plain2:
- YYTOKEN = YYCURSOR;
-
-Plain3:
-
-
-#line 1509 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy110;
- ++YYCURSOR;
-yy110:
- if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy124;
- case 0x09: goto yy126;
- case 0x0A: goto yy112;
- case 0x0D: goto yy114;
- case ' ': goto yy122;
- case ',': goto yy117;
- case ':': goto yy116;
- case ']': goto yy120;
- case '}': goto yy118;
- default: goto yy127;
- }
-yy112: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- goto yy142;
-yy113:
-#line 540 "token.re"
-{ int indt_len, nl_count = 0;
- SyckLevel *lvl;
- char *tok = YYTOKEN;
- GOBBLE_UP_YAML_INDENT( indt_len, tok );
- lvl = CURRENT_LEVEL();
-
- if ( indt_len <= parentIndent )
- {
- RETURN_IMPLICIT();
- }
-
- while ( YYTOKEN < YYCURSOR )
- {
- int nl_len = newline_len( YYTOKEN++ );
- if ( nl_len )
- {
- nl_count++;
- YYTOKEN += nl_len - 1;
- }
- }
- if ( nl_count <= 1 )
- {
- QUOTECAT(qstr, qcapa, qidx, ' ');
- }
- else
- {
- int i;
- for ( i = 0; i < nl_count - 1; i++ )
- {
- QUOTECAT(qstr, qcapa, qidx, '\n');
- }
- }
-
- goto Plain2;
- }
-#line 1570 "<stdout>"
-yy114: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy141;
- default: goto yy115;
- }
-yy115:
-#line 627 "token.re"
-{ QUOTECATS(qstr, qcapa, qidx, YYTOKEN, YYCURSOR - YYTOKEN);
- goto Plain2;
- }
-#line 1581 "<stdout>"
-yy116: yyaccept = 1;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 0x0A: goto yy136;
- case 0x0D: goto yy140;
- case ' ': goto yy138;
- default: goto yy115;
- }
-yy117: yyaccept = 1;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 0x0A: goto yy130;
- case 0x0D: goto yy134;
- case ' ': goto yy132;
- default: goto yy115;
- }
-yy118: ++YYCURSOR;
- goto yy119;
-yy119:
-#line 589 "token.re"
-{ if ( plvl->status != syck_lvl_imap )
- {
- PLAIN_NOT_INL();
- }
- else
- {
- PLAIN_IS_INL();
- }
- RETURN_IMPLICIT();
- }
-#line 1612 "<stdout>"
-yy120: ++YYCURSOR;
- goto yy121;
-yy121:
-#line 600 "token.re"
-{ if ( plvl->status != syck_lvl_iseq )
- {
- PLAIN_NOT_INL();
- }
- else
- {
- PLAIN_IS_INL();
- }
- RETURN_IMPLICIT();
- }
-#line 1627 "<stdout>"
-yy122: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case '#': goto yy128;
- default: goto yy123;
- }
-yy123:
-#line 617 "token.re"
-{ if ( qidx == 0 )
- {
- goto Plain2;
- }
- else
- {
- goto Plain3;
- }
- }
-#line 1644 "<stdout>"
-yy124: ++YYCURSOR;
- goto yy125;
-yy125:
-#line 615 "token.re"
-{ RETURN_IMPLICIT(); }
-#line 1650 "<stdout>"
-yy126: yych = *++YYCURSOR;
- goto yy123;
-yy127: yych = *++YYCURSOR;
- goto yy115;
-yy128: ++YYCURSOR;
- goto yy129;
-yy129:
-#line 611 "token.re"
-{ eat_comments( parser );
- RETURN_IMPLICIT();
- }
-#line 1662 "<stdout>"
-yy130: ++YYCURSOR;
- goto yy131;
-yy131:
-#line 578 "token.re"
-{ if ( plvl->status != syck_lvl_iseq && plvl->status != syck_lvl_imap )
- {
- PLAIN_NOT_INL();
- }
- else
- {
- PLAIN_IS_INL();
- }
- RETURN_IMPLICIT();
- }
-#line 1677 "<stdout>"
-yy132: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy133;
-yy133: switch(yych){
- case ' ': goto yy132;
- default: goto yy131;
- }
-yy134: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy130;
- default: goto yy135;
- }
-yy135: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy113;
- case 1: goto yy115;
- }
-yy136: ++YYCURSOR;
- goto yy137;
-yy137:
-#line 576 "token.re"
-{ RETURN_IMPLICIT(); }
-#line 1701 "<stdout>"
-yy138: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy139;
-yy139: switch(yych){
- case ' ': goto yy138;
- default: goto yy137;
- }
-yy140: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy136;
- default: goto yy135;
- }
-yy141: yyaccept = 0;
- YYMARKER = ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy142;
-yy142: switch(yych){
- case 0x0A: case ' ': goto yy141;
- case 0x0D: goto yy143;
- default: goto yy113;
- }
-yy143: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- switch(yych){
- case 0x0A: goto yy141;
- default: goto yy135;
- }
-}
-#line 631 "token.re"
-
- }
-
-SingleQuote:
- {
- int qidx = 0;
- int qcapa = 100;
- char *qstr = S_ALLOC_N( char, qcapa );
-
-SingleQuote2:
- YYTOKEN = YYCURSOR;
-
-
-#line 1747 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy144;
- ++YYCURSOR;
-yy144:
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy152;
- case 0x0A: goto yy146;
- case 0x0D: goto yy148;
- case '\'': goto yy150;
- default: goto yy153;
- }
-yy146: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- goto yy157;
-yy147:
-#line 645 "token.re"
-{ int indt_len;
- int nl_count = 0;
- SyckLevel *lvl;
- GOBBLE_UP_YAML_INDENT( indt_len, YYTOKEN );
- lvl = CURRENT_LEVEL();
-
- if ( lvl->status != syck_lvl_str )
- {
- ADD_LEVEL( indt_len, syck_lvl_str );
- }
- else if ( indt_len < lvl->spaces )
- {
- /* Error! */
- }
-
- while ( YYTOKEN < YYCURSOR )
- {
- int nl_len = newline_len( YYTOKEN++ );
- if ( nl_len )
- {
- nl_count++;
- YYTOKEN += nl_len - 1;
- }
- }
- if ( nl_count <= 1 )
- {
- QUOTECAT(qstr, qcapa, qidx, ' ');
- }
- else
- {
- int i;
- for ( i = 0; i < nl_count - 1; i++ )
- {
- QUOTECAT(qstr, qcapa, qidx, '\n');
- }
- }
-
- goto SingleQuote2;
- }
-#line 1807 "<stdout>"
-yy148: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy156;
- default: goto yy149;
- }
-yy149:
-#line 712 "token.re"
-{ QUOTECAT(qstr, qcapa, qidx, *(YYCURSOR - 1));
- goto SingleQuote2;
- }
-#line 1818 "<stdout>"
-yy150: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case '\'': goto yy154;
- default: goto yy151;
- }
-yy151:
-#line 689 "token.re"
-{ SyckLevel *lvl;
- SyckNode *n = syck_alloc_str();
- lvl = CURRENT_LEVEL();
-
- if ( lvl->status == syck_lvl_str )
- {
- POP_LEVEL();
- }
- if ( ((SyckParser *)parser)->taguri_expansion == 1 )
- {
- n->type_id = syck_taguri( YAML_DOMAIN, "str", 3 );
- }
- else
- {
- n->type_id = syck_strndup( "str", 3 );
- }
- n->data.str->ptr = qstr;
- n->data.str->len = qidx;
- n->data.str->style = scalar_1quote;
- sycklval->nodeData = n;
- return YAML_PLAIN;
- }
-#line 1848 "<stdout>"
-yy152: yych = *++YYCURSOR;
- goto yy151;
-yy153: yych = *++YYCURSOR;
- goto yy149;
-yy154: ++YYCURSOR;
- goto yy155;
-yy155:
-#line 685 "token.re"
-{ QUOTECAT(qstr, qcapa, qidx, '\'');
- goto SingleQuote2;
- }
-#line 1860 "<stdout>"
-yy156: yyaccept = 0;
- YYMARKER = ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy157;
-yy157: switch(yych){
- case 0x0A: case ' ': goto yy156;
- case 0x0D: goto yy158;
- default: goto yy147;
- }
-yy158: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- switch(yych){
- case 0x0A: goto yy156;
- default: goto yy159;
- }
-yy159: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy147;
- }
-}
-#line 716 "token.re"
-
-
- }
-
-
-DoubleQuote:
- {
- int keep_nl = 1;
- int qidx = 0;
- int qcapa = 100;
- char *qstr = S_ALLOC_N( char, qcapa );
-
-DoubleQuote2:
- YYTOKEN = YYCURSOR;
-
-
-
-#line 1901 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy160;
- ++YYCURSOR;
-yy160:
- if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy167;
- case 0x0A: goto yy162;
- case 0x0D: goto yy164;
- case '"': goto yy169;
- case '\\': goto yy166;
- default: goto yy170;
- }
-yy162: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- goto yy184;
-yy163:
-#line 734 "token.re"
-{ int indt_len;
- int nl_count = 0;
- SyckLevel *lvl;
- GOBBLE_UP_YAML_INDENT( indt_len, YYTOKEN );
- lvl = CURRENT_LEVEL();
-
- if ( lvl->status != syck_lvl_str )
- {
- ADD_LEVEL( indt_len, syck_lvl_str );
- }
- else if ( indt_len < lvl->spaces )
- {
- /* FIXME */
- }
-
- if ( keep_nl == 1 )
- {
- while ( YYTOKEN < YYCURSOR )
- {
- int nl_len = newline_len( YYTOKEN++ );
- if ( nl_len )
- {
- nl_count++;
- YYTOKEN += nl_len - 1;
- }
- }
- if ( nl_count <= 1 )
- {
- QUOTECAT(qstr, qcapa, qidx, ' ');
- }
- else
- {
- int i;
- for ( i = 0; i < nl_count - 1; i++ )
- {
- QUOTECAT(qstr, qcapa, qidx, '\n');
- }
- }
- }
-
- keep_nl = 1;
- goto DoubleQuote2;
- }
-#line 1966 "<stdout>"
-yy164: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy183;
- default: goto yy165;
- }
-yy165:
-#line 820 "token.re"
-{ QUOTECAT(qstr, qcapa, qidx, *(YYCURSOR - 1));
- goto DoubleQuote2;
- }
-#line 1977 "<stdout>"
-yy166: yyaccept = 1;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case 0x0A: goto yy174;
- case 0x0D: goto yy176;
- case ' ': goto yy171;
- case '"': case '0': case '\\': case 'a':
- case 'b': case 'e':
- case 'f': case 'n': case 'r': case 't': case 'v': goto yy178;
- case 'x': goto yy177;
- default: goto yy165;
- }
-yy167: ++YYCURSOR;
- goto yy168;
-yy168:
-#line 797 "token.re"
-{ SyckLevel *lvl;
- SyckNode *n = syck_alloc_str();
- lvl = CURRENT_LEVEL();
-
- if ( lvl->status == syck_lvl_str )
- {
- POP_LEVEL();
- }
- if ( ((SyckParser *)parser)->taguri_expansion == 1 )
- {
- n->type_id = syck_taguri( YAML_DOMAIN, "str", 3 );
- }
- else
- {
- n->type_id = syck_strndup( "str", 3 );
- }
- n->data.str->ptr = qstr;
- n->data.str->len = qidx;
- n->data.str->style = scalar_2quote;
- sycklval->nodeData = n;
- return YAML_PLAIN;
- }
-#line 2016 "<stdout>"
-yy169: yych = *++YYCURSOR;
- goto yy168;
-yy170: yych = *++YYCURSOR;
- goto yy165;
-yy171: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- goto yy172;
-yy172: switch(yych){
- case 0x0A: goto yy174;
- case 0x0D: goto yy176;
- case ' ': goto yy171;
- default: goto yy173;
- }
-yy173: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy163;
- case 1: goto yy165;
- }
-yy174: ++YYCURSOR;
- goto yy175;
-yy175:
-#line 792 "token.re"
-{ keep_nl = 0;
- YYCURSOR--;
- goto DoubleQuote2;
- }
-#line 2044 "<stdout>"
-yy176: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy174;
- default: goto yy173;
- }
-yy177: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f': goto yy180;
- default: goto yy173;
- }
-yy178: ++YYCURSOR;
- goto yy179;
-yy179:
-#line 778 "token.re"
-{ char ch = *( YYCURSOR - 1 );
- QUOTECAT(qstr, qcapa, qidx, escape_seq( ch ));
- goto DoubleQuote2;
- }
-#line 2082 "<stdout>"
-yy180: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f': goto yy181;
- default: goto yy173;
- }
-yy181: ++YYCURSOR;
- goto yy182;
-yy182:
-#line 783 "token.re"
-{ long ch;
- char *chr_text = syck_strndup( YYTOKEN, 4 );
- chr_text[0] = '0';
- ch = strtol( chr_text, NULL, 16 );
- free( chr_text );
- QUOTECAT(qstr, qcapa, qidx, ch);
- goto DoubleQuote2;
- }
-#line 2119 "<stdout>"
-yy183: yyaccept = 0;
- YYMARKER = ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy184;
-yy184: switch(yych){
- case 0x0A: case ' ': goto yy183;
- case 0x0D: goto yy185;
- default: goto yy163;
- }
-yy185: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- switch(yych){
- case 0x0A: goto yy183;
- default: goto yy173;
- }
-}
-#line 824 "token.re"
-
- }
-
-TransferMethod:
- {
- int qidx = 0;
- int qcapa = 100;
- char *qstr = S_ALLOC_N( char, qcapa );
-
-TransferMethod2:
- YYTOKTMP = YYCURSOR;
-
-
-#line 2152 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy186;
- ++YYCURSOR;
-yy186:
- if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy188;
- case 0x0A: goto yy190;
- case 0x0D: goto yy192;
- case ' ': goto yy191;
- case '\\': goto yy194;
- default: goto yy195;
- }
-yy188: ++YYCURSOR;
- goto yy189;
-yy189:
-#line 838 "token.re"
-{ SyckLevel *lvl;
- YYCURSOR = YYTOKTMP;
- if ( YYCURSOR == YYTOKEN + 1 )
- {
- free( qstr );
- return YAML_ITRANSFER;
- }
-
- lvl = CURRENT_LEVEL();
-
- /*
- * URL Prefixing
- */
- if ( *qstr == '^' )
- {
- sycklval->name = S_ALLOC_N( char, qidx + strlen( lvl->domain ) );
- sycklval->name[0] = '\0';
- strcat( sycklval->name, lvl->domain );
- strncat( sycklval->name, qstr + 1, qidx - 1 );
- free( qstr );
- }
- else
- {
- char *carat = qstr;
- char *qend = qstr + qidx;
- while ( (++carat) < qend )
- {
- if ( *carat == '^' )
- break;
- }
-
- if ( carat < qend )
- {
- free( lvl->domain );
- lvl->domain = syck_strndup( qstr, carat - qstr );
- sycklval->name = S_ALLOC_N( char, ( qend - carat ) + strlen( lvl->domain ) );
- sycklval->name[0] = '\0';
- strcat( sycklval->name, lvl->domain );
- strncat( sycklval->name, carat + 1, ( qend - carat ) - 1 );
- free( qstr );
- }
- else
- {
- sycklval->name = qstr;
- }
- }
-
- return YAML_TRANSFER;
- }
-#line 2222 "<stdout>"
-yy190: yych = *++YYCURSOR;
- goto yy189;
-yy191: yych = *++YYCURSOR;
- goto yy204;
-yy192: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy188;
- default: goto yy193;
- }
-yy193:
-#line 905 "token.re"
-{ QUOTECAT(qstr, qcapa, qidx, *(YYCURSOR - 1));
- goto TransferMethod2;
- }
-#line 2237 "<stdout>"
-yy194: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case '"': case '0': case '\\': case 'a':
- case 'b': case 'e':
- case 'f': case 'n': case 'r': case 't': case 'v': goto yy198;
- case 'x': goto yy196;
- default: goto yy193;
- }
-yy195: yych = *++YYCURSOR;
- goto yy193;
-yy196: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f': goto yy200;
- default: goto yy197;
- }
-yy197: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy193;
- }
-yy198: ++YYCURSOR;
- goto yy199;
-yy199:
-#line 891 "token.re"
-{ char ch = *( YYCURSOR - 1 );
- QUOTECAT(qstr, qcapa, qidx, escape_seq( ch ));
- goto TransferMethod2;
- }
-#line 2285 "<stdout>"
-yy200: yych = *++YYCURSOR;
- switch(yych){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F': case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f': goto yy201;
- default: goto yy197;
- }
-yy201: ++YYCURSOR;
- goto yy202;
-yy202:
-#line 896 "token.re"
-{ long ch;
- char *chr_text = syck_strndup( YYTOKTMP, 4 );
- chr_text[0] = '0';
- ch = strtol( chr_text, NULL, 16 );
- free( chr_text );
- QUOTECAT(qstr, qcapa, qidx, ch);
- goto TransferMethod2;
- }
-#line 2322 "<stdout>"
-yy203: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy204;
-yy204: switch(yych){
- case ' ': goto yy203;
- default: goto yy189;
- }
-}
-#line 910 "token.re"
-
- }
-
-ScalarBlock:
- {
- int qidx = 0;
- int qcapa = 100;
- char *qstr = S_ALLOC_N( char, qcapa );
- int blockType = 0;
- int nlDoWhat = 0;
- int lastIndent = 0;
- int forceIndent = -1;
- char *yyt = YYTOKEN;
- SyckLevel *lvl = CURRENT_LEVEL();
- int parentIndent = -1;
-
- switch ( *yyt )
- {
- case '|': blockType = BLOCK_LIT; break;
- case '>': blockType = BLOCK_FOLD; break;
- }
-
- while ( ++yyt <= YYCURSOR )
- {
- if ( *yyt == '-' )
- {
- nlDoWhat = NL_CHOMP;
- }
- else if ( *yyt == '+' )
- {
- nlDoWhat = NL_KEEP;
- }
- else if ( isdigit( *yyt ) )
- {
- forceIndent = strtol( yyt, NULL, 10 );
- }
- }
-
- qstr[0] = '\0';
- YYTOKEN = YYCURSOR;
-
-ScalarBlock2:
- YYTOKEN = YYCURSOR;
-
-
-#line 2378 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy205;
- ++YYCURSOR;
-yy205:
- if((YYLIMIT - YYCURSOR) < 5) YYFILL(5);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy213;
- case 0x0A: goto yy207;
- case 0x0D: goto yy209;
- case '#': goto yy211;
- case '-': goto yy215;
- default: goto yy216;
- }
-yy207: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- goto yy226;
-yy208:
-#line 956 "token.re"
-{ char *pacer;
- char *tok = YYTOKEN;
- int indt_len = 0, nl_count = 0, fold_nl = 0, nl_begin = 0;
- GOBBLE_UP_YAML_INDENT( indt_len, tok );
- lvl = CURRENT_LEVEL();
-
- if ( lvl->status != syck_lvl_block )
- {
- GET_TRUE_YAML_INDENT(parentIndent);
- if ( forceIndent > 0 ) forceIndent += parentIndent;
- if ( indt_len > parentIndent )
- {
- int new_spaces = forceIndent > 0 ? forceIndent : indt_len;
- ADD_LEVEL( new_spaces, syck_lvl_block );
- lastIndent = indt_len - new_spaces;
- nl_begin = 1;
- lvl = CURRENT_LEVEL();
- }
- else
- {
- YYCURSOR = YYTOKEN;
- RETURN_YAML_BLOCK();
- }
- }
-
- /*
- * Fold only in the event of two lines being on the leftmost
- * indentation.
- */
- if ( blockType == BLOCK_FOLD && lastIndent == 0 && ( indt_len - lvl->spaces ) == 0 )
- {
- fold_nl = 1;
- }
-
- pacer = YYTOKEN;
- while ( pacer < YYCURSOR )
- {
- int nl_len = newline_len( pacer++ );
- if ( nl_len )
- {
- nl_count++;
- pacer += nl_len - 1;
- }
- }
-
- if ( fold_nl == 1 || nl_begin == 1 )
- {
- nl_count--;
- }
-
- if ( nl_count < 1 && nl_begin == 0 )
- {
- QUOTECAT(qstr, qcapa, qidx, ' ');
- }
- else
- {
- int i;
- for ( i = 0; i < nl_count; i++ )
- {
- QUOTECAT(qstr, qcapa, qidx, '\n');
- }
- }
-
- lastIndent = indt_len - lvl->spaces;
- YYCURSOR -= lastIndent;
-
- if ( indt_len < lvl->spaces )
- {
- POP_LEVEL();
- YYCURSOR = YYTOKEN;
- RETURN_YAML_BLOCK();
- }
- goto ScalarBlock2;
- }
-#line 2474 "<stdout>"
-yy209: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy225;
- default: goto yy210;
- }
-yy210:
-#line 1070 "token.re"
-{ QUOTECAT(qstr, qcapa, qidx, *YYTOKEN);
- goto ScalarBlock2;
- }
-#line 2485 "<stdout>"
-yy211: ++YYCURSOR;
- goto yy212;
-yy212:
-#line 1032 "token.re"
-{ lvl = CURRENT_LEVEL();
- if ( lvl->status != syck_lvl_block )
- {
- eat_comments( parser );
- YYTOKEN = YYCURSOR;
- }
- else
- {
- QUOTECAT(qstr, qcapa, qidx, *YYTOKEN);
- }
- goto ScalarBlock2;
- }
-#line 2502 "<stdout>"
-yy213: ++YYCURSOR;
- goto yy214;
-yy214:
-#line 1046 "token.re"
-{ YYCURSOR--;
- POP_LEVEL();
- RETURN_YAML_BLOCK();
- }
-#line 2511 "<stdout>"
-yy215: yyaccept = 1;
- yych = *(YYMARKER = ++YYCURSOR);
- switch(yych){
- case '-': goto yy217;
- default: goto yy210;
- }
-yy216: yych = *++YYCURSOR;
- goto yy210;
-yy217: yych = *++YYCURSOR;
- switch(yych){
- case '-': goto yy219;
- default: goto yy218;
- }
-yy218: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy208;
- case 1: goto yy210;
- }
-yy219: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy220;
- case 0x0D: goto yy224;
- case ' ': goto yy222;
- default: goto yy218;
- }
-yy220: ++YYCURSOR;
- goto yy221;
-yy221:
-#line 1051 "token.re"
-{ if ( YYTOKEN == YYLINEPTR )
- {
- if ( blockType == BLOCK_FOLD && qidx > 0 )
- {
- qidx -= 1;
- }
- QUOTECAT(qstr, qcapa, qidx, '\n');
- POP_LEVEL();
- YYCURSOR = YYTOKEN;
- RETURN_YAML_BLOCK();
- }
- else
- {
- QUOTECAT(qstr, qcapa, qidx, *YYTOKEN);
- YYCURSOR = YYTOKEN + 1;
- goto ScalarBlock2;
- }
- }
-#line 2559 "<stdout>"
-yy222: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy223;
-yy223: switch(yych){
- case ' ': goto yy222;
- default: goto yy221;
- }
-yy224: yych = *++YYCURSOR;
- switch(yych){
- case 0x0A: goto yy220;
- default: goto yy218;
- }
-yy225: yyaccept = 0;
- YYMARKER = ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy226;
-yy226: switch(yych){
- case 0x0A: case ' ': goto yy225;
- case 0x0D: goto yy227;
- default: goto yy208;
- }
-yy227: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- switch(yych){
- case 0x0A: goto yy225;
- default: goto yy218;
- }
-}
-#line 1075 "token.re"
-
- }
-
- return 0;
-
-}
-
-void
-eat_comments( SyckParser *parser )
-{
-Comment:
- {
- YYTOKEN = YYCURSOR;
-
-
-#line 2607 "<stdout>"
-{
- YYCTYPE yych;
- unsigned int yyaccept;
- goto yy228;
- ++YYCURSOR;
-yy228:
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- switch(yych){
- case 0x00: goto yy230;
- case 0x0A: goto yy232;
- case 0x0D: goto yy233;
- default: goto yy235;
- }
-yy230: ++YYCURSOR;
- goto yy231;
-yy231:
-#line 1091 "token.re"
-{ YYCURSOR = YYTOKEN;
- return;
- }
-#line 2629 "<stdout>"
-yy232: yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- goto yy237;
-yy233: ++YYCURSOR;
- switch((yych = *YYCURSOR)) {
- case 0x0A: goto yy236;
- default: goto yy234;
- }
-yy234:
-#line 1095 "token.re"
-{ goto Comment;
- }
-#line 2642 "<stdout>"
-yy235: yych = *++YYCURSOR;
- goto yy234;
-yy236: yyaccept = 0;
- YYMARKER = ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- goto yy237;
-yy237: switch(yych){
- case 0x0A: goto yy236;
- case 0x0D: goto yy238;
- default: goto yy231;
- }
-yy238: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- switch(yych){
- case 0x0A: goto yy236;
- default: goto yy239;
- }
-yy239: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy231;
- }
-}
-#line 1098 "token.re"
-
-
- }
-
-}
-
-char
-escape_seq( char ch )
-{
- switch ( ch )
- {
- case '0': return '\0';
- case 'a': return 7;
- case 'b': return '\010';
- case 'e': return '\033';
- case 'f': return '\014';
- case 'n': return '\n';
- case 'r': return '\015';
- case 't': return '\t';
- case 'v': return '\013';
- default: return ch;
- }
-}
-
-int
-is_newline( char *ptr )
-{
- return newline_len( ptr );
-}
-
-int
-newline_len( char *ptr )
-{
- if ( *ptr == '\n' )
- return 1;
-
- if ( *ptr == '\r' && *( ptr + 1 ) == '\n' )
- return 2;
-
- return 0;
-}
-
-int
-syckwrap()
-{
- return 1;
-}
-
-void
-syckerror( char *msg )
-{
- if ( syck_parser_ptr->error_handler == NULL )
- syck_parser_ptr->error_handler = syck_default_error_handler;
-
- syck_parser_ptr->root = syck_parser_ptr->root_on_error;
- (syck_parser_ptr->error_handler)(syck_parser_ptr, msg);
-}
-
diff --git a/ext/syck/yaml2byte.c b/ext/syck/yaml2byte.c
deleted file mode 100644
index 821a3cd5b5..0000000000
--- a/ext/syck/yaml2byte.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * yaml2byte.c
- *
- * $Author$
- * $Date$
- *
- * Copyright (C) 2003 why the lucky stiff, clark evans
- *
- * WARNING WARNING WARNING --- THIS IS *NOT JUST* PLAYING
- * ANYMORE! -- WHY HAS EMBRACED THIS AS THE REAL THING!
- */
-#include "ruby.h"
-#include <syck.h>
-#include <assert.h>
-#define YAMLBYTE_UTF8
-#include "yamlbyte.h"
-
-#include <stdio.h>
-#define TRACE0(a) \
- do { printf(a); printf("\n"); fflush(stdout); } while(0)
-#define TRACE1(a,b) \
- do { printf(a,b); printf("\n"); fflush(stdout); } while(0)
-#define TRACE2(a,b,c) \
- do { printf(a,b,c); printf("\n"); fflush(stdout); } while(0)
-#define TRACE3(a,b,c,d) \
- do { printf(a,b,c,d); printf("\n"); fflush(stdout); } while(0)
-
-/* Reinvent the wheel... */
-#define CHUNKSIZE 64
-#define HASH ((long)0xCAFECAFE)
-typedef struct {
- long hash;
- char *buffer;
- long length;
- long remaining;
- int printed;
-} bytestring_t;
-bytestring_t *bytestring_alloc() {
- bytestring_t *ret;
- /*TRACE0("bytestring_alloc()");*/
- ret = S_ALLOC(bytestring_t);
- ret->hash = HASH;
- ret->length = CHUNKSIZE;
- ret->remaining = ret->length;
- ret->buffer = S_ALLOC_N(char, ret->length + 1 );
- ret->buffer[0] = 0;
- ret->printed = 0;
- return ret;
-}
-void bytestring_append(bytestring_t *str, char code,
- char *start, char *finish)
-{
- long grow;
- long length = 2; /* CODE + LF */
- char *curr;
- assert(str && HASH == str->hash);
- /*TRACE0("bytestring_append()");*/
- if(start) {
- if(!finish)
- finish = start + strlen(start);
- length += (finish-start);
- }
- if(length > str->remaining) {
- grow = (length - str->remaining) + CHUNKSIZE;
- str->remaining += grow;
- str->length += grow;
- str->buffer = S_REALLOC_N( str->buffer, char, str->length + 1 );
- assert(str->buffer);
- }
- curr = str->buffer + (str->length - str->remaining);
- *curr = code;
- curr += 1;
- if(start)
- while(start < finish)
- *curr ++ = *start ++;
- *curr = '\n';
- curr += 1;
- *curr = 0;
- str->remaining = str->remaining - length;
- assert( (str->buffer + str->length) - str->remaining );
-}
-void bytestring_extend(bytestring_t *str, bytestring_t *ext)
-{
- char *from;
- char *curr;
- char *stop;
- long grow;
- long length;
- assert(str && HASH == str->hash);
- assert(ext && HASH == ext->hash);
- if(ext->printed) {
- assert(ext->buffer[0] ==YAMLBYTE_ANCHOR);
- curr = ext->buffer;
- while( '\n' != *curr)
- curr++;
- bytestring_append(str, YAMLBYTE_ALIAS, ext->buffer + 1, curr);
- } else {
- ext->printed = 1;
- length = (ext->length - ext->remaining);
- if(length > str->remaining) {
- grow = (length - str->remaining) + CHUNKSIZE;
- str->remaining += grow;
- str->length += grow;
- str->buffer = S_REALLOC_N( str->buffer, char, str->length + 1 );
- }
- curr = str->buffer + (str->length - str->remaining);
- from = ext->buffer;
- stop = ext->buffer + length;
- while( from < stop )
- *curr ++ = *from ++;
- *curr = 0;
- str->remaining = str->remaining - length;
- assert( (str->buffer + str->length) - str->remaining );
- }
-}
-
-/* convert SyckNode into yamlbyte_buffer_t objects */
-SYMID
-syck_yaml2byte_handler(p, n)
- SyckParser *p;
- SyckNode *n;
-{
- SYMID oid;
- long i;
- char ch;
- char nextcode;
- char *start;
- char *current;
- char *finish;
- bytestring_t *val = NULL;
- bytestring_t *sav = NULL;
- /*TRACE0("syck_yaml2byte_handler()");*/
- val = bytestring_alloc();
- if(n->anchor) bytestring_append(val,YAMLBYTE_ANCHOR, n->anchor, NULL);
- if ( n->type_id )
- {
- if ( p->taguri_expansion )
- {
- bytestring_append(val,YAMLBYTE_TRANSFER, n->type_id, NULL);
- }
- else
- {
- char *type_tag = S_ALLOC_N( char, strlen( n->type_id ) + 1 );
- type_tag[0] = '\0';
- strcat( type_tag, "!" );
- strcat( type_tag, n->type_id );
- bytestring_append( val, YAMLBYTE_TRANSFER, type_tag, NULL);
- S_FREE(type_tag);
- }
- }
- switch (n->kind)
- {
- case syck_str_kind:
- nextcode = YAMLBYTE_SCALAR;
- start = n->data.str->ptr;
- finish = start + n->data.str->len - 1;
- current = start;
- /*TRACE2("SCALAR: %s %d", start, n->data.str->len); */
- while(1) {
- ch = *current;
- if('\n' == ch || 0 == ch || current > finish) {
- if(current >= start) {
- bytestring_append(val, nextcode, start, current);
- nextcode = YAMLBYTE_CONTINUE;
- }
- start = current + 1;
- if(current > finish)
- {
- break;
- }
- else if('\n' == ch )
- {
- bytestring_append(val,YAMLBYTE_NEWLINE,NULL,NULL);
- }
- else if(0 == ch)
- {
- bytestring_append(val,YAMLBYTE_NULLCHAR,NULL,NULL);
- }
- else
- {
- assert("oops");
- }
- }
- current += 1;
- }
- break;
- case syck_seq_kind:
- bytestring_append(val,YAMLBYTE_SEQUENCE,NULL,NULL);
- for ( i = 0; i < n->data.list->idx; i++ )
- {
- oid = syck_seq_read( n, i );
- syck_lookup_sym( p, oid, (char **)&sav );
- bytestring_extend(val, sav);
- }
- bytestring_append(val,YAMLBYTE_END_BRANCH,NULL,NULL);
- break;
- case syck_map_kind:
- bytestring_append(val,YAMLBYTE_MAPPING,NULL,NULL);
- for ( i = 0; i < n->data.pairs->idx; i++ )
- {
- oid = syck_map_read( n, map_key, i );
- syck_lookup_sym( p, oid, (char **)&sav );
- bytestring_extend(val, sav);
- oid = syck_map_read( n, map_value, i );
- syck_lookup_sym( p, oid, (char **)&sav );
- bytestring_extend(val, sav);
- }
- bytestring_append(val,YAMLBYTE_END_BRANCH,NULL,NULL);
- break;
- }
- oid = syck_add_sym( p, (char *) val );
- /*TRACE1("Saving: %s", val->buffer );*/
- return oid;
-}
-
-char *
-syck_yaml2byte(char *yamlstr)
-{
- SYMID oid;
- char *ret;
- bytestring_t *sav;
-
- SyckParser *parser = syck_new_parser();
- syck_parser_str_auto( parser, yamlstr, NULL );
- syck_parser_handler( parser, syck_yaml2byte_handler );
- syck_parser_error_handler( parser, NULL );
- syck_parser_implicit_typing( parser, 1 );
- syck_parser_taguri_expansion( parser, 1 );
- oid = syck_parse( parser );
-
- if ( syck_lookup_sym( parser, oid, (char **)&sav ) == 1 ) {
- ret = S_ALLOC_N( char, strlen( sav->buffer ) + 3 );
- ret[0] = '\0';
- strcat( ret, "D\n" );
- strcat( ret, sav->buffer );
- }
- else
- {
- ret = NULL;
- }
-
- syck_free_parser( parser );
- return ret;
-}
-
-#ifdef TEST_YBEXT
-#include <stdio.h>
-int main() {
- char *yaml = "test: 1\nand: \"with new\\nline\\n\"\nalso: &3 three\nmore: *3";
- printf("--- # YAML \n");
- printf(yaml);
- printf("\n...\n");
- printf(syck_yaml2byte(yaml));
- return 0;
-}
-#endif
-
diff --git a/ext/syck/yamlbyte.h b/ext/syck/yamlbyte.h
deleted file mode 100644
index 0fe4e7b576..0000000000
--- a/ext/syck/yamlbyte.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/* yamlbyte.h
- *
- * The YAML bytecode "C" interface header file. See the YAML bytecode
- * reference for bytecode sequence rules and for the meaning of each
- * bytecode.
- */
-
-#ifndef YAMLBYTE_H
-#define YAMLBYTE_H
-#include <stddef.h>
-
-/* define what a character is */
-typedef unsigned char yamlbyte_utf8_t;
-typedef unsigned short yamlbyte_utf16_t;
-#ifdef YAMLBYTE_UTF8
- #ifdef YAMLBYTE_UTF16
- #error Must only define YAMLBYTE_UTF8 or YAMLBYTE_UTF16
- #endif
- typedef yamlbyte_utf8_t yamlbyte_char_t;
-#else
- #ifdef YAMLBYTE_UTF16
- typedef yamlbyte_utf16_t yamlbyte_char_t;
- #else
- #error Must define YAMLBYTE_UTF8 or YAMLBYTE_UTF16
- #endif
-#endif
-
-/* specify list of bytecodes */
-#define YAMLBYTE_FINISH ((yamlbyte_char_t) 0)
-#define YAMLBYTE_DOCUMENT ((yamlbyte_char_t)'D')
-#define YAMLBYTE_DIRECTIVE ((yamlbyte_char_t)'V')
-#define YAMLBYTE_PAUSE ((yamlbyte_char_t)'P')
-#define YAMLBYTE_MAPPING ((yamlbyte_char_t)'M')
-#define YAMLBYTE_SEQUENCE ((yamlbyte_char_t)'Q')
-#define YAMLBYTE_END_BRANCH ((yamlbyte_char_t)'E')
-#define YAMLBYTE_SCALAR ((yamlbyte_char_t)'S')
-#define YAMLBYTE_CONTINUE ((yamlbyte_char_t)'C')
-#define YAMLBYTE_NEWLINE ((yamlbyte_char_t)'N')
-#define YAMLBYTE_NULLCHAR ((yamlbyte_char_t)'Z')
-#define YAMLBYTE_ANCHOR ((yamlbyte_char_t)'A')
-#define YAMLBYTE_ALIAS ((yamlbyte_char_t)'R')
-#define YAMLBYTE_TRANSFER ((yamlbyte_char_t)'T')
-/* formatting bytecodes */
-#define YAMLBYTE_COMMENT ((yamlbyte_char_t)'c')
-#define YAMLBYTE_INDENT ((yamlbyte_char_t)'i')
-#define YAMLBYTE_STYLE ((yamlbyte_char_t)'s')
-/* other bytecodes */
-#define YAMLBYTE_LINE_NUMBER ((yamlbyte_char_t)'#')
-#define YAMLBYTE_WHOLE_SCALAR ((yamlbyte_char_t)'<')
-#define YAMLBYTE_NOTICE ((yamlbyte_char_t)'!')
-#define YAMLBYTE_SPAN ((yamlbyte_char_t)')')
-#define YAMLBYTE_ALLOC ((yamlbyte_char_t)'@')
-
-/* second level style bytecodes, ie "s>" */
-#define YAMLBYTE_FLOW ((yamlbyte_char_t)'>')
-#define YAMLBYTE_LITERAL ((yamlbyte_char_t)'|')
-#define YAMLBYTE_BLOCK ((yamlbyte_char_t)'b')
-#define YAMLBYTE_PLAIN ((yamlbyte_char_t)'p')
-#define YAMLBYTE_INLINE_MAPPING ((yamlbyte_char_t)'{')
-#define YAMLBYTE_INLINE_SEQUENCE ((yamlbyte_char_t)'[')
-#define YAMLBYTE_SINGLE_QUOTED ((yamlbyte_char_t)39)
-#define YAMLBYTE_DOUBLE_QUOTED ((yamlbyte_char_t)'"')
-
-/*
- * The "C" API has two variants, one based on instructions,
- * with events delivered via pointers; and the other one
- * is character based where one or more instructions are
- * serialized into a buffer.
- *
- * Note: In the instruction based API, WHOLE_SCALAR does
- * not have the '<here' marshalling stuff.
- */
-
-typedef void * yamlbyte_consumer_t;
-typedef void * yamlbyte_producer_t;
-
-/* push and pull APIs need a way to communicate results */
-typedef enum {
- YAMLBYTE_OK = 0, /* proceed */
- YAMLBYTE_E_MEMORY = 'M', /* could not allocate memory */
- YAMLBYTE_E_READ = 'R', /* input stream read error */
- YAMLBYTE_E_WRITE = 'W', /* output stream write error */
- YAMLBYTE_E_OTHER = '?', /* some other error condition */
- YAMLBYTE_E_PARSE = 'P', /* parse error, check bytecodes */
-} yamlbyte_result_t;
-
-typedef const yamlbyte_char_t *yamlbyte_buff_t;
-
-/*
- * The "Instruction" API
- */
-
-typedef struct yaml_instruction {
- yamlbyte_char_t bytecode;
- yamlbyte_buff_t start;
- yamlbyte_buff_t finish; /* open range, *finish is _not_ part */
-} *yamlbyte_inst_t;
-
-/* producer pushes the instruction with one bytecode event to the
- * consumer; if the consumer's result is not YAMLBYTE_OK, then
- * the producer should stop */
-typedef
- yamlbyte_result_t
- (*yamlbyte_push_t)(
- yamlbyte_consumer_t self,
- yamlbyte_inst_t inst
- );
-
-/* consumer pulls a bytecode instruction from the producer; in this
- * case the instruction (and is buffer) are owned by the producer and
- * will remain valid till the pull function is called once again;
- * if the instruction is NULL, then there are no more results; and
- * it is important to call the pull function till it returns NULL so
- * that the producer can clean up its memory allocations */
-typedef
- yamlbyte_result_t
- (*yamlbyte_pull_t)(
- yamlbyte_producer_t self,
- yamlbyte_inst_t *inst /* to be filled in by the producer */
- );
-
-/*
- * Buffer based API
- */
-
-/* producer pushes a null terminated buffer filled with one or more
- * bytecode events to the consumer; if the consumer's result is not
- * YAMLBYTE_OK, then the producer should stop */
-typedef
- yamlbyte_result_t
- (*yamlbyte_pushbuff_t)(
- yamlbyte_consumer_t self,
- yamlbyte_buff_t buff
- );
-
-/* consumer pulls bytecode events from the producer; in this case
- * the buffer is owned by the producer, and will remain valid till
- * the pull function is called once again; if the buffer pointer
- * is set to NULL, then there are no more results; it is important
- * to call the pull function till it returns NULL so that the
- * producer can clean up its memory allocations */
-typedef
- yamlbyte_result_t
- (*yamlbyte_pullbuff_t)(
- yamlbyte_producer_t self,
- yamlbyte_buff_t *buff /* to be filled in by the producer */
- );
-
-/* convert a pull interface to a push interface; the reverse process
- * requires threads and thus is language dependent */
-#define YAMLBYTE_PULL2PUSH(pull,producer,push,consumer,result) \
- do { \
- yamlbyte_pullbuff_t _pull = (pull); \
- yamlbyte_pushbuff_t _push = (push); \
- yamlbyte_result_t _result = YAMLBYTE_OK; \
- yamlbyte_producer_t _producer = (producer); \
- yamlbyte_consumer_t _consumer = (consumer); \
- while(1) { \
- yamlbyte_buff_t buff = NULL; \
- _result = _pull(_producer,&buff); \
- if(YAMLBYTE_OK != result || NULL == buff) \
- break; \
- _result = _push(_consumer,buff); \
- if(YAMLBYTE_OK != result) \
- break; \
- } \
- (result) = _result; \
- } while(0)
-
-#endif
diff --git a/ext/syslog/.cvsignore b/ext/syslog/.cvsignore
deleted file mode 100644
index 4088712231..0000000000
--- a/ext/syslog/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.def
diff --git a/ext/syslog/depend b/ext/syslog/depend
deleted file mode 100644
index 45cbea293a..0000000000
--- a/ext/syslog/depend
+++ /dev/null
@@ -1,2 +0,0 @@
-syslog.o: syslog.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h \
- $(hdrdir)/intern.h
diff --git a/ext/syslog/extconf.rb b/ext/syslog/extconf.rb
deleted file mode 100644
index 0fa0bc339b..0000000000
--- a/ext/syslog/extconf.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# $RoughId: extconf.rb,v 1.3 2001/11/24 17:49:26 knu Exp $
-# $Id$
-
-require 'mkmf'
-
-have_header("syslog.h") &&
- have_func("openlog") &&
- have_func("setlogmask") &&
- create_makefile("syslog")
-
diff --git a/ext/syslog/syslog.c b/ext/syslog/syslog.c
deleted file mode 100644
index 477489ddfe..0000000000
--- a/ext/syslog/syslog.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * UNIX Syslog extension for Ruby
- * Amos Gouaux, University of Texas at Dallas
- * <amos+ruby@utdallas.edu>
- *
- * $RoughId: syslog.c,v 1.21 2002/02/25 12:21:17 knu Exp $
- * $Id$
- */
-
-#include "ruby.h"
-#include "util.h"
-#include <syslog.h>
-
-/* Syslog class */
-static VALUE mSyslog, mSyslogConstants;
-static const char *syslog_ident = NULL;
-static int syslog_options = -1, syslog_facility = -1, syslog_mask = -1;
-static int syslog_opened = 0;
-
-/* Package helper routines */
-static void syslog_write(int pri, int argc, VALUE *argv)
-{
- VALUE str;
-
- if (argc < 1) {
- rb_raise(rb_eArgError, "no log message supplied");
- }
-
- if (!syslog_opened) {
- rb_raise(rb_eRuntimeError, "must open syslog before write");
- }
-
- str = rb_f_sprintf(argc, argv);
-
- syslog(pri, "%s", RSTRING(str)->ptr);
-}
-
-/* Syslog module methods */
-static VALUE mSyslog_close(VALUE self)
-{
- if (!syslog_opened) {
- rb_raise(rb_eRuntimeError, "syslog not opened");
- }
-
- closelog();
-
- free((void *)syslog_ident);
- syslog_ident = NULL;
- syslog_options = syslog_facility = syslog_mask = -1;
- syslog_opened = 0;
-
- return Qnil;
-}
-
-static VALUE mSyslog_open(int argc, VALUE *argv, VALUE self)
-{
- VALUE ident, opt, fac;
-
- if (syslog_opened) {
- rb_raise(rb_eRuntimeError, "syslog already open");
- }
-
- rb_scan_args(argc, argv, "03", &ident, &opt, &fac);
-
- if (NIL_P(ident)) {
- ident = rb_gv_get("$0");
- }
-#ifdef SafeStringValue
- SafeStringValue(ident);
-#else
- Check_SafeStr(ident);
-#endif
- syslog_ident = strdup(RSTRING(ident)->ptr);
-
- if (NIL_P(opt)) {
- syslog_options = LOG_PID | LOG_CONS;
- } else {
- syslog_options = NUM2INT(opt);
- }
-
- if (NIL_P(fac)) {
- syslog_facility = LOG_USER;
- } else {
- syslog_facility = NUM2INT(fac);
- }
-
- openlog(syslog_ident, syslog_options, syslog_facility);
-
- syslog_opened = 1;
-
- setlogmask(syslog_mask = setlogmask(0));
-
- /* be like File.new.open {...} */
- if (rb_block_given_p()) {
- rb_ensure(rb_yield, self, mSyslog_close, self);
- }
-
- return self;
-}
-
-static VALUE mSyslog_reopen(int argc, VALUE *argv, VALUE self)
-{
- mSyslog_close(self);
-
- return mSyslog_open(argc, argv, self);
-}
-
-static VALUE mSyslog_isopen(VALUE self)
-{
- return syslog_opened ? Qtrue : Qfalse;
-}
-
-static VALUE mSyslog_ident(VALUE self)
-{
- return syslog_opened ? rb_str_new2(syslog_ident) : Qnil;
-}
-
-static VALUE mSyslog_options(VALUE self)
-{
- return syslog_opened ? INT2NUM(syslog_options) : Qnil;
-}
-
-static VALUE mSyslog_facility(VALUE self)
-{
- return syslog_opened ? INT2NUM(syslog_facility) : Qnil;
-}
-
-static VALUE mSyslog_get_mask(VALUE self)
-{
- return syslog_opened ? INT2NUM(syslog_mask) : Qnil;
-}
-
-static VALUE mSyslog_set_mask(VALUE self, VALUE mask)
-{
- if (!syslog_opened) {
- rb_raise(rb_eRuntimeError, "must open syslog before setting log mask");
- }
-
- setlogmask(syslog_mask = NUM2INT(mask));
-
- return mask;
-}
-
-static VALUE mSyslog_log(int argc, VALUE *argv, VALUE self)
-{
- VALUE pri;
-
- if (argc < 2) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2+)", argc);
- }
-
- argc--;
- pri = *argv++;
-
- if (!FIXNUM_P(pri)) {
- rb_raise(rb_eTypeError, "type mismatch: %s given", rb_class2name(CLASS_OF(pri)));
- }
-
- syslog_write(FIX2INT(pri), argc, argv);
-
- return self;
-}
-
-static VALUE mSyslog_inspect(VALUE self)
-{
- char buf[1024];
-
- if (syslog_opened) {
- snprintf(buf, sizeof(buf),
- "<#%s: opened=true, ident=\"%s\", options=%d, facility=%d, mask=%d>",
- rb_class2name(self),
- syslog_ident,
- syslog_options,
- syslog_facility,
- syslog_mask);
- } else {
- snprintf(buf, sizeof(buf),
- "<#%s: opened=false>", rb_class2name(self));
- }
-
- return rb_str_new2(buf);
-}
-
-static VALUE mSyslog_instance(VALUE self)
-{
- return self;
-}
-
-#define define_syslog_shortcut_method(pri, name) \
-static VALUE mSyslog_##name(int argc, VALUE *argv, VALUE self) \
-{ \
- syslog_write(pri, argc, argv); \
-\
- return self; \
-}
-
-#ifdef LOG_EMERG
-define_syslog_shortcut_method(LOG_EMERG, emerg)
-#endif
-#ifdef LOG_ALERT
-define_syslog_shortcut_method(LOG_ALERT, alert)
-#endif
-#ifdef LOG_CRIT
-define_syslog_shortcut_method(LOG_CRIT, crit)
-#endif
-#ifdef LOG_ERR
-define_syslog_shortcut_method(LOG_ERR, err)
-#endif
-#ifdef LOG_WARNING
-define_syslog_shortcut_method(LOG_WARNING, warning)
-#endif
-#ifdef LOG_NOTICE
-define_syslog_shortcut_method(LOG_NOTICE, notice)
-#endif
-#ifdef LOG_INFO
-define_syslog_shortcut_method(LOG_INFO, info)
-#endif
-#ifdef LOG_DEBUG
-define_syslog_shortcut_method(LOG_DEBUG, debug)
-#endif
-
-static VALUE mSyslogConstants_LOG_MASK(VALUE klass, VALUE pri)
-{
- return INT2FIX(LOG_MASK(FIX2INT(pri)));
-}
-
-static VALUE mSyslogConstants_LOG_UPTO(VALUE klass, VALUE pri)
-{
- return INT2FIX(LOG_UPTO(FIX2INT(pri)));
-}
-
-/* Init for package syslog */
-void Init_syslog()
-{
- mSyslog = rb_define_module("Syslog");
-
- mSyslogConstants = rb_define_module_under(mSyslog, "Constants");
-
- rb_include_module(mSyslog, mSyslogConstants);
-
- rb_define_module_function(mSyslog, "open", mSyslog_open, -1);
- rb_define_module_function(mSyslog, "reopen", mSyslog_reopen, -1);
- rb_define_module_function(mSyslog, "open!", mSyslog_reopen, -1);
- rb_define_module_function(mSyslog, "opened?", mSyslog_isopen, 0);
-
- rb_define_module_function(mSyslog, "ident", mSyslog_ident, 0);
- rb_define_module_function(mSyslog, "options", mSyslog_options, 0);
- rb_define_module_function(mSyslog, "facility", mSyslog_facility, 0);
-
- rb_define_module_function(mSyslog, "log", mSyslog_log, -1);
- rb_define_module_function(mSyslog, "close", mSyslog_close, 0);
- rb_define_module_function(mSyslog, "mask", mSyslog_get_mask, 0);
- rb_define_module_function(mSyslog, "mask=", mSyslog_set_mask, 1);
-
- rb_define_module_function(mSyslog, "LOG_MASK", mSyslogConstants_LOG_MASK, 1);
- rb_define_module_function(mSyslog, "LOG_UPTO", mSyslogConstants_LOG_UPTO, 1);
-
- rb_define_module_function(mSyslog, "inspect", mSyslog_inspect, 0);
- rb_define_module_function(mSyslog, "instance", mSyslog_instance, 0);
-
- rb_define_module_function(mSyslogConstants, "LOG_MASK", mSyslogConstants_LOG_MASK, 1);
- rb_define_module_function(mSyslogConstants, "LOG_UPTO", mSyslogConstants_LOG_UPTO, 1);
-
-#define rb_define_syslog_const(id) \
- rb_define_const(mSyslogConstants, #id, INT2NUM(id))
-
- /* Various options when opening log */
-#ifdef LOG_PID
- rb_define_syslog_const(LOG_PID);
-#endif
-#ifdef LOG_CONS
- rb_define_syslog_const(LOG_CONS);
-#endif
-#ifdef LOG_ODELAY
- rb_define_syslog_const(LOG_ODELAY); /* deprecated */
-#endif
-#ifdef LOG_NDELAY
- rb_define_syslog_const(LOG_NDELAY);
-#endif
-#ifdef LOG_NOWAIT
- rb_define_syslog_const(LOG_NOWAIT); /* deprecated */
-#endif
-#ifdef LOG_PERROR
- rb_define_syslog_const(LOG_PERROR);
-#endif
-
- /* Various syslog facilities */
-#ifdef LOG_AUTH
- rb_define_syslog_const(LOG_AUTH);
-#endif
-#ifdef LOG_AUTHPRIV
- rb_define_syslog_const(LOG_AUTHPRIV);
-#endif
-#ifdef LOG_CONSOLE
- rb_define_syslog_const(LOG_CONSOLE);
-#endif
-#ifdef LOG_CRON
- rb_define_syslog_const(LOG_CRON);
-#endif
-#ifdef LOG_DAEMON
- rb_define_syslog_const(LOG_DAEMON);
-#endif
-#ifdef LOG_FTP
- rb_define_syslog_const(LOG_FTP);
-#endif
-#ifdef LOG_KERN
- rb_define_syslog_const(LOG_KERN);
-#endif
-#ifdef LOG_LPR
- rb_define_syslog_const(LOG_LPR);
-#endif
-#ifdef LOG_MAIL
- rb_define_syslog_const(LOG_MAIL);
-#endif
-#ifdef LOG_NEWS
- rb_define_syslog_const(LOG_NEWS);
-#endif
-#ifdef LOG_NTP
- rb_define_syslog_const(LOG_NTP);
-#endif
-#ifdef LOG_SECURITY
- rb_define_syslog_const(LOG_SECURITY);
-#endif
-#ifdef LOG_SYSLOG
- rb_define_syslog_const(LOG_SYSLOG);
-#endif
-#ifdef LOG_USER
- rb_define_syslog_const(LOG_USER);
-#endif
-#ifdef LOG_UUCP
- rb_define_syslog_const(LOG_UUCP);
-#endif
-#ifdef LOG_LOCAL0
- rb_define_syslog_const(LOG_LOCAL0);
-#endif
-#ifdef LOG_LOCAL1
- rb_define_syslog_const(LOG_LOCAL1);
-#endif
-#ifdef LOG_LOCAL2
- rb_define_syslog_const(LOG_LOCAL2);
-#endif
-#ifdef LOG_LOCAL3
- rb_define_syslog_const(LOG_LOCAL3);
-#endif
-#ifdef LOG_LOCAL4
- rb_define_syslog_const(LOG_LOCAL4);
-#endif
-#ifdef LOG_LOCAL5
- rb_define_syslog_const(LOG_LOCAL5);
-#endif
-#ifdef LOG_LOCAL6
- rb_define_syslog_const(LOG_LOCAL6);
-#endif
-#ifdef LOG_LOCAL7
- rb_define_syslog_const(LOG_LOCAL7);
-#endif
-
-#define rb_define_syslog_shortcut(name) \
- rb_define_module_function(mSyslog, #name, mSyslog_##name, -1)
-
- /* Various syslog priorities and the shortcut methods */
-#ifdef LOG_EMERG
- rb_define_syslog_const(LOG_EMERG);
- rb_define_syslog_shortcut(emerg);
-#endif
-#ifdef LOG_ALERT
- rb_define_syslog_const(LOG_ALERT);
- rb_define_syslog_shortcut(alert);
-#endif
-#ifdef LOG_CRIT
- rb_define_syslog_const(LOG_CRIT);
- rb_define_syslog_shortcut(crit);
-#endif
-#ifdef LOG_ERR
- rb_define_syslog_const(LOG_ERR);
- rb_define_syslog_shortcut(err);
-#endif
-#ifdef LOG_WARNING
- rb_define_syslog_const(LOG_WARNING);
- rb_define_syslog_shortcut(warning);
-#endif
-#ifdef LOG_NOTICE
- rb_define_syslog_const(LOG_NOTICE);
- rb_define_syslog_shortcut(notice);
-#endif
-#ifdef LOG_INFO
- rb_define_syslog_const(LOG_INFO);
- rb_define_syslog_shortcut(info);
-#endif
-#ifdef LOG_DEBUG
- rb_define_syslog_const(LOG_DEBUG);
- rb_define_syslog_shortcut(debug);
-#endif
-}
diff --git a/ext/syslog/syslog.txt b/ext/syslog/syslog.txt
deleted file mode 100644
index 9aed35133d..0000000000
--- a/ext/syslog/syslog.txt
+++ /dev/null
@@ -1,121 +0,0 @@
-.\" syslog.txt - -*- Indented-Text -*-
-$RoughId: syslog.txt,v 1.18 2002/02/25 08:20:14 knu Exp $
-$Id$
-
-UNIX Syslog extension for Ruby
-Amos Gouaux, University of Texas at Dallas
-<amos+ruby@utdallas.edu>
-&
-Akinori MUSHA
-<knu@ruby-lang.org>
-
-** Syslog(Module)
-
-Included Modules: Syslog::Constants
-
-require 'syslog'
-
-A Simple wrapper for the UNIX syslog system calls that might be handy
-if you're writing a server in Ruby. For the details of the syslog(8)
-architecture and constants, see the syslog(3) manual page of your
-platform.
-
-Module Methods:
-
- open(ident = $0, logopt = Syslog::LOG_PID | Syslog::LOG_CONS,
- facility = Syslog::LOG_USER) [{ |syslog| ... }]
-
- Opens syslog with the given options and returns the module
- itself. If a block is given, calls it with an argument of
- itself. If syslog is already opened, raises RuntimeError.
-
- Example:
- Syslog.open('ftpd', Syslog::LOG_PID | Syslog::LOG_NDELAY,
- Syslog::LOG_FTP)
-
- open!(ident = $0, logopt = Syslog::LOG_PID | Syslog::LOG_CONS,
- facility = Syslog::LOG_USER)
- reopen(ident = $0, logopt = Syslog::LOG_PID | Syslog::LOG_CONS,
- facility = Syslog::LOG_USER)
-
- Same as open, but does a close first.
-
- opened?
-
- Returns true if syslog opened, otherwise false.
-
- ident
- options
- facility
-
- Returns the parameters given in the last open, respectively.
- Every call of Syslog::open resets these values.
-
- log(pri, message, ...)
-
- Writes message to syslog.
-
- Example:
- Syslog.log(Syslog::LOG_CRIT, "the sky is falling in %d seconds!", 10)
-
- crit(message, ...)
- emerg(message, ...)
- alert(message, ...)
- err(message, ...)
- warning(message, ...)
- notice(message, ...)
- info(message, ...)
- debug(message, ...)
-
- These are shortcut methods of Syslog::log(). The lineup may
- vary depending on what priorities are defined on your system.
-
- Example:
- Syslog.crit("the sky is falling in %d seconds!", 5)
-
- mask
- mask=(mask)
-
- Returns or sets the log priority mask. The value of the mask
- is persistent and will not be reset by Syslog::open or
- Syslog::close.
-
- Example:
- Syslog.mask = Syslog::LOG_UPTO(Syslog::LOG_ERR)
-
- close
-
- Closes syslog.
-
- inspect
-
- Returns the "inspect" string of the Syslog module.
-
- instance
-
- Returns the module itself. (Just for backward compatibility)
-
- LOG_MASK(pri)
-
- Creates a mask for one priority.
-
- LOG_UPTO(pri)
-
- Creates a mask for all priorities up to pri.
-
-** Syslog::Constants(Module)
-
-require 'syslog'
-include Syslog::Constants
-
-This module includes the LOG_* constants available on the system.
-
-Module Methods:
-
- LOG_MASK(pri)
-
- Creates a mask for one priority.
-
- LOG_UPTO(pri)
-
- Creates a mask for all priorities up to pri.
diff --git a/ext/syslog/test.rb b/ext/syslog/test.rb
deleted file mode 100644
index cfa33eff8f..0000000000
--- a/ext/syslog/test.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/env ruby
-# $RoughId: test.rb,v 1.9 2002/02/25 08:20:14 knu Exp $
-# $Id$
-
-# Please only run this test on machines reasonable for testing.
-# If in doubt, ask your admin.
-
-require 'test/unit'
-
-# Prepend current directory to load path for testing.
-$:.unshift('.')
-
-require 'syslog'
-
-class TestSyslog < Test::Unit::TestCase
- def test_new
- assert_raises(NoMethodError) {
- Syslog.new
- }
- end
-
- def test_instance
- sl1 = Syslog.instance
- sl2 = Syslog.open
- sl3 = Syslog.instance
-
- assert_equal(Syslog, sl1)
- assert_equal(Syslog, sl2)
- assert_equal(Syslog, sl3)
- ensure
- Syslog.close if Syslog.opened?
- end
-
- def test_open
- # default parameters
- Syslog.open
-
- assert_equal($0, Syslog.ident)
- assert_equal(Syslog::LOG_PID | Syslog::LOG_CONS, Syslog.options)
- assert_equal(Syslog::LOG_USER, Syslog.facility)
-
- # open without close
- assert_raises(RuntimeError) {
- Syslog.open
- }
-
- Syslog.close
-
- # given parameters
- Syslog.open("foo", Syslog::LOG_NDELAY | Syslog::LOG_PERROR, Syslog::LOG_DAEMON)
-
- assert_equal('foo', Syslog.ident)
- assert_equal(Syslog::LOG_NDELAY | Syslog::LOG_PERROR, Syslog.options)
- assert_equal(Syslog::LOG_DAEMON, Syslog.facility)
-
- Syslog.close
-
- # default parameters again (after close)
- Syslog.open
- Syslog.close
-
- assert_equal(nil, Syslog.ident)
- assert_equal(nil, Syslog.options)
- assert_equal(nil, Syslog.facility)
-
- # block
- param = nil
- Syslog.open { |param| }
- assert_equal(Syslog, param)
- ensure
- Syslog.close if Syslog.opened?
- end
-
- def test_opened?
- assert_equal(false, Syslog.opened?)
-
- Syslog.open
- assert_equal(true, Syslog.opened?)
-
- Syslog.close
- assert_equal(false, Syslog.opened?)
-
- Syslog.open {
- assert_equal(true, Syslog.opened?)
- }
-
- assert_equal(false, Syslog.opened?)
- end
-
- def test_close
- assert_raises(RuntimeError) {
- Syslog.close
- }
- end
-
- def test_mask
- assert_equal(nil, Syslog.mask)
-
- Syslog.open
-
- orig = Syslog.mask
-
- Syslog.mask = Syslog.LOG_UPTO(Syslog::LOG_ERR)
- assert_equal(Syslog.LOG_UPTO(Syslog::LOG_ERR), Syslog.mask)
-
- Syslog.mask = Syslog.LOG_MASK(Syslog::LOG_CRIT)
- assert_equal(Syslog.LOG_MASK(Syslog::LOG_CRIT), Syslog.mask)
-
- Syslog.mask = orig
- ensure
- Syslog.close if Syslog.opened?
- end
-
- def test_log
- stderr = IO::pipe
-
- pid = fork {
- stderr[0].close
- STDERR.reopen(stderr[1])
- stderr[1].close
-
- options = Syslog::LOG_PERROR | Syslog::LOG_NDELAY
-
- Syslog.open("syslog_test", options) { |sl|
- sl.log(Syslog::LOG_NOTICE, "test1 - hello, %s!", "world")
- sl.notice("test1 - hello, %s!", "world")
- }
-
- Syslog.open("syslog_test", options | Syslog::LOG_PID) { |sl|
- sl.log(Syslog::LOG_CRIT, "test2 - pid")
- sl.crit("test2 - pid")
- }
- exit!
- }
-
- stderr[1].close
- Process.waitpid(pid)
-
- # LOG_PERROR is not yet implemented on Cygwin.
- return if RUBY_PLATFORM =~ /cygwin/
-
- 2.times {
- assert_equal("syslog_test: test1 - hello, world!\n", stderr[0].gets)
- }
-
- 2.times {
- assert_equal(format("syslog_test[%d]: test2 - pid\n", pid), stderr[0].gets)
- }
- end
-
- def test_inspect
- Syslog.open { |sl|
- assert_equal(format('<#%s: opened=true, ident="%s", options=%d, facility=%d, mask=%d>',
- Syslog,
- sl.ident,
- sl.options,
- sl.facility,
- sl.mask),
- sl.inspect)
- }
-
- assert_equal(format('<#%s: opened=false>', Syslog), Syslog.inspect)
- end
-end
diff --git a/ext/tk/.cvsignore b/ext/tk/.cvsignore
deleted file mode 100644
index 44e7f262dc..0000000000
--- a/ext/tk/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-mkmf.log
-*.log
diff --git a/ext/tk/ChangeLog.tkextlib b/ext/tk/ChangeLog.tkextlib
deleted file mode 100644
index fa5524da01..0000000000
--- a/ext/tk/ChangeLog.tkextlib
+++ /dev/null
@@ -1,858 +0,0 @@
-2005-12-11 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/SUPPORT_STATUS: update to support libraries in
- ActiveTcl8.4.12.0.
-
- * lib/tkextlib/tile/tnotebook.rb: add Tk::Tile::TNotebook#insert.
-
- * sample/tkextlib/tile/demo.rb: improve the look of a part of the demo.
-
-2005-11-25 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * sample/tkextlib/tile/demo.rb: bug fix
-
- * sample/tkextlib/tile/themes/*: add some themes (blue,
- keramik, and plastik; require Tile-0.5 or later).
-
-2005-11-22 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/tile.rb: bug fix (Tk::Tile::USE_TTK_NAMESPACE
- is not defined).
-
-2005-11-19 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * sample/tkextlib/treectrl/demo.rb: remove dependency on Ruby's
- version (1.8 or 1.9).
-
-2005-10-23 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/*: update to support ActiveTcl8.4.11.2
-
- * lib/tkextlib/trofs/*: support Trofs 0.4.3
-
- * lib/tkextlib/tile/*: support Tile 0.7.2
-
- * lib/tkextlib/vu/*: support vu 2.3.0
-
- * lib/tkextlib/tcllib/*: support Tcllib 1.8 (Tklib 0.3 part only)
-
- * lib/tkextlib/*: improve conversion of option values
-
-2005-10-04 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/tktable/tktable.rb: border_* instance methods
- don't call 'border' subcommands.
-
-2005-08-10 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/blt/component.rb: didn't check
- __item_ruby2val_optkeys().
-
-2005-08-09 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/blt/barchart.rb: support to treat tkvariable-type
- configure options.
-
- * lib/tkextlib/blt/component.rb: ditto.
-
- * lib/tkextlib/blt/dragdrop.rb: ditto.
-
- * lib/tkextlib/blt/treeview.rb: ditto.
-
- * lib/tkextlib/bwidget/button.rb: ditto.
-
- * lib/tkextlib/bwidget/entry.rb: ditto.
-
- * lib/tkextlib/bwidget/label.rb: ditto.
-
- * lib/tkextlib/bwidget/labelentry.rb: ditto.
-
- * lib/tkextlib/bwidget/labelframe.rb: ditto.
-
- * lib/tkextlib/bwidget/mainframe.rb: ditto.
-
- * lib/tkextlib/bwidget/passwddlg.rb: ditto.
-
- * lib/tkextlib/bwidget/spinbox.rb: ditto.
-
- * lib/tkextlib/bwidget/tree.rb: ditto.
-
- * lib/tkextlib/iwidgets/calendar.rb: ditto.
-
- * lib/tkextlib/iwidgets/entryfield.rb: ditto.
-
- * lib/tkextlib/iwidgets/hierarchy.rb: ditto.
-
- * lib/tkextlib/iwidgets/labeledframe.rb: ditto.
-
- * lib/tkextlib/iwidgets/labeledwidget.rb: ditto.
-
- * lib/tkextlib/iwidgets/menubar.rb: ditto.
-
- * lib/tkextlib/iwidgets/scrolledlistbox.rb: ditto.
-
- * lib/tkextlib/iwidgets/spinner.rb: ditto.
-
- * lib/tkextlib/iwidgets/toolbar.rb: ditto.
-
- * lib/tkextlib/tkimg/pixmap.rb: ditto.
-
- * lib/tkextlib/tktable/tktable.rb: ditto.
-
-2005-08-06 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/tile/demo.rb: use Tk::Tile::Scale#variable.
-
-2005-08-04 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/tile/demo.rb: followed previous changes.
-
-2005-08-04 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/tile/t*.rb: aliased class names starting with 'T'
- to non 'T' ones. (ie. Tk::Tile::TButton -> Tk::Tile::Button)
- [ruby-dev:26724]
-
- * lib/tkextlib/tile.rb: ditto. (autoload support)
-
-2005-08-04 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/tile/demo.rb: fixed: Tk::Tile::TProgressbar is
- supported on tile 0.6 or later, not tile 0.5.
-
- * sample/tkextlib/tile/demo.rb: updated scales demo to use
- Tk::Tile::TProgressbar for tile 0.6 or later.
-
- * sample/tkextlib/tile/demo.rb: set some TkVariable default values.
-
-2005-08-03 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/tile/treeview.rb: Tk::Tile::Treeview#headingconfigure
- is now working and more. [ruby-dev:26716]
-
- * sample/tkextlib/tile/demo.rb: use Tk::Tile::Treeview#headingconfigure instead of direct Tk.tk_call.
-
-2005-08-02 ocean <ocean@ruby-lang.org>
-
- * lib/tkextlib/tile/tprogressbar.rb: Tk::Tile::TProgressbar#start
- takes optional argument `interval'.
-
- * sample/tkextlib/tile/demo.rb: emulate Tk::Tile::TProgressbar
- with Tk::Tile::TProgress in tile 0.4. (repeating buttons demo)
-
-2005-08-02 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/tile/demo.rb: added repeating buttons demo.
-
- * sample/tkextlib/tile/repeater.tcl: ditto. (new file)
-
-2005-08-01 ocean <ocean@ruby-lang.org>
-
- * lib/tkextlib/tile.rb: fixed autoload for Treeview.
-
- * lib/tkextlib/tile/treeview.rb: replaced `ary2tk_list(items)' with
- `*items'.
-
- * sample/tkextlib/tile/demo.rb: added treeview demo. (tile 0.5 or
- later is required) [ruby-dev:26668]
-
-2005-08-01 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/tile/demo.rb: added combobox demo.
-
-2005-07-27 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/tile/demo.rb: fixed typo.
-
-2005-06-16 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/SUPPOPRT_STATUS: add RELEASE_DATE information.
-
- * lib/tkextlib/tile/style.rb: add "style element options <elem>"
- command support.
-
-2005-06-08 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/ICONS/icons.rb: fail to create instances of
- Tk::ICONS [ruby-dev:26305].
-
-2005-06-07 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/tile/themes/kroc.{rb,tcl}: also support tile 0.4.
-
-2005-06-07 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/tile/themes/kroc.{rb,tcl}: support tile 0.5 or later.
- ("pixmap" element constructor replaced by "image")
-
-2005-06-05 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * sample/tkextlib/tile/demo.rb: fix TypeError & create Console
-
-2005-05-30 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/blt.rb: add PACKAGE_NAME information of Tcl/Tk
- Extension.
-
- * lib/tkextlib/bwidget.rb: ditto.
-
- * lib/tkextlib/iwidgets.rb: ditto.
-
- * lib/tkextlib/tile.rb: ditto.
-
- * lib/tkextlib/tkimg.rb: ditto.
-
- * lib/tkextlib/vu.rb: ditto.
-
- * lib/tkextlib/ICONS/icons.rb: ditto.
-
- * lib/tkextlib/itcl/incr_tcl.rb: ditto.
-
- * lib/tkextlib/itk/incr_tk.rb: ditto.
-
- * lib/tkextlib/tcllib/autoscroll.rb: ditto.
-
- * lib/tkextlib/tcllib/ctext.rb: ditto.
-
- * lib/tkextlib/tcllib/cursor.rb: ditto.
-
- * lib/tkextlib/tcllib/datefield.rb: ditto.
-
- * lib/tkextlib/tcllib/ico.rb: ditto.
-
- * lib/tkextlib/tcllib/ip_entry.rb: ditto.
-
- * lib/tkextlib/tcllib/plotchart.rb: ditto.
-
- * lib/tkextlib/tcllib/style.rb: ditto.
-
- * lib/tkextlib/tcllib/tkpiechart.rb: ditto.
-
- * lib/tkextlib/tclx/tclx.rb: ditto.
-
- * lib/tkextlib/tkDND/shape.rb: ditto.
-
- * lib/tkextlib/tkDND/tkdnd.rb: ditto.
-
- * lib/tkextlib/tkHTML/htmlwidget.rb: ditto.
-
- * lib/tkextlib/tkimg/bmp.rb: ditto.
-
- * lib/tkextlib/tkimg/gif.rb: ditto.
-
- * lib/tkextlib/tkimg/ico.rb: ditto.
-
- * lib/tkextlib/tkimg/jpeg.rb: ditto.
-
- * lib/tkextlib/tkimg/pcx.rb: ditto.
-
- * lib/tkextlib/tkimg/pixmap.rb: ditto.
-
- * lib/tkextlib/tkimg/png.rb: ditto.
-
- * lib/tkextlib/tkimg/ppm.rb: ditto.
-
- * lib/tkextlib/tkimg/ps.rb: ditto.
-
- * lib/tkextlib/tkimg/sgi.rb: ditto.
-
- * lib/tkextlib/tkimg/sun.rb: ditto.
-
- * lib/tkextlib/tkimg/tga.rb: ditto.
-
- * lib/tkextlib/tkimg/tiff.rb: ditto.
-
- * lib/tkextlib/tkimg/window.rb: ditto.
-
- * lib/tkextlib/tkimg/xbm.rb: ditto.
-
- * lib/tkextlib/tkimg/xpm.rb: ditto.
-
- * lib/tkextlib/tktable/tktable.rb: ditto.
-
- * lib/tkextlib/tktrans/tktrans.rb: ditto.
-
- * lib/tkextlib/treectrl/tktreectrl.rb: ditto.
-
- * lib/tkextlib/winico/winico.rb: ditto.
-
-2005-05-25 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/iwidgets/scrolledlistbox.rb: follow the change
- of tk.rb. modify to attend encoding.
-
- * lib/tkextlib/iwidgets/scrolledtext.rb: ditto.
-
- * lib/tkextlib/iwidgets/scrolledcanvas.rb: bug fix on
- TkCanvas#delete when given non-TkcItem arguments.
-
-2005-05-10 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/blt/winop.rb: fix typo
-
-2005-05-08 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/vu/pie.rb: fix typo
-
-2005-04-10 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/treectrl/mailwasher.rb: fixed typo. [ruby-dev:26008]
-
-2005-04-09 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * sample/tkextlib/tile/demo.rb: new demo of Tile extension.
-
- * sample/tkextlib/tile/iconlib.tcl: part of the demo.
-
- * sample/tkextlib/tile/toolbutton.tcl: ditto.
-
- * sample/tkextlib/tile/readme.txt: document of the demo.
-
- * sample/tkextlib/tile/Orig_LICENSE.txt: ditto.
-
- * sample/tkextlib/tile/themes/kroc.tcl: sample theme written with Tcl.
-
- * sample/tkextlib/tile/themes/pkgIndex.tcl: pkgIndex of kroc.tcl.
-
- * sample/tkextlib/tile/themes/kroc.rb: Kroc theme written with Ruby.
-
- * sample/tkextlib/tile/themes/kroc/button-h.gif: images for Kroc theme.
-
- * sample/tkextlib/tile/themes/kroc/button-n.gif: ditto.
-
- * sample/tkextlib/tile/themes/kroc/button-p.gif: ditto.
-
- * sample/tkextlib/tile/themes/kroc/check-hc.gif: ditto.
-
- * sample/tkextlib/tile/themes/kroc/check-hu.gif: ditto.
-
- * sample/tkextlib/tile/themes/kroc/check-nc.gif: ditto.
-
- * sample/tkextlib/tile/themes/kroc/check-nu.gif: ditto.
-
- * sample/tkextlib/tile/themes/kroc/radio-hc.gif: ditto.
-
- * sample/tkextlib/tile/themes/kroc/radio-hu.gif: ditto.
-
- * sample/tkextlib/tile/themes/kroc/radio-nc.gif: ditto.
-
- * sample/tkextlib/tile/themes/kroc/radio-nu.gif: ditto.
-
- * lib/tkextlib/tile.rb: bug fix (tested on the new demo).
-
- * lib/tkextlib/tile/style.rb: ditto.
-
- * lib/tkextlib/tile/tbutton.rb: ditto.
-
- * lib/tkextlib/tile/tcheckbutton.rb: ditto.
-
- * lib/tkextlib/tile/tcombobox.rb: ditto.
-
- * lib/tkextlib/tile/tentry.rb: ditto.
-
- * lib/tkextlib/tile/tframe.rb: ditto.
-
- * lib/tkextlib/tile/tlabel.rb: ditto.
-
- * lib/tkextlib/tile/tlabelframe.rb: ditto.
-
- * lib/tkextlib/tile/tmenubutton.rb: ditto.
-
- * lib/tkextlib/tile/tnotebook.rb: ditto.
-
- * lib/tkextlib/tile/tprogressbar.rb: ditto.
-
- * lib/tkextlib/tile/tradiobutton.rb: ditto.
-
- * lib/tkextlib/tile/treeview.rb: ditto.
-
- * lib/tkextlib/tile/tscrollbar.rb: ditto.
-
- * lib/tkextlib/tile/tseparator.rb: ditto.
-
- * lib/tkextlib/tile/tsquare.rb: ditto.
-
- * lib/tkextlib/tile/tpaned.rb: new library
-
- * lib/tkextlib/tile/tscale.rb: ditto.
-
- * lib/tkextlib/SUPPORT_STATUS: update support status of Tile extension.
-
- * lib/tkextlib/tcllib/ctext.rb: use TkCommandNames on create_self().
-
- * lib/tkextlib/tcllib/datefield.rb: ditto.
-
- * lib/tkextlib/tcllib/ip_entry.rb: ditto.
-
- * lib/tkextlib/tkHTML/htmlwidget.rb: ditto.
-
- * lib/tkextlib/treectrl/tktreectrl.rb: ditto.
-
-2005-04-09 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/treectrl/explorer.rb: File.executable? returns true
- even if it's plain text file. (this function only checks access right)
-
-2005-04-09 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/treectrl/{help,www-options}.rb: fixed typo.
- (click or resize column header)
-
-2005-04-09 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/treectrl/imovie.rb: fixed typo. (click on clip title)
-
-2005-04-08 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/treectrl/random.rb: fixed typo. (drop node outside of
- widget, or reenter widget while draggging)
-
-2005-04-08 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/treectrl/outlook-newgrounp.rb: image had disappered when
- node was selected.
-
-2005-04-08 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/treectrl/{random,outlook-newgroup}.rb:
- tk::treectrl uses 'afterId' not 'afterID'.
-
- * sample/tkextlib/treectrl/{random,outlook-newgroup}.rb:
- item_firstchild can return empty string. (drop node to leaf node)
-
- * sample/tkextlib/treectrl/random.rb: Enumerable#find didn't work properly
- because tried to compare String with Integer. (drag node and leave widget)
-
- * sample/tkextlib/treectrl/random.rb: and some fixes.
-
-2005-04-08 ocean <ocean@ruby-lang.org>
-
- * lib/tkextlib/treectrl/tktreectrl.rb (selection_clear): fixed typo.
-
- * sample/tkextlib/treectrl/random.rb: node deselection now works.
-
- * sample/tkextlib/treectrl/demo.rb: fixed typo. (popup menu on column header)
-
-2005-04-08 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/treectrl/help.rb: fixed typo. (wrong color)
-
-2005-04-08 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/treectrl/random.rb: fixed typo. (wrong itemheight)
-
- * sample/tkextlib/treectrl/outlook-newgroup.rb: ditto.
-
- * sample/tkextlib/treectrl/explorer.rb: ditto.
-
- * sample/tkextlib/treectrl/help.rb: ditto.
-
-2005-04-07 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/treectrl/*.rb: some speed up... cache the result of
- version checking.
-
-2005-04-07 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/treectrl/tktreectrl.rb: performance tuning by calling
- tk_send_without_enc. [ruby-dev:25997]
-
-2005-04-04 ocean <ocean@ruby-lang.org>
-
- * lib/tkextlib/tktable/tktable.rb: added Tk::TkTable#selection_present.
-
-2005-04-02 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/treectrl/tktreectrl.rb: support TreeCtrl's cvs head.
-
-2005-04-02 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/blt/component.rb: add TreeCtrl#legend_window_create().
-
- * sample/tkextlib/blt/graph6.rb: use legend_window_create().
-
- * lib/tkextlib/blt/tree.rb: forget to call tagid().
-
- * lib/tkextlib/blt/treeview.rb: ditto.
-
-2005-04-01 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * sample/tkextlib/treectrl/demo.rb: bridge the gap of
- Hash#index or Hash#key between ruby 1.8 and 1.9
-
-2005-04-01 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/blt/component.rb: bug fix on treatment of
- component objects.
-
- * sample/tkextlib/blt/graph6.rb: a new sample script.
-
-2005-03-31 ocean <ocean@ruby-lang.org>
-
- * sample/tkextlib/treectrl/demo.rb: should use Hash#index.
-
- * sample/tkextlib/treectrl/demo.rb: TkImage was not
- cached properly.
-
- * sample/tkextlib/treectrl/random.rb: fixed typo.
-
-2005-03-31 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * sample/tkextlib/iwidgets/sample/hierarchy.rb: show basename
- only [ruby-dev:25970]
-
- * sample/tkextlib/treectrl/demo.rb: add check for existence of
- 'backgroundimage' option.
-
- * sample/tkextlib/treectrl/bitmaps.rb: ditto.
-
- * sample/tkextlib/treectrl/outlook-newgroup.rb: lack of '%I'
- event callback argument.
-
-2005-03-31 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * sample/tkextlib/iwidgets/sample/hierarchy.rb: fail to treat
- Japanese (i18n?) filenames.
-
-2005-03-30 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * sample/tkextlib/bwidget/tree.rb: use 'return' in the Proc object.
-
- * sample/tkextlib/tkHTML/hv.rb: ditto.
-
- * sample/tkextlib/tkHTML/ss.rb: ditto.
-
- * sample/tkextlib/tktable/basic.rb: ditto.
-
- * sample/tkextlib/tktable/command.rb: ditto.
-
- * sample/tkextlib/tktable/debug.rb: ditto.
-
- * sample/tkextlib/tktable/maxsize.rb: ditto.
-
- * sample/tkextlib/treectrl/demo.rb: ditto.
-
-2005-03-29 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/blt/component.rb: cannot create elements except
- default type of element.
-
- * lib/tkextlib/blt/barchart.rb: ditto.
-
- * lib/tkextlib/blt/graph.rb: ditto.
-
- * lib/tkextlib/blt/stripchart.rb: ditto.
-
- * lib/tkextlib/blt/component.rb: axis command option gets
- proper object type of arguments.
-
- * sample/tkextlib/blt/calendar.rb: new sample.
-
- * sample/tkextlib/blt/pareto.rb: ditto.
-
-2005-03-28 ocean <ocean@ruby-lang.org>
-
- * lib/tkextlib/iwidgets/notebook.rb: fixed typo.
-
-2005-03-26 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/blt.rb: add commands for zooming.
-
- * lib/tkextlib/blt/bitmap.rb (new_with_name): add for using
- given name.
-
- * lib/tkextlib/blt/busy.rb: bug fix on Tk::BLT::Busy::Shild class.
-
- * lib/tkextlib/blt/component.rb: typo fix.
-
- * lib/tkextlib/blt/component.rb: fix lack of *_create methods
-
- * lib/tkextlib/blt/component.rb: proper call on xaxis_* and so on.
-
- * lib/tkextlib/blt/htext.rb: add TkVariable object to access
- special Tcl variables.
-
- * lib/tkextlib/treectrl/tktreectrl.rb: typo fix.
-
- * lib/tkextlib/treectrl/tktreectrl.rb: proper treatment
- of 'font' option of element_configure.
-
- * lib/tkextlib/treectrl/tktreectrl.rb: bug fix on item_sort.
-
- * lib/tkextlib/treectrl/tktreectrl.rb: add methods to
- call TreeCtrl commands for bindings.
-
- * sample/tkextlib/blt/*: add some sample scripts.
-
- * sample/tkextlib/treectrl/*: add some sample scripts.
-
-2005-03-18 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/treectrl/tktreectrl.rb: bug fix and define some
- classes for components of Tk::TreeCtrl
-
-2005-03-17 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/treectrl/tktreectrl.rb: call wrong method in
- Tk::TreeCtrl#*_configinfo and current_*_configinfo method
-
-2005-03-16 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/SUPPORT_STATUS: change the status of TkImg
-
- * lib/tkextlib/treectrl/tktreectrl.rb: bug fix and support
- TkTreeCtrl-1.1
-
- * lib/tkextlib/SUPPORT_STATUS: change the supported version of
- TkTreeCtrl
-
-2005-03-15 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * sample/tkextlib/tkimg: add sample
-
-2005-03-06 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/SUPPORT_STATUS: add version info of each extension
-
-2005-03-05 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/tile.rb: lack of "autoload TProgressbar"
-
-2005-03-05 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/tile.rb: support tile-0.6
-
- * lib/tkextlib/tile/tbutton.rb: ditto
-
- * lib/tkextlib/tile/tcheckbutton.rb: ditto
-
- * lib/tkextlib/tile/tlabel.rb: ditto
-
- * lib/tkextlib/tile/tmenubutton.rb: ditto
-
- * lib/tkextlib/tile/tnotebook.rb: ditto
-
- * lib/tkextlib/tile/tradiobutton.rb: ditto
-
- * lib/tkextlib/tile/tcombobox.rb: [new] ditto
-
- * lib/tkextlib/tile/tentry.rb: [new] ditto
-
- * lib/tkextlib/tile/tframe.rb: [new] ditto
-
- * lib/tkextlib/tile/tlabelframe.rb: [new] ditto
-
- * lib/tkextlib/tile/tprogressbar.rb: [new] ditto
-
- * lib/tkextlib/tile/treeview.rb: [new] ditto
-
- * lib/tkextlib/tile/tscrollbar.rb: [new] ditto
-
- * lib/tkextlib/tile/tseparator.rb: [new] ditto
-
- * lib/tkextlib/tile/tsquare.rb: [new] ditto
-
-2005-02-20 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/tclx/tclx.rb: warning TclX's 'signal' command.
-
-2005-01-25 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/blt/component.rb: bug fix. cannot accept
- a callback ID string for a command argument. [ruby-dev:25479]
-
- * lib/tkextlib/blt/tabset.rb: ditto
-
- * lib/tkextlib/blt/treeview.rb: ditto
-
- * lib/tkextlib/bwidget/labelentry.rb: ditto
-
- * lib/tkextlib/bwidget/listbox.rb: ditto
-
- * lib/tkextlib/bwidget/notebook.rb: ditto
-
- * lib/tkextlib/bwidget/spinbox.rb: ditto
-
- * lib/tkextlib/bwidget/tree.rb: ditto
-
- * lib/tkextlib/itk/incr_tk.rb: ditto
-
- * lib/tkextlib/iwidgets/scrolledcanvas.rb: ditto
-
- * lib/tkextlib/tkDND/tkdnd.rb: ditto
-
- * lib/tkextlib/treectrl/tktreectrl.rb: ditto
-
- * sample/tkextlib/tkHTML/ss.rb: local variable scope bug fix
- [ruby-dev:25479]
-
- * sample/tkextlib/vu/vu_demo.rb: rename from vu.rb; avoid the bug on
- Windows version of Tcl/Tk. The trouble based on the bug occurs when
- the script name (without extension) is a same name as a Tcl/Tk's
- library file name (without extension) required in the script.
-
-2004-12-24 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/blt: add BLT extension support
-
-2004-12-16 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/bwidget/labelentry.rb: use TkCore.callback_obj?()
-
- * lib/tkextlib/bwidget/listbox.rb: ditto
-
- * lib/tkextlib/bwidget/notebook.rb: ditto
-
- * lib/tkextlib/bwidget/spinbox.rb: ditto
-
- * lib/tkextlib/itk/incr_tk.rb: ditto
-
- * lib/tkextlib/iwidgets/scrolledcanvas.rb: ditto
-
- * lib/tkextlib/tkDND/tkdnd.rb: ditto
-
- * lib/tkextlib/treectrl/tktreectrl.rb: ditto
-
- * lib/tkextlib/winico/winico.rb: ditto
-
-2004-12-10 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/tile/style.rb: 'theme_use' method bug fix
-
-2004-12-08 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/bwidget/notebook.rb: raise method cannot return
- the raised page.
-
- * lib/tkextlib/bwidget/labelentry.rb: bind methods accept
- subst_args + block
-
- * lib/tkextlib/bwidget/listbox.rb: ditto
-
- * lib/tkextlib/bwidget/notebook.rb: ditto
-
- * lib/tkextlib/bwidget/spinbox.rb: ditto
-
- * lib/tkextlib/bwidget/tree.rb: ditto
-
- * lib/tkextlib/itk/incr_tk.rb: ditto
-
- * lib/tkextlib/iwidgets/scrolledcanvas.rb: ditto
-
- * lib/tkextlib/tkDND/tkdnd.rb: ditto
-
- * lib/tkextlib/treectrl/tktreectrl.rb: ditto
-
-2004-11-26 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/bwidget/notebook.rb: uses epath
-
- * lib/tkextlib/bwidget/widget.rb: ditto
-
- * lib/tkextlib/tktable/tktable.rb: ditto
-
- * lib/tkextlib/tcllib/cursor.rb: ditto, and bug fix
-
-2004-11-10 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/tile/style.rb: bug fix
-
-2004-11-07 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/iwidgets/scrolledcanvas.rb: bind-event methods
- accept multi substitution arguments.
-
- * lib/tkextlib/tktable/tktable.rb: ditto.
-
- * lib/tkextlib/treectrl/tktreectrl.rb: ditto
-
-2004-11-03 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/SUPPORT_STATUS: BLT moves to 'plan to support'
- from 'not determined'
-
- * lib/tkextlib/itk/incr_tk.rb: __cget_cmd and __config_cmd are
- private methods
-
- * lib/tkextlib/tcllib/autoscroll.rb: extend TkCore
-
- * lib/tkextlib/tcllib/cursor.rb: ditto.
-
- * lib/tkextlib/tcllib/plotchart.rb: ditto.
-
- * lib/tkextlib/tcllib/style.rb: ditto.
-
- * lib/tkextlib/tile/style.rb: ditto.
-
- * lib/tkextlib/tkDND/shape.rb: ditto.
-
-2004-10-24 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/bwidget/tree.rb: bug fix on Windows
-
-2004-10-16 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/tcllib/ico.rb: new library (Tk::Tcllib:ICO)
-
- * lib/tkextlib/tcllib.rb: add Tk::Tcllib::ICO (based on tcllib 1.7)
-
-2004-10-06 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/bwidget.rb (BWidget.grab): bug fix
-
- * lib/tkextlib/tcllib.rb: typo fix
-
-2004-07-28 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/add winico support
-
-2004-07-23 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * lib/tkextlib/add TclX support (partially; infox command and
- XPG/3 MsgCat only)
-
-2004-07-15 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * bug fix
-
- * support TkTable extension
-
-2004-07-12 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * bug fix
-
- * support Iwidgets extension
-
-2004-07-10 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * bug fix
-
- * add more part of [incr Widget] support (about 65%? are complete)
-
- * use Tk::ValidateConfigure.__def_validcmd() method
- (new function to define validatecommand methods easier)
-
- * tcllib.rb : avoid the loading trouble that almost all part of
- the extension is not available when some libraries are invalid.
-
-2004-07-09 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * add some part of [incr Widget] support (about 50%? are complete)
-
-2004-07-07 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * add [incr Tck], [incr Tk] support
-
-2004-07-06 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * support BWidget extension
-
- * add BWidget extension demo
-
- * add ICONS extension demo
-
- * many bug fix
-
-2004-07-01 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
- * 1st release of tkextlib ( to support Tcl/Tk extensions )
diff --git a/ext/tk/MANUAL_tcltklib.eng b/ext/tk/MANUAL_tcltklib.eng
deleted file mode 100644
index 1db61f228e..0000000000
--- a/ext/tk/MANUAL_tcltklib.eng
+++ /dev/null
@@ -1,445 +0,0 @@
-(tof)
- 2005/07/05 Hidetoshi NAGAI
-
-This document discribes about the 'tcltklib' library. Although there
-is the 'tcltk' library (tcltk.rb) under this directory, no description
-in this document (because it is not maintained recently).
-
-==============================================================
-module TclTklib
- : Defines methods to do operations which are independed on
- : Tcl/Tk interpreters
-
- module TclTkLib::EventFlag
- : Defines flags to define taget events on 'do_one_event' methos.
- : When to give, please use bit-operator (e.g. WINDOW | DONT_WAIT).
-
- [constants]
- NONE
- : Is 0. It means "there is no target". But on the real
- : operation, it is same to ALL.
-
- WINDOW
- : 'window' event is processed.
-
- FILE
- : 'file' event is processed.
-
- TIMER
- : 'timer' event is processed.
-
- IDLE
- : 'idle' operation (e.g. 're-draw'; the operations when the
- : other kinds of events doesn't occur) is processed.
-
- ALL
- : All kinds of events are processed.
- : Same to 'WINDOW | FILE | TIMER | IDLE'.
-
- DONT_WAIT
- : Without this flag, 'do_one_event' waits the occurence of
- : a target event. With this flag, doesn't wait and returns
- : false if there is no target event for processing.
-
- module TclTkLib::VarAccessFlag
- : Defines flags to give '_get_variable' and so on. When to give,
- : please use bit-operator (e.g. GLOBAL_ONLY | LEAVE_ERR_MSG ).
-
- [constants]
- NONE
- : Is 0. It means "set no flag".
-
- GLOBAL_ONLY
- : (site Tcl/Tk's man page)
- : Under normal circumstances the procedures look up
- : variables as follows: If a procedure call is active
- : in interp, a variable is looked up at the current
- : level of procedure call. Otherwise, a variable is
- : looked up first in the current namespace, then in
- : the global namespace. However, if this bit is set
- : in flags then the variable is looked up only in the
- : global namespace even if there is a procedure call
- : active. If both GLOBAL_ONLY and NAMESPACE_ONLY are
- : given, GLOBAL_ONLY is ignored.
- :
- : *** ATTENTION ***
- : Tcl7.6 doesn't have namespaces. So NAMESPACE_ONLY
- : is defined as 0, and then GLOBAL_ONLY is available
- : even if flag is (GLOBAL_ONLY | NAMESPACE_ONLY).
-
- NAMESPACE_ONLY
- : (site Tcl/Tk's man page)
- : Under normal circumstances the procedures look up
- : variables as follows: If a procedure call is active
- : in interp, a variable is looked up at the current
- : level of procedure call. Otherwise, a variable is
- : looked up first in the current namespace, then in
- : the global namespace. However, if this bit is set
- : in flags then the variable is looked up only in the
- : current namespace even if there is a procedure call
- : active.
- :
- : *** ATTENTION ***
- : Tcl7.6 doesn't have namespaces. So NAMESPACE_ONLY
- : is defined as 0.
-
- LEAVE_ERR_MSG
- : (site Tcl/Tk's man page)
- : If an error is returned and this bit is set in flags,
- : then an error message will be left in the interpreter's
- : result, where it can be retrieved with Tcl_GetObjResult
- : or Tcl_GetStringResult. If this flag bit isn't set then
- : no error message is left and the interpreter's result
- : will not be modified.
-
- APPEND_VALUE
- : (site Tcl/Tk's man page)
- : If this bit is set then newValue is appended to the
- : current value, instead of replacing it. If the variable
- : is currently undefined, then this bit is ignored.
-
- LIST_ELEMENT
- : (site Tcl/Tk's man page)
- : If this bit is set, then newValue is converted to a
- : valid Tcl list element before setting (or appending
- : to) the variable. A separator space is appended before
- : the new list element unless the list element is going
- : to be the first element in a list or sublist (i.e. the
- : variable's current value is empty, or contains the
- : single character ``{'', or ends in `` }'').
-
- PARSE_VARNAME
- : (site Tcl/Tk's man page)
- : If this bit is set when calling _set_variable and so
- : on, var_name argument may contain both an array and an
- : element name: if the name contains an open parenthesis
- : and ends with a close parenthesis, then the value
- : between the parentheses is treated as an element name
- : (which can have any string value) and the characters
- : before the first open parenthesis are treated as the
- : name of an array variable. If the flag PARSE_VARNAME
- : is given, index_name argument should be 'nil' since the
- : array and element names are taken from var_name.
- :
- : *** ATTENTION ***
- : Tcl7.6 doesn't have this flag. So PARSE_VARNAME is
- : defined as 0.
-
- [module methods]
- mainloop(check_root = true)
- : Starts the eventloop. If 'check_root' is true, this method
- : doesn't return when a root widget exists.
- : If 'check_root' is false, doen't return by the other
- : reasons than exceptions.
-
- mainloop_thread?
- : Returns whether the current thread executes the eventloop.
- : If true, the eventloop is working on the current thread.
- : If no eventloop is working, this method returns nil.
- : And if the other thread executes the eventloop, returns false.
- :
- : *** ATTENTION ***
- : When this methods returns false, it is dangerous to call a Tk
- : interpreter directly.
-
- mainloop_watchdog(check_root = true)
- : On the normal eventloop, some kinds of callback operations
- : cause deadlock. To avoid some of such deadlocks, this
- : method starts an eventloop and a watchdog-thread.
-
- do_one_event(flag = TclTkLib::EventFlag::ALL |
- TclTkLib::EventFlag::DONT_WAIT)
- : Do one event for processing. When processed an event,
- : returns true.
- : If NOT set DONT_WAIT flag, this method waits occurrence of
- : a target event.
- : If set DONT_WAIT flag and no event for processing, returns
- : false immediately.
- : If $SAFE >= 4, or $SAFE >= 1 and the flag is tainted,
- : force to set DONT_WAIT flag.
-
- set_eventloop_tick(timer_tick)
- : Define the interval of thread-switching with an integer
- : value of mili-seconds.
- : Default timer_tick is 0. It means that thread-switching
- : is based on the count of processed events.
- : ( see 'set_eventloop_weight' method )
- : However, if the eventloop thread is the only thread,
- : timer_tick cannt be set to 0. If 0, then is set to 100 ms
- : automatically (see NO_THREAD_INTERRUPT_TIME on tcltklib.c).
- : On $SAFE >= 4, cannot call this method.
-
- get_eventloop_tick
- : Get current value of 'timer_tick'
-
- set_no_event_wait(no_event_wait)
- : Define sleeping time of the eventloop when two or more
- : thread are running and there is no event for processing.
- : Default value is 20 (ms).
- : If the eventloop thread is the only thread, this value is
- : invalid.
- : On $SAFE >= 4, cannot call this method.
-
- get_no_event_wait
- : Get current value of 'no_event_wait'.
-
- set_eventloop_weight(loop_max, no_event_tick)
- : Define the weight parameters for the eventloop thread.
- : That is invalid when the eventloop is the only thread.
- : 'loop_max' is the max events for thread-switching.
- : 'no_event_tick' is the increment value of the event count
- : when no event for processing (And then, the eventloop thead
- : sleeps 'no_event_wait' mili-seconds).
- : 'loop_max == 800' and 'no_event_tick == 10' are defalut.
- : On $SAFE >= 4, cannot call this method.
-
- get_eventloop_weight
- : Get current values of 'loop_max' and 'no_event_tick'.
-
- mainloop_abort_on_exception=(bool)
- : Define whether the eventloop stops on exception or not.
- : If true (default value), stops on exception.
- : If false, show a warinig message but ignore the exception.
- : If nil, no warning message and ignore the excepsion.
- : This parameter is sometimes useful when multiple Tk
- : interpreters are working. Because the only one eventloop
- : admins all Tk interpreters, sometimes exception on a
- : interpreter kills the eventloop thread. Even if such
- : situation, when abort_on_exception == false or nil,
- : the eventloop ignores the exception and continue to working.
- : On $SAFE >= 4, cannot call this method.
-
- mainloop_abort_on_exception
- : Get current status of that.
-
- num_of_mainwindows
- : Returns the number of main-windows (root-widget).
- : Because there is only one main-window for one Tk interpreter,
- : the value is same to the number of interpreters which has
- : available Tk functions.
-
- _merge_tklist(str, str, ... )
- : Get a Tcl's list string from arguments with a Tcl/Tk's
- : library function. Each arguemnt is converted to a valid
- : Tcl list element.
-
- _conv_listelement(str)
- : Convert the argument to a valid Tcl list element with
- : Tcl/Tk's library function.
-
- _toUTF8(str, encoding=nil)
- _fromUTF8(str, encoding=nil)
- : Call the function (which is internal function of Tcl/Tk) to
- : convert to/from a UTF8 string.
-
- _subst_UTF_backslash(str)
- _subst_Tcl_backslash(str)
- : Substitute backslash sequence with Tcl's rule (include \uhhhh;
- : give a sixteen-bit hexadecimal value for Unicode character).
- : _subst_Tcl_backslash method parses all backslash sequence.
- : _subst_UTF_backslash method parses \uhhhh only.
-
- encoding_system
- encoding_system=(encoding)
- : Get and set Tcl's system encoding.
-
- encoding
- encoding=(encoding)
- : alias of encoding_system / encoding_system=
- : ( probably, Ruby/Tk's tk.rb will override them )
-
-
-class TclTkIp
- [class methods]
- new(ip_name=nil, options='')
- : Generate an instance of TclTkIp class.
- : If 'ip_name' argument is given as a string, it is the name
- : of the Tk interpreter which is shown by 'winfo interps'
- : command.
- : 'options' argument accepts a string which is the command
- : line options of wish; such as '-geometry' or '-use'.
- : The information is used to generate the root widget of the
- : interpreter.
- : ( e.g. TclTkIp.new('FOO', '-geometry 500x200 -use 0x2200009') )
- : If is given nil or falsr for the 'option' argument, generates
- : the Tcl interpreter without Tk library. Then the interpreter
- : doesn't need GUI environment. Therefore, even if a window
- : system doesn't exist or cannot be used, Ruby can control the
- : Tcl interpreter and the extention libraries loaded on the
- : interpreter.
-
- [instance methods]
- create_slave(name, safe=false)
- : Create a slave interpreter.
- : The parent of the interpreter is the receiver of this method.
- : The name of the slave interpreter is given by 'name' argument.
- : The 'safe' argument decides whether the slave interpreter is
- : created as a safe interpreter or not. If true, create a safe
- : interpreter. Default is false. However, if the parent
- : interpreter is a safe interpreter, the created interpreter is
- : a safe interpreter (ignore 'safe' argument value).
- : If $SAFE >= 4, can create a safe interpreter only.
-
- make_safe
- : Make the interpreter to the safe interpreter, and returns
- : self. If fail, raise RuntimeError.
-
- safe?
- : Check whether the interpreter is the safe interpreter.
- : If is the safe interpreter, returns true.
-
- allow_ruby_exit?
- : Return the mode whether 'exit' function of ruby or 'exit'
- : command of Tcl/Tk can quit the ruby process or not on the
- : interpreter. If false, such a command quit the interpreter
- : only.
- : The default value for a master interpreter is true, and
- : for a slave interpreter is false.
-
- allow_ruby_exit=(mode)
- : Change the mode of 'allow_ruby_exit?'.
- : If $SAFE >= 4 or the interpreter is a "safe" interpreter,
- : this is not permitted (raise an exception).
-
- delete
- : Delete the interpreter.
- : The deleted interpreter doesn't accept command and then
- : raise an exception.
-
- deleted?
- : Check whether the interpreter is already deleted.
- : If deleted, returns true.
-
- has_mainwindow?
- : Check whether the interpreter has a MainWindow (root widget).
- : If has, returns true. If doesn't, returns false.
- : If IP is already deleted, returns nil.
-
- restart
- : Restart Tk part of the interpreter.
- : Use this when you need Tk functions after destroying the
- : root widget.
- : On $SAFE >= 4, cannot call this method.
-
- _eval(str)
- _invoke(*args)
- : Estimates the arguments as a command on the Tk interpreter.
- : The argument of _eval is a script of Tcl/Tk.
- : Each argument of _invoke is a token of one command line of
- : Tcl/Tk.
- : Because the operation of _invoke doesn't through the
- : command line parser of Tk interpreter, the cost of
- : estimation is smaller than _eval. However, auto_load
- : mechanism of the Tk interpreter doesn't work on _invoke.
- : So _invoke can call only the command which already
- : registered on the interpreter by 'load' command and so on.
- : On _eval command, auto_load mechanism words. So if succeed
- : to _eval and regist the command once, after that, the
- : command can be called by _invoke.
-
- _toUTF8(str, encoding=nil)
- _fromUTF8(str, encoding=nil)
- : Call the function (which is internal function of Tcl/Tk) to
- : convert to/from a UTF8 string.
-
- _thread_vwait(var_name)
- _thread_tkwait(mode, target)
- : 'vwait' or 'tkwait' with thread support.
- : The difference from normal 'vwait' or 'tkwait' command is
- : doing independent wait from the vwait stack when they are
- : called on the other thread than the eventloop thread.
- : In the case of Tcl/Tk's vwait / tkwait, if 2nd vwait /
- : tkwait is called on waiting for 1st vwait / tkwait,
- : returns the order of [2nd]->[1st] regardless of the order
- : of when the wait condition was fulfilled.
- : If _thread_vwait / _thread_tkwait is called on the
- : eventloop thread, there is no difference from vwait /
- : tkwait. But if called on the other thread than the
- : eventloop, stops the thread. And when the wait condition
- : is fulfilled, the thread restarts. The meaning of
- : "independent from the vwait stack" is that the timing of
- : restarting is independent from the waiting status of the
- : other threads. That is, even if the eventloop thread is
- : waiting by vwait and is not fulfilled the condition,
- : _thread_vwait completes the waiting when its waiting
- : condition is fulfilled and the thread which stopped by
- : _thread_vwait can continue the operation.
-
- _return_value
- : Get the last result value on the interpreter.
-
- _get_variable(var_name, flag)
- _get_variable2(var_name, index_name, flag)
- : Get the current value of a variable. If specified a
- : index_name (see also the PARSE_VARNAME flag), get the
- : value of the index_name element.
-
- _set_variable(var_name, value, flag)
- _set_variable2(var_name, index_name, value, flag)
- : Create or modify a variable. If specified a index_name
- : (see also the PARSE_VARNAME flag), create or modify the
- : index_name element.
-
- _unset_variable(var_name)
- _unset_variable2(var_name, index_name)
- : Remove a variable. If specified a index_name (see also
- : the PARSE_VARNAME flag), remove the index_name element.
-
- _get_global_var(var_name)
- _get_global_var2(var_name, index_name)
- _set_global_var(var_name, value)
- _set_global_var2(var_name, index_name, value)
- _unset_global_var(var_name)
- _unset_global_var2(var_name, index_name)
- : Call the associated method with the flag argument
- : (GLOBAL_ONLY | LEAVE_ERR_MSG).
-
- _split_tklist(str)
- : Split the argument with Tcl/Tk's library function and
- : get an array as a list of Tcl list elements.
-
- _merge_tklist(str, str, ... )
- : Get a Tcl's list string from arguments with a Tcl/Tk's
- : library function. Each arguemnt is converted to a valid
- : Tcl list element.
-
- _conv_listelement(str)
- : Convert the argument to a valid Tcl list element with
- : Tcl/Tk's library function.
-
- mainloop
- mainloop_watchdog
- : If on the slave interpreter, never start an eventloop and
- : returns nil.
- : With the exception that, same to the TclTkLib module method
- : with the same name.
-
- do_one_event
- : With the exception that the argument is forced to set
- : DONT_WAIT flag on the slave interpreter, same to
- : TclTkLib#do_one_event.
-
- set_eventloop_tick
- get_eventloop_tick
- set_no_event_wait
- get_no_event_wait
- set_eventloop_weight
- get_eventloop_weight
- mainloop_abort_on_exception
- mainloop_abort_on_exception=
- : With the exception that it is ignored to set value on the
- : slave interpreter, same to the TclTkLib module method with
- : the same name.
-
-class TkCallbackBreak < StandardError
-class TkCallbackContinue < StandardError
- : They are exception classes to break or continue the Tk callback
- : operation.
- : If raise TkCallbackBreak on the callback procedure, Ruby returns
- : 'break' code to Tk interpreter (Then the Tk interpreter will
- : break the operation for the current event).
- : If raise TkCallbackContinue, returns 'continue' code (Then the Tk
- : interpreter will break the operateion for the current bindtag and
- : starts the operation for the next buindtag for the current event).
-
-(eof)
diff --git a/ext/tk/MANUAL_tcltklib.eucj b/ext/tk/MANUAL_tcltklib.eucj
deleted file mode 100644
index 5dd36726ba..0000000000
--- a/ext/tk/MANUAL_tcltklib.eucj
+++ /dev/null
@@ -1,557 +0,0 @@
-(tof)
- 2005/07/05 Hidetoshi NAGAI
-
-Ëܥɥ­¥å¥á¥ó¥È¤Ë¤Ï¸Å¤¤ tcltk ¥é¥¤¥Ö¥é¥ê¡¤tcltklib ¥é¥¤¥Ö¥é¥ê¤ÎÀâÌÀ
-¤¬´Þ¤Þ¤ì¤Æ¤¤¤Þ¤¹¤¬¡¤¤½¤Îµ­½ÒÆâÍÆ¤Ï¸Å¤¤¤â¤Î¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
-
-tcltk ¥é¥¤¥Ö¥é¥ê¡Êtcltk.rb¡Ë¤Ï¸½ºß¤Ç¤Ï¥á¥ó¥Æ¥Ê¥ó¥¹¤¬»ö¼Â¾å¹Ô¤ï¤ì¤Æ
-¤¤¤Ê¤¤¤¿¤á¡¤¸Å¤¤¥É¥­¥å¥á¥ó¥È¤ÎÀâÌÀ¤¬¤½¤Î¤Þ¤ÞÍ­¸ú¤Ç¤¹¡¥¤½¤ì¤ËÂФ·¡¤
-tcltklib ¥é¥¤¥Ö¥é¥ê¤Ë¤Ä¤¤¤Æ¤Ï¡¤¸½ºß¤Î Ruby/Tk¡Êtk.rb °Ê²¼¤Î¥é¥¤¥Ö¥é
-¥ê·²¡Ë¤ò²ÔƯ¤µ¤»¤ë¤¿¤á¤ÎÃæ¿´¤È¤·¤Æ¥á¥ó¥Æ¥Ê¥ó¥¹¤µ¤ì¤Æ¤¤¤ë¤¿¤á¡¤¾¯¡¹
-°ã¤¤¤¬À¸¤¸¤Æ¤¤¤Þ¤¹¡¥
-
-¤½¤³¤Ç¡¤¤Þ¤º¸Å¤¤ÀâÌÀʸ½ñ¤ò¼¨¤·¤¿¸å¡¤¸½ºß¤Î tcltklib ¥é¥¤¥Ö¥é¥ê¤Ë¤Ä
-¤¤¤Æ¤ÎÀâÌÀ¤ò²Ã¤¨¤Þ¤¹¡¥
-
-°Ê²¼¤¬¥é¥¤¥Ö¥é¥ê¤Î¸Å¤¤ÀâÌÀʸ½ñ¤Ç¤¹¡¥
-==============================================================
- MANUAL.euc
- Sep. 19, 1997 Y. Shigehiro
-
-°Ê²¼, ¡Ötcl/tk¡×¤È¤¤¤¦É½µ­¤Ï, tclsh ¤ä wish ¤ò¼Â¸½¤·¤Æ¤¤¤ë, °ìÈ̤Ǥ¤¤¦
-¤È¤³¤í¤Î tcl/tk ¤ò»Ø¤·¤Þ¤¹. ¡Ötcltk ¥é¥¤¥Ö¥é¥ê¡×, ¡Ötcltklib ¥é¥¤¥Ö¥é
-¥ê¡×¤È¤¤¤¦É½µ­¤Ï, Ëܥѥ屡¼¥¸¤Ë´Þ¤Þ¤ì¤ë ruby ÍѤΥ饤¥Ö¥é¥ê¤ò»Ø¤·¤Þ¤¹.
-
-<< tcltk ¥é¥¤¥Ö¥é¥ê >>
-
-tcl/tk ¤Î C ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ¹¤ë¤¿¤á¤Î¹â(Ãæ?)¿å½à¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤òÄó
-¶¡¤·¤Þ¤¹.
-
-¤³¤Î¥é¥¤¥Ö¥é¥ê¤Ï ruby ¤«¤é tcl/tk ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ¹¤ë¤¿¤á¤Î¤â¤Î¤Ç, Æâ
-Éô¤Ç tcltklib ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ·¤Æ¤¤¤Þ¤¹.
-
-[ÀâÌÀ]
-
-tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤Ç¤Ï, ¥¦¥£¥¸¥§¥Ã¥È¤Ë²¿¤«»Ø¼¨¤òÁ÷¤ë¤Ë¤Ï, ¥¦¥£¥¸¥§¥Ã
-¥È̾¤Ë³¤¤¤Æ¥Ñ¥é¥á¡¼¥¿¤ò½ñ¤­¤Þ¤¹. ¤·¤¿¤¬¤Ã¤Æ, ¥¦¥£¥¸¥§¥Ã¥È¤¬¥ª¥Ö¥¸¥§¥¯
-¥È¤Ç¤¢¤ê, ¤½¤ì¤ËÂФ·¤Æ¥á¥½¥Ã¥É¤òÁ÷¤Ã¤Æ¤¤¤ë, ¤È¤ß¤Ê¤¹¤³¤È¤¬¤Ç¤­¤Þ¤¹. ¤µ
-¤Æ, tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤Ç¤Ï, ÁȤ߹þ¤ß¥³¥Þ¥ó¥É¤â, Á°½Ò¤Î¥¦¥£¥¸¥§¥Ã¥È¤È
-Ʊ¤¸¤è¤¦¤Ê½ñ¼°¤ÎÌ¿Îá¤Ç¼Â¹Ô¤µ¤ì¤Þ¤¹. ¤¹¤Ê¤ï¤Á, ¥³¥Þ¥ó¥É¤â¥ª¥Ö¥¸¥§¥¯¥È¤Ç
-¤¢¤ë¤È¹Í¤¨¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹.
-
-¤³¤Î¤è¤¦¤Ê¹Í¤¨¤Ë´ð¤Å¤­, tcltk ¥é¥¤¥Ö¥é¥ê¤Ç¤Ï, tcl/tk ¤Î¥³¥Þ¥ó¥É¤ä¥¦¥£
-¥¸¥§¥Ã¥È¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Þ¤¹. ¥ª¥Ö¥¸¥§¥¯¥È¤ËÂФ¹¤ë¥á¥½¥Ã
-¥É¸Æ¤Ó½Ð¤·¤Ï, e() ¥á¥½¥Ã¥É¤Ë¤è¤ê¼Â¹Ô¤µ¤ì¤Þ¤¹. Î㤨¤Ð, tcl/tk ¤Î info
-¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë ruby ¤Î¥ª¥Ö¥¸¥§¥¯¥È¤¬ info ¤È¤¤¤¦Ì¾Á°¤Ç¤¢¤ë¤È¤¹¤ë¤È,
-tcl/tk ¤Î
- info commands
-¤È¤¤¤¦Ì¿Îá¤Ï tcltk ¥é¥¤¥Ö¥é¥ê¤Ç¤Ï
- info.e("commands")
-¤Èµ­½Ò¤µ¤ì¤Þ¤¹. ¤Þ¤¿, ¡Ö.¡×¤È¤¤¤¦¥¦¥£¥¸¥§¥Ã¥È (wish ¼Â¹Ô»þ¤Ë¼«Æ°Åª¤ËÀ¸
-À®¤µ¤ì¤ë¥ë¡¼¥È¥¦¥£¥¸¥§¥Ã¥È) ¤ËÂбþ¤¹¤ë ruby ¤Î¥ª¥Ö¥¸¥§¥¯¥È¤¬ root ¤È¤¤
-¤¦Ì¾Á°¤Ç¤¢¤ë¤È¤¹¤ë¤È,
- . configure -height 300 -width 300
-¤È¤¤¤¦ tcl/tk ¤ÎÌ¿Îá¤Ï
- root.e("configure -height 300 -width 300")
-¤Èµ­½Ò¤µ¤ì¤Þ¤¹. ¤³¤Î¤è¤¦¤Êµ­½Ò¤Ï, ¸«¤¿¤á¤Ë¤ÏÈþ¤·¤¯¤¢¤ê¤Þ¤»¤ó¤¬, ¤½¤·¤Æ,
-¥¹¥¯¥ê¥×¥È¤òÆÉ¤à¿Í¤Ë¤Ï¸«¤Å¤é¤¤¤«¤âÃΤì¤Þ¤»¤ó¤¬, ¼ÂºÝ¤Ë¥¹¥¯¥ê¥×¥È¤ò½ñ¤¤
-¤Æ¤ß¤ë¤ÈͽÁÛ³°¤Ë¼ê·Ú¤Ç¤¹.
-
-[»ÈÍÑË¡]
-
-1. ¥é¥¤¥Ö¥é¥ê¤òÆÉ¤ß¹þ¤à.
- require "tcltk"
-
-2. tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤òÀ¸À®¤¹¤ë.
- ip = TclTkInterpreter.new()
-
-3. tcl/tk ¤Î¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤òÊÑ¿ô¤ËÂåÆþ¤·¤Æ¤ª¤¯.
- # ¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤¬Æþ¤Ã¤¿ Hash ¤ò¼è¤ê½Ð¤¹.
- c = ip.commands()
- # »È¤¤¤¿¤¤¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ò¸ÄÊ̤ÎÊÑ¿ô¤ËÂåÆþ¤¹¤ë.
- bind, button, info, wm = c.indexes("bind", "button", "info", "wm")
-
-4. ɬÍפʽèÍý¤ò¹Ô¤¦.
- ¾Ü¤·¤¯¤Ï, ¥µ¥ó¥×¥ë¤ò»²¾È¤Î¤³¤È.
-
-5. ½àÈ÷¤¬¤Ç¤­¤¿¤é, ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ËÆþ¤ë.
- TclTk.mainloop()
-
-(( °Ê²¼, ¥â¥¸¥å¡¼¥ë, ¥¯¥é¥¹Åù¤ÎÀâÌÀ¤ò½ñ¤¯Í½Äê.))
-
-
-
-<< tcltklib ¥é¥¤¥Ö¥é¥ê >>
-
-tcl/tk ¤Î C ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ¹¤ë¤¿¤á¤ÎÄã¿å½à¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤òÄ󶡤·¤Þ
-¤¹.
-
-¥³¥ó¥Ñ¥¤¥ë/¼Â¹Ô¤Ë¤Ï, tcl/tk ¤Î C ¥é¥¤¥Ö¥é¥ê¤¬É¬ÍפǤ¹.
-
-[ÀâÌÀ]
-
-¤³¤Î¥é¥¤¥Ö¥é¥ê¤òÍѤ¤¤ë¤È, ruby ¤«¤é tcl/tk ¤Î C ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤǤ­¤Þ
-¤¹. ¶ñÂÎŪ¤Ë¤Ï, ruby ¥¤¥ó¥¿¥×¥ê¥¿¤«¤é tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤ò¸Æ¤Ó½Ð¤¹¤³
-¤È¤¬¤Ç¤­¤Þ¤¹. ¤µ¤é¤Ë, ¤½¤Î(ruby ¥¤¥ó¥¿¥×¥ê¥¿¤«¤é¸Æ¤Ó½Ð¤·¤¿) tcl/tk ¥¤
-¥ó¥¿¥×¥ê¥¿¤«¤é, µÕ¤Ë ruby ¥¤¥ó¥¿¥×¥ê¥¿¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤â¤Ç¤­¤Þ¤¹.
-
-[»ÈÍÑË¡]
-
-require "tcltklib" ¤¹¤ë¤È, °Ê²¼¤Î¥â¥¸¥å¡¼¥ë, ¥¯¥é¥¹¤¬ÍøÍѲÄǽ¤Ç¤¹.
-
-¥â¥¸¥å¡¼¥ë TclTkLib
- tcl/tk ¥é¥¤¥Ö¥é¥ê¤ò¸Æ¤Ó½Ð¤¹¥á¥½¥Ã¥É¤ò½¸¤á¤¿¥â¥¸¥å¡¼¥ë¤Ç¤¹. ¤¿¤À¤·,
- tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿´Ø·¸¤Î¥á¥½¥Ã¥É¤Ï¥¯¥é¥¹ TclTkIp ¤Ë¤¢¤ê¤Þ¤¹.
-
- ¥â¥¸¥å¡¼¥ë¥á¥½¥Ã¥É mainloop()
- Tk_MainLoop ¤ò¼Â¹Ô¤·¤Þ¤¹. Á´¤Æ¤Î tk ¤Î¥¦¥¤¥ó¥É¥¦¤¬Ìµ¤¯¤Ê¤ë¤È½ªÎ»
- ¤·¤Þ¤¹(Î㤨¤Ð, tcl/tk ¤Ç½ñ¤¯¤È¤³¤í¤Î "destroy ." ¤ò¤·¤¿¾ì¹çÅù).
- °ú¿ô: ̵¤·
- Ìá¤êÃÍ: nil
-
-¥¯¥é¥¹ TclTkIp
- ¥¤¥ó¥¹¥¿¥ó¥¹¤¬ tcl/tk ¤Î¥¤¥ó¥¿¥×¥ê¥¿¤ËÂбþ¤·¤Þ¤¹. tcl/tk ¤Î¥é¥¤¥Ö
- ¥é¥ê¤Î»ÅÍÍÄ̤ê, ¥¤¥ó¥¹¥¿¥ó¥¹¤òÊ£¿ô¸ÄÀ¸À®¤·¤Æ¤âÀµ¤·¤¯Æ°ºî¤·¤Þ¤¹(¤½
- ¤ó¤Ê¤³¤È¤ò¤¹¤ëɬÍפϤ¢¤Þ¤ê̵¤¤¤Ï¤º¤Ç¤¹¤¬). ¥¤¥ó¥¿¥×¥ê¥¿¤Ï wish ¤Î
- tcl/tk ¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤Ç¤­¤Þ¤¹. ¤µ¤é¤Ë, °Ê²¼¤Î¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤Ç¤­¤Þ
- ¤¹.
- ¥³¥Þ¥ó¥É ruby
- °ú¿ô¤ò ruby ¤Ç¼Â¹Ô¤·¤Þ¤¹(ruby_eval_string ¤ò¼Â¹Ô¤·¤Þ¤¹). °ú¿ô
- ¤Ï 1 ¤Ä¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó. Ìá¤êÃÍ¤Ï ruby ¤Î¼Â¹Ô·ë²Ì¤Ç¤¹.
- ruby ¤Î¼Â¹Ô·ë²Ì¤Ï nil ¤« String ¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó.
-
- ¥¯¥é¥¹¥á¥½¥Ã¥É new()
- TclTkIp ¥¯¥é¥¹¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤·¤Þ¤¹
- °ú¿ô: ̵¤·
- Ìá¤êÃÍ (TclTkIp): À¸À®¤µ¤ì¤¿¥¤¥ó¥¹¥¿¥ó¥¹
-
- ¥á¥½¥Ã¥É _eval(script)
- ¥¤¥ó¥¿¥×¥ê¥¿¤Ç script ¤òɾ²Á¤·¤Þ¤¹(Tcl_Eval ¤ò¼Â¹Ô¤·¤Þ¤¹). Á°½Ò
- ¤Î¤è¤¦¤Ë, ruby ¥³¥Þ¥ó¥É¤Ë¤è¤ê script Æâ¤«¤é ruby ¥¹¥¯¥ê¥×¥È¤ò¼Â
- ¹Ô¤Ç¤­¤Þ¤¹.
- °ú¿ô: script (String) - ¥¤¥ó¥¿¥×¥ê¥¿¤Çɾ²Á¤¹¤ë¥¹¥¯¥ê¥×¥Èʸ»úÎó
- Ìá¤êÃÍ (String): ɾ²Á·ë²Ì ((Tcl_Interp *)->result)
-
- ¥á¥½¥Ã¥É _return_value()
- ľÁ°¤Î Tcl_Eval ¤ÎÌá¤êÃͤòÊÖ¤·¤Þ¤¹. 0(TCL_OK) ¤ÇÀµ¾ï½ªÎ»¤Ç¤¹.
- °ú¿ô: ̵¤·
- Ìá¤êÃÍ (Fixnum): ľÁ°¤Î Tcl_Eval() ¤¬ÊÖ¤·¤¿ÃÍ.
-
-==============================================================
-
-°Ê²¼¤¬Ëܥɥ­¥å¥á¥ó¥ÈºîÀ®»þÅÀ¤Ç¤Î tcltklib ¥é¥¤¥Ö¥é¥ê¤ÎÀâÌÀ¤Ç¤¹¡¥
-==============================================================
-¥â¥¸¥å¡¼¥ë TclTkLib
- : ¸Ä¡¹¤Î Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ë°Í¸¤·¤Ê¤¤½èÍý ( == ¥¤¥Ù¥ó¥È¥ë¡¼
- : ¥×¤Ë´Ø¤¹¤ë½èÍý ) ¤ò¸Æ¤Ó½Ð¤¹¥á¥½¥Ã¥É¤òÄêµÁ¤·¤¿¥â¥¸¥å¡¼¥ë¡¥
-
- ¥â¥¸¥å¡¼¥ë TclTkLib::EventFlag
- : do_one_event ¤ò¸Æ¤Ó½Ð¤¹ºÝ¤Î½èÍýÂоݥ¤¥Ù¥ó¥È¤ò»ØÄꤹ¤ë¤¿¤á¤Î
- : ¥Õ¥é¥° ( WINDOW|DONT_WAIT ¤È¤¤¤¦¤è¤¦¤Ë¥Ó¥Ã¥È±é»»»Ò¤ÇÏ¢·ë¤·¤Æ
- : »ØÄê ) ¤òÄê¿ô¤È¤·¤ÆÄêµÁ¤·¤¿¥â¥¸¥å¡¼¥ë¡¥°Ê²¼¤ÎÄê¿ô¤¬´Þ¤Þ¤ì¤ë¡¥
-
- Äê¿ô NONE
- : ÃÍ¤Ï 0 ¤Ç¡¤ÃͤȤ·¤Æ¤Ï¤¤¤«¤Ê¤ë¼ïÎà¤Î¥¤¥Ù¥ó¥È¤â»ØÄꤷ¤Æ¤¤¤Ê¤¤
- : ¤³¤È¤Ë¤Ê¤ë¤¬¡¤¼ÂºÝ¤Î½èÍý¾å¤Ï ALL ¤ÈƱ¤¸¤È¤·¤Æ°·¤ï¤ì¤ë¡¥
-
- Äê¿ô WINDOW
- : window ¥¤¥Ù¥ó¥È¤ò½èÍýÂоݤȤ¹¤ë
-
- Äê¿ô FILE
- : file ¥¤¥Ù¥ó¥È¤ò½èÍýÂоݤȤ¹¤ë
-
- Äê¿ô TIMER
- : timer ¥¤¥Ù¥ó¥È¤ò½èÍýÂоݤȤ¹¤ë
-
- Äê¿ô IDLE
- : ¥¢¥¤¥É¥ë¥ë¡¼¥×½èÍý ( ºÆÉÁ²è¤Ê¤É¡¤Â¾¤Î¼ïÎà¤Î¥¤¥Ù¥ó¥È¤¬È¯À¸
- : ¤·¤Æ¤¤¤Ê¤¤¤È¤­¤Ë¹Ô¤ï¤ì¤ë½èÍý ) ¤ò½èÍýÂоݤȤ¹¤ë
-
- Äê¿ô ALL
- : ¤¹¤Ù¤Æ¤Î¼ïÎà¤Î¥¤¥Ù¥ó¥È¤ò½èÍýÂоݤȤ¹¤ë
- : WINDOW|FILE|TIMER|IDLE ¤ÈƱ¤¸
-
- Äê¿ô DONT_WAIT
- : ½èÍýÂоݥ¤¥Ù¥ó¥È¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ë¡¤¥¤¥Ù¥ó¥ÈȯÀ¸¤òÂÔ¤¿¤º
- : ¤Ë do_one_event ¤ò½ªÎ» ( false ¤òÊÖ¤¹ ) ¤¹¤ë
-
- ¥â¥¸¥å¡¼¥ë TclTkLib::VarAccessFlag
- : _get_variable ¤Ê¤É¤Ç¤Î¥Õ¥é¥°¤ò»ØÄꤹ¤ë¤¿¤á¤Î¤â¤Î¡¥¥Õ¥é¥°¤Ë
- : ¤Ï°Ê²¼¤ÎÄê¿ô¤ò OR ¤ÇÏ¢·ë¤·¤ÆÍ¿¤¨¤ë¡¥
-
- Äê¿ô NONE
- : ÃÍ¤Ï 0 ¤Ç¡¤²¿¤â¥Õ¥é¥°¤ò»ØÄꤷ¤Æ¤¤¤Ê¤¤¤Î¤ËÅù¤·¤¤¡¥
-
- Äê¿ô GLOBAL_ONLY
- : Ä̾ÊÑ¿ô¤Î¸¡º÷¤Ï¤Þ¤º¼ê³¤­¸Æ¤Ó½Ð¤·¤ò¹Ô¤Ã¤¿¥ì¥Ù¥ë¤Ç¸¡
- : º÷¤·¡¤¼¡¤Ë¸½ºß¤Î̾Á°¶õ´Ö¤Ç¸¡º÷¡¤ºÇ¸å¤Ë¥°¥í¡¼¥Ð¥ë¶õ´Ö¤Ç
- : ¸¡º÷¤ò¹Ô¤¦¡¥¤·¤«¤·¡¤¤³¤Î¥Õ¥é¥°¤¬»ØÄꤵ¤ì¤¿¾ì¹ç¤Ë¤Ï¡¤¥°
- : ¥í¡¼¥Ð¥ë¶õ´Ö¤Ç¤Î¤ß¸¡º÷¤¹¤ë¡¥
- : ¤â¤· GLOBAL_ONLY ¤È NAMESPACE_ONLY ¤È¤¬Î¾Êý»ØÄꤵ¤ì¤¿¾ì
- : ¹ç¤Ë¤Ï¡¤GLOBAL_ONLY ¤Î»ØÄê¤Ï̵»ë¤µ¤ì¤ë¡¥
-
- Äê¿ô NAMESPACE_ONLY
- : ¤³¤Î¥Õ¥é¥°¤¬»ØÄꤵ¤ì¤¿¾ì¹ç¤Ë¤Ï¡¤¸½ºß¤Î̾Á°¶õ´Ö¤Ç¤Î¤ßÊÑ
- : ¿ô¤Î¸¡º÷¤ò¹Ô¤¦¡¥GLOBAL_ONLY ¤ÎÀâÌÀ¤â»²¾È¤¹¤ë¤³¤È¡¥
-
- Äê¿ô LEAVE_ERR_MSG
- : ÊÑ¿ô¥¢¥¯¥»¥¹¤Ë¤ª¤¤¤Æ¥¨¥é¡¼¤¬È¯À¸¤·¤¿¾ì¹ç¡¤¤³¤Î¥Õ¥é¥°¤¬
- : »ØÄꤵ¤ì¤Æ¤¤¤ì¤Ð¡¤¼Â¹Ô·ë²Ì¤È¤·¤Æ Tcl ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ë¥¨
- : ¥é¡¼¥á¥Ã¥»¡¼¥¸¤¬»Ä¤µ¤ì¤ë¡¥¤³¤Î¥Õ¥é¥°¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±
- : ¤ì¤Ð¡¤¥¨¥é¡¼¥á¥Ã¥»¡¼¥¸¤Ï°ìÀڻĤµ¤ì¤Ê¤¤¡¥
-
- Äê¿ô APPEND_VALUE
- : ¤³¤Î¥Õ¥é¥°¤¬»ØÄꤵ¤ì¤Æ¤¤¤¿¾ì¹ç¡¤ÊÑ¿ô¤ÎÃͤòÃÖ¤­´¹¤¨¤Î¤Ç
- : ¤Ï¤Ê¤¯¡¤¸½ºß¤ÎÃͤËÂåÆþÃͤ¬Äɲà (append; ʸ»úÎóÏ¢·ë) ¤µ
- : ¤ì¤ë¡¥ÊÑ¿ô¤¬Ì¤ÄêµÁ¤¢¤Ã¤¿¾ì¹ç¡¤¤³¤Î¥Õ¥é¥°¤Ï̵»ë¤µ¤ì¤ë¡¥
-
- Äê¿ô LIST_ELEMENT
- : ¤³¤Î¥Õ¥é¥°¤¬»ØÄꤵ¤ì¤Æ¤¤¤¿¾ì¹ç¡¤ÂåÆþÃͤϤޤº Tcl ¤Î¥ê¥¹
- : ¥ÈÍ×ÁǤȤ·¤ÆÅ¬ÀڤȤʤë¤è¤¦¤ËÊÑ´¹¤µ¤ì¤ë¡¥ÂåÆþÃͤ¬¥ê¥¹¥È
- : (¤Þ¤¿¤Ï¥µ¥Ö¥ê¥¹¥È) ¤ÎºÇ½é¤ÎÍ×ÁǤȤʤë¤Î¤Ç¤Ê¤¤¸Â¤ê¡¤ÂåÆþ
- : ÃͤÎľÁ°¤Ë¤Ï¶õÇòʸ»ú¤¬Äɲ䵤ì¤ë¡¥
-
- Äê¿ô PARSE_VARNAME
- : _set_variable ¤Ê¤É¤Î¸Æ¤Ó½Ð¤·¤Ë¤ª¤¤¤Æ¤³¤Î¥Õ¥é¥°¤¬»ØÄꤵ
- : ¤ì¤Æ¤¤¤¿¾ì¹ç¡¤var_name °ú¿ô¤¬Ï¢ÁÛÇÛÎó̾¤ÈÍ×ÁÇ̾¤È¤òξÊý
- : ´Þ¤à²ÄǽÀ­¤¬¤¢¤ë (³«¤­³ç¸Ì¤ò´Þ¤ß¡¤ÊĤ¸³ç¸Ì¤Ç½ª¤ï¤ë) ¤³
- : ¤È¤ò¼¨¤¹¡¥¤½¤Î¾ì¹ç¡¤³ç¸Ì¤Î´Ö¤¬Í×ÁÇ̾»ØÄꡤºÇ½é¤Î³«¤­³ç
- : ¸Ì¤Þ¤Ç¤¬Ï¢ÁÛÇÛÎó̾¤È¤·¤Æ°·¤ï¤ì¤ë¡¥_set_variable2 ¤Ê¤É¤Ç
- : ¤³¤Î¥Õ¥é¥°¤ò»ØÄꤹ¤ë¾ì¹ç¡¤Ï¢ÁÛÇÛÎó̾¤ÈÍ×ÁÇ̾¤Ï var_name
- : ¤«¤éÃê½Ð¤µ¤ì¤ë¤Ï¤º¤Ç¤¢¤ë¤«¤é¡¤index_name °ú¿ô¤Ï nil ¤È
- : ¤»¤Í¤Ð¤Ê¤é¤Ê¤¤¡¥
-
- ¥â¥¸¥å¡¼¥ë¥á¥½¥Ã¥É
- mainloop(check_root = true)
- : ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤òµ¯Æ°¤¹¤ë¡¥check_root ¤¬ true ¤Ç¤¢¤ì¤Ð¡¤
- : root widget ¤¬Â¸ºß¤¹¤ë¸Â¤ê¡¤¤³¤Î¥á¥½¥Ã¥É¤Ï½ªÎ»¤·¤Ê¤¤¡¥
- : check_root ¤¬ false ¤Î¾ì¹ç¤Ï¡¤root widget ¤¬¾ÃÌǤ·¤Æ¤â
- : ¤³¤Î¥á¥½¥Ã¥É¤Ï½ªÎ»¤·¤Ê¤¤ ( root widget ¤¬¾ÃÌǤ·¤Æ¤â¡¤
- : WINDOW °Ê³°¤Î¥¤¥Ù¥ó¥È¤ÏȯÀ¸¤·¤¦¤ë¤¿¤á )¡¥½ªÎ»¤Ë¤Ï¡¤³°Éô
- : ¤«¤é¤ÎƯ¤­³Ý¤± ( ¥¹¥ì¥Ã¥É¤ò³èÍѤ¹¤ë¤Ê¤É ) ¤¬É¬Íס¥
-
- mainloop_thread?
- : ¥«¥ì¥ó¥È¥¹¥ì¥Ã¥É¤¬¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò¼Â¹Ô¤·¤Æ¤¤¤ë¥¹¥ì¥Ã¥É
- : ¤«¤É¤¦¤«¤òÊÖ¤¹¡¥
- : ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò¼Â¹Ô¤·¤Æ¤¤¤ë¥¹¥ì¥Ã¥É¤Ç¤¢¤ì¤Ð true ¤ò¡¤
- : ¤É¤Î¥¹¥ì¥Ã¥É¤Ç¤â¥¤¥Ù¥ó¥È¥ë¡¼¥×¤¬¼Â¹Ô¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï
- : nil ¤ò¡¤Â¾¤Î¥¹¥ì¥Ã¥É¤Ç¥¤¥Ù¥ó¥È¥ë¡¼¥×¤¬¼Â¹Ô¤µ¤ì¤Æ¤¤¤ë¾ì
- : ¹ç¤Ï false ¤òÊÖ¤¹¡¥
- : false ¤ÎºÝ¤Ë Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤òľÀÜ¸Æ¤Ö¤Î¤Ï´í¸±¤Ç¤¢¤ë¡¥
-
- mainloop_watchdog(check_root = true)
- : Ä̾ï¤Î¥¤¥Ù¥ó¥È¥ë¡¼¥×¤Ç¤Ï¡¤¥¤¥Ù¥ó¥È½èÍý¤ÎÆâÍÆ¤Ë¤è¤Ã¤Æ¤Ï
- : ¥Ç¥Ã¥É¥í¥Ã¥¯¤ò°ú¤­µ¯¤³¤¹²ÄǽÀ­¤¬¤¢¤ë (Î㤨¤Ð¥¤¥Ù¥ó¥È¤Ë
- : ÂФ¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯½èÍýÃæ¤Ç widget Áàºî¤ò¤·¡¤¤½¤Î½ªÎ»¤ò
- : ÂԤĤʤÉ)¡¥¤³¤Î¥á¥½¥Ã¥É¤Ï¡¤¤½¤¦¤·¤¿¥Ç¥Ã¥É¥í¥Ã¥¯¤ò²óÈò¤¹
- : ¤ë¤¿¤á¤Î´Æ»ë¥¹¥ì¥Ã¥ÉÉÕ¤­¤Ç¥¤¥Ù¥ó¥È¥ë¡¼¥×¤òµ¯Æ°¤¹¤ë
- : ( ´Æ»ë¥¹¥ì¥Ã¥É¤òÀ¸À®¤·¤¿¸å¤Ë¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò¼Â¹Ô¤¹¤ë )¡¥
- : °ú¿ô¤Î°ÕÌ£¤Ï mainloop ¤ÈƱ¤¸¤Ç¤¢¤ë¡¥
-
- do_one_event(flag = TclTkLib::EventFlag::ALL |
- TclTkLib::EventFlag::DONT_WAIT)
- : ½èÍýÂÔ¤Á¤Î¥¤¥Ù¥ó¥È 1 ¸Ä¤ò¼Â¹Ô¤¹¤ë¡¥
- : ¥¤¥Ù¥ó¥È¤ò½èÍý¤·¤¿¾ì¹ç¤Ï true ¤òÊÖ¤¹¡¥
- : ¥Õ¥é¥°¤Ç DONT_WAIT ¤ò»ØÄꤷ¤Æ¤¤¤Ê¤¤¾ì¹ç¡¤¥Õ¥é¥°¤Ç½èÍýÂÐ
- : ¾Ý¤È¤Ê¤Ã¤Æ¤¤¤ë¼ïÎà¤Î¥¤¥Ù¥ó¥È¤¬È¯À¸¤¹¤ë¤Þ¤ÇÂÔ¤Á³¤±¤ë¡¥
- : DONT_WAIT ¤ò»ØÄꤷ¤Æ¤¤¤¿¾ì¹ç¡¤½èÍýÂоݥ¤¥Ù¥ó¥È¤¬¤Ê¤¯¤Æ¤â
- : ¤¹¤°¤Ë½ªÎ»¤· false ¤òÊÖ¤¹¡¥
- : $SAFE >= 4 ¤«¡¤$SAFE >= 1 ¤«¤Ä flag ¤¬±øÀ÷¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð
- : flag ¤Ë¤Ï DONT_WAIT ¤¬¶¯À©Åª¤ËÉÕ¤±¤é¤ì¤ë¡¥
-
- set_eventloop_tick(timer_tick)
- : ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ÈƱ»þ¤ËÊÌ¥¹¥ì¥Ã¥É¤¬²ÔƯ¤·¤Æ¤¤¤ë¾ì¹ç¤Ë¡¤»þ
- : ´Ö¤Ë´ð¤Å¤¤¤¿¶¯À©Åª¤Ê¥¹¥ì¥Ã¥É¥¹¥¤¥Ã¥Á¥ó¥°¤ò¤É¤ÎÄøÅÙ¤ÎÉÑÅÙ
- : ( »þ´Ö´Ö³Ö ) ¤ÇȯÀ¸¤µ¤»¤ë¤«¤ò¥ß¥êÉÃñ°Ì¤ÎÀ°¿ôÃͤǻØÄꤹ¤ë¡¥
- : 0 ¤ò»ØÄꤹ¤ë¤È¡¤¤³¤Î¶¯À©Åª¤Ê¥¹¥¤¥Ã¥Á¥ó¥°¤Ï¹Ô¤ï¤ì¤Ê¤¤¡¥
- : ɸ½à¤Ç¤Ï 0 ¤ËÀßÄꤵ¤ì¤Æ¤ª¤ê¡¤¥¤¥Ù¥ó¥È½èÍý¿ô¤Ë´ð¤Å¤¯¥¹¥¤¥Ã
- : ¥Á¥ó¥°¤À¤±¤¬¹Ô¤ï¤ì¤ë ( see set_eventloop_weight )¡¥
- : ¤¿¤À¤·¡¤²ÔƯ¤·¤Æ¤¤¤ë¥¹¥ì¥Ã¥É¤¬¥¤¥Ù¥ó¥È¥ë¡¼¥×¤À¤±¤Î¾ì¹ç¡¤
- : timer_tick ¤ò 0 ¤ËÀßÄꤹ¤ë¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡¥¤â¤·ÀßÄꤵ¤ì¤Æ
- : ¤¤¤¿¤é¡¤100 ms ( see NO_THREAD_INTERRUPT_TIME ) ¤Ë¼«Æ°Àß
- : Äꤵ¤ì¤ë¡¥
- : ¾ÜºÙ¤ÊÀâÌÀ¤Ïά¤¹¤¬¡¤¤³¤ì¤Ï CPU ¥Ñ¥ï¡¼¤òÀáÌ󤷤ĤİÂÁ´¤Ç
- : °ÂÄꤷ¤¿Æ°ºî¤ò¼Â¸½¤¹¤ë¤¿¤á¤Ë¼ÂÁõ¤·¤¿»ÅÍͤǤ¢¤ë¡¥
- : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
-
- get_eventloop_tick
- : timer_tick ¤Î¸½ºßÃͤòÊÖ¤¹¡¥
-
- set_no_event_wait(no_event_wait)
- : Ê£¿ô¤Î¥¹¥ì¥Ã¥É¤¬²ÔƯ¤·¤Æ¤¤¤ë¾ì¹ç¤Ç¡¤½èÍýÂÔ¤Á¥¤¥Ù¥ó¥È¤¬Á´
- : ¤¯Â¸ºß¤·¤Ê¤«¤Ã¤¿ºÝ¤Ë sleep ¾õÂÖ¤ËÆþ¤ë»þ´ÖŤò»ØÄꤹ¤ë¡¥
- : ²ÔƯ¥¹¥ì¥Ã¥É¤¬¥¤¥Ù¥ó¥È¥ë¡¼¥×¤À¤±¤Î¾ì¹ç¤Ë¤Ï°ÕÌ£¤ò¤Ê¤µ¤Ê¤¤¡¥
- : ¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¤Ï 20 (ms)
- : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
-
- get_no_event_wait
- : no_event_wait ¤Î¸½ºßÃͤòÊÖ¤¹¡¥
-
- set_eventloop_weight(loop_max, no_event_tick)
- : Ê£¿ô¤Î¥¹¥ì¥Ã¥É¤¬²ÔƯ¤·¤Æ¤¤¤ëºÝ¤Ë Ruby/Tk ¤Î¥¤¥Ù¥ó¥È¥ë¡¼
- : ¥×¤Ë³ä¤êÅö¤Æ¤ëÈæ½Å¤òÄê¤á¤ë¤¿¤á¤Î¥Ñ¥é¥á¡¼¥¿¤òÀßÄꤹ¤ë¡¥
- : ²ÔƯ¥¹¥ì¥Ã¥É¤¬¥¤¥Ù¥ó¥È¥ë¡¼¥×¤À¤±¤Î¾ì¹ç¤Ë¤Ï°ÕÌ£¤ò¤Ê¤µ¤Ê¤¤¡¥
- : °ìÅ٤Υ¹¥ì¥Ã¥ÉÀÚ¤êÂØ¤¨¤Î´Ö¤Ë½èÍý¤¹¤ë¥¤¥Ù¥ó¥È¤ÎºÇÂç¿ô¤È¡¤
- : ½èÍýÂÔ¤Á¤Î¥¤¥Ù¥ó¥È¤¬Â¸ºß¤·¤Ê¤¤ºÝ¤Î²Ã»»¿ô¤È¤òÀßÄꤹ¤ë¡¥
- : ½èÍýÂÔ¤Á¥¤¥Ù¥ó¥È¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ï no_event_wait ( see
- : set_no_event_wait ) ¤À¤±¤Î´Ö sleep ¾õÂÖ¤ËÆþ¤ë¡¥
- : ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¤½¤ì¤¾¤ì 800 ²ó¤È 10 ²ó¡¤¤Ä¤Þ¤ê¡¤800 ¸Ä¤Î¥¤
- : ¥Ù¥ó¥È (¥¢¥¤¥É¥ë¥¤¥Ù¥ó¥È¤ò´Þ¤à) ¤ò½èÍý¤¹¤ë¤È¤«¡¤¥¤¥Ù¥ó¥È
- : ¤¬Á´¤¯È¯À¸¤·¤Ê¤¤¤Þ¤Þ¤Ë 80 ²ó¤Î½èÍýÂÔ¤Á¥¤¥Ù¥ó¥È¸¡ºº¤¬´°Î»
- : ¤¹¤ë¤È¤«¤Ç¥«¥¦¥ó¥È¤¬ 800 °Ê¾å¤Ë¤Ê¤ë¤È¥¹¥ì¥Ã¥É¥¹¥¤¥Ã¥Á¥ó¥°
- : ¤¬È¯À¸¤¹¤ë¤³¤È¤Ë¤Ê¤ë¡¥
- : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
-
- get_eventloop_weight
- : ¸½ºß¤Î loop_max ¤È no_event_tick ¤È¤ÎÃͤòÊÖ¤¹¡¥
- : ( see set_eventloop_wait )
-
- mainloop_abort_on_exception=(bool)
- : Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¾å¤ÇÎã³°¤òȯÀ¸¤·¤¿ºÝ¤Ë¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò
- : ¥¨¥é¡¼Ää»ß¤µ¤»¤ë¤«¤É¤¦¤«¤ò»ØÄꤹ¤ë¡¥true ¤ò»ØÄꤷ¤¿¾ì¹ç¤Ï
- : ¥¨¥é¡¼Ää»ß¤¹¤ë¤¬¡¤false ¤Î¾ì¹ç¤ÏÎã³°¤ò̵»ë¤·¤Æ¥¤¥Ù¥ó¥È¥ë¡¼
- : ¥×¤ò·Ñ³¤¹¤ë¡¥¤µ¤é¤Ë nil ¤Î¾ì¹ç¤Ï·Ù¹ð¥â¡¼¥É¤Ç¤Ê¤¤¸Â¤ê¤Ï¥¨
- : ¥é¡¼¥á¥Ã¥»¡¼¥¸¤Î½ÐÎϤ¹¤é¾Êά¤·¤Æ¡¤Îã³°¤ò̵»ë¤¹¤ë¡¥
- : ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï true ¤ËÀßÄꤵ¤ì¤Æ¤¤¤ë¡¥
- : £±¸Ä¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤À¤±¤ò»È¤Ã¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï¥¨¥é¡¼»þ¤Ë¤½¤Î
- : ¤Þ¤ÞÄä»ß¤·¤Æ¤âÄ̾ï¤ÏÌäÂê¤Ê¤¤¤¬¡¤Ê£¿ô¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬Æ±»þ
- : ¤Ëưºî¤·¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï¡¤¤½¤ì¤é¤ò´ÉÍý¤¹¤ë¥¤¥Ù¥ó¥È¥ë¡¼¥×¤Ï£±
- : ¸Ä¤À¤±¤Ç¤¢¤ë¤¿¤á¡¤¤¤¤º¤ì¤«¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î¥¨¥é¡¼¤¬¸¶°ø¤Ç¡¤
- : ¾¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î½èÍý·Ñ³¤¬ÉÔ²Äǽ¤Ë¤Ê¤ë¤³¤È¤¬¤¢¤ë¡¥¤½¤Î
- : ¤è¤¦¤Ê¾ì¹ç¤Ç¤â¥¨¥é¡¼¤ò̵»ë¤·¤Æ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤¬²ÔƯ¤ò³¤±¤ë
- : ¤³¤È¤Ç¡¤Â¾¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬Àµ¾ï¤Ëưºî¤·Â³¤±¤ë¤³¤È¤¬¤Ç¤­¤ë¡¥
- : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
-
- mainloop_abort_on_exception
- : Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¾å¤ÇÎã³°¤òȯÀ¸¤·¤¿ºÝ¤Ë¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò¥¨
- : ¥é¡¼Ää»ß¤µ¤»¤ë¤«¤É¤¦¤«¤ÎÀßÄê¾õÂÖ¤ò true/false ¤ÇÆÀ¤ë¡¥
-
- num_of_mainwindows
- : ¸½ºß¤Î¥á¥¤¥ó¥¦¥£¥ó¥É¥¦ (¥ë¡¼¥È¥¦¥£¥¸¥§¥Ã¥È) ¤Î¿ô¤òÊÖ¤¹¡¥
- : ¥á¥¤¥ó¥¦¥£¥ó¥É¥¦¤Ï°ì¤Ä¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ËÉÕ¤­ºÇÂç°ì¤Ä¤Ç¤¢¤ë
- : ¤Î¤Ç¡¤¤³¤ÎÃͤϸ½ºß Tk ¤Îµ¡Ç½¤¬Í­¸ú¤Ç¤¢¤ë¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ÎÁí
- : ¿ô¤ËÅù¤·¤¤¡¥
-
- _merge_tklist(str, str, ... )
- : Tcl/Tk ¤Î¥é¥¤¥Ö¥é¥ê´Ø¿ô¤ò»È¤Ã¤Æ¡¤°ú¿ô¤Îʸ»úÎ󤬤½¤ì¤¾¤ì
- : Àµ¤·¤¯°ì¤Ä¤Î¥ê¥¹¥ÈÍ×ÁǤȤʤë¤è¤¦¤ËÏ¢·ë¤·¤¿Ê¸»úÎó¤òÊÖ¤¹¡¥
-
- _conv_listelement(str)
- : Tcl/Tk ¤Î¥é¥¤¥Ö¥é¥ê´Ø¿ô¤ò»È¤Ã¤Æ¡¤°ú¿ô¤Îʸ»úÎó¤¬ Tcl ¤Î
- : °ì¤Ä¤Î¥ê¥¹¥ÈÍ×ÁǤȤ·¤ÆÅ¬ÀÚ¤Êɽ¸½¤Ë¤Ê¤ë¤è¤¦¤ËÊÑ´¹¤·¤¿Ê¸
- : »úÎó¤òÊÖ¤¹¡¥
-
- _toUTF8(str, encoding=nil)
- _fromUTF8(str, encoding=nil)
- : Tcl/Tk ¤¬Æâ¢¤·¤Æ¤¤¤ë UTF8 ÊÑ´¹½èÍý¤ò¸Æ¤Ó½Ð¤¹¡¥
-
- _subst_UTF_backslash(str)
- _subst_Tcl_backslash(str)
- : Tcl ¤Î¥ë¡¼¥ë¤Ç¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥åµ­Ë¡ ( \uhhhh ¤Ë¤è¤ë
- : Unicode ʸ»úɽ¸½¤ò´Þ¤à ) ¤ò²òÀϤ¹¤ë¡¥
- : _subst_Tcl_backslash ¤Ï¤¹¤Ù¤Æ¤Î¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥åµ­Ë¡¤ò
- : ÃÖ¤­´¹¤¨¤ë¤Î¤ËÂФ·¡¤_subst_UTF_backslash ¤Ï \uhhhh
- : ¤Ë¤è¤ë Unicode ʸ»úɽ¸½¤À¤±¤òÃÖ¤­´¹¤¨¤ë¡¥
-
- encoding_system
- encoding_system=(encoding)
- : Tcl ¤Î system encoding ¤Î³ÍÆÀ¤ª¤è¤ÓÀßÄê
-
- encoding
- encoding=(encoding)
- : encoding_system / encoding_system= ¤Î alias
- : ( Ruby/Tk ¤Î tk.rb ¤Ç¤ÏÃÖ¤­´¹¤¨¤é¤ì¤ëͽÄê¤Î¤â¤Î¡¥)
-
-
-¥¯¥é¥¹ TclTkIp
- ¥¯¥é¥¹¥á¥½¥Ã¥É
- new(ip_name=nil, options='')
- : TclTkIp ¥¯¥é¥¹¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤¹¤ë¡¥
- : ip_name ¤Ëʸ»úÎó¤òÍ¿¤¨¤¿¾ì¹ç¤Ï¡¤¤½¤ì¤¬ winfo interps ¤Ê¤É¤Ç
- : ɽ¼¨¤µ¤ì¤ë̾Á°¤Ë¤Ê¤ë¡¥
- : options ¤Ë¤Ï¡¤-geometry ¤ä -use ¤Ê¤É¡¤wish ¤Î¥³¥Þ¥ó¥É¥é¥¤¥ó
- : °ú¿ô¤È¤·¤ÆÍ¿¤¨¤ë¥ª¥×¥·¥ç¥ó¤ÈƱÍͤξðÊó¤òʸ»úÎó¤È¤·¤ÆÍ¿¤¨¤ë¡¥
- : Í¿¤¨¤é¤ì¤¿¾ðÊó¤Ï¡¤root widget À¸À®¤ÎºÝ¤ËÍѤ¤¤é¤ì¤ë¡¥
- : ( e.g. TclTkIp.new('FOO', '-geometry 500x200 -use 0x2200009') )
- : ¤â¤· options ¤Ë´º¤¨¤Æ nil ¤Þ¤¿¤Ï false ¤òÍ¿¤¨¤¿¾ì¹ç¡¤Tk ¥é¥¤
- : ¥Ö¥é¥ê¤¬Æ³Æþ¤µ¤ì¤Æ¤¤¤Ê¤¤ (¤Ä¤Þ¤ê¤Ï Tcl ¤Î¤ß¤Î) ¥¤¥ó¥¿¡¼¥×¥ê
- : ¥¿¤òÀ¸À®¤¹¤ë¡¥¤³¤Î¾ì¹ç¤Ï GUI ´Ä¶­¤ÏɬÍפʤ¤¤¿¤á¡¤¥¦¥¤¥ó¥É¥¦
- : ¥·¥¹¥Æ¥à¤¬Â¸ºß¤·¤Ê¤¤¡¤¤Þ¤¿¤Ï»ÈÍѤǤ­¤Ê¤¤´Ä¶­¤Ç¤â Tcl ¥¤¥ó¥¿¡¼
- : ¥×¥ê¥¿¤òÀ¸À®¤·¡¤Tcl ¤ä¤½¤Î³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ò³èÍѤ¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡¥
-
- ¥¤¥ó¥¹¥¿¥ó¥¹¥á¥½¥Ã¥É
- create_slave(name, safe=false)
- : ¥ì¥·¡¼¥Ð¤ò¿Æ¤È¤¹¤ë name ¤È¤¤¤¦Ì¾Á°¤Î¥¹¥ì¡¼¥Ö¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò
- : À¸À®¤¹¤ë¡¥
- : safe ¤Ë¤ÏÀ¸À®¤¹¤ë¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤È¤¹¤ë
- : ¤«¤ò»ØÄꤹ¤ë¡¥¥Ç¥Õ¥©¥ë¥È¤Ï false ¤È¤¤¤¦¤³¤È¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤¬¡¤
- : ¤¿¤È¤¨ÌÀ³Î¤Ë false ¤ò»ØÄꤷ¤Æ¤¤¤¿¤È¤·¤Æ¤â¡¤¿Æ¤È¤Ê¤ë¥¤¥ó¥¿¡¼
- : ¥×¥ê¥¿¤¬ safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ç¤¢¤ì¤Ð¡¤¤½¤ÎÀßÄê¤ò°ú¤­·Ñ¤¤¤Ç
- : safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤È¤·¤ÆÀ¸À®¤µ¤ì¤ë¡¥
- : $SAFE >= 4 ¤Ç¤Ï¡¤safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿°Ê³°¤ÎÀ¸À®¤¬¶Ø»ß¤µ¤ì¤ë¡¥
-
- make_safe
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ËÊѹ¹¤¹¤ë¡¥
- : Ìá¤êÃͤϥ쥷¡¼¥Ð¤Ç¤¢¤ë¥¤¥ó¥¿¡¼¥×¥ê¥¿¼«¿È¤Ç¤¢¤ë¡¥
- : ¼ºÇÔ¤·¤¿¾ì¹ç¤Ï RuntimeError ¤ÎÎã³°¤òȯÀ¸¤¹¤ë¡¥
-
- safe?
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬ safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ç¤¢¤ë¤«¤òÄ´¤Ù¤ë¡¥
- : safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ç¤¢¤ì¤Ð true ¤òÊÖ¤¹¡¥
-
- allow_ruby_exit?
- : ÂоݤȤʤ륤¥ó¥¿¡¼¥×¥ê¥¿¾å¤Îɾ²Á¤Ç¡¤ruby ¤Î exit ´Ø¿ô¤Þ¤¿¤Ï
- : Tcl/Tk ¾å¤Î exit ¥³¥Þ¥ó¥É¤Ë¤è¤Ã¤Æ ruby ¼«ÂΤò½ªÎ»¤µ¤»¤ë¤³¤È
- : ¤òµö¤¹¤«¤É¤¦¤«¤òÊÖ¤¹¡¥
- : µö¤µ¤Ê¤¤¾ì¹ç¤ÏÂоݤΥ¤¥ó¥¿¡¼¥×¥ê¥¿¤À¤±¤¬½ªÎ»¤¹¤ë¡¥
- : ¥Þ¥¹¥¿¡¼¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï true¡¤¥¹¥ì¡¼¥Ö¥¤¥ó¥¿¡¼
- : ¥×¥ê¥¿¤Î¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï false ¤Ç¤¢¤ë¡¥
-
- allow_ruby_exit=(mode)
- : ÂоݤȤʤ륤¥ó¥¿¡¼¥×¥ê¥¿¤Î allow_ruby_exit? ¤Î¾õÂÖ¤òÊѹ¹¤¹¤ë¡¥
- : $SAFE >= 4 ¤Þ¤¿¤Ï¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬ safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î¾ì¹ç¤Ï
- : Êѹ¹¤¬µö¤µ¤ì¤Ê¤¤ (Îã³°¤òȯÀ¸)¡¥
-
- delete
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò delete ¤¹¤ë¡¥
- : delete ¤µ¤ì¤¿¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ï¡¤°Ê¸å°ìÀÚ¤ÎÁàºî¤¬¤Ç¤­¤Ê¤¯¤Ê¤ê¡¤
- : ¥³¥Þ¥ó¥É¤òÁ÷¤Ã¤Æ¤âÎã³°¤òȯÀ¸¤¹¤ë¤è¤¦¤Ë¤Ê¤ë¡¥
-
- deleted?
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬¤¹¤Ç¤Ë delete ¤µ¤ì¤Æ¤¤¤ë¤«¤òÄ´¤Ù¤ë¡¥
- : delete ºÑ¤ß¤Ç¥³¥Þ¥ó¥É¤ò¼õ¤±ÉÕ¤±¤Ê¤¤¾õÂ֤ˤʤäƤ¤¤ë¤Ê¤é¤Ð
- : true ¤òÊÖ¤¹¡¥
-
- has_mainwindow?
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ë¥á¥¤¥ó¥¦¥£¥ó¥É¥¦ (root widget) ¤¬
- : ¸ºß¤¹¤ì¤Ð true ¤ò¡¤Â¸ºß¤·¤Ê¤±¤ì¤Ð false ¤òÊÖ¤¹¡¥
- : ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬´û¤Ë delete ºÑ¤ß¤Ç¤¢¤ì¤Ð nil ¤òÊÖ¤¹¡¥
-
- restart
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î Tk Éôʬ¤Î½é´ü²½¡¤ºÆµ¯Æ°¤ò¹Ô¤¦¡¥
- : °ìö root widget ¤òÇ˲õ¤·¤¿¸å¤ËºÆÅÙ Tk ¤Îµ¡Ç½¤¬É¬ÍפÈ
- : ¤Ê¤Ã¤¿¾ì¹ç¤ËÍѤ¤¤ë¡¥
- : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
-
- _eval(str)
- _invoke(*args)
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¾å¤Çɾ²Á¤ò¹Ô¤¦¡¥
- : _eval ¤Ïɾ²Á¥¹¥¯¥ê¥×¥È¤¬°ì¤Ä¤Îʸ»úÎó¤Ç¤¢¤ë¤³¤È¤ËÂФ·¡¤
- : _invoke ¤Ïɾ²Á¥¹¥¯¥ê¥×¥È¤Î token ¤´¤È¤Ë°ì¤Ä¤Î°ú¿ô¤È¤Ê
- : ¤ë¤è¤¦¤ËÍ¿¤¨¤ë¡¥
- : _invoke ¤ÎÊý¤Ï Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î»ú¶ç²òÀÏ´ï¤òÍѤ¤
- : ¤Ê¤¤¤¿¤á¡¤É¾²Á¤ÎÉé²Ù¤¬¤è¤ê¾¯¤Ê¤¯¤Æ¤¹¤à¡¥¤¿¤À¤·¡¤¤½¤ÎÂå
- : ¤ï¤ê¤Ë auto_load ¤Î¤è¤¦¤Êµ¡¹½¤ÏƯ¤«¤º¡¤load Åù¤Ë¤è¤Ã¤Æ
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¾å¤Ë´û¤ËÅÐÏ¿ºÑ¤ß¤Î¥³¥Þ¥ó¥É¤·¤«¸Æ
- : ¤Ó½Ð¤¹¤³¤È¤¬¤Ç¤­¤Ê¤¤¡¥
- : _eval ¤Ç¤Ï auto_load µ¡¹½¤¬Æ¯¤¯¤¿¤á¡¤°ìÅÙ _eval ¤ò¼Â¹Ô
- : ¤·¤ÆÅÐÏ¿¤ËÀ®¸ù¤·¤µ¤¨¤¹¤ì¤Ð¡¤°Ê¹ß¤Ï _invoke ¤Ç¤âÍøÍѤÇ
- : ¤­¤ë¤è¤¦¤Ë¤Ê¤ë¡¥
-
- _toUTF8(str, encoding=nil)
- _fromUTF8(str, encoding=nil)
- : Tcl/Tk ¤¬Æâ¢¤·¤Æ¤¤¤ë UTF8 ÊÑ´¹½èÍý¤ò¸Æ¤Ó½Ð¤¹¡¥
-
- _thread_vwait(var_name)
- _thread_tkwait(mode, target)
- : ¥¹¥ì¥Ã¥ÉÂбþ¤Î vwait ¤¢¤ë¤¤¤Ï tkwait ÁêÅö¤Î¥á¥½¥Ã¥É¡¥
- : Ä̾ï¤Î vwait ¤¢¤ë¤¤¤Ï tkwait ¥³¥Þ¥ó¥É¤È°Û¤Ê¤ë¤Î¤Ï¡¤¥¤¥Ù¥ó
- : ¥È¥ë¡¼¥×¤È¤Ï°Û¤Ê¤ë¥¹¥ì¥Ã¥É¤«¤é¸Æ¤Ó½Ð¤·¤¿¾ì¹ç¤Ë vwait Åù¤Î
- : ¥¹¥¿¥Ã¥¯¤È¤ÏÆÈΩ¤Ë¾ò·ï¤ÎÀ®Î©ÂÔ¤Á¤¬¤Ê¤µ¤ì¤ë¤³¤È¤Ç¤¢¤ë¡¥
- : Ä̾ï¤Î vwait / tkwait ¤Ç¤Ï¡¤vwait / tkwait (1) ¤ÎÂÔ¤Á¤ÎÅÓ
- : Ãæ¤Ç¤µ¤é¤Ë vwait / tkwait (2) ¤¬¸Æ¤Ð¤ì¤¿¾ì¹ç¡¤ÂÔ¤Á¤ÎÂоÝ
- : ¤È¤Ê¤Ã¤Æ¤¤¤ë¾ò·ï¤ÎÀ®Î©½ç½ø¤¬¤É¤¦¤¢¤ì¡¤(2)->(1) ¤Î½ç¤ÇÂÔ¤Á
- : ¤ò½ªÎ»¤·¤ÆÌá¤Ã¤Æ¤¯¤ë¡¥
- : _thread_vwait / _thread_tkwait ¤Ï¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×¤Î¥¹¥ì¥Ã
- : ¥É¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¤ÏÄ̾ï¤Î vwait / tkwait ¤ÈƱÍÍ¤ËÆ°ºî¤¹¤ë
- : ¤¬¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×°Ê³°¤Î¥¹¥ì¥Ã¥É¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¤Ë¤Ï¤½¤Î¥¹
- : ¥ì¥Ã¥É¤òÄä»ß¤µ¤»¤ÆÂÔ¤Á¤ËÆþ¤ê¡¤¾ò·ï¤¬À®Î©¤·¤¿»þ¤Ë¥¹¥ì¥Ã¥É
- : ¤Î¼Â¹Ô¤òºÆ³«¤¹¤ë¡¥¡Övwait Åù¤ÎÂÔ¤Á¥¹¥¿¥Ã¥¯¤È¤ÏÆÈΩ¡×¤È¤¤
- : ¤¦°ÕÌ£¤Ï¡¤¤³¤ÎºÆ³«¤Î¥¿¥¤¥ß¥ó¥°¤¬Â¾¤Î¥¹¥ì¥Ã¥É¤Ç¤ÎÂÔ¤Á¾õ¶·
- : ¤È¤Ï̵´Ø·¸¤È¤¤¤¦¤³¤È¤Ç¤¢¤ë¡¥¤Ä¤Þ¤ê¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×Åù¤Î¾
- : ¤Î¥¹¥ì¥Ã¥É¤Ç vwait Åù¤ÇÂÔ¤Á¤Î¾õÂ֤ˤ¢¤Ã¤¿¤È¤·¤Æ¤â¤½¤Î´°Î»
- : ¤òÂԤĤ³¤È¤Ê¤¯¡¤¼«¤é¤ÎÂÔ¤Á¾ò·ï¤¬À®Î©¼¡Â衤½èÍý¤ò·Ñ³¤¹¤ë
- : ¤³¤È¤Ë¤Ê¤ë¡¥
-
- _return_value
- : ľÁ°¤Î Tcl/Tk ¾å¤Ç¤Îɾ²Á¤Î¼Â¹Ô·ë²Ì¤È¤·¤Æ¤ÎÌá¤êÃͤòÊÖ¤¹¡¥
-
- _get_variable(var_name, flag)
- _get_variable2(var_name, index_name, flag)
- : Tcl/Tk ¾å¤Î var ¤È¤¤¤¦ÊÑ¿ô̾¤ÎÊÑ¿ô¤ÎÃͤòÊÖ¤¹¡¥
- : ¤â¤· index_name ¤¬»ØÄê (PARSE_VARNAME ¥Õ¥é¥°¤ÎÀâÌÀ¤â»²¾È)
- : ¤µ¤ì¤¿¾ì¹ç¤ÏÏ¢ÁÛÇÛÎó var_name ¤Î index_name ¤ÎÍ×ÁǤòÊÖ¤¹¡¥
- : flag ¤Ë¤ÏÊÑ¿ô¤ò¸¡º÷¤¹¤ëºÝ¤Î¾ò·ï¤ò»ØÄꤹ¤ë¡¥flag ¤ËÍ¿¤¨¤ë
- : Ãͤϥ⥸¥å¡¼¥ë TclTkLib::VarAccessFlag ¤ò»²¾È¤¹¤ë¤³¤È¡¥
-
- _set_variable(var_name, value, flag)
- _set_variable2(var_name, index_name, value, flag)
- : Tcl/Tk ¾å¤Î var ¤È¤¤¤¦ÊÑ¿ô̾¤ÎÊÑ¿ô¤ËÃͤòÀßÄꤹ¤ë¡¥
- : ¤â¤· index_name ¤¬»ØÄê (PARSE_VARNAME ¥Õ¥é¥°¤ÎÀâÌÀ¤â»²¾È)
- : ¤µ¤ì¤¿¾ì¹ç¤ÏÏ¢ÁÛÇÛÎó var_name ¤Î index_name ¤ÎÍ×ÁǤòÀßÄê
- : ¤¹¤ë¡¥
- : flag ¤Ë¤ÏÊÑ¿ô¤ò¸¡º÷¤¹¤ëºÝ¤Î¾ò·ï¤ò»ØÄꤹ¤ë¡¥flag ¤ËÍ¿¤¨¤ë
- : Ãͤϥ⥸¥å¡¼¥ë TclTkLib::VarAccessFlag ¤ò»²¾È¤¹¤ë¤³¤È¡¥
-
- _unset_variable(var_name)
- _unset_variable2(var_name, index_name)
- : Tcl/Tk ¾å¤Î var_name ¤È¤¤¤¦ÊÑ¿ô̾¤ÎÊÑ¿ô¤ò¾Ãµî¤¹¤ë¡¥
- : ¤â¤· index_name ¤¬»ØÄê (PARSE_VARNAME ¥Õ¥é¥°¤ÎÀâÌÀ¤â»²¾È)
- : ¤µ¤ì¤¿¾ì¹ç¤ÏÏ¢ÁÛÇÛÎó var_name ¤«¤é index_name ¤ÎÍ×ÁǤÀ¤±
- : ¤ò¾Ãµî¤¹¤ë¡¥
-
- _get_global_var(var_name)
- _get_global_var2(var_name, index_name)
- _set_global_var(var_name, value)
- _set_global_var2(var_name, index_name, value)
- _unset_global_var(var_name)
- _unset_global_var2(var_name, index_name)
- : ¤½¤ì¤¾¤ì¡¤Âбþ¤¹¤ëÊÑ¿ô¥¢¥¯¥»¥¹¥á¥½¥Ã¥É¤Î flag ¤ËÂФ·¤Æ
- : (GLOBAL_ONLY | LEAVE_ERR_MSG) ¤òÍ¿¤¨¤¿¤â¤Î¡¥
-
- _split_tklist(str)
- : Tcl/Tk ¤Î¥é¥¤¥Ö¥é¥ê´Ø¿ô¤ò»È¤Ã¤Æ¡¤Ê¸»úÎó str ¤ò¥ê¥¹¥È¤Ë
- : ʬ³ä¤¹¤ë (ʸ»úÎó¤ÎÇÛÎó¤È¤·¤ÆÊÖ¤¹)¡¥
-
- _merge_tklist(str, str, ... )
- : Tcl/Tk ¤Î¥é¥¤¥Ö¥é¥ê´Ø¿ô¤ò»È¤Ã¤Æ¡¤°ú¿ô¤Îʸ»úÎ󤬤½¤ì¤¾¤ì
- : Àµ¤·¤¯°ì¤Ä¤Î¥ê¥¹¥ÈÍ×ÁǤȤʤë¤è¤¦¤ËÏ¢·ë¤·¤¿Ê¸»úÎó¤òÊÖ¤¹¡¥
-
- _conv_listelement(str)
- : Tcl/Tk ¤Î¥é¥¤¥Ö¥é¥ê´Ø¿ô¤ò»È¤Ã¤Æ¡¤°ú¿ô¤Îʸ»úÎó¤¬ Tcl ¤Î
- : °ì¤Ä¤Î¥ê¥¹¥ÈÍ×ÁǤȤ·¤ÆÅ¬ÀÚ¤Êɽ¸½¤Ë¤Ê¤ë¤è¤¦¤ËÊÑ´¹¤·¤¿Ê¸
- : »úÎó¤òÊÖ¤¹¡¥
-
- mainloop
- mainloop_watchdog
- : ¥¹¥ì¡¼¥Ö IP ¤Î¾ì¹ç¤Ë¤Ï¥¤¥Ù¥ó¥È¥ë¡¼¥×¤òµ¯Æ°¤»¤º¤Ë nil ¤òÊÖ¤¹¡¥
- : ¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï°ú¿ô¤ò´Þ¤á¤Æ TclTkLib ¤ÎƱ̾¥á¥½¥Ã¥É¤ËƱ¤¸¡¥
-
- do_one_event
- : ¥¹¥ì¡¼¥Ö IP ¤Î¾ì¹ç¤Ë¤Ï°ú¿ô¤Î¥¤¥Ù¥ó¥È¥Õ¥é¥°¤Ë DONT_WAIT ¤¬
- : ¶¯À©Åª¤ËÄɲ䵤ì¤ë (¥¤¥Ù¥ó¥ÈÂÔ¤Á¤Ç¥¹¥ê¡¼¥×¤¹¤ë¤³¤È¤Ï¶Ø»ß)¡¥
- : ¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï°ú¿ô¤ò´Þ¤á¤Æ TclTkLib ¤ÎƱ̾¥á¥½¥Ã¥É¤ËƱ¤¸¡¥
-
- set_eventloop_tick
- get_eventloop_tick
- set_no_event_wait
- get_no_event_wait
- set_eventloop_weight
- get_eventloop_weight
- mainloop_abort_on_exception
- mainloop_abort_on_exception=
- : ¥¹¥ì¡¼¥Ö IP ¤Î¾ì¹ç¤Ë¤ÏÃͤÎÀßÄ꤬µö¤µ¤ì¤Ê¤¤ (̵»ë¤µ¤ì¤ë)¡¥
- : ¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï°ú¿ô¤ò´Þ¤á¤Æ TclTkLib ¤ÎƱ̾¥á¥½¥Ã¥É¤ËƱ¤¸¡¥
-
-¥¯¥é¥¹ TkCallbackBreak < StandardError
-¥¯¥é¥¹ TkCallbackContinue < StandardError
- : ¤³¤ì¤é¤Ï¥¤¥Ù¥ó¥È¥³¡¼¥ë¥Ð¥Ã¥¯¤Ë¤ª¤¤¤Æ¡¤¥³¡¼¥ë¥Ð¥Ã¥¯½èÍý¤òŬÀÚ¤ËÃæ
- : ÃǤ·¤¿¤ê¡¤¼¡¤Î¥Ð¥¤¥ó¥É¥¿¥°¤Î¥Ð¥¤¥ó¥Ç¥£¥ó¥°½èÍý¤Ë¿Ê¤á¤¿¤ê¤¹¤ë¤³¤È
- : ¤ò²Äǽ¤Ë¤¹¤ë¤¿¤á¤ÎÎã³°¥¯¥é¥¹¤Ç¤¢¤ë¡¥
- : ¥³¡¼¥ë¥Ð¥Ã¥¯¤Ç break ¤ä continue ¤ò¼Â¸½¤¹¤ë¤¿¤á¤Ë¤Ï¡¤¥³¡¼¥ë¥Ð¥Ã¥¯
- : ¤Ç¤¢¤ë Ruby ¼ê³¤­¤¬ Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿Â¦¤ËŬÀڤʥ꥿¡¼¥ó¥³¡¼
- : ¥É¤òÊÖ¤¹É¬Íפ¬¤¢¤ë¡¥Ruby ¤Î¼ê³¤­¤¬ÉáÄ̤ËÃͤòÊÖ¤¹¤Î¤Ç¤Ï¡¤¤½¤ì¤¬Éá
- : Ä̤ÎÌá¤êÃͤǤ¢¤ë¤Î¤«Èݤ«¤ò¶èÊ̤¬¤Ç¤­¤Ê¤¤¤¿¤á¡¤Î㳰ȯÀ¸¤òÍøÍѤ·¤¿
- : ¼ÂÁõ¤ò¹Ô¤Ã¤Æ¤¤¤ë¡¥
-
-(eof)
diff --git a/ext/tk/README.1st b/ext/tk/README.1st
deleted file mode 100644
index df6c819d26..0000000000
--- a/ext/tk/README.1st
+++ /dev/null
@@ -1,22 +0,0 @@
-If you want to use Ruby/Tk (tk.rb and so on), you must have tcltklib.so
-which is working correctly. If you fail to call 'require "tcltklib"',
-you may not have tcltklib.so. When you have some troubles on compiling
-tcltklib, please read README files on tcltklib.
-Even if there is a tcltklib.so on your Ruby library directry, it will not
-work without Tcl/Tk libraries (e.g. libtcl8.4.so) on your environment.
-You must also check that your Tcl/Tk is installed properly.
-
---------------------------------------------
- ( the following is written in EUC-JP )
-
-Ruby/Tk (tk.rb ¤Ê¤É) ¤ò»È¤¤¤¿¤¤¾ì¹ç¤Ë¤Ï¡¤tcltklib.so ¤¬Àµ¤·¤¯Æ°¤¤¤Æ
-¤¤¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡¥¤â¤· 'require "tcltklib"' ¤Ë¼ºÇÔ¤¹¤ë¤è¤¦¤Ê¤é¡¤
-tcltklib.so ¤¬¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Æ¤¤¤Ê¤¤¤Î¤«¤â¤·¤ì¤Þ¤»¤ó¡¥tcltklib ¤Î
-¥³¥ó¥Ñ¥¤¥ë»þ¤Ë²¿¤«ÌäÂ꤬À¸¤¸¤Æ¤¤¤ë¾ì¹ç¤Ï¡¤tcltklib ¤Î README ¥Õ¥¡¥¤¥ë
-¤ò¸«¤Æ¤¯¤À¤µ¤¤¡¥
-¤¿¤È¤¨ Ruby ¤Î¥é¥¤¥Ö¥é¥ê¥Ç¥£¥ì¥¯¥È¥ê¤Ë tcltklib.so ¤¬Â¸ºß¤·¤Æ¤¤¤¿¤È¤·¤Æ
-¤â¡¤¼Â¹Ô´Ä¶­¤Ë Tcl/Tk ¥é¥¤¥Ö¥é¥ê (libtcl8.4.so ¤Ê¤É) ¤¬¤Ê¤±¤ì¤Ðµ¡Ç½¤·¤Þ
-¤»¤ó¡¥Tcl/Tk ¤¬Àµ¤·¤¯¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Æ¤¤¤ë¤«¤â¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡¥
-
-==========================================================
- Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
diff --git a/ext/tk/README.ActiveTcl b/ext/tk/README.ActiveTcl
deleted file mode 100644
index 3afb3f4cf6..0000000000
--- a/ext/tk/README.ActiveTcl
+++ /dev/null
@@ -1,49 +0,0 @@
-ActiveTcl is ActiveState's quality-assured distribution of Tcl.
-
-# see <http://www.activestate.com/Products/ActiveTcl/>
-# <http://www.tcl.tk/>
-
-If you want to use ActiveTcl binary package as the Tcl/Tk libraries,
-please use the following configure options.
-
- --with-tcl-dir=<ActiveTcl_root>
- --with-tk-dir=<ActiveTcl_root>
-
-And use the followings if you need.
-
- --with-tcllib=<libname>
- --with-tklib=<libname>
- --enable-tcltk-stubs
-
-For example, when you install ActiveTcl-8.4.x to '/usr/local/ActiveTcl',
-
- configure --with-tcl-dir=/usr/local/ActiveTcl/ \
- --with-tk-dir=/usr/local/ActiveTcl/ \
- --with-tcllib=tclstub8.4 \
- --with-tklib=tkstub8.4 \
- --enable-tcltk-stubs
-
-It depends on your environment that you have to add the directory of
-ActiveTcl's libraries to your library path when execute Ruby/Tk.
-One of the way is to add entries to TCLLIBPATH environment variable,
-and one of the others add to LD_LIBRARY_PATH environment variable
-
-Probably, using TCLLIBPATH is better. The value is appended at the
-head of Tcl's 'auto_path' variable. You can see the value of the
-variable by using 'Tk::AUTO_PATH.value' or 'Tk::AUTO_PATH.list'.
-
-For example, on Linux, one of the ways is to use LD_LIBRARY_PATH
-environment variable.
--------------------------------------------------------------------------
- [bash]$ LD_LIBRARY_PATH=/usr/local/ActiveTcl/lib:$LD_LIBRARY_PATH \
- ruby your-Ruby/Tk-script
-
- [bash]$ LD_LIBRARY_PATH=/usr/local/ActiveTcl/lib:$LD_LIBRARY_PATH irb
--------------------------------------------------------------------------
-Based on it, the Tcl interpreter changes auto_path variable's value.
-
-Then, you'll be able to use Tcl/Tk extension libraries included in the
-ActiveTcl package (e.g. call TkPackage.require('BWidget'), and then,
-use functions/widgets of BWidget extention).
-
- Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
diff --git a/ext/tk/README.fork b/ext/tk/README.fork
deleted file mode 100644
index 707d78fc12..0000000000
--- a/ext/tk/README.fork
+++ /dev/null
@@ -1,34 +0,0 @@
-Ruby/Tk does NOT support forking the process on which Tk interpreter
-is running (unless NEVER control Tk interpreter under the forked child
-process). In the library 'tk.rb', a Tk interpreter is initialized.
-Therefore, if you want running Tk under a child process, please call
-"require 'tk'" in the child process.
-
-# If do fork and exec(<new Ruby/Tk>) on the child process, you can
-# control Ruby/Tk interpreter on the child process by 'send' command
-# of Tcl/Tk. About this, please see Tk.appsend and Tk.rb_appsend, or
-# 'remote-tk.rb' and the sample 'sample/remote-ip_sample.rb'.
-
-For example, the following sample1 will NOT work, and sample2 will
-work properly.
-
----<sample1: NOT work>---------------------------------------
-require 'tk' ## init Tk interpreter under parent process
-
-exit! if fork ## exit parent process
-
-## child process
-TkButton.new(:text=>'QUIT', :command=>proc{exit}).pack
-Tk.mainloop
--------------------------------------------------------------
-
----<sample2: will work>--------------------------------------
-exit! if fork ## exit main process
-
-## child process
-require 'tk' ## init Tk interpreter under child process
-TkButton.new(:text=>'QUIT', :command=>proc{exit}).pack
-Tk.mainloop
--------------------------------------------------------------
-
- 2004/05/22 Hidetoshi NAGAI
diff --git a/ext/tk/README.macosx-aqua b/ext/tk/README.macosx-aqua
deleted file mode 100644
index 25a8ed827c..0000000000
--- a/ext/tk/README.macosx-aqua
+++ /dev/null
@@ -1,67 +0,0 @@
-
- *** for MacOS X Aqua (Tcl/Tk Aqua) users ***
-
-First of all, please read README.tcltklib to use Tcl/Tk Aqua Framework.
-
-With Tcl/Tk Aqua libraries, current tcltklib somtimes freezes when
-using Aqua specific dialogs (e.g. Tk.messageBox).
-This is a known bug of Ruby-1.8.4 release.
-
-When you meet the trouble on your GUI, you'll be able to avoid the trouble
-by Tcl/Tk's traditional dialogs.
-If you want to do that, please call some of the following bits of script
-after "reqruie 'tk'".
-
-=================================================================
-# use a traditional dialog for Tk.chooseColor()
-Tk.ip_eval(<<'EOS')
- proc ::tk_chooseColor {args} {
- return [eval tk::dialog::color:: $args]
- }
-EOS
-
-# use a traditional dialog for Tk.getOpenFile() and Tk.getMultipleOpenFile()
-Tk.ip_eval(<<'EOS')
- proc ::tk_getOpenFile {args} {
- if {$::tk_strictMotif} {
- return [eval tk::MotifFDialog open $args]
- } else {
- return [eval ::tk::dialog::file:: open $args]
- }
- }
-EOS
-
-# use a traditional dialog for Tk.getSaveFile() and Tk.getMultipleSaveFile()
-Tk.ip_eval(<<'EOS')
- proc ::tk_getSaveFile {args} {
- if {$::tk_strictMotif} {
- return [eval tk::MotifFDialog save $args]
- } else {
- return [eval ::tk::dialog::file:: save $args]
- }
- }
-EOS
-
-# use a traditional dialog for Tk.messageBox()
-Tk.ip_eval(<<'EOS')
- proc ::tk_messageBox {args} {
- return [eval tk::MessageBox $args]
- }
-EOS
-
-# use a traditional dialog for Tk.chooseDirectory()
-Tk.ip_eval(<<'EOS')
- proc ::tk_chooseDirectory {args} {
- return [eval ::tk::dialog::file::chooseDir:: $args]
- }
-EOS
-=================================================================
-
-Each of them replaces the platform specific dialog command to the
-traditional one.
-
-If you use some MultiTkIp objects, probably, you'll have to call the
-bits of script for each MultiTkIp object.
-
---
-Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
diff --git a/ext/tk/README.tcltklib b/ext/tk/README.tcltklib
deleted file mode 100644
index 5d1da48a45..0000000000
--- a/ext/tk/README.tcltklib
+++ /dev/null
@@ -1,72 +0,0 @@
-To compile 'tcltklib', you must have Tcl/Tk libraries on your environment.
-Although 'extconf.rb' script searches Tcl/Tk libraries and header files,
-sometimes fails to find them. And then, 'tcltklib' cannot be compiled. If
-Tcl/Tk libraries or header files are installed but are not found, you can
-give the information by arguments of the 'configure' script. Please give
-some or all of the following options.
-
- --with-tcllib=<libname> (e.g. libtcl8.4.so ==> --with-tcllib=tcl8.4)
- --with-tklib=<libname> (e.g. libtk8.4.so ==> --with-tklib=tk8.4)
-
- --enable-tcltk_stubs (if you force to enable stubs)
-
- --with-tcl-dir=<path>
- equal to "--with-tcl-include=<path>/include --with-tcl-lib=<path>/lib"
-
- --with-tk-dir=<path>
- equal to "--with-tk-include=<path>/include --with-tk-lib=<path>/lib"
-
- --with-tcl-include=<dir> the directry containts 'tcl.h'
- --with-tk-include=<dir> the directry containts 'tk.h'
-
- --with-tcl-lib=<dir> the directry containts 'libtcl<version>.so'
- --with-tk-lib=<dir> the directry containts 'libtk<version>.so'
-
- --enable-mac-tcltk-framework (MacOS X) use Tcl/Tk framework
- (Obsolete. Please use '--enable-tcltk-framework'.)
-
- --enable-tcltk-framework use Tcl/Tk framework
-
- --with-tcltk-framework=<dir> the directory containts Tcl/Tk framework;
- "<dir>/Tcl.framework" and "<dir>/Tk.framework".
- When this option is given, it is assumed that
- --enable-tcltk-framework option is given also.
-
- --with-tcl-framework-header=<dir>
- Tcl framework headers directory
- (e.g. "/Library/Frameworks/Tcl.framework/Headers")
-
- --with-tk-framework-header=<dir>
- Tk framework headers directory
- (e.g. "/Library/Frameworks/Tk.framework/Headers")
-
-
-If you forgot to give the options when do 'configure' on toplevel
-directry of Ruby sources, please try something like as the followings.
-
- $ cd ext/tcltklib
- $ rm Makefile
- $ CONFIGURE_ARGS='--with-tcl-include=/usr/local/include/tcl8.4/ --with-tcllib=tcl8.4 --with-tklib=tk8.4' ruby extconf.rb
-
-
- *** ATTENTION ***
-When your Tcl/Tk libraries are compiled with "pthread support",
-Ruby/Tk may cause "Hang-up" or "Segmentation Fault" frequently.
-If you have such a trouble, please try to use the '--enable-pthread'
-option of the 'configure' command and re-compile Ruby sources.
-It may help you to avoid this trouble. The following configure
-options may be useful.
-
- --enable-tcl-thread/--disable-tcl-thread
- --with-tclConfig-file=<path of 'tclConfig.sh'>
-
-It is not need that 'tclConfig.sh' is a normal Tcl/Tk's tclConfig.sh.
-But the file is expected to include the line "TCL_THREADS=0" or "...=1".
-When no "TCL_THREADS=?" line, if Tcl version is 7.x or 8.0 which is
-given by "TCL_MAJOR_VERSION=?" line and "TCL_MINOR_VERSION=?" line,
-then --disable-tcl-thread is expected. Else, ignore the 'tclConfig.sh'.
-If --enable-tcl-thread or --disable-tcl-thread option is given, then
---with-tclConfig-file option is ignored.
-
-==========================================================
- Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
diff --git a/ext/tk/depend b/ext/tk/depend
deleted file mode 100644
index 2cd9c400f7..0000000000
--- a/ext/tk/depend
+++ /dev/null
@@ -1,2 +0,0 @@
-tcltklib.o: tcltklib.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
-stubs.o: stubs.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/tk/extconf.rb b/ext/tk/extconf.rb
deleted file mode 100644
index 8c8d833481..0000000000
--- a/ext/tk/extconf.rb
+++ /dev/null
@@ -1,309 +0,0 @@
-# extconf.rb for tcltklib
-
-require 'mkmf'
-
-is_win32 = (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM)
-#is_macosx = (/darwin/ =~ RUBY_PLATFORM)
-
-def find_framework(tcl_hdr, tk_hdr)
- if framework_dir = with_config("tcltk-framework")
- paths = [framework_dir]
- else
- unless tcl_hdr || tk_hdr ||
- enable_config("tcltk-framework", false) ||
- enable_config("mac-tcltk-framework", false)
- return false
- end
- paths = ["/Library/Frameworks", "/System/Library/Frameworks"]
- end
-
- checking_for('Tcl/Tk Framework') {
- paths.find{|dir|
- dir.strip!
- dir.chomp!('/')
- (tcl_hdr || FileTest.directory?(dir + "/Tcl.framework/") ) &&
- (tk_hdr || FileTest.directory?(dir + "/Tk.framework/") )
- }
- }
-end
-
-tcl_framework_header = with_config("tcl-framework-header")
-tk_framework_header = with_config("tk-framework-header")
-
-tcltk_framework = find_framework(tcl_framework_header, tk_framework_header)
-
-unless is_win32
- have_library("nsl", "t_open")
- have_library("socket", "socket")
- have_library("dl", "dlopen")
- have_library("m", "log")
-end
-
-dir_config("tk")
-dir_config("tcl")
-dir_config("X11")
-
-tklib = with_config("tklib")
-tcllib = with_config("tcllib")
-stubs = enable_config("tcltk_stubs") || with_config("tcltk_stubs")
-
-def find_tcl(tcllib, stubs)
- paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
- if stubs
- func = "Tcl_InitStubs"
- lib = "tclstub"
- else
- func = "Tcl_FindExecutable"
- lib = "tcl"
- end
- if tcllib
- find_library(tcllib, func, *paths)
- elsif find_library(lib, func, *paths)
- true
- else
- %w[8.5 8.4 8.3 8.2 8.1 8.0 7.6].find { |ver|
- find_library("#{lib}#{ver}", func, *paths) or
- find_library("#{lib}#{ver.delete('.')}", func, *paths) or
- find_library("tcl#{ver}", func, *paths) or
- find_library("tcl#{ver.delete('.')}", func, *paths)
- }
- end
-end
-
-def find_tk(tklib, stubs)
- paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
- if stubs
- func = "Tk_InitStubs"
- lib = "tkstub"
- else
- func = "Tk_Init"
- lib = "tk"
- end
- if tklib
- find_library(tklib, func, *paths)
- elsif find_library(lib, func, *paths)
- true
- else
- %w[8.5 8.4 8.3 8.2 8.1 8.0 4.2].find { |ver|
- find_library("#{lib}#{ver}", func, *paths) or
- find_library("#{lib}#{ver.delete('.')}", func, *paths) or
- find_library("tk#{ver}", func, *paths) or
- find_library("tk#{ver.delete('.')}", func, *paths)
- }
- end
-end
-
-def pthread_check()
- tcl_major_ver = nil
- tcl_minor_ver = nil
-
- # Is tcl-thread given by user ?
- case enable_config("tcl-thread")
- when true
- tcl_enable_thread = true
- when false
- tcl_enable_thread = false
- else
- tcl_enable_thread = nil
- end
-
- if (tclConfig = with_config("tclConfig-file"))
- if tcl_enable_thread == true
- puts("Warning: --with-tclConfig-file option is ignored, because --enable-tcl-thread option is given.")
- elsif tcl_enable_thread == false
- puts("Warning: --with-tclConfig-file option is ignored, because --disable-tcl-thread option is given.")
- else
- # tcl-thread is unknown and tclConfig.sh is given
- begin
- open(tclConfig, "r") do |cfg|
- while line = cfg.gets()
- if line =~ /^\s*TCL_THREADS=(0|1)/
- tcl_enable_thread = ($1 == "1")
- break
- end
-
- if line =~ /^\s*TCL_MAJOR_VERSION=("|')(\d+)\1/
- tcl_major_ver = $2
- if tcl_major_ver =~ /^[1-7]$/
- tcl_enable_thread = false
- break
- end
- if tcl_major_ver == "8" && tcl_minor_ver == "0"
- tcl_enable_thread = false
- break
- end
- end
-
- if line =~ /^\s*TCL_MINOR_VERSION=("|')(\d+)\1/
- tcl_minor_ver = $2
- if tcl_major_ver == "8" && tcl_minor_ver == "0"
- tcl_enable_thread = false
- break
- end
- end
- end
- end
-
- if tcl_enable_thread == nil
- # not find definition
- if tcl_major_ver
- puts("Warning: '#{tclConfig}' doesn't include TCL_THREADS definition.")
- else
- puts("Warning: '#{tclConfig}' may not be a tclConfig file.")
- end
- tclConfig = false
- end
- rescue Exception
- puts("Warning: fail to read '#{tclConfig}'!! --> ignore the file")
- tclConfig = false
- end
- end
- end
-
- if tcl_enable_thread == nil && !tclConfig
- # tcl-thread is unknown and tclConfig is unavailable
- begin
- try_run_available = try_run("int main() { exit(0); }")
- rescue Exception
- # cannot try_run. Is CROSS-COMPILE environment?
- puts(%Q'\
-*****************************************************************************
-**
-** PTHREAD SUPPORT CHECK WARNING:
-**
-** We cannot check the consistency of pthread support between Ruby
-** and the Tcl/Tk library in your environment (are you perhaps
-** cross-compiling?). If pthread support for these 2 packages is
-** inconsistent you may find you get errors when running Ruby/Tk
-** (e.g. hangs or segmentation faults). We strongly recommend
-** you to check the consistency manually.
-**
-*****************************************************************************
-')
- return true
- end
- end
-
- if tcl_enable_thread == nil
- # tcl-thread is unknown
- if try_run(<<EOF)
-#include <tcl.h>
-int main() {
- Tcl_Interp *ip;
- ip = Tcl_CreateInterp();
- exit((Tcl_Eval(ip, "set tcl_platform(threaded)") == TCL_OK)? 0: 1);
-}
-EOF
- tcl_enable_thread = true
- elsif try_run(<<EOF)
-#include <tcl.h>
-static Tcl_ThreadDataKey dataKey;
-int main() { exit((Tcl_GetThreadData(&dataKey, 1) == dataKey)? 1: 0); }
-EOF
- tcl_enable_thread = true
- else
- tcl_enable_thread = false
- end
- end
-
- # check pthread mode
- if (macro_defined?('HAVE_NATIVETHREAD', '#include "ruby.h"'))
- # ruby -> enable
- unless tcl_enable_thread
- # ruby -> enable && tcl -> disable
- puts(%Q'\
-*****************************************************************************
-**
-** PTHREAD SUPPORT MODE WARNING:
-**
-** Ruby is compiled with --enable-pthread, but your Tcl/Tk library
-** seems to be compiled without pthread support. Although you can
-** create the tcltklib library, this combination may cause errors
-** (e.g. hangs or segmentation faults). If you have no reason to
-** keep the current pthread support status, we recommend you reconfigure
-** and recompile the libraries so that both or neither support pthreads.
-**
-** If you want change the status of pthread support, please recompile
-** Ruby without "--enable-pthread" configure option or recompile Tcl/Tk
-** with "--enable-threads" configure option (if your Tcl/Tk is later
-** than or equal to Tcl/Tk 8.1).
-**
-*****************************************************************************
-')
- end
-
- # ruby -> enable && tcl -> enable/disable
- if tcl_enable_thread
- $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=1'
- else
- $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=0'
- end
-
- return true
-
- else
- # ruby -> disable
- if tcl_enable_thread
- # ruby -> disable && tcl -> enable
- puts(%Q'\
-*****************************************************************************
-**
-** PTHREAD SUPPORT MODE ERROR:
-**
-** Ruby is not compiled with --enable-pthread, but your Tcl/Tk
-** library seems to be compiled with pthread support. This
-** combination may cause frequent hang or segmentation fault
-** errors when Ruby/Tk is working. We recommend that you NEVER
-** create the library with such a combination of pthread support.
-**
-** Please recompile Ruby with the "--enable-pthread" configure option
-** or recompile Tcl/Tk with the "--disable-threads" configure option.
-**
-*****************************************************************************
-')
- $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=1'
- return false
- else
- # ruby -> disable && tcl -> disable
- $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=0'
- return true
- end
- end
-end
-
-if tcltk_framework ||
- (have_header("tcl.h") && have_header("tk.h") &&
- (is_win32 || find_library("X11", "XOpenDisplay",
- "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib")) &&
- find_tcl(tcllib, stubs) &&
- find_tk(tklib, stubs))
- $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs
- $CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM
-
- if tcltk_framework
- if tcl_framework_header
- $CPPFLAGS += " -I#{tcl_framework_header}"
- else
- $CPPFLAGS += " -I#{tcltk_framework}/Tcl.framework/Headers"
- end
-
- if tk_framework_header
- $CPPFLAGS += " -I#{tk_framework_header}"
- else
- $CPPFLAGS += " -I#{tcltk_framework}/Tk.framework/Headers"
- end
-
- $LDFLAGS += ' -framework Tk -framework Tcl'
- end
-
- if stubs or pthread_check
- # create Makefile
-
- # for SUPPORT_STATUS
- $INSTALLFILES ||= []
- $INSTALLFILES << ["lib/tkextlib/SUPPORT_STATUS", "$(RUBYLIBDIR)", "lib"]
-
- # create
- create_makefile("tcltklib")
- end
-end
diff --git a/ext/tk/lib/README b/ext/tk/lib/README
deleted file mode 100644
index 5918fe4bf0..0000000000
--- a/ext/tk/lib/README
+++ /dev/null
@@ -1,30 +0,0 @@
-README this file
-multi-tk.rb multiple Tk interpreter (included safe-Tk) support
-remotei-tk.rb control remote Tk interpreter on the other process support
-tk.rb Tk interface
-
-tk/ library files construct Ruby/Tk
-
-tkextlib/ non-standard Tcl/Tk extension support libraries
-
-*********************************************************************
-*** The followings exists for backward compatibility only.
-*** The only thing which they work is that requires current
-*** library files ( tk/*.rb ).
-*********************************************************************
-tkafter.rb handles Tcl after
-tkbgerror.rb Tk error module
-tkcanvas.rb Tk canvas interface
-tkclass.rb provides generic names for Tk classes
-tkconsole.rb console command support
-tkdialog.rb Tk dialog class
-tkentry.rb Tk entry class
-tkfont.rb Tk font support
-tkmacpkg.rb Mac resource support
-tkmenubar.rb TK menubar utility
-tkmngfocus.rb focus manager
-tkpalette.rb pallete support
-tkscrollbox.rb scroll box, also example of compound widget
-tktext.rb text classes
-tkvirtevent.rb virtual event support
-tkwinpkg.rb Win DDE and registry support
diff --git a/ext/tk/lib/multi-tk.rb b/ext/tk/lib/multi-tk.rb
deleted file mode 100644
index 78ed1aa6ee..0000000000
--- a/ext/tk/lib/multi-tk.rb
+++ /dev/null
@@ -1,3233 +0,0 @@
-#
-# multi-tk.rb - supports multi Tk interpreters
-# by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
-require 'tcltklib'
-require 'tkutil'
-require 'thread'
-
-if defined? Tk
- fail RuntimeError,"'multi-tk' library must be required before requiring 'tk'"
-end
-
-################################################
-# ignore exception on the mainloop?
-
-TclTkLib.mainloop_abort_on_exception = true
-# TclTkLib.mainloop_abort_on_exception = false
-# TclTkLib.mainloop_abort_on_exception = nil
-
-
-################################################
-# add ThreadGroup check to TclTkIp.new
-class << TclTkIp
- alias __new__ new
- private :__new__
-
- def new(*args)
- if Thread.current.group != ThreadGroup::Default
- raise SecurityError, 'only ThreadGroup::Default can call TclTkIp.new'
- end
- __new__(*args)
- end
-end
-
-
-################################################
-# use pseudo-toplevel feature of MultiTkIp ?
-if (!defined?(Use_PseudoToplevel_Feature_of_MultiTkIp) ||
- Use_PseudoToplevel_Feature_of_MultiTkIp)
- module MultiTkIp_PseudoToplevel_Evaluable
- #def pseudo_toplevel_eval(body = Proc.new)
- # Thread.current[:TOPLEVEL] = self
- # begin
- # body.call
- # ensure
- # Thread.current[:TOPLEVEL] = nil
- # end
- #end
-
- def pseudo_toplevel_evaluable?
- @pseudo_toplevel_evaluable
- end
-
- def pseudo_toplevel_evaluable=(mode)
- @pseudo_toplevel_evaluable = (mode)? true: false
- end
-
- def self.extended(mod)
- mod.__send__(:extend_object, mod)
- mod.instance_variable_set('@pseudo_toplevel_evaluable', true)
- end
- end
-
- class Object
- alias __method_missing_alias_for_MultiTkIp__ method_missing
- private :__method_missing_alias_for_MultiTkIp__
-
- def method_missing(id, *args)
- begin
- has_top = (top = MultiTkIp.__getip.__pseudo_toplevel) &&
- top.respond_to?(:pseudo_toplevel_evaluable?) &&
- top.pseudo_toplevel_evaluable? &&
- top.respond_to?(id)
- rescue Exception => e
- has_top = false
- end
-
- if has_top
- top.__send__(id, *args)
- else
- __method_missing_alias_for_MultiTkIp__(id, *args)
- end
- end
- end
-else
- # dummy
- module MultiTkIp_PseudoToplevel_Evaluable
- def pseudo_toplevel_evaluable?
- false
- end
- end
-end
-
-################################################
-# exceptiopn to treat the return value from IP
-class MultiTkIp_OK < Exception
- def self.send(thread, ret=nil)
- thread.raise self.new(ret)
- end
-
- def initialize(ret=nil)
- super('succeed')
- @return_value = ret
- end
-
- attr_reader :return_value
- alias value return_value
-end
-MultiTkIp_OK.freeze
-
-
-################################################
-# methods for construction
-class MultiTkIp
- BASE_DIR = File.dirname(__FILE__)
-
- @@SLAVE_IP_ID = ['slave'.freeze, '0'.taint].freeze
-
- @@IP_TABLE = {}.taint unless defined?(@@IP_TABLE)
-
- @@INIT_IP_ENV = [].taint unless defined?(@@INIT_IP_ENV) # table of Procs
- @@ADD_TK_PROCS = [].taint unless defined?(@@ADD_TK_PROCS) # table of [name, args, body]
-
- @@TK_TABLE_LIST = [].taint unless defined?(@@TK_TABLE_LIST)
-
- unless defined?(@@TK_CMD_TBL)
- @@TK_CMD_TBL = Object.new.taint
-
- @@TK_CMD_TBL.instance_variable_set('@tbl', {}.taint)
-
- class << @@TK_CMD_TBL
- allow = [
- '__send__', '__id__', 'freeze', 'inspect', 'kind_of?',
- '[]', '[]=', 'delete', 'each', 'has_key?'
- ]
- instance_methods.each{|m| undef_method(m) unless allow.index(m)}
-
- def kind_of?(klass)
- @tbl.kind_of?(klass)
- end
-
- def inspect
- if Thread.current.group == ThreadGroup::Default
- @tbl.inspect
- else
- ip = MultiTkIp.__getip
- @tbl.reject{|idx, ent| ent.respond_to?(:ip) && ent.ip != ip}.inspect
- end
- end
-
- def [](idx)
- return unless (ent = @tbl[idx])
- if Thread.current.group == ThreadGroup::Default
- ent
- elsif ent.respond_to?(:ip)
- (ent.ip == MultiTkIp.__getip)? ent: nil
- else
- ent
- end
- end
-
- def []=(idx,val)
- if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default
- fail SecurityError,"cannot change the entried command"
- end
- @tbl[idx] = val
- end
-
- def delete(idx, &blk)
- # if gets an entry, is permited to delete
- if self[idx]
- @tbl.delete(idx)
- elsif blk
- blk.call(idx)
- else
- nil
- end
- end
-
- def each(&blk)
- if Thread.current.group == ThreadGroup::Default
- @tbl.each(&blk)
- else
- ip = MultiTkIp.__getip
- @tbl.each{|idx, ent|
- blk.call(idx, ent) unless ent.respond_to?(:ip) && ent.ip != ip
- }
- end
- self
- end
-
- def has_key?(k)
- @tbl.has_key?(k)
- end
- alias include? has_key?
- alias key? has_key?
- alias member? has_key?
- end
-
- @@TK_CMD_TBL.freeze
- end
-
- ######################################
-
- @@CB_ENTRY_CLASS = Class.new(TkCallbackEntry){
- def initialize(ip, cmd)
- @ip = ip
- @cmd = cmd
- freeze
- end
- attr_reader :ip, :cmd
- def inspect
- cmd.inspect
- end
- def call(*args)
- unless @ip.deleted?
- current = Thread.current
- backup_ip = current['callback_ip']
- current['callback_ip'] = @ip
- begin
- ret = @ip.cb_eval(@cmd, *args)
- fail ret if ret.kind_of?(Exception)
- ret
- rescue TkCallbackBreak, TkCallbackContinue => e
- fail e
- rescue SecurityError => e
- # in 'exit', 'exit!', and 'abort' : security error --> delete IP
- if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/
- @ip.delete
- elsif @ip.safe?
- if @ip.respond_to?(:cb_error)
- @ip.cb_error(e)
- else
- nil # ignore
- end
- else
- fail e
- end
- rescue Exception => e
- fail e if e.message =~ /^TkCallback/
-
- if @ip.safe?
- if @ip.respond_to?(:cb_error)
- @ip.cb_error(e)
- else
- nil # ignore
- end
- else
- fail e
- end
- ensure
- current['callback_ip'] = backup_ip
- end
- end
- end
- }.freeze
-
- ######################################
-
- def _keys2opts(src_keys)
- return nil if src_keys == nil
- keys = {}; src_keys.each{|k, v| keys[k.to_s] = v}
- #keys.collect{|k,v| "-#{k} #{v}"}.join(' ')
- keys.collect{|k,v| "-#{k} #{TclTkLib._conv_listelement(TkComm::_get_eval_string(v))}"}.join(' ')
- end
- private :_keys2opts
-
- def _check_and_return(thread, exception, wait=0)
- unless thread
- unless exception.kind_of?(MultiTkIp_OK)
- msg = "#{exception.class}: #{exception.message}"
-
- if @interp.deleted?
- warn("Warning (#{self}): " + msg)
- return nil
- end
-
- if safe?
- warn("Warning (#{self}): " + msg) if $DEBUG
- return nil
- end
-
- begin
- @interp._eval_without_enc(@interp._merge_tklist('bgerror', msg))
- rescue Exception => e
- warn("Warning (#{self}): " + msg)
- end
- end
- return nil
- end
-
- if wait == 0
- # no wait
- Thread.pass
- if thread.stop?
- thread.raise exception
- end
- return thread
- end
-
- # wait to stop the caller thread
- wait.times{
- if thread.stop?
- # ready to send exception
- thread.raise exception
- return thread
- end
-
- # wait
- Thread.pass
- }
-
- # unexpected error
- thread.raise RuntimeError, "the thread may not wait for the return value"
- return thread
- end
-
- ######################################
-
- def set_cb_error(cmd = Proc.new)
- @cb_error_proc[0] = cmd
- end
-
- def cb_error(e)
- if @cb_error_proc[0].respond_to?(:call)
- @cb_error_proc[0].call(e)
- end
- end
-
- ######################################
-
- def set_safe_level(safe)
- if safe > @safe_level[0]
- @safe_level[0] = safe
- @cmd_queue.enq([@system, 'set_safe_level', safe])
- end
- @safe_level[0]
- end
- def safe_level=(safe)
- set_safe_level(safe)
- end
- def self.set_safe_level(safe)
- __getip.set_safe_level(safe)
- end
- def self.safe_level=(safe)
- self.set_safe_level(safe)
- end
- def safe_level
- @safe_level[0]
- end
- def self.safe_level
- __getip.safe_level
- end
-
- def wait_on_mainloop?
- @wait_on_mainloop[0]
- end
- def wait_on_mainloop=(bool)
- @wait_on_mainloop[0] = bool
- end
-
- def running_mainloop?
- @wait_on_mainloop[1] > 0
- end
-
- def _destroy_slaves_of_slaveIP(ip)
- unless ip.deleted?
- # ip._split_tklist(ip._invoke('interp', 'slaves')).each{|name|
- ip._split_tklist(ip._invoke_without_enc('interp', 'slaves')).each{|name|
- name = _fromUTF8(name)
- begin
- # ip._eval_without_enc("#{name} eval {foreach i [after info] {after cancel $i}}")
- after_ids = ip._eval_without_enc("#{name} eval {after info}")
- ip._eval_without_enc("#{name} eval {foreach i {#{after_ids}} {after cancel $i}}")
- rescue Exception
- end
- begin
- # ip._invoke('interp', 'eval', name, 'destroy', '.')
- ip._invoke(name, 'eval', 'destroy', '.')
- rescue Exception
- end
-
- # safe_base?
- if ip._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0'
- begin
- ip._eval_without_enc("::safe::interpDelete #{name}")
- rescue Exception
- end
- end
-=begin
- if ip._invoke('interp', 'exists', name) == '1'
- begin
- ip._invoke(name, 'eval', 'exit')
- rescue Exception
- end
- end
-=end
- unless ip.deleted?
- if ip._invoke('interp', 'exists', name) == '1'
- begin
- ip._invoke('interp', 'delete', name)
- rescue Exception
- end
- end
- end
- }
- end
- end
-
- def _receiver_eval_proc_core(safe_level, thread, cmd, *args)
- begin
- #ret = proc{$SAFE = safe_level; cmd.call(*args)}.call
- #ret = cmd.call(safe_level, *args)
- normal_ret = false
- ret = catch(:IRB_EXIT) do # IRB hack
- retval = cmd.call(safe_level, *args)
- normal_ret = true
- retval
- end
- unless normal_ret
- # catch IRB_EXIT
- exit(ret)
- end
- ret
- rescue SystemExit => e
- # delete IP
- unless @interp.deleted?
- @slave_ip_tbl.each{|name, subip|
- _destroy_slaves_of_slaveIP(subip)
- begin
- # subip._eval_without_enc("foreach i [after info] {after cancel $i}")
- after_ids = subip._eval_without_enc("after info")
- subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
- rescue Exception
- end
-=begin
- begin
- subip._invoke('destroy', '.') unless subip.deleted?
- rescue Exception
- end
-=end
- # safe_base?
- if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0'
- begin
- @interp._eval_without_enc("::safe::interpDelete #{name}")
- rescue Exception
- else
- next if subip.deleted?
- end
- end
- if subip.respond_to?(:safe_base?) && subip.safe_base? &&
- !subip.deleted?
- # do 'exit' to call the delete_hook procedure
- begin
- subip._eval_without_enc('exit')
- rescue Exception
- end
- else
- begin
- subip.delete unless subip.deleted?
- rescue Exception
- end
- end
- }
-
- begin
- # @interp._eval_without_enc("foreach i [after info] {after cancel $i}")
- after_ids = @interp._eval_without_enc("after info")
- @interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
- rescue Exception
- end
- begin
- @interp._invoke('destroy', '.') unless @interp.deleted?
- rescue Exception
- end
- if @safe_base && !@interp.deleted?
- # do 'exit' to call the delete_hook procedure
- @interp._eval_without_enc('exit')
- else
- @interp.delete unless @interp.deleted?
- end
- end
-
- if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/
- _check_and_return(thread, MultiTkIp_OK.new($3 == 'exit'))
- else
- _check_and_return(thread, MultiTkIp_OK.new(nil))
- end
-
- # if master? && !safe? && allow_ruby_exit?
- if !@interp.deleted? && master? && !safe? && allow_ruby_exit?
-=begin
- ObjectSpace.each_object(TclTkIp){|obj|
- obj.delete unless obj.deleted?
- }
-=end
- #exit(e.status)
- fail e
- end
- # break
-
- rescue SecurityError => e
- # in 'exit', 'exit!', and 'abort' : security error --> delete IP
- if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/
- ret = ($3 == 'exit')
- unless @interp.deleted?
- @slave_ip_tbl.each{|name, subip|
- _destroy_slaves_of_slaveIP(subip)
- begin
- # subip._eval_without_enc("foreach i [after info] {after cancel $i}")
- after_ids = subip._eval_without_enc("after info")
- subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
- rescue Exception
- end
-=begin
- begin
- subip._invoke('destroy', '.') unless subip.deleted?
- rescue Exception
- end
-=end
- # safe_base?
- if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0'
- begin
- @interp._eval_without_enc("::safe::interpDelete #{name}")
- rescue Exception
- else
- next if subip.deleted?
- end
- end
- if subip.respond_to?(:safe_base?) && subip.safe_base? &&
- !subip.deleted?
- # do 'exit' to call the delete_hook procedure
- begin
- subip._eval_without_enc('exit')
- rescue Exception
- end
- else
- begin
- subip.delete unless subip.deleted?
- rescue Exception
- end
- end
- }
-
- begin
- # @interp._eval_without_enc("foreach i [after info] {after cancel $i}")
- after_ids = @interp._eval_without_enc("after info")
- @interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
- rescue Exception
- end
-=begin
- begin
- @interp._invoke('destroy', '.') unless @interp.deleted?
- rescue Exception
- end
-=end
- if @safe_base && !@interp.deleted?
- # do 'exit' to call the delete_hook procedure
- @interp._eval_without_enc('exit')
- else
- @interp.delete unless @interp.deleted?
- end
- end
- _check_and_return(thread, MultiTkIp_OK.new(ret))
- # break
-
- else
- # raise security error
- _check_and_return(thread, e)
- end
-
- rescue Exception => e
- # raise exception
- begin
- bt = _toUTF8(e.backtrace.join("\n"))
- bt.instance_variable_set(:@encoding, 'utf-8')
- rescue Exception
- bt = e.backtrace.join("\n")
- end
- begin
- @interp._set_global_var('errorInfo', bt)
- rescue Exception
- end
- _check_and_return(thread, e)
-
- else
- # no exception
- _check_and_return(thread, MultiTkIp_OK.new(ret))
- end
- end
-
- def _receiver_eval_proc(last_thread, safe_level, thread, cmd, *args)
- if thread
- Thread.new{
- last_thread.join if last_thread
- unless @interp.deleted?
- _receiver_eval_proc_core(safe_level, thread, cmd, *args)
- end
- }
- else
- Thread.new{
- unless @interp.deleted?
- _receiver_eval_proc_core(safe_level, thread, cmd, *args)
- end
- }
- last_thread
- end
- end
-
- private :_receiver_eval_proc, :_receiver_eval_proc_core
-
- def _receiver_mainloop(check_root)
- if @evloop_thread[0] && @evloop_thread[0].alive?
- @evloop_thread[0]
- else
- @evloop_thread[0] = Thread.new{
- while !@interp.deleted?
- #if check_root
- # inf = @interp._invoke_without_enc('info', 'command', '.')
- # break if !inf.kind_of?(String) || inf != '.'
- #end
- break if check_root && !@interp.has_mainwindow?
- sleep 0.5
- end
- }
- @evloop_thread[0]
- end
- end
-
- def _create_receiver_and_watchdog(lvl = $SAFE)
- lvl = $SAFE if lvl < $SAFE
-
- # command-procedures receiver
- receiver = Thread.new(lvl){|safe_level|
- last_thread = {}
-
- loop do
- break if @interp.deleted?
- thread, cmd, *args = @cmd_queue.deq
- if thread == @system
- # control command
- case cmd
- when 'set_safe_level'
- begin
- safe_level = args[0] if safe_level < args[0]
- rescue Exception
- end
- when 'call_mainloop'
- thread = args.shift
- _check_and_return(thread,
- MultiTkIp_OK.new(_receiver_mainloop(*args)))
- else
- # ignore
- end
-
- else
- # procedure
- last_thread[thread] = _receiver_eval_proc(last_thread[thread],
- safe_level, thread,
- cmd, *args)
- end
- end
- }
-
- # watchdog of receiver
- watchdog = Thread.new{
- begin
- loop do
- sleep 1
- receiver.kill if @interp.deleted?
- break unless receiver.alive?
- end
- rescue Exception
- # ignore all kind of Exception
- end
- # receiver is dead
- loop do
- thread, cmd, *args = @cmd_queue.deq
- next unless thread
- if thread.alive?
- if @interp.deleted?
- thread.raise RuntimeError, 'the interpreter is already deleted'
- else
- thread.raise RuntimeError,
- 'the interpreter no longer receives command procedures'
- end
- end
- end
- }
-
- # return threads
- [receiver, watchdog]
- end
- private :_check_and_return, :_create_receiver_and_watchdog
-
- ######################################
-
- if self.const_defined? :DEFAULT_MASTER_NAME
- name = DEFAULT_MASTER_NAME.to_s
- else
- name = nil
- end
- if self.const_defined?(:DEFAULT_MASTER_OPTS) &&
- DEFAULT_MASTER_OPTS.kind_of?(Hash)
- keys = DEFAULT_MASTER_OPTS
- else
- keys = {}
- end
-
- @@DEFAULT_MASTER = self.allocate
- @@DEFAULT_MASTER.instance_eval{
- @tk_windows = {}.taint
-
- @tk_table_list = [].taint
-
- @slave_ip_tbl = {}.taint
-
- @slave_ip_top = {}.taint
-
- @evloop_thread = [].taint
-
- unless keys.kind_of? Hash
- fail ArgumentError, "expecting a Hash object for the 2nd argument"
- end
-
- @interp = TclTkIp.new(name, _keys2opts(keys))
- @ip_name = nil
-
- @callback_status = [].taint
-
- @system = Object.new
-
- @wait_on_mainloop = [true, 0].taint
-
- @threadgroup = Thread.current.group
-
- @safe_base = false
-
- @safe_level = [$SAFE]
-
- @cmd_queue = Queue.new
-
- @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0])
-
- @threadgroup.add @cmd_receiver
- @threadgroup.add @receiver_watchdog
-
- # NOT enclose @threadgroup for @@DEFAULT_MASTER
-
- @@IP_TABLE[ThreadGroup::Default] = self
- @@IP_TABLE[@threadgroup] = self
-
- #################################
-
- @pseudo_toplevel = [false, nil]
-
- def self.__pseudo_toplevel
- Thread.current.group == ThreadGroup::Default &&
- MultiTkIp.__getip == @@DEFAULT_MASTER &&
- self.__pseudo_toplevel_evaluable? && @pseudo_toplevel[1]
- end
-
- def self.__pseudo_toplevel=(m)
- unless (Thread.current.group == ThreadGroup::Default &&
- MultiTkIp.__getip == @@DEFAULT_MASTER)
- fail SecurityError, "no permission to manipulate"
- end
-
- # if m.kind_of?(Module) && m.respond_to?(:pseudo_toplevel_evaluable?)
- if m.respond_to?(:pseudo_toplevel_evaluable?)
- @pseudo_toplevel[0] = true
- @pseudo_toplevel[1] = m
- else
- fail ArgumentError, 'fail to set pseudo-toplevel'
- end
- self
- end
-
- def self.__pseudo_toplevel_evaluable?
- begin
- @pseudo_toplevel[0] && @pseudo_toplevel[1].pseudo_toplevel_evaluable?
- rescue Exception
- false
- end
- end
-
- def self.__pseudo_toplevel_evaluable=(mode)
- unless (Thread.current.group == ThreadGroup::Default &&
- MultiTkIp.__getip == @@DEFAULT_MASTER)
- fail SecurityError, "no permission to manipulate"
- end
-
- @pseudo_toplevel[0] = (mode)? true: false
- end
-
- #################################
-
- @assign_request = Class.new(Exception){
- def self.new(target, ret)
- obj = super()
- obj.target = target
- obj.ret = ret
- obj
- end
- attr_accessor :target, :ret
- }
-
- @assign_thread = Thread.new{
- loop do
- begin
- Thread.stop
- rescue @assign_request=>req
- begin
- req.ret[0] = req.target.instance_eval{
- @cmd_receiver, @receiver_watchdog =
- _create_receiver_and_watchdog(@safe_level[0])
- @threadgroup.add @cmd_receiver
- @threadgroup.add @receiver_watchdog
- @threadgroup.enclose
- true
- }
- rescue Exception=>e
- begin
- req.ret[0] = e
- rescue Exception
- # ignore
- end
- end
- rescue Exception
- # ignore
- end
- end
- }
-
- def self.assign_receiver_and_watchdog(target)
- ret = [nil]
- @assign_thread.raise(@assign_request.new(target, ret))
- while ret[0] == nil
- unless @assign_thread.alive?
- raise RuntimeError, 'lost the thread to assign a receiver and a watchdog thread'
- end
- end
- if ret[0].kind_of?(Exception)
- raise ret[0]
- else
- ret[0]
- end
- end
-
- #################################
-
- @init_ip_env_queue = Queue.new
- Thread.new{
- current = Thread.current
- loop {
- mtx, ret, table, script = @init_ip_env_queue.deq
- begin
- ret[0] = table.each{|tg, ip| ip._init_ip_env(script) }
- rescue Exception => e
- ret[0] = e
- ensure
- mtx.unlock
- end
- }
- }
-
- def self.__init_ip_env__(table, script)
- ret = []
- mtx = Mutex.new.lock
- @init_ip_env_queue.enq([mtx, ret, table, script])
- mtx.lock
- if ret[0].kind_of?(Exception)
- raise ret[0]
- else
- ret[0]
- end
- end
-
- #################################
-
- class << self
- undef :instance_eval
- end
- }
-
- @@DEFAULT_MASTER.freeze # defend against modification
-
- ######################################
-
- def self.inherited(subclass)
- # trust if on ThreadGroup::Default or @@DEFAULT_MASTER's ThreadGroup
- if @@IP_TABLE[Thread.current.group] == @@DEFAULT_MASTER
- begin
- class << subclass
- self.methods.each{|m|
- begin
- unless m == '__id__' || m == '__send__' || m == 'freeze'
- undef_method(m)
- end
- rescue Exception
- # ignore all exceptions
- end
- }
- end
- ensure
- subclass.freeze
- fail SecurityError,
- "cannot create subclass of MultiTkIp on a untrusted ThreadGroup"
- end
- end
- end
-
- ######################################
-
- @@SAFE_OPT_LIST = [
- 'accessPath'.freeze,
- 'statics'.freeze,
- 'nested'.freeze,
- 'deleteHook'.freeze
- ].freeze
-
- def _parse_slaveopts(keys)
- name = nil
- safe = false
- safe_opts = {}
- tk_opts = {}
-
- keys.each{|k,v|
- k_str = k.to_s
- if k_str == 'name'
- name = v
- elsif k_str == 'safe'
- safe = v
- elsif @@SAFE_OPT_LIST.member?(k_str)
- safe_opts[k_str] = v
- else
- tk_opts[k_str] = v
- end
- }
-
- if keys['without_tk'] || keys[:without_tk]
- [name, safe, safe_opts, nil]
- else
- [name, safe, safe_opts, tk_opts]
- end
- end
- private :_parse_slaveopts
-
- def _create_slave_ip_name
- name = @@SLAVE_IP_ID.join('')
- @@SLAVE_IP_ID[1].succ!
- name.freeze
- end
- private :_create_slave_ip_name
-
- ######################################
-
- def __check_safetk_optkeys(optkeys)
- # based on 'safetk.tcl'
- new_keys = {}
- optkeys.each{|k,v| new_keys[k.to_s] = v}
-
- # check 'display'
- if !new_keys.key?('display')
- begin
- #new_keys['display'] = @interp._invoke('winfo screen .')
- new_keys['display'] = @interp._invoke('winfo', 'screen', '.')
- rescue
- if ENV[DISPLAY]
- new_keys['display'] = ENV[DISPLAY]
- elsif !new_keys.key?('use')
- warn "Warning: no screen info or ENV[DISPLAY], so use ':0.0'"
- new_keys['display'] = ':0.0'
- end
- end
- end
-
- # check 'use'
- if new_keys.key?('use')
- # given 'use'
- case new_keys['use']
- when TkWindow
- new_keys['use'] = TkWinfo.id(new_keys['use'])
- #assoc_display = @interp._eval('winfo screen .')
- assoc_display = @interp._invoke('winfo', 'screen', '.')
- when /^\..*/
- new_keys['use'] = @interp._invoke('winfo', 'id', new_keys['use'])
- assoc_display = @interp._invoke('winfo', 'screen', new_keys['use'])
- else
- begin
- pathname = @interp._invoke('winfo', 'pathname', new_keys['use'])
- assoc_display = @interp._invoke('winfo', 'screen', pathname)
- rescue
- assoc_display = new_keys['display']
- end
- end
-
- # match display?
- if assoc_display != new_keys['display']
- if optkeys.key?(:display) || optkeys.key?('display')
- fail RuntimeError,
- "conflicting 'display'=>#{new_keys['display']} " +
- "and display '#{assoc_display}' on 'use'=>#{new_keys['use']}"
- else
- new_keys['display'] = assoc_display
- end
- end
- end
-
- # return
- new_keys
- end
- private :__check_safetk_optkeys
-
- def __create_safetk_frame(slave_ip, slave_name, app_name, keys)
- # display option is used by ::safe::loadTk
- loadTk_keys = {}
- loadTk_keys['display'] = keys['display']
- dup_keys = keys.dup
-
- # keys for toplevel : allow followings
- toplevel_keys = {}
- ['height', 'width', 'background', 'menu'].each{|k|
- toplevel_keys[k] = dup_keys.delete(k) if dup_keys.key?(k)
- }
- toplevel_keys['classname'] = 'SafeTk'
- toplevel_keys['screen'] = dup_keys.delete('display')
-
- # other keys used by pack option of container frame
-
- # create toplevel widget
- begin
- top = TkToplevel.new(toplevel_keys)
- rescue NameError => e
- fail e unless @interp.safe?
- fail SecurityError, "unable create toplevel on the safe interpreter"
- end
- msg = "Untrusted Ruby/Tk applet (#{slave_name})"
- if app_name.kind_of?(String)
- top.title "#{app_name} (#{slave_name})"
- else
- top.title msg
- end
-
- # procedure to delete slave interpreter
- slave_delete_proc = proc{
- unless slave_ip.deleted?
- #if slave_ip._invoke('info', 'command', '.') != ""
- # slave_ip._invoke('destroy', '.')
- #end
- #slave_ip.delete
- slave_ip._eval_without_enc('exit')
- end
- begin
- top.destroy if top.winfo_exist?
- rescue
- # ignore
- end
- }
- tag = TkBindTag.new.bind('Destroy', slave_delete_proc)
-
- top.bindtags = top.bindtags.unshift(tag)
-
- # create control frame
- TkFrame.new(top, :bg=>'red', :borderwidth=>3, :relief=>'ridge') {|fc|
- fc.bindtags = fc.bindtags.unshift(tag)
-
- TkFrame.new(fc, :bd=>0){|f|
- TkButton.new(f,
- :text=>'Delete', :bd=>1, :padx=>2, :pady=>0,
- :highlightthickness=>0, :command=>slave_delete_proc
- ).pack(:side=>:right, :fill=>:both)
- f.pack(:side=>:right, :fill=>:both, :expand=>true)
- }
-
- TkLabel.new(fc, :text=>msg, :padx=>2, :pady=>0,
- :anchor=>:w).pack(:side=>:left, :fill=>:both, :expand=>true)
-
- fc.pack(:side=>:bottom, :fill=>:x)
- }
-
- # container frame for slave interpreter
- dup_keys['fill'] = :both unless dup_keys.key?('fill')
- dup_keys['expand'] = true unless dup_keys.key?('expand')
- c = TkFrame.new(top, :container=>true).pack(dup_keys)
- c.bind('Destroy', proc{top.destroy})
-
- # return keys
- loadTk_keys['use'] = TkWinfo.id(c)
- [loadTk_keys, top.path]
- end
- private :__create_safetk_frame
-
- def __create_safe_slave_obj(safe_opts, app_name, tk_opts)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- # safe interpreter
- ip_name = _create_slave_ip_name
- slave_ip = @interp.create_slave(ip_name, true)
- @slave_ip_tbl[ip_name] = slave_ip
- def slave_ip.safe_base?
- true
- end
-
- @interp._eval("::safe::interpInit #{ip_name}")
-
- slave_ip._invoke('set', 'argv0', app_name) if app_name.kind_of?(String)
-
- if tk_opts
- tk_opts = __check_safetk_optkeys(tk_opts)
- if tk_opts.key?('use')
- @slave_ip_top[ip_name] = ''
- else
- tk_opts, top_path = __create_safetk_frame(slave_ip, ip_name, app_name,
- tk_opts)
- @slave_ip_top[ip_name] = top_path
- end
- @interp._eval("::safe::loadTk #{ip_name} #{_keys2opts(tk_opts)}")
- else
- @slave_ip_top[ip_name] = nil
- end
-
- if safe_opts.key?('deleteHook') || safe_opts.key?(:deleteHook)
- @interp._eval("::safe::interpConfigure #{ip_name} " +
- _keys2opts(safe_opts))
- else
- @interp._eval("::safe::interpConfigure #{ip_name} " +
- _keys2opts(safe_opts) + '-deleteHook {' +
- TkComm._get_eval_string(proc{|slave|
- self._default_delete_hook(slave)
- }) + '}')
- end
-
- [slave_ip, ip_name]
- end
-
- def __create_trusted_slave_obj(name, keys)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- ip_name = _create_slave_ip_name
- slave_ip = @interp.create_slave(ip_name, false)
- slave_ip._invoke('set', 'argv0', name) if name.kind_of?(String)
- slave_ip._invoke('set', 'argv', _keys2opts(keys))
- @interp._invoke('load', '', 'Tk', ip_name)
- @slave_ip_tbl[ip_name] = slave_ip
- [slave_ip, ip_name]
- end
-
- ######################################
-
- def _create_slave_object(keys={})
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- ip = MultiTkIp.new_slave(self, keys={})
- @slave_ip_tbl[ip.name] = ip
- end
-
- ######################################
-
- def initialize(master, safeip=true, keys={})
- if $SAFE >= 4
- fail SecurityError, "cannot create a new interpreter at level #{$SAFE}"
- end
-
- if safeip == nil && $SAFE >= 2
- fail SecurityError, "cannot create a master-ip at level #{$SAFE}"
- end
-
- if master.deleted? && safeip == nil
- fail RuntimeError, "cannot create a slave of a deleted interpreter"
- end
-
- if !master.deleted? && !master.master? && master.safe?
- fail SecurityError, "safe-slave-ip cannot create a new interpreter"
- end
-
- if safeip == nil && !master.master?
- fail SecurityError, "slave-ip cannot create a master-ip"
- end
-
- unless keys.kind_of? Hash
- fail ArgumentError, "expecting a Hash object for the 2nd argument"
- end
-
- @tk_windows = {}
- @tk_table_list = []
- @slave_ip_tbl = {}
- @slave_ip_top = {}
- @cb_error_proc = []
- @evloop_thread = []
-
- @tk_windows.taint unless @tk_windows.tainted?
- @tk_table_list.taint unless @tk_table_list.tainted?
- @slave_ip_tbl.taint unless @slave_ip_tbl.tainted?
- @slave_ip_top.taint unless @slave_ip_top.tainted?
- @cb_error_proc.taint unless @cb_error_proc.tainted?
- @evloop_thread.taint unless @evloop_thread.tainted?
-
- @callback_status = []
-
- name, safe, safe_opts, tk_opts = _parse_slaveopts(keys)
-
- safe = 4 if safe && !safe.kind_of?(Fixnum)
-
- @safe_base = false
-
- if safeip == nil
- # create master-ip
- @interp = TclTkIp.new(name, _keys2opts(tk_opts))
-
- @ip_name = nil
- if safe
- safe = $SAFE if safe < $SAFE
- @safe_level = [safe]
- else
- @safe_level = [$SAFE]
- end
- else
- # create slave-ip
- if safeip || master.safe?
- @safe_base = true
- @interp, @ip_name = master.__create_safe_slave_obj(safe_opts,
- name, tk_opts)
- if safe
- safe = master.safe_level if safe < master.safe_level
- @safe_level = [safe]
- else
- @safe_level = [4]
- end
- else
- @interp, @ip_name = master.__create_trusted_slave_obj(name, tk_opts)
- if safe
- safe = master.safe_level if safe < master.safe_level
- @safe_level = [safe]
- else
- @safe_level = [master.safe_level]
- end
- end
- @set_alias_proc = proc{|name|
- master._invoke('interp', 'alias', @ip_name, name, '', name)
- }.freeze
- end
-
- @system = Object.new
-
- @wait_on_mainloop = [true, 0].taint
- # @wait_on_mainloop = [false, 0].taint
-
- @threadgroup = ThreadGroup.new
-
- @pseudo_toplevel = [false, nil]
-
- @cmd_queue = Queue.new
-
-=begin
- @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0])
-
- @threadgroup.add @cmd_receiver
- @threadgroup.add @receiver_watchdog
-
- @threadgroup.enclose
-=end
- @@DEFAULT_MASTER.assign_receiver_and_watchdog(self)
-
- @@IP_TABLE[@threadgroup] = self
- _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
- @@TK_TABLE_LIST.size.times{
- (tbl = {}).tainted? || tbl.taint
- @tk_table_list << tbl
- }
-
- class << self
- undef :instance_eval
- end
-
- # dummy call for initialization
- self.eval_proc{ Tk.tk_call('set', 'tcl_patchLevel') }
-
- self.freeze # defend against modification
- end
-
- ######################################
-
- def _default_delete_hook(slave)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @slave_ip_tbl.delete(slave)
- top = @slave_ip_top.delete(slave)
- if top.kind_of?(String)
- # call default hook of safetk.tcl (ignore exceptions)
- if top == ''
- begin
- @interp._eval("::safe::disallowTk #{slave}")
- rescue
- warn("Waring: fail to call '::safe::disallowTk'") if $DEBUG
- end
- else # toplevel path
- begin
- @interp._eval("::safe::tkDelete {} #{top} #{slave}")
- rescue
- warn("Waring: fail to call '::safe::tkDelete'") if $DEBUG
- begin
- @interp._eval("destroy #{top}")
- rescue
- warn("Waring: fail to destroy toplevel") if $DEBUG
- end
- end
- end
- end
- end
-
-end
-
-
-# get target IP
-class MultiTkIp
- def self._ip_id_
- __getip._ip_id_
- end
- def _ip_id_
- # for RemoteTkIp
- ''
- end
-
- def self.__getip
- current = Thread.current
- if TclTkLib.mainloop_thread? != false && current['callback_ip']
- return current['callback_ip']
- end
- if current.group == ThreadGroup::Default
- @@DEFAULT_MASTER
- else
- ip = @@IP_TABLE[current.group]
- unless ip
- fail SecurityError,
- "cannot call Tk methods on #{Thread.current.inspect}"
- end
- ip
- end
- end
-end
-
-
-# aliases of constructor
-class << MultiTkIp
- alias __new new
- private :__new
-
-
- def new_master(safe=nil, keys={})
- if safe.kind_of?(Hash)
- keys = safe
- elsif safe.kind_of?(Integer)
- raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash)
- if !keys.key?(:safe) && !keys.key?('safe')
- keys[:safe] = safe
- end
- elsif safe == nil
- # do nothing
- else
- raise ArgumentError, "unexpected argument(s)"
- end
-
- ip = __new(__getip, nil, keys)
- #ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given?
- if block_given?
- Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)}
- end
- ip
- end
-
- alias new new_master
-
- def new_slave(safe=nil, keys={})
- if safe.kind_of?(Hash)
- keys = safe
- elsif safe.kind_of?(Integer)
- raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash)
- if !keys.key?(:safe) && !keys.key?('safe')
- keys[:safe] = safe
- end
- elsif safe == nil
- # do nothing
- else
- raise ArgumentError, "unexpected argument(s)"
- end
-
- ip = __new(__getip, false, keys)
- # ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given?
- if block_given?
- Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)}
- end
- ip
- end
- alias new_trusted_slave new_slave
-
- def new_safe_slave(safe=4, keys={})
- if safe.kind_of?(Hash)
- keys = safe
- elsif safe.kind_of?(Integer)
- raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash)
- if !keys.key?(:safe) && !keys.key?('safe')
- keys[:safe] = safe
- end
- else
- raise ArgumentError, "unexpected argument(s)"
- end
-
- ip = __new(__getip, true, keys)
- # ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given?
- if block_given?
- Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)}
- end
- ip
- end
- alias new_safeTk new_safe_slave
-end
-
-
-# get info
-class MultiTkIp
- def inspect
- s = self.to_s.chop!
- if self.manipulable?
- if master?
- if @interp.deleted?
- s << ':deleted-master'
- else
- s << ':master'
- end
- else
- if @interp.deleted?
- s << ':deleted-slave'
- elsif @interp.safe?
- s << ':safe-slave'
- else
- s << ':trusted-slave'
- end
- end
- end
- s << '>'
- end
-
- def master?
- if @ip_name
- false
- else
- true
- end
- end
- def self.master?
- __getip.master?
- end
-
- def slave?
- not master?
- end
- def self.slave?
- not self.master?
- end
-
- def alive?
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- begin
- return false unless @cmd_receiver.alive?
- return false if @interp.deleted?
- return false if @interp._invoke('interp', 'exists', '') == '0'
- rescue Exception
- return false
- end
- true
- end
- def self.alive?
- __getip.alive?
- end
-
- def path
- @ip_name || ''
- end
- def self.path
- __getip.path
- end
- def ip_name
- @ip_name || ''
- end
- def self.ip_name
- __getip.ip_name
- end
- def to_eval
- @ip_name || ''
- end
- def self.to_eval
- __getip.to_eval
- end
-
- def slaves(all = false)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp','slaves').split.map!{|name|
- if @slave_ip_tbl.key?(name)
- @slave_ip_tbl[name]
- elsif all
- name
- else
- nil
- end
- }.compact!
- end
- def self.slaves(all = false)
- __getip.slaves(all)
- end
-
- def manipulable?
- return true if (Thread.current.group == ThreadGroup::Default)
- ip = MultiTkIp.__getip
- (ip == self) || ip._is_master_of?(@interp)
- end
- def self.manipulable?
- true
- end
-
- def _is_master_of?(tcltkip_obj)
- tcltkip_obj.slave_of?(@interp)
- end
- protected :_is_master_of?
-end
-
-
-# instance methods to treat tables
-class MultiTkIp
- def _tk_cmd_tbl
- tbl = {}
- MultiTkIp.tk_cmd_tbl.each{|id, ent| tbl[id] = ent if ent.ip == self }
- tbl
- end
-
- def _tk_windows
- @tk_windows
- end
-
- def _tk_table_list
- @tk_table_list
- end
-
- def _add_new_tables
- (@@TK_TABLE_LIST.size - @tk_table_list.size).times{
- (tbl = {}).tainted? || tbl.taint
- @tk_table_list << tbl
- }
- end
-
- def _init_ip_env(script)
- self.eval_proc{script.call(self)}
- end
-
- def _add_tk_procs(name, args, body)
- return if slave?
- @interp._invoke('proc', name, args, body) if args && body
- @interp._invoke('interp', 'slaves').split.each{|slave|
- @interp._invoke('interp', 'alias', slave, name, '', name)
- }
- end
-
- def _remove_tk_procs(*names)
- return if slave?
- names.each{|name|
- name = name.to_s
- @interp._invoke('rename', name, '')
- @interp._invoke('interp', 'slaves').split.each{|slave|
- @interp._invoke('interp', 'alias', slave, name, '') rescue nil
- }
- }
- end
-
- def _init_ip_internal(init_ip_env, add_tk_procs)
- #init_ip_env.each{|script| self.eval_proc{script.call(self)}}
- init_ip_env.each{|script| self._init_ip_env(script)}
- add_tk_procs.each{|name, args, body|
- if master?
- @interp._invoke('proc', name, args, body) if args && body
- else
- @set_alias_proc.call(name)
- end
- }
- end
-end
-
-
-# class methods to treat tables
-class MultiTkIp
- def self.tk_cmd_tbl
- @@TK_CMD_TBL
- end
- def self.tk_windows
- __getip._tk_windows
- end
- def self.tk_object_table(id)
- __getip._tk_table_list[id]
- end
- def self.create_table
- if __getip.slave?
- begin
- raise SecurityError, "slave-IP has no permission creating a new table"
- rescue SecurityError => e
- #p e.backtrace
- # Is called on a Ruby/Tk library?
- caller_info = e.backtrace[1]
- if caller_info =~ %r{^#{MultiTkIp::BASE_DIR}/(tk|tkextlib)/[^:]+\.rb:}
- # Probably, caller is a Ruby/Tk library --> allow creating
- else
- raise e
- end
- end
- end
-
- id = @@TK_TABLE_LIST.size
- obj = Object.new
- @@TK_TABLE_LIST << obj
- obj.instance_eval <<-EOD
- def self.method_missing(m, *args)
- MultiTkIp.tk_object_table(#{id}).__send__(m, *args)
- end
- EOD
- obj.freeze
- @@IP_TABLE.each{|tg, ip| ip._add_new_tables }
- return obj
- end
-
- def self.init_ip_env(script = Proc.new)
- @@INIT_IP_ENV << script
- if __getip.slave?
- begin
- raise SecurityError, "slave-IP has no permission initializing IP env"
- rescue SecurityError => e
- #p e.backtrace
- # Is called on a Ruby/Tk library?
- caller_info = e.backtrace[1]
- if caller_info =~ %r{^#{MultiTkIp::BASE_DIR}/(tk|tkextlib)/[^:]+\.rb:}
- # Probably, caller is a Ruby/Tk library --> allow creating
- else
- raise e
- end
- end
- end
-
- # @@IP_TABLE.each{|tg, ip|
- # ip._init_ip_env(script)
- # }
- @@DEFAULT_MASTER.__init_ip_env__(@@IP_TABLE, script)
- end
-
- def self.add_tk_procs(name, args=nil, body=nil)
- if name.kind_of?(Array) # => an array of [name, args, body]
- name.each{|param| self.add_tk_procs(*param)}
- else
- name = name.to_s
- @@ADD_TK_PROCS << [name, args, body]
- @@IP_TABLE.each{|tg, ip|
- ip._add_tk_procs(name, args, body)
- }
- end
- end
-
- def self.remove_tk_procs(*names)
- names.each{|name|
- name = name.to_s
- @@ADD_TK_PROCS.delete_if{|elem|
- elem.kind_of?(Array) && elem[0].to_s == name
- }
- }
- @@IP_TABLE.each{|tg, ip|
- ip._remove_tk_procs(*names)
- }
- end
-
- def self.init_ip_internal
- __getip._init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
- end
-end
-
-
-# for callback operation
-class MultiTkIp
- def self.cb_entry_class
- @@CB_ENTRY_CLASS
- end
- def self.get_cb_entry(cmd)
- @@CB_ENTRY_CLASS.new(__getip, cmd).freeze
- end
-
-=begin
- def cb_eval(cmd, *args)
- #self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) }
- #ret = self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) }
- ret = self.eval_callback(*args){|safe, *params|
- $SAFE=safe if $SAFE < safe
- TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params))
- }
- if ret.kind_of?(Exception)
- raise ret
- end
- ret
- end
-=end
- def cb_eval(cmd, *args)
- self.eval_callback(*args){|safe, *params|
- $SAFE=safe if $SAFE < safe
- # TkUtil.eval_cmd(cmd, *params)
- TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params))
- }
- end
-=begin
- def cb_eval(cmd, *args)
- @callback_status[0] ||= TkVariable.new
- @callback_status[1] ||= TkVariable.new
- st, val = @callback_status
- th = Thread.new{
- self.eval_callback(*args){|safe, *params|
- #p [status, val, safe, *params]
- $SAFE=safe if $SAFE < safe
- begin
- TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params))
- rescue TkCallbackContinue
- st.value = 4
- rescue TkCallbackBreak
- st.value = 3
- rescue TkCallbackReturn
- st.value = 2
- rescue Exception => e
- val.value = e.message
- st.value = 1
- else
- st.value = 0
- end
- }
- }
- begin
- st.wait
- status = st.numeric
- retval = val.value
- rescue => e
- fail e
- end
-
- if status == 1
- fail RuntimeError, retval
- elsif status == 2
- fail TkCallbackReturn, "Tk callback returns 'return' status"
- elsif status == 3
- fail TkCallbackBreak, "Tk callback returns 'break' status"
- elsif status == 4
- fail TkCallbackContinue, "Tk callback returns 'continue' status"
- else
- ''
- end
- end
-=end
-
-end
-
-# pseudo-toplevel operation support
-class MultiTkIp
- # instance method
- def __pseudo_toplevel
- ip = MultiTkIp.__getip
- (ip == @@DEFAULT_MASTER || ip == self) &&
- self.__pseudo_toplevel_evaluable? && @pseudo_toplevel[1]
- end
-
- def __pseudo_toplevel=(m)
- unless (Thread.current.group == ThreadGroup::Default &&
- MultiTkIp.__getip == @@DEFAULT_MASTER)
- fail SecurityError, "no permission to manipulate"
- end
-
- # if m.kind_of?(Module) && m.respond_to?(:pseudo_toplevel_evaluable?)
- if m.respond_to?(:pseudo_toplevel_evaluable?)
- @pseudo_toplevel[0] = true
- @pseudo_toplevel[1] = m
- else
- fail ArgumentError, 'fail to set pseudo-toplevel'
- end
- self
- end
-
- def __pseudo_toplevel_evaluable?
- begin
- @pseudo_toplevel[0] && @pseudo_toplevel[1].pseudo_toplevel_evaluable?
- rescue Exception
- false
- end
- end
-
- def __pseudo_toplevel_evaluable=(mode)
- unless (Thread.current.group == ThreadGroup::Default &&
- MultiTkIp.__getip == @@DEFAULT_MASTER)
- fail SecurityError, "no permission to manipulate"
- end
-
- @pseudo_toplevel[0] = (mode)? true: false
- end
-end
-
-# evaluate a procedure on the proper interpreter
-class MultiTkIp
- # instance method
- def eval_proc_core(req_val, cmd, *args)
- # check
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- unless cmd.kind_of?(Proc) || cmd.kind_of?(Method)
- raise RuntimeError, "A Proc/Method object is expected for the 'cmd' argument"
- end
-
- # on IP thread
- if @cmd_receiver == Thread.current ||
- (!req_val && TclTkLib.mainloop_thread? != false) # callback
- begin
- ret = cmd.call(safe_level, *args)
- rescue SystemExit => e
- # exit IP
- warn("Warning: "+ $! + " on " + self.inspect) if $DEBUG
- begin
- self._eval_without_enc('exit')
- rescue Exception
- end
- self.delete
- ret = nil
- rescue Exception => e
- if $DEBUG
- warn("Warning: " + e.class.inspect +
- ((e.message.length > 0)? ' "' + e.message + '"': '') +
- " on " + self.inspect)
- end
-=begin
- begin
- bt = _toUTF8(e.backtrace.join("\n"))
- bt.instance_variable_set(:@encoding, 'utf-8')
- rescue Exception
- bt = e.backtrace.join("\n")
- end
- begin
- @interp._set_global_var('errorInfo', bt)
- rescue Exception
- end
-=end
- ret = e
- end
- return ret
- end
-
- # send cmd to the proc-queue
- unless req_val
- begin
- @cmd_queue.enq([nil, cmd, *args])
- rescue Exception => e
- # ignore
- if $DEBUG
- warn("Warning: " + e.class.inspect +
- ((e.message.length > 0)? ' "' + e.message + '"': '') +
- " on " + self.inspect)
- end
- return e
- end
- return nil
- end
-
- # send and get return value by exception
- begin
- @cmd_queue.enq([Thread.current, cmd, *args])
- Thread.stop
- rescue MultiTkIp_OK => ret
- # return value
- return ret.value
- rescue SystemExit => e
- # exit IP
- warn("Warning: " + $! + " on " + self.inspect) if $DEBUG
- begin
- self._eval_without_enc('exit')
- rescue Exception
- end
- if !self.deleted? && !safe? && allow_ruby_exit?
- self.delete
- fail e
- else
- self.delete
- end
- rescue Exception => e
- if $DEBUG
- warn("Warning: " + e.class.inspect +
- ((e.message.length > 0)? ' "' + e.message + '"': '') +
- " on " + self.inspect)
- end
- return e
- end
- return nil
- end
- private :eval_proc_core
-
- def eval_callback(*args)
- if block_given?
- cmd = Proc.new
- else
- cmd = args.shift
- end
- current = Thread.current
- backup_ip = current['callback_ip']
- current['callback_ip'] = self
- begin
- eval_proc_core(false, cmd, *args)
- ensure
- current['callback_ip'] = backup_ip
- end
- end
-
- def eval_proc(*args)
- # The scope of the eval-block of 'eval_proc' method is different from
- # the external. If you want to pass local values to the eval-block,
- # use arguments of eval_proc method. They are passed to block-arguments.
- if block_given?
- cmd = Proc.new
- else
- unless (cmd = args.shift)
- fail ArgumentError, "A Proc or Method object is expected for 1st argument"
- end
- end
- if TclTkLib.mainloop_thread? == true
- # call from eventloop
- current = Thread.current
- backup_ip = current['callback_ip']
- current['callback_ip'] = self
- begin
- eval_proc_core(false,
- proc{|safe, *params|
- $SAFE=safe if $SAFE < safe
- cmd.call(*params)
- }, *args)
- ensure
- current['callback_ip'] = backup_ip
- end
- else
- eval_proc_core(true,
- proc{|safe, *params|
- $SAFE=safe if $SAFE < safe
- Thread.new(*params, &cmd).value
- },
- *args)
- end
- end
- alias call eval_proc
-
- def bg_eval_proc(*args)
- if block_given?
- cmd = Proc.new
- else
- unless (cmd = args.shift)
- fail ArgumentError, "A Proc or Method object is expected for 1st argument"
- end
- end
- Thread.new{
- eval_proc(cmd, *args)
-=begin
- eval_proc_core(false,
- proc{|safe, *params|
- $SAFE=safe if $SAFE < safe
- Thread.new(*params, &cmd).value
- },
- safe_level, *args)
-=end
- }
- end
- alias background_eval_proc bg_eval_proc
- alias thread_eval_proc bg_eval_proc
- alias bg_call bg_eval_proc
- alias background_call bg_eval_proc
-
- def eval_string(cmd, *eval_args)
- # cmd string ==> proc
- unless cmd.kind_of?(String)
- raise RuntimeError, "A String object is expected for the 'cmd' argument"
- end
-
- eval_proc_core(true,
- proc{|safe|
- Kernel.eval("$SAFE=#{safe} if $SAFE < #{safe};" << cmd,
- *eval_args)
- })
- end
- alias eval_str eval_string
-
- def bg_eval_string(cmd, *eval_args)
- # cmd string ==> proc
- unless cmd.kind_of?(String)
- raise RuntimeError, "A String object is expected for the 'cmd' argument"
- end
- Thread.new{
- eval_proc_core(true,
- proc{|safe|
- Kernel.eval("$SAFE=#{safe} if $SAFE < #{safe};" << cmd,
- *eval_args)
- })
- }
- end
- alias background_eval_string bg_eval_string
- alias bg_eval_str bg_eval_string
- alias background_eval_str bg_eval_string
-
- def eval(*args, &blk)
- if block_given?
- eval_proc(*args, &blk)
- elsif args[0]
- if args[0].respond_to?(:call)
- eval_proc(*args)
- else
- eval_string(*args)
- end
- else
- fail ArgumentError, "no argument to eval"
- end
- end
-
- def bg_eval(*args, &blk)
- if block_given?
- bg_eval_proc(*args, &blk)
- elsif args[0]
- if args[0].respond_to?(:call)
- bg_eval_proc(*args)
- else
- bg_eval_string(*args)
- end
- else
- fail ArgumentError, "no argument to eval"
- end
- end
- alias background_eval bg_eval
-end
-
-class << MultiTkIp
- # class method
- def eval_proc(*args, &blk)
- # class ==> interp object
- __getip.eval_proc(*args, &blk)
- end
- alias call eval_proc
-
- def bg_eval_proc(*args, &blk)
- # class ==> interp object
- __getip.bg_eval_proc(*args, &blk)
- end
- alias background_eval_proc bg_eval_proc
- alias thread_eval_proc bg_eval_proc
- alias bg_call bg_eval_proc
- alias background_call bg_eval_proc
-
- def eval_string(cmd, *eval_args)
- # class ==> interp object
- __getip.eval_string(cmd, *eval_args)
- end
- alias eval_str eval_string
-
- def bg_eval_string(cmd, *eval_args)
- # class ==> interp object
- __getip.bg_eval_string(cmd, *eval_args)
- end
- alias background_eval_string bg_eval_string
- alias bg_eval_str bg_eval_string
- alias background_eval_str bg_eval_string
-
- def eval(*args, &blk)
- # class ==> interp object
- __getip.eval(*args, &blk)
- end
- def bg_eval(*args, &blk)
- # class ==> interp object
- __getip.bg_eval(*args, &blk)
- end
- alias background_eval bg_eval
-end
-
-
-# event loop
-# all master/slave IPs are controled by only one event-loop
-class << MultiTkIp
- def mainloop(check_root = true)
- __getip.mainloop(check_root)
- end
- def mainloop_watchdog(check_root = true)
- __getip.mainloop_watchdog(check_root)
- end
- def do_one_event(flag = TclTkLib::EventFlag::ALL)
- __getip.do_one_event(flag)
- end
- def mainloop_abort_on_exception
- # __getip.mainloop_abort_on_exception
- TclTkLib.mainloop_abort_on_exception
- end
- def mainloop_abort_on_exception=(mode)
- # __getip.mainloop_abort_on_exception=(mode)
- TclTkLib.mainloop_abort_on_exception=(mode)
- end
- def set_eventloop_tick(tick)
- __getip.set_eventloop_tick(tick)
- end
- def get_eventloop_tick
- __getip.get_eventloop_tick
- end
- def set_no_event_wait(tick)
- __getip.set_no_event_wait(tick)
- end
- def get_no_event_wait
- __getip.get_no_event_wait
- end
- def set_eventloop_weight(loop_max, no_event_tick)
- __getip.set_eventloop_weight(loop_max, no_event_tick)
- end
- def get_eventloop_weight
- __getip.get_eventloop_weight
- end
-end
-
-# class methods to delegate to TclTkIp
-class << MultiTkIp
- def method_missing(id, *args)
- __getip.__send__(id, *args)
- end
-
- def make_safe
- __getip.make_safe
- end
-
- def safe?
- __getip.safe?
- end
-
- def safe_base?
- begin
- __getip.safe_base?
- rescue
- false
- end
- end
-
- def allow_ruby_exit?
- __getip.allow_ruby_exit?
- end
-
- def allow_ruby_exit= (mode)
- __getip.allow_ruby_exit = mode
- end
-
- def delete
- __getip.delete
- end
-
- def deleted?
- __getip.deleted?
- end
-
- def has_mainwindow?
- __getip.has_mainwindow?
- end
-
- def invalid_namespace?
- __getip.invalid_namespace?
- end
-
- def abort(msg = nil)
- __getip.abort(msg)
- end
-
- def exit(st = true)
- __getip.exit(st)
- end
-
- def exit!(st = false)
- __getip.exit!(st)
- end
-
- def restart(app_name = nil, keys = {})
- init_ip_internal
-
- __getip._invoke('set', 'argv0', app_name) if app_name
- if keys.kind_of?(Hash)
- __getip._invoke('set', 'argv', _keys2opts(keys))
- end
-
- __getip.restart
- end
-
- def _eval(str)
- __getip._eval(str)
- end
-
- def _invoke(*args)
- __getip._invoke(*args)
- end
-
- def _eval_without_enc(str)
- __getip._eval_without_enc(str)
- end
-
- def _invoke_without_enc(*args)
- __getip._invoke_without_enc(*args)
- end
-
- def _eval_with_enc(str)
- __getip._eval_with_enc(str)
- end
-
- def _invoke_with_enc(*args)
- __getip._invoke_with_enc(*args)
- end
-
- def _toUTF8(str, encoding=nil)
- __getip._toUTF8(str, encoding)
- end
-
- def _fromUTF8(str, encoding=nil)
- __getip._fromUTF8(str, encoding)
- end
-
- def _thread_vwait(var)
- __getip._thread_vwait(var)
- end
-
- def _thread_tkwait(mode, target)
- __getip._thread_tkwait(mode, target)
- end
-
- def _return_value
- __getip._return_value
- end
-
- def _get_variable(var, flag)
- __getip._get_variable(var, flag)
- end
- def _get_variable2(var, idx, flag)
- __getip._get_variable2(var, idx, flag)
- end
- def _set_variable(var, value, flag)
- __getip._set_variable(var, value, flag)
- end
- def _set_variable2(var, idx, value, flag)
- __getip._set_variable2(var, idx, value, flag)
- end
- def _unset_variable(var, flag)
- __getip._unset_variable(var, flag)
- end
- def _unset_variable2(var, idx, flag)
- __getip._unset_variable2(var, idx, flag)
- end
-
- def _get_global_var(var)
- __getip._get_global_var(var)
- end
- def _get_global_var2(var, idx)
- __getip._get_global_var2(var, idx)
- end
- def _set_global_var(var, value)
- __getip._set_global_var(var, value)
- end
- def _set_global_var2(var, idx, value)
- __getip._set_global_var2(var, idx, value)
- end
- def _unset_global_var(var)
- __getip._unset_global_var(var)
- end
- def _unset_global_var2(var, idx)
- __getip._unset_global_var2(var, idx)
- end
-
- def _make_menu_embeddable(menu_path)
- __getip._make_menu_embeddable(menu_path)
- end
-
- def _split_tklist(str)
- __getip._split_tklist(str)
- end
- def _merge_tklist(*args)
- __getip._merge_tklist(*args)
- end
- def _conv_listelement(arg)
- __getip._conv_listelement(arg)
- end
-
- def _create_console
- __getip._create_console
- end
-end
-
-
-# wrap methods on TclTkLib : not permit calling TclTkLib module methods
-class << TclTkLib
- def mainloop(check_root = true)
- MultiTkIp.mainloop(check_root)
- end
- def mainloop_watchdog(check_root = true)
- MultiTkIp.mainloop_watchdog(check_root)
- end
- def do_one_event(flag = TclTkLib::EventFlag::ALL)
- MultiTkIp.do_one_event(flag)
- end
- #def mainloop_abort_on_exception
- # MultiTkIp.mainloop_abort_on_exception
- #end
- #def mainloop_abort_on_exception=(mode)
- # MultiTkIp.mainloop_abort_on_exception=(mode)
- #end
- def set_eventloop_tick(tick)
- MultiTkIp.set_eventloop_tick(tick)
- end
- def get_eventloop_tick
- MultiTkIp.get_eventloop_tick
- end
- def set_no_event_wait(tick)
- MultiTkIp.set_no_event_wait(tick)
- end
- def get_no_event_wait
- MultiTkIp.get_no_event_wait
- end
- def set_eventloop_weight(loop_max, no_event_tick)
- MultiTkIp.set_eventloop_weight(loop_max, no_event_tick)
- end
- def get_eventloop_weight
- MultiTkIp.get_eventloop_weight
- end
- def restart(*args)
- MultiTkIp.restart(*args)
- end
-
- def _merge_tklist(*args)
- MultiTkIp._merge_tklist(*args)
- end
- def _conv_listelement(arg)
- MultiTkIp._conv_listelement(arg)
- end
-end
-
-
-# depend on TclTkIp
-class MultiTkIp
- def mainloop(check_root = true, restart_on_dead = true)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- #return self if self.slave?
- #return self if self != @@DEFAULT_MASTER
- if self != @@DEFAULT_MASTER
- if @wait_on_mainloop[0]
- begin
- @wait_on_mainloop[1] += 1
- if $SAFE >= 4
- _receiver_mainloop(check_root).join
- else
- @cmd_queue.enq([@system, 'call_mainloop',
- Thread.current, check_root])
- Thread.stop
- end
- rescue MultiTkIp_OK => ret
- # return value
- if ret.value.kind_of?(Thread)
- return ret.value.value
- else
- return ret.value
- end
- rescue SystemExit => e
- # exit IP
- warn("Warning: " + $! + " on " + self.inspect) if $DEBUG
- begin
- self._eval_without_enc('exit')
- rescue Exception
- end
- self.delete
- rescue StandardError => e
- if $DEBUG
- warn("Warning: " + e.class.inspect +
- ((e.message.length > 0)? ' "' + e.message + '"': '') +
- " on " + self.inspect)
- end
- return e
- rescue Exception => e
- return e
- ensure
- @wait_on_mainloop[1] -= 1
- end
- end
- return
- end
-
- unless restart_on_dead
- @wait_on_mainloop[1] += 1
-=begin
- begin
- @interp.mainloop(check_root)
- rescue StandardError => e
- if $DEBUG
- warn("Warning: " + e.class.inspect +
- ((e.message.length > 0)? ' "' + e.message + '"': '') +
- " on " + self.inspect)
- end
- end
-=end
- begin
- @interp.mainloop(check_root)
- ensure
- @wait_on_mainloop[1] -= 1
- end
- else
- loop do
- break unless self.alive?
- if check_root
- begin
- break if TclTkLib.num_of_mainwindows == 0
- rescue StandardError
- break
- end
- end
- break if @interp.deleted?
- begin
- @wait_on_mainloop[1] += 1
- @interp.mainloop(check_root)
- rescue StandardError => e
- if TclTkLib.mainloop_abort_on_exception != nil
- #STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect,
- # " exception (ignore) : ", $!.message, "\n");
- if $DEBUG
- warn("Warning: Tk mainloop receives " << e.class.inspect <<
- " exception (ignore) : " << e.message);
- end
- end
- #raise e
- rescue Exception => e
-=begin
- if TclTkLib.mainloop_abort_on_exception != nil
- #STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect,
- # " exception (ignore) : ", $!.message, "\n");
- if $DEBUG
- warn("Warning: Tk mainloop receives " << e.class.inspect <<
- " exception (ignore) : " << e.message);
- end
- end
-=end
- raise e
- ensure
- @wait_on_mainloop[1] -= 1
- Thread.pass # avoid eventloop conflict
- end
- end
- end
- self
- end
-
- def make_safe
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.make_safe
- end
-
- def safe?
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.safe?
- end
-
- def safe_base?
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @safe_base
- end
-
- def allow_ruby_exit?
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.allow_ruby_exit?
- end
-
- def allow_ruby_exit= (mode)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.allow_ruby_exit = mode
- end
-
- def delete
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @slave_ip_tbl.each{|name, subip|
- _destroy_slaves_of_slaveIP(subip)
-=begin
- begin
- subip._invoke('destroy', '.') unless subip.deleted?
- rescue Exception
- end
-=end
- begin
- # subip._eval_without_enc("foreach i [after info] {after cancel $i}")
- unless subip.deleted?
- after_ids = subip._eval_without_enc("after info")
- subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
- end
- rescue Exception
- end
-
- # safe_base?
- if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0'
- begin
- @interp._eval_without_enc("::safe::interpDelete #{name}")
- rescue Exception
- else
- next if subip.deleted?
- end
- end
- if subip.respond_to?(:safe_base?) && subip.safe_base? &&
- !subip.deleted?
- # do 'exit' to call the delete_hook procedure
- begin
- subip._eval_without_enc('exit')
- rescue Exception
- end
- else
- begin
- subip.delete unless subip.deleted?
- rescue Exception
- end
- end
- }
-
- begin
- # @interp._eval_without_enc("foreach i [after info] {after cancel $i}")
- after_ids = @interp._eval_without_enc("after info")
- @interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
- rescue Exception
- end
-
- begin
- @interp._invoke('destroy', '.') unless @interp.deleted?
- rescue Exception
- end
-
- if @safe_base && !@interp.deleted?
- # do 'exit' to call the delete_hook procedure
- @interp._eval_without_enc('exit')
- end
- @interp.delete
- self
- end
-
- def deleted?
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.deleted?
- end
-
- def has_mainwindow?
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.has_mainwindow?
- end
-
- def invalid_namespace?
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.invalid_namespace?
- end
-
- def abort(msg = nil)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- if master? && !safe? && allow_ruby_exit?
- if msg
- Kernel.abort(msg)
- else
- Kernel.abort
- end
- else
- # ignore msg
- delete
- 1
- end
- end
-
- def exit(st = true)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- if master? && !safe? && allow_ruby_exit?
- Kernel.exit(st)
- else
- delete
- st
- end
- end
-
- def exit!(st = false)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- if master? && !safe? && allow_ruby_exit?
- Kernel.exit!(st)
- else
- delete
- st
- end
- end
-
- def restart(app_name = nil, keys = {})
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
-
- @interp._invoke('set', 'argv0', app_name) if app_name
- if keys.kind_of?(Hash)
- @interp._invoke('set', 'argv', _keys2opts(keys))
- end
-
- @interp.restart
- end
-
- def __eval(str)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.__eval(str)
- end
-
- def __invoke(*args)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.__invoke(*args)
- end
-
- def _eval(str)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._eval(str)
- end
-
- def _invoke(*args)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke(*args)
- end
-
- def _eval_without_enc(str)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._eval_without_enc(str)
- end
-
- def _invoke_without_enc(*args)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke_without_enc(*args)
- end
-
- def _eval_with_enc(str)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._eval_with_enc(str)
- end
-
- def _invoke_with_enc(*args)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke_with_enc(*args)
- end
-
- def _toUTF8(str, encoding=nil)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._toUTF8(str, encoding)
- end
-
- def _fromUTF8(str, encoding=nil)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._fromUTF8(str, encoding)
- end
-
- def _thread_vwait(var)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._thread_vwait(var)
- end
-
- def _thread_tkwait(mode, target)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._thread_tkwait(mode, target)
- end
-
- def _return_value
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._return_value
- end
-
- def _get_variable(var, flag)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._get_variable(var, flag)
- end
- def _get_variable2(var, idx, flag)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._get_variable2(var, idx, flag)
- end
- def _set_variable(var, value, flag)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._set_variable(var, value, flag)
- end
- def _set_variable2(var, idx, value, flag)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._set_variable2(var, idx, value, flag)
- end
- def _unset_variable(var, flag)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._unset_variable(var, flag)
- end
- def _unset_variable2(var, idx, flag)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._unset_variable2(var, idx, flag)
- end
-
- def _get_global_var(var)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._get_global_var(var)
- end
- def _get_global_var2(var, idx)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._get_global_var2(var, idx)
- end
- def _set_global_var(var, value)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._set_global_var(var, value)
- end
- def _set_global_var2(var, idx, value)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._set_global_var2(var, idx, value)
- end
- def _unset_global_var(var)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._unset_global_var(var)
- end
- def _unset_global_var2(var, idx)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._unset_global_var2(var, idx)
- end
-
- def _make_menu_embeddable(menu_path)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._make_menu_embeddable(menu_path)
- end
-
- def _split_tklist(str)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._split_tklist(str)
- end
- def _merge_tklist(*args)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._merge_tklist(*args)
- end
- def _conv_listelement(arg)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._conv_listelement(arg)
- end
-end
-
-
-# interp command support
-class MultiTkIp
- def _lst2ary(str)
- return [] if str == ""
- idx = str.index('{')
- while idx and idx > 0 and str[idx-1] == ?\\
- idx = str.index('{', idx+1)
- end
- return str.split unless idx
-
- list = str[0,idx].split
- str = str[idx+1..-1]
- i = -1
- brace = 1
- str.each_byte {|c|
- i += 1
- brace += 1 if c == ?{
- brace -= 1 if c == ?}
- break if brace == 0
- }
- if i == 0
- list.push ''
- elsif str[0, i] == ' '
- list.push ' '
- else
- list.push str[0..i-1]
- end
- #list += _lst2ary(str[i+1..-1])
- list.concat(_lst2ary(str[i+1..-1]))
- list
- end
- private :_lst2ary
-
- def _slavearg(slave)
- if slave.kind_of?(MultiTkIp)
- slave.path
- elsif slave.kind_of?(String)
- slave
- else
- slave.to_s
- end
- end
- private :_slavearg
-
- def alias_info(slave, cmd_name)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- _lst2ary(@interp._invoke('interp', 'alias', _slavearg(slave), cmd_name))
- end
- def self.alias_info(slave, cmd_name)
- __getip.alias_info(slave, cmd_name)
- end
-
- def alias_delete(slave, cmd_name)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp', 'alias', _slavearg(slave), cmd_name, '')
- self
- end
- def self.alias_delete(slave, cmd_name)
- __getip.alias_delete(slave, cmd_name)
- self
- end
-
- def def_alias(slave, new_cmd, org_cmd, *args)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- ret = @interp._invoke('interp', 'alias', _slavearg(slave), new_cmd,
- '', org_cmd, *args)
- (ret == new_cmd)? self: nil
- end
- def self.def_alias(slave, new_cmd, org_cmd, *args)
- ret = __getip.def_alias(slave, new_cmd, org_cmd, *args)
- (ret == new_cmd)? self: nil
- end
-
- def aliases(slave = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- _lst2ary(@interp._invoke('interp', 'aliases', _slavearg(slave)))
- end
- def self.aliases(slave = '')
- __getip.aliases(slave)
- end
-
- def delete_slaves(*args)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- slaves = args.collect{|s| _slavearg(s)}
- @interp._invoke('interp', 'delete', *slaves) if slaves.size > 0
- self
- end
- def self.delete_slaves(*args)
- __getip.delete_slaves(*args)
- self
- end
-
- def exist?(slave = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- ret = @interp._invoke('interp', 'exists', _slavearg(slave))
- (ret == '1')? true: false
- end
- def self.exist?(slave = '')
- __getip.exist?(slave)
- end
-
- def delete_cmd(slave, cmd)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- slave_invoke = @interp._invoke('list', 'rename', cmd, '')
- @interp._invoke('interp', 'eval', _slavearg(slave), slave_invoke)
- self
- end
- def self.delete_cmd(slave, cmd)
- __getip.delete_cmd(slave, cmd)
- self
- end
-
- def expose_cmd(slave, cmd, aliasname = nil)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- if aliasname
- @interp._invoke('interp', 'expose', _slavearg(slave), cmd, aliasname)
- else
- @interp._invoke('interp', 'expose', _slavearg(slave), cmd)
- end
- self
- end
- def self.expose_cmd(slave, cmd, aliasname = nil)
- __getip.expose_cmd(slave, cmd, aliasname)
- self
- end
-
- def hide_cmd(slave, cmd, aliasname = nil)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- if aliasname
- @interp._invoke('interp', 'hide', _slavearg(slave), cmd, aliasname)
- else
- @interp._invoke('interp', 'hide', _slavearg(slave), cmd)
- end
- self
- end
- def self.hide_cmd(slave, cmd, aliasname = nil)
- __getip.hide_cmd(slave, cmd, aliasname)
- self
- end
-
- def hidden_cmds(slave = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- _lst2ary(@interp._invoke('interp', 'hidden', _slavearg(slave)))
- end
- def self.hidden_cmds(slave = '')
- __getip.hidden_cmds(slave)
- end
-
- def invoke_hidden(slave, cmd, *args)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- if args[-1].kind_of?(Hash)
- keys = _symbolkey2str(args.pop)
- else
- keys = []
- end
- keys << _slavearg(slave)
- if Tk::TCL_MAJOR_VERSION > 8 ||
- (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5)
- keys << '--'
- end
- keys << cmd
- keys.concat(args)
- @interp._invoke('interp', 'invokehidden', *keys)
- end
- def self.invoke_hidden(slave, cmd, *args)
- __getip.invoke_hidden(slave, cmd, *args)
- end
-
- def invoke_hidden_on_global(slave, cmd, *args)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- if args[-1].kind_of?(Hash)
- keys = _symbolkey2str(args.pop)
- else
- keys = []
- end
- keys << _slavearg(slave)
- keys << '-global'
- if Tk::TCL_MAJOR_VERSION > 8 ||
- (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5)
- keys << '--'
- end
- keys << cmd
- keys.concat(args)
- @interp._invoke('interp', 'invokehidden', *keys)
- end
- def self.invoke_hidden_on_global(slave, cmd, *args)
- __getip.invoke_hidden_on_global(slave, cmd, *args)
- end
-
- def invoke_hidden_on_namespace(slave, ns, cmd, *args)
- # for Tcl8.5 or later
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- if args[-1].kind_of?(Hash)
- keys = _symbolkey2str(args.pop)
- else
- keys = []
- end
- keys << _slavearg(slave)
- keys << '-namespace' << TkComm._get_eval_string(ns)
- keys << '--' << cmd
- keys.concat(args)
- @interp._invoke('interp', 'invokehidden', *keys)
- end
- def self.invoke_hidden_on_namespace(slave, ns, cmd, *args)
- __getip.invoke_hidden_on_namespace(slave, ns, cmd, *args)
- end
-
- def mark_trusted(slave = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp', 'marktrusted', _slavearg(slave))
- self
- end
- def self.mark_trusted(slave = '')
- __getip.mark_trusted(slave)
- self
- end
-
- def set_bgerror_handler(cmd = Proc.new, slave = nil, &b)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- unless TkComm._callback_entry?(cmd)
- if !slave && b
- slave = cmd
- cmd = Proc.new(&b)
- end
- end
- slave = '' unless slave
-
- @interp._invoke('interp', 'bgerror', _slavearg(slave), cmd)
- end
- def self.bgerror(cmd = Proc.new, slave = nil, &b)
- __getip.bgerror(cmd, slave, &b)
- end
-
- def get_bgerror_handler(slave = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- procedure(@interp._invoke('interp', 'bgerror', _slavearg(slave)))
- end
- def self.bgerror(slave = '')
- __getip.bgerror(slave)
- end
-
- def set_limit(limit_type, slave = '', opts = {})
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp', 'limit', _slavearg(slave), limit_type, opts)
- end
- def self.set_limit(limit_type, slave = '', opts = {})
- __getip.set_limit(limit_type, slave, opts)
- end
-
- def get_limit(limit_type, slave = '', slot = nil)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- if slot
- num_or_str(@interp._invoke('interp', 'limit', _slavearg(slave),
- limit_type, slot))
- else
- l = @interp._split_tklist(@interp._invoke_without_enc('interp', 'limit',
- _slavearg(slave),
- limit_type))
- l.map!{|s| _fromUTF8(s)}
- r = {}
- until l.empty?
- key = l.shift[1..-1]
- val = l.shift
- val = num_or_str(val) if val
- r[key] = val
- end
- r
- end
- end
- def self.get_limit(limit_type, slave = '', slot = nil)
- __getip.get_limit(limit_type, slave, slot)
- end
-
- def recursion_limit(slave = '', limit = None)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- number(@interp._invoke('interp', 'recursionlimit',
- _slavearg(slave), limit))
- end
- def self.recursion_limit(slave = '', limit = None)
- __getip.recursion_limit(slave)
- end
-
- def alias_target(aliascmd, slave = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp', 'target', _slavearg(slave), aliascmd)
- end
- def self.alias_target(aliascmd, slave = '')
- __getip.alias_target(aliascmd, slave)
- end
-
- def share_stdin(dist, src = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp', 'share', src, 'stdin', dist)
- self
- end
- def self.share_stdin(dist, src = '')
- __getip.share_stdin(dist, src)
- self
- end
-
- def share_stdout(dist, src = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp', 'share', src, 'stdout', dist)
- self
- end
- def self.share_stdout(dist, src = '')
- __getip.share_stdout(dist, src)
- self
- end
-
- def share_stderr(dist, src = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp', 'share', src, 'stderr', dist)
- self
- end
- def self.share_stderr(dist, src = '')
- __getip.share_stderr(dist, src)
- self
- end
-
- def transfer_stdin(dist, src = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp', 'transfer', src, 'stdin', dist)
- self
- end
- def self.transfer_stdin(dist, src = '')
- __getip.transfer_stdin(dist, src)
- self
- end
-
- def transfer_stdout(dist, src = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp', 'transfer', src, 'stdout', dist)
- self
- end
- def self.transfer_stdout(dist, src = '')
- __getip.transfer_stdout(dist, src)
- self
- end
-
- def transfer_stderr(dist, src = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp', 'transfer', src, 'stderr', dist)
- self
- end
- def self.transfer_stderr(dist, src = '')
- __getip.transfer_stderr(dist, src)
- self
- end
-
- def share_stdio(dist, src = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp', 'share', src, 'stdin', dist)
- @interp._invoke('interp', 'share', src, 'stdout', dist)
- @interp._invoke('interp', 'share', src, 'stderr', dist)
- self
- end
- def self.share_stdio(dist, src = '')
- __getip.share_stdio(dist, src)
- self
- end
-
- def transfer_stdio(dist, src = '')
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._invoke('interp', 'transfer', src, 'stdin', dist)
- @interp._invoke('interp', 'transfer', src, 'stdout', dist)
- @interp._invoke('interp', 'transfer', src, 'stderr', dist)
- self
- end
- def self.transfer_stdio(dist, src = '')
- __getip.transfer_stdio(dist, src)
- self
- end
-end
-
-
-# Safe Base :: manipulating safe interpreter
-class MultiTkIp
- def safeip_configure(slot, value=None)
- # use for '-noStatics' option ==> {statics=>false}
- # for '-nestedLoadOk' option ==> {nested=>true}
- if slot.kind_of?(Hash)
- ip = MultiTkIp.__getip
- ip._eval('::safe::interpConfigure ' + @ip_name + ' ' + _keys2opts(slot))
- else
- ip._eval('::safe::interpConfigure ' + @ip_name + ' ' +
- "-#{slot} #{_get_eval_string(value)}")
- end
- self
- end
-
- def safeip_configinfo(slot = nil)
- ip = MultiTkIp.__getip
- ret = {}
- if slot
- conf = _lst2ary(ip._eval("::safe::interpConfigure " +
- @ip_name + " -#{slot}"))
- if conf[0] == '-deleteHook'
-=begin
- if conf[1] =~ /^rb_out\S* (c(_\d+_)?\d+)/
- ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
-=end
- if conf[1] =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
- ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$4]
- else
- ret[conf[0][1..-1]] = conf[1]
- end
- else
- ret[conf[0][1..-1]] = conf[1]
- end
- else
- Hash[*_lst2ary(ip._eval("::safe::interpConfigure " +
- @ip_name))].each{|k, v|
- if k == '-deleteHook'
-=begin
- if v =~ /^rb_out\S* (c(_\d+_)?\d+)/
- ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
-=end
- if v =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
- ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$4]
- else
- ret[k[1..-1]] = v
- end
- else
- ret[k[1..-1]] = v
- end
- }
- end
- ret
- end
-
- def safeip_delete
- ip = MultiTkIp.__getip
- ip._eval("::safe::interpDelete " + @ip_name)
- end
-
- def safeip_add_to_access_path(dir)
- ip = MultiTkIp.__getip
- ip._eval("::safe::interpAddToAccessPath #{@ip_name} #{dir}")
- end
-
- def safeip_find_in_access_path(dir)
- ip = MultiTkIp.__getip
- ip._eval("::safe::interpFindInAccessPath #{@ip_name} #{dir}")
- end
-
- def safeip_set_log_cmd(cmd = Proc.new)
- ip = MultiTkIp.__getip
- ip._eval("::safe::setLogCmd #{@ip_name} #{_get_eval_string(cmd)}")
- end
-end
-
-
-# encoding convert
-class MultiTkIp
- def encoding
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.encoding
- end
- def encoding=(enc)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.encoding = enc
- end
-
- def encoding_convertfrom(str, enc=None)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.encoding_convertfrom(str, enc)
- end
- alias encoding_convert_from encoding_convertfrom
-
- def encoding_convertto(str, enc=None)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.encoding_convertto(str, enc)
- end
- alias encoding_convert_to encoding_convertto
-end
-
-
-# remove methods for security
-class MultiTkIp
- # undef_method :instance_eval
- undef_method :instance_variable_get
- undef_method :instance_variable_set
-end
-
-
-# end of MultiTkIp definition
-
-# defend against modification
-#MultiTkIp.freeze
-#TclTkLib.freeze
-
-########################################
-# start Tk which depends on MultiTkIp
-module TkCore
- INTERP = MultiTkIp
-end
-require 'tk'
diff --git a/ext/tk/lib/remote-tk.rb b/ext/tk/lib/remote-tk.rb
deleted file mode 100644
index 70115a60aa..0000000000
--- a/ext/tk/lib/remote-tk.rb
+++ /dev/null
@@ -1,526 +0,0 @@
-#
-# remote-tk.rb - supports to control remote Tk interpreters
-# by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
-
-if defined? MultiTkIp
- fail RuntimeError, "'remote-tk' library must be required before requiring 'multi-tk'"
-end
-
-class MultiTkIp; end
-class RemoteTkIp < MultiTkIp; end
-
-class MultiTkIp
- @@IP_TABLE = {}.taint unless defined?(@@IP_TABLE)
- @@TK_TABLE_LIST = [].taint unless defined?(@@TK_TABLE_LIST)
- def self._IP_TABLE; @@IP_TABLE; end
- def self._TK_TABLE_LIST; @@TK_TABLE_LIST; end
-
- @flag = true
- def self._DEFAULT_MASTER
- # work only once
- if @flag
- @flag = nil
- @@DEFAULT_MASTER
- else
- nil
- end
- end
-end
-class RemoteTkIp
- @@IP_TABLE = MultiTkIp._IP_TABLE unless defined?(@@IP_TABLE)
- @@TK_TABLE_LIST = MultiTkIp._TK_TABLE_LIST unless defined?(@@TK_TABLE_LIST)
-end
-class << MultiTkIp
- undef _IP_TABLE
- undef _TK_TABLE_LIST
-end
-
-require 'multi-tk'
-
-class RemoteTkIp
- if defined?(@@DEFAULT_MASTER)
- MultiTkIp._DEFAULT_MASTER
- else
- @@DEFAULT_MASTER = MultiTkIp._DEFAULT_MASTER
- end
-end
-
-
-###############################
-
-class << RemoteTkIp
- undef new_master, new_slave, new_safe_slave
- undef new_trusted_slave, new_safeTk
-
- def new(*args, &b)
- ip = __new(*args)
- ip.eval_proc(&b) if b
- ip
- end
-end
-
-class RemoteTkIp
- def initialize(remote_ip, displayof=nil, timeout=5)
- if $SAFE >= 4
- fail SecurityError, "cannot access another interpreter at level #{$SAFE}"
- end
-
- @interp = MultiTkIp.__getip
- if @interp.safe?
- fail SecurityError, "safe-IP cannot create RemoteTkIp"
- end
-
-
- @interp.allow_ruby_exit = false
- @appname = @interp._invoke('tk', 'appname')
- @remote = remote_ip.to_s.dup.freeze
- if displayof.kind_of?(TkWindow)
- @displayof = displayof.path.dup.freeze
- else
- @displayof = nil
- end
- if self.deleted?
- fail RuntimeError, "no Tk application named \"#{@remote}\""
- end
-
- @tk_windows = {}
- @tk_table_list = []
- @slave_ip_tbl = {}
- @slave_ip_top = {}
-
- @tk_windows.taint unless @tk_windows.tainted?
- @tk_table_list.taint unless @tk_table_list.tainted?
- @slave_ip_tbl.taint unless @slave_ip_tbl.tainted?
- @slave_ip_top.taint unless @slave_ip_top.tainted?
-
- @system = Object.new
-
- @threadgroup = ThreadGroup.new
-
- @safe_level = [$SAFE]
-
- @wait_on_mainloop = [true, 0]
-
- @cmd_queue = Queue.new
-
-=begin
- @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog()
-
- @threadgroup.add @cmd_receiver
- @threadgroup.add @receiver_watchdog
-
- @threadgroup.enclose
-=end
- @@DEFAULT_MASTER.assign_receiver_and_watchdog(self)
-
- @@IP_TABLE[@threadgroup] = self
- @@TK_TABLE_LIST.size.times{
- (tbl = {}).tainted? || tbl.taint
- @tk_table_list << tbl
- }
-
- @ret_val = TkVariable.new
- if timeout > 0 && ! _available_check(timeout)
- fail RuntimeError, "cannot create connection"
- end
- @ip_id = _create_connection
-
- class << self
- undef :instance_eval
- end
-
- self.freeze # defend against modification
- end
-
- def manipulable?
- return true if (Thread.current.group == ThreadGroup::Default)
- MultiTkIp.__getip == @interp && ! @interp.safe?
- end
- def self.manipulable?
- true
- end
-
- def _is_master_of?(tcltkip_obj)
- tcltkip_obj == @interp
- end
- protected :_is_master_of?
-
- def _ip_id_
- @ip_id
- end
-
- def _available_check(timeout = 5)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- return nil if timeout < 1
- @ret_val.value = ''
- @interp._invoke('send', '-async', @remote,
- 'send', '-async', Tk.appname,
- "set #{@ret_val.id} ready")
- Tk.update
- if @ret_val != 'ready'
- (1..(timeout*5)).each{
- sleep 0.2
- Tk.update
- break if @ret_val == 'ready'
- }
- end
- @ret_val.value == 'ready'
- end
- private :_available_check
-
- def _create_connection
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- ip_id = '_' + @interp._invoke('send', @remote, <<-'EOS') + '_'
- if {[catch {set _rubytk_control_ip_id_} ret] != 0} {
- set _rubytk_control_ip_id_ 0
- } else {
- set _rubytk_control_ip_id_ [expr $ret + 1]
- }
- return $_rubytk_control_ip_id_
- EOS
-
- @interp._invoke('send', @remote, <<-EOS)
- proc rb_out#{ip_id} args {
- send #{@appname} rb_out \$args
- }
- EOS
-
- ip_id
- end
- private :_create_connection
-
- def _appsend(enc_mode, async, *cmds)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- p ['_appsend', [@remote, @displayof], enc_mode, async, cmds] if $DEBUG
- if $SAFE >= 4
- fail SecurityError, "cannot send commands at level 4"
- elsif $SAFE >= 1 && cmds.find{|obj| obj.tainted?}
- fail SecurityError, "cannot send tainted commands at level #{$SAFE}"
- end
-
- cmds = @interp._merge_tklist(*TkUtil::_conv_args([], enc_mode, *cmds))
- if @displayof
- if async
- @interp.__invoke('send', '-async', '-displayof', @displayof,
- '--', @remote, *cmds)
- else
- @interp.__invoke('send', '-displayof', @displayof,
- '--', @remote, *cmds)
- end
- else
- if async
- @interp.__invoke('send', '-async', '--', @remote, *cmds)
- else
- @interp.__invoke('send', '--', @remote, *cmds)
- end
- end
- end
- private :_appsend
-
- def ready?(timeout=5)
- if timeout < 0
- fail ArgumentError, "timeout must be positive number"
- end
- _available_check(timeout)
- end
-
- def is_rubytk?
- return false if _appsend(false, false, 'info', 'command', 'ruby') == ""
- [ _appsend(false, false, 'ruby', 'RUBY_VERSION'),
- _appsend(false, false, 'set', 'tk_patchLevel') ]
- end
-
- def appsend(async, *args)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- if async != true && async != false && async != nil
- args.unshift(async)
- async = false
- end
- if @displayof
- Tk.appsend_displayof(@remote, @displayof, async, *args)
- else
- Tk.appsend(@remote, async, *args)
- end
- end
-
- def rb_appsend(async, *args)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- if async != true && async != false && async != nil
- args.unshift(async)
- async = false
- end
- if @displayof
- Tk.rb_appsend_displayof(@remote, @displayof, async, *args)
- else
- Tk.rb_appsend(@remote, async, *args)
- end
- end
-
- def create_slave(name, safe=false)
- if safe
- safe_opt = ''
- else
- safe_opt = '-safe'
- end
- _appsend(false, false, "interp create #{safe_opt} -- #{name}")
- end
-
- def make_safe
- fail RuntimeError, 'cannot change safe mode of the remote interpreter'
- end
-
- def safe?
- _appsend(false, false, 'interp issafe')
- end
-
- def safe_base?
- false
- end
-
- def allow_ruby_exit?
- false
- end
-
- def allow_ruby_exit= (mode)
- fail RuntimeError, 'cannot change mode of the remote interpreter'
- end
-
- def delete
- _appsend(false, true, 'exit')
- end
-
- def deleted?
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- if @displayof
- lst = @interp._invoke_without_enc('winfo', 'interps',
- '-displayof', @displayof)
- else
- lst = @interp._invoke_without_enc('winfo', 'interps')
- end
- # unless @interp._split_tklist(lst).index(@remote)
- unless @interp._split_tklist(lst).index(_toUTF8(@remote))
- true
- else
- false
- end
- end
-
- def has_mainwindow?
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
-
- begin
- inf = @interp._invoke_without_enc('info', 'command', '.')
- rescue Exception
- return nil
- end
- if !inf.kind_of?(String) || inf != '.'
- false
- else
- true
- end
- end
-
- def invalid_namespace?
- false
- end
-
- def restart
- fail RuntimeError, 'cannot restart the remote interpreter'
- end
-
- def __eval(str)
- _appsend(false, false, str)
- end
- def _eval(str)
- _appsend(nil, false, str)
- end
- def _eval_without_enc(str)
- _appsend(false, false, str)
- end
- def _eval_with_enc(str)
- _appsend(true, false, str)
- end
-
- def _invoke(*args)
- _appsend(nil, false, *args)
- end
-
- def __invoke(*args)
- _appsend(false, false, *args)
- end
- def _invoke(*args)
- _appsend(nil, false, *args)
- end
- def _invoke_without_enc(*args)
- _appsend(false, false, *args)
- end
- def _invoke_with_enc(*args)
- _appsend(true, false, *args)
- end
-
- def _toUTF8(str, encoding=nil)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._toUTF8(str, encoding)
- end
-
- def _fromUTF8(str, encoding=nil)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._fromUTF8(str, encoding)
- end
-
- def _thread_vwait(var_name)
- _appsend(false, 'thread_vwait', varname)
- end
-
- def _thread_tkwait(mode, target)
- _appsend(false, 'thread_tkwait', mode, target)
- end
-
- def _return_value
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._return_value
- end
-
- def _get_variable(var_name, flag)
- # ignore flag
- _appsend(false, 'set', TkComm::_get_eval_string(var_name))
- end
- def _get_variable2(var_name, index_name, flag)
- # ignore flag
- _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})")
- end
-
- def _set_variable(var_name, value, flag)
- # ignore flag
- _appsend(false, 'set', TkComm::_get_eval_string(var_name), TkComm::_get_eval_string(value))
- end
- def _set_variable2(var_name, index_name, value, flag)
- # ignore flag
- _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})", TkComm::_get_eval_string(value))
- end
-
- def _unset_variable(var_name, flag)
- # ignore flag
- _appsend(false, 'unset', TkComm::_get_eval_string(var_name))
- end
- def _unset_variable2(var_name, index_name, flag)
- # ignore flag
- _appsend(false, 'unset', "#{var_name}(#{index_name})")
- end
-
- def _get_global_var(var_name)
- _appsend(false, 'set', TkComm::_get_eval_string(var_name))
- end
- def _get_global_var2(var_name, index_name)
- _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})")
- end
-
- def _set_global_var(var_name, value)
- _appsend(false, 'set', TkComm::_get_eval_string(var_name), TkComm::_get_eval_string(value))
- end
- def _set_global_var2(var_name, index_name, value)
- _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})", TkComm::_get_eval_string(value))
- end
-
- def _unset_global_var(var_name)
- _appsend(false, 'unset', TkComm::_get_eval_string(var_name))
- end
- def _unset_global_var2(var_name, index_name)
- _appsend(false, 'unset', "#{var_name}(#{index_name})")
- end
-
- def _split_tklist(str)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._split_tklist(str)
- end
-
- def _merge_tklist(*args)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._merge_tklist(*args)
- end
-
- def _conv_listelement(str)
- raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp._conv_listelement(str)
- end
-
- def _create_console
- fail RuntimeError, 'not support "_create_console" on the remote interpreter'
- end
-
- def mainloop
- fail RuntimeError, 'not support "mainloop" on the remote interpreter'
- end
- def mainloop_watchdog
- fail RuntimeError, 'not support "mainloop_watchdog" on the remote interpreter'
- end
- def do_one_evant(flag = nil)
- fail RuntimeError, 'not support "do_one_event" on the remote interpreter'
- end
- def mainloop_abort_on_exception
- fail RuntimeError, 'not support "mainloop_abort_on_exception" on the remote interpreter'
- end
- def mainloop_abort_on_exception=(mode)
- fail RuntimeError, 'not support "mainloop_abort_on_exception=" on the remote interpreter'
- end
- def set_eventloop_tick(*args)
- fail RuntimeError, 'not support "set_eventloop_tick" on the remote interpreter'
- end
- def get_eventloop_tick
- fail RuntimeError, 'not support "get_eventloop_tick" on the remote interpreter'
- end
- def set_no_event_wait(*args)
- fail RuntimeError, 'not support "set_no_event_wait" on the remote interpreter'
- end
- def get_no_event_wait
- fail RuntimeError, 'not support "get_no_event_wait" on the remote interpreter'
- end
- def set_eventloop_weight(*args)
- fail RuntimeError, 'not support "set_eventloop_weight" on the remote interpreter'
- end
- def get_eventloop_weight
- fail RuntimeError, 'not support "get_eventloop_weight" on the remote interpreter'
- end
-end
-
-class << RemoteTkIp
- def mainloop(*args)
- fail RuntimeError, 'not support "mainloop" on the remote interpreter'
- end
- def mainloop_watchdog(*args)
- fail RuntimeError, 'not support "mainloop_watchdog" on the remote interpreter'
- end
- def do_one_evant(flag = nil)
- fail RuntimeError, 'not support "do_one_event" on the remote interpreter'
- end
- def mainloop_abort_on_exception
- fail RuntimeError, 'not support "mainloop_abort_on_exception" on the remote interpreter'
- end
- def mainloop_abort_on_exception=(mode)
- fail RuntimeError, 'not support "mainloop_abort_on_exception=" on the remote interpreter'
- end
- def set_eventloop_tick(*args)
- fail RuntimeError, 'not support "set_eventloop_tick" on the remote interpreter'
- end
- def get_eventloop_tick
- fail RuntimeError, 'not support "get_eventloop_tick" on the remote interpreter'
- end
- def set_no_event_wait(*args)
- fail RuntimeError, 'not support "set_no_event_wait" on the remote interpreter'
- end
- def get_no_event_wait
- fail RuntimeError, 'not support "get_no_event_wait" on the remote interpreter'
- end
- def set_eventloop_weight(*args)
- fail RuntimeError, 'not support "set_eventloop_weight" on the remote interpreter'
- end
- def get_eventloop_weight
- fail RuntimeError, 'not support "get_eventloop_weight" on the remote interpreter'
- end
-end
diff --git a/ext/tk/lib/tcltk.rb b/ext/tk/lib/tcltk.rb
deleted file mode 100644
index 1a6694dbff..0000000000
--- a/ext/tk/lib/tcltk.rb
+++ /dev/null
@@ -1,367 +0,0 @@
-# tof
-
-#### tcltk library, more direct manipulation of tcl/tk
-#### Sep. 5, 1997 Y. Shigehiro
-
-require "tcltklib"
-
-################
-
-# module TclTk: collection of tcl/tk utilities (supplies namespace.)
-module TclTk
-
- # initialize Hash to hold unique symbols and such
- @namecnt = {}
-
- # initialize Hash to hold callbacks
- @callback = {}
-end
-
-# TclTk.mainloop(): call TclTkLib.mainloop()
-def TclTk.mainloop()
- print("mainloop: start\n") if $DEBUG
- TclTkLib.mainloop()
- print("mainloop: end\n") if $DEBUG
-end
-
-# TclTk.deletecallbackkey(ca): remove callback from TclTk module
-# this does not remove callbacks from tcl/tk interpreter
-# without calling this method, TclTkInterpreter will not be GCed
-# ca: callback(TclTkCallback)
-def TclTk.deletecallbackkey(ca)
- print("deletecallbackkey: ", ca.to_s(), "\n") if $DEBUG
- @callback.delete(ca.to_s)
-end
-
-# TclTk.dcb(ca, wid, W): call TclTk.deletecallbackkey() for each callbacks
-# in an array.
-# this is for callback for top-level <Destroy>
-# ca: array of callbacks(TclTkCallback)
-# wid: top-level widget(TclTkWidget)
-# w: information about window given by %W(String)
-def TclTk.dcb(ca, wid, w)
- if wid.to_s() == w
- ca.each{|i|
- TclTk.deletecallbackkey(i)
- }
- end
-end
-
-# TclTk._addcallback(ca): register callback
-# ca: callback(TclTkCallback)
-def TclTk._addcallback(ca)
- print("_addcallback: ", ca.to_s(), "\n") if $DEBUG
- @callback[ca.to_s()] = ca
-end
-
-# TclTk._callcallback(key, arg): invoke registered callback
-# key: key to select callback (to_s value of the TclTkCallback)
-# arg: parameter from tcl/tk interpreter
-def TclTk._callcallback(key, arg)
- print("_callcallback: ", @callback[key].inspect, "\n") if $DEBUG
- @callback[key]._call(arg)
- # throw out callback value
- # should return String to satisfy rb_eval_string()
- return ""
-end
-
-# TclTk._newname(prefix): generate unique name(String)
-# prefix: prefix of the unique name
-def TclTk._newname(prefix)
- # generated name counter is stored in @namecnt
- if !@namecnt.key?(prefix)
- # first appearing prefix, initialize
- @namecnt[prefix] = 1
- else
- # already appeared prefix, generate next name
- @namecnt[prefix] += 1
- end
- return "#{prefix}#{@namecnt[prefix]}"
-end
-
-################
-
-# class TclTkInterpreter: tcl/tk interpreter
-class TclTkInterpreter
-
- # initialize():
- def initialize()
- # generate interpreter object
- @ip = TclTkIp.new()
-
- # add ruby_fmt command to tcl interpreter
- # ruby_fmt command format arguments by `format' and call `ruby' command
- # (notice ruby command receives only one argument)
- if $DEBUG
- @ip._eval("proc ruby_fmt {fmt args} { puts \"ruby_fmt: $fmt $args\" ; set cmd [list ruby [format $fmt $args]] ; uplevel $cmd }")
- else
- @ip._eval("proc ruby_fmt {fmt args} { set cmd [list ruby [format $fmt $args]] ; uplevel $cmd }")
- end
-
- # @ip._get_eval_string(*args): generate string to evaluate in tcl interpreter
- # *args: script which is going to be evaluated under tcl/tk
- def @ip._get_eval_string(*args)
- argstr = ""
- args.each{|arg|
- argstr += " " if argstr != ""
- # call to_eval if it is defined
- if (arg.respond_to?(:to_eval))
- argstr += arg.to_eval()
- else
- # call to_s unless defined
- argstr += arg.to_s()
- end
- }
- return argstr
- end
-
- # @ip._eval_args(*args): evaluate string under tcl/tk interpreter
- # returns result string.
- # *args: script which is going to be evaluated under tcl/tk
- def @ip._eval_args(*args)
- # calculate the string to eval in the interpreter
- argstr = _get_eval_string(*args)
-
- # evaluate under the interpreter
- print("_eval: \"", argstr, "\"") if $DEBUG
- res = _eval(argstr)
- if $DEBUG
- print(" -> \"", res, "\"\n")
- elsif _return_value() != 0
- print(res, "\n")
- end
- fail(%Q/can't eval "#{argstr}"/) if _return_value() != 0 #'
- return res
- end
-
- # generate tcl/tk command object and register in the hash
- @commands = {}
- # for all commands registered in tcl/tk interpreter:
- @ip._eval("info command").split(/ /).each{|comname|
- if comname =~ /^[.]/
- # if command is a widget (path), generate TclTkWidget,
- # and register it in the hash
- @commands[comname] = TclTkWidget.new(@ip, comname)
- else
- # otherwise, generate TclTkCommand
- @commands[comname] = TclTkCommand.new(@ip, comname)
- end
- }
- end
-
- # commands(): returns hash of the tcl/tk commands
- def commands()
- return @commands
- end
-
- # rootwidget(): returns root widget(TclTkWidget)
- def rootwidget()
- return @commands["."]
- end
-
- # _tcltkip(): returns @ip(TclTkIp)
- def _tcltkip()
- return @ip
- end
-
- # method_missing(id, *args): execute undefined method as tcl/tk command
- # id: method symbol
- # *args: method arguments
- def method_missing(id, *args)
- # if command named by id registered, then execute it
- if @commands.key?(id.id2name)
- return @commands[id.id2name].e(*args)
- else
- # otherwise, exception
- super
- end
- end
-end
-
-# class TclTkObject: base class of the tcl/tk objects
-class TclTkObject
-
- # initialize(ip, exp):
- # ip: interpreter(TclTkIp)
- # exp: tcl/tk representation
- def initialize(ip, exp)
- fail("type is not TclTkIp") if !ip.kind_of?(TclTkIp)
- @ip = ip
- @exp = exp
- end
-
- # to_s(): returns tcl/tk representation
- def to_s()
- return @exp
- end
-end
-
-# class TclTkCommand: tcl/tk commands
-# you should not call TclTkCommand.new()
-# commands are created by TclTkInterpreter:initialize()
-class TclTkCommand < TclTkObject
-
- # e(*args): execute command. returns String (e is for exec or eval)
- # *args: command arguments
- def e(*args)
- return @ip._eval_args(to_s(), *args)
- end
-end
-
-# class TclTkLibCommand: tcl/tk commands in the library
-class TclTkLibCommand < TclTkCommand
-
- # initialize(ip, name):
- # ip: interpreter(TclTkInterpreter)
- # name: command name (String)
- def initialize(ip, name)
- super(ip._tcltkip, name)
- end
-end
-
-# class TclTkVariable: tcl/tk variable
-class TclTkVariable < TclTkObject
-
- # initialize(interp, dat):
- # interp: interpreter(TclTkInterpreter)
- # dat: the value to set(String)
- # if nil, not initialize variable
- def initialize(interp, dat)
- # auto-generate tcl/tk representation (variable name)
- exp = TclTk._newname("v_")
- # initialize TclTkObject
- super(interp._tcltkip(), exp)
- # safe this for `set' command
- @set = interp.commands()["set"]
- # set value
- set(dat) if dat
- end
-
- # although you can set/refer variable by using set in tcl/tk,
- # we provide the method for accessing variables
-
- # set(data): set tcl/tk variable using `set'
- # data: new value
- def set(data)
- @set.e(to_s(), data.to_s())
- end
-
- # get(): read tcl/tk variable(String) using `set'
- def get()
- return @set.e(to_s())
- end
-end
-
-# class TclTkWidget: tcl/tk widget
-class TclTkWidget < TclTkCommand
-
- # initialize(*args):
- # *args: parameters
- def initialize(*args)
- if args[0].kind_of?(TclTkIp)
- # in case the 1st argument is TclTkIp:
-
- # Wrap tcl/tk widget by TclTkWidget
- # (used in TclTkInterpreter#initialize())
-
- # need two arguments
- fail("illegal # of parameter") if args.size != 2
-
- # ip: interpreter(TclTkIp)
- # exp: tcl/tk representation
- ip, exp = args
-
- # initialize TclTkObject
- super(ip, exp)
- elsif args[0].kind_of?(TclTkInterpreter)
- # in case 1st parameter is TclTkInterpreter:
-
- # generate new widget from parent widget
-
- # interp: interpreter(TclTkInterpreter)
- # parent: parent widget
- # command: widget generating tk command(label Åù)
- # *args: argument to the command
- interp, parent, command, *args = args
-
- # generate widget name
- exp = parent.to_s()
- exp += "." if exp !~ /[.]$/
- exp += TclTk._newname("w_")
- # initialize TclTkObject
- super(interp._tcltkip(), exp)
- # generate widget
- res = @ip._eval_args(command, exp, *args)
-# fail("can't create Widget") if res != exp
- # for tk_optionMenu, it is legal res != exp
- else
- fail("first parameter is not TclTkInterpreter")
- end
- end
-end
-
-# class TclTkCallback: tcl/tk callbacks
-class TclTkCallback < TclTkObject
-
- # initialize(interp, pr, arg):
- # interp: interpreter(TclTkInterpreter)
- # pr: callback procedure(Proc)
- # arg: string to pass as block parameters of pr
- # bind command of tcl/tk uses % replacement for parameters
- # pr can receive replaced data using block parameter
- # its format is specified by arg string
- # You should not specify arg for the command like
- # scrollbar with -command option, which receives parameters
- # without specifying any replacement
- def initialize(interp, pr, arg = nil)
- # auto-generate tcl/tk representation (variable name)
- exp = TclTk._newname("c_")
- # initialize TclTkObject
- super(interp._tcltkip(), exp)
- # save parameters
- @pr = pr
- @arg = arg
- # register in the module
- TclTk._addcallback(self)
- end
-
- # to_eval(): retuens string representation for @ip._eval_args
- def to_eval()
- if @arg
- # bind replaces %s before calling ruby_fmt, so %%s is used
- s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%%s")} #{@arg}}/
- else
- s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%s")}}/
- end
-
- return s
- end
-
- # _call(arg): invoke callback
- # arg: callback parameter
- def _call(arg)
- @pr.call(arg)
- end
-end
-
-# class TclTkImage: tcl/tk images
-class TclTkImage < TclTkCommand
-
- # initialize(interp, t, *args):
- # generating image is done by TclTkImage.new()
- # destrying is done by image delete (inconsistent, sigh)
- # interp: interpreter(TclTkInterpreter)
- # t: image type (photo, bitmap, etc.)
- # *args: command argument
- def initialize(interp, t, *args)
- # auto-generate tcl/tk representation
- exp = TclTk._newname("i_")
- # initialize TclTkObject
- super(interp._tcltkip(), exp)
- # generate image
- res = @ip._eval_args("image create", t, exp, *args)
- fail("can't create Image") if res != exp
- end
-end
-
-# eof
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
deleted file mode 100644
index eefe4b5556..0000000000
--- a/ext/tk/lib/tk.rb
+++ /dev/null
@@ -1,4615 +0,0 @@
-#
-# tk.rb - Tk interface module using tcltklib
-# $Date$
-# by Yukihiro Matsumoto <matz@netlab.jp>
-
-# use Shigehiro's tcltklib
-require 'tcltklib'
-require 'tkutil'
-
-# autoload
-require 'tk/autoload'
-
-class TclTkIp
- # backup original (without encoding) _eval and _invoke
- alias _eval_without_enc _eval
- alias _invoke_without_enc _invoke
-
- def _ip_id_
- # for RemoteTkIp
- ''
- end
-end
-
-# define TkComm module (step 1: basic functions)
-module TkComm
- include TkUtil
- extend TkUtil
-
- WidgetClassNames = {}.taint
- TkExtlibAutoloadModule = [].taint
-
- # None = Object.new ### --> definition is moved to TkUtil module
- # def None.to_s
- # 'None'
- # end
- # None.freeze
-
- #Tk_CMDTBL = {}
- #Tk_WINDOWS = {}
- Tk_IDs = ["00000".taint, "00000".taint].freeze # [0]-cmdid, [1]-winid
-
- # for backward compatibility
- Tk_CMDTBL = Object.new
- def Tk_CMDTBL.method_missing(id, *args)
- TkCore::INTERP.tk_cmd_tbl.__send__(id, *args)
- end
- Tk_CMDTBL.freeze
- Tk_WINDOWS = Object.new
- def Tk_WINDOWS.method_missing(id, *args)
- TkCore::INTERP.tk_windows.__send__(id, *args)
- end
- Tk_WINDOWS.freeze
-
- self.instance_eval{
- @cmdtbl = [].taint
- }
-
- unless const_defined?(:GET_CONFIGINFO_AS_ARRAY)
- # GET_CONFIGINFO_AS_ARRAY = false => returns a Hash { opt =>val, ... }
- # true => returns an Array [[opt,val], ... ]
- # val is a list which includes resource info.
- GET_CONFIGINFO_AS_ARRAY = true
- end
- unless const_defined?(:GET_CONFIGINFOwoRES_AS_ARRAY)
- # for configinfo without resource info; list of [opt, value] pair
- # false => returns a Hash { opt=>val, ... }
- # true => returns an Array [[opt,val], ... ]
- GET_CONFIGINFOwoRES_AS_ARRAY = true
- end
- # *** ATTENTION ***
- # 'current_configinfo' method always returns a Hash under all cases of above.
-
- def error_at
- frames = caller()
- frames.delete_if do |c|
- c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+!
- end
- frames
- end
- private :error_at
-
- def _genobj_for_tkwidget(path)
- return TkRoot.new if path == '.'
-
- begin
- #tk_class = TkCore::INTERP._invoke('winfo', 'class', path)
- tk_class = Tk.ip_invoke_without_enc('winfo', 'class', path)
- rescue
- return path
- end
-
- if ruby_class = WidgetClassNames[tk_class]
- ruby_class_name = ruby_class.name
- # gen_class_name = ruby_class_name + 'GeneratedOnTk'
- gen_class_name = ruby_class_name
- classname_def = ''
- else # ruby_class == nil
- mods = TkExtlibAutoloadModule.find_all{|m| m.const_defined?(tk_class)}
- mods.each{|mod|
- begin
- mod.const_get(tk_class) # auto_load
- break if (ruby_class = WidgetClassNames[tk_class])
- rescue LoadError
- # ignore load error
- end
- }
-
- unless ruby_class
- std_class = 'Tk' << tk_class
- if Object.const_defined?(std_class)
- Object.const_get(std_class) # auto_load
- ruby_class = WidgetClassNames[tk_class]
- end
- end
-
- if ruby_class
- # found
- ruby_class_name = ruby_class.name
- gen_class_name = ruby_class_name
- classname_def = ''
- else
- # unknown
- ruby_class_name = 'TkWindow'
- gen_class_name = 'TkWidget_' + tk_class
- classname_def = "WidgetClassName = '#{tk_class}'.freeze"
- end
- end
-
-###################################
-=begin
- if ruby_class = WidgetClassNames[tk_class]
- ruby_class_name = ruby_class.name
- # gen_class_name = ruby_class_name + 'GeneratedOnTk'
- gen_class_name = ruby_class_name
- classname_def = ''
- else
- mod = TkExtlibAutoloadModule.find{|m| m.const_defined?(tk_class)}
- if mod
- ruby_class_name = mod.name + '::' + tk_class
- gen_class_name = ruby_class_name
- classname_def = ''
- elsif Object.const_defined?('Tk' + tk_class)
- ruby_class_name = 'Tk' + tk_class
- # gen_class_name = ruby_class_name + 'GeneratedOnTk'
- gen_class_name = ruby_class_name
- classname_def = ''
- else
- ruby_class_name = 'TkWindow'
- # gen_class_name = ruby_class_name + tk_class + 'GeneratedOnTk'
- gen_class_name = 'TkWidget_' + tk_class
- classname_def = "WidgetClassName = '#{tk_class}'.freeze"
- end
- end
-=end
-
-=begin
- unless Object.const_defined? gen_class_name
- Object.class_eval "class #{gen_class_name}<#{ruby_class_name}
- #{classname_def}
- end"
- end
- Object.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}',
- 'without_creating'=>true)"
-=end
- base = Object
- gen_class_name.split('::').each{|klass|
- next if klass == ''
- if base.const_defined?(klass)
- base = base.class_eval klass
- else
- base = base.class_eval "class #{klass}<#{ruby_class_name}
- #{classname_def}
- end
- #{klass}"
- end
- }
- base.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}',
- 'without_creating'=>true)"
- end
- private :_genobj_for_tkwidget
- module_function :_genobj_for_tkwidget
-
- def _at(x,y=nil)
- if y
- "@#{Integer(x)},#{Integer(y)}"
- else
- "@#{Integer(x)}"
- end
- end
- module_function :_at
-
- def tk_tcl2ruby(val, enc_mode = false, listobj = true)
-=begin
- if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
- #return Tk_CMDTBL[$1]
- return TkCore::INTERP.tk_cmd_tbl[$1]
- #cmd_obj = TkCore::INTERP.tk_cmd_tbl[$1]
- #if cmd_obj.kind_of?(Proc) || cmd_obj.kind_of?(Method)
- # cmd_obj
- #else
- # cmd_obj.cmd
- #end
- end
-=end
- if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
- return TkCore::INTERP.tk_cmd_tbl[$4]
- end
- #if val.include? ?\s
- # return val.split.collect{|v| tk_tcl2ruby(v)}
- #end
- case val
- when /\A@font\S+\z/
- TkFont.get_obj(val)
- when /\A-?\d+\z/
- val.to_i
- when /\A\.\S*\z/
- #Tk_WINDOWS[val] ? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
- TkCore::INTERP.tk_windows[val]?
- TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val)
- when /\Ai(_\d+_)?\d+\z/
- TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
- when /\A-?\d+\.?\d*(e[-+]?\d+)?\z/
- val.to_f
- when /\\ /
- val.gsub(/\\ /, ' ')
- when /[^\\] /
- if listobj
- #tk_split_escstr(val).collect{|elt|
- # tk_tcl2ruby(elt, enc_mode, listobj)
- #}
- val = _toUTF8(val) unless enc_mode
- tk_split_escstr(val, false, false).collect{|elt|
- tk_tcl2ruby(elt, true, listobj)
- }
- elsif enc_mode
- _fromUTF8(val)
- else
- val
- end
- else
- if enc_mode
- _fromUTF8(val)
- else
- val
- end
- end
- end
-
- private :tk_tcl2ruby
- module_function :tk_tcl2ruby
- #private_class_method :tk_tcl2ruby
-
-unless const_defined?(:USE_TCLs_LIST_FUNCTIONS)
- USE_TCLs_LIST_FUNCTIONS = true
-end
-
-if USE_TCLs_LIST_FUNCTIONS
- ###########################################################################
- # use Tcl function version of split_list
- ###########################################################################
-
- def tk_split_escstr(str, src_enc=true, dst_enc=true)
- str = _toUTF8(str) if src_enc
- if dst_enc
- TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)}
- else
- TkCore::INTERP._split_tklist(str)
- end
- end
-
- def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true)
- # return [] if str == ""
- # list = TkCore::INTERP._split_tklist(str)
- str = _toUTF8(str) if src_enc
-
- if depth == 0
- return "" if str == ""
- list = [str]
- else
- return [] if str == ""
- list = TkCore::INTERP._split_tklist(str)
- end
- if list.size == 1
- # tk_tcl2ruby(list[0], nil, false)
- tk_tcl2ruby(list[0], dst_enc, false)
- else
- list.collect{|token| tk_split_sublist(token, depth - 1, false, dst_enc)}
- end
- end
-
- def tk_split_list(str, depth=0, src_enc=true, dst_enc=true)
- return [] if str == ""
- str = _toUTF8(str) if src_enc
- TkCore::INTERP._split_tklist(str).map!{|token|
- tk_split_sublist(token, depth - 1, false, dst_enc)
- }
- end
-
- def tk_split_simplelist(str, src_enc=true, dst_enc=true)
- #lst = TkCore::INTERP._split_tklist(str)
- #if (lst.size == 1 && lst =~ /^\{.*\}$/)
- # TkCore::INTERP._split_tklist(str[1..-2])
- #else
- # lst
- #end
-
- str = _toUTF8(str) if src_enc
- if dst_enc
- TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)}
- else
- TkCore::INTERP._split_tklist(str)
- end
- end
-
- def array2tk_list(ary, enc=nil)
- return "" if ary.size == 0
-
- sys_enc = TkCore::INTERP.encoding
- sys_enc = TclTkLib.encoding_system unless sys_enc
-
- dst_enc = (enc == nil)? sys_enc: enc
-
- dst = ary.collect{|e|
- if e.kind_of? Array
- s = array2tk_list(e, enc)
- elsif e.kind_of? Hash
- tmp_ary = []
- #e.each{|k,v| tmp_ary << k << v }
- e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v }
- s = array2tk_list(tmp_ary, enc)
- else
- s = _get_eval_string(e, enc)
- end
-
- if dst_enc != true && dst_enc != false
- if (s_enc = s.instance_variable_get(:@encoding))
- s_enc = s_enc.to_s
- else
- s_enc = sys_enc
- end
- dst_enc = true if s_enc != dst_enc
- end
-
- s
- }
-
- if sys_enc && dst_enc
- dst.map!{|s| _toUTF8(s)}
- ret = TkCore::INTERP._merge_tklist(*dst)
- if dst_enc.kind_of?(String)
- ret = _fromUTF8(ret, dst_enc)
- ret.instance_variable_set(:@encoding, dst_enc)
- else
- ret.instance_variable_set(:@encoding, 'utf-8')
- end
- ret
- else
- TkCore::INTERP._merge_tklist(*dst)
- end
- end
-
-else
- ###########################################################################
- # use Ruby script version of split_list (traditional methods)
- ###########################################################################
-
- def tk_split_escstr(str, src_enc=true, dst_enc=true)
- return [] if str == ""
- list = []
- token = nil
- escape = false
- brace = 0
- str.split('').each {|c|
- brace += 1 if c == '{' && !escape
- brace -= 1 if c == '}' && !escape
- if brace == 0 && c == ' ' && !escape
- list << token.gsub(/^\{(.*)\}$/, '\1') if token
- token = nil
- else
- token = (token || "") << c
- end
- escape = (c == '\\' && !escape)
- }
- list << token.gsub(/^\{(.*)\}$/, '\1') if token
- list
- end
-
- def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true)
- #return [] if str == ""
- #return [tk_split_sublist(str[1..-2])] if str =~ /^\{.*\}$/
- #list = tk_split_escstr(str)
- if depth == 0
- return "" if str == ""
- str = str[1..-2] if str =~ /^\{.*\}$/
- list = [str]
- else
- return [] if str == []
- return [tk_split_sublist(str[1..-2], depth - 1)] if str =~ /^\{.*\}$/
- list = tk_split_escstr(str)
- end
- if list.size == 1
- tk_tcl2ruby(list[0], nil, false)
- else
- list.collect{|token| tk_split_sublist(token, depth - 1)}
- end
- end
-
- def tk_split_list(str, depth=0, src_enc=true, dst_enc=true)
- return [] if str == ""
- tk_split_escstr(str).collect{|token|
- tk_split_sublist(token, depth - 1)
- }
- end
-=begin
- def tk_split_list(str)
- return [] if str == ""
- idx = str.index('{')
- while idx and idx > 0 and str[idx-1] == ?\\
- idx = str.index('{', idx+1)
- end
- unless idx
- list = tk_tcl2ruby(str)
- unless Array === list
- list = [list]
- end
- return list
- end
-
- list = tk_tcl2ruby(str[0,idx])
- list = [] if list == ""
- str = str[idx+1..-1]
- i = -1
- escape = false
- brace = 1
- str.each_byte {|c|
- i += 1
- brace += 1 if c == ?{ && !escape
- brace -= 1 if c == ?} && !escape
- escape = (c == ?\\)
- break if brace == 0
- }
- if str.size == i + 1
- return tk_split_list(str[0, i])
- end
- if str[0, i] == ' '
- list.push ' '
- else
- list.push tk_split_list(str[0, i])
- end
- list += tk_split_list(str[i+1..-1])
- list
- end
-=end
-
- def tk_split_simplelist(str, src_enc=true, dst_enc=true)
- return [] if str == ""
- list = []
- token = nil
- escape = false
- brace = 0
- str.split('').each {|c|
- if c == '\\' && !escape
- escape = true
- token = (token || "") << c if brace > 0
- next
- end
- brace += 1 if c == '{' && !escape
- brace -= 1 if c == '}' && !escape
- if brace == 0 && c == ' ' && !escape
- list << token.gsub(/^\{(.*)\}$/, '\1') if token
- token = nil
- else
- token = (token || "") << c
- end
- escape = false
- }
- list << token.gsub(/^\{(.*)\}$/, '\1') if token
- list
- end
-
- def array2tk_list(ary, enc=nil)
- ary.collect{|e|
- if e.kind_of? Array
- "{#{array2tk_list(e, enc)}}"
- elsif e.kind_of? Hash
- # "{#{e.to_a.collect{|ee| array2tk_list(ee)}.join(' ')}}"
- e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v }
- array2tk_list(tmp_ary, enc)
- else
- s = _get_eval_string(e, enc)
- (s.index(/\s/) || s.size == 0)? "{#{s}}": s
- end
- }.join(" ")
- end
-end
-
- private :tk_split_escstr, :tk_split_sublist
- private :tk_split_list, :tk_split_simplelist
- private :array2tk_list
-
- module_function :tk_split_escstr, :tk_split_sublist
- module_function :tk_split_list, :tk_split_simplelist
- module_function :array2tk_list
-
- private_class_method :tk_split_escstr, :tk_split_sublist
- private_class_method :tk_split_list, :tk_split_simplelist
-# private_class_method :array2tk_list
-
-=begin
- ### --> definition is moved to TkUtil module
- def _symbolkey2str(keys)
- h = {}
- keys.each{|key,value| h[key.to_s] = value}
- h
- end
- private :_symbolkey2str
- module_function :_symbolkey2str
-=end
-
-=begin
- ### --> definition is moved to TkUtil module
- # def hash_kv(keys, enc_mode = nil, conf = [], flat = false)
- def hash_kv(keys, enc_mode = nil, conf = nil)
- # Hash {key=>val, key=>val, ... } or Array [ [key, val], [key, val], ... ]
- # ==> Array ['-key', val, '-key', val, ... ]
- dst = []
- if keys and keys != None
- keys.each{|k, v|
- #dst.push("-#{k}")
- dst.push('-' + k.to_s)
- if v != None
- # v = _get_eval_string(v, enc_mode) if (enc_mode || flat)
- v = _get_eval_string(v, enc_mode) if enc_mode
- dst.push(v)
- end
- }
- end
- if conf
- conf + dst
- else
- dst
- end
- end
- private :hash_kv
- module_function :hash_kv
-=end
-
-=begin
- ### --> definition is moved to TkUtil module
- def bool(val)
- case val
- when "1", 1, 'yes', 'true'
- true
- else
- false
- end
- end
-
- def number(val)
- case val
- when /^-?\d+$/
- val.to_i
- when /^-?\d+\.?\d*(e[-+]?\d+)?$/
- val.to_f
- else
- fail(ArgumentError, "invalid value for Number:'#{val}'")
- end
- end
- def string(val)
- if val == "{}"
- ''
- elsif val[0] == ?{ && val[-1] == ?}
- val[1..-2]
- else
- val
- end
- end
- def num_or_str(val)
- begin
- number(val)
- rescue ArgumentError
- string(val)
- end
- end
-=end
-
- def list(val, depth=0, enc=true)
- tk_split_list(val, depth, enc, enc)
- end
- def simplelist(val, src_enc=true, dst_enc=true)
- tk_split_simplelist(val, src_enc, dst_enc)
- end
- def window(val)
- if val =~ /^\./
- #Tk_WINDOWS[val]? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
- TkCore::INTERP.tk_windows[val]?
- TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val)
- else
- nil
- end
- end
- def image_obj(val)
- if val =~ /^i(_\d+_)?\d+$/
- TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
- else
- val
- end
- end
- def procedure(val)
-=begin
- if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
- #Tk_CMDTBL[$1]
- #TkCore::INTERP.tk_cmd_tbl[$1]
- TkCore::INTERP.tk_cmd_tbl[$1].cmd
-=end
- if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
- return TkCore::INTERP.tk_cmd_tbl[$4].cmd
- else
- #nil
- val
- end
- end
- private :bool, :number, :string, :num_or_str
- private :list, :simplelist, :window, :procedure
- module_function :bool, :number, :num_or_str, :string
- module_function :list, :simplelist, :window, :image_obj, :procedure
-
- def subst(str, *opts)
- # opts := :nobackslashes | :nocommands | novariables
- tk_call('subst',
- *(opts.collect{|opt|
- opt = opt.to_s
- (opt[0] == ?-)? opt: '-' << opt
- } << str))
- end
-
- def _toUTF8(str, encoding = nil)
- TkCore::INTERP._toUTF8(str, encoding)
- end
- def _fromUTF8(str, encoding = nil)
- TkCore::INTERP._fromUTF8(str, encoding)
- end
- private :_toUTF8, :_fromUTF8
- module_function :_toUTF8, :_fromUTF8
-
- def _callback_entry_class?(cls)
- cls <= Proc || cls <= Method || cls <= TkCallbackEntry
- end
- private :_callback_entry_class?
- module_function :_callback_entry_class?
-
- def _callback_entry?(obj)
- obj.kind_of?(Proc) || obj.kind_of?(Method) || obj.kind_of?(TkCallbackEntry)
- end
- private :_callback_entry?
- module_function :_callback_entry?
-
-=begin
- ### --> definition is moved to TkUtil module
- def _get_eval_string(str, enc_mode = nil)
- return nil if str == None
- if str.kind_of?(TkObject)
- str = str.path
- elsif str.kind_of?(String)
- str = _toUTF8(str) if enc_mode
- elsif str.kind_of?(Symbol)
- str = str.id2name
- str = _toUTF8(str) if enc_mode
- elsif str.kind_of?(Hash)
- str = hash_kv(str, enc_mode).join(" ")
- elsif str.kind_of?(Array)
- str = array2tk_list(str)
- str = _toUTF8(str) if enc_mode
- elsif str.kind_of?(Proc)
- str = install_cmd(str)
- elsif str == nil
- str = ""
- elsif str == false
- str = "0"
- elsif str == true
- str = "1"
- elsif (str.respond_to?(:to_eval))
- str = str.to_eval()
- str = _toUTF8(str) if enc_mode
- else
- str = str.to_s() || ''
- unless str.kind_of? String
- fail RuntimeError, "fail to convert the object to a string"
- end
- str = _toUTF8(str) if enc_mode
- end
- return str
- end
-=end
-=begin
- def _get_eval_string(obj, enc_mode = nil)
- case obj
- when Numeric
- obj.to_s
- when String
- (enc_mode)? _toUTF8(obj): obj
- when Symbol
- (enc_mode)? _toUTF8(obj.id2name): obj.id2name
- when TkObject
- obj.path
- when Hash
- hash_kv(obj, enc_mode).join(' ')
- when Array
- (enc_mode)? _toUTF8(array2tk_list(obj)): array2tk_list(obj)
- when Proc, Method, TkCallbackEntry
- install_cmd(obj)
- when false
- '0'
- when true
- '1'
- when nil
- ''
- when None
- nil
- else
- if (obj.respond_to?(:to_eval))
- (enc_mode)? _toUTF8(obj.to_eval): obj.to_eval
- else
- begin
- obj = obj.to_s || ''
- rescue
- fail RuntimeError, "fail to convert object '#{obj}' to string"
- end
- (enc_mode)? _toUTF8(obj): obj
- end
- end
- end
- private :_get_eval_string
- module_function :_get_eval_string
-=end
-
-=begin
- ### --> definition is moved to TkUtil module
- def _get_eval_enc_str(obj)
- return obj if obj == None
- _get_eval_string(obj, true)
- end
- private :_get_eval_enc_str
- module_function :_get_eval_enc_str
-=end
-
-=begin
- ### --> obsolete
- def ruby2tcl(v, enc_mode = nil)
- if v.kind_of?(Hash)
- v = hash_kv(v)
- v.flatten!
- v.collect{|e|ruby2tcl(e, enc_mode)}
- else
- _get_eval_string(v, enc_mode)
- end
- end
- private :ruby2tcl
-=end
-
-=begin
- ### --> definition is moved to TkUtil module
- def _conv_args(args, enc_mode, *src_args)
- conv_args = []
- src_args.each{|arg|
- conv_args << _get_eval_string(arg, enc_mode) unless arg == None
- # if arg.kind_of?(Hash)
- # arg.each{|k, v|
- # args << '-' + k.to_s
- # args << _get_eval_string(v, enc_mode)
- # }
- # elsif arg != None
- # args << _get_eval_string(arg, enc_mode)
- # end
- }
- args + conv_args
- end
- private :_conv_args
-=end
-
- def _curr_cmd_id
- #id = format("c%.4d", Tk_IDs[0])
- id = "c" + TkCore::INTERP._ip_id_ + TkComm::Tk_IDs[0]
- end
- def _next_cmd_id
- id = _curr_cmd_id
- #Tk_IDs[0] += 1
- TkComm::Tk_IDs[0].succ!
- id
- end
- private :_curr_cmd_id, :_next_cmd_id
- module_function :_curr_cmd_id, :_next_cmd_id
-
- def install_cmd(cmd)
- return '' if cmd == ''
- begin
- ns = TkCore::INTERP._invoke_without_enc('namespace', 'current')
- ns = nil if ns == '::' # for backward compatibility
- rescue
- # probably, Tcl7.6
- ns = nil
- end
- id = _next_cmd_id
- #Tk_CMDTBL[id] = cmd
- if cmd.kind_of?(TkCallbackEntry)
- TkCore::INTERP.tk_cmd_tbl[id] = cmd
- else
- TkCore::INTERP.tk_cmd_tbl[id] = TkCore::INTERP.get_cb_entry(cmd)
- end
- @cmdtbl = [] unless defined? @cmdtbl
- @cmdtbl.taint unless @cmdtbl.tainted?
- @cmdtbl.push id
- #return Kernel.format("rb_out %s", id);
- if ns
- 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << ns << ' ' << id
- else
- 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << id
- end
- end
- def uninstall_cmd(id)
- #id = $1 if /rb_out\S* (c(_\d+_)?\d+)/ =~ id
- id = $4 if id =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
- #Tk_CMDTBL.delete(id)
- TkCore::INTERP.tk_cmd_tbl.delete(id)
- end
- # private :install_cmd, :uninstall_cmd
- module_function :install_cmd, :uninstall_cmd
-
-=begin
- def install_win(ppath,name=nil)
- if !name or name == ''
- #name = format("w%.4d", Tk_IDs[1])
- #Tk_IDs[1] += 1
- name = "w" + Tk_IDs[1]
- Tk_IDs[1].succ!
- end
- if name[0] == ?.
- @path = name.dup
- elsif !ppath or ppath == "."
- @path = Kernel.format(".%s", name);
- else
- @path = Kernel.format("%s.%s", ppath, name)
- end
- #Tk_WINDOWS[@path] = self
- TkCore::INTERP.tk_windows[@path] = self
- end
-=end
- def install_win(ppath,name=nil)
- if name
- if name == ''
- raise ArgumentError, "invalid wiget-name '#{name}'"
- end
- if name[0] == ?.
- @path = '' + name
- @path.freeze
- return TkCore::INTERP.tk_windows[@path] = self
- end
- else
- name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
- Tk_IDs[1].succ!
- end
- if !ppath or ppath == '.'
- @path = '.' + name
- else
- @path = ppath + '.' + name
- end
- @path.freeze
- TkCore::INTERP.tk_windows[@path] = self
- end
-
- def uninstall_win()
- #Tk_WINDOWS.delete(@path)
- TkCore::INTERP.tk_windows.delete(@path)
- end
- private :install_win, :uninstall_win
-
- def _epath(win)
- if win.kind_of?(TkObject)
- win.epath
- elsif win.respond_to?(:epath)
- win.epath
- else
- win
- end
- end
- private :_epath
-end
-
-# define TkComm module (step 2: event binding)
-module TkComm
- include TkEvent
- extend TkEvent
-
- def tk_event_sequence(context)
- if context.kind_of? TkVirtualEvent
- context = context.path
- end
- if context.kind_of? Array
- context = context.collect{|ev|
- if ev.kind_of? TkVirtualEvent
- ev.path
- else
- ev
- end
- }.join("><")
- end
- if /,/ =~ context
- context = context.split(/\s*,\s*/).join("><")
- else
- context
- end
- end
-
- def _bind_core(mode, what, context, cmd, *args)
- id = install_bind(cmd, *args) if cmd
- begin
- tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>",
- mode + id]))
- rescue
- uninstall_cmd(id) if cmd
- fail
- end
- end
-
- def _bind(what, context, cmd, *args)
- _bind_core('', what, context, cmd, *args)
- end
-
- def _bind_append(what, context, cmd, *args)
- _bind_core('+', what, context, cmd, *args)
- end
-
- def _bind_remove(what, context)
- tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>", '']))
- end
-
- def _bindinfo(what, context=nil)
- if context
- tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]) .collect {|cmdline|
-=begin
- if cmdline =~ /^rb_out\S* (c(?:_\d+_)?\d+)\s+(.*)$/
- #[Tk_CMDTBL[$1], $2]
- [TkCore::INTERP.tk_cmd_tbl[$1], $2]
-=end
- if cmdline =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
- [TkCore::INTERP.tk_cmd_tbl[$4], $5]
- else
- cmdline
- end
- }
- else
- tk_split_simplelist(tk_call_without_enc(*what)).collect!{|seq|
- l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
- case (subseq)
- when /^<<[^<>]+>>$/
- TkVirtualEvent.getobj(subseq[1..-2])
- when /^<[^<>]+>$/
- subseq[1..-2]
- else
- subseq.split('')
- end
- }.flatten
- (l.size == 1) ? l[0] : l
- }
- end
- end
-
- def _bind_core_for_event_class(klass, mode, what, context, cmd, *args)
- id = install_bind_for_event_class(klass, cmd, *args) if cmd
- begin
- tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>",
- mode + id]))
- rescue
- uninstall_cmd(id) if cmd
- fail
- end
- end
-
- def _bind_for_event_class(klass, what, context, cmd, *args)
- _bind_core_for_event_class(klass, '', what, context, cmd, *args)
- end
-
- def _bind_append_for_event_class(klass, what, context, cmd, *args)
- _bind_core_for_event_class(klass, '+', what, context, cmd, *args)
- end
-
- def _bind_remove_for_event_class(klass, what, context)
- _bind_remove(what, context)
- end
-
- def _bindinfo_for_event_class(klass, what, context=nil)
- _bindinfo(what, context)
- end
-
- private :tk_event_sequence
- private :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo
- private :_bind_core_for_event_class, :_bind_for_event_class,
- :_bind_append_for_event_class, :_bind_remove_for_event_class,
- :_bindinfo_for_event_class
-
- #def bind(tagOrClass, context, cmd=Proc.new, *args)
- # _bind(["bind", tagOrClass], context, cmd, *args)
- # tagOrClass
- #end
- def bind(tagOrClass, context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind(["bind", tagOrClass], context, cmd, *args)
- tagOrClass
- end
-
- #def bind_append(tagOrClass, context, cmd=Proc.new, *args)
- # _bind_append(["bind", tagOrClass], context, cmd, *args)
- # tagOrClass
- #end
- def bind_append(tagOrClass, context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append(["bind", tagOrClass], context, cmd, *args)
- tagOrClass
- end
-
- def bind_remove(tagOrClass, context)
- _bind_remove(['bind', tagOrClass], context)
- tagOrClass
- end
-
- def bindinfo(tagOrClass, context=nil)
- _bindinfo(['bind', tagOrClass], context)
- end
-
- #def bind_all(context, cmd=Proc.new, *args)
- # _bind(['bind', 'all'], context, cmd, *args)
- # TkBindTag::ALL
- #end
- def bind_all(context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind(['bind', 'all'], context, cmd, *args)
- TkBindTag::ALL
- end
-
- #def bind_append_all(context, cmd=Proc.new, *args)
- # _bind_append(['bind', 'all'], context, cmd, *args)
- # TkBindTag::ALL
- #end
- def bind_append_all(context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append(['bind', 'all'], context, cmd, *args)
- TkBindTag::ALL
- end
-
- def bind_remove_all(context)
- _bind_remove(['bind', 'all'], context)
- TkBindTag::ALL
- end
-
- def bindinfo_all(context=nil)
- _bindinfo(['bind', 'all'], context)
- end
-end
-
-
-module TkCore
- include TkComm
- extend TkComm
-
- unless self.const_defined? :INTERP
- if self.const_defined? :IP_NAME
- name = IP_NAME.to_s
- else
- #name = nil
- name = $0
- end
- if self.const_defined? :IP_OPTS
- if IP_OPTS.kind_of?(Hash)
- opts = hash_kv(IP_OPTS).join(' ')
- else
- opts = IP_OPTS.to_s
- end
- else
- opts = ''
- end
-
- INTERP = TclTkIp.new(name, opts)
-
- def INTERP.__getip
- self
- end
-
- INTERP.instance_eval{
- @tk_cmd_tbl = {}.taint
- def @tk_cmd_tbl.[]=(idx,val)
- if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default
- fail SecurityError,"cannot change the entried command"
- end
- super(idx,val)
- end
-
- @tk_windows = {}.taint
-
- @tk_table_list = [].taint
-
- @init_ip_env = [].taint # table of Procs
- @add_tk_procs = [].taint # table of [name, args, body]
-
- @cb_entry_class = Class.new(TkCallbackEntry){
- class << self
- def inspect
- sprintf("#<Class(TkCallbackEntry):%0x>", self.__id__)
- end
- alias to_s inspect
- end
-
- def initialize(ip, cmd)
- @ip = ip
- @cmd = cmd
- end
- attr_reader :ip, :cmd
- def call(*args)
- @ip.cb_eval(@cmd, *args)
- end
- def inspect
- sprintf("#<cb_entry:%0x>", self.__id__)
- end
- alias to_s inspect
- }.freeze
- }
-
- def INTERP.cb_entry_class
- @cb_entry_class
- end
- def INTERP.tk_cmd_tbl
- @tk_cmd_tbl
- end
- def INTERP.tk_windows
- @tk_windows
- end
-
- class Tk_OBJECT_TABLE
- def initialize(id)
- @id = id
- end
- def method_missing(m, *args, &b)
- TkCore::INTERP.tk_object_table(@id).__send__(m, *args, &b)
- end
- end
-
- def INTERP.tk_object_table(id)
- @tk_table_list[id]
- end
- def INTERP.create_table
- id = @tk_table_list.size
- (tbl = {}).tainted? || tbl.taint
- @tk_table_list << tbl
-# obj = Object.new
-# obj.instance_eval <<-EOD
-# def self.method_missing(m, *args)
-# TkCore::INTERP.tk_object_table(#{id}).send(m, *args)
-# end
-# EOD
-# return obj
- Tk_OBJECT_TABLE.new(id)
- end
-
- def INTERP.get_cb_entry(cmd)
- @cb_entry_class.new(__getip, cmd).freeze
- end
- def INTERP.cb_eval(cmd, *args)
- TkUtil._get_eval_string(TkUtil.eval_cmd(cmd, *args))
- end
-
- def INTERP.init_ip_env(script = Proc.new)
- @init_ip_env << script
- script.call(self)
- end
- def INTERP.add_tk_procs(name, args = nil, body = nil)
- if name.kind_of?(Array)
- name.each{|param| self.add_tk_procs(*param)}
- else
- name = name.to_s
- @add_tk_procs << [name, args, body]
- self._invoke('proc', name, args, body) if args && body
- end
- end
- def INTERP.remove_tk_procs(*names)
- names.each{|name|
- name = name.to_s
- @add_tk_procs.delete_if{|elem|
- elem.kind_of?(Array) && elem[0].to_s == name
- }
- self._invoke('rename', name, '')
- }
- end
- def INTERP.init_ip_internal
- ip = self
- @init_ip_env.each{|script| script.call(ip)}
- @add_tk_procs.each{|name,args,body| ip._invoke('proc',name,args,body)}
- end
- end
-
- WIDGET_DESTROY_HOOK = '<WIDGET_DESTROY_HOOK>'
- INTERP._invoke_without_enc('event', 'add',
- "<#{WIDGET_DESTROY_HOOK}>", '<Destroy>')
- INTERP._invoke_without_enc('bind', 'all', "<#{WIDGET_DESTROY_HOOK}>",
- install_cmd(proc{|path|
- unless TkCore::INTERP.deleted?
- begin
- if (widget=TkCore::INTERP.tk_windows[path])
- if widget.respond_to?(:__destroy_hook__)
- widget.__destroy_hook__
- end
- end
- rescue Exception=>e
- p e if $DEBUG
- end
- end
- }) << ' %W')
-
- INTERP.add_tk_procs(TclTkLib::FINALIZE_PROC_NAME, '',
- "bind all <#{WIDGET_DESTROY_HOOK}> {}")
-
- INTERP.add_tk_procs('rb_out', 'ns args', <<-'EOL')
- if [regexp {^::} $ns] {
- set cmd {namespace eval $ns {ruby_cmd TkCore callback} $args}
- } else {
- set cmd {eval {ruby_cmd TkCore callback} $ns $args}
- }
- if {[set st [catch $cmd ret]] != 0} {
- #return -code $st $ret
- set idx [string first "\n\n" $ret]
- if {$idx > 0} {
- return -code $st \
- -errorinfo [string range $ret [expr $idx + 2] \
- [string length $ret]] \
- [string range $ret 0 [expr $idx - 1]]
- } else {
- return -code $st $ret
- }
- } else {
- return $ret
- }
- EOL
-=begin
- INTERP.add_tk_procs('rb_out', 'args', <<-'EOL')
- if {[set st [catch {eval {ruby_cmd TkCore callback} $args} ret]] != 0} {
- #return -code $st $ret
- set idx [string first "\n\n" $ret]
- if {$idx > 0} {
- return -code $st \
- -errorinfo [string range $ret [expr $idx + 2] \
- [string length $ret]] \
- [string range $ret 0 [expr $idx - 1]]
- } else {
- return -code $st $ret
- }
- } else {
- return $ret
- }
- EOL
-=end
-=begin
- INTERP.add_tk_procs('rb_out', 'args', <<-'EOL')
- #regsub -all {\\} $args {\\\\} args
- #regsub -all {!} $args {\\!} args
- #regsub -all "{" $args "\\{" args
- regsub -all {(\\|!|\{|\})} $args {\\\1} args
- if {[set st [catch {ruby [format "TkCore.callback %%Q!%s!" $args]} ret]] != 0} {
- #return -code $st $ret
- set idx [string first "\n\n" $ret]
- if {$idx > 0} {
- return -code $st \
- -errorinfo [string range $ret [expr $idx + 2] \
- [string length $ret]] \
- [string range $ret 0 [expr $idx - 1]]
- } else {
- return -code $st $ret
- }
- } else {
- return $ret
- }
- EOL
-=end
-
- at_exit{ INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME) }
-
- EventFlag = TclTkLib::EventFlag
-
- def callback_break
- fail TkCallbackBreak, "Tk callback returns 'break' status"
- end
-
- def callback_continue
- fail TkCallbackContinue, "Tk callback returns 'continue' status"
- end
-
- def callback_return
- fail TkCallbackReturn, "Tk callback returns 'return' status"
- end
-
- def TkCore.callback(*arg)
- begin
- if TkCore::INTERP.tk_cmd_tbl.kind_of?(Hash)
- #TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
- normal_ret = false
- ret = catch(:IRB_EXIT) do # IRB hack
- retval = TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
- normal_ret = true
- retval
- end
- unless normal_ret
- # catch IRB_EXIT
- exit(ret)
- end
- ret
- end
- rescue SystemExit=>e
- exit(e.status)
- rescue Interrupt=>e
- fail(e)
- rescue Exception => e
- begin
- msg = _toUTF8(e.class.inspect) + ': ' +
- _toUTF8(e.message) + "\n" +
- "\n---< backtrace of Ruby side >-----\n" +
- _toUTF8(e.backtrace.join("\n")) +
- "\n---< backtrace of Tk side >-------"
- msg.instance_variable_set(:@encoding, 'utf-8')
- rescue Exception
- msg = e.class.inspect + ': ' + e.message + "\n" +
- "\n---< backtrace of Ruby side >-----\n" +
- e.backtrace.join("\n") +
- "\n---< backtrace of Tk side >-------"
- end
- # TkCore::INTERP._set_global_var('errorInfo', msg)
- # fail(e)
- fail(e, msg)
- end
- end
-=begin
- def TkCore.callback(arg_str)
- # arg = tk_split_list(arg_str)
- arg = tk_split_simplelist(arg_str)
- #_get_eval_string(TkUtil.eval_cmd(Tk_CMDTBL[arg.shift], *arg))
- #_get_eval_string(TkUtil.eval_cmd(TkCore::INTERP.tk_cmd_tbl[arg.shift],
- # *arg))
- # TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
- begin
- TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
- rescue Exception => e
- raise(e, e.class.inspect + ': ' + e.message + "\n" +
- "\n---< backtrace of Ruby side >-----\n" +
- e.backtrace.join("\n") +
- "\n---< backtrace of Tk side >-------")
- end
-#=begin
-# cb_obj = TkCore::INTERP.tk_cmd_tbl[arg.shift]
-# unless $DEBUG
-# cb_obj.call(*arg)
-# else
-# begin
-# raise 'check backtrace'
-# rescue
-# # ignore backtrace before 'callback'
-# pos = -($!.backtrace.size)
-# end
-# begin
-# cb_obj.call(*arg)
-# rescue
-# trace = $!.backtrace
-# raise $!, "\n#{trace[0]}: #{$!.message} (#{$!.class})\n" +
-# "\tfrom #{trace[1..pos].join("\n\tfrom ")}"
-# end
-# end
-#=end
- end
-=end
-
- def load_cmd_on_ip(tk_cmd)
- bool(tk_call('auto_load', tk_cmd))
- end
-
- def after(ms, cmd=Proc.new)
- crit_bup = Thread.critical
- Thread.critical = true
-
- myid = _curr_cmd_id
- cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret})
-
- Thread.critical = crit_bup
-
- tk_call_without_enc("after",ms,cmdid) # return id
-# return
-# if false #defined? Thread
-# Thread.start do
-# ms = Float(ms)/1000
-# ms = 10 if ms == 0
-# sleep ms/1000
-# cmd.call
-# end
-# else
-# cmdid = install_cmd(cmd)
-# tk_call("after",ms,cmdid)
-# end
- end
-
- def after_idle(cmd=Proc.new)
- crit_bup = Thread.critical
- Thread.critical = true
-
- myid = _curr_cmd_id
- cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret})
-
- Thread.critical = crit_bup
-
- tk_call_without_enc('after','idle',cmdid)
- end
-
- def after_cancel(afterId)
- tk_call_without_enc('after','cancel',afterId)
- end
-
- def windowingsystem
- tk_call_without_enc('tk', 'windowingsystem')
- end
-
- def scaling(scale=nil)
- if scale
- tk_call_without_enc('tk', 'scaling', scale)
- else
- Float(number(tk_call_without_enc('tk', 'scaling')))
- end
- end
- def scaling_displayof(win, scale=nil)
- if scale
- tk_call_without_enc('tk', 'scaling', '-displayof', win, scale)
- else
- Float(number(tk_call_without_enc('tk', '-displayof', win, 'scaling')))
- end
- end
-
- def inactive
- Integer(tk_call_without_enc('tk', 'inactive'))
- end
- def inactive_displayof(win)
- Integer(tk_call_without_enc('tk', 'inactive', '-displayof', win))
- end
- def reset_inactive
- tk_call_without_enc('tk', 'inactive', 'reset')
- end
- def reset_inactive_displayof(win)
- tk_call_without_enc('tk', 'inactive', '-displayof', win, 'reset')
- end
-
- def appname(name=None)
- tk_call('tk', 'appname', name)
- end
-
- def appsend_deny
- tk_call('rename', 'send', '')
- end
-
- def appsend(interp, async, *args)
- if $SAFE >= 4
- fail SecurityError, "cannot send Tk commands at level 4"
- elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
- fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}"
- end
- if async != true && async != false && async != nil
- args.unshift(async)
- async = false
- end
- if async
- tk_call('send', '-async', '--', interp, *args)
- else
- tk_call('send', '--', interp, *args)
- end
- end
-
- def rb_appsend(interp, async, *args)
- if $SAFE >= 4
- fail SecurityError, "cannot send Ruby commands at level 4"
- elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
- fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}"
- end
- if async != true && async != false && async != nil
- args.unshift(async)
- async = false
- end
- #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')}
- args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')}
- # args.push(').to_s"')
- # appsend(interp, async, 'ruby "(', *args)
- args.push('}.call)"')
- appsend(interp, async, 'ruby "TkComm._get_eval_string(proc{', *args)
- end
-
- def appsend_displayof(interp, win, async, *args)
- if $SAFE >= 4
- fail SecurityError, "cannot send Tk commands at level 4"
- elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
- fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}"
- end
- win = '.' if win == nil
- if async != true && async != false && async != nil
- args.unshift(async)
- async = false
- end
- if async
- tk_call('send', '-async', '-displayof', win, '--', interp, *args)
- else
- tk_call('send', '-displayor', win, '--', interp, *args)
- end
- end
-
- def rb_appsend_displayof(interp, win, async, *args)
- if $SAFE >= 4
- fail SecurityError, "cannot send Ruby commands at level 4"
- elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
- fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}"
- end
- win = '.' if win == nil
- if async != true && async != false && async != nil
- args.unshift(async)
- async = false
- end
- #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')}
- args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')}
- # args.push(').to_s"')
- # appsend_displayof(interp, win, async, 'ruby "(', *args)
- args.push('}.call)"')
- appsend(interp, win, async, 'ruby "TkComm._get_eval_string(proc{', *args)
- end
-
- def info(*args)
- tk_call('info', *args)
- end
-
- def mainloop(check_root = true)
- TclTkLib.mainloop(check_root)
- end
-
- def mainloop_thread?
- # true : current thread is mainloop
- # nil : there is no mainloop
- # false : mainloop is running on the other thread
- # ( At then, it is dangerous to call Tk interpreter directly. )
- TclTkLib.mainloop_thread?
- end
-
- def mainloop_exist?
- TclTkLib.mainloop_thread? != nil
- end
-
- def is_mainloop?
- TclTkLib.mainloop_thread? == true
- end
-
- def mainloop_watchdog(check_root = true)
- # watchdog restarts mainloop when mainloop is dead
- TclTkLib.mainloop_watchdog(check_root)
- end
-
- def do_one_event(flag = TclTkLib::EventFlag::ALL)
- TclTkLib.do_one_event(flag)
- end
-
- def set_eventloop_tick(timer_tick)
- TclTkLib.set_eventloop_tick(timer_tick)
- end
-
- def get_eventloop_tick()
- TclTkLib.get_eventloop_tick
- end
-
- def set_no_event_wait(wait)
- TclTkLib.set_no_even_wait(wait)
- end
-
- def get_no_event_wait()
- TclTkLib.get_no_eventloop_wait
- end
-
- def set_eventloop_weight(loop_max, no_event_tick)
- TclTkLib.set_eventloop_weight(loop_max, no_event_tick)
- end
-
- def get_eventloop_weight()
- TclTkLib.get_eventloop_weight
- end
-
- def restart(app_name = nil, keys = {})
- TkCore::INTERP.init_ip_internal
-
- tk_call('set', 'argv0', app_name) if app_name
- if keys.kind_of?(Hash)
- # tk_call('set', 'argc', keys.size * 2)
- tk_call('set', 'argv', hash_kv(keys).join(' '))
- end
-
- INTERP.restart
- nil
- end
-
- def event_generate(win, context, keys=nil)
- #win = win.path if win.kind_of?(TkObject)
- if context.kind_of?(TkEvent::Event)
- context.generate(win, ((keys)? keys: {}))
- elsif keys
- tk_call_without_enc('event', 'generate', win,
- "<#{tk_event_sequence(context)}>",
- *hash_kv(keys, true))
- else
- tk_call_without_enc('event', 'generate', win,
- "<#{tk_event_sequence(context)}>")
- end
- nil
- end
-
- def messageBox(keys)
- tk_call('tk_messageBox', *hash_kv(keys))
- end
-
- def getOpenFile(keys = nil)
- tk_call('tk_getOpenFile', *hash_kv(keys))
- end
- def getMultipleOpenFile(keys = nil)
- simplelist(tk_call('tk_getOpenFile', '-multiple', '1', *hash_kv(keys)))
- end
-
- def getSaveFile(keys = nil)
- tk_call('tk_getSaveFile', *hash_kv(keys))
- end
- def getMultipleSaveFile(keys = nil)
- simplelist(tk_call('tk_getSaveFile', '-multiple', '1', *hash_kv(keys)))
- end
-
- def chooseColor(keys = nil)
- tk_call('tk_chooseColor', *hash_kv(keys))
- end
-
- def chooseDirectory(keys = nil)
- tk_call('tk_chooseDirectory', *hash_kv(keys))
- end
-
- def _ip_eval_core(enc_mode, cmd_string)
- case enc_mode
- when nil
- res = INTERP._eval(cmd_string)
- when false
- res = INTERP._eval_without_enc(cmd_string)
- when true
- res = INTERP._eval_with_enc(cmd_string)
- end
- if INTERP._return_value() != 0
- fail RuntimeError, res, error_at
- end
- return res
- end
- private :_ip_eval_core
-
- def ip_eval(cmd_string)
- _ip_eval_core(nil, cmd_string)
- end
-
- def ip_eval_without_enc(cmd_string)
- _ip_eval_core(false, cmd_string)
- end
-
- def ip_eval_with_enc(cmd_string)
- _ip_eval_core(true, cmd_string)
- end
-
- def _ip_invoke_core(enc_mode, *args)
- case enc_mode
- when false
- res = INTERP._invoke_without_enc(*args)
- when nil
- res = INTERP._invoke(*args)
- when true
- res = INTERP._invoke_with_enc(*args)
- end
- if INTERP._return_value() != 0
- fail RuntimeError, res, error_at
- end
- return res
- end
- private :_ip_invoke_core
-
- def ip_invoke(*args)
- _ip_invoke_core(nil, *args)
- end
-
- def ip_invoke_without_enc(*args)
- _ip_invoke_core(false, *args)
- end
-
- def ip_invoke_with_enc(*args)
- _ip_invoke_core(true, *args)
- end
-
- def _tk_call_core(enc_mode, *args)
- ### puts args.inspect if $DEBUG
- #args.collect! {|x|ruby2tcl(x, enc_mode)}
- #args.compact!
- #args.flatten!
- args = _conv_args([], enc_mode, *args)
- puts 'invoke args => ' + args.inspect if $DEBUG
- ### print "=> ", args.join(" ").inspect, "\n" if $DEBUG
- begin
- # res = INTERP._invoke(*args).taint
- # res = INTERP._invoke(enc_mode, *args)
- res = _ip_invoke_core(enc_mode, *args)
- # >>>>> _invoke returns a TAINTED string <<<<<
- rescue NameError => err
- # err = $!
- begin
- args.unshift "unknown"
- #res = INTERP._invoke(*args).taint
- #res = INTERP._invoke(enc_mode, *args)
- res = _ip_invoke_core(enc_mode, *args)
- # >>>>> _invoke returns a TAINTED string <<<<<
- rescue StandardError => err2
- fail err2 unless /^invalid command/ =~ err2.message
- fail err
- end
- end
- if INTERP._return_value() != 0
- fail RuntimeError, res, error_at
- end
- ### print "==> ", res.inspect, "\n" if $DEBUG
- return res
- end
- private :_tk_call_core
-
- def tk_call(*args)
- _tk_call_core(nil, *args)
- end
-
- def tk_call_without_enc(*args)
- _tk_call_core(false, *args)
- end
-
- def tk_call_with_enc(*args)
- _tk_call_core(true, *args)
- end
-
- def _tk_call_to_list_core(depth, arg_enc, val_enc, *args)
- args = _conv_args([], arg_enc, *args)
- val = _tk_call_core(false, *args)
- if !depth.kind_of?(Integer) || depth == 0
- tk_split_simplelist(val, false, val_enc)
- else
- tk_split_list(val, depth, false, val_enc)
- end
- end
- #private :_tk_call_to_list_core
-
- def tk_call_to_list(*args)
- _tk_call_to_list_core(-1, nil, true, *args)
- end
-
- def tk_call_to_list_without_enc(*args)
- _tk_call_to_list_core(-1, false, false, *args)
- end
-
- def tk_call_to_list_with_enc(*args)
- _tk_call_to_list_core(-1, true, true, *args)
- end
-
- def tk_call_to_simplelist(*args)
- _tk_call_to_list_core(0, nil, true, *args)
- end
-
- def tk_call_to_simplelist_without_enc(*args)
- _tk_call_to_list_core(0, false, false, *args)
- end
-
- def tk_call_to_simplelist_with_enc(*args)
- _tk_call_to_list_core(0, true, true, *args)
- end
-end
-
-
-module Tk
- include TkCore
- extend Tk
-
- TCL_VERSION = INTERP._invoke_without_enc("info", "tclversion").freeze
- TCL_PATCHLEVEL = INTERP._invoke_without_enc("info", "patchlevel").freeze
-
- major, minor = TCL_VERSION.split('.')
- TCL_MAJOR_VERSION = major.to_i
- TCL_MINOR_VERSION = minor.to_i
-
- TK_VERSION = INTERP._invoke_without_enc("set", "tk_version").freeze
- TK_PATCHLEVEL = INTERP._invoke_without_enc("set", "tk_patchLevel").freeze
-
- major, minor = TK_VERSION.split('.')
- TK_MAJOR_VERSION = major.to_i
- TK_MINOR_VERSION = minor.to_i
-
- JAPANIZED_TK = (INTERP._invoke_without_enc("info", "commands",
- "kanji") != "").freeze
-
- def Tk.const_missing(sym)
- case(sym)
- when :TCL_LIBRARY
- INTERP._invoke_without_enc('global', 'tcl_library')
- INTERP._invoke("set", "tcl_library").freeze
-
- when :TK_LIBRARY
- INTERP._invoke_without_enc('global', 'tk_library')
- INTERP._invoke("set", "tk_library").freeze
-
- when :LIBRARY
- INTERP._invoke("info", "library").freeze
-
- #when :PKG_PATH, :PACKAGE_PATH, :TCL_PACKAGE_PATH
- # INTERP._invoke_without_enc('global', 'tcl_pkgPath')
- # tk_split_simplelist(INTERP._invoke('set', 'tcl_pkgPath'))
-
- #when :LIB_PATH, :LIBRARY_PATH, :TCL_LIBRARY_PATH
- # INTERP._invoke_without_enc('global', 'tcl_libPath')
- # tk_split_simplelist(INTERP._invoke('set', 'tcl_libPath'))
-
- when :PLATFORM, :TCL_PLATFORM
- if $SAFE >= 4
- fail SecurityError, "can't get #{sym} when $SAFE >= 4"
- end
- INTERP._invoke_without_enc('global', 'tcl_platform')
- Hash[*tk_split_simplelist(INTERP._invoke_without_enc('array', 'get',
- 'tcl_platform'))]
-
- when :ENV
- INTERP._invoke_without_enc('global', 'env')
- Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'env'))]
-
- #when :AUTO_PATH #<===
- # tk_split_simplelist(INTERP._invoke('set', 'auto_path'))
-
- #when :AUTO_OLDPATH
- # tk_split_simplelist(INTERP._invoke('set', 'auto_oldpath'))
-
- when :AUTO_INDEX
- INTERP._invoke_without_enc('global', 'auto_index')
- Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'auto_index'))]
-
- when :PRIV, :PRIVATE, :TK_PRIV
- priv = {}
- if INTERP._invoke_without_enc('info', 'vars', 'tk::Priv') != ""
- var_nam = 'tk::Priv'
- else
- var_nam = 'tkPriv'
- end
- INTERP._invoke_without_enc('global', var_nam)
- Hash[*tk_split_simplelist(INTERP._invoke('array', 'get',
- var_nam))].each{|k,v|
- k.freeze
- case v
- when /^-?\d+$/
- priv[k] = v.to_i
- when /^-?\d+\.?\d*(e[-+]?\d+)?$/
- priv[k] = v.to_f
- else
- priv[k] = v.freeze
- end
- }
- priv
-
- else
- raise NameError, 'uninitialized constant Tk::' + sym.id2name
- end
- end
-
- def Tk.errorInfo
- INTERP._invoke_without_enc('global', 'errorInfo')
- INTERP._invoke_without_enc('set', 'errorInfo')
- end
-
- def Tk.errorCode
- INTERP._invoke_without_enc('global', 'errorCode')
- code = tk_split_simplelist(INTERP._invoke_without_enc('set', 'errorCode'))
- case code[0]
- when 'CHILDKILLED', 'CHILDSTATUS', 'CHILDSUSP'
- begin
- pid = Integer(code[1])
- code[1] = pid
- rescue
- end
- end
- code
- end
-
- def Tk.has_mainwindow?
- INTERP.has_mainwindow?
- end
-
- def root
- TkRoot.new
- end
-
- def Tk.load_tclscript(file, enc=nil)
- if enc
- # TCL_VERSION >= 8.5
- tk_call('source', '-encoding', enc, file)
- else
- tk_call('source', file)
- end
- end
-
- def Tk.load_tcllibrary(file, pkg_name=None, interp=None)
- tk_call('load', file, pkg_name, interp)
- end
-
- def Tk.unload_tcllibrary(*args)
- if args[-1].kind_of?(Hash)
- keys = _symbolkey2str(args.pop)
- nocomp = (keys['nocomplain'])? '-nocomplain': None
- keeplib = (keys['keeplibrary'])? '-keeplibrary': None
- tk_call('unload', nocomp, keeplib, '--', *args)
- else
- tk_call('unload', *args)
- end
- end
-
- def Tk.pkgconfig_list(mod)
- # Tk8.5 feature
- if mod.kind_of?(Module)
- if mod.respond_to?(:package_name)
- pkgname = mod.package_name
- elsif mod.const_defined?(:PACKAGE_NAME)
- pkgname = mod::PACKAGE_NAME
- else
- fail NotImplementedError, 'may not be a module for a Tcl extension'
- end
- else
- pkgname = mod.to_s
- end
-
- pkgname = '::' << pkgname unless pkgname =~ /^::/
-
- tk_split_list(tk_call(pkgname + '::pkgconfig', 'list'))
- end
-
- def Tk.pkgconfig_get(mod, key)
- # Tk8.5 feature
- if mod.kind_of?(Module)
- if mod.respond_to?(:package_name)
- pkgname = mod.package_name
- else
- fail NotImplementedError, 'may not be a module for a Tcl extension'
- end
- else
- pkgname = mod.to_s
- end
-
- pkgname = '::' << pkgname unless pkgname =~ /^::/
-
- tk_call(pkgname + '::pkgconfig', 'get', key)
- end
-
- def Tk.tcl_pkgconfig_list
- # Tk8.5 feature
- Tk.pkgconfig_list('::tcl')
- end
-
- def Tk.tcl_pkgconfig_get(key)
- # Tk8.5 feature
- Tk.pkgconfig_get('::tcl', key)
- end
-
- def Tk.tk_pkgconfig_list
- # Tk8.5 feature
- Tk.pkgconfig_list('::tk')
- end
-
- def Tk.tk_pkgconfig_get(key)
- # Tk8.5 feature
- Tk.pkgconfig_get('::tk', key)
- end
-
- def Tk.bell(nice = false)
- if nice
- tk_call_without_enc('bell', '-nice')
- else
- tk_call_without_enc('bell')
- end
- nil
- end
-
- def Tk.bell_on_display(win, nice = false)
- if nice
- tk_call_without_enc('bell', '-displayof', win, '-nice')
- else
- tk_call_without_enc('bell', '-displayof', win)
- end
- nil
- end
-
- def Tk.destroy(*wins)
- #tk_call_without_enc('destroy', *wins)
- tk_call_without_enc('destroy', *(wins.collect{|win|
- if win.kind_of?(TkWindow)
- win.epath
- else
- win
- end
- }))
- end
-
- def Tk.exit
- tk_call_without_enc('destroy', '.')
- end
-
- def Tk.pack(*args)
- TkPack.configure(*args)
- end
- def Tk.pack_forget(*args)
- TkPack.forget(*args)
- end
- def Tk.unpack(*args)
- TkPack.forget(*args)
- end
-
- def Tk.grid(*args)
- TkGrid.configure(*args)
- end
- def Tk.grid_forget(*args)
- TkGrid.forget(*args)
- end
- def Tk.ungrid(*args)
- TkGrid.forget(*args)
- end
-
- def Tk.place(*args)
- TkPlace.configure(*args)
- end
- def Tk.place_forget(*args)
- TkPlace.forget(*args)
- end
- def Tk.unplace(*args)
- TkPlace.forget(*args)
- end
-
- def Tk.update(idle=nil)
- if idle
- tk_call_without_enc('update', 'idletasks')
- else
- tk_call_without_enc('update')
- end
- end
- def Tk.update_idletasks
- update(true)
- end
- def update(idle=nil)
- # only for backward compatibility (This never be recommended to use)
- Tk.update(idle)
- self
- end
-
- # NOTE::
- # If no eventloop-thread is running, "thread_update" method is same
- # to "update" method. Else, "thread_update" method waits to complete
- # idletask operation on the eventloop-thread.
- def Tk.thread_update(idle=nil)
- if idle
- tk_call_without_enc('thread_update', 'idletasks')
- else
- tk_call_without_enc('thread_update')
- end
- end
- def Tk.thread_update_idletasks
- thread_update(true)
- end
-
- def Tk.lower_window(win, below=None)
- tk_call('lower', _epath(win), _epath(below))
- nil
- end
- def Tk.raise_window(win, above=None)
- tk_call('raise', _epath(win), _epath(above))
- nil
- end
-
- def Tk.current_grabs(win = nil)
- if win
- window(tk_call_without_enc('grab', 'current', win))
- else
- tk_split_list(tk_call_without_enc('grab', 'current'))
- end
- end
-
- def Tk.focus(display=nil)
- if display == nil
- window(tk_call_without_enc('focus'))
- else
- window(tk_call_without_enc('focus', '-displayof', display))
- end
- end
-
- def Tk.focus_to(win, force=false)
- if force
- tk_call_without_enc('focus', '-force', win)
- else
- tk_call_without_enc('focus', win)
- end
- end
-
- def Tk.focus_lastfor(win)
- window(tk_call_without_enc('focus', '-lastfor', win))
- end
-
- def Tk.focus_next(win)
- TkManageFocus.next(win)
- end
-
- def Tk.focus_prev(win)
- TkManageFocus.prev(win)
- end
-
- def Tk.strictMotif(mode=None)
- bool(tk_call_without_enc('set', 'tk_strictMotif', mode))
- end
-
- def Tk.show_kinsoku(mode='both')
- begin
- if /^8\.*/ === TK_VERSION && JAPANIZED_TK
- tk_split_simplelist(tk_call('kinsoku', 'show', mode))
- end
- rescue
- end
- end
- def Tk.add_kinsoku(chars, mode='both')
- begin
- if /^8\.*/ === TK_VERSION && JAPANIZED_TK
- tk_split_simplelist(tk_call('kinsoku', 'add', mode,
- *(chars.split(''))))
- else
- []
- end
- rescue
- []
- end
- end
- def Tk.delete_kinsoku(chars, mode='both')
- begin
- if /^8\.*/ === TK_VERSION && JAPANIZED_TK
- tk_split_simplelist(tk_call('kinsoku', 'delete', mode,
- *(chars.split(''))))
- end
- rescue
- end
- end
-
- def Tk.toUTF8(str, encoding = nil)
- _toUTF8(str, encoding)
- end
-
- def Tk.fromUTF8(str, encoding = nil)
- _fromUTF8(str, encoding)
- end
-end
-
-###########################################
-# string with Tcl's encoding
-###########################################
-module Tk
- def Tk.subst_utf_backslash(str)
- Tk::EncodedString.subst_utf_backslash(str)
- end
- def Tk.subst_tk_backslash(str)
- Tk::EncodedString.subst_tk_backslash(str)
- end
- def Tk.utf_to_backslash_sequence(str)
- Tk::EncodedString.utf_to_backslash_sequence(str)
- end
- def Tk.utf_to_backslash(str)
- Tk::EncodedString.utf_to_backslash_sequence(str)
- end
- def Tk.to_backslash_sequence(str)
- Tk::EncodedString.to_backslash_sequence(str)
- end
-end
-
-
-###########################################
-# convert kanji string to/from utf-8
-###########################################
-if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
- class TclTkIp
- # from tkencoding.rb by ttate@jaist.ac.jp
- attr_accessor :encoding
-
- alias __eval _eval
- alias __invoke _invoke
-
- alias __toUTF8 _toUTF8
- alias __fromUTF8 _fromUTF8
-
-=begin
- #### --> definition is moved to TclTkIp module
-
- def _toUTF8(str, encoding = nil)
- # decide encoding
- if encoding
- encoding = encoding.to_s
- elsif str.kind_of?(Tk::EncodedString) && str.encoding != nil
- encoding = str.encoding.to_s
- elsif str.instance_variable_get(:@encoding)
- encoding = str.instance_variable_get(:@encoding).to_s
- elsif defined?(@encoding) && @encoding != nil
- encoding = @encoding.to_s
- else
- encoding = __invoke('encoding', 'system')
- end
-
- # convert
- case encoding
- when 'utf-8', 'binary'
- str
- else
- __toUTF8(str, encoding)
- end
- end
-
- def _fromUTF8(str, encoding = nil)
- unless encoding
- if defined?(@encoding) && @encoding != nil
- encoding = @encoding.to_s
- else
- encoding = __invoke('encoding', 'system')
- end
- end
-
- if str.kind_of?(Tk::EncodedString)
- if str.encoding == 'binary'
- str
- else
- __fromUTF8(str, encoding)
- end
- elsif str.instance_variable_get(:@encoding).to_s == 'binary'
- str
- else
- __fromUTF8(str, encoding)
- end
- end
-=end
-
- def _eval(cmd)
- _fromUTF8(__eval(_toUTF8(cmd)))
- end
-
- def _invoke(*cmds)
- _fromUTF8(__invoke(*(cmds.collect{|cmd| _toUTF8(cmd)})))
- end
-
- alias _eval_with_enc _eval
- alias _invoke_with_enc _invoke
-
-=begin
- def _eval(cmd)
- if defined?(@encoding) && @encoding != 'utf-8'
- ret = if cmd.kind_of?(Tk::EncodedString)
- case cmd.encoding
- when 'utf-8', 'binary'
- __eval(cmd)
- else
- __eval(_toUTF8(cmd, cmd.encoding))
- end
- elsif cmd.instance_variable_get(:@encoding) == 'binary'
- __eval(cmd)
- else
- __eval(_toUTF8(cmd, @encoding))
- end
- if ret.kind_of?(String) && ret.instance_variable_get(:@encoding) == 'binary'
- ret
- else
- _fromUTF8(ret, @encoding)
- end
- else
- __eval(cmd)
- end
- end
-
- def _invoke(*cmds)
- if defined?(@encoding) && @encoding != 'utf-8'
- cmds = cmds.collect{|cmd|
- if cmd.kind_of?(Tk::EncodedString)
- case cmd.encoding
- when 'utf-8', 'binary'
- cmd
- else
- _toUTF8(cmd, cmd.encoding)
- end
- elsif cmd.instance_variable_get(:@encoding) == 'binary'
- cmd
- else
- _toUTF8(cmd, @encoding)
- end
- }
- ret = __invoke(*cmds)
- if ret.kind_of?(String) && ret.instance_variable_get(:@encoding) == 'binary'
- ret
- else
- _fromUTF8(ret, @encoding)
- end
- else
- __invoke(*cmds)
- end
- end
-=end
- end
-
- module TclTkLib
- class << self
- alias _encoding encoding
- alias _encoding= encoding=
- def encoding=(name)
- TkCore::INTERP.encoding = name
- end
- def encoding
- TkCore::INTERP.encoding
- end
- end
- end
-
- module Tk
- module Encoding
- extend Encoding
-
- TkCommandNames = ['encoding'.freeze].freeze
-
- def encoding=(name)
- TkCore::INTERP.encoding = name
- end
-
- def encoding
- TkCore::INTERP.encoding
- end
-
- def encoding_names
- TkComm.simplelist(Tk.tk_call('encoding', 'names'))
- end
-
- def encoding_system
- Tk.tk_call('encoding', 'system')
- end
-
- def encoding_system=(enc)
- Tk.tk_call('encoding', 'system', enc)
- end
-
- def encoding_convertfrom(str, enc=nil)
- # str is an usual enc string or a Tcl's internal string expression
- # in enc (which is returned from 'encoding_convertto' method).
- # the return value is a UTF-8 string.
- enc = encoding_system unless enc
- ret = TkCore::INTERP.__invoke('encoding', 'convertfrom', enc, str)
- ret.instance_variable_set('@encoding', 'utf-8')
- ret
- end
- alias encoding_convert_from encoding_convertfrom
-
- def encoding_convertto(str, enc=nil)
- # str must be a UTF-8 string.
- # The return value is a Tcl's internal string expression in enc.
- # To get an usual enc string, use Tk.fromUTF8(ret_val, enc).
- enc = encoding_system unless enc
- ret = TkCore::INTERP.__invoke('encoding', 'convertto', enc, str)
- ret.instance_variable_set('@encoding', 'binary')
- ret
- end
- alias encoding_convert_to encoding_convertto
-
- def encoding_dirs
- # Tcl8.5 feature
- TkComm.simplelist(Tk.tk_call_without_enc('encoding', 'dirs'))
- end
-
- def encoding_dirs=(dir_list) # an array or a Tcl's list string
- # Tcl8.5 feature
- Tk.tk_call_without_enc('encoding', 'dirs', dir_list)
- end
- end
-
- extend Encoding
- end
-
- # estimate encoding
- case $KCODE
- when /^e/i # EUC
- Tk.encoding = 'euc-jp'
- Tk.encoding_system = 'euc-jp'
- when /^s/i # SJIS
- begin
- if Tk.encoding_system == 'cp932'
- Tk.encoding = 'cp932'
- else
- Tk.encoding = 'shiftjis'
- Tk.encoding_system = 'shiftjis'
- end
- rescue StandardError, NameError
- Tk.encoding = 'shiftjis'
- Tk.encoding_system = 'shiftjis'
- end
- when /^u/i # UTF8
- Tk.encoding = 'utf-8'
- Tk.encoding_system = 'utf-8'
- else # NONE
- if defined? DEFAULT_TK_ENCODING
- Tk.encoding_system = DEFAULT_TK_ENCODING
- end
- begin
- Tk.encoding = Tk.encoding_system
- rescue StandardError, NameError
- Tk.encoding = 'utf-8'
- Tk.encoding_system = 'utf-8'
- end
- end
-
-else
- # dummy methods
- class TclTkIp
- attr_accessor :encoding
-
- alias __eval _eval
- alias __invoke _invoke
-
- alias _eval_with_enc _eval
- alias _invoke_with_enc _invoke
- end
-
- module Tk
- module Encoding
- extend Encoding
-
- def encoding=(name)
- nil
- end
- def encoding
- nil
- end
- def encoding_names
- nil
- end
- def encoding_system
- nil
- end
- def encoding_system=(enc)
- nil
- end
-
- def encoding_convertfrom(str, enc=None)
- str
- end
- alias encoding_convert_from encoding_convertfrom
-
- def encoding_convertto(str, enc=None)
- str
- end
- alias encoding_convert_to encoding_convertto
- def encoding_dirs
- nil
- end
- def encoding_dirs=(dir_array)
- nil
- end
- end
-
- extend Encoding
- end
-end
-
-
-module TkBindCore
- #def bind(context, cmd=Proc.new, *args)
- # Tk.bind(self, context, cmd, *args)
- #end
- def bind(context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- Tk.bind(self, context, cmd, *args)
- end
-
- #def bind_append(context, cmd=Proc.new, *args)
- # Tk.bind_append(self, context, cmd, *args)
- #end
- def bind_append(context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- Tk.bind_append(self, context, cmd, *args)
- end
-
- def bind_remove(context)
- Tk.bind_remove(self, context)
- end
-
- def bindinfo(context=nil)
- Tk.bindinfo(self, context)
- end
-end
-
-
-module TkTreatFont
- def __font_optkeys
- ['font']
- end
- private :__font_optkeys
-
- def __pathname
- self.path
- end
- private :__pathname
-
- ################################
-
- def font_configinfo(key = nil)
- optkeys = __font_optkeys
- if key && !optkeys.find{|opt| opt.to_s == key.to_s}
- fail ArgumentError, "unknown font option name `#{key}'"
- end
-
- win, tag = __pathname.split(':')
-
- if key
- pathname = [win, tag, key].join(';')
- TkFont.used_on(pathname) ||
- TkFont.init_widget_font(pathname, *__confinfo_cmd)
- elsif optkeys.size == 1
- pathname = [win, tag, optkeys[0]].join(';')
- TkFont.used_on(pathname) ||
- TkFont.init_widget_font(pathname, *__confinfo_cmd)
- else
- fonts = {}
- optkeys.each{|key|
- key = key.to_s
- pathname = [win, tag, key].join(';')
- fonts[key] =
- TkFont.used_on(pathname) ||
- TkFont.init_widget_font(pathname, *__confinfo_cmd)
- }
- fonts
- end
- end
- alias fontobj font_configinfo
-
- def font_configure(slot)
- pathname = __pathname
-
- slot = _symbolkey2str(slot)
-
- __font_optkeys.each{|optkey|
- optkey = optkey.to_s
- l_optkey = 'latin' << optkey
- a_optkey = 'ascii' << optkey
- k_optkey = 'kanji' << optkey
-
- if slot.key?(optkey)
- fnt = slot.delete(optkey)
- if fnt.kind_of?(TkFont)
- slot.delete(l_optkey)
- slot.delete(a_optkey)
- slot.delete(k_optkey)
-
- fnt.call_font_configure([pathname, optkey], *(__config_cmd << {}))
- next
- else
- if fnt
- if (slot.key?(l_optkey) ||
- slot.key?(a_optkey) ||
- slot.key?(k_optkey))
- fnt = TkFont.new(fnt)
-
- lfnt = slot.delete(l_optkey)
- lfnt = slot.delete(a_optkey) if slot.key?(a_optkey)
- kfnt = slot.delete(k_optkey)
-
- fnt.latin_replace(lfnt) if lfnt
- fnt.kanji_replace(kfnt) if kfnt
-
- fnt.call_font_configure([pathname, optkey],
- *(__config_cmd << {}))
- next
- else
- fnt = hash_kv(fnt) if fnt.kind_of?(Hash)
- tk_call(*(__config_cmd << "-#{optkey}" << fnt))
- end
- end
- next
- end
- end
-
- lfnt = slot.delete(l_optkey)
- lfnt = slot.delete(a_optkey) if slot.key?(a_optkey)
- kfnt = slot.delete(k_optkey)
-
- if lfnt && kfnt
- TkFont.new(lfnt, kfnt).call_font_configure([pathname, optkey],
- *(__config_cmd << {}))
- elsif lfnt
- latinfont_configure([lfnt, optkey])
- elsif kfnt
- kanjifont_configure([kfnt, optkey])
- end
- }
-
- # configure other (without font) options
- tk_call(*(__config_cmd.concat(hash_kv(slot)))) if slot != {}
- self
- end
-
- def latinfont_configure(ltn, keys=nil)
- if ltn.kind_of?(Array)
- key = ltn[1]
- ltn = ltn[0]
- else
- key = nil
- end
-
- optkeys = __font_optkeys
- if key && !optkeys.find{|opt| opt.to_s == key.to_s}
- fail ArgumentError, "unknown font option name `#{key}'"
- end
-
- win, tag = __pathname.split(':')
-
- optkeys = [key] if key
-
- optkeys.each{|optkey|
- optkey = optkey.to_s
-
- pathname = [win, tag, optkey].join(';')
-
- if (fobj = TkFont.used_on(pathname))
- fobj = TkFont.new(fobj) # create a new TkFont object
- elsif Tk::JAPANIZED_TK
- fobj = fontobj # create a new TkFont object
- else
- ltn = hash_kv(ltn) if ltn.kind_of?(Hash)
- tk_call(*(__config_cmd << "-#{optkey}" << ltn))
- next
- end
-
- if fobj.kind_of?(TkFont)
- if ltn.kind_of?(TkFont)
- conf = {}
- ltn.latin_configinfo.each{|key,val| conf[key] = val}
- if keys
- fobj.latin_configure(conf.update(keys))
- else
- fobj.latin_configure(conf)
- end
- else
- fobj.latin_replace(ltn)
- end
- end
-
- fobj.call_font_configure([pathname, optkey], *(__config_cmd << {}))
- }
- self
- end
- alias asciifont_configure latinfont_configure
-
- def kanjifont_configure(knj, keys=nil)
- if knj.kind_of?(Array)
- key = knj[1]
- knj = knj[0]
- else
- key = nil
- end
-
- optkeys = __font_optkeys
- if key && !optkeys.find{|opt| opt.to_s == key.to_s}
- fail ArgumentError, "unknown font option name `#{key}'"
- end
-
- win, tag = __pathname.split(':')
-
- optkeys = [key] if key
-
- optkeys.each{|optkey|
- optkey = optkey.to_s
-
- pathname = [win, tag, optkey].join(';')
-
- if (fobj = TkFont.used_on(pathname))
- fobj = TkFont.new(fobj) # create a new TkFont object
- elsif Tk::JAPANIZED_TK
- fobj = fontobj # create a new TkFont object
- else
- knj = hash_kv(knj) if knj.kind_of?(Hash)
- tk_call(*(__config_cmd << "-#{optkey}" << knj))
- next
- end
-
- if fobj.kind_of?(TkFont)
- if knj.kind_of?(TkFont)
- conf = {}
- knj.kanji_configinfo.each{|key,val| conf[key] = val}
- if keys
- fobj.kanji_configure(conf.update(keys))
- else
- fobj.kanji_configure(conf)
- end
- else
- fobj.kanji_replace(knj)
- end
- end
-
- fobj.call_font_configure([pathname, optkey], *(__config_cmd << {}))
- }
- self
- end
-
- def font_copy(win, wintag=nil, winkey=nil, targetkey=nil)
- if wintag
- if winkey
- fnt = win.tagfontobj(wintag, winkey).dup
- else
- fnt = win.tagfontobj(wintag).dup
- end
- else
- if winkey
- fnt = win.fontobj(winkey).dup
- else
- fnt = win.fontobj.dup
- end
- end
-
- if targetkey
- fnt.call_font_configure([__pathname, targetkey], *(__config_cmd << {}))
- else
- fnt.call_font_configure(__pathname, *(__config_cmd << {}))
- end
- self
- end
-
- def latinfont_copy(win, wintag=nil, winkey=nil, targetkey=nil)
- if targetkey
- fontobj(targetkey).dup.call_font_configure([__pathname, targetkey],
- *(__config_cmd << {}))
- else
- fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {}))
- end
-
- if wintag
- if winkey
- fontobj.latin_replace(win.tagfontobj(wintag, winkey).latin_font_id)
- else
- fontobj.latin_replace(win.tagfontobj(wintag).latin_font_id)
- end
- else
- if winkey
- fontobj.latin_replace(win.fontobj(winkey).latin_font_id)
- else
- fontobj.latin_replace(win.fontobj.latin_font_id)
- end
- end
- self
- end
- alias asciifont_copy latinfont_copy
-
- def kanjifont_copy(win, wintag=nil, winkey=nil, targetkey=nil)
- if targetkey
- fontobj(targetkey).dup.call_font_configure([__pathname, targetkey],
- *(__config_cmd << {}))
- else
- fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {}))
- end
-
- if wintag
- if winkey
- fontobj.kanji_replace(win.tagfontobj(wintag, winkey).kanji_font_id)
- else
- fontobj.kanji_replace(win.tagfontobj(wintag).kanji_font_id)
- end
- else
- if winkey
- fontobj.kanji_replace(win.fontobj(winkey).kanji_font_id)
- else
- fontobj.kanji_replace(win.fontobj.kanji_font_id)
- end
- end
- self
- end
-end
-
-
-module TkConfigMethod
- include TkUtil
- include TkTreatFont
-
- def __cget_cmd
- [self.path, 'cget']
- end
- private :__cget_cmd
-
- def __config_cmd
- [self.path, 'configure']
- end
- private :__config_cmd
-
- def __confinfo_cmd
- __config_cmd
- end
- private :__config_cmd
-
- def __configinfo_struct
- {:key=>0, :alias=>1, :db_name=>1, :db_class=>2,
- :default_value=>3, :current_value=>4}
- end
- private :__configinfo_struct
-
- def __numval_optkeys
- []
- end
- private :__numval_optkeys
-
- def __numstrval_optkeys
- []
- end
- private :__numstrval_optkeys
-
- def __boolval_optkeys
- ['exportselection', 'jump', 'setgrid', 'takefocus']
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- [
- 'text', 'label', 'show', 'data', 'file',
- 'activebackground', 'activeforeground', 'background',
- 'disabledforeground', 'disabledbackground', 'foreground',
- 'highlightbackground', 'highlightcolor', 'insertbackground',
- 'selectbackground', 'selectforeground', 'troughcolor'
- ]
- end
- private :__strval_optkeys
-
- def __listval_optkeys
- []
- end
- private :__listval_optkeys
-
- def __numlistval_optkeys
- []
- end
- private :__numlistval_optkeys
-
- def __tkvariable_optkeys
- ['variable', 'textvariable']
- end
- private :__tkvariable_optkeys
-
- def __val2ruby_optkeys # { key=>proc, ... }
- # The method is used to convert a opt-value to a ruby's object.
- # When get the value of the option "key", "proc.call(value)" is called.
- {}
- end
- private :__val2ruby_optkeys
-
- def __ruby2val_optkeys # { key=>proc, ... }
- # The method is used to convert a ruby's object to a opt-value.
- # When set the value of the option "key", "proc.call(value)" is called.
- # That is, "-#{key} #{proc.call(value)}".
- {}
- end
- private :__ruby2val_optkeys
-
- def __methodcall_optkeys # { key=>method, ... }
- # The method is used to both of get and set.
- # Usually, the 'key' will not be a widget option.
- {}
- end
- private :__methodcall_optkeys
-
- def __keyonly_optkeys # { def_key=>undef_key or nil, ... }
- {}
- end
- private :__keyonly_optkeys
-
- def __conv_keyonly_opts(keys)
- return keys unless keys.kind_of?(Hash)
- keyonly = __keyonly_optkeys
- keys2 = {}
- keys.each{|k, v|
- optkey = keyonly.find{|kk,vv| kk.to_s == k.to_s}
- if optkey
- defkey, undefkey = optkey
- if v
- keys2[defkey.to_s] = None
- elsif undefkey
- keys2[undefkey.to_s] = None
- else
- # remove key
- end
- else
- keys2[k.to_s] = v
- end
- }
- keys2
- end
-
- def config_hash_kv(keys, enc_mode = nil, conf = nil)
- hash_kv(__conv_keyonly_opts(keys), enc_mode, conf)
- end
-
- ################################
-
- def [](id)
- cget(id)
- end
-
- def []=(id, val)
- configure(id, val)
- val
- end
-
- def cget(slot)
- orig_slot = slot
- slot = slot.to_s
-
- if slot.length == 0
- fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
- end
-
- if ( method = _symbolkey2str(__val2ruby_optkeys())[slot] )
- optval = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
- begin
- return method.call(optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
- return optval
- end
- end
-
- if ( method = _symbolkey2str(__methodcall_optkeys)[slot] )
- return self.__send__(method)
- end
-
- case slot
- when /^(#{__numval_optkeys.join('|')})$/
- begin
- number(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
- rescue
- nil
- end
-
- when /^(#{__numstrval_optkeys.join('|')})$/
- num_or_str(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
-
- when /^(#{__boolval_optkeys.join('|')})$/
- begin
- bool(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
- rescue
- nil
- end
-
- when /^(#{__listval_optkeys.join('|')})$/
- simplelist(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
-
- when /^(#{__numlistval_optkeys.join('|')})$/
- conf = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
- if conf =~ /^[0-9+-]/
- list(conf)
- else
- conf
- end
-
- when /^(#{__strval_optkeys.join('|')})$/
- _fromUTF8(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
-
- when /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/
- fontcode = $1
- fontkey = $2
- fnt = tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{fontkey}")), true)
- unless fnt.kind_of?(TkFont)
- fnt = fontobj(fontkey)
- end
- if fontcode == 'kanji' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
-
- when /^(#{__tkvariable_optkeys.join('|')})$/
- v = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
- (v.empty?)? nil: TkVarAccess.new(v)
-
- else
- tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{slot}")), true)
- end
- end
-
- def configure(slot, value=None)
- if slot.kind_of? Hash
- slot = _symbolkey2str(slot)
-
- __methodcall_optkeys.each{|key, method|
- value = slot.delete(key.to_s)
- self.__send__(method, value) if value
- }
-
- __ruby2val_optkeys.each{|key, method|
- key = key.to_s
- slot[key] = method.call(slot[key]) if slot.has_key?(key)
- }
-
- __keyonly_optkeys.each{|defkey, undefkey|
- conf = slot.find{|kk, vv| kk == defkey.to_s}
- if conf
- k, v = conf
- if v
- slot[k] = None
- else
- slot[undefkey.to_s] = None if undefkey
- slot.delete(k)
- end
- end
- }
-
- if (slot.find{|k, v| k =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/})
- font_configure(slot)
- elsif slot.size > 0
- tk_call(*(__config_cmd.concat(hash_kv(slot))))
- end
-
- else
- orig_slot = slot
- slot = slot.to_s
- if slot.length == 0
- fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
- end
-
- if ( conf = __keyonly_optkeys.find{|k, v| k.to_s == slot} )
- defkey, undefkey = conf
- if value
- tk_call(*(__config_cmd << "-#{defkey}"))
- elsif undefkey
- tk_call(*(__config_cmd << "-#{undefkey}"))
- end
- elsif ( method = _symbolkey2str(__ruby2val_optkeys)[slot] )
- tk_call(*(__config_cmd << "-#{slot}" << method.call(value)))
- elsif ( method = _symbolkey2str(__methodcall_optkeys)[slot] )
- self.__send__(method, value)
- elsif (slot =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
- if value == None
- fontobj($2)
- else
- font_configure({slot=>value})
- end
- else
- tk_call(*(__config_cmd << "-#{slot}" << value))
- end
- end
- self
- end
-
- def configure_cmd(slot, value)
- configure(slot, install_cmd(value))
- end
-
- def configinfo(slot = nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if (slot &&
- slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
- fontkey = $2
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")), false, true)
- conf[__configinfo_struct[:key]] =
- conf[__configinfo_struct[:key]][1..-1]
- if ( ! __configinfo_struct[:alias] \
- || conf.size > __configinfo_struct[:alias] + 1 )
- conf[__configinfo_struct[:current_value]] = fontobj(fontkey)
- elsif ( __configinfo_struct[:alias] \
- && conf.size == __configinfo_struct[:alias] + 1 \
- && conf[__configinfo_struct[:alias]][0] == ?- )
- conf[__configinfo_struct[:alias]] =
- conf[__configinfo_struct[:alias]][1..-1]
- end
- conf
- else
- if slot
- slot = slot.to_s
- case slot
- when /^(#{__val2ruby_optkeys().keys.join('|')})$/
- method = _symbolkey2str(__val2ruby_optkeys())[slot]
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd() << "-#{slot}")), false, true)
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- optval = conf[__configinfo_struct[:default_value]]
- begin
- val = method.call(optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__configinfo_struct[:default_value]] = val
- end
- if ( conf[__configinfo_struct[:current_value]] )
- optval = conf[__configinfo_struct[:current_value]]
- begin
- val = method.call(optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__configinfo_struct[:current_value]] = val
- end
-
- when /^(#{__methodcall_optkeys.keys.join('|')})$/
- method = _symbolkey2str(__methodcall_optkeys)[slot]
- return [slot, '', '', '', self.__send__(method)]
-
- when /^(#{__numval_optkeys.join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]])
- begin
- conf[__configinfo_struct[:default_value]] =
- number(conf[__configinfo_struct[:default_value]])
- rescue
- conf[__configinfo_struct[:default_value]] = nil
- end
- end
- if ( conf[__configinfo_struct[:current_value]] )
- begin
- conf[__configinfo_struct[:current_value]] =
- number(conf[__configinfo_struct[:current_value]])
- rescue
- conf[__configinfo_struct[:current_value]] = nil
- end
- end
-
- when /^(#{__numstrval_optkeys.join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]])
- conf[__configinfo_struct[:default_value]] =
- num_or_str(conf[__configinfo_struct[:default_value]])
- end
- if ( conf[__configinfo_struct[:current_value]] )
- conf[__configinfo_struct[:current_value]] =
- num_or_str(conf[__configinfo_struct[:current_value]])
- end
-
- when /^(#{__boolval_optkeys.join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]])
- begin
- conf[__configinfo_struct[:default_value]] =
- bool(conf[__configinfo_struct[:default_value]])
- rescue
- conf[__configinfo_struct[:default_value]] = nil
- end
- end
- if ( conf[__configinfo_struct[:current_value]] )
- begin
- conf[__configinfo_struct[:current_value]] =
- bool(conf[__configinfo_struct[:current_value]])
- rescue
- conf[__configinfo_struct[:current_value]] = nil
- end
- end
-
- when /^(#{__listval_optkeys.join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]])
- conf[__configinfo_struct[:default_value]] =
- simplelist(conf[__configinfo_struct[:default_value]])
- end
- if ( conf[__configinfo_struct[:current_value]] )
- conf[__configinfo_struct[:current_value]] =
- simplelist(conf[__configinfo_struct[:current_value]])
- end
-
- when /^(#{__numlistval_optkeys.join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] \
- && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ )
- conf[__configinfo_struct[:default_value]] =
- list(conf[__configinfo_struct[:default_value]])
- end
- if ( conf[__configinfo_struct[:current_value]] \
- && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ )
- conf[__configinfo_struct[:current_value]] =
- list(conf[__configinfo_struct[:current_value]])
- end
-
- when /^(#{__strval_optkeys.join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- when /^(#{__tkvariable_optkeys.join('|')})$/
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]])
- v = conf[__configinfo_struct[:default_value]]
- if v.empty?
- conf[__configinfo_struct[:default_value]] = nil
- else
- conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v)
- end
- end
- if ( conf[__configinfo_struct[:current_value]] )
- v = conf[__configinfo_struct[:current_value]]
- if v.empty?
- conf[__configinfo_struct[:current_value]] = nil
- else
- conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v)
- end
- end
-
- else
- # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true)
- end
- conf[__configinfo_struct[:key]] =
- conf[__configinfo_struct[:key]][1..-1]
-
- if ( __configinfo_struct[:alias] \
- && conf.size == __configinfo_struct[:alias] + 1 \
- && conf[__configinfo_struct[:alias]][0] == ?- )
- conf[__configinfo_struct[:alias]] =
- conf[__configinfo_struct[:alias]][1..-1]
- end
-
- conf
-
- else
- # ret = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__confinfo_cmd))).collect{|conflist|
- # conf = tk_split_simplelist(conflist)
- ret = tk_split_simplelist(tk_call_without_enc(*__confinfo_cmd), false, false).collect{|conflist|
- conf = tk_split_simplelist(conflist, false, true)
- conf[__configinfo_struct[:key]] =
- conf[__configinfo_struct[:key]][1..-1]
-
- optkey = conf[__configinfo_struct[:key]]
- case optkey
- when /^(#{__val2ruby_optkeys().keys.join('|')})$/
- method = _symbolkey2str(__val2ruby_optkeys())[optkey]
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- optval = conf[__configinfo_struct[:default_value]]
- begin
- val = method.call(optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__configinfo_struct[:default_value]] = val
- end
- if ( conf[__configinfo_struct[:current_value]] )
- optval = conf[__configinfo_struct[:current_value]]
- begin
- val = method.call(optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__configinfo_struct[:current_value]] = val
- end
-
- when /^(#{__strval_optkeys.join('|')})$/
- # do nothing
-
- when /^(#{__numval_optkeys.join('|')})$/
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- begin
- conf[__configinfo_struct[:default_value]] =
- number(conf[__configinfo_struct[:default_value]])
- rescue
- conf[__configinfo_struct[:default_value]] = nil
- end
- end
- if ( conf[__configinfo_struct[:current_value]] )
- begin
- conf[__configinfo_struct[:current_value]] =
- number(conf[__configinfo_struct[:current_value]])
- rescue
- conf[__configinfo_struct[:current_value]] = nil
- end
- end
-
- when /^(#{__numstrval_optkeys.join('|')})$/
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- conf[__configinfo_struct[:default_value]] =
- num_or_str(conf[__configinfo_struct[:default_value]])
- end
- if ( conf[__configinfo_struct[:current_value]] )
- conf[__configinfo_struct[:current_value]] =
- num_or_str(conf[__configinfo_struct[:current_value]])
- end
-
- when /^(#{__boolval_optkeys.join('|')})$/
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- begin
- conf[__configinfo_struct[:default_value]] =
- bool(conf[__configinfo_struct[:default_value]])
- rescue
- conf[__configinfo_struct[:default_value]] = nil
- end
- end
- if ( conf[__configinfo_struct[:current_value]] )
- begin
- conf[__configinfo_struct[:current_value]] =
- bool(conf[__configinfo_struct[:current_value]])
- rescue
- conf[__configinfo_struct[:current_value]] = nil
- end
- end
-
- when /^(#{__listval_optkeys.join('|')})$/
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- conf[__configinfo_struct[:default_value]] =
- simplelist(conf[__configinfo_struct[:default_value]])
- end
- if ( conf[__configinfo_struct[:current_value]] )
- conf[__configinfo_struct[:current_value]] =
- simplelist(conf[__configinfo_struct[:current_value]])
- end
-
- when /^(#{__numlistval_optkeys.join('|')})$/
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] \
- && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ )
- conf[__configinfo_struct[:default_value]] =
- list(conf[__configinfo_struct[:default_value]])
- end
- if ( conf[__configinfo_struct[:current_value]] \
- && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ )
- conf[__configinfo_struct[:current_value]] =
- list(conf[__configinfo_struct[:current_value]])
- end
-
- when /^(#{__tkvariable_optkeys.join('|')})$/
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- v = conf[__configinfo_struct[:default_value]]
- if v.empty?
- conf[__configinfo_struct[:default_value]] = nil
- else
- conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v)
- end
- end
- if ( conf[__configinfo_struct[:current_value]] )
- v = conf[__configinfo_struct[:current_value]]
- if v.empty?
- conf[__configinfo_struct[:current_value]] = nil
- else
- conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v)
- end
- end
-
- else
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- if conf[__configinfo_struct[:default_value]].index('{')
- conf[__configinfo_struct[:default_value]] =
- tk_split_list(conf[__configinfo_struct[:default_value]])
- else
- conf[__configinfo_struct[:default_value]] =
- tk_tcl2ruby(conf[__configinfo_struct[:default_value]])
- end
- end
- if conf[__configinfo_struct[:current_value]]
- if conf[__configinfo_struct[:current_value]].index('{')
- conf[__configinfo_struct[:current_value]] =
- tk_split_list(conf[__configinfo_struct[:current_value]])
- else
- conf[__configinfo_struct[:current_value]] =
- tk_tcl2ruby(conf[__configinfo_struct[:current_value]])
- end
- end
- end
-
- if ( __configinfo_struct[:alias] \
- && conf.size == __configinfo_struct[:alias] + 1 \
- && conf[__configinfo_struct[:alias]][0] == ?- )
- conf[__configinfo_struct[:alias]] =
- conf[__configinfo_struct[:alias]][1..-1]
- end
-
- conf
- }
-
- __font_optkeys.each{|optkey|
- optkey = optkey.to_s
- fontconf = ret.assoc(optkey)
- if fontconf && fontconf.size > 2
- ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/}
- fontconf[__configinfo_struct[:current_value]] = fontobj(optkey)
- ret.push(fontconf)
- end
- }
-
- __methodcall_optkeys.each{|optkey, method|
- ret << [optkey.to_s, '', '', '', self.__send__(method)]
- }
-
- ret
- end
- end
-
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if (slot &&
- slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
- fontkey = $2
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")), false, true)
- conf[__configinfo_struct[:key]] =
- conf[__configinfo_struct[:key]][1..-1]
-
- if ( ! __configinfo_struct[:alias] \
- || conf.size > __configinfo_struct[:alias] + 1 )
- conf[__configinfo_struct[:current_value]] = fontobj(fontkey)
- { conf.shift => conf }
- elsif ( __configinfo_struct[:alias] \
- && conf.size == __configinfo_struct[:alias] + 1 )
- if conf[__configinfo_struct[:alias]][0] == ?-
- conf[__configinfo_struct[:alias]] =
- conf[__configinfo_struct[:alias]][1..-1]
- end
- { conf[0] => conf[1] }
- else
- { conf.shift => conf }
- end
- else
- if slot
- slot = slot.to_s
- case slot
- when /^(#{__val2ruby_optkeys().keys.join('|')})$/
- method = _symbolkey2str(__val2ruby_optkeys())[slot]
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- optval = conf[__configinfo_struct[:default_value]]
- begin
- val = method.call(optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__configinfo_struct[:default_value]] = val
- end
- if ( conf[__configinfo_struct[:current_value]] )
- optval = conf[__configinfo_struct[:current_value]]
- begin
- val = method.call(optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__configinfo_struct[:current_value]] = val
- end
-
- when /^(#{__methodcall_optkeys.keys.join('|')})$/
- method = _symbolkey2str(__methodcall_optkeys)[slot]
- return {slot => ['', '', '', self.__send__(method)]}
-
- when /^(#{__numval_optkeys.join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- begin
- conf[__configinfo_struct[:default_value]] =
- number(conf[__configinfo_struct[:default_value]])
- rescue
- conf[__configinfo_struct[:default_value]] = nil
- end
- end
- if ( conf[__configinfo_struct[:current_value]] )
- begin
- conf[__configinfo_struct[:current_value]] =
- number(conf[__configinfo_struct[:current_value]])
- rescue
- conf[__configinfo_struct[:current_value]] = nil
- end
- end
-
- when /^(#{__numstrval_optkeys.join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- conf[__configinfo_struct[:default_value]] =
- num_or_str(conf[__configinfo_struct[:default_value]])
- end
- if ( conf[__configinfo_struct[:current_value]] )
- conf[__configinfo_struct[:current_value]] =
- num_or_str(conf[__configinfo_struct[:current_value]])
- end
-
- when /^(#{__boolval_optkeys.join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- begin
- conf[__configinfo_struct[:default_value]] =
- bool(conf[__configinfo_struct[:default_value]])
- rescue
- conf[__configinfo_struct[:default_value]] = nil
- end
- end
- if ( conf[__configinfo_struct[:current_value]] )
- begin
- conf[__configinfo_struct[:current_value]] =
- bool(conf[__configinfo_struct[:current_value]])
- rescue
- conf[__configinfo_struct[:current_value]] = nil
- end
- end
-
- when /^(#{__listval_optkeys.join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- conf[__configinfo_struct[:default_value]] =
- simplelist(conf[__configinfo_struct[:default_value]])
- end
- if ( conf[__configinfo_struct[:current_value]] )
- conf[__configinfo_struct[:current_value]] =
- simplelist(conf[__configinfo_struct[:current_value]])
- end
-
- when /^(#{__numlistval_optkeys.join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] \
- && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ )
- conf[__configinfo_struct[:default_value]] =
- list(conf[__configinfo_struct[:default_value]])
- end
- if ( conf[__configinfo_struct[:current_value]] \
- && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ )
- conf[__configinfo_struct[:current_value]] =
- list(conf[__configinfo_struct[:current_value]])
- end
-
- when /^(#{__tkvariable_optkeys.join('|')})$/
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
-
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- v = conf[__configinfo_struct[:default_value]]
- if v.empty?
- conf[__configinfo_struct[:default_value]] = nil
- else
- conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v)
- end
- end
- if ( conf[__configinfo_struct[:current_value]] )
- v = conf[__configinfo_struct[:current_value]]
- if v.empty?
- conf[__configinfo_struct[:current_value]] = nil
- else
- conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v)
- end
- end
-
- when /^(#{__strval_optkeys.join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
- else
- # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
- conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true)
- end
- conf[__configinfo_struct[:key]] =
- conf[__configinfo_struct[:key]][1..-1]
-
- if ( __configinfo_struct[:alias] \
- && conf.size == __configinfo_struct[:alias] + 1 )
- if conf[__configinfo_struct[:alias]][0] == ?-
- conf[__configinfo_struct[:alias]] =
- conf[__configinfo_struct[:alias]][1..-1]
- end
- { conf[0] => conf[1] }
- else
- { conf.shift => conf }
- end
-
- else
- ret = {}
- # tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__confinfo_cmd))).each{|conflist|
- # conf = tk_split_simplelist(conflist)
- tk_split_simplelist(tk_call_without_enc(*__confinfo_cmd), false, false).each{|conflist|
- conf = tk_split_simplelist(conflist, false, true)
- conf[__configinfo_struct[:key]] =
- conf[__configinfo_struct[:key]][1..-1]
-
- optkey = conf[__configinfo_struct[:key]]
- case optkey
- when /^(#{__val2ruby_optkeys().keys.join('|')})$/
- method = _symbolkey2str(__val2ruby_optkeys())[optkey]
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- optval = conf[__configinfo_struct[:default_value]]
- begin
- val = method.call(optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__configinfo_struct[:default_value]] = val
- end
- if ( conf[__configinfo_struct[:current_value]] )
- optval = conf[__configinfo_struct[:current_value]]
- begin
- val = method.call(optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__configinfo_struct[:current_value]] = val
- end
-
- when /^(#{__strval_optkeys.join('|')})$/
- # do nothing
-
- when /^(#{__numval_optkeys.join('|')})$/
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- begin
- conf[__configinfo_struct[:default_value]] =
- number(conf[__configinfo_struct[:default_value]])
- rescue
- conf[__configinfo_struct[:default_value]] = nil
- end
- end
- if ( conf[__configinfo_struct[:current_value]] )
- begin
- conf[__configinfo_struct[:current_value]] =
- number(conf[__configinfo_struct[:current_value]])
- rescue
- conf[__configinfo_struct[:current_value]] = nil
- end
- end
-
- when /^(#{__numstrval_optkeys.join('|')})$/
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- conf[__configinfo_struct[:default_value]] =
- num_or_str(conf[__configinfo_struct[:default_value]])
- end
- if ( conf[__configinfo_struct[:current_value]] )
- conf[__configinfo_struct[:current_value]] =
- num_or_str(conf[__configinfo_struct[:current_value]])
- end
-
- when /^(#{__boolval_optkeys.join('|')})$/
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- begin
- conf[__configinfo_struct[:default_value]] =
- bool(conf[__configinfo_struct[:default_value]])
- rescue
- conf[__configinfo_struct[:default_value]] = nil
- end
- end
- if ( conf[__configinfo_struct[:current_value]] )
- begin
- conf[__configinfo_struct[:current_value]] =
- bool(conf[__configinfo_struct[:current_value]])
- rescue
- conf[__configinfo_struct[:current_value]] = nil
- end
- end
-
- when /^(#{__listval_optkeys.join('|')})$/
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- conf[__configinfo_struct[:default_value]] =
- simplelist(conf[__configinfo_struct[:default_value]])
- end
- if ( conf[__configinfo_struct[:current_value]] )
- conf[__configinfo_struct[:current_value]] =
- simplelist(conf[__configinfo_struct[:current_value]])
- end
-
- when /^(#{__numlistval_optkeys.join('|')})$/
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] \
- && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ )
- conf[__configinfo_struct[:default_value]] =
- list(conf[__configinfo_struct[:default_value]])
- end
- if ( conf[__configinfo_struct[:current_value]] \
- && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ )
- conf[__configinfo_struct[:current_value]] =
- list(conf[__configinfo_struct[:current_value]])
- end
-
- when /^(#{__tkvariable_optkeys.join('|')})$/
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- v = conf[__configinfo_struct[:default_value]]
- if v.empty?
- conf[__configinfo_struct[:default_value]] = nil
- else
- conf[__configinfo_struct[:default_value]] = TkVarAccess.new
- end
- end
- if ( conf[__configinfo_struct[:current_value]] )
- v = conf[__configinfo_struct[:current_value]]
- if v.empty?
- conf[__configinfo_struct[:current_value]] = nil
- else
- conf[__configinfo_struct[:current_value]] = TkVarAccess.new
- end
- end
-
- else
- if ( __configinfo_struct[:default_value] \
- && conf[__configinfo_struct[:default_value]] )
- if conf[__configinfo_struct[:default_value]].index('{')
- conf[__configinfo_struct[:default_value]] =
- tk_split_list(conf[__configinfo_struct[:default_value]])
- else
- conf[__configinfo_struct[:default_value]] =
- tk_tcl2ruby(conf[__configinfo_struct[:default_value]])
- end
- end
- if conf[__configinfo_struct[:current_value]]
- if conf[__configinfo_struct[:current_value]].index('{')
- conf[__configinfo_struct[:current_value]] =
- tk_split_list(conf[__configinfo_struct[:current_value]])
- else
- conf[__configinfo_struct[:current_value]] =
- tk_tcl2ruby(conf[__configinfo_struct[:current_value]])
- end
- end
- end
-
- if ( __configinfo_struct[:alias] \
- && conf.size == __configinfo_struct[:alias] + 1 )
- if conf[__configinfo_struct[:alias]][0] == ?-
- conf[__configinfo_struct[:alias]] =
- conf[__configinfo_struct[:alias]][1..-1]
- end
- ret[conf[0]] = conf[1]
- else
- ret[conf.shift] = conf
- end
- }
-
- __font_optkeys.each{|optkey|
- optkey = optkey.to_s
- fontconf = ret[optkey]
- if fontconf.kind_of?(Array)
- ret.delete(optkey)
- ret.delete('latin' << optkey)
- ret.delete('ascii' << optkey)
- ret.delete('kanji' << optkey)
- fontconf[__configinfo_struct[:current_value]] = fontobj(optkey)
- ret[optkey] = fontconf
- end
- }
-
- __methodcall_optkeys.each{|optkey, method|
- ret[optkey.to_s] = ['', '', '', self.__send__(method)]
- }
-
- ret
- end
- end
- end
- end
-
- def current_configinfo(slot = nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- org_slot = slot
- begin
- conf = configinfo(slot)
- if ( ! __configinfo_struct[:alias] \
- || conf.size > __configinfo_struct[:alias] + 1 )
- return {conf[0] => conf[-1]}
- end
- slot = conf[__configinfo_struct[:alias]]
- end while(org_slot != slot)
- fail RuntimeError,
- "there is a configure alias loop about '#{org_slot}'"
- else
- ret = {}
- configinfo().each{|conf|
- if ( ! __configinfo_struct[:alias] \
- || conf.size > __configinfo_struct[:alias] + 1 )
- ret[conf[0]] = conf[-1]
- end
- }
- ret
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- ret = {}
- configinfo(slot).each{|key, conf|
- ret[key] = conf[-1] if conf.kind_of?(Array)
- }
- ret
- end
- end
-end
-
-class TkObject<TkKernel
- extend TkCore
- include Tk
- include TkConfigMethod
- include TkBindCore
-
-### --> definition is moved to TkUtil module
-# def path
-# @path
-# end
-
- def epath
- @path
- end
-
- def to_eval
- @path
- end
-
- def tk_send(cmd, *rest)
- tk_call(path, cmd, *rest)
- end
- def tk_send_without_enc(cmd, *rest)
- tk_call_without_enc(path, cmd, *rest)
- end
- def tk_send_with_enc(cmd, *rest)
- tk_call_with_enc(path, cmd, *rest)
- end
- # private :tk_send, :tk_send_without_enc, :tk_send_with_enc
-
- def tk_send_to_list(cmd, *rest)
- tk_call_to_list(path, cmd, *rest)
- end
- def tk_send_to_list_without_enc(cmd, *rest)
- tk_call_to_list_without_enc(path, cmd, *rest)
- end
- def tk_send_to_list_with_enc(cmd, *rest)
- tk_call_to_list_with_enc(path, cmd, *rest)
- end
- def tk_send_to_simplelist(cmd, *rest)
- tk_call_to_simplelist(path, cmd, *rest)
- end
- def tk_send_to_simplelist_without_enc(cmd, *rest)
- tk_call_to_simplelist_without_enc(path, cmd, *rest)
- end
- def tk_send_to_simplelist_with_enc(cmd, *rest)
- tk_call_to_simplelist_with_enc(path, cmd, *rest)
- end
-
- def method_missing(id, *args)
- name = id.id2name
- case args.length
- when 1
- if name[-1] == ?=
- configure name[0..-2], args[0]
- args[0]
- else
- configure name, args[0]
- self
- end
- when 0
- begin
- cget(name)
- rescue
- super(id, *args)
-# fail NameError,
-# "undefined local variable or method `#{name}' for #{self.to_s}",
-# error_at
- end
- else
- super(id, *args)
-# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
- end
- end
-
-=begin
- def [](id)
- cget(id)
- end
-
- def []=(id, val)
- configure(id, val)
- val
- end
-=end
-
- def event_generate(context, keys=nil)
- if context.kind_of?(TkEvent::Event)
- context.generate(self, ((keys)? keys: {}))
- elsif keys
- #tk_call('event', 'generate', path,
- # "<#{tk_event_sequence(context)}>", *hash_kv(keys))
- tk_call_without_enc('event', 'generate', path,
- "<#{tk_event_sequence(context)}>",
- *hash_kv(keys, true))
- else
- #tk_call('event', 'generate', path, "<#{tk_event_sequence(context)}>")
- tk_call_without_enc('event', 'generate', path,
- "<#{tk_event_sequence(context)}>")
- end
- end
-
- def tk_trace_variable(v)
- #unless v.kind_of?(TkVariable)
- # fail(ArgumentError, "type error (#{v.class}); must be TkVariable object")
- #end
- v
- end
- private :tk_trace_variable
-
- def destroy
- #tk_call 'trace', 'vdelete', @tk_vn, 'w', @var_id if @var_id
- end
-end
-
-
-class TkWindow<TkObject
- include TkWinfo
- extend TkBindCore
-
- TkCommandNames = [].freeze
- ## ==> If TkCommandNames[0] is a string (not a null string),
- ## assume the string is a Tcl/Tk's create command of the widget class.
- WidgetClassName = ''.freeze
- # WidgetClassNames[WidgetClassName] = self
- ## ==> If self is a widget class, entry to the WidgetClassNames table.
- def self.to_eval
- self::WidgetClassName
- end
-
- def initialize(parent=nil, keys=nil)
- if parent.kind_of? Hash
- keys = _symbolkey2str(parent)
- parent = keys.delete('parent')
- widgetname = keys.delete('widgetname')
- install_win(if parent then parent.path end, widgetname)
- without_creating = keys.delete('without_creating')
- # if without_creating && !widgetname
- # fail ArgumentError,
- # "if set 'without_creating' to true, need to define 'widgetname'"
- # end
- elsif keys
- keys = _symbolkey2str(keys)
- widgetname = keys.delete('widgetname')
- install_win(if parent then parent.path end, widgetname)
- without_creating = keys.delete('without_creating')
- # if without_creating && !widgetname
- # fail ArgumentError,
- # "if set 'without_creating' to true, need to define 'widgetname'"
- # end
- else
- install_win(if parent then parent.path end)
- end
- if self.method(:create_self).arity == 0
- p 'create_self has no arg' if $DEBUG
- create_self unless without_creating
- if keys
- # tk_call @path, 'configure', *hash_kv(keys)
- configure(keys)
- end
- else
- p 'create_self has args' if $DEBUG
- fontkeys = {}
- methodkeys = {}
- if keys
- #['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
- # fontkeys[key] = keys.delete(key) if keys.key?(key)
- #}
- __font_optkeys.each{|key|
- fkey = key.to_s
- fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
-
- fkey = "kanji#{key}"
- fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
-
- fkey = "latin#{key}"
- fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
-
- fkey = "ascii#{key}"
- fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
- }
-
- __methodcall_optkeys.each{|key|
- key = key.to_s
- methodkeys[key] = keys.delete(key) if keys.key?(key)
- }
-
- __ruby2val_optkeys.each{|key, method|
- key = key.to_s
- keys[key] = method.call(keys[key]) if keys.has_key?(key)
- }
- end
- if without_creating && keys
- #configure(keys)
- configure(__conv_keyonly_opts(keys))
- else
- #create_self(keys)
- create_self(__conv_keyonly_opts(keys))
- end
- font_configure(fontkeys) unless fontkeys.empty?
- configure(methodkeys) unless methodkeys.empty?
- end
- end
-
- def create_self(keys)
- # may need to override
- begin
- cmd = self.class::TkCommandNames[0]
- fail unless (cmd.kind_of?(String) && cmd.length > 0)
- rescue
- fail RuntimeError, "class #{self.class} may be an abstract class"
- end
-
- if keys and keys != None
- tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
- else
- tk_call_without_enc(cmd, @path)
- end
- end
- private :create_self
-
- def exist?
- TkWinfo.exist?(self)
- end
-
- def bind_class
- @db_class || self.class()
- end
-
- def database_classname
- TkWinfo.classname(self)
- end
- def database_class
- name = database_classname()
- if WidgetClassNames[name]
- WidgetClassNames[name]
- else
- TkDatabaseClass.new(name)
- end
- end
- def self.database_classname
- self::WidgetClassName
- end
- def self.database_class
- WidgetClassNames[self::WidgetClassName]
- end
-
- def pack(keys = nil)
- #tk_call_without_enc('pack', epath, *hash_kv(keys, true))
- if keys
- TkPack.configure(self, keys)
- else
- TkPack.configure(self)
- end
- self
- end
-
- def pack_in(target, keys = nil)
- if keys
- keys = keys.dup
- keys['in'] = target
- else
- keys = {'in'=>target}
- end
- #tk_call 'pack', epath, *hash_kv(keys)
- TkPack.configure(self, keys)
- self
- end
-
- def pack_forget
- #tk_call_without_enc('pack', 'forget', epath)
- TkPack.forget(self)
- self
- end
- alias unpack pack_forget
-
- def pack_config(slot, value=None)
- #if slot.kind_of? Hash
- # tk_call 'pack', 'configure', epath, *hash_kv(slot)
- #else
- # tk_call 'pack', 'configure', epath, "-#{slot}", value
- #end
- if slot.kind_of? Hash
- TkPack.configure(self, slot)
- else
- TkPack.configure(self, slot=>value)
- end
- end
- alias pack_configure pack_config
-
- def pack_info()
- #ilist = list(tk_call('pack', 'info', epath))
- #info = {}
- #while key = ilist.shift
- # info[key[1..-1]] = ilist.shift
- #end
- #return info
- TkPack.info(self)
- end
-
- def pack_propagate(mode=None)
- #if mode == None
- # bool(tk_call('pack', 'propagate', epath))
- #else
- # tk_call('pack', 'propagate', epath, mode)
- # self
- #end
- if mode == None
- TkPack.propagate(self)
- else
- TkPack.propagate(self, mode)
- self
- end
- end
-
- def pack_slaves()
- #list(tk_call('pack', 'slaves', epath))
- TkPack.slaves(self)
- end
-
- def grid(keys = nil)
- #tk_call 'grid', epath, *hash_kv(keys)
- if keys
- TkGrid.configure(self, keys)
- else
- TkGrid.configure(self)
- end
- self
- end
-
- def grid_in(target, keys = nil)
- if keys
- keys = keys.dup
- keys['in'] = target
- else
- keys = {'in'=>target}
- end
- #tk_call 'grid', epath, *hash_kv(keys)
- TkGrid.configure(self, keys)
- self
- end
-
- def grid_forget
- #tk_call('grid', 'forget', epath)
- TkGrid.forget(self)
- self
- end
- alias ungrid grid_forget
-
- def grid_bbox(*args)
- #list(tk_call('grid', 'bbox', epath, *args))
- TkGrid.bbox(self, *args)
- end
-
- def grid_config(slot, value=None)
- #if slot.kind_of? Hash
- # tk_call 'grid', 'configure', epath, *hash_kv(slot)
- #else
- # tk_call 'grid', 'configure', epath, "-#{slot}", value
- #end
- if slot.kind_of? Hash
- TkGrid.configure(self, slot)
- else
- TkGrid.configure(self, slot=>value)
- end
- end
- alias grid_configure grid_config
-
- def grid_columnconfig(index, keys)
- #tk_call('grid', 'columnconfigure', epath, index, *hash_kv(keys))
- TkGrid.columnconfigure(self, index, keys)
- end
- alias grid_columnconfigure grid_columnconfig
-
- def grid_rowconfig(index, keys)
- #tk_call('grid', 'rowconfigure', epath, index, *hash_kv(keys))
- TkGrid.rowconfigure(self, index, keys)
- end
- alias grid_rowconfigure grid_rowconfig
-
- def grid_columnconfiginfo(index, slot=nil)
- #if slot
- # tk_call('grid', 'columnconfigure', epath, index, "-#{slot}").to_i
- #else
- # ilist = list(tk_call('grid', 'columnconfigure', epath, index))
- # info = {}
- # while key = ilist.shift
- # info[key[1..-1]] = ilist.shift
- # end
- # info
- #end
- TkGrid.columnconfiginfo(self, index, slot)
- end
-
- def grid_rowconfiginfo(index, slot=nil)
- #if slot
- # tk_call('grid', 'rowconfigure', epath, index, "-#{slot}").to_i
- #else
- # ilist = list(tk_call('grid', 'rowconfigure', epath, index))
- # info = {}
- # while key = ilist.shift
- # info[key[1..-1]] = ilist.shift
- # end
- # info
- #end
- TkGrid.rowconfiginfo(self, index, slot)
- end
-
- def grid_info()
- #list(tk_call('grid', 'info', epath))
- TkGrid.info(self)
- end
-
- def grid_location(x, y)
- #list(tk_call('grid', 'location', epath, x, y))
- TkGrid.location(self, x, y)
- end
-
- def grid_propagate(mode=None)
- #if mode == None
- # bool(tk_call('grid', 'propagate', epath))
- #else
- # tk_call('grid', 'propagate', epath, mode)
- # self
- #end
- if mode == None
- TkGrid.propagate(self)
- else
- TkGrid.propagate(self, mode)
- self
- end
- end
-
- def grid_remove()
- #tk_call 'grid', 'remove', epath
- TkGrid.remove(self)
- self
- end
-
- def grid_size()
- #list(tk_call('grid', 'size', epath))
- TkGrid.size(self)
- end
-
- def grid_slaves(args)
- #list(tk_call('grid', 'slaves', epath, *hash_kv(args)))
- TkGrid.slaves(self, args)
- end
-
- def place(keys)
- #tk_call 'place', epath, *hash_kv(keys)
- TkPlace.configure(self, keys)
- self
- end
-
- def place_in(target, keys = nil)
- if keys
- keys = keys.dup
- keys['in'] = target
- else
- keys = {'in'=>target}
- end
- #tk_call 'place', epath, *hash_kv(keys)
- TkPlace.configure(self, keys)
- self
- end
-
- def place_forget
- #tk_call 'place', 'forget', epath
- TkPlace.forget(self)
- self
- end
- alias unplace place_forget
-
- def place_config(slot, value=None)
- #if slot.kind_of? Hash
- # tk_call 'place', 'configure', epath, *hash_kv(slot)
- #else
- # tk_call 'place', 'configure', epath, "-#{slot}", value
- #end
- TkPlace.configure(self, slot, value)
- end
- alias place_configure place_config
-
- def place_configinfo(slot = nil)
- # for >= Tk8.4a2 ?
- #if slot
- # conf = tk_split_list(tk_call('place', 'configure', epath, "-#{slot}") )
- # conf[0] = conf[0][1..-1]
- # conf
- #else
- # tk_split_simplelist(tk_call('place',
- # 'configure', epath)).collect{|conflist|
- # conf = tk_split_simplelist(conflist)
- # conf[0] = conf[0][1..-1]
- # conf
- # }
- #end
- TkPlace.configinfo(self, slot)
- end
-
- def place_info()
- #ilist = list(tk_call('place', 'info', epath))
- #info = {}
- #while key = ilist.shift
- # info[key[1..-1]] = ilist.shift
- #end
- #return info
- TkPlace.info(self)
- end
-
- def place_slaves()
- #list(tk_call('place', 'slaves', epath))
- TkPlace.slaves(self)
- end
-
- def set_focus(force=false)
- if force
- tk_call_without_enc('focus', '-force', path)
- else
- tk_call_without_enc('focus', path)
- end
- self
- end
- alias focus set_focus
-
- def grab(opt = nil)
- unless opt
- tk_call_without_enc('grab', 'set', path)
- return self
- end
-
- case opt
- when 'set', :set
- tk_call_without_enc('grab', 'set', path)
- return self
- when 'global', :global
- #return(tk_call('grab', 'set', '-global', path))
- tk_call_without_enc('grab', 'set', '-global', path)
- return self
- when 'release', :release
- #return tk_call('grab', 'release', path)
- tk_call_without_enc('grab', 'release', path)
- return self
- when 'current', :current
- return window(tk_call_without_enc('grab', 'current', path))
- when 'status', :status
- return tk_call_without_enc('grab', 'status', path)
- else
- return tk_call_without_enc('grab', opt, path)
- end
- end
-
- def grab_current
- grab('current')
- end
- alias current_grab grab_current
- def grab_release
- grab('release')
- end
- alias release_grab grab_release
- def grab_set
- grab('set')
- end
- alias set_grab grab_set
- def grab_set_global
- grab('global')
- end
- alias set_global_grab grab_set_global
- def grab_status
- grab('status')
- end
-
- def lower(below=None)
- # below = below.epath if below.kind_of?(TkObject)
- below = _epath(below)
- tk_call 'lower', epath, below
- self
- end
- alias lower_window lower
- def raise(above=None)
- #above = above.epath if above.kind_of?(TkObject)
- above = _epath(above)
- tk_call 'raise', epath, above
- self
- end
- alias raise_window raise
-
- def command(cmd=nil, &b)
- if cmd
- configure_cmd('command', cmd)
- elsif b
- configure_cmd('command', Proc.new(&b))
- else
- cget('command')
- end
- end
-
- def colormodel(model=None)
- tk_call('tk', 'colormodel', path, model)
- self
- end
-
- def caret(keys=nil)
- TkXIM.caret(path, keys)
- end
-
- def destroy
- super
- children = []
- rexp = /^#{self.path}\.[^.]+$/
- TkCore::INTERP.tk_windows.each{|path, obj|
- children << [path, obj] if path =~ rexp
- }
- if defined?(@cmdtbl)
- for id in @cmdtbl
- uninstall_cmd id
- end
- end
-
- children.each{|path, obj|
- if defined?(@cmdtbl)
- for id in @cmdtbl
- uninstall_cmd id
- end
- end
- TkCore::INTERP.tk_windows.delete(path)
- }
-
- begin
- tk_call_without_enc('destroy', epath)
- rescue
- end
- uninstall_win
- end
-
- def wait_visibility(on_thread = true)
- if $SAFE >= 4
- fail SecurityError, "can't wait visibility at $SAFE >= 4"
- end
- on_thread &= (Thread.list.size != 1)
- if on_thread
- INTERP._thread_tkwait('visibility', path)
- else
- INTERP._invoke('tkwait', 'visibility', path)
- end
- end
- def eventloop_wait_visibility
- wait_visibility(false)
- end
- def thread_wait_visibility
- wait_visibility(true)
- end
- alias wait wait_visibility
- alias tkwait wait_visibility
- alias eventloop_wait eventloop_wait_visibility
- alias eventloop_tkwait eventloop_wait_visibility
- alias eventloop_tkwait_visibility eventloop_wait_visibility
- alias thread_wait thread_wait_visibility
- alias thread_tkwait thread_wait_visibility
- alias thread_tkwait_visibility thread_wait_visibility
-
- def wait_destroy(on_thread = true)
- if $SAFE >= 4
- fail SecurityError, "can't wait destroy at $SAFE >= 4"
- end
- on_thread &= (Thread.list.size != 1)
- if on_thread
- INTERP._thread_tkwait('window', epath)
- else
- INTERP._invoke('tkwait', 'window', epath)
- end
- end
- alias wait_window wait_destroy
- def eventloop_wait_destroy
- wait_destroy(false)
- end
- alias eventloop_wait_window eventloop_wait_destroy
- def thread_wait_destroy
- wait_destroy(true)
- end
- alias thread_wait_window thread_wait_destroy
-
- alias tkwait_destroy wait_destroy
- alias tkwait_window wait_destroy
-
- alias eventloop_tkwait_destroy eventloop_wait_destroy
- alias eventloop_tkwait_window eventloop_wait_destroy
-
- alias thread_tkwait_destroy thread_wait_destroy
- alias thread_tkwait_window thread_wait_destroy
-
- def bindtags(taglist=nil)
- if taglist
- fail ArgumentError, "taglist must be Array" unless taglist.kind_of? Array
- tk_call('bindtags', path, taglist)
- taglist
- else
- list(tk_call('bindtags', path)).collect{|tag|
- if tag.kind_of?(String)
- if cls = WidgetClassNames[tag]
- cls
- elsif btag = TkBindTag.id2obj(tag)
- btag
- else
- tag
- end
- else
- tag
- end
- }
- end
- end
-
- def bindtags=(taglist)
- bindtags(taglist)
- taglist
- end
-
- def bindtags_shift
- taglist = bindtags
- tag = taglist.shift
- bindtags(taglist)
- tag
- end
-
- def bindtags_unshift(tag)
- bindtags(bindtags().unshift(tag))
- end
-end
-
-
-# freeze core modules
-#TclTkLib.freeze
-#TclTkIp.freeze
-#TkUtil.freeze
-#TkKernel.freeze
-#TkComm.freeze
-#TkComm::Event.freeze
-#TkCore.freeze
-#Tk.freeze
-
-module Tk
- RELEASE_DATE = '2006-07-14'.freeze
-
- autoload :AUTO_PATH, 'tk/variable'
- autoload :TCL_PACKAGE_PATH, 'tk/variable'
- autoload :PACKAGE_PATH, 'tk/variable'
- autoload :TCL_LIBRARY_PATH, 'tk/variable'
- autoload :LIBRARY_PATH, 'tk/variable'
- autoload :TCL_PRECISION, 'tk/variable'
-end
-
-# call setup script for Tk extension libraries (base configuration)
-begin
- require 'tkextlib/setup.rb'
-rescue LoadError
- # ignore
-end
diff --git a/ext/tk/lib/tk/after.rb b/ext/tk/lib/tk/after.rb
deleted file mode 100644
index 8c58210331..0000000000
--- a/ext/tk/lib/tk/after.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# tk/after.rb : methods for Tcl/Tk after command
-#
-# $Id$
-#
-require 'tk/timer'
diff --git a/ext/tk/lib/tk/autoload.rb b/ext/tk/lib/tk/autoload.rb
deleted file mode 100644
index 6b3773f4ea..0000000000
--- a/ext/tk/lib/tk/autoload.rb
+++ /dev/null
@@ -1,196 +0,0 @@
-#
-# autoload
-#
-
-#######################
-# geometry manager
-autoload :TkGrid, 'tk/grid'
-def TkGrid(*args); TkGrid.configure(*args); end
-
-autoload :TkPack, 'tk/pack'
-def TkPack(*args); TkPack.configure(*args); end
-
-autoload :TkPlace, 'tk/place'
-def TkPlace(*args); TkPlace.configure(*args); end
-
-
-#######################
-# others
-autoload :TkBgError, 'tk/bgerror'
-
-autoload :TkBindTag, 'tk/bindtag'
-autoload :TkBindTagAll, 'tk/bindtag'
-autoload :TkDatabaseClass, 'tk/bindtag'
-
-autoload :TkButton, 'tk/button'
-
-autoload :TkConsole, 'tk/console'
-
-autoload :TkCanvas, 'tk/canvas'
-
-autoload :TkcTagAccess, 'tk/canvastag'
-autoload :TkcTag, 'tk/canvastag'
-autoload :TkcTagString, 'tk/canvastag'
-autoload :TkcNamedTag, 'tk/canvastag'
-autoload :TkcTagAll, 'tk/canvastag'
-autoload :TkcTagCurrent, 'tk/canvastag'
-autoload :TkcTagGroup, 'tk/canvastag'
-
-autoload :TkCheckButton, 'tk/checkbutton'
-autoload :TkCheckbutton, 'tk/checkbutton'
-
-autoload :TkClipboard, 'tk/clipboard'
-
-autoload :TkComposite, 'tk/composite'
-
-autoload :TkConsole, 'tk/console'
-
-autoload :TkDialog, 'tk/dialog'
-autoload :TkDialog2, 'tk/dialog'
-autoload :TkDialogObj, 'tk/dialog'
-autoload :TkWarning, 'tk/dialog'
-autoload :TkWarning2, 'tk/dialog'
-autoload :TkWarningObj, 'tk/dialog'
-
-autoload :TkEntry, 'tk/entry'
-
-autoload :TkEvent, 'tk/event'
-
-autoload :TkFont, 'tk/font'
-autoload :TkTreatTagFont, 'tk/font'
-
-autoload :TkFrame, 'tk/frame'
-
-autoload :TkImage, 'tk/image'
-autoload :TkBitmapImage, 'tk/image'
-autoload :TkPhotoImage, 'tk/image'
-
-autoload :TkItemConfigMethod, 'tk/itemconfig'
-
-autoload :TkTreatItemFont, 'tk/itemfont'
-
-autoload :TkKinput, 'tk/kinput'
-
-autoload :TkLabel, 'tk/label'
-
-autoload :TkLabelFrame, 'tk/labelframe'
-autoload :TkLabelframe, 'tk/labelframe'
-
-autoload :TkListbox, 'tk/listbox'
-
-autoload :TkMacResource, 'tk/macpkg'
-
-autoload :TkMenu, 'tk/menu'
-autoload :TkMenuClone, 'tk/menu'
-autoload :TkSystemMenu, 'tk/menu'
-autoload :TkSysMenu_Help, 'tk/menu'
-autoload :TkSysMenu_System, 'tk/menu'
-autoload :TkSysMenu_Apple, 'tk/menu'
-autoload :TkMenubutton, 'tk/menu'
-autoload :TkOptionMenubutton, 'tk/menu'
-
-autoload :TkMenubar, 'tk/menubar'
-
-autoload :TkMenuSpec, 'tk/menuspec'
-
-autoload :TkMessage, 'tk/message'
-
-autoload :TkManageFocus, 'tk/mngfocus'
-
-autoload :TkMsgCatalog, 'tk/msgcat'
-autoload :TkMsgCat, 'tk/msgcat'
-
-autoload :TkNamespace, 'tk/namespace'
-
-autoload :TkOptionDB, 'tk/optiondb'
-autoload :TkOption, 'tk/optiondb'
-autoload :TkResourceDB, 'tk/optiondb'
-
-autoload :TkPackage, 'tk/package'
-
-autoload :TkPalette, 'tk/palette'
-
-autoload :TkPanedWindow, 'tk/panedwindow'
-autoload :TkPanedwindow, 'tk/panedwindow'
-
-autoload :TkRadioButton, 'tk/radiobutton'
-autoload :TkRadiobutton, 'tk/radiobutton'
-
-autoload :TkRoot, 'tk/root'
-
-autoload :TkScale, 'tk/scale'
-
-autoload :TkScrollbar, 'tk/scrollbar'
-autoload :TkXScrollbar, 'tk/scrollbar'
-autoload :TkYScrollbar, 'tk/scrollbar'
-
-autoload :TkScrollbox, 'tk/scrollbox'
-
-autoload :TkSelection, 'tk/selection'
-
-autoload :TkSpinbox, 'tk/spinbox'
-
-autoload :TkTreatTagFont, 'tk/tagfont'
-
-autoload :TkText, 'tk/text'
-
-autoload :TkTextImage, 'tk/textimage'
-
-autoload :TkTextMark, 'tk/textmark'
-autoload :TkTextNamedMark, 'tk/textmark'
-autoload :TkTextMarkInsert, 'tk/textmark'
-autoload :TkTextMarkCurrent, 'tk/textmark'
-autoload :TkTextMarkAnchor, 'tk/textmark'
-
-autoload :TkTextTag, 'tk/texttag'
-autoload :TkTextNamedTag, 'tk/texttag'
-autoload :TkTextTagSel, 'tk/texttag'
-
-autoload :TkTextWindow, 'tk/textwindow'
-
-autoload :TkAfter, 'tk/timer'
-autoload :TkTimer, 'tk/timer'
-autoload :TkRTTimer, 'tk/timer'
-
-autoload :TkToplevel, 'tk/toplevel'
-
-autoload :TkTextWin, 'tk/txtwin_abst'
-
-autoload :TkValidation, 'tk/validation'
-
-autoload :TkVariable, 'tk/variable'
-autoload :TkVarAccess, 'tk/variable'
-
-autoload :TkVirtualEvent, 'tk/virtevent'
-autoload :TkNamedVirtualEvent,'tk/virtevent'
-
-autoload :TkWinfo, 'tk/winfo'
-
-autoload :TkWinDDE, 'tk/winpkg'
-autoload :TkWinRegistry, 'tk/winpkg'
-
-autoload :TkXIM, 'tk/xim'
-
-
-#######################
-# sub-module of Tk
-module Tk
- autoload :Clock, 'tk/clock'
- autoload :OptionObj, 'tk/optionobj'
- autoload :X_Scrollable, 'tk/scrollable'
- autoload :Y_Scrollable, 'tk/scrollable'
- autoload :Scrollable, 'tk/scrollable'
- autoload :Wm, 'tk/wm'
-
- autoload :ValidateConfigure, 'tk/validation'
- autoload :ItemValidateConfigure, 'tk/validation'
-
- autoload :EncodedString, 'tk/encodedstr'
- def Tk.EncodedString(str, enc = nil); Tk::EncodedString.new(str, enc); end
-
- autoload :BinaryString, 'tk/encodedstr'
- def Tk.BinaryString(str); Tk::BinaryString.new(str); end
-
- autoload :UTF8_String, 'tk/encodedstr'
- def Tk.UTF8_String(str); Tk::UTF8_String.new(str); end
-end
diff --git a/ext/tk/lib/tk/bgerror.rb b/ext/tk/lib/tk/bgerror.rb
deleted file mode 100644
index c82a8e046b..0000000000
--- a/ext/tk/lib/tk/bgerror.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# tkbgerror -- bgerror ( tkerror ) module
-# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
-#
-require 'tk'
-
-module TkBgError
- extend Tk
-
- TkCommandNames = ['bgerror'.freeze].freeze
-
- def bgerror(message)
- tk_call('bgerror', message)
- end
- alias tkerror bgerror
- alias show bgerror
- module_function :bgerror, :tkerror, :show
-
- def set_handler(hdlr = Proc.new) #==> handler :: proc{|msg| ...body... }
- tk_call('proc', 'bgerror', 'msg', install_cmd(hdlr) + ' $msg')
- end
- def set_default
- begin
- tk_call('rename', 'bgerror', '')
- rescue RuntimeError
- end
- end
- module_function :set_handler, :set_default
-end
diff --git a/ext/tk/lib/tk/bindtag.rb b/ext/tk/lib/tk/bindtag.rb
deleted file mode 100644
index 9023a08e06..0000000000
--- a/ext/tk/lib/tk/bindtag.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# tk/bind.rb : control event binding
-#
-require 'tk'
-
-class TkBindTag
- include TkBindCore
-
- #BTagID_TBL = {}
- BTagID_TBL = TkCore::INTERP.create_table
- Tk_BINDTAG_ID = ["btag".freeze, "00000".taint].freeze
-
- TkCore::INTERP.init_ip_env{ BTagID_TBL.clear }
-
- def TkBindTag.id2obj(id)
- BTagID_TBL[id]? BTagID_TBL[id]: id
- end
-
- def TkBindTag.new_by_name(name, *args, &b)
- return BTagID_TBL[name] if BTagID_TBL[name]
- self.new.instance_eval{
- BTagID_TBL.delete @id
- @id = name
- BTagID_TBL[@id] = self
- bind(*args, &b) if args != []
- self
- }
- end
-
- def initialize(*args, &b)
- # @id = Tk_BINDTAG_ID.join('')
- @id = Tk_BINDTAG_ID.join(TkCore::INTERP._ip_id_)
- Tk_BINDTAG_ID[1].succ!
- BTagID_TBL[@id] = self
- bind(*args, &b) if args != []
- end
-
- ALL = self.new_by_name('all')
-
- def name
- @id
- end
-
- def to_eval
- @id
- end
-
- def inspect
- #Kernel.format "#<TkBindTag: %s>", @id
- '#<TkBindTag: ' + @id + '>'
- end
-end
-
-
-class TkBindTagAll<TkBindTag
- def TkBindTagAll.new(*args, &b)
- $stderr.puts "Warning: TkBindTagALL is obsolete. Use TkBindTag::ALL\n"
-
- TkBindTag::ALL.bind(*args, &b) if args != []
- TkBindTag::ALL
- end
-end
-
-
-class TkDatabaseClass<TkBindTag
- def self.new(name, *args, &b)
- return BTagID_TBL[name] if BTagID_TBL[name]
- super(name, *args, &b)
- end
-
- def initialize(name, *args, &b)
- @id = name
- BTagID_TBL[@id] = self
- bind(*args, &b) if args != []
- end
-
- def inspect
- #Kernel.format "#<TkDatabaseClass: %s>", @id
- '#<TkDatabaseClass: ' + @id + '>'
- end
-end
diff --git a/ext/tk/lib/tk/button.rb b/ext/tk/lib/tk/button.rb
deleted file mode 100644
index 407a47c400..0000000000
--- a/ext/tk/lib/tk/button.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# tk/button.rb : treat button widget
-#
-require 'tk'
-require 'tk/label'
-
-class TkButton<TkLabel
- TkCommandNames = ['button'.freeze].freeze
- WidgetClassName = 'Button'.freeze
- WidgetClassNames[WidgetClassName] = self
- #def create_self(keys)
- # if keys and keys != None
- # tk_call_without_enc('button', @path, *hash_kv(keys, true))
- # else
- # tk_call_without_enc('button', @path)
- # end
- #end
- #private :create_self
-
- def invoke
- _fromUTF8(tk_send_without_enc('invoke'))
- end
- def flash
- tk_send_without_enc('flash')
- self
- end
-end
diff --git a/ext/tk/lib/tk/canvas.rb b/ext/tk/lib/tk/canvas.rb
deleted file mode 100644
index 02b4a8cb20..0000000000
--- a/ext/tk/lib/tk/canvas.rb
+++ /dev/null
@@ -1,759 +0,0 @@
-#
-# tk/canvas.rb - Tk canvas classes
-# $Date$
-# by Yukihiro Matsumoto <matz@caelum.co.jp>
-#
-require 'tk'
-require 'tk/canvastag'
-require 'tk/itemconfig'
-require 'tk/scrollable'
-
-module TkCanvasItemConfig
- include TkItemConfigMethod
-
- def __item_strval_optkeys(id)
- # maybe need to override
- super(id) + [
- 'fill', 'activefill', 'disabledfill',
- 'outline', 'activeoutline', 'disabledoutline'
- ]
- end
- private :__item_strval_optkeys
-
- def __item_methodcall_optkeys(id)
- {'coords'=>'coords'}
- end
- private :__item_methodcall_optkeys
-
- def __item_val2ruby_optkeys(id) # { key=>proc, ... }
- super(id).update('window'=>proc{|i, v| window(v)})
- end
- private :__item_val2ruby_optkeys
-
- def __item_pathname(tagOrId)
- if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag)
- self.path + ';' + tagOrId.id.to_s
- else
- self.path + ';' + tagOrId.to_s
- end
- end
- private :__item_pathname
-end
-
-class TkCanvas<TkWindow
- include TkCanvasItemConfig
- include Scrollable
-
- TkCommandNames = ['canvas'.freeze].freeze
- WidgetClassName = 'Canvas'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __destroy_hook__
- TkcItem::CItemID_TBL.delete(@path)
- end
-
- #def create_self(keys)
- # if keys and keys != None
- # tk_call_without_enc('canvas', @path, *hash_kv(keys, true))
- # else
- # tk_call_without_enc('canvas', @path)
- # end
- #end
- #private :create_self
-
- def __numval_optkeys
- super() + ['closeenough']
- end
- private :__numval_optkeys
-
- def __boolval_optkeys
- super() + ['confine']
- end
- private :__boolval_optkeys
-
- def tagid(tag)
- if tag.kind_of?(TkcItem) || tag.kind_of?(TkcTag)
- tag.id
- else
- tag # maybe an Array of configure paramters
- end
- end
- private :tagid
-
-
- # create a canvas item without creating a TkcItem object
- def create(type, *args)
- type.create(self, *args)
- end
-
-
- def addtag(tag, mode, *args)
- mode = mode.to_s
- if args[0] && mode =~ /^(above|below|with(tag)?)$/
- args[0] = tagid(args[0])
- end
- tk_send_without_enc('addtag', tagid(tag), mode, *args)
- self
- end
- def addtag_above(tagOrId, target)
- addtag(tagOrId, 'above', tagid(target))
- end
- def addtag_all(tagOrId)
- addtag(tagOrId, 'all')
- end
- def addtag_below(tagOrId, target)
- addtag(tagOrId, 'below', tagid(target))
- end
- def addtag_closest(tagOrId, x, y, halo=None, start=None)
- addtag(tagOrId, 'closest', x, y, halo, start)
- end
- def addtag_enclosed(tagOrId, x1, y1, x2, y2)
- addtag(tagOrId, 'enclosed', x1, y1, x2, y2)
- end
- def addtag_overlapping(tagOrId, x1, y1, x2, y2)
- addtag(tagOrId, 'overlapping', x1, y1, x2, y2)
- end
- def addtag_withtag(tagOrId, tag)
- addtag(tagOrId, 'withtag', tagid(tag))
- end
-
- def bbox(tagOrId, *tags)
- list(tk_send_without_enc('bbox', tagid(tagOrId),
- *tags.collect{|t| tagid(t)}))
- end
-
- #def itembind(tag, context, cmd=Proc.new, *args)
- # _bind([path, "bind", tagid(tag)], context, cmd, *args)
- # self
- #end
- def itembind(tag, context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([path, "bind", tagid(tag)], context, cmd, *args)
- self
- end
-
- #def itembind_append(tag, context, cmd=Proc.new, *args)
- # _bind_append([path, "bind", tagid(tag)], context, cmd, *args)
- # self
- #end
- def itembind_append(tag, context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([path, "bind", tagid(tag)], context, cmd, *args)
- self
- end
-
- def itembind_remove(tag, context)
- _bind_remove([path, "bind", tagid(tag)], context)
- self
- end
-
- def itembindinfo(tag, context=nil)
- _bindinfo([path, "bind", tagid(tag)], context)
- end
-
- def canvasx(screen_x, *args)
- #tk_tcl2ruby(tk_send_without_enc('canvasx', screen_x, *args))
- number(tk_send_without_enc('canvasx', screen_x, *args))
- end
- def canvasy(screen_y, *args)
- #tk_tcl2ruby(tk_send_without_enc('canvasy', screen_y, *args))
- number(tk_send_without_enc('canvasy', screen_y, *args))
- end
-
- def coords(tag, *args)
- if args == []
- tk_split_list(tk_send_without_enc('coords', tagid(tag)))
- else
- tk_send_without_enc('coords', tagid(tag), *(args.flatten))
- self
- end
- end
-
- def dchars(tag, first, last=None)
- tk_send_without_enc('dchars', tagid(tag),
- _get_eval_enc_str(first), _get_eval_enc_str(last))
- self
- end
-
- def delete(*args)
- if TkcItem::CItemID_TBL[self.path]
- args.each{|tag|
- find('withtag', tag).each{|item|
- if item.kind_of?(TkcItem)
- TkcItem::CItemID_TBL[self.path].delete(item.id)
- end
- }
- }
- end
- tk_send_without_enc('delete', *args.collect{|t| tagid(t)})
- self
- end
- alias remove delete
-
- def dtag(tag, tag_to_del=None)
- tk_send_without_enc('dtag', tagid(tag), tagid(tag_to_del))
- self
- end
- alias deltag dtag
-
- def find(mode, *args)
- list(tk_send_without_enc('find', mode, *args)).collect!{|id|
- TkcItem.id2obj(self, id)
- }
- end
- def find_above(target)
- find('above', tagid(target))
- end
- def find_all
- find('all')
- end
- def find_below(target)
- find('below', tagid(target))
- end
- def find_closest(x, y, halo=None, start=None)
- find('closest', x, y, halo, start)
- end
- def find_enclosed(x1, y1, x2, y2)
- find('enclosed', x1, y1, x2, y2)
- end
- def find_overlapping(x1, y1, x2, y2)
- find('overlapping', x1, y1, x2, y2)
- end
- def find_withtag(tag)
- find('withtag', tag)
- end
-
- def itemfocus(tagOrId=nil)
- if tagOrId
- tk_send_without_enc('focus', tagid(tagOrId))
- self
- else
- ret = tk_send_without_enc('focus')
- if ret == ""
- nil
- else
- TkcItem.id2obj(self, ret)
- end
- end
- end
-
- def gettags(tagOrId)
- list(tk_send_without_enc('gettags', tagid(tagOrId))).collect{|tag|
- TkcTag.id2obj(self, tag)
- }
- end
-
- def icursor(tagOrId, index)
- tk_send_without_enc('icursor', tagid(tagOrId), index)
- self
- end
-
- def index(tagOrId, idx)
- number(tk_send_without_enc('index', tagid(tagOrId), idx))
- end
-
- def insert(tagOrId, index, string)
- tk_send_without_enc('insert', tagid(tagOrId), index,
- _get_eval_enc_str(string))
- self
- end
-
-=begin
- def itemcget(tagOrId, option)
- case option.to_s
- when 'dash', 'activedash', 'disableddash'
- conf = tk_send_without_enc('itemcget', tagid(tagOrId), "-#{option}")
- if conf =~ /^[0-9]/
- list(conf)
- else
- conf
- end
- when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
- _fromUTF8(tk_send_without_enc('itemcget', tagid(tagOrId), "-#{option}"))
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_send('itemcget', tagid(tagOrId), "-#{option}"))
- fnt = tk_tcl2ruby(_fromUTF8(tk_send_with_enc('itemcget', tagid(tagOrId), '-font')))
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(tagid(tagOrId), fnt)
- end
- if option.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby(_fromUTF8(tk_send_without_enc('itemcget', tagid(tagOrId),
- "-#{option}")))
- end
- end
-
- def itemconfigure(tagOrId, key, value=None)
- if key.kind_of? Hash
- key = _symbolkey2str(key)
- coords = key.delete('coords')
- self.coords(tagOrId, coords) if coords
-
- if ( key['font'] || key['kanjifont'] \
- || key['latinfont'] || key['asciifont'] )
- tagfont_configure(tagid(tagOrId), key.dup)
- else
- _fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),
- *hash_kv(key, true)))
- end
-
- else
- if ( key == 'coords' || key == :coords )
- self.coords(tagOrId, value)
- elsif ( key == 'font' || key == :font ||
- key == 'kanjifont' || key == :kanjifont ||
- key == 'latinfont' || key == :latinfont ||
- key == 'asciifont' || key == :asciifont )
- if value == None
- tagfontobj(tagid(tagOrId))
- else
- tagfont_configure(tagid(tagOrId), {key=>value})
- end
- else
- _fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),
- "-#{key}", _get_eval_enc_str(value)))
- end
- end
- self
- end
-# def itemconfigure(tagOrId, key, value=None)
-# if key.kind_of? Hash
-# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(key)
-# else
-# tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
-# end
-# end
-# def itemconfigure(tagOrId, keys)
-# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(keys)
-# end
-
- def itemconfiginfo(tagOrId, key=nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- case key.to_s
- when 'coords'
- return ['coords', '', '', '', self.coords(tagOrId)]
- when 'dash', 'activedash', 'disableddash'
- conf = tk_split_simplelist(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}"))
- if conf[3] && conf[3] =~ /^[0-9]/
- conf[3] = list(conf[3])
- end
- if conf[4] && conf[4] =~ /^[0-9]/
- conf[4] = list(conf[4])
- end
- when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")))
- when 'font', 'kanjifont'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),"-#{key}")))
- conf[4] = tagfont_configinfo(tagid(tagOrId), conf[4])
- else
- conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")))
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId)))).collect{|conflist|
- conf = tk_split_simplelist(conflist)
- conf[0] = conf[0][1..-1]
- case conf[0]
- when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
- when 'dash', 'activedash', 'disableddash'
- if conf[3] && conf[3] =~ /^[0-9]/
- conf[3] = list(conf[3])
- end
- if conf[4] && conf[4] =~ /^[0-9]/
- conf[4] = list(conf[4])
- end
- else
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- if conf[4]
- if conf[4].index('{')
- conf[4] = tk_split_list(conf[4])
- else
- conf[4] = tk_tcl2ruby(conf[4])
- end
- end
- end
- conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
- conf
- }
-
- fontconf = ret.assoc('font')
- if fontconf
- ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
- fontconf[4] = tagfont_configinfo(tagid(tagOrId), fontconf[4])
- ret.push(fontconf)
- end
-
- ret << ['coords', '', '', '', self.coords(tagOrId)]
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- case key.to_s
- when 'coords'
- {'coords' => ['', '', '', self.coords(tagOrId)]}
- when 'dash', 'activedash', 'disableddash'
- conf = tk_split_simplelist(tk_send_without_enc('itemconfigure',
- tagid(tagOrId),
- "-#{key}"))
- if conf[3] && conf[3] =~ /^[0-9]/
- conf[3] = list(conf[3])
- end
- if conf[4] && conf[4] =~ /^[0-9]/
- conf[4] = list(conf[4])
- end
- when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")))
- when 'font', 'kanjifont'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),"-#{key}")))
- conf[4] = tagfont_configinfo(tagid(tagOrId), conf[4])
- else
- conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")))
- end
- key = conf.shift[1..-1]
- { key => conf }
- else
- ret = {}
- tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId)))).each{|conflist|
- conf = tk_split_simplelist(conflist)
- key = conf.shift[1..-1]
- case key
- when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
- when 'dash', 'activedash', 'disableddash'
- if conf[2] && conf[2] =~ /^[0-9]/
- conf[2] = list(conf[2])
- end
- if conf[3] && conf[3] =~ /^[0-9]/
- conf[3] = list(conf[3])
- end
- else
- if conf[2]
- if conf[2].index('{')
- conf[2] = tk_split_list(conf[2])
- else
- conf[2] = tk_tcl2ruby(conf[2])
- end
- end
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- end
- if conf.size == 1
- ret[key] = conf[0][1..-1] # alias info
- else
- ret[key] = conf
- end
- }
-
- fontconf = ret['font']
- if fontconf
- ret.delete('font')
- ret.delete('kanjifont')
- fontconf[3] = tagfont_configinfo(tagid(tagOrId), fontconf[3])
- ret['font'] = fontconf
- end
-
- ret['coords'] = ['', '', '', self.coords(tagOrId)]
-
- ret
- end
- end
- end
-
- def current_itemconfiginfo(tagOrId, key=nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- conf = itemconfiginfo(tagOrId, key)
- {conf[0] => conf[4]}
- else
- ret = {}
- itemconfiginfo(tagOrId).each{|conf|
- ret[conf[0]] = conf[4] if conf.size > 2
- }
- ret
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- ret = {}
- itemconfiginfo(tagOrId, key).each{|k, conf|
- ret[k] = conf[-1] if conf.kind_of?(Array)
- }
- ret
- end
- end
-=end
-
- def lower(tag, below=nil)
- if below
- tk_send_without_enc('lower', tagid(tag), tagid(below))
- else
- tk_send_without_enc('lower', tagid(tag))
- end
- self
- end
-
- def move(tag, x, y)
- tk_send_without_enc('move', tagid(tag), x, y)
- self
- end
-
- def postscript(keys)
- tk_send("postscript", *hash_kv(keys))
- end
-
- def raise(tag, above=nil)
- if above
- tk_send_without_enc('raise', tagid(tag), tagid(above))
- else
- tk_send_without_enc('raise', tagid(tag))
- end
- self
- end
-
- def scale(tag, x, y, xs, ys)
- tk_send_without_enc('scale', tagid(tag), x, y, xs, ys)
- self
- end
-
- def scan_mark(x, y)
- tk_send_without_enc('scan', 'mark', x, y)
- self
- end
- def scan_dragto(x, y)
- tk_send_without_enc('scan', 'dragto', x, y)
- self
- end
-
- def select(mode, *args)
- r = tk_send_without_enc('select', mode, *args)
- (mode == 'item')? TkcItem.id2obj(self, r): self
- end
- def select_adjust(tagOrId, index)
- select('adjust', tagid(tagOrId), index)
- end
- def select_clear
- select('clear')
- end
- def select_from(tagOrId, index)
- select('from', tagid(tagOrId), index)
- end
- def select_item
- select('item')
- end
- def select_to(tagOrId, index)
- select('to', tagid(tagOrId), index)
- end
-
- def itemtype(tag)
- TkcItem.type2class(tk_send('type', tagid(tag)))
- end
-end
-
-class TkcItem<TkObject
- extend Tk
- include TkcTagAccess
- extend TkItemFontOptkeys
- extend TkItemConfigOptkeys
-
- CItemTypeName = nil
- CItemTypeToClass = {}
- CItemID_TBL = TkCore::INTERP.create_table
-
- TkCore::INTERP.init_ip_env{ CItemID_TBL.clear }
-
- def TkcItem.type2class(type)
- CItemTypeToClass[type]
- end
-
- def TkcItem.id2obj(canvas, id)
- cpath = canvas.path
- return id unless CItemID_TBL[cpath]
- CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id
- end
-
- ########################################
- def self._parse_create_args(args)
- fontkeys = {}
- methodkeys = {}
- if args[-1].kind_of? Hash
- keys = _symbolkey2str(args.pop)
- if args.size == 0
- args = keys.delete('coords')
- unless args.kind_of?(Array)
- fail "coords parameter must be given by an Array"
- end
- end
-
- #['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
- # fontkeys[key] = keys.delete(key) if keys.key?(key)
- #}
- __item_font_optkeys(nil).each{|key|
- fkey = key.to_s
- fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
-
- fkey = "kanji#{key}"
- fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
-
- fkey = "latin#{key}"
- fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
-
- fkey = "ascii#{key}"
- fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
- }
-
- __item_methodcall_optkeys(nil).each{|key|
- key = key.to_s
- methodkeys[key] = keys.delete(key) if keys.key?(key)
- }
-
- __item_ruby2val_optkeys(nil).each{|key, method|
- key = key.to_s
- keys[key] = method.call(keys[key]) if keys.has_key?(key)
- }
-
- #args = args.flatten.concat(hash_kv(keys))
- args = args.flatten.concat(itemconfig_hash_kv(nil, keys))
- else
- args = args.flatten
- end
-
- [args, fontkeys]
- end
- private_class_method :_parse_create_args
-
- def self.create(canvas, *args)
- unless self::CItemTypeName
- fail RuntimeError, "#{self} is an abstract class"
- end
- args, fontkeys = _parse_create_args(args)
- idnum = tk_call_without_enc(canvas.path, 'create',
- self::CItemTypeName, *args)
- canvas.itemconfigure(idnum, fontkeys) unless fontkeys.empty?
- idnum.to_i # 'canvas item id' is an integer number
- end
- ########################################
-
- def initialize(parent, *args)
- #unless parent.kind_of?(TkCanvas)
- # fail ArgumentError, "expect TkCanvas for 1st argument"
- #end
- @parent = @c = parent
- @path = parent.path
-
- @id = create_self(*args) # an integer number as 'canvas item id'
- CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
- CItemID_TBL[@path][@id] = self
- end
- def create_self(*args)
- self.class.create(@c, *args) # return an integer number as 'canvas item id'
- end
- private :create_self
-
- def id
- @id
- end
-
- def exist?
- if @c.find_withtag(@id)
- true
- else
- false
- end
- end
-
- def delete
- @c.delete @id
- CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
- self
- end
- alias remove delete
- alias destroy delete
-end
-
-class TkcArc<TkcItem
- CItemTypeName = 'arc'.freeze
- CItemTypeToClass[CItemTypeName] = self
-end
-
-class TkcBitmap<TkcItem
- CItemTypeName = 'bitmap'.freeze
- CItemTypeToClass[CItemTypeName] = self
-end
-
-class TkcImage<TkcItem
- CItemTypeName = 'image'.freeze
- CItemTypeToClass[CItemTypeName] = self
-end
-
-class TkcLine<TkcItem
- CItemTypeName = 'line'.freeze
- CItemTypeToClass[CItemTypeName] = self
-end
-
-class TkcOval<TkcItem
- CItemTypeName = 'oval'.freeze
- CItemTypeToClass[CItemTypeName] = self
-end
-
-class TkcPolygon<TkcItem
- CItemTypeName = 'polygon'.freeze
- CItemTypeToClass[CItemTypeName] = self
-end
-
-class TkcRectangle<TkcItem
- CItemTypeName = 'rectangle'.freeze
- CItemTypeToClass[CItemTypeName] = self
-end
-
-class TkcText<TkcItem
- CItemTypeName = 'text'.freeze
- CItemTypeToClass[CItemTypeName] = self
- def self.create(canvas, *args)
- if args[-1].kind_of?(Hash)
- keys = _symbolkey2str(args.pop)
- txt = keys['text']
- keys['text'] = _get_eval_enc_str(txt) if txt
- args.push(keys)
- end
- super(canvas, *args)
- end
-end
-
-class TkcWindow<TkcItem
- CItemTypeName = 'window'.freeze
- CItemTypeToClass[CItemTypeName] = self
- def self.create(canvas, *args)
- if args[-1].kind_of?(Hash)
- keys = _symbolkey2str(args.pop)
- win = keys['window']
- # keys['window'] = win.epath if win.kind_of?(TkWindow)
- keys['window'] = _epath(win) if win
- args.push(keys)
- end
- super(canvas, *args)
- end
-end
diff --git a/ext/tk/lib/tk/canvastag.rb b/ext/tk/lib/tk/canvastag.rb
deleted file mode 100644
index a5650ee68b..0000000000
--- a/ext/tk/lib/tk/canvastag.rb
+++ /dev/null
@@ -1,375 +0,0 @@
-#
-# tk/canvastag.rb - methods for treating canvas tags
-#
-require 'tk'
-require 'tk/tagfont'
-
-module TkcTagAccess
- include TkComm
- include TkTreatTagFont
-end
-
-require 'tk/canvas'
-
-module TkcTagAccess
- def addtag(tag)
- @c.addtag(tag, 'withtag', @id)
- self
- end
-
- def bbox
- @c.bbox(@id)
- end
-
- #def bind(seq, cmd=Proc.new, *args)
- # @c.itembind(@id, seq, cmd, *args)
- # self
- #end
- def bind(seq, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- @c.itembind(@id, seq, cmd, *args)
- self
- end
-
- #def bind_append(seq, cmd=Proc.new, *args)
- # @c.itembind_append(@id, seq, cmd, *args)
- # self
- #end
- def bind_append(seq, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- @c.itembind_append(@id, seq, cmd, *args)
- self
- end
-
- def bind_remove(seq)
- @c.itembind_remove(@id, seq)
- self
- end
-
- def bindinfo(seq=nil)
- @c.itembindinfo(@id, seq)
- end
-
- def cget(option)
- @c.itemcget(@id, option)
- end
-
- def configure(key, value=None)
- @c.itemconfigure(@id, key, value)
- self
- end
-# def configure(keys)
-# @c.itemconfigure @id, keys
-# end
-
- def configinfo(key=nil)
- @c.itemconfiginfo(@id, key)
- end
-
- def current_configinfo(key=nil)
- @c.current_itemconfiginfo(@id, key)
- end
-
- def coords(*args)
- @c.coords(@id, *args)
- end
-
- def dchars(first, last=None)
- @c.dchars(@id, first, last)
- self
- end
-
- def dtag(tag_to_del=None)
- @c.dtag(@id, tag_to_del)
- self
- end
- alias deltag dtag
-
- def find
- @c.find('withtag', @id)
- end
- alias list find
-
- def focus
- @c.itemfocus(@id)
- end
-
- def gettags
- @c.gettags(@id)
- end
-
- def icursor(index)
- @c.icursor(@id, index)
- self
- end
-
- def index(idx)
- @c.index(@id, idx)
- end
-
- def insert(beforethis, string)
- @c.insert(@id, beforethis, string)
- self
- end
-
- def lower(belowthis=None)
- @c.lower(@id, belowthis)
- self
- end
-
- def move(xamount, yamount)
- @c.move(@id, xamount, yamount)
- self
- end
-
- def raise(abovethis=None)
- @c.raise(@id, abovethis)
- self
- end
-
- def scale(xorigin, yorigin, xscale, yscale)
- @c.scale(@id, xorigin, yorigin, xscale, yscale)
- self
- end
-
- def select_adjust(index)
- @c.select('adjust', @id, index)
- self
- end
- def select_from(index)
- @c.select('from', @id, index)
- self
- end
- def select_to(index)
- @c.select('to', @id, index)
- self
- end
-
- def itemtype
- @c.itemtype(@id)
- end
-
- # Following operators support logical expressions of canvas tags
- # (for Tk8.3+).
- # If tag1.path is 't1' and tag2.path is 't2', then
- # ltag = tag1 & tag2; ltag.path => "(t1)&&(t2)"
- # ltag = tag1 | tag2; ltag.path => "(t1)||(t2)"
- # ltag = tag1 ^ tag2; ltag.path => "(t1)^(t2)"
- # ltag = - tag1; ltag.path => "!(t1)"
- def & (tag)
- if tag.kind_of? TkObject
- TkcTagString.new(@c, '(' + @id + ')&&(' + tag.path + ')')
- else
- TkcTagString.new(@c, '(' + @id + ')&&(' + tag.to_s + ')')
- end
- end
-
- def | (tag)
- if tag.kind_of? TkObject
- TkcTagString.new(@c, '(' + @id + ')||(' + tag.path + ')')
- else
- TkcTagString.new(@c, '(' + @id + ')||(' + tag.to_s + ')')
- end
- end
-
- def ^ (tag)
- if tag.kind_of? TkObject
- TkcTagString.new(@c, '(' + @id + ')^(' + tag.path + ')')
- else
- TkcTagString.new(@c, '(' + @id + ')^(' + tag.to_s + ')')
- end
- end
-
- def -@
- TkcTagString.new(@c, '!(' + @id + ')')
- end
-end
-
-class TkcTag<TkObject
- include TkcTagAccess
-
- CTagID_TBL = TkCore::INTERP.create_table
- Tk_CanvasTag_ID = ['ctag'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ CTagID_TBL.clear }
-
- def TkcTag.id2obj(canvas, id)
- cpath = canvas.path
- return id unless CTagID_TBL[cpath]
- CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id
- end
-
- def initialize(parent, mode=nil, *args)
- #unless parent.kind_of?(TkCanvas)
- # fail ArgumentError, "expect TkCanvas for 1st argument"
- #end
- @c = parent
- @cpath = parent.path
- # @path = @id = Tk_CanvasTag_ID.join('')
- @path = @id = Tk_CanvasTag_ID.join(TkCore::INTERP._ip_id_)
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- Tk_CanvasTag_ID[1].succ!
- if mode
- tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
- end
- end
- def id
- @id
- end
-
- def exist?
- if @c.find_withtag(@id)
- true
- else
- false
- end
- end
-
- def delete
- @c.delete @id
- CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath]
- self
- end
- alias remove delete
- alias destroy delete
-
- def set_to_above(target)
- @c.addtag_above(@id, target)
- self
- end
- alias above set_to_above
-
- def set_to_all
- @c.addtag_all(@id)
- self
- end
- alias all set_to_all
-
- def set_to_below(target)
- @c.addtag_below(@id, target)
- self
- end
- alias below set_to_below
-
- def set_to_closest(x, y, halo=None, start=None)
- @c.addtag_closest(@id, x, y, halo, start)
- self
- end
- alias closest set_to_closest
-
- def set_to_enclosed(x1, y1, x2, y2)
- @c.addtag_enclosed(@id, x1, y1, x2, y2)
- self
- end
- alias enclosed set_to_enclosed
-
- def set_to_overlapping(x1, y1, x2, y2)
- @c.addtag_overlapping(@id, x1, y1, x2, y2)
- self
- end
- alias overlapping set_to_overlapping
-
- def set_to_withtag(target)
- @c.addtag_withtag(@id, target)
- self
- end
- alias withtag set_to_withtag
-end
-
-class TkcTagString<TkcTag
- def self.new(parent, name, *args)
- if CTagID_TBL[parent.path] && CTagID_TBL[parent.path][name]
- return CTagID_TBL[parent.path][name]
- else
- super(parent, name, *args)
- end
- end
-
- def initialize(parent, name, mode=nil, *args)
- #unless parent.kind_of?(TkCanvas)
- # fail ArgumentError, "expect TkCanvas for 1st argument"
- #end
- @c = parent
- @cpath = parent.path
- @path = @id = name
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- if mode
- tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
- end
- end
-end
-TkcNamedTag = TkcTagString
-
-class TkcTagAll<TkcTag
- def initialize(parent)
- #unless parent.kind_of?(TkCanvas)
- # fail ArgumentError, "expect TkCanvas for 1st argument"
- #end
- @c = parent
- @cpath = parent.path
- @path = @id = 'all'
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- end
-end
-
-class TkcTagCurrent<TkcTag
- def initialize(parent)
- #unless parent.kind_of?(TkCanvas)
- # fail ArgumentError, "expect TkCanvas for 1st argument"
- #end
- @c = parent
- @cpath = parent.path
- @path = @id = 'current'
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- end
-end
-
-class TkcGroup<TkcTag
- Tk_cGroup_ID = ['tkcg'.freeze, '00000'.taint].freeze
- #def create_self(parent, *args)
- def initialize(parent, *args)
- #unless parent.kind_of?(TkCanvas)
- # fail ArgumentError, "expect TkCanvas for 1st argument"
- #end
- @c = parent
- @cpath = parent.path
- # @path = @id = Tk_cGroup_ID.join('')
- @path = @id = Tk_cGroup_ID.join(TkCore::INTERP._ip_id_)
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- Tk_cGroup_ID[1].succ!
- include(*args) if args != []
- end
- #private :create_self
-
- def include(*tags)
- for i in tags
- #i.addtag(@id)
- @c.addtag_withtag(@id, i)
- end
- self
- end
- alias add include
-
- def exclude(*tags)
- for i in tags
- #i.dtag(@id)
- @c.dtag(i, @id)
- end
- self
- end
-end
diff --git a/ext/tk/lib/tk/checkbutton.rb b/ext/tk/lib/tk/checkbutton.rb
deleted file mode 100644
index d76d99c0f2..0000000000
--- a/ext/tk/lib/tk/checkbutton.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# tk/checkbutton.rb : treat checkbutton widget
-#
-require 'tk'
-require 'tk/radiobutton'
-
-class TkCheckButton<TkRadioButton
- TkCommandNames = ['checkbutton'.freeze].freeze
- WidgetClassName = 'Checkbutton'.freeze
- WidgetClassNames[WidgetClassName] = self
- #def create_self(keys)
- # if keys and keys != None
- # tk_call_without_enc('checkbutton', @path, *hash_kv(keys, true))
- # else
- # tk_call_without_enc('checkbutton', @path)
- # end
- #end
- #private :create_self
-
- def toggle
- tk_send_without_enc('toggle')
- self
- end
-end
-TkCheckbutton = TkCheckButton
diff --git a/ext/tk/lib/tk/clipboard.rb b/ext/tk/lib/tk/clipboard.rb
deleted file mode 100644
index d4205a5c28..0000000000
--- a/ext/tk/lib/tk/clipboard.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-#
-# tk/clipboard.rb : methods to treat clipboard
-#
-require 'tk'
-
-module TkClipboard
- include Tk
- extend Tk
-
- TkCommandNames = ['clipboard'.freeze].freeze
-
- def self.clear(win=nil)
- if win
- tk_call_without_enc('clipboard', 'clear', '-displayof', win)
- else
- tk_call_without_enc('clipboard', 'clear')
- end
- end
- def self.clear_on_display(win)
- tk_call_without_enc('clipboard', 'clear', '-displayof', win)
- end
-
- def self.get(type=nil)
- if type
- tk_call_without_enc('clipboard', 'get', '-type', type)
- else
- tk_call_without_enc('clipboard', 'get')
- end
- end
- def self.get_on_display(win, type=nil)
- if type
- tk_call_without_enc('clipboard', 'get', '-displayof', win, '-type', type)
- else
- tk_call_without_enc('clipboard', 'get', '-displayof', win)
- end
- end
-
- def self.set(data, keys=nil)
- clear
- append(data, keys)
- end
- def self.set_on_display(win, data, keys=nil)
- clear(win)
- append_on_display(win, data, keys)
- end
-
- def self.append(data, keys=nil)
- args = ['clipboard', 'append']
- args.concat(hash_kv(keys))
- args.concat(['--', data])
- tk_call(*args)
- end
- def self.append_on_display(win, data, keys=nil)
- args = ['clipboard', 'append', '-displayof', win]
- args.concat(hash_kv(keys))
- args.concat(['--', data])
- tk_call(*args)
- end
-
- def clear
- TkClipboard.clear_on_display(self)
- self
- end
- def get(type=nil)
- TkClipboard.get_on_display(self, type)
- end
- def set(data, keys=nil)
- TkClipboard.set_on_display(self, data, keys)
- self
- end
- def append(data, keys=nil)
- TkClipboard.append_on_display(self, data, keys)
- self
- end
-end
diff --git a/ext/tk/lib/tk/clock.rb b/ext/tk/lib/tk/clock.rb
deleted file mode 100644
index 4e9438f5ab..0000000000
--- a/ext/tk/lib/tk/clock.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# tk/clock.rb : methods for clock command
-#
-require 'tk'
-
-module Tk
- module Clock
- include Tk
- extend TkCore
-
- def self.add(clk, *args)
- tk_call_without_enc('clock','add', clk, *args).to_i
- end
-
- def self.clicks(ms=nil)
- ms = ms.to_s if ms.kind_of?(Symbol)
- case ms
- when nil, ''
- tk_call_without_enc('clock','clicks').to_i
- when /^mic/
- tk_call_without_enc('clock','clicks','-microseconds').to_i
- when /^mil/
- tk_call_without_enc('clock','clicks','-milliseconds').to_i
- else
- tk_call_without_enc('clock','clicks','-milliseconds').to_i
- end
- end
-
- def self.format(clk, form=nil)
- if form
- tk_call('clock','format',clk,'-format',form)
- else
- tk_call('clock','format',clk)
- end
- end
-
- def self.formatGMT(clk, form=nil)
- if form
- tk_call('clock','format',clk,'-format',form,'-gmt','1')
- else
- tk_call('clock','format',clk,'-gmt','1')
- end
- end
-
- def self.scan(str, base=nil)
- if base
- tk_call('clock','scan',str,'-base',base).to_i
- else
- tk_call('clock','scan',str).to_i
- end
- end
-
- def self.scanGMT(str, base=nil)
- if base
- tk_call('clock','scan',str,'-base',base,'-gmt','1').to_i
- else
- tk_call('clock','scan',str,'-gmt','1').to_i
- end
- end
-
- def self.seconds
- tk_call_without_enc('clock','seconds').to_i
- end
- def self.milliseconds
- tk_call_without_enc('clock','milliseconds').to_i
- end
- def self.microseconds
- tk_call_without_enc('clock','microseconds').to_i
- end
- end
-end
diff --git a/ext/tk/lib/tk/composite.rb b/ext/tk/lib/tk/composite.rb
deleted file mode 100644
index eaed8ed363..0000000000
--- a/ext/tk/lib/tk/composite.rb
+++ /dev/null
@@ -1,394 +0,0 @@
-#
-# tk/composite.rb :
-#
-require 'tk'
-
-module TkComposite
- include Tk
- extend Tk
-
-=begin
- def initialize(parent=nil, *args)
- @delegates = {}
- @option_methods = {}
- @option_setting = {}
-
- if parent.kind_of? Hash
- keys = _symbolkey2str(parent)
- parent = keys.delete('parent')
- @frame = TkFrame.new(parent)
- @path = @epath = @frame.path
- initialize_composite(keys)
- else
- @frame = TkFrame.new(parent)
- @path = @epath = @frame.path
- initialize_composite(*args)
- end
- end
-=end
-
- def _choice_classname_of_baseframe
- base_class_name = nil
-
- klass = WidgetClassNames[self.class::WidgetClassName]
-
- if klass
- # WidgetClassName is a known class
- if klass <= TkFrame || klass < TkComposite
- # klass is valid for the base frame
- if self.class <= klass
- # use my classname
- base_class_name = self.class.name
- if base_class_name == ''
- # anonymous class -> use ancestor's name
- base_class_name = klass.name
- end
- else
- # not subclass -> use WidgetClassName
- base_class_name = klass.name
- end
-
- else
- # klass is invalid for the base frame
- if self.class < TkFrame || self.class.superclass < TkComposite
- # my class name is valid for the base frame -> use my classname
- base_class_name = self.class.name
- if base_class_name == ''
- # anonymous class -> use TkFrame
- base_class_name = nil
- end
- else
- # no idea for the base frame -> use TkFrame
- base_class_name = nil
- end
- end
-
- elsif self.class::WidgetClassName && ! self.class::WidgetClassName.empty?
- # unknown WidgetClassName is defined -> use it for the base frame
- base_class_name = self.class::WidgetClassName
-
- else
- # no valid WidgetClassName
- if self.class < TkFrame || self.class.superclass < TkComposite
- # my class name is valid for the base frame -> use my classname
- base_class_name = self.class.name
- if base_class_name == ''
- # anonymous class -> use TkFrame
- base_class_name = nil
- end
- else
- # no idea for the base frame -> use TkFrame
- base_class_name = nil
- end
- end
-
- base_class_name
- end
- private :_choice_classname_of_baseframe
-
- # def initialize(parent=nil, *args)
- def initialize(*args)
- @delegates = {}
- @option_methods = {}
- @option_setting = {}
-
- if args[-1].kind_of?(Hash)
- keys = _symbolkey2str(args.pop)
- else
- keys = {}
- end
- parent = args.shift
- parent = keys.delete('parent') if keys.has_key?('parent')
-
- if keys.key?('classname')
- keys['class'] = keys.delete('classname')
- end
- if (base_class_name = (keys.delete('class')).to_s).empty?
- base_class_name = _choice_classname_of_baseframe
- end
-
- if base_class_name
- @frame = TkFrame.new(parent, :class=>base_class_name)
- else
- @frame = TkFrame.new(parent)
- end
- @path = @epath = @frame.path
-
- args.push(keys) unless keys.empty?
- initialize_composite(*args)
- end
-
- def database_classname
- @frame.database_classname
- end
-
- def database_class
- @frame.database_class
- end
-
- def epath
- @epath
- end
-
- def initialize_composite(*args) end
- private :initialize_composite
-
- def option_methods(*opts)
- opts.each{|m_set, m_cget, m_info|
- m_set = m_set.to_s
- m_cget = m_set if !m_cget && self.method(m_set).arity == -1
- m_cget = m_cget.to_s if m_cget
- m_info = m_info.to_s if m_info
- @option_methods[m_set] = {
- :set => m_set, :cget => m_cget, :info => m_info
- }
- }
- end
-
- def delegate_alias(alias_opt, option, *wins)
- if wins.length == 0
- fail ArgumentError, "target widgets are not given"
- end
- if alias_opt != option && (alias_opt == 'DEFAULT' || option == 'DEFAULT')
- fail ArgumentError, "cannot alias 'DEFAULT' option"
- end
- alias_opt = alias_opt.to_s
- option = option.to_s
- if @delegates[alias_opt].kind_of?(Array)
- if (elem = @delegates[alias_opt].assoc(option))
- wins.each{|w| elem[1].push(w)}
- else
- @delegates[alias_opt] << [option, wins]
- end
- else
- @delegates[alias_opt] = [ [option, wins] ]
- end
- end
-
- def delegate(option, *wins)
- delegate_alias(option, option, *wins)
- end
-
- def cget(slot)
- slot = slot.to_s
-
- if @option_methods.include?(slot)
- if @option_methods[slot][:cget]
- return self.__send__(@option_methods[slot][:cget])
- else
- if @option_setting[slot]
- return @option_setting[slot]
- else
- return ''
- end
- end
- end
-
- tbl = @delegates[slot]
- tbl = @delegates['DEFAULT'] unless tbl
-
- begin
- if tbl
- opt, wins = tbl[-1]
- opt = slot if opt == 'DEFAULT'
- if wins && wins[-1]
- return wins[-1].cget(opt)
- end
- end
- rescue
- end
-
- super(slot)
- end
-
- def configure(slot, value=None)
- if slot.kind_of? Hash
- slot.each{|slot,value| configure slot, value}
- return self
- end
-
- slot = slot.to_s
-
- if @option_methods.include?(slot)
- unless @option_methods[slot][:cget]
- if value.kind_of?(Symbol)
- @option_setting[slot] = value.to_s
- else
- @option_setting[slot] = value
- end
- end
- return self.__send__(@option_methods[slot][:set], value)
- end
-
- tbl = @delegates[slot]
- tbl = @delegates['DEFAULT'] unless tbl
-
- begin
- if tbl
- last = nil
- tbl.each{|opt, wins|
- opt = slot if opt == 'DEFAULT'
- wins.each{|w| last = w.configure(opt, value)}
- }
- return last
- end
- rescue
- end
-
- super(slot, value)
- end
-
- def configinfo(slot = nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- slot = slot.to_s
- if @option_methods.include?(slot)
- if @option_methods[slot][:info]
- return self.__send__(@option_methods[slot][:info])
- else
- return [slot, '', '', '', self.cget(slot)]
- end
- end
-
- tbl = @delegates[slot]
- tbl = @delegates['DEFAULT'] unless tbl
-
- begin
- if tbl
- if tbl.length == 1
- opt, wins = tbl[0]
- if slot == opt || opt == 'DEFAULT'
- return wins[-1].configinfo(slot)
- else
- info = wins[-1].configinfo(opt)
- info[0] = slot
- return info
- end
- else
- opt, wins = tbl[-1]
- return [slot, '', '', '', wins[-1].cget(opt)]
- end
- end
- rescue
- end
-
- super(slot)
-
- else # slot == nil
- info_list = super(slot)
-
- tbl = @delegates['DEFAULT']
- if tbl
- wins = tbl[0][1]
- if wins && wins[-1]
- wins[-1].configinfo.each{|info|
- slot = info[0]
- info_list.delete_if{|i| i[0] == slot} << info
- }
- end
- end
-
- @delegates.each{|slot, tbl|
- next if slot == 'DEFAULT'
- if tbl.length == 1
- opt, wins = tbl[0]
- next unless wins && wins[-1]
- if slot == opt
- info_list.delete_if{|i| i[0] == slot} <<
- wins[-1].configinfo(slot)
- else
- info = wins[-1].configinfo(opt)
- info[0] = slot
- info_list.delete_if{|i| i[0] == slot} << info
- end
- else
- opt, wins = tbl[-1]
- info_list.delete_if{|i| i[0] == slot} <<
- [slot, '', '', '', wins[-1].cget(opt)]
- end
- }
-
- @option_methods.each{|slot, m|
- if m[:info]
- info = self.__send__(m[:info])
- else
- info = [slot, '', '', '', self.cget(slot)]
- end
- info_list.delete_if{|i| i[0] == slot} << info
- }
-
- info_list
- end
-
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- slot = slot.to_s
- if @option_methods.include?(slot)
- if @option_methods[slot][:info]
- return self.__send__(@option_methods[slot][:info])
- else
- return {slot => ['', '', '', self.cget(slot)]}
- end
- end
-
- tbl = @delegates[slot]
- tbl = @delegates['DEFAULT'] unless tbl
-
- begin
- if tbl
- if tbl.length == 1
- opt, wins = tbl[0]
- if slot == opt || opt == 'DEFAULT'
- return wins[-1].configinfo(slot)
- else
- return {slot => wins[-1].configinfo(opt)[opt]}
- end
- else
- opt, wins = tbl[-1]
- return {slot => ['', '', '', wins[-1].cget(opt)]}
- end
- end
- rescue
- end
-
- super(slot)
-
- else # slot == nil
- info_list = super(slot)
-
- tbl = @delegates['DEFAULT']
- if tbl
- wins = tbl[0][1]
- info_list.update(wins[-1].configinfo) if wins && wins[-1]
- end
-
- @delegates.each{|slot, tbl|
- next if slot == 'DEFAULT'
- if tbl.length == 1
- opt, wins = tbl[0]
- next unless wins && wins[-1]
- if slot == opt
- info_list.update(wins[-1].configinfo(slot))
- else
- info_list.update({slot => wins[-1].configinfo(opt)[opt]})
- end
- else
- opt, wins = tbl[-1]
- info_list.update({slot => ['', '', '', wins[-1].cget(opt)]})
- end
- }
-
- @option_methods.each{|slot, m|
- if m[:info]
- info = self.__send__(m[:info])
- else
- info = {slot => ['', '', '', self.cget(slot)]}
- end
- info_list.update(info)
- }
-
- info_list
- end
- end
- end
-end
diff --git a/ext/tk/lib/tk/console.rb b/ext/tk/lib/tk/console.rb
deleted file mode 100644
index 26ce262caa..0000000000
--- a/ext/tk/lib/tk/console.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# tk/console.rb : control the console on system without a real console
-#
-require 'tk'
-
-module TkConsole
- include Tk
- extend Tk
-
- TkCommandNames = ['console'.freeze, 'consoleinterp'.freeze].freeze
-
- def self.create
- TkCore::INTERP._create_console
- end
- self.create # initialize console
-
- def self.title(str=None)
- tk_call 'console', str
- end
- def self.hide
- tk_call_without_enc('console', 'hide')
- end
- def self.show
- tk_call_without_enc('console', 'show')
- end
- def self.eval(tcl_script)
- #
- # supports a Tcl script only
- # I have no idea to support a Ruby script seamlessly.
- #
- _fromUTF8(tk_call_without_enc('console', 'eval',
- _get_eval_enc_str(tcl_script)))
- end
- def self.maininterp_eval(tcl_script)
- #
- # supports a Tcl script only
- # I have no idea to support a Ruby script seamlessly.
- #
- _fromUTF8(tk_call_without_enc('consoleinterp', 'eval',
- _get_eval_enc_str(tcl_script)))
-
- end
- def self.maininterp_record(tcl_script)
- #
- # supports a Tcl script only
- # I have no idea to support a Ruby script seamlessly.
- #
- _fromUTF8(tk_call_without_enc('consoleinterp', 'record',
- _get_eval_enc_str(tcl_script)))
-
- end
-end
diff --git a/ext/tk/lib/tk/dialog.rb b/ext/tk/lib/tk/dialog.rb
deleted file mode 100644
index 180da101e3..0000000000
--- a/ext/tk/lib/tk/dialog.rb
+++ /dev/null
@@ -1,326 +0,0 @@
-#
-# tk/dialog.rb : create dialog boxes
-#
-require 'tk'
-require 'tk/variable.rb'
-
-class TkDialogObj < TkWindow
- extend Tk
-
- TkCommandNames = ['tk_dialog'.freeze].freeze
-
- def self.show(*args)
- dlog = self.new(*args)
- dlog.show
- dlog
- end
-
- def _set_button_config(configs)
- set_config = proc{|c,i|
- if $VERBOSE && (c.has_key?('command') || c.has_key?(:command))
- STDERR.print("Warning: cannot give a command option " +
- "to the dialog button#{i}. It was removed.\n")
- end
- c.delete('command'); c.delete(:command)
- # @config << Kernel.format("%s.button%s configure %s; ",
- # @path, i, hash_kv(c).join(' '))
- # @config << @path+'.button'+i.to_s+' configure '+hash_kv(c).join(' ')+'; '
- @config << @path+'.button'+i.to_s+' configure '+
- array2tk_list(hash_kv(c))+'; '
- }
- case configs
- when Proc
- @buttons.each_index{|i|
- if (c = configs.call(i)).kind_of?(Hash)
- set_config.call(c,i)
- end
- }
-
- when Array
- @buttons.each_index{|i|
- if (c = configs[i]).kind_of?(Hash)
- set_config.call(c,i)
- end
- }
-
- when Hash
- @buttons.each_with_index{|s,i|
- if (c = configs[s]).kind_of?(Hash)
- set_config.call(c,i)
- end
- }
- end
- # @config = 'after idle {' + @config + '};' if @config != ""
- @config = array2tk_list(['after', 'idle', @config]) << ';' if @config != ""
- end
- private :_set_button_config
-
- # initialize tk_dialog
- def create_self(keys)
- # @var = TkVariable.new
- @val = nil
-
- @title = title
-
- @message = message
- @message_config = message_config
- @msgframe_config = msgframe_config
-
- @bitmap = bitmap
- @bitmap_config = message_config
-
- @default_button = default_button
-
- @buttons = buttons
- @button_configs = proc{|num| button_configs(num)}
- @btnframe_config = btnframe_config
-
- #@config = "puts [winfo children .w0000];"
- @config = ""
-
- @command = prev_command
-
- if keys.kind_of?(Hash)
- @title = keys['title'] if keys.key? 'title'
- @message = keys['message'] if keys.key? 'message'
- @bitmap = keys['bitmap'] if keys.key? 'bitmap'
- # @bitmap = '{}' if @bitmap == nil || @bitmap == ""
- @bitmap = '' unless @bitmap
- @default_button = keys['default'] if keys.key? 'default'
- @buttons = keys['buttons'] if keys.key? 'buttons'
-
- @command = keys['prev_command'] if keys.key? 'prev_command'
-
- @message_config = keys['message_config'] if keys.key? 'message_config'
- @msgframe_config = keys['msgframe_config'] if keys.key? 'msgframe_config'
- @bitmap_config = keys['bitmap_config'] if keys.key? 'bitmap_config'
- @button_configs = keys['button_configs'] if keys.key? 'button_configs'
- @btnframe_config = keys['btnframe_config'] if keys.key? 'btnframe_config'
- end
-
- #if @title.include? ?\s
- # @title = '{' + @title + '}'
- #end
-
- if @buttons.kind_of?(Array)
- _set_button_config(@buttons.collect{|cfg|
- (cfg.kind_of? Array)? cfg[1]: nil})
- @buttons = @buttons.collect{|cfg| (cfg.kind_of? Array)? cfg[0]: cfg}
- end
- if @buttons.kind_of?(Hash)
- _set_button_config(@buttons)
- @buttons = @buttons.keys
- end
- @buttons = tk_split_simplelist(@buttons) if @buttons.kind_of?(String)
- @buttons = [] unless @buttons
-=begin
- @buttons = @buttons.collect{|s|
- if s.kind_of?(Array)
- s = s.join(' ')
- end
- if s.include? ?\s
- '{' + s + '}'
- else
- s
- end
- }
-=end
-
- if @message_config.kind_of?(Hash)
- # @config << Kernel.format("%s.msg configure %s;",
- # @path, hash_kv(@message_config).join(' '))
- # @config << @path+'.msg configure '+hash_kv(@message_config).join(' ')+';'
- @config << @path+'.msg configure '+
- array2tk_list(hash_kv(@message_config))+';'
- end
-
- if @msgframe_config.kind_of?(Hash)
- # @config << Kernel.format("%s.top configure %s;",
- # @path, hash_kv(@msgframe_config).join(' '))
- # @config << @path+'.top configure '+hash_kv(@msgframe_config).join(' ')+';'
- @config << @path+'.top configure '+
- array2tk_list(hash_kv(@msgframe_config))+';'
- end
-
- if @btnframe_config.kind_of?(Hash)
- # @config << Kernel.format("%s.bot configure %s;",
- # @path, hash_kv(@btnframe_config).join(' '))
- # @config << @path+'.bot configure '+hash_kv(@btnframe_config).join(' ')+';'
- @config << @path+'.bot configure '+
- array2tk_list(hash_kv(@btnframe_config))+';'
- end
-
- if @bitmap_config.kind_of?(Hash)
- # @config << Kernel.format("%s.bitmap configure %s;",
- # @path, hash_kv(@bitmap_config).join(' '))
- # @config << @path+'.bitmap configure '+hash_kv(@bitmap_config).join(' ')+';'
- @config << @path+'.bitmap configure '+
- array2tk_list(hash_kv(@bitmap_config))+';'
- end
-
- _set_button_config(@button_configs) if @button_configs
- end
- private :create_self
-
- def show
- # if @command.kind_of?(Proc)
- if TkComm._callback_entry?(@command)
- @command.call(self)
- end
-
- if @default_button.kind_of?(String)
- default_button = @buttons.index(@default_button)
- else
- default_button = @default_button
- end
- # default_button = '{}' if default_button == nil
- default_button = '' if default_button == nil
- #Tk.ip_eval('eval {global '+@var.id+';'+@config+
- # 'set '+@var.id+' [tk_dialog '+
- # @path+" "+@title+" {#{@message}} "+@bitmap+" "+
- # String(default_button)+" "+@buttons.join(' ')+']}')
- Tk.ip_eval(@config)
- # @val = Tk.ip_eval('tk_dialog ' + @path + ' ' + @title +
- # ' {' + @message + '} ' + @bitmap + ' ' +
- # String(default_button) + ' ' + @buttons.join(' ')).to_i
- # @val = Tk.ip_eval(self.class::TkCommandNames[0] + ' ' + @path + ' ' +
- # @title + ' {' + @message + '} ' + @bitmap + ' ' +
- # String(default_button) + ' ' + @buttons.join(' ')).to_i
- @val = Tk.ip_eval(array2tk_list([
- self.class::TkCommandNames[0],
- @path, @title, @message, @bitmap,
- String(default_button)
- ].concat(@buttons))).to_i
- end
-
- def value
- # @var.value.to_i
- @val
- end
-
- def name
- (@val)? @buttons[@val]: nil
- end
-
- ############################################################
- # #
- # following methods should be overridden for each dialog #
- # #
- ############################################################
- private
-
- def title
- # returns a title string of the dialog window
- return "DIALOG"
- end
- def message
- # returns a message text to display on the dialog
- return "MESSAGE"
- end
- def message_config
- # returns a Hash {option=>value, ...} for the message text
- return nil
- end
- def msgframe_config
- # returns a Hash {option=>value, ...} for the message text frame
- return nil
- end
- def bitmap
- # returns a bitmap name or a bitmap file path
- # (@ + path ; e.g. '@/usr/share/bitmap/sample.xbm')
- return "info"
- end
- def bitmap_config
- # returns nil or a Hash {option=>value, ...} for the bitmap
- return nil
- end
- def default_button
- # returns a default button's number or name
- # if nil or null string, set no-default
- return 0
- end
- def buttons
- #return "BUTTON1 BUTTON2"
- return ["BUTTON1", "BUTTON2"]
- end
- def button_configs(num)
- # returns nil / Proc / Array or Hash (see _set_button_config)
- return nil
- end
- def btnframe_config
- # returns nil or a Hash {option=>value, ...} for the button frame
- return nil
- end
- def prev_command
- # returns nil or a Proc
- return nil
- end
-end
-TkDialog2 = TkDialogObj
-
-#
-# TkDialog : with showing at initialize
-#
-class TkDialog < TkDialogObj
- def self.show(*args)
- self.new(*args)
- end
-
- def initialize(*args)
- super(*args)
- show
- end
-end
-
-
-#
-# dialog for warning
-#
-class TkWarningObj < TkDialogObj
- def initialize(parent = nil, mes = nil)
- if !mes
- if parent.kind_of?(TkWindow)
- mes = ""
- else
- mes = parent.to_s
- parent = nil
- end
- end
- super(parent, :message=>mes)
- end
-
- def show(mes = nil)
- mes_bup = @message
- @message = mes if mes
- ret = super()
- @message = mes_bup
- ret
- end
-
- #######
- private
-
- def title
- return "WARNING";
- end
- def bitmap
- return "warning";
- end
- def default_button
- return 0;
- end
- def buttons
- return "OK";
- end
-end
-TkWarning2 = TkWarningObj
-
-class TkWarning < TkWarningObj
- def self.show(*args)
- self.new(*args)
- end
- def initialize(*args)
- super(*args)
- show
- end
-end
diff --git a/ext/tk/lib/tk/encodedstr.rb b/ext/tk/lib/tk/encodedstr.rb
deleted file mode 100644
index 797e514a4c..0000000000
--- a/ext/tk/lib/tk/encodedstr.rb
+++ /dev/null
@@ -1,111 +0,0 @@
-#
-# tk/encodedstr.rb : Tk::EncodedString class
-#
-require 'tk'
-
-###########################################
-# string with Tcl's encoding
-###########################################
-module Tk
- class EncodedString < String
- Encoding = nil
-
- def self.subst_utf_backslash(str)
- # str.gsub(/\\u([0-9A-Fa-f]{1,4})/){[$1.hex].pack('U')}
- TclTkLib._subst_UTF_backslash(str)
- end
- def self.utf_backslash(str)
- self.subst_utf_backslash(str)
- end
-
- def self.subst_tk_backslash(str)
- TclTkLib._subst_Tcl_backslash(str)
- end
-
- def self.utf_to_backslash_sequence(str)
- str.unpack('U*').collect{|c|
- if c <= 0xFF # ascii character
- c.chr
- else
- format('\u%X', c)
- end
- }.join('')
- end
- def self.utf_to_backslash(str)
- self.utf_to_backslash_sequence(str)
- end
-
- def self.to_backslash_sequence(str)
- str.unpack('U*').collect{|c|
- if c <= 0x1F # control character
- case c
- when 0x07; '\a'
- when 0x08; '\b'
- when 0x09; '\t'
- when 0x0a; '\n'
- when 0x0b; '\v'
- when 0x0c; '\f'
- when 0x0d; '\r'
- else
- format('\x%02X', c)
- end
- elsif c <= 0xFF # ascii character
- c.chr
- else
- format('\u%X', c)
- end
- }.join('')
- end
-
- def self.new_with_utf_backslash(str, enc = nil)
- self.new('', enc).replace(self.subst_utf_backslash(str))
- end
-
- def self.new_without_utf_backslash(str, enc = nil)
- self.new('', enc).replace(str)
- end
-
- def initialize(str, enc = nil)
- super(str)
- # @encoding = ( enc ||
- # ((self.class::Encoding)?
- # self.class::Encoding : Tk.encoding_system) )
- @encoding = ( enc ||
- ((self.class::Encoding)?
- self.class::Encoding :
- ((Tk.encoding)? Tk.encoding : Tk.encoding_system) ) )
- end
-
- attr_reader :encoding
- end
- # def Tk.EncodedString(str, enc = nil)
- # Tk::EncodedString.new(str, enc)
- # end
-
- ##################################
-
- class BinaryString < EncodedString
- Encoding = 'binary'.freeze
- end
- # def Tk.BinaryString(str)
- # Tk::BinaryString.new(str)
- # end
-
- ##################################
-
- class UTF8_String < EncodedString
- Encoding = 'utf-8'.freeze
- def self.new(str)
- super(self.subst_utf_backslash(str))
- end
-
- def to_backslash_sequence
- Tk::EncodedString.utf_to_backslash_sequence(self)
- end
- alias to_backslash to_backslash_sequence
- end
- # def Tk.UTF8_String(str)
- # Tk::UTF8_String.new(str)
- # end
-
-end
diff --git a/ext/tk/lib/tk/entry.rb b/ext/tk/lib/tk/entry.rb
deleted file mode 100644
index 4ac3f28229..0000000000
--- a/ext/tk/lib/tk/entry.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-#
-# tk/entry.rb - Tk entry classes
-# $Date$
-# by Yukihiro Matsumoto <matz@caelum.co.jp>
-
-require 'tk'
-require 'tk/label'
-require 'tk/scrollable'
-require 'tk/validation'
-
-class TkEntry<TkLabel
- include X_Scrollable
- include TkValidation
-
- TkCommandNames = ['entry'.freeze].freeze
- WidgetClassName = 'Entry'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- #def create_self(keys)
- # super(__conv_vcmd_on_hash_kv(keys))
- #end
- #private :create_self
-
- def __strval_optkeys
- super() + ['show', 'disabledbackground', 'readonlybackground']
- end
- private :__strval_optkeys
-
- def bbox(index)
- list(tk_send_without_enc('bbox', index))
- end
- def cursor
- number(tk_send_without_enc('index', 'insert'))
- end
- alias icursor cursor
- def cursor=(index)
- tk_send_without_enc('icursor', index)
- #self
- index
- end
- alias icursor= cursor=
- def index(idx)
- number(tk_send_without_enc('index', idx))
- end
- def insert(pos,text)
- tk_send_without_enc('insert', pos, _get_eval_enc_str(text))
- self
- end
- def delete(first, last=None)
- tk_send_without_enc('delete', first, last)
- self
- end
- def mark(pos)
- tk_send_without_enc('scan', 'mark', pos)
- self
- end
- def dragto(pos)
- tk_send_without_enc('scan', 'dragto', pos)
- self
- end
- def selection_adjust(index)
- tk_send_without_enc('selection', 'adjust', index)
- self
- end
- def selection_clear
- tk_send_without_enc('selection', 'clear')
- self
- end
- def selection_from(index)
- tk_send_without_enc('selection', 'from', index)
- self
- end
- def selection_present()
- bool(tk_send_without_enc('selection', 'present'))
- end
- def selection_range(s, e)
- tk_send_without_enc('selection', 'range', s, e)
- self
- end
- def selection_to(index)
- tk_send_without_enc('selection', 'to', index)
- self
- end
-
- def invoke_validate
- bool(tk_send_without_enc('validate'))
- end
- def validate(mode = nil)
- if mode
- configure 'validate', mode
- else
- invoke_validate
- end
- end
-
- def value
- _fromUTF8(tk_send_without_enc('get'))
- end
- def value= (val)
- tk_send_without_enc('delete', 0, 'end')
- tk_send_without_enc('insert', 0, _get_eval_enc_str(val))
- val
- end
- alias get value
- alias set value=
-
- def [](*args)
- self.value[*args]
- end
- def []=(*args)
- val = args.pop
- str = self.value
- str[*args] = val
- self.value = str
- val
- end
-end
diff --git a/ext/tk/lib/tk/event.rb b/ext/tk/lib/tk/event.rb
deleted file mode 100644
index 70a1e38bbe..0000000000
--- a/ext/tk/lib/tk/event.rb
+++ /dev/null
@@ -1,488 +0,0 @@
-#
-# tk/event.rb - module for event
-#
-
-module TkEvent
-end
-
-########################
-
-require 'tkutil'
-require 'tk'
-
-########################
-
-module TkEvent
- class Event < TkUtil::CallbackSubst
- module Grp
- KEY = 0x1
- BUTTON = 0x2
- MOTION = 0x4
- CROSSING = 0x8
- FOCUS = 0x10
- EXPOSE = 0x20
- VISIBILITY = 0x40
- CREATE = 0x80
- DESTROY = 0x100
- UNMAP = 0x200
- MAP = 0x400
- REPARENT = 0x800
- CONFIG = 0x1000
- GRAVITY = 0x2000
- CIRC = 0x4000
- PROP = 0x8000
- COLORMAP = 0x10000
- VIRTUAL = 0x20000
- ACTIVATE = 0x40000
- MAPREQ = 0x80000
- CONFIGREQ = 0x100000
- RESIZEREQ = 0x200000
- CIRCREQ = 0x400000
-
- MWHEEL = 0x10000000
-
- ALL = 0xFFFFFFFF
-
- KEY_BUTTON_MOTION_VIRTUAL = (KEY|MWHEEL|BUTTON|MOTION|VIRTUAL)
- KEY_BUTTON_MOTION_CROSSING = (KEY|MWHEEL|BUTTON|MOTION|CROSSING|VIRTUAL)
- end
-
- type_data = [
- #-----+-------------------+------------------+-----------------------#
- # ID | const | group_flag | context_name #
- #-----+-------------------+------------------+-----------------------#
- [ 2, :KeyPress, Grp::KEY, 'KeyPress', 'Key' ],
- [ 3, :KeyRelease, Grp::KEY, 'KeyRelease' ],
- [ 4, :ButtonPress, Grp::BUTTON, 'ButtonPress', 'Button' ],
- [ 5, :ButtonRelease, Grp::BUTTON, 'ButtonRelease' ],
- [ 6, :MotionNotify, Grp::MOTION, 'Motion' ],
- [ 7, :EnterNotify, Grp::CROSSING, 'Enter' ],
- [ 8, :LeaveNotify, Grp::CROSSING, 'Leave' ],
- [ 9, :FocusIn, Grp::FOCUS, 'FocusIn' ],
- [ 10, :FocusOut, Grp::FOCUS, 'FocusOut' ],
- [ 11, :KeymapNotify, 0, ],
- [ 12, :Expose, Grp::EXPOSE, 'Expose' ],
- [ 13, :GraphicsExpose, Grp::EXPOSE, ],
- [ 14, :NoExpose, 0, ],
- [ 15, :VisibilityNotify, Grp::VISIBILITY, 'Visibility' ],
- [ 16, :CreateNotify, Grp::CREATE, 'Create' ],
- [ 17, :DestroyNotify, Grp::DESTROY, 'Destroy' ],
- [ 18, :UnmapNotify, Grp::UNMAP, 'Unmap' ],
- [ 19, :MapNotify, Grp::MAP, 'Map' ],
- [ 20, :MapRequest, Grp::MAPREQ, 'MapRequest' ],
- [ 21, :ReparentNotify, Grp::REPARENT, 'Reparent' ],
- [ 22, :ConfigureNotify, Grp::CONFIG, 'Configure' ],
- [ 23, :ConfigureRequest, Grp::CONFIGREQ, 'ConfigureRequest' ],
- [ 24, :GravityNotify, Grp::GRAVITY, 'Gravity' ],
- [ 25, :ResizeRequest, Grp::RESIZEREQ, 'ResizeRequest' ],
- [ 26, :CirculateNotify, Grp::CIRC, 'Circulate' ],
- [ 27, :CirculateRequest, 0, 'CirculateRequest' ],
- [ 28, :PropertyNotify, Grp::PROP, 'Property' ],
- [ 29, :SelectionClear, 0, ],
- [ 30, :SelectionRequest, 0, ],
- [ 31, :SelectionNotify, 0, ],
- [ 32, :ColormapNotify, Grp::COLORMAP, 'Colormap' ],
- [ 33, :ClientMessage, 0, ],
- [ 34, :MappingNotify, 0, ],
- [ 35, :VirtualEvent, Grp::VIRTUAL, ],
- [ 36, :ActivateNotify, Grp::ACTIVATE, 'Activate' ],
- [ 37, :DeactivateNotify, Grp::ACTIVATE, 'Deactivate' ],
- [ 38, :MouseWheelEvent, Grp::MWHEEL, 'MouseWheel' ],
- [ 39, :TK_LASTEVENT, 0, ]
- ]
-
- module TypeNum
- end
-
- TYPE_NAME_TBL = Hash.new
- TYPE_ID_TBL = Hash.new
- TYPE_GROUP_TBL = Hash.new
-
- type_data.each{|id, c_name, g_flag, *t_names|
- TypeNum.const_set(c_name, id)
- t_names.each{|t_name| t_name.freeze; TYPE_NAME_TBL[t_name] = id }
- TYPE_ID_TBL[id] = t_names
- TYPE_GROUP_TBL[id] = g_flag
- }
-
- TYPE_NAME_TBL.freeze
- TYPE_ID_TBL.freeze
-
- def self.type_id(name)
- TYPE_NAME_TBL[name.to_s]
- end
-
- def self.type_name(id)
- TYPE_ID_TBL[id] && TYPE_ID_TBL[id][0]
- end
-
- def self.group_flag(id)
- TYPE_GROUP_TBL[id] || 0
- end
-
- #############################################
-
- module StateMask
- ShiftMask = (1<<0)
- LockMask = (1<<1)
- ControlMask = (1<<2)
- Mod1Mask = (1<<3)
- Mod2Mask = (1<<4)
- Mod3Mask = (1<<5)
- Mod4Mask = (1<<6)
- Mod5Mask = (1<<7)
- Button1Mask = (1<<8)
- Button2Mask = (1<<9)
- Button3Mask = (1<<10)
- Button4Mask = (1<<11)
- Button5Mask = (1<<12)
-
- AnyModifier = (1<<15)
-
- META_MASK = (AnyModifier<<1)
- ALT_MASK = (AnyModifier<<2)
- EXTENDED_MASK = (AnyModifier<<3)
-
- CommandMask = Mod1Mask
- OptionMask = Mod2Mask
- end
-
- #############################################
-
- FIELD_FLAG = {
- # key => flag
- 'above' => Grp::CONFIG,
- 'borderwidth' => (Grp::CREATE|Grp::CONFIG),
- 'button' => Grp::BUTTON,
- 'count' => Grp::EXPOSE,
- 'data' => Grp::VIRTUAL,
- 'delta' => Grp::MWHEEL,
- 'detail' => (Grp::FOCUS|Grp::CROSSING),
- 'focus' => Grp::CROSSING,
- 'height' => (Grp::EXPOSE|Grp::CONFIG),
- 'keycode' => Grp::KEY,
- 'keysym' => Grp::KEY,
- 'mode' => (Grp::CROSSING|Grp::FOCUS),
- 'override' => (Grp::CREATE|Grp::MAP|Grp::REPARENT|Grp::CONFIG),
- 'place' => Grp::CIRC,
- 'root' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING),
- 'rootx' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING),
- 'rooty' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING),
- 'sendevent' => Grp::ALL,
- 'serial' => Grp::ALL,
- 'state' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|
- Grp::CROSSING|Grp::VISIBILITY),
- 'subwindow' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING),
- 'time' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING|
- Grp::PROP),
- 'warp' => Grp::KEY_BUTTON_MOTION_VIRTUAL,
- 'width' => (Grp::EXPOSE|Grp::CREATE|Grp::CONFIG),
- 'window' => (Grp::CREATE|Grp::UNMAP|Grp::MAP|Grp::REPARENT|
- Grp::CONFIG|Grp::GRAVITY|Grp::CIRC),
- 'when' => Grp::ALL,
- 'x' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING|
- Grp::EXPOSE|Grp::CREATE|Grp::CONFIG|Grp::GRAVITY|
- Grp::REPARENT),
- 'y' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING|
- Grp::EXPOSE|Grp::CREATE|Grp::CONFIG|Grp::GRAVITY|
- Grp::REPARENT),
- }
-
- FIELD_OPERATION = {
- 'root' => proc{|val|
- begin
- Tk.tk_call_without_enc('winfo', 'pathname', val)
- val
- rescue
- nil
- end
- },
-
- 'subwindow' => proc{|val|
- begin
- Tk.tk_call_without_enc('winfo', 'pathname', val)
- val
- rescue
- nil
- end
- },
-
- 'window' => proc{|val| nil}
- }
-
- #-------------------------------------------
-
- def valid_fields(group_flag=nil)
- group_flag = self.class.group_flag(self.type) unless group_flag
-
- fields = {}
- FIELD_FLAG.each{|key, flag|
- next if (flag & group_flag) == 0
- begin
- val = self.__send__(key)
- rescue
- next
- end
- next if !val || val == '??'
- fields[key] = val
- }
-
- fields
- end
-
- def valid_for_generate(group_flag=nil)
- fields = valid_fields(group_flag)
-
- FIELD_OPERATION.each{|key, cmd|
- next unless fields.has_key?(key)
- val = FIELD_OPERATION[key].call(fields[key])
- if val
- fields[key] = val
- else
- fields.delete(key)
- end
- }
-
- fields
- end
-
- def generate(win, modkeys={})
- klass = self.class
-
- if modkeys.has_key?(:type) || modkeys.has_key?('type')
- modkeys = TkComm._symbolkey2str(modkeys)
- type_id = modkeys.delete('type')
- else
- type_id = self.type
- end
-
- type_name = klass.type_name(type_id)
- unless type_name
- fail RuntimeError, "type_id #{type_id} is invalid"
- end
-
- group_flag = klass.group_flag(type_id)
-
- opts = valid_for_generate(group_flag)
-
- modkeys.each{|key, val|
- if val
- opts[key.to_s] = val
- else
- opts.delete(key.to_s)
- end
- }
-
- if group_flag != Grp::KEY
- Tk.event_generate(win, type_name, opts)
- else
- # If type is KEY event, focus should be set to target widget.
- # If not set, original widget will get the same event.
- # That will make infinite loop.
- w = Tk.tk_call_without_enc('focus')
- begin
- Tk.tk_call_without_enc('focus', win)
- Tk.event_generate(win, type_name, opts)
- ensure
- Tk.tk_call_without_enc('focus', w)
- end
- end
- end
-
- #############################################
-
- # [ <'%' subst-key char>, <proc type char>, <instance var (accessor) name>]
- KEY_TBL = [
- [ ?#, ?n, :serial ],
- [ ?a, ?s, :above ],
- [ ?b, ?n, :num ],
- [ ?c, ?n, :count ],
- [ ?d, ?s, :detail ],
- [ ?f, ?b, :focus ],
- [ ?h, ?n, :height ],
- [ ?i, ?s, :win_hex ],
- [ ?k, ?n, :keycode ],
- [ ?m, ?s, :mode ],
- [ ?o, ?b, :override ],
- [ ?p, ?s, :place ],
- [ ?s, ?x, :state ],
- [ ?t, ?n, :time ],
- [ ?w, ?n, :width ],
- [ ?x, ?n, :x ],
- [ ?y, ?n, :y ],
- [ ?A, ?s, :char ],
- [ ?B, ?n, :borderwidth ],
- [ ?D, ?n, :wheel_delta ],
- [ ?E, ?b, :send_event ],
- [ ?K, ?s, :keysym ],
- [ ?N, ?n, :keysym_num ],
- [ ?P, ?s, :property ],
- [ ?R, ?s, :rootwin_id ],
- [ ?S, ?s, :subwindow ],
- [ ?T, ?n, :type ],
- [ ?W, ?w, :widget ],
- [ ?X, ?n, :x_root ],
- [ ?Y, ?n, :y_root ],
- nil
- ]
-
- # [ <proc type char>, <proc/method to convert tcl-str to ruby-obj>]
- PROC_TBL = [
- [ ?n, TkComm.method(:num_or_str) ],
- [ ?s, TkComm.method(:string) ],
- [ ?b, TkComm.method(:bool) ],
- [ ?w, TkComm.method(:window) ],
-
- [ ?x, proc{|val|
- begin
- TkComm::number(val)
- rescue ArgumentError
- val
- end
- }
- ],
-
- nil
- ]
-
- # setup tables to be used by scan_args, _get_subst_key, _get_all_subst_keys
- #
- # _get_subst_key() and _get_all_subst_keys() generates key-string
- # which describe how to convert callback arguments to ruby objects.
- # When binding parameters are given, use _get_subst_key().
- # But when no parameters are given, use _get_all_subst_keys() to
- # create a Event class object as a callback parameter.
- #
- # scan_args() is used when doing callback. It convert arguments
- # ( which are Tcl strings ) to ruby objects based on the key string
- # that is generated by _get_subst_key() or _get_all_subst_keys().
- #
- _setup_subst_table(KEY_TBL, PROC_TBL);
-
- #
- # NOTE: The order of parameters which passed to callback procedure is
- # <extra_arg>, <extra_arg>, ... , <subst_arg>, <subst_arg>, ...
- #
-
- # If you need support extra arguments given by Tcl/Tk,
- # please override _get_extra_args_tbl
- #
- #def self._get_extra_args_tbl
- # # return an array of convert procs
- # []
- #end
-
-=begin
- alias button num
- alias delta wheel_delta
- alias root rootwin_id
- alias rootx x_root
- alias root_x x_root
- alias rooty y_root
- alias root_y y_root
- alias sendevent send_event
-=end
- ALIAS_TBL = {
- :button => :num,
- :data => :detail,
- :delta => :wheel_delta,
- :root => :rootwin_id,
- :rootx => :x_root,
- :root_x => :x_root,
- :rooty => :y_root,
- :root_y => :y_root,
- :sendevent => :send_event,
- :window => :widget
- }
-
- _define_attribute_aliases(ALIAS_TBL)
-
- end
-
- ###############################################
-
- def install_bind_for_event_class(klass, cmd, *args)
- extra_args_tbl = klass._get_extra_args_tbl
-
- if args.compact.size > 0
- args = args.join(' ')
- keys = klass._get_subst_key(args)
-
- if cmd.kind_of?(String)
- id = cmd
- elsif cmd.kind_of?(TkCallbackEntry)
- id = install_cmd(cmd)
- else
- id = install_cmd(proc{|*arg|
- ex_args = []
- extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)}
- begin
- TkUtil.eval_cmd(cmd, *(ex_args.concat(klass.scan_args(keys, arg))))
- rescue Exception=>e
- if TkCore::INTERP.kind_of?(TclTkIp)
- fail e
- else
- # MultiTkIp
- fail Exception, "#{e.class}: #{e.message.dup}"
- end
- end
- })
- end
- else
- keys, args = klass._get_all_subst_keys
-
- if cmd.kind_of?(String)
- id = cmd
- elsif cmd.kind_of?(TkCallbackEntry)
- id = install_cmd(cmd)
- else
- id = install_cmd(proc{|*arg|
- ex_args = []
- extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)}
- begin
- TkUtil.eval_cmd(cmd, *(ex_args << klass.new(*klass.scan_args(keys, arg))))
- rescue Exception=>e
- if TkCore::INTERP.kind_of?(TclTkIp)
- fail e
- else
- # MultiTkIp
- fail Exception, "#{e.class}: #{e.message.dup}"
- end
- end
- })
- end
- end
-
- if TkCore::INTERP.kind_of?(TclTkIp)
- id + ' ' + args
- else
- # MultiTkIp
- "if {[set st [catch {#{id} #{args}} ret]] != 0} {
- if {$st == 4} {
- return -code continue $ret
- } elseif {$st == 3} {
- return -code break $ret
- } elseif {$st == 2} {
- return -code return $ret
- } elseif {[regexp {^Exception: (TkCallbackContinue: .*)$} \
- $ret m msg]} {
- return -code continue $msg
- } elseif {[regexp {^Exception: (TkCallbackBreak: .*)$} $ret m msg]} {
- return -code break $msg
- } elseif {[regexp {^Exception: (TkCallbackReturn: .*)$} $ret m msg]} {
- return -code return $msg
- } elseif {[regexp {^Exception: (\\S+: .*)$} $ret m msg]} {
- return -code return $msg
- } else {
- return -code error $ret
- }
- } else {
- set ret
- }"
- end
- end
-
- def install_bind(cmd, *args)
- install_bind_for_event_class(TkEvent::Event, cmd, *args)
- end
-end
diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb
deleted file mode 100644
index de02d4957c..0000000000
--- a/ext/tk/lib/tk/font.rb
+++ /dev/null
@@ -1,1762 +0,0 @@
-#
-# tk/font.rb - the class to treat fonts on Ruby/Tk
-#
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-require 'tk'
-
-class TkFont
- include Tk
- extend TkCore
-
- TkCommandNames = ['font'.freeze].freeze
-
- Tk_FontID = ["@font".freeze, "00000".taint].freeze
- Tk_FontNameTBL = TkCore::INTERP.create_table
- Tk_FontUseTBL = TkCore::INTERP.create_table
-
- TkCore::INTERP.init_ip_env{
- Tk_FontNameTBL.clear
- Tk_FontUseTBL.clear
- }
-
- # option_type : default => string
- OptionType = Hash.new(?s)
- OptionType['size'] = ?n
- OptionType['pointadjust'] = ?n
- OptionType['underline'] = ?b
- OptionType['overstrike'] = ?b
-
- # metric_type : default => num_or_str
- MetricType = Hash.new(?n)
- MetricType['fixed'] = ?b
-
- # set default font
- case Tk::TK_VERSION
- when /^4\.*/
- DEFAULT_LATIN_FONT_NAME = 'a14'.freeze
- DEFAULT_KANJI_FONT_NAME = 'k14'.freeze
-
- when /^8\.*/
- if JAPANIZED_TK
- begin
- fontnames = tk_call('font', 'names')
- case fontnames
- when /defaultgui/
- # Tcl/Tk-JP for Windows
- ltn = 'defaultgui'
- knj = 'defaultgui'
- when /Mincho:Helvetica-Bold-12/
- # Tcl/Tk-JP for UNIX/X
- ltn, knj = tk_split_simplelist(tk_call('font', 'configure',
- 'Mincho:Helvetica-Bold-12',
- '-compound'))
- else
- # unknown Tcl/Tk-JP
- #platform = tk_call('set', 'tcl_platform(platform)')
- platform = Tk::PLATFORM['platform']
- case platform
- when 'unix'
- ltn = {'family'=>'Helvetica'.freeze,
- 'size'=>-12, 'weight'=>'bold'.freeze}
- #knj = 'k14'
- #knj = '-misc-fixed-medium-r-normal--14-*-*-*-c-*-jisx0208.1983-0'
- knj = '-*-fixed-bold-r-normal--12-*-*-*-c-*-jisx0208.1983-0'
- when 'windows'
- ltn = {'family'=>'MS Sans Serif'.freeze, 'size'=>8}
- knj = 'mincho'
- when 'macintosh'
- ltn = 'system'
- knj = 'mincho'
- else # unknown
- ltn = 'Helvetica'
- knj = 'mincho'
- end
- end
- rescue
- ltn = 'Helvetica'
- knj = 'mincho'
- end
-
- else # not JAPANIZED_TK
- begin
- #platform = tk_call('set', 'tcl_platform(platform)')
- platform = Tk::PLATFORM['platform']
- case platform
- when 'unix'
- ltn = {'family'=>'Helvetica'.freeze,
- 'size'=>-12, 'weight'=>'bold'.freeze}
- when 'windows'
- ltn = {'family'=>'MS Sans Serif'.freeze, 'size'=>8}
- when 'macintosh'
- ltn = 'system'
- else # unknown
- ltn = 'Helvetica'
- end
- rescue
- ltn = 'Helvetica'
- end
-
- knj = ltn.dup
- end
-
- DEFAULT_LATIN_FONT_NAME = ltn.freeze
- DEFAULT_KANJI_FONT_NAME = knj.freeze
-
- else # unknown version
- DEFAULT_LATIN_FONT_NAME = 'Helvetica'.freeze
- DEFAULT_KANJI_FONT_NAME = 'mincho'.freeze
-
- end
-
- if $DEBUG
- print "default latin font = "; p DEFAULT_LATIN_FONT_NAME
- print "default kanji font = "; p DEFAULT_KANJI_FONT_NAME
- end
-
-
- ###################################
- class DescendantFont
- def initialize(compound, type)
- unless compound.kind_of?(TkFont)
- fail ArgumentError, "a TkFont object is expected for the 1st argument"
- end
- @compound = compound
- case type
- when 'kanji', 'latin', 'ascii'
- @type = type
- when :kanji, :latin, :ascii
- @type = type.to_s
- else
- fail ArgumentError, "unknown type '#{type}'"
- end
- end
-
- def dup
- fail RuntimeError, "cannot dupulicate a descendant font"
- end
- def clone
- fail RuntimeError, "cannot clone a descendant font"
- end
-
- def to_eval
- @compound.__send__(@type + '_font_id')
- end
- def font
- @compound.__send__(@type + '_font_id')
- end
-
- def [](slot)
- @compound.__send__(@type + '_configinfo', slot)
- end
- def []=(slot, value)
- @compound.__send__(@type + '_configure', slot, value)
- value
- end
-
- def method_missing(id, *args)
- @compound.__send__(@type + '_' + id.id2name, *args)
- end
- end
-
-
- ###################################
- # class methods
- ###################################
- def TkFont.actual(fnt, option=nil)
- fnt = '{}' if fnt == ''
- if fnt.kind_of?(TkFont)
- fnt.actual(option)
- else
- actual_core(fnt, nil, option)
- end
- end
-
- def TkFont.actual_displayof(fnt, win, option=nil)
- fnt = '{}' if fnt == ''
- if fnt.kind_of?(TkFont)
- fnt.actual_displayof(win, option)
- else
- win = '.' unless win
- actual_core(fnt, win, option)
- end
- end
-
- def TkFont.configure(fnt, slot, value=None)
- if fnt.kind_of?(TkFont)
- fnt.configure(fnt, slot, value)
- else
- configure_core(fnt, slot, value)
- end
- fnt
- end
-
- def TkFont.configinfo(fnt, slot=nil)
- if fnt.kind_of?(TkFont)
- fnt.configinfo(fnt, slot)
- else
- configinfo_core(fnt, slot)
- end
- end
-
- def TkFont.current_configinfo(fnt, slot=nil)
- if fnt.kind_of?(TkFont)
- fnt.current_configinfo(fnt, slot)
- else
- current_configinfo_core(fnt, slot)
- end
- end
-
- def TkFont.measure(fnt, text)
- fnt = '{}' if fnt == ''
- if fnt.kind_of?(TkFont)
- fnt.measure(text)
- else
- measure_core(fnt, nil, text)
- end
- end
-
- def TkFont.measure_displayof(fnt, win, text)
- fnt = '{}' if fnt == ''
- if fnt.kind_of?(TkFont)
- fnt.measure_displayof(win, text)
- else
- win = '.' unless win
- measure_core(fnt, win, text)
- end
- end
-
- def TkFont.metrics(fnt, option=nil)
- fnt = '{}' if fnt == ''
- if fnt.kind_of?(TkFont)
- fnt.metrics(option)
- else
- metrics_core(fnt, nil, option)
- end
- end
-
- def TkFont.metrics_displayof(fnt, win, option=nil)
- fnt = '{}' if fnt == ''
- if fnt.kind_of?(TkFont)
- font.metrics_displayof(win, option=nil)
- else
- win = '.' unless win
- metrics_core(fnt, win, option)
- end
- end
-
- def TkFont.families(win=nil)
- case (Tk::TK_VERSION)
- when /^4\.*/
- ['fixed']
-
- when /^8\.*/
- if win
- tk_split_simplelist(tk_call('font', 'families', '-displayof', win))
- else
- tk_split_simplelist(tk_call('font', 'families'))
- end
- end
- end
-
- def TkFont.names
- case (Tk::TK_VERSION)
- when /^4\.*/
- r = ['fixed']
- r += ['a14', 'k14'] if JAPANIZED_TK
- Tk_FontNameTBL.each_value{|obj| r.push(obj)}
- r | []
-
- when /^8\.*/
- tk_split_simplelist(tk_call('font', 'names'))
-
- end
- end
-
- def TkFont.create_copy(font)
- fail 'source-font must be a TkFont object' unless font.kind_of? TkFont
- if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
- keys = {}
- font.configinfo.each{|key,value| keys[key] = value }
- TkFont.new(font.latin_font_id, font.kanji_font_id, keys)
- else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
- TkFont.new(font.latin_font_id, font.kanji_font_id, font.configinfo)
- end
- end
-
- def TkFont.get_obj(name)
- if name =~ /^(@font[0-9]+)(|c|l|k)$/
- Tk_FontNameTBL[$1]
- else
- nil
- end
- end
-
- def TkFont.init_widget_font(pathname, *args)
- win, tag, key = pathname.split(';')
- key = 'font' if key == nil || key == ''
- path = [win, tag, key].join(';')
-
- case (Tk::TK_VERSION)
- when /^4\.*/
- regexp = /^-(|kanji)#{key} /
-
- conf_list = tk_split_simplelist(tk_call(*args)).
- find_all{|prop| prop =~ regexp}.
- collect{|prop| tk_split_simplelist(prop)}
-
- if conf_list.size == 0
- raise RuntimeError, "the widget may not support 'font' option"
- end
-
- args << {}
-
- ltn_key = "-#{key}"
- knj_key = "-kanji#{key}"
-
- ltn_info = conf_list.find{|conf| conf[0] == ltn_key}
- ltn = ltn_info[-1]
- ltn = nil if ltn == [] || ltn == ""
-
- knj_info = conf_list.find{|conf| conf[0] == knj_key}
- knj = knj_info[-1]
- knj = nil if knj == [] || knj == ""
-
- TkFont.new(ltn, knj).call_font_configure([path, key], *args)
-
- when /^8\.*/
- regexp = /^-#{key} /
-
- conf_list = tk_split_simplelist(tk_call(*args)).
- find_all{|prop| prop =~ regexp}.
- collect{|prop| tk_split_simplelist(prop)}
-
- if conf_list.size == 0
- raise RuntimeError, "the widget may not support 'font' option"
- end
-
- args << {}
-
- optkey = "-#{key}"
-
- info = conf_list.find{|conf| conf[0] == optkey}
- fnt = info[-1]
- fnt = nil if fnt == [] || fnt == ""
-
- unless fnt
- # create dummy
- # TkFont.new(nil, nil).call_font_configure([path, key], *args)
- dummy_fnt = TkFont.allocate
- dummy_fnt.instance_eval{ init_dummy_fontobj() }
- dummy_fnt
- else
- begin
- compound = tk_split_simplelist(
- Hash[*tk_split_simplelist(tk_call('font', 'configure',
- fnt))].collect{|k,v|
- [k[1..-1], v]
- }.assoc('compound')[1])
- rescue
- compound = []
- end
- if compound == []
- TkFont.new(fnt).call_font_configure([path, key], *args)
- else
- TkFont.new(compound[0],
- compound[1]).call_font_configure([path, key], *args)
- end
- end
- end
- end
-
- def TkFont.used_on(path=nil)
- if path
- Tk_FontUseTBL[path]
- else
- Tk_FontUseTBL.values | []
- end
- end
-
- def TkFont.failsafe(font)
- begin
- if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
- tk_call('font', 'failsafe', font)
- end
- rescue
- end
- end
-
- ###################################
- # instance methods
- ###################################
- private
- ###################################
- def init_dummy_fontobj
- @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
- Tk_FontID[1].succ!
- Tk_FontNameTBL[@id] = self
-
- @latin_desscendant = nil
- @kanji_desscendant = nil
-
- case (Tk::TK_VERSION)
- when /^4\.*/
- @latinfont = ""
- @kanjifont = ""
- if JAPANIZED_TK
- @compoundfont = [[@latinfont], [@kanjifont]]
- @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont}
- else
- @compoundfont = @latinfont
- @fontslot = {'font'=>@latinfont}
- end
- else
- @latinfont = @id + 'l'
- @kanjifont = @id + 'k'
- @compoundfont = @id + 'c'
-
- if JAPANIZED_TK
- tk_call('font', 'create', @latinfont, '-charset', 'iso8859')
- tk_call('font', 'create', @kanjifont, '-charset', 'jisx0208.1983')
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont])
- else
- tk_call('font', 'create', @latinfont)
- tk_call('font', 'create', @kanjifont)
- tk_call('font', 'create', @compoundfont)
- end
-
- @fontslot = {'font'=>@compoundfont}
- end
-
- self
- end
-
- def initialize(ltn=nil, knj=nil, keys=nil)
- ltn = '{}' if ltn == ''
- knj = '{}' if knj == ''
-
- # @id = Tk_FontID.join('')
- @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
- Tk_FontID[1].succ!
- Tk_FontNameTBL[@id] = self
-
- @latin_desscendant = nil
- @kanji_desscendant = nil
-
- if knj.kind_of?(Hash) && !keys
- keys = knj
- knj = nil
- end
-
- # compound font check
- if Tk::TK_VERSION == '8.0' && JAPANIZED_TK
- begin
- compound = tk_split_simplelist(tk_call('font', 'configure',
- ltn, '-compound'))
- if knj == nil
- if compound != []
- ltn, knj = compound
- end
- else
- if compound != []
- ltn = compound[0]
- end
- compound = tk_split_simplelist(tk_call('font', 'configure',
- knj, '-compound'))
- if compound != []
- knj = compound[1]
- end
- end
- rescue
- end
- end
-
- if ltn
- if JAPANIZED_TK && !knj
- if Tk::TK_VERSION =~ /^4.*/
- knj = DEFAULT_KANJI_FONT_NAME
- else
- knj = ltn
- end
- end
- else
- ltn = DEFAULT_LATIN_FONT_NAME
- knj = DEFAULT_KANJI_FONT_NAME if JAPANIZED_TK && !knj
- end
-
- create_compoundfont(ltn, knj, keys)
- end
-
- def initialize_copy(font)
- unless font.kind_of?(TkFont)
- fail TypeError, '"initialize_copy should take same class object'
- end
- if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
- keys = {}
- font.configinfo.each{|key,value| keys[key] = value }
- initialize(font.latin_font_id, font.kanji_font_id, keys)
- else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
- initialize(font.latin_font_id, font.kanji_font_id, font.configinfo)
- end
- end
-
- def _get_font_info_from_hash(font)
- font = _symbolkey2str(font)
- foundry = (info = font['foundry'] .to_s)? info: '*'
- family = (info = font['family'] .to_s)? info: '*'
- weight = (info = font['weight'] .to_s)? info: '*'
- slant = (info = font['slant'] .to_s)? info: '*'
- swidth = (info = font['swidth'] .to_s)? info: '*'
- adstyle = (info = font['adstyle'] .to_s)? info: '*'
- pixels = (info = font['pixels'] .to_s)? info: '*'
- points = (info = font['points'] .to_s)? info: '*'
- resx = (info = font['resx'] .to_s)? info: '*'
- resy = (info = font['resy'] .to_s)? info: '*'
- space = (info = font['space'] .to_s)? info: '*'
- avgWidth = (info = font['avgWidth'].to_s)? info: '*'
- charset = (info = font['charset'] .to_s)? info: '*'
- encoding = (info = font['encoding'].to_s)? info: '*'
-
- [foundry, family, weight, slant, swidth, adstyle,
- pixels, points, resx, resy, space, avgWidth, charset, encoding]
- end
-
- def create_latinfont_tk4x(font)
- if font.kind_of? Hash
- @latinfont = '-' + _get_font_info_from_hash(font).join('-') + '-'
-
- elsif font.kind_of? Array
- finfo = {}
- finfo['family'] = font[0].to_s
- if font[1]
- fsize = font[1].to_s
- if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/
- if $1 == '-'
- finfo['pixels'] = $2
- else
- finfo['points'] = $2
- end
- else
- finfo['points'] = '13'
- end
- end
- font[2..-1].each{|style|
- case (style)
- when 'normal'
- finfo['weight'] = style
- when 'bold'
- finfo['weight'] = style
- when 'roman'
- finfo['slant'] = 'r'
- when 'italic'
- finfo['slant'] = 'i'
- end
- }
-
- @latinfont = '-' + _get_font_info_from_hash(finfo).join('-') + '-'
-
- elsif font.kind_of? TkFont
- @latinfont = font.latin_font
-
- else
- if font
- @latinfont = font
- else
- @latinfont = DEFAULT_LATIN_FONT_NAME
- end
-
- end
- end
-
- def create_kanjifont_tk4x(font)
- unless JAPANIZED_TK
- @kanjifont = ""
- return
- end
-
- if font.kind_of? Hash
- @kanjifont = '-' + _get_font_info_from_hash(font).join('-') + '-'
-
- elsif font.kind_of? Array
- finfo = {}
- finfo['family'] = font[0].to_s
- if font[1]
- fsize = font[1].to_s
- if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/
- if $1 == '-'
- finfo['pixels'] = $2
- else
- finfo['points'] = $2
- end
- else
- finfo['points'] = '13'
- end
- end
- font[2..-1].each{|style|
- case (style)
- when 'normal'
- finfo['weight'] = style
- when 'bold'
- finfo['weight'] = style
- when 'roman'
- finfo['slant'] = 'r'
- when 'italic'
- finfo['slant'] = 'i'
- end
- }
-
- @kanjifont = '-' + _get_font_info_from_hash(finfo).join('-') + '-'
- elsif font.kind_of? TkFont
- @kanjifont = font.kanji_font_id
- else
- if font
- @kanjifont = font
- else
- @kanjifont = DEFAULT_KANJI_FONT_NAME
- end
- end
- end
-
- def create_compoundfont_tk4x(ltn, knj, keys)
- create_latinfont(ltn)
- create_kanjifont(knj)
-
- if JAPANIZED_TK
- @compoundfont = [[@latinfont], [@kanjifont]]
- @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont}
- else
- @compoundfont = @latinfont
- @fontslot = {'font'=>@latinfont}
- end
- end
-
- def create_latinfont_tk8x(font)
- @latinfont = @id + 'l'
-
- if JAPANIZED_TK
- if font.kind_of? Hash
- if font[:charset] || font['charset']
- tk_call('font', 'create', @latinfont, *hash_kv(font))
- else
- tk_call('font', 'create', @latinfont,
- '-charset', 'iso8859', *hash_kv(font))
- end
- elsif font.kind_of? Array
- tk_call('font', 'create', @latinfont, '-copy', array2tk_list(font))
- tk_call('font', 'configure', @latinfont, '-charset', 'iso8859')
- elsif font.kind_of? TkFont
- tk_call('font', 'create', @latinfont, '-copy', font.latin_font)
- elsif font
- tk_call('font', 'create', @latinfont, '-copy', font,
- '-charset', 'iso8859')
- else
- tk_call('font', 'create', @latinfont, '-charset', 'iso8859')
- end
- else
- if font.kind_of? Hash
- tk_call('font', 'create', @latinfont, *hash_kv(font))
- else
- keys = {}
- if font.kind_of? Array
- actual_core(array2tk_list(font)).each{|key,val| keys[key] = val}
- elsif font.kind_of? TkFont
- actual_core(font.latin_font).each{|key,val| keys[key] = val}
- elsif font
- actual_core(font).each{|key,val| keys[key] = val}
- end
- tk_call('font', 'create', @latinfont, *hash_kv(keys))
- end
-
- if font && @compoundfont
- keys = {}
- actual_core(@latinfont).each{|key,val| keys[key] = val}
- tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
- end
- end
- end
-
- def create_kanjifont_tk8x(font)
- @kanjifont = @id + 'k'
-
- if JAPANIZED_TK
- if font.kind_of? Hash
- if font[:charset] || font['charset']
- tk_call('font', 'create', @kanjifont, *hash_kv(font))
- else
- tk_call('font', 'create', @kanjifont,
- '-charset', 'jisx0208.1983', *hash_kv(font))
- end
- elsif font.kind_of? Array
- tk_call('font', 'create', @kanjifont, '-copy', array2tk_list(font))
- tk_call('font', 'configure', @kanjifont, '-charset', 'jisx0208.1983')
- elsif font.kind_of? TkFont
- tk_call('font', 'create', @kanjifont, '-copy', font.kanji_font_id)
- elsif font
- tk_call('font', 'create', @kanjifont, '-copy', font,
- '-charset', 'jisx0208.1983')
- else
- tk_call('font', 'create', @kanjifont, '-charset', 'jisx0208.1983')
- end
- # end of JAPANIZED_TK
-
- else
- if font.kind_of? Hash
- tk_call('font', 'create', @kanjifont, *hash_kv(font))
- else
- keys = {}
- if font.kind_of? Array
- actual_core(array2tk_list(font)).each{|key,val| keys[key] = val}
- elsif font.kind_of? TkFont
- actual_core(font.kanji_font_id).each{|key,val| keys[key] = val}
- elsif font
- actual_core(font).each{|key,val| keys[key] = val}
- end
- tk_call('font', 'create', @kanjifont, *hash_kv(keys))
- end
-
- if font && @compoundfont
- keys = {}
- actual_core(@kanjifont).each{|key,val| keys[key] = val}
- tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
- end
- end
- end
-
- def create_compoundfont_tk8x(ltn, knj, keys)
- if knj
- create_latinfont(ltn)
- create_kanjifont(knj)
- else
- cfnt = ltn
- create_kanjifont(cfnt)
- create_latinfont(cfnt)
- end
-
- @compoundfont = @id + 'c'
-
- if JAPANIZED_TK
- unless keys
- keys = {}
- else
- keys = keys.dup
- end
- if (tk_call('font', 'configure', @latinfont, '-underline') == '1' &&
- tk_call('font', 'configure', @kanjifont, '-underline') == '1' &&
- !keys.key?('underline'))
- keys['underline'] = true
- end
- if (tk_call('font', 'configure', @latinfont, '-overstrike') == '1' &&
- tk_call('font', 'configure', @kanjifont, '-overstrike') == '1' &&
- !keys.key?('overstrike'))
- keys['overstrike'] = true
- end
-
- @fontslot = {'font'=>@compoundfont}
- begin
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
- rescue RuntimeError => e
- if ltn == knj
- if e.message =~ /kanji font .* specified/
- tk_call('font', 'delete', @latinfont)
- create_latinfont(DEFAULT_LATIN_FONT_NAME)
- opts = []
- Hash[*(tk_split_simplelist(tk_call('font', 'configure',
- @kanjifont)))].each{|k,v|
- case k
- when '-size', '-weight', '-slant', '-underline', '-overstrike'
- opts << k << v
- end
- }
- tk_call('font', 'configure', @latinfont, *opts)
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
-
- elsif e.message =~ /ascii font .* specified/
- tk_call('font', 'delete', @kanjifont)
- create_kanjifont(DEFAULT_KANJI_FONT_NAME)
- opts = []
- Hash[*(tk_split_simplelist(tk_call('font', 'configure',
- @latinfont)))].each{|k,v|
- case k
- when '-size', '-weight', '-slant', '-underline', '-overstrike'
- opts << k << v
- end
- }
- tk_call('font', 'configure', @kanjifont, *opts)
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
-
- else
- raise e
- end
- else
- raise e
- end
- end
- else
- tk_call('font', 'create', @compoundfont)
-
- latinkeys = {}
- begin
- actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
- rescue
- latinkeys = {}
- end
- if latinkeys != {}
- tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
- end
-
- if knj
- compoundkeys = nil
- kanjikeys = {}
- begin
- actual_core(@kanjifont).each{|key,val| kanjikeys[key] = val}
- rescue
- kanjikeys = {}
- end
- if kanjikeys != {}
- tk_call('font', 'configure', @compoundfont, *hash_kv(kanjikeys))
- end
- end
-
- if cfnt
- if cfnt.kind_of?(Hash)
- compoundkeys = cfnt.dup
- else
- compoundkeys = {}
- actual_core(cfnt).each{|key,val| compoundkeys[key] = val}
- end
- compoundkeys.update(_symbolkey2str(keys))
- keys = compoundkeys
- end
-
- @fontslot = {'font'=>@compoundfont}
- tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
- end
- end
-
- ###################################
- public
- ###################################
- def inspect
- sprintf("#<%s:%0x:%s>", self.class.inspect, self.__id__, @compoundfont)
- end
-
- def method_missing(id, *args)
- name = id.id2name
- case args.length
- when 1
- if name[-1] == ?=
- configure name[0..-2], args[0]
- args[0]
- else
- configure name, args[0]
- self
- end
- when 0
- begin
- configinfo name
- rescue
- super(id, *args)
-# fail NameError, "undefined local variable or method `#{name}' for #{self.to_s}", error_at
- end
- else
- super(id, *args)
-# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
- end
- end
-
- def call_font_configure(path, *args)
- if path.kind_of?(Array)
- # [path, optkey]
- win, tag = path[0].split(';')
- optkey = path[1].to_s
- else
- win, tag, optkey = path.split(';')
- end
-
- fontslot = _symbolkey2str(@fontslot)
- if optkey && optkey != ""
- ltn = fontslot.delete('font')
- knj = fontslot.delete('kanjifont')
- fontslot[optkey] = ltn if ltn
- fontslot["kanji#{optkey}"] = knj if knj
- end
-
- keys = _symbolkey2str(args.pop).update(fontslot)
- args.concat(hash_kv(keys))
- tk_call(*args)
- Tk_FontUseTBL[[win, tag, optkey].join(';')] = self
- self
- end
-
- def used
- ret = []
- Tk_FontUseTBL.each{|key,value|
- next unless self == value
- if key.include?(';')
- win, tag, optkey = key.split(';')
- winobj = tk_tcl2ruby(win)
- if winobj.kind_of? TkText
- if optkey
- ret.push([winobj, winobj.tagid2obj(tag), optkey])
- else
- ret.push([winobj, winobj.tagid2obj(tag)])
- end
- elsif winobj.kind_of? TkCanvas
- if (tagobj = TkcTag.id2obj(winobj, tag)).kind_of? TkcTag
- if optkey
- ret.push([winobj, tagobj, optkey])
- else
- ret.push([winobj, tagobj])
- end
- elsif (tagobj = TkcItem.id2obj(winobj, tag)).kind_of? TkcItem
- if optkey
- ret.push([winobj, tagobj, optkey])
- else
- ret.push([winobj, tagobj])
- end
- else
- if optkey
- ret.push([winobj, tag, optkey])
- else
- ret.push([winobj, tag])
- end
- end
- elsif winobj.kind_of? TkMenu
- if optkey
- ret.push([winobj, tag, optkey])
- else
- ret.push([winobj, tag])
- end
- else
- if optkey
- ret.push([win, tag, optkey])
- else
- ret.push([win, tag])
- end
- end
- else
- ret.push(tk_tcl2ruby(key))
- end
- }
- ret
- end
-
- def id
- @id
- end
-
- def to_eval
- font
- end
-
- def font
- @compoundfont
- end
- alias font_id font
-
- def latin_font_id
- @latinfont
- end
-
- def latin_font
- # @latinfont
- if @latin_descendant
- @latin_descendant
- else
- @latin_descendant = DescendantFont.new(self, 'latin')
- end
- end
- alias latinfont latin_font
-
- def kanji_font_id
- @kanjifont
- end
-
- def kanji_font
- # @kanjifont
- if @kanji_descendant
- @kanji_descendant
- else
- @kanji_descendant = DescendantFont.new(self, 'kanji')
- end
- end
- alias kanjifont kanji_font
-
- def actual(option=nil)
- actual_core(@compoundfont, nil, option)
- end
-
- def actual_displayof(win, option=nil)
- win = '.' unless win
- actual_core(@compoundfont, win, option)
- end
-
- def latin_actual(option=nil)
- actual_core(@latinfont, nil, option)
- end
-
- def latin_actual_displayof(win, option=nil)
- win = '.' unless win
- actual_core(@latinfont, win, option)
- end
-
- def kanji_actual(option=nil)
- #if JAPANIZED_TK
- if @kanjifont != ""
- actual_core(@kanjifont, nil, option)
- else
- actual_core_tk4x(nil, nil, option)
- end
- end
-
- def kanji_actual_displayof(win, option=nil)
- #if JAPANIZED_TK
- if @kanjifont != ""
- win = '.' unless win
- actual_core(@kanjifont, win, option)
- else
- actual_core_tk4x(nil, win, option)
- end
- end
-
- def [](slot)
- configinfo slot
- end
-
- def []=(slot, val)
- configure slot, val
- val
- end
-
- def configure(slot, value=None)
- configure_core(@compoundfont, slot, value)
- self
- end
-
- def configinfo(slot=nil)
- configinfo_core(@compoundfont, slot)
- end
-
- def current_configinfo(slot=nil)
- current_configinfo_core(@compoundfont, slot)
- end
-
- def delete
- delete_core
- end
-
- def latin_configure(slot, value=None)
- if JAPANIZED_TK
- configure_core(@latinfont, slot, value)
- else
- configure(slot, value)
- end
- self
- end
-
- def latin_configinfo(slot=nil)
- if JAPANIZED_TK
- configinfo_core(@latinfont, slot)
- else
- configinfo(slot)
- end
- end
-
- def kanji_configure(slot, value=None)
- #if JAPANIZED_TK
- if @kanjifont != ""
- configure_core(@kanjifont, slot, value)
- configure('size'=>configinfo('size')) # to reflect new configuration
- else
- #""
- configure(slot, value)
- end
- self
- end
-
- def kanji_configinfo(slot=nil)
- #if JAPANIZED_TK
- if @kanjifont != ""
- configinfo_core(@kanjifont, slot)
- else
- #[]
- configinfo(slot)
- end
- end
-
- def replace(ltn, knj=None)
- knj = ltn if knj == None
- latin_replace(ltn)
- kanji_replace(knj)
- self
- end
-
- def latin_replace(ltn)
- latin_replace_core(ltn)
- reset_pointadjust
- self
- end
-
- def kanji_replace(knj)
- kanji_replace_core(knj)
- reset_pointadjust
- self
- end
-
- def measure(text)
- measure_core(@compoundfont, nil, text)
- end
-
- def measure_displayof(win, text)
- win = '.' unless win
- measure_core(@compoundfont, win, text)
- end
-
- def metrics(option=nil)
- metrics_core(@compoundfont, nil, option)
- end
-
- def metrics_displayof(win, option=nil)
- win = '.' unless win
- metrics_core(@compoundfont, win, option)
- end
-
- def latin_metrics(option=nil)
- metrics_core(@latinfont, nil, option)
- end
-
- def latin_metrics_displayof(win, option=nil)
- win = '.' unless win
- metrics_core(@latinfont, win, option)
- end
-
- def kanji_metrics(option=nil)
- if JAPANIZED_TK
- metrics_core(@kanjifont, nil, option)
- else
- metrics_core_tk4x(nil, nil, option)
- end
- end
-
- def kanji_metrics_displayof(win, option=nil)
- if JAPANIZED_TK
- win = '.' unless win
- metrics_core(@kanjifont, win, option)
- else
- metrics_core_tk4x(nil, win, option)
- end
- end
-
- def reset_pointadjust
- begin
- if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
- configure('pointadjust' => latin_actual.assoc('size')[1].to_f /
- kanji_actual.assoc('size')[1].to_f )
- end
- rescue
- end
- self
- end
-
- ###################################
- # private alias
- ###################################
- case (Tk::TK_VERSION)
- when /^4\.*/
- alias create_latinfont create_latinfont_tk4x
- alias create_kanjifont create_kanjifont_tk4x
- alias create_compoundfont create_compoundfont_tk4x
-
- when /^8\.[0-5]/
- alias create_latinfont create_latinfont_tk8x
- alias create_kanjifont create_kanjifont_tk8x
- alias create_compoundfont create_compoundfont_tk8x
-
- else
- alias create_latinfont create_latinfont_tk8x
- alias create_kanjifont create_kanjifont_tk8x
- alias create_compoundfont create_compoundfont_tk8x
-
- end
-
- ###################################
- # public alias
- ###################################
- alias ascii_font latin_font
- alias asciifont latinfont
- alias create_asciifont create_latinfont
- alias ascii_actual latin_actual
- alias ascii_actual_displayof latin_actual_displayof
- alias ascii_configure latin_configure
- alias ascii_configinfo latin_configinfo
- alias ascii_replace latin_replace
- alias ascii_metrics latin_metrics
-
- ###################################
-=begin
- def dup
- TkFont.new(self)
- end
- def clone
- TkFont.new(self)
- end
-=end
-end
-
-module TkFont::CoreMethods
- include Tk
- extend TkCore
-
- private
-
- def actual_core_tk4x(font, win=nil, option=nil)
- # dummy
- if option == 'pointadjust' || option == :pointadjust
- 1.0
- elsif option
- case TkFont::OptionType[option.to_s]
- when ?n
- 0
- when ?b
- false
- else
- ''
- end
- else
- [['family',''], ['size',0], ['weight',''], ['slant',''],
- ['underline',false], ['overstrike',false], ['charset',''],
- ['pointadjust',0]]
- end
- end
-
- def actual_core_tk8x(font, win=nil, option=nil)
- font = '{}' if font == ''
-
- if option == 'compound' || option == :compound
- ""
- elsif option
- if win
- val = tk_call('font', 'actual', font,
- "-displayof", win, "-#{option}")
- else
- val = tk_call('font', 'actual', font, "-#{option}")
- end
- case TkFont::OptionType[option.to_s]
- when ?n
- num_or_str(val)
- when ?b
- bool(val)
- else
- val
- end
- else
- l = tk_split_simplelist(if win
- tk_call('font', 'actual', font,
- "-displayof", win)
- else
- tk_call('font', 'actual', font)
- end)
- r = []
- while key=l.shift
- if key == '-compound'
- l.shift
- else
- key = key[1..-1]
- val = l.shift
- case TkFont::OptionType[key]
- when ?n
- r.push [key, num_or_str(val)]
- when ?b
- r.push [key, bool(val)]
- else
- r.push [key, val]
- end
- end
- end
- r
- end
- end
-
- def configure_core_tk4x(font, slot, value=None)
- #""
- self
- end
-
- def configinfo_core_tk4x(font, option=nil)
- # dummy
- if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
- if option == 'pointadjust' || option == :pointadjust
- 1.0
- elsif option
- case TkFont::OptionType[option.to_s]
- when ?n
- 0
- when ?b
- false
- else
- ''
- end
- else
- [['family',''], ['size',0], ['weight',''], ['slant',''],
- ['underline',false], ['overstrike',false], ['charset',''],
- ['pointadjust',1.0]]
- end
- else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
- current_configinfo_core_tk4x(font, option)
- end
- end
-
- def current_configinfo_core_tk4x(font, option=nil)
- if option
- case TkFont::OptionType[option.to_s]
- when ?n
- 0
- when ?b
- false
- else
- ''
- end
- else
- {'family'=>'', 'size'=>0, 'weight'=>'', 'slant'=>'',
- 'underline'=>false, 'overstrike'=>false,
- 'charset'=>false, 'pointadjust'=>1.0}
- end
- end
-
- def configure_core_tk8x(font, slot, value=None)
- if JAPANIZED_TK
- begin
- padjust = tk_call('font', 'configure', font, '-pointadjust')
- rescue
- padjust = nil
- end
- else
- padjust = nil
- end
- if slot.kind_of? Hash
- if JAPANIZED_TK && (slot.key?('family') || slot.key?(:family))
- slot = _symbolkey2str(slot)
- configure_core_tk8x(font, 'family', slot.delete('family'))
- end
-
- if ((slot.key?('size') || slot.key?(:size)) &&
- padjust && !slot.key?('pointadjust') && !slot.key?(:pointadjust))
- tk_call('font', 'configure', font,
- '-pointadjust', padjust, *hash_kv(slot))
- else
- tk_call('font', 'configure', font, *hash_kv(slot))
- end
- elsif (slot == 'size' || slot == :size) && padjust != nil
- tk_call('font', 'configure', font,
- "-#{slot}", value, '-pointadjust', padjust)
- elsif JAPANIZED_TK && (slot == 'family' || slot == :family)
- # coumpund font?
- begin
- compound = tk_split_simplelist(tk_call('font', 'configure',
- font, '-compound'))
- rescue
- tk_call('font', 'configure', font, '-family', value)
- return self
- end
- if compound == []
- tk_call('font', 'configure', font, '-family', value)
- return self
- end
- ltn, knj = compound
-
- lfnt = tk_call('font', 'create', '-copy', ltn)
- begin
- tk_call('font', 'configure', lfnt, '-family', value)
- latin_replace_core_tk8x(lfnt)
- rescue RuntimeError => e
- fail e if $DEBUG
- ensure
- tk_call('font', 'delete', lfnt) if lfnt != ''
- end
-
- kfnt = tk_call('font', 'create', '-copy', knj)
- begin
- tk_call('font', 'configure', kfnt, '-family', value)
- kanji_replace_core_tk8x(lfnt)
- rescue RuntimeError => e
- fail e if $DEBUG
- ensure
- tk_call('font', 'delete', kfnt) if kfnt != ''
- end
-
- else
- tk_call('font', 'configure', font, "-#{slot}", value)
- end
- self
- end
-
- def configinfo_core_tk8x(font, option=nil)
- if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
- if option == 'compound' || option == :compound
- ""
- elsif option
- val = tk_call('font', 'configure', font, "-#{option}")
- case TkFont::OptionType[option.to_s]
- when ?n
- num_or_str(val)
- when ?b
- bool(val)
- else
- val
- end
- else
- l = tk_split_simplelist(tk_call('font', 'configure', font))
- r = []
- while key=l.shift
- if key == '-compound'
- l.shift
- else
- key = key[1..-1]
- val = l.shift
- case TkFont::OptionType[key]
- when ?n
- r.push [key, num_or_str(val)]
- when ?b
- r.push [key, bool(val)]
- else
- r.push [key, val]
- end
- end
- end
- r
- end
- else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
- current_configinfo_core_tk8x(font, option)
- end
- end
-
- def current_configinfo_core_tk8x(font, option=nil)
- if option == 'compound'
- ""
- elsif option
- val = tk_call('font', 'configure', font, "-#{option}")
- case TkFont::OptionType[option.to_s]
- when ?n
- num_or_str(val)
- when ?b
- bool(val)
- else
- val
- end
- else
- l = tk_split_simplelist(tk_call('font', 'configure', font))
- r = {}
- while key=l.shift
- if key == '-compound'
- l.shift
- else
- key = key[1..-1]
- val = l.shift
- case TkFont::OptionType[key]
- when ?n
- r.push [key, num_or_str(val)]
- when ?b
- r.push [key, bool(val)]
- else
- r.push [key, val]
- end
- end
- end
- r
- end
- end
-
- def delete_core_tk4x
- TkFont::Tk_FontNameTBL.delete(@id)
- TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self}
- end
-
- def delete_core_tk8x
- begin
- tk_call('font', 'delete', @latinfont)
- rescue
- end
- begin
- tk_call('font', 'delete', @kanjifont)
- rescue
- end
- begin
- tk_call('font', 'delete', @compoundfont)
- rescue
- end
- TkFont::Tk_FontNameTBL.delete(@id)
- TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self}
- end
-
- def latin_replace_core_tk4x(ltn)
- create_latinfont_tk4x(ltn)
- @compoundfont[0] = [@latinfont] if JAPANIZED_TK
- @fontslot['font'] = @latinfont
- TkFont::Tk_FontUseTBL.dup.each{|w, fobj|
- if self == fobj
- begin
- if w.include?(';')
- win, tag, optkey = w.split(';')
- optkey = 'font' if optkey == nil || optkey == ''
- winobj = tk_tcl2ruby(win)
-# winobj.tagfont_configure(tag, {'font'=>@latinfont})
- if winobj.kind_of? TkText
- tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @latinfont)
- elsif winobj.kind_of? TkCanvas
- tk_call(win, 'itemconfigure', tag, "-#{optkey}", @latinfont)
- elsif winobj.kind_of? TkMenu
- tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont)
- else
- raise RuntimeError, "unknown widget type"
- end
- else
-# tk_tcl2ruby(w).font_configure('font'=>@latinfont)
- tk_call(w, 'configure', '-font', @latinfont)
- end
- rescue
- TkFont::Tk_FontUseTBL.delete(w)
- end
- end
- }
- self
- end
-
- def kanji_replace_core_tk4x(knj)
- return self unless JAPANIZED_TK
-
- create_kanjifont_tk4x(knj)
- @compoundfont[1] = [@kanjifont]
- @fontslot['kanjifont'] = @kanjifont
- TkFont::Tk_FontUseTBL.dup.each{|w, fobj|
- if self == fobj
- begin
- if w.include?(';')
- win, tag, optkey = w.split(';')
- optkey = 'kanjifont' unless optkey
- winobj = tk_tcl2ruby(win)
-# winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont})
- if winobj.kind_of? TkText
- tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @kanjifont)
- elsif winobj.kind_of? TkCanvas
- tk_call(win, 'itemconfigure', tag, "-#{optkey}", @kanjifont)
- elsif winobj.kind_of? TkMenu
- tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont)
- else
- raise RuntimeError, "unknown widget type"
- end
- else
-# tk_tcl2ruby(w).font_configure('kanjifont'=>@kanjifont)
- tk_call(w, 'configure', '-kanjifont', @kanjifont)
- end
- rescue
- TkFont::Tk_FontUseTBL.delete(w)
- end
- end
- }
- self
- end
-
- def latin_replace_core_tk8x(ltn)
- ltn = '{}' if ltn == ''
-
- if JAPANIZED_TK
- begin
- tk_call('font', 'delete', '@font_tmp')
- rescue
- end
- begin
- fnt_bup = tk_call('font', 'create', '@font_tmp', '-copy', @latinfont)
- rescue
- #fnt_bup = ''
- fnt_bup = TkFont::DEFAULT_LATIN_FONT_NAME
- end
- end
-
- begin
- tk_call('font', 'delete', @latinfont)
- rescue
- end
- create_latinfont(ltn)
-
- if JAPANIZED_TK
- keys = self.configinfo
- tk_call('font', 'delete', @compoundfont)
- begin
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
-=begin
- latinkeys = {}
- begin
- actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
- rescue
- latinkeys = {}
- end
- if latinkeys != {}
- tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
- end
-=end
- rescue RuntimeError => e
- tk_call('font', 'delete', @latinfont)
- if fnt_bup && fnt_bup != ''
- tk_call('font', 'create', @latinfont, '-copy', fnt_bup)
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
- tk_call('font', 'delete', fnt_bup)
- else
- fail e
- end
- end
-
- else
- latinkeys = {}
- begin
- actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
- rescue
- latinkeys = {}
- end
- if latinkeys != {}
- tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
- end
- end
- self
- end
-
- def kanji_replace_core_tk8x(knj)
- knj = '{}' if knj == ''
-
- if JAPANIZED_TK
- begin
- tk_call('font', 'delete', '@font_tmp')
- rescue
- end
- begin
- fnt_bup = tk_call('font', 'create', '@font_tmp', '-copy', @kanjifont)
- rescue
- #fnt_bup = ''
- fnt_bup = TkFont::DEFAULT_KANJI_FONT_NAME
- end
- end
-
- begin
- tk_call('font', 'delete', @kanjifont)
- rescue
- end
- create_kanjifont(knj)
-
- if JAPANIZED_TK
- keys = self.configinfo
- tk_call('font', 'delete', @compoundfont)
- begin
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
- rescue RuntimeError => e
- tk_call('font', 'delete', @kanjifont)
- if fnt_bup && fnt_bup != ''
- tk_call('font', 'create', @kanjifont, '-copy', fnt_bup)
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
- tk_call('font', 'delete', fnt_bup)
- else
- fail e
- end
- end
- end
- self
- end
-
- def measure_core_tk4x(font, win, text)
- 0
- end
-
- def measure_core_tk8x(font, win, text)
- font = '{}' if font == ''
-
- if win
- number(tk_call('font', 'measure', font,
- '-displayof', win, text))
- else
- number(tk_call('font', 'measure', font, text))
- end
- end
-
- def metrics_core_tk4x(font, win, option=nil)
- # dummy
- if option
- ""
- else
- [['ascent',[]], ['descent',[]], ['linespace',[]], ['fixed',[]]]
- end
- end
-
- def metrics_core_tk8x(font, win, option=nil)
- font = '{}' if font == ''
-
- if option
- if win
- number(tk_call('font', 'metrics', font,
- "-displayof", win, "-#{option}"))
- else
- number(tk_call('font', 'metrics', font, "-#{option}"))
- end
- else
- l = tk_split_list(if win
- tk_call('font','metrics',font,"-displayof",win)
- else
- tk_call('font','metrics',font)
- end)
- r = []
- while key=l.shift
- r.push [key[1..-1], l.shift.to_i]
- end
- r
- end
- end
-
- ###################################
- # private alias
- ###################################
- case (Tk::TK_VERSION)
- when /^4\.*/
- alias actual_core actual_core_tk4x
- alias configure_core configure_core_tk4x
- alias configinfo_core configinfo_core_tk4x
- alias current_configinfo_core current_configinfo_core_tk4x
- alias delete_core delete_core_tk4x
- alias latin_replace_core latin_replace_core_tk4x
- alias kanji_replace_core kanji_replace_core_tk4x
- alias measure_core measure_core_tk4x
- alias metrics_core metrics_core_tk4x
-
- when /^8\.[0-5]/
- alias actual_core actual_core_tk8x
- alias configure_core configure_core_tk8x
- alias configinfo_core configinfo_core_tk8x
- alias current_configinfo_core current_configinfo_core_tk8x
- alias delete_core delete_core_tk8x
- alias latin_replace_core latin_replace_core_tk8x
- alias kanji_replace_core kanji_replace_core_tk8x
- alias measure_core measure_core_tk8x
- alias metrics_core metrics_core_tk8x
-
- else
- alias actual_core actual_core_tk8x
- alias configure_core configure_core_tk8x
- alias configinfo_core configinfo_core_tk8x
- alias current_configinfo_core current_configinfo_core_tk8x
- alias delete_core delete_core_tk8x
- alias latin_replace_core latin_replace_core_tk8x
- alias kanji_replace_core kanji_replace_core_tk8x
- alias measure_core measure_core_tk8x
- alias metrics_core metrics_core_tk8x
-
- end
-end
-
-class TkFont
- include TkFont::CoreMethods
- extend TkFont::CoreMethods
-end
diff --git a/ext/tk/lib/tk/frame.rb b/ext/tk/lib/tk/frame.rb
deleted file mode 100644
index 6636fef5b5..0000000000
--- a/ext/tk/lib/tk/frame.rb
+++ /dev/null
@@ -1,128 +0,0 @@
-#
-# tk/frame.rb : treat frame widget
-#
-require 'tk'
-
-class TkFrame<TkWindow
- TkCommandNames = ['frame'.freeze].freeze
- WidgetClassName = 'Frame'.freeze
- WidgetClassNames[WidgetClassName] = self
-
-################# old version
-# def initialize(parent=nil, keys=nil)
-# if keys.kind_of? Hash
-# keys = keys.dup
-# @classname = keys.delete('classname') if keys.key?('classname')
-# @colormap = keys.delete('colormap') if keys.key?('colormap')
-# @container = keys.delete('container') if keys.key?('container')
-# @visual = keys.delete('visual') if keys.key?('visual')
-# end
-# super(parent, keys)
-# end
-#
-# def create_self
-# s = []
-# s << "-class" << @classname if @classname
-# s << "-colormap" << @colormap if @colormap
-# s << "-container" << @container if @container
-# s << "-visual" << @visual if @visual
-# tk_call 'frame', @path, *s
-# end
-#################
-
- def __boolval_optkeys
- super() << 'container'
- end
- private :__boolval_optkeys
-
- def initialize(parent=nil, keys=nil)
- my_class_name = nil
- if self.class < WidgetClassNames[self.class::WidgetClassName]
- my_class_name = self.class.name
- my_class_name = nil if my_class_name == ''
- end
- if parent.kind_of? Hash
- keys = _symbolkey2str(parent)
- else
- if keys
- keys = _symbolkey2str(keys)
- keys['parent'] = parent
- else
- keys = {'parent'=>parent}
- end
- end
- if keys.key?('classname')
- keys['class'] = keys.delete('classname')
- end
- @classname = keys['class']
- @colormap = keys['colormap']
- @container = keys['container']
- @visual = keys['visual']
- if !@classname && my_class_name
- keys['class'] = @classname = my_class_name
- end
- if @classname.kind_of? TkBindTag
- @db_class = @classname
- @classname = @classname.id
- elsif @classname
- @db_class = TkDatabaseClass.new(@classname)
- else
- @db_class = self.class
- @classname = @db_class::WidgetClassName
- end
- super(keys)
- end
-
- #def create_self(keys)
- # if keys and keys != None
- # tk_call_without_enc('frame', @path, *hash_kv(keys))
- # else
- # tk_call_without_enc( 'frame', @path)
- # end
- #end
- #private :create_self
-
- def database_classname
- @classname
- end
-
- def self.database_class
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- self
- else
- TkDatabaseClass.new(self.name)
- end
- end
- def self.database_classname
- self.database_class.name
- end
-
- def self.bind(*args, &b)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args, &b)
- else
- TkDatabaseClass.new(self.name).bind(*args, &b)
- end
- end
- def self.bind_append(*args, &b)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args, &b)
- else
- TkDatabaseClass.new(self.name).bind_append(*args, &b)
- end
- end
- def self.bind_remove(*args)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args)
- else
- TkDatabaseClass.new(self.name).bind_remove(*args)
- end
- end
- def self.bindinfo(*args)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args)
- else
- TkDatabaseClass.new(self.name).bindinfo(*args)
- end
- end
-end
diff --git a/ext/tk/lib/tk/grid.rb b/ext/tk/lib/tk/grid.rb
deleted file mode 100644
index 10fdf3569b..0000000000
--- a/ext/tk/lib/tk/grid.rb
+++ /dev/null
@@ -1,220 +0,0 @@
-#
-# tk/grid.rb : control grid geometry manager
-#
-require 'tk'
-
-module TkGrid
- include Tk
- extend Tk
-
- TkCommandNames = ['grid'.freeze].freeze
-
- def anchor(master, anchor=None)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- tk_call_without_enc('grid', 'anchor', master, anchor)
- end
-
- def bbox(master, *args)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- args.unshift(master)
- list(tk_call_without_enc('grid', 'bbox', *args))
- end
-
- def configure(win, *args)
- if args[-1].kind_of?(Hash)
- opts = args.pop
- else
- opts = {}
- end
- params = []
- params.push(_epath(win))
- args.each{|win|
- case win
- when '-', 'x', '^' # RELATIVE PLACEMENT
- params.push(win)
- else
- params.push(_epath(win))
- end
- }
- opts.each{|k, v|
- params.push("-#{k}")
- params.push((v.kind_of?(TkObject))? v.epath: v)
- }
- if Tk::TCL_MAJOR_VERSION < 8 ||
- (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION <= 3)
- if params[0] == '-' || params[0] == 'x' || params[0] == '^'
- tk_call_without_enc('grid', *params)
- else
- tk_call_without_enc('grid', 'configure', *params)
- end
- else
- tk_call_without_enc('grid', 'configure', *params)
- end
- end
- alias grid configure
-
- def columnconfigure(master, index, args)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- tk_call_without_enc("grid", 'columnconfigure',
- master, index, *hash_kv(args))
- end
-
- def rowconfigure(master, index, args)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- tk_call_without_enc("grid", 'rowconfigure', master, index, *hash_kv(args))
- end
-
- def columnconfiginfo(master, index, slot=nil)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- if slot
- case slot
- when 'uniform', :uniform
- tk_call_without_enc('grid', 'columnconfigure',
- master, index, "-#{slot}")
- else
- num_or_str(tk_call_without_enc('grid', 'columnconfigure',
- master, index, "-#{slot}"))
- end
- else
- #ilist = list(tk_call_without_enc('grid','columnconfigure',master,index))
- ilist = simplelist(tk_call_without_enc('grid', 'columnconfigure',
- master, index))
- info = {}
- while key = ilist.shift
- case key
- when 'uniform'
- info[key[1..-1]] = ilist.shift
- else
- info[key[1..-1]] = tk_tcl2ruby(ilist.shift)
- end
- end
- info
- end
- end
-
- def rowconfiginfo(master, index, slot=nil)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- if slot
- case slot
- when 'uniform', :uniform
- tk_call_without_enc('grid', 'rowconfigure',
- master, index, "-#{slot}")
- else
- num_or_str(tk_call_without_enc('grid', 'rowconfigure',
- master, index, "-#{slot}"))
- end
- else
- #ilist = list(tk_call_without_enc('grid', 'rowconfigure', master, index))
- ilist = simplelist(tk_call_without_enc('grid', 'rowconfigure',
- master, index))
- info = {}
- while key = ilist.shift
- case key
- when 'uniform'
- info[key[1..-1]] = ilist.shift
- else
- info[key[1..-1]] = tk_tcl2ruby(ilist.shift)
- end
- end
- info
- end
- end
-
- def add(widget, *args)
- configure(widget, *args)
- end
-
- def forget(*args)
- return '' if args.size == 0
- wins = args.collect{|win|
- # (win.kind_of?(TkObject))? win.epath: win
- _epath(win)
- }
- tk_call_without_enc('grid', 'forget', *wins)
- end
-
- def info(slave)
- # slave = slave.epath if slave.kind_of?(TkObject)
- slave = _epath(slave)
- #ilist = list(tk_call_without_enc('grid', 'info', slave))
- ilist = simplelist(tk_call_without_enc('grid', 'info', slave))
- info = {}
- while key = ilist.shift
- #info[key[1..-1]] = ilist.shift
- info[key[1..-1]] = tk_tcl2ruby(ilist.shift)
- end
- return info
- end
-
- def location(master, x, y)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- list(tk_call_without_enc('grid', 'location', master, x, y))
- end
-
- def propagate(master, mode=None)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- if mode == None
- bool(tk_call_without_enc('grid', 'propagate', master))
- else
- tk_call_without_enc('grid', 'propagate', master, mode)
- end
- end
-
- def remove(*args)
- return '' if args.size == 0
- wins = args.collect{|win|
- # (win.kind_of?(TkObject))? win.epath: win
- _epath(win)
- }
- tk_call_without_enc('grid', 'remove', *wins)
- end
-
- def size(master)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- list(tk_call_without_enc('grid', 'size', master))
- end
-
- def slaves(master, args)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- list(tk_call_without_enc('grid', 'slaves', master, *hash_kv(args)))
- end
-
- module_function :bbox, :forget, :propagate, :info
- module_function :remove, :size, :slaves, :location
- module_function :grid, :configure, :columnconfigure, :rowconfigure
- module_function :columnconfiginfo, :rowconfiginfo
-end
-=begin
-def TkGrid(win, *args)
- if args[-1].kind_of?(Hash)
- opts = args.pop
- else
- opts = {}
- end
- params = []
- params.push((win.kind_of?(TkObject))? win.epath: win)
- args.each{|win|
- case win
- when '-', 'x', '^' # RELATIVE PLACEMENT
- params.push(win)
- else
- params.push((win.kind_of?(TkObject))? win.epath: win)
- end
- }
- opts.each{|k, v|
- params.push("-#{k}")
- params.push((v.kind_of?(TkObject))? v.epath: v)
- }
- tk_call_without_enc("grid", *params)
-end
-=end
diff --git a/ext/tk/lib/tk/image.rb b/ext/tk/lib/tk/image.rb
deleted file mode 100644
index 35e2c4e394..0000000000
--- a/ext/tk/lib/tk/image.rb
+++ /dev/null
@@ -1,237 +0,0 @@
-#
-# tk/image.rb : treat Tk image objects
-#
-
-require 'tk'
-
-class TkImage<TkObject
- include Tk
-
- TkCommandNames = ['image'.freeze].freeze
-
- Tk_IMGTBL = TkCore::INTERP.create_table
- Tk_Image_ID = ['i'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ Tk_IMGTBL.clear }
-
- def self.new(keys=nil)
- if keys.kind_of?(Hash)
- name = nil
- if keys.key?(:imagename)
- name = keys[:imagename]
- elsif keys.key?('imagename')
- name = keys['imagename']
- end
- if name
- if name.kind_of?(TkImage)
- obj = name
- else
- name = _get_eval_string(name)
- obj = Tk_IMGTBL[name]
- end
- if obj
- if !(keys[:without_creating] || keys['without_creating'])
- keys = _symbolkey2str(keys)
- keys.delete('imagename')
- keys.delete('without_creating')
- obj.instance_eval{
- tk_call_without_enc('image', 'create',
- @type, @path, *hash_kv(keys, true))
- }
- end
- return obj
- end
- end
- end
- super(keys)
- end
-
- def initialize(keys=nil)
- @path = nil
- without_creating = false
- if keys.kind_of?(Hash)
- keys = _symbolkey2str(keys)
- @path = keys.delete('imagename')
- without_creating = keys.delete('without_creating')
- end
- unless @path
- # @path = Tk_Image_ID.join('')
- @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
- Tk_Image_ID[1].succ!
- end
- unless without_creating
- tk_call_without_enc('image', 'create',
- @type, @path, *hash_kv(keys, true))
- end
- Tk_IMGTBL[@path] = self
- end
-
- def delete
- Tk_IMGTBL.delete(@id) if @id
- tk_call_without_enc('image', 'delete', @path)
- self
- end
- def height
- number(tk_call_without_enc('image', 'height', @path))
- end
- def inuse
- bool(tk_call_without_enc('image', 'inuse', @path))
- end
- def itemtype
- tk_call_without_enc('image', 'type', @path)
- end
- def width
- number(tk_call_without_enc('image', 'width', @path))
- end
-
- def TkImage.names
- Tk.tk_call_without_enc('image', 'names').split.collect!{|id|
- (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
- }
- end
-
- def TkImage.types
- Tk.tk_call_without_enc('image', 'types').split
- end
-end
-
-class TkBitmapImage<TkImage
- def __strval_optkeys
- super() + ['maskdata', 'maskfile']
- end
- private :__strval_optkeys
-
- def initialize(*args)
- @type = 'bitmap'
- super(*args)
- end
-end
-
-class TkPhotoImage<TkImage
- NullArgOptionKeys = [ "shrink", "grayscale" ]
-
- def _photo_hash_kv(keys)
- keys = _symbolkey2str(keys)
- NullArgOptionKeys.collect{|opt|
- if keys[opt]
- keys[opt] = None
- else
- keys.delete(opt)
- end
- }
- keys.collect{|k,v|
- ['-' << k, v]
- }.flatten
- end
- private :_photo_hash_kv
-
- def initialize(*args)
- @type = 'photo'
- super(*args)
- end
-
- def blank
- tk_send_without_enc('blank')
- self
- end
-
- def cget(option)
- case option.to_s
- when 'data', 'file'
- tk_send 'cget', '-' << option.to_s
- else
- tk_tcl2ruby(tk_send('cget', '-' << option.to_s))
- end
- end
-
- def copy(src, *opts)
- if opts.size == 0
- tk_send('copy', src)
- elsif opts.size == 1 && opts[0].kind_of?(Hash)
- tk_send('copy', src, *_photo_hash_kv(opts[0]))
- else
- # for backward compatibility
- args = opts.collect{|term|
- if term.kind_of?(String) && term.include?(?\s)
- term.split
- else
- term
- end
- }.flatten
- tk_send('copy', src, *args)
- end
- self
- end
-
- def data(keys={})
- #tk_send('data', *_photo_hash_kv(keys))
- tk_split_list(tk_send('data', *_photo_hash_kv(keys)))
- end
-
- def get(x, y)
- tk_send('get', x, y).split.collect{|n| n.to_i}
- end
-
- def put(data, *opts)
- if opts == []
- tk_send('put', data)
- elsif opts.size == 1 && opts[0].kind_of?(Hash)
- tk_send('put', data, *_photo_hash_kv(opts[0]))
- else
- # for backward compatibility
- tk_send('put', data, '-to', *opts)
- end
- self
- end
-
- def read(file, *opts)
- if opts.size == 0
- tk_send('read', file)
- elsif opts.size == 1 && opts[0].kind_of?(Hash)
- tk_send('read', file, *_photo_hash_kv(opts[0]))
- else
- # for backward compatibility
- args = opts.collect{|term|
- if term.kind_of?(String) && term.include?(?\s)
- term.split
- else
- term
- end
- }.flatten
- tk_send('read', file, *args)
- end
- self
- end
-
- def redither
- tk_send 'redither'
- self
- end
-
- def get_transparency(x, y)
- bool(tk_send('transparency', 'get', x, y))
- end
- def set_transparency(x, y, st)
- tk_send('transparency', 'set', x, y, st)
- self
- end
-
- def write(file, *opts)
- if opts.size == 0
- tk_send('write', file)
- elsif opts.size == 1 && opts[0].kind_of?(Hash)
- tk_send('write', file, *_photo_hash_kv(opts[0]))
- else
- # for backward compatibility
- args = opts.collect{|term|
- if term.kind_of?(String) && term.include?(?\s)
- term.split
- else
- term
- end
- }.flatten
- tk_send('write', file, *args)
- end
- self
- end
-end
diff --git a/ext/tk/lib/tk/itemconfig.rb b/ext/tk/lib/tk/itemconfig.rb
deleted file mode 100644
index 0b84be38b8..0000000000
--- a/ext/tk/lib/tk/itemconfig.rb
+++ /dev/null
@@ -1,1056 +0,0 @@
-#
-# tk/itemconfig.rb : control item/tag configuration of widget
-#
-require 'tk'
-require 'tkutil'
-require 'tk/itemfont.rb'
-
-module TkItemConfigOptkeys
- include TkUtil
-
- def __item_numval_optkeys(id)
- []
- end
- private :__item_numval_optkeys
-
- def __item_numstrval_optkeys(id)
- []
- end
- private :__item_numstrval_optkeys
-
- def __item_boolval_optkeys(id)
- ['exportselection', 'jump', 'setgrid', 'takefocus']
- end
- private :__item_boolval_optkeys
-
- def __item_strval_optkeys(id)
- # maybe need to override
- [
- 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile',
- 'activebackground', 'activeforeground', 'background',
- 'disabledforeground', 'disabledbackground', 'foreground',
- 'highlightbackground', 'highlightcolor', 'insertbackground',
- 'selectbackground', 'selectforeground', 'troughcolor'
- ]
- end
- private :__item_strval_optkeys
-
- def __item_listval_optkeys(id)
- []
- end
- private :__item_listval_optkeys
-
- def __item_numlistval_optkeys(id)
- # maybe need to override
- ['dash', 'activedash', 'disableddash']
- end
- private :__item_numlistval_optkeys
-
- def __item_tkvariable_optkeys(id)
- ['variable', 'textvariable']
- end
- private :__item_tkvariable_optkeys
-
- def __item_val2ruby_optkeys(id) # { key=>method, ... }
- # The method is used to convert a opt-value to a ruby's object.
- # When get the value of the option "key", "method.call(id, val)" is called.
- {}
- end
- private :__item_val2ruby_optkeys
-
- def __item_ruby2val_optkeys(id) # { key=>method, ... }
- # The method is used to convert a ruby's object to a opt-value.
- # When set the value of the option "key", "method.call(id, val)" is called.
- # That is, "-#{key} #{method.call(id, value)}".
- {}
- end
- private :__item_ruby2val_optkeys
-
- def __item_methodcall_optkeys(id) # { key=>method, ... }
- # Use the method for both of get and set.
- # Usually, the 'key' will not be a widget option.
- #
- # maybe need to override
- # {'coords'=>'coords'}
- {}
- end
- private :__item_methodcall_optkeys
-
- ################################################
-
- def __item_keyonly_optkeys(id) # { def_key=>(undef_key|nil), ... }
- # maybe need to override
- {}
- end
- private :__item_keyonly_optkeys
-
-
- def __conv_item_keyonly_opts(id, keys)
- return keys unless keys.kind_of?(Hash)
- keyonly = __item_keyonly_optkeys(id)
- keys2 = {}
- keys.each{|k, v|
- optkey = keyonly.find{|kk,vv| kk.to_s == k.to_s}
- if optkey
- defkey, undefkey = optkey
- if v
- keys2[defkey.to_s] = None
- else
- keys2[undefkey.to_s] = None
- end
- else
- keys2[k.to_s] = v
- end
- }
- keys2
- end
-
- def itemconfig_hash_kv(id, keys, enc_mode = nil, conf = nil)
- hash_kv(__conv_item_keyonly_opts(id, keys), enc_mode, conf)
- end
-end
-
-module TkItemConfigMethod
- include TkUtil
- include TkTreatItemFont
- include TkItemConfigOptkeys
-
- def __item_cget_cmd(id)
- # maybe need to override
- [self.path, 'itemcget', id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- # maybe need to override
- [self.path, 'itemconfigure', id]
- end
- private :__item_config_cmd
-
- def __item_confinfo_cmd(id)
- # maybe need to override
- __item_config_cmd(id)
- end
- private :__item_confinfo_cmd
-
- def __item_configinfo_struct(id)
- # maybe need to override
- {:key=>0, :alias=>1, :db_name=>1, :db_class=>2,
- :default_value=>3, :current_value=>4}
- end
- private :__item_configinfo_struct
-
- ################################################
-
- def tagid(tagOrId)
- # maybe need to override
- tagOrId
- end
-
- ################################################
-
- def itemcget(tagOrId, option)
- orig_opt = option
- option = option.to_s
-
- if option.length == 0
- fail ArgumentError, "Invalid option `#{orig_opt.inspect}'"
- end
-
- if ( method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[option] )
- optval = tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))
- begin
- return method.call(tagOrId, optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
- return optval
- end
- end
-
- if ( method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[option] )
- return self.__send__(method, tagOrId)
- end
-
- case option
- when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
- begin
- number(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")))
- rescue
- nil
- end
-
- when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
- num_or_str(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")))
-
- when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
- begin
- bool(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")))
- rescue
- nil
- end
-
- when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
- simplelist(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")))
-
- when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
- conf = tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))
- if conf =~ /^[0-9]/
- list(conf)
- else
- conf
- end
-
- when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
- v = tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))
- (v.empty?)? nil: TkVarAccess.new(v)
-
- when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
- _fromUTF8(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")))
-
- when /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/
- fontcode = $1
- fontkey = $2
- fnt = tk_tcl2ruby(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{fontkey}")), true)
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(tagid(tagOrId), fontkey)
- end
- if fontcode == 'kanji' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")), true)
- end
- end
-
- def itemconfigure(tagOrId, slot, value=None)
- if slot.kind_of? Hash
- slot = _symbolkey2str(slot)
-
- __item_methodcall_optkeys(tagid(tagOrId)).each{|key, method|
- value = slot.delete(key.to_s)
- self.__send__(method, tagOrId, value) if value
- }
-
- __item_ruby2val_optkeys(tagid(tagOrId)).each{|key, method|
- key = key.to_s
- slot[key] = method.call(tagOrId, slot[key]) if slot.has_key?(key)
- }
-
- __item_keyonly_optkeys(tagid(tagOrId)).each{|defkey, undefkey|
- conf = slot.find{|kk, vv| kk == defkey.to_s}
- if conf
- k, v = conf
- if v
- slot[k] = None
- else
- slot[undefkey.to_s] = None if undefkey
- slot.delete(k)
- end
- end
- }
-
- if (slot.find{|k, v| k =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/})
- tagfont_configure(tagid(tagOrId), slot)
- elsif slot.size > 0
- tk_call(*(__item_config_cmd(tagid(tagOrId)).concat(hash_kv(slot))))
- end
-
- else
- orig_slot = slot
- slot = slot.to_s
- if slot.length == 0
- fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
- end
-
- if ( conf = __item_keyonly_optkeys(tagid(tagOrId)).find{|k, v| k.to_s == slot } )
- defkey, undefkey = conf
- if value
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{defkey}"))
- elsif undefkey
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{undefkey}"))
- end
- elsif ( method = _symbolkey2str(__item_ruby2val_optkeys(tagid(tagOrId)))[slot] )
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}" << method.call(tagOrId, value)))
- elsif ( method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot] )
- self.__send__(method, tagOrId, value)
- elsif (slot =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
- if value == None
- tagfontobj(tagid(tagOrId), $2)
- else
- tagfont_configure(tagid(tagOrId), {slot=>value})
- end
- else
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}" << value))
- end
- end
- self
- end
-
- def itemconfiginfo(tagOrId, slot = nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
- fontkey = $2
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}")), false, true)
- conf[__item_configinfo_struct(tagid(tagOrId))[:key]] =
- conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1]
- if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
- || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), fontkey)
- elsif ( __item_configinfo_struct(tagid(tagOrId))[:alias] \
- && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- )
- conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] =
- conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1]
- end
- conf
- else
- if slot
- slot = slot.to_s
- case slot
- when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
- method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot]
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- optval = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
- begin
- val = method.call(tagOrId, optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = val
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- optval = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
- begin
- val = method.call(tagOrId, optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}lcall(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = val
- end
-
- when /^(#{__item_methodcall_optkeys(tagid(tagOrId)).keys.join('|')})$/
- method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot]
- return [slot, '', '', '', self.__send__(method, tagOrId)]
-
- when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- number(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
- end
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- number(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
- end
- end
-
- when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
-
- when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- bool(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
- end
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- bool(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
- end
- end
-
- when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
-
- when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =~ /^[0-9]/ )
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =~ /^[0-9]/ )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
-
- when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- v = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
- if v.empty?
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
- else
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkVarAccess.new(v)
- end
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- v = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
- if v.empty?
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
- else
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v)
- end
- end
-
- else
- # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_list(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), 0, false, true)
- end
- conf[__item_configinfo_struct(tagid(tagOrId))[:key]] =
- conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1]
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:alias] \
- && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- )
- conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] =
- conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1]
- end
-
- conf
-
- else
- # ret = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))))).collect{|conflist|
- # conf = tk_split_simplelist(conflist)
- ret = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false).collect{|conflist|
- conf = tk_split_simplelist(conflist, false, true)
- conf[__item_configinfo_struct(tagid(tagOrId))[:key]] =
- conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1]
-
- optkey = conf[__item_configinfo_struct(tagid(tagOrId))[:key]]
- case optkey
- when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
- method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[optkey]
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- optval = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
- begin
- val = method(tagOrId, optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = val
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- optval = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
- begin
- val = method.call(tagOrId, optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = val
- end
-
- when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
- # do nothing
-
- when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- number(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
- end
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- number(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
- end
- end
-
- when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
-
- when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- bool(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
- end
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- bool(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
- end
- end
-
- when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
-
- when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =~ /^[0-9]/ )
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =~ /^[0-9]/ )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
-
- when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- v = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
- if v.empty?
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
- else
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkVarAccess.new(v)
- end
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- v = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
- if v.empty?
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
- else
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new
- end
- end
-
- else
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- if conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]].index('{')
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- tk_split_list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- else
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- tk_tcl2ruby(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- end
- if conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
- if conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]].index('{')
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- tk_split_list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- else
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- tk_tcl2ruby(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
- end
- end
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:alias] \
- && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- )
- conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] =
- conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1]
- end
-
- conf
- }
-
- __item_font_optkeys(tagid(tagOrId)).each{|optkey|
- optkey = optkey.to_s
- fontconf = ret.assoc(optkey)
- if fontconf && fontconf.size > 2
- ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/}
- fontconf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), optkey)
- ret.push(fontconf)
- end
- }
-
- __item_methodcall_optkeys(tagid(tagOrId)).each{|optkey, method|
- ret << [optkey.to_s, '', '', '', self.__send__(method, tagOrId)]
- }
-
- ret
- end
- end
-
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
- fontkey = $2
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}")), false, true)
- conf[__item_configinfo_struct(tagid(tagOrId))[:key]] =
- conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1]
-
- if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
- || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = fontobj(tagid(tagOrId), fontkey)
- { conf.shift => conf }
- elsif ( __item_configinfo_struct(tagid(tagOrId))[:alias] \
- && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
- if conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?-
- conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] =
- conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1]
- end
- { conf[0] => conf[1] }
- else
- { conf.shift => conf }
- end
- else
- if slot
- slot = slot.to_s
- case slot
- when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
- method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot]
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- optval = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
- begin
- val = method.call(tagOrId, optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = val
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- optval = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
- begin
- val = method.call(tagOrId, optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = val
- end
-
- when /^(#{__item_methodcall_optkeys(tagid(tagOrId)).keys.join('|')})$/
- method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot]
- return {slot => ['', '', '', self.__send__(method, tagOrId)]}
-
- when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- number(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
- end
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- number(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
- end
- end
-
- when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- num_or_stre(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
-
- when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- bool(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
- end
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- bool(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
- end
- end
-
- when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
-
- when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =~ /^[0-9]/ )
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =~ /^[0-9]/ )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
-
- when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
- # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
- conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- v = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
- if v.empty?
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
- else
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkVarAccess.new(v)
- end
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- v = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
- if v.empty?
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
- else
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v)
- end
- end
-
- else
- # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
- conf = tk_split_list(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), 0, false, true)
- end
- conf[__item_configinfo_struct(tagid(tagOrId))[:key]] =
- conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1]
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:alias] \
- && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
- if conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?-
- conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] =
- conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1]
- end
- { conf[0] => conf[1] }
- else
- { conf.shift => conf }
- end
-
- else
- ret = {}
- # tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))))).each{|conflist|
- # conf = tk_split_simplelist(conflist)
- tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false).each{|conflist|
- conf = tk_split_simplelist(conflist, false, true)
- conf[__item_configinfo_struct(tagid(tagOrId))[:key]] =
- conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1]
-
- optkey = conf[__item_configinfo_struct(tagid(tagOrId))[:key]]
- case optkey
- when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
- method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[optkey]
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- optval = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
- begin
- val = method.call(tagOrId, optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = val
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- optval = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
- begin
- val = method.call(tagOrId, optval)
- rescue => e
- warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
- val = optval
- end
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = val
- end
-
- when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
- # do nothing
-
- when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- number(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
- end
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- number(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
- end
- end
-
- when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
-
- when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- bool(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
- end
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- begin
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- bool(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- rescue
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
- end
- end
-
- when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
-
- when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =~ /^[0-9]/ )
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =~ /^[0-9]/ )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
-
- when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- v = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
- if v.empty?
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
- else
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkVarAccess.new(v)
- end
- end
- if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
- v = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
- if v.empty?
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
- else
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v)
- end
- end
-
- else
- if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
- && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
- if conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]].index('{')
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- tk_split_list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- else
- conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =
- tk_tcl2ruby(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]])
- end
- end
- if conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
- if conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]].index('{')
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- tk_split_list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- else
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =
- tk_tcl2ruby(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]])
- end
- end
- end
-
- if ( __item_configinfo_struct(tagid(tagOrId))[:alias] \
- && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
- if conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?-
- conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] =
- conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1]
- end
- ret[conf[0]] = conf[1]
- else
- ret[conf.shift] = conf
- end
- }
-
- __item_font_optkeys(tagid(tagOrId)).each{|optkey|
- optkey = optkey.to_s
- fontconf = ret[optkey]
- if fontconf.kind_of?(Array)
- ret.delete(optkey)
- ret.delete('latin' << optkey)
- ret.delete('ascii' << optkey)
- ret.delete('kanji' << optkey)
- fontconf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), optkey)
- ret[optkey] = fontconf
- end
- }
-
- __item_methodcall_optkeys(tagid(tagOrId)).each{|optkey, method|
- ret[optkey.to_s] = ['', '', '', self.__send__(method, tagOrId)]
- }
-
- ret
- end
- end
- end
- end
-
- def current_itemconfiginfo(tagOrId, slot = nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- org_slot = slot
- begin
- conf = itemconfiginfo(tagOrId, slot)
- if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
- || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
- return {conf[0] => conf[-1]}
- end
- slot = conf[__item_configinfo_struct(tagid(tagOrId))[:alias]]
- end while(org_slot != slot)
- fail RuntimeError,
- "there is a configure alias loop about '#{org_slot}'"
- else
- ret = {}
- itemconfiginfo(tagOrId).each{|conf|
- if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
- || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
- ret[conf[0]] = conf[-1]
- end
- }
- ret
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- ret = {}
- itemconfiginfo(slot).each{|key, conf|
- ret[key] = conf[-1] if conf.kind_of?(Array)
- }
- ret
- end
- end
-end
diff --git a/ext/tk/lib/tk/itemfont.rb b/ext/tk/lib/tk/itemfont.rb
deleted file mode 100644
index ab9e3ff6c9..0000000000
--- a/ext/tk/lib/tk/itemfont.rb
+++ /dev/null
@@ -1,300 +0,0 @@
-#
-# tk/itemfont.rb : control font of widget items
-#
-require 'tk'
-
-module TkItemFontOptkeys
- def __item_font_optkeys(id)
- # maybe need to override
- ['font']
- end
- private :__item_font_optkeys
-end
-
-module TkTreatItemFont
- include TkItemFontOptkeys
-
- def __item_pathname(id)
- # maybe need to override
- [self.path, id].join(';')
- end
- private :__item_pathname
-
- ################################################
-
- def tagfont_configinfo(tagOrId, key = nil)
- optkeys = __item_font_optkeys(tagid(tagOrId))
- if key && !optkeys.find{|opt| opt.to_s == key.to_s}
- fail ArgumentError, "unknown font option name `#{key}'"
- end
-
- win, tag = __item_pathname(tagid(tagOrId)).split(';')
-
- if key
- pathname = [win, tag, key].join(';')
- TkFont.used_on(pathname) ||
- TkFont.init_widget_font(pathname,
- *(__item_confinfo_cmd(tagid(tagOrId))))
- elsif optkeys.size == 1
- pathname = [win, tag, optkeys[0]].join(';')
- TkFont.used_on(pathname) ||
- TkFont.init_widget_font(pathname,
- *(__item_confinfo_cmd(tagid(tagOrId))))
- else
- fonts = {}
- optkeys.each{|key|
- key = key.to_s
- pathname = [win, tag, key].join(';')
- fonts[key] =
- TkFont.used_on(pathname) ||
- TkFont.init_widget_font(pathname,
- *(__item_confinfo_cmd(tagid(tagOrId))))
- }
- fonts
- end
- end
- alias tagfontobj tagfont_configinfo
-
- def tagfont_configure(tagOrId, slot)
- pathname = __item_pathname(tagid(tagOrId))
-
- slot = _symbolkey2str(slot)
-
- __item_font_optkeys(tagid(tagOrId)).each{|optkey|
- optkey = optkey.to_s
- l_optkey = 'latin' << optkey
- a_optkey = 'ascii' << optkey
- k_optkey = 'kanji' << optkey
-
- if slot.key?(optkey)
- fnt = slot.delete(optkey)
- if fnt.kind_of?(TkFont)
- slot.delete(l_optkey)
- slot.delete(a_optkey)
- slot.delete(k_optkey)
-
- fnt.call_font_configure([pathname, optkey],
- *(__item_config_cmd(tagid(tagOrId)) << {}))
- next
- else
- if fnt
- if (slot.key?(l_optkey) ||
- slot.key?(a_optkey) ||
- slot.key?(k_optkey))
- fnt = TkFont.new(fnt)
-
- lfnt = slot.delete(l_optkey)
- lfnt = slot.delete(a_optkey) if slot.key?(a_optkey)
- kfnt = slot.delete(k_optkey)
-
- fnt.latin_replace(lfnt) if lfnt
- fnt.kanji_replace(kfnt) if kfnt
-
- fnt.call_font_configure([pathname, optkey],
- *(__item_config_cmd(tagid(tagOrId)) << {}))
- next
- else
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << fnt))
- end
- end
- next
- end
- end
-
- lfnt = slot.delete(l_optkey)
- lfnt = slot.delete(a_optkey) if slot.key?(a_optkey)
- kfnt = slot.delete(k_optkey)
-
- if lfnt && kfnt
- TkFont.new(lfnt, kfnt).call_font_configure([pathname, optkey],
- *(__item_config_cmd(tagid(tagOrId)) << {}))
- elsif lfnt
- latintagfont_configure([lfnt, optkey])
- elsif kfnt
- kanjitagfont_configure([kfnt, optkey])
- end
- }
-
- # configure other (without font) options
- tk_call(*(__item_config_cmd(tagid(tagOrId)).concat(hash_kv(slot)))) if slot != {}
- self
- end
-
- def latintagfont_configure(tagOrId, ltn, keys=nil)
- if ltn.kind_of?(Array)
- key = ltn[1]
- ltn = ltn[0]
- else
- key = nil
- end
-
- optkeys = __item_font_optkeys(tagid(tagOrId))
- if key && !optkeys.find{|opt| opt.to_s == key.to_s}
- fail ArgumentError, "unknown font option name `#{key}'"
- end
-
- win, tag = __item_pathname(tagid(tagOrId)).split(';')
-
- optkeys = [key] if key
-
- optkeys.each{|optkey|
- optkey = optkey.to_s
-
- pathname = [win, tag, optkey].join(';')
-
- if (fobj = TkFont.used_on(pathname))
- fobj = TkFont.new(fobj) # create a new TkFont object
- elsif Tk::JAPANIZED_TK
- fobj = fontobj # create a new TkFont object
- else
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << ltn))
- next
- end
-
- if fobj.kind_of?(TkFont)
- if ltn.kind_of?(TkFont)
- conf = {}
- ltn.latin_configinfo.each{|key,val| conf[key] = val}
- if keys
- fobj.latin_configure(conf.update(keys))
- else
- fobj.latin_configure(conf)
- end
- else
- fobj.latin_replace(ltn)
- end
- end
-
- fobj.call_font_configure([pathname, optkey], *(__item_config_cmd(tagid(tagOrId)) << {}))
- }
- self
- end
- alias asciitagfont_configure latintagfont_configure
-
- def kanjitagfont_configure(tagOrId, knj, keys=nil)
- if knj.kind_of?(Array)
- key = knj[1]
- knj = knj[0]
- else
- key = nil
- end
-
- optkeys = __item_font_optkeys(tagid(tagOrId))
- if key && !optkeys.find{|opt| opt.to_s == key.to_s}
- fail ArgumentError, "unknown font option name `#{key}'"
- end
-
- win, tag = __item_pathname(tagid(tagOrId)).split(';')
-
- optkeys = [key] if key
-
- optkeys.each{|optkey|
- optkey = optkey.to_s
-
- pathname = [win, tag, optkey].join(';')
-
- if (fobj = TkFont.used_on(pathname))
- fobj = TkFont.new(fobj) # create a new TkFont object
- elsif Tk::JAPANIZED_TK
- fobj = fontobj # create a new TkFont object
- else
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << knj))
- next
- end
-
- if fobj.kind_of?(TkFont)
- if knj.kind_of?(TkFont)
- conf = {}
- knj.kanji_configinfo.each{|key,val| conf[key] = val}
- if keys
- fobj.kanji_configure(conf.update(keys))
- else
- fobj.kanji_configure(conf)
- end
- else
- fobj.kanji_replace(knj)
- end
- end
-
- fobj.call_font_configure([pathname, optkey], *(__item_config_cmd(tagid(tagOrId)) << {}))
- }
- self
- end
-
- def tagfont_copy(tagOrId, win, wintag=nil, winkey=nil, targetkey=nil)
- if wintag
- if winkey
- fnt = win.tagfontobj(wintag, winkey).dup
- else
- fnt = win.tagfontobj(wintag).dup
- end
- else
- if winkey
- fnt = win.fontobj(winkey).dup
- else
- fnt = win.fontobj.dup
- end
- end
-
- if targetkey
- fnt.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey],
- *(__item_config_cmd(tagid(tagOrId)) << {}))
- else
- fnt.call_font_configure(__item_pathname(tagid(tagOrId)),
- *(__item_config_cmd(tagid(tagOrId)) << {}))
- end
- self
- end
-
-
- def latintagfont_copy(tagOrId, win, wintag=nil, winkey=nil, targetkey=nil)
- if targetkey
- fontobj(targetkey).dup.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey],
- *(__item_config_cmd(tagid(tagOrId)) << {}))
- else
- fontobj.dup.call_font_configure(__item_pathname(tagid(tagOrId)),
- *(__item_config_cmd(tagid(tagOrId)) << {}))
- end
-
- if wintag
- if winkey
- fontobj.latin_replace(win.tagfontobj(wintag, winkey).latin_font_id)
- else
- fontobj.latin_replace(win.tagfontobj(wintag).latin_font_id)
- end
- else
- if winkey
- fontobj.latin_replace(win.fontobj(winkey).latin_font_id)
- else
- fontobj.latin_replace(win.fontobj.latin_font_id)
- end
- end
- self
- end
- alias asciitagfont_copy latintagfont_copy
-
- def kanjifont_copy(tagOrId, win, wintag=nil, winkey=nil, targetkey=nil)
- if targetkey
- fontobj(targetkey).dup.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey],
- *(__item_config_cmd(tagid(tagOrId)) << {}))
- else
- fontobj.dup.call_font_configure(__item_pathname(tagid(tagOrId)),
- *(__item_config_cmd(tagid(tagOrId)) << {}))
- end
-
- if wintag
- if winkey
- fontobj.kanji_replace(win.tagfontobj(wintag, winkey).kanji_font_id)
- else
- fontobj.kanji_replace(win.tagfontobj(wintag).kanji_font_id)
- end
- else
- if winkey
- fontobj.kanji_replace(win.fontobj(winkey).kanji_font_id)
- else
- fontobj.kanji_replace(win.fontobj.kanji_font_id)
- end
- end
- self
- end
-end
diff --git a/ext/tk/lib/tk/kinput.rb b/ext/tk/lib/tk/kinput.rb
deleted file mode 100644
index a29dbcdb72..0000000000
--- a/ext/tk/lib/tk/kinput.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# tk/kinput.rb : control kinput
-#
-require 'tk'
-
-module TkKinput
- include Tk
- extend Tk
-
- TkCommandNames = [
- 'kinput_start'.freeze,
- 'kinput_send_spot'.freeze,
- 'kanjiInput'.freeze
- ].freeze
-
- def TkKinput.start(win, style=None)
- tk_call('kinput_start', win, style)
- end
- def kinput_start(style=None)
- TkKinput.start(self, style)
- end
-
- def TkKinput.send_spot(win)
- tk_call('kinput_send_spot', win)
- end
- def kinput_send_spot
- TkKinput.send_spot(self)
- end
-
- def TkKinput.input_start(win, keys=nil)
- tk_call('kanjiInput', 'start', win, *hash_kv(keys))
- end
- def kanji_input_start(keys=nil)
- TkKinput.input_start(self, keys)
- end
-
- def TkKinput.attribute_config(win, slot, value=None)
- if slot.kind_of? Hash
- tk_call('kanjiInput', 'attribute', win, *hash_kv(slot))
- else
- tk_call('kanjiInput', 'attribute', win, "-#{slot}", value)
- end
- end
- def kinput_attribute_config(slot, value=None)
- TkKinput.attribute_config(self, slot, value)
- end
-
- def TkKinput.attribute_info(win, slot=nil)
- if slot
- conf = tk_split_list(tk_call('kanjiInput', 'attribute',
- win, "-#{slot}"))
- conf[0] = conf[0][1..-1]
- conf
- else
- tk_split_list(tk_call('kanjiInput', 'attribute', win)).collect{|conf|
- conf[0] = conf[0][1..-1]
- conf
- }
- end
- end
- def kinput_attribute_info(slot=nil)
- TkKinput.attribute_info(self, slot)
- end
-
- def TkKinput.input_end(win)
- tk_call('kanjiInput', 'end', win)
- end
- def kanji_input_end
- TkKinput.input_end(self)
- end
-end
diff --git a/ext/tk/lib/tk/label.rb b/ext/tk/lib/tk/label.rb
deleted file mode 100644
index 8b45db9b30..0000000000
--- a/ext/tk/lib/tk/label.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# tk/label.rb : treat label widget
-#
-require 'tk'
-
-class TkLabel<TkWindow
- TkCommandNames = ['label'.freeze].freeze
- WidgetClassName = 'Label'.freeze
- WidgetClassNames[WidgetClassName] = self
- #def create_self(keys)
- # if keys and keys != None
- # tk_call_without_enc('label', @path, *hash_kv(keys, true))
- # else
- # tk_call_without_enc('label', @path)
- # end
- #end
- #private :create_self
-end
diff --git a/ext/tk/lib/tk/labelframe.rb b/ext/tk/lib/tk/labelframe.rb
deleted file mode 100644
index 73d5603200..0000000000
--- a/ext/tk/lib/tk/labelframe.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# tk/labelframe.rb : treat labelframe widget
-#
-require 'tk'
-require 'tk/frame'
-
-class TkLabelFrame<TkFrame
- TkCommandNames = ['labelframe'.freeze].freeze
- WidgetClassName = 'Labelframe'.freeze
- WidgetClassNames[WidgetClassName] = self
- #def create_self(keys)
- # if keys and keys != None
- # tk_call_without_enc('labelframe', @path, *hash_kv(keys, true))
- # else
- # tk_call_without_enc('labelframe', @path)
- # end
- #end
- #private :create_self
-
- def __val2ruby_optkeys # { key=>proc, ... }
- super().update('labelwidget'=>proc{|v| window(v)})
- end
- private :__val2ruby_optkeys
-end
-TkLabelframe = TkLabelFrame
diff --git a/ext/tk/lib/tk/listbox.rb b/ext/tk/lib/tk/listbox.rb
deleted file mode 100644
index 41d02d279e..0000000000
--- a/ext/tk/lib/tk/listbox.rb
+++ /dev/null
@@ -1,279 +0,0 @@
-#
-# tk/listbox.rb : treat listbox widget
-#
-require 'tk'
-require 'tk/itemconfig'
-require 'tk/scrollable'
-require 'tk/txtwin_abst'
-
-module TkListItemConfig
- include TkItemConfigMethod
-
- def __item_listval_optkeys(id)
- []
- end
- private :__item_listval_optkeys
-end
-
-class TkListbox<TkTextWin
- include TkListItemConfig
- include Scrollable
-
- TkCommandNames = ['listbox'.freeze].freeze
- WidgetClassName = 'Listbox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- #def create_self(keys)
- # if keys and keys != None
- # tk_call_without_enc('listbox', @path, *hash_kv(keys, true))
- # else
- # tk_call_without_enc('listbox', @path)
- # end
- #end
- #private :create_self
-
- def __tkvariable_optkeys
- super() << 'listvariable'
- end
- private :__tkvariable_optkeys
-
- def tagid(id)
- #id.to_s
- _get_eval_string(id)
- end
-
- def activate(y)
- tk_send_without_enc('activate', y)
- self
- end
- def curselection
- list(tk_send_without_enc('curselection'))
- end
- def get(first, last=nil)
- if last
- # tk_split_simplelist(_fromUTF8(tk_send_without_enc('get', first, last)))
- tk_split_simplelist(tk_send_without_enc('get', first, last), false, true)
- else
- _fromUTF8(tk_send_without_enc('get', first))
- end
- end
- def nearest(y)
- tk_send_without_enc('nearest', y).to_i
- end
- def size
- tk_send_without_enc('size').to_i
- end
- def selection_anchor(index)
- tk_send_without_enc('selection', 'anchor', index)
- self
- end
- def selection_clear(first, last=None)
- tk_send_without_enc('selection', 'clear', first, last)
- self
- end
- def selection_includes(index)
- bool(tk_send_without_enc('selection', 'includes', index))
- end
- def selection_set(first, last=None)
- tk_send_without_enc('selection', 'set', first, last)
- self
- end
-
- def index(idx)
- tk_send_without_enc('index', idx).to_i
- end
-
- def value
- get('0', 'end')
- end
-
- def value= (vals)
- unless vals.kind_of?(Array)
- fail ArgumentError, 'an Array is expected'
- end
- tk_send_without_enc('delete', '0', 'end')
- tk_send_without_enc('insert', '0',
- *(vals.collect{|v| _get_eval_enc_str(v)}))
- vals
- end
-
- def clear
- tk_send_without_enc('delete', '0', 'end')
- self
- end
- alias erase clear
-
-=begin
- def itemcget(index, key)
- case key.to_s
- when 'text', 'label', 'show'
- _fromUTF8(tk_send_without_enc('itemcget', index, "-#{key}"))
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_send('itemcget', index, "-#{key}"))
- fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('itemcget', index,
- '-font')))
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(index, fnt)
- end
- if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby(_fromUTF8(tk_send_without_enc('itemcget', index, "-#{key}")))
- end
- end
- def itemconfigure(index, key, val=None)
- if key.kind_of? Hash
- if (key['font'] || key[:font] ||
- key['kanjifont'] || key[:kanjifont] ||
- key['latinfont'] || key[:latinfont] ||
- key['asciifont'] || key[:asciifont] )
- tagfont_configure(index, _symbolkey2str(key))
- else
- tk_send_without_enc('itemconfigure', index, *hash_kv(key, true))
- end
-
- else
- if (key == 'font' || key == :font ||
- key == 'kanjifont' || key == :kanjifont ||
- key == 'latinfont' || key == :latinfont ||
- key == 'asciifont' || key == :asciifont )
- if val == None
- tagfontobj(index)
- else
- tagfont_configure(index, {key=>val})
- end
- else
- tk_call('itemconfigure', index, "-#{key}", val)
- end
- end
- self
- end
-
- def itemconfiginfo(index, key=nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- case key.to_s
- when 'text', 'label', 'show'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
- when 'font', 'kanjifont'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
- conf[4] = tagfont_configinfo(index, conf[4])
- else
- conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', index))).collect{|conflist|
- conf = tk_split_simplelist(conflist)
- conf[0] = conf[0][1..-1]
- case conf[0]
- when 'text', 'label', 'show'
- else
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- if conf[4]
- if conf[4].index('{')
- conf[4] = tk_split_list(conf[4])
- else
- conf[4] = tk_tcl2ruby(conf[4])
- end
- end
- end
- conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
- conf
- }
- fontconf = ret.assoc('font')
- if fontconf
- ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
- fontconf[4] = tagfont_configinfo(index, fontconf[4])
- ret.push(fontconf)
- else
- ret
- end
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- case key.to_s
- when 'text', 'label', 'show'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
- when 'font', 'kanjifont'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
- conf[4] = tagfont_configinfo(index, conf[4])
- else
- conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
- end
- key = conf.shift[1..-1]
- { key => conf }
- else
- ret = {}
- tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', index))).each{|conflist|
- conf = tk_split_simplelist(conflist)
- key = conf.shift[1..-1]
- case key
- when 'text', 'label', 'show'
- else
- if conf[2]
- if conf[2].index('{')
- conf[2] = tk_split_list(conf[2])
- else
- conf[2] = tk_tcl2ruby(conf[2])
- end
- end
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- end
- if conf.size == 1
- ret[key] = conf[0][1..-1] # alias info
- else
- ret[key] = conf
- end
- }
- fontconf = ret['font']
- if fontconf
- ret.delete('font')
- ret.delete('kanjifont')
- fontconf[3] = tagfont_configinfo(index, fontconf[3])
- ret['font'] = fontconf
- end
- ret
- end
- end
- end
-
- def current_itemconfiginfo(index, key=nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- conf = itemconfiginfo(index, key)
- {conf[0] => conf[4]}
- else
- ret = {}
- itemconfiginfo(index).each{|conf|
- ret[conf[0]] = conf[4] if conf.size > 2
- }
- ret
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- ret = {}
- itemconfiginfo(index, key).each{|k, conf|
- ret[k] = conf[-1] if conf.kind_of?(Array)
- }
- ret
- end
- end
-=end
-end
diff --git a/ext/tk/lib/tk/macpkg.rb b/ext/tk/lib/tk/macpkg.rb
deleted file mode 100644
index 1802073f46..0000000000
--- a/ext/tk/lib/tk/macpkg.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-#
-# tk/macpkg.rb : methods for Tcl/Tk packages for Macintosh
-# 2000/11/22 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
-#
-# ATTENTION !!
-# This is NOT TESTED. Because I have no test-environment.
-#
-#
-require 'tk'
-
-module Tk
- def Tk.load_tclscript_rsrc(resource_name, file=None)
- # Mac only
- tk_call('source', '-rsrc', resource_name, file)
- end
-
- def Tk.load_tclscript_rsrcid(resource_id, file=None)
- # Mac only
- tk_call('source', '-rsrcid', resource_id, file)
- end
-end
-
-module TkMacResource
- extend Tk
- extend TkMacResource
-
- TkCommandNames = ['resource'.freeze].freeze
-
- PACKAGE_NAME = 'resource'.freeze
- def self.package_name
- PACKAGE_NAME
- end
-
- tk_call_without_enc('package', 'require', 'resource')
-
- def close(rsrcRef)
- tk_call('resource', 'close', rsrcRef)
- end
-
- def delete(rsrcType, opts=nil)
- tk_call('resource', 'delete', *(hash_kv(opts) << rsrcType))
- end
-
- def files(rsrcRef=nil)
- if rsrcRef
- tk_call('resource', 'files', rsrcRef)
- else
- tk_split_simplelist(tk_call('resource', 'files'))
- end
- end
-
- def list(rsrcType, rsrcRef=nil)
- tk_split_simplelist(tk_call('resource', 'list', rsrcType, rsrcRef))
- end
-
- def open(fname, access=nil)
- tk_call('resource', 'open', fname, access)
- end
-
- def read(rsrcType, rsrcID, rsrcRef=nil)
- tk_call('resource', 'read', rsrcType, rsrcID, rsrcRef)
- end
-
- def types(rsrcRef=nil)
- tk_split_simplelist(tk_call('resource', 'types', rsrcRef))
- end
-
- def write(rsrcType, data, opts=nil)
- tk_call('resource', 'write', *(hash_kv(opts) << rsrcType << data))
- end
-
- module_function :close, :delete, :files, :list, :open, :read, :types, :write
-end
diff --git a/ext/tk/lib/tk/menu.rb b/ext/tk/lib/tk/menu.rb
deleted file mode 100644
index ddddc8e53e..0000000000
--- a/ext/tk/lib/tk/menu.rb
+++ /dev/null
@@ -1,632 +0,0 @@
-#
-# tk/menu.rb : treat menu and menubutton
-#
-require 'tk'
-require 'tk/itemconfig'
-require 'tk/menuspec'
-
-module TkMenuEntryConfig
- include TkItemConfigMethod
-
- def __item_cget_cmd(id)
- [self.path, 'entrycget', id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- [self.path, 'entryconfigure', id]
- end
- private :__item_config_cmd
-
- def __item_strval_optkeys(id)
- super(id) << 'selectcolor'
- end
- private :__item_strval_optkeys
-
- def __item_listval_optkeys(id)
- []
- end
- private :__item_listval_optkeys
-
- def __item_val2ruby_optkeys(id) # { key=>proc, ... }
- super(id).update('menu'=>proc{|i, v| window(v)})
- end
- private :__item_val2ruby_optkeys
-
- alias entrycget itemcget
- alias entryconfigure itemconfigure
- alias entryconfiginfo itemconfiginfo
- alias current_entryconfiginfo current_itemconfiginfo
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-end
-
-class TkMenu<TkWindow
- include Wm
- include TkMenuEntryConfig
- extend TkMenuSpec
-
- TkCommandNames = ['menu'.freeze].freeze
- WidgetClassName = 'Menu'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- #def create_self(keys)
- # if keys and keys != None
- # tk_call_without_enc('menu', @path, *hash_kv(keys, true))
- # else
- # tk_call_without_enc('menu', @path)
- # end
- #end
- #private :create_self
-
- def __strval_optkeys
- super() << 'selectcolor' << 'title'
- end
- private :__strval_optkeys
-
- def __boolval_optkeys
- super() << 'tearoff'
- end
- private :__boolval_optkeys
-
- def self.new_menuspec(menu_spec, parent = nil, tearoff = false, keys = nil)
- if parent.kind_of?(Hash)
- keys = _symbolkey2str(parent)
- parent = keys.delete('parent')
- tearoff = keys.delete('tearoff')
- elsif tearoff.kind_of?(Hash)
- keys = _symbolkey2str(tearoff)
- tearoff = keys.delete('tearoff')
- elsif keys
- keys = _symbolkey2str(keys)
- else
- keys = {}
- end
-
- widgetname = keys.delete('widgetname')
- _create_menu(parent, menu_spec, widgetname, tearoff, keys)
- end
-
- def tagid(id)
- #id.to_s
- _get_eval_string(id)
- end
-
- def activate(index)
- tk_send_without_enc('activate', _get_eval_enc_str(index))
- self
- end
- def add(type, keys=nil)
- tk_send_without_enc('add', type, *hash_kv(keys, true))
- self
- end
- def add_cascade(keys=nil)
- add('cascade', keys)
- end
- def add_checkbutton(keys=nil)
- add('checkbutton', keys)
- end
- def add_command(keys=nil)
- add('command', keys)
- end
- def add_radiobutton(keys=nil)
- add('radiobutton', keys)
- end
- def add_separator(keys=nil)
- add('separator', keys)
- end
-
- def clone_menu(*args)
- if args[0].kind_of?(TkWindow)
- parent = args.shift
- else
- parent = self
- end
-
- if args[0].kind_of?(String) || args[0].kind_of?(Symbol) # menu type
- type = args.shift
- else
- type = None # 'normal'
- end
-
- if args[0].kind_of?(Hash)
- keys = _symbolkey2str(args.shift)
- else
- keys = {}
- end
-
- parent = keys.delete('parent') if keys.has_key?('parent')
- type = keys.delete('type') if keys.has_key?('type')
-
- if keys.empty?
- TkMenuClone.new(self, parent, type)
- else
- TkMenuClone.new(self, parent, type, keys)
- end
- end
-
- def index(idx)
- ret = tk_send_without_enc('index', _get_eval_enc_str(idx))
- (ret == 'none')? nil: number(ret)
- end
- def invoke(index)
- _fromUTF8(tk_send_without_enc('invoke', _get_eval_enc_str(index)))
- end
- def insert(index, type, keys=nil)
- tk_send_without_enc('insert', _get_eval_enc_str(index),
- type, *hash_kv(keys, true))
- self
- end
- def delete(first, last=nil)
- if last
- tk_send_without_enc('delete', _get_eval_enc_str(first),
- _get_eval_enc_str(last))
- else
- tk_send_without_enc('delete', _get_eval_enc_str(first))
- end
- self
- end
- def popup(x, y, index=nil)
- if index
- tk_call_without_enc('tk_popup', path, x, y,
- _get_eval_enc_str(index))
- else
- tk_call_without_enc('tk_popup', path, x, y)
- end
- self
- end
- def post(x, y)
- _fromUTF8(tk_send_without_enc('post', x, y))
- end
- def postcascade(index)
- tk_send_without_enc('postcascade', _get_eval_enc_str(index))
- self
- end
- def postcommand(cmd=Proc.new)
- configure_cmd 'postcommand', cmd
- self
- end
- def set_focus
- tk_call_without_enc('tk_menuSetFocus', path)
- self
- end
- def tearoffcommand(cmd=Proc.new)
- configure_cmd 'tearoffcommand', cmd
- self
- end
- def menutype(index)
- tk_send_without_enc('type', _get_eval_enc_str(index))
- end
- def unpost
- tk_send_without_enc('unpost')
- self
- end
- def yposition(index)
- number(tk_send_without_enc('yposition', _get_eval_enc_str(index)))
- end
-
-=begin
- def entrycget(index, key)
- case key.to_s
- when 'text', 'label', 'show'
- _fromUTF8(tk_send_without_enc('entrycget',
- _get_eval_enc_str(index), "-#{key}"))
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_send('entrycget', index, "-#{key}"))
- fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('entrycget', _get_eval_enc_str(index), '-font')))
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(index, fnt)
- end
- if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby(_fromUTF8(tk_send_without_enc('entrycget', _get_eval_enc_str(index), "-#{key}")))
- end
- end
- def entryconfigure(index, key, val=None)
- if key.kind_of? Hash
- if (key['font'] || key[:font] ||
- key['kanjifont'] || key[:kanjifont] ||
- key['latinfont'] || key[:latinfont] ||
- key['asciifont'] || key[:asciifont])
- tagfont_configure(index, _symbolkey2str(key))
- else
- tk_send_without_enc('entryconfigure', _get_eval_enc_str(index),
- *hash_kv(key, true))
- end
-
- else
- if (key == 'font' || key == :font ||
- key == 'kanjifont' || key == :kanjifont ||
- key == 'latinfont' || key == :latinfont ||
- key == 'asciifont' || key == :asciifont )
- if val == None
- tagfontobj(index)
- else
- tagfont_configure(index, {key=>val})
- end
- else
- tk_call('entryconfigure', index, "-#{key}", val)
- end
- end
- self
- end
-
- def entryconfiginfo(index, key=nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- case key.to_s
- when 'text', 'label', 'show'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
- when 'font', 'kanjifont'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
- conf[4] = tagfont_configinfo(index, conf[4])
- else
- conf = tk_split_list(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure', _get_eval_enc_str(index)))).collect{|conflist|
- conf = tk_split_simplelist(conflist)
- conf[0] = conf[0][1..-1]
- case conf[0]
- when 'text', 'label', 'show'
- else
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- if conf[4]
- if conf[4].index('{')
- conf[4] = tk_split_list(conf[4])
- else
- conf[4] = tk_tcl2ruby(conf[4])
- end
- end
- end
- conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
- conf
- }
- if fontconf
- ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
- fontconf[4] = tagfont_configinfo(index, fontconf[4])
- ret.push(fontconf)
- else
- ret
- end
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- case key.to_s
- when 'text', 'label', 'show'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
- when 'font', 'kanjifont'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
- conf[4] = tagfont_configinfo(index, conf[4])
- else
- conf = tk_split_list(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
- end
- key = conf.shift[1..-1]
- { key => conf }
- else
- ret = {}
- tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure', _get_eval_enc_str(index)))).each{|conflist|
- conf = tk_split_simplelist(conflist)
- key = conf.shift[1..-1]
- case key
- when 'text', 'label', 'show'
- else
- if conf[2]
- if conf[2].index('{')
- conf[2] = tk_split_list(conf[2])
- else
- conf[2] = tk_tcl2ruby(conf[2])
- end
- end
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- end
- if conf.size == 1
- ret[key] = conf[0][1..-1] # alias info
- else
- ret[key] = conf
- end
- }
- fontconf = ret['font']
- if fontconf
- ret.delete('font')
- ret.delete('kanjifont')
- fontconf[3] = tagfont_configinfo(index, fontconf[3])
- ret['font'] = fontconf
- end
- ret
- end
- end
- end
-
- def current_entryconfiginfo(index, key=nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- conf = entryconfiginfo(index, key)
- {conf[0] => conf[4]}
- else
- ret = {}
- entryconfiginfo(index).each{|conf|
- ret[conf[0]] = conf[4] if conf.size > 2
- }
- ret
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- ret = {}
- entryconfiginfo(index, key).each{|k, conf|
- ret[k] = conf[-1] if conf.kind_of?(Array)
- }
- ret
- end
- end
-=end
-end
-
-
-class TkMenuClone<TkMenu
-=begin
- def initialize(parent, type=None)
- widgetname = nil
- if parent.kind_of? Hash
- keys = _symbolkey2str(parent)
- parent = keys.delete('parent')
- widgetname = keys.delete('widgetname')
- type = keys.delete('type'); type = None unless type
- end
- #unless parent.kind_of?(TkMenu)
- # fail ArgumentError, "parent must be TkMenu"
- #end
- @parent = parent
- install_win(@parent.path, widgetname)
- tk_call_without_enc(@parent.path, 'clone', @path, type)
- end
-=end
- def initialize(src_menu, *args)
- widgetname = nil
-
- if args[0].kind_of?(TkWindow) # parent window
- parent = args.shift
- else
- parent = src_menu
- end
-
- if args[0].kind_of?(String) || args[0].kind_of?(Symbol) # menu type
- type = args.shift
- else
- type = None # 'normal'
- end
-
- if args[0].kind_of?(Hash)
- keys = _symbolkey2str(args.shift)
- parent = keys.delete('parent') if keys.has_key?('parent')
- widgetname = keys.delete('widgetname')
- type = keys.delete('type') if keys.has_key?('type')
- else
- keys = nil
- end
-
- @src_menu = src_menu
- @parent = parent
- @type = type
- install_win(@parent.path, widgetname)
- tk_call_without_enc(@src_menu.path, 'clone', @path, @type)
- configure(keys) if keys && !keys.empty?
- end
-
- def source_menu
- @src_menu
- end
-end
-TkCloneMenu = TkMenuClone
-
-module TkSystemMenu
- def initialize(parent, keys=nil)
- if parent.kind_of? Hash
- keys = _symbolkey2str(parent)
- parent = keys.delete('parent')
- end
- #unless parent.kind_of? TkMenu
- # fail ArgumentError, "parent must be a TkMenu object"
- #end
- # @path = Kernel.format("%s.%s", parent.path, self.class::SYSMENU_NAME)
- @path = parent.path + '.' + self.class::SYSMENU_NAME
- #TkComm::Tk_WINDOWS[@path] = self
- TkCore::INTERP.tk_windows[@path] = self
- if self.method(:create_self).arity == 0
- p 'create_self has no arg' if $DEBUG
- create_self
- configure(keys) if keys
- else
- p 'create_self has an arg' if $DEBUG
- create_self(keys)
- end
- end
-end
-
-
-class TkSysMenu_Help<TkMenu
- # for all platform
- include TkSystemMenu
- SYSMENU_NAME = 'help'
-end
-
-
-class TkSysMenu_System<TkMenu
- # for Windows
- include TkSystemMenu
- SYSMENU_NAME = 'system'
-end
-
-
-class TkSysMenu_Apple<TkMenu
- # for Machintosh
- include TkSystemMenu
- SYSMENU_NAME = 'apple'
-end
-
-
-class TkMenubutton<TkLabel
- TkCommandNames = ['menubutton'.freeze].freeze
- WidgetClassName = 'Menubutton'.freeze
- WidgetClassNames[WidgetClassName] = self
- def create_self(keys)
- if keys and keys != None
- # tk_call_without_enc('menubutton', @path, *hash_kv(keys, true))
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
- else
- # tk_call_without_enc('menubutton', @path)
- tk_call_without_enc(self.class::TkCommandNames[0], @path)
- end
- end
- private :create_self
-
- def __boolval_optkeys
- super() << 'indicatoron'
- end
- private :__boolval_optkeys
-
-end
-TkMenuButton = TkMenubutton
-
-
-class TkOptionMenubutton<TkMenubutton
- TkCommandNames = ['tk_optionMenu'.freeze].freeze
-
- class OptionMenu<TkMenu
- def initialize(path) #==> return value of tk_optionMenu
- @path = path
- #TkComm::Tk_WINDOWS[@path] = self
- TkCore::INTERP.tk_windows[@path] = self
- end
- end
-
- def initialize(*args)
- # args :: [parent,] [var,] [value[, ...],] [keys]
- # parent --> TkWindow or nil
- # var --> TkVariable or nil
- # keys --> Hash
- # keys[:parent] or keys['parent'] --> parent
- # keys[:variable] or keys['variable'] --> var
- # keys[:values] or keys['values'] --> value, ...
- # other Hash keys are menubutton options
- keys = {}
- keys = args.pop if args[-1].kind_of?(Hash)
- keys = _symbolkey2str(keys)
-
- parent = nil
- if args[0].kind_of?(TkWindow) || args[0] == nil
- keys.delete('parent') # ignore
- parent = args.shift
- else
- parent = keys.delete('parent')
- end
-
- @variable = nil
- if args[0].kind_of?(TkVariable) || args[0] == nil
- keys.delete('variable') # ignore
- @variable = args.shift
- else
- @variable = keys.delete('variable')
- end
- @variable = TkVariable.new unless @variable
-
- (args = keys.delete('values') || []) if args.empty?
- if args.empty?
- args << @variable.value
- else
- @variable.value = args[0]
- end
-
- install_win(if parent then parent.path end)
- @menu = OptionMenu.new(tk_call('tk_optionMenu',
- @path, @variable.id, *args))
-
- configure(keys) if keys
- end
-
- def value
- @variable.value
- end
-
- def value=(val)
- @variable.value = val
- end
-
- def activate(index)
- @menu.activate(index)
- self
- end
- def add(value)
- @menu.add('radiobutton', 'variable'=>@variable,
- 'label'=>value, 'value'=>value)
- self
- end
- def index(index)
- @menu.index(index)
- end
- def invoke(index)
- @menu.invoke(index)
- end
- def insert(index, value)
- @menu.insert(index, 'radiobutton', 'variable'=>@variable,
- 'label'=>value, 'value'=>value)
- self
- end
- def delete(index, last=None)
- @menu.delete(index, last)
- self
- end
- def yposition(index)
- @menu.yposition(index)
- end
- def menu
- @menu
- end
- def menucget(key)
- @menu.cget(key)
- end
- def menuconfigure(key, val=None)
- @menu.configure(key, val)
- self
- end
- def menuconfiginfo(key=nil)
- @menu.configinfo(key)
- end
- def current_menuconfiginfo(key=nil)
- @menu.current_configinfo(key)
- end
- def entrycget(index, key)
- @menu.entrycget(index, key)
- end
- def entryconfigure(index, key, val=None)
- @menu.entryconfigure(index, key, val)
- self
- end
- def entryconfiginfo(index, key=nil)
- @menu.entryconfiginfo(index, key)
- end
- def current_entryconfiginfo(index, key=nil)
- @menu.current_entryconfiginfo(index, key)
- end
-end
-TkOptionMenuButton = TkOptionMenubutton
diff --git a/ext/tk/lib/tk/menubar.rb b/ext/tk/lib/tk/menubar.rb
deleted file mode 100644
index 392b6fbd4e..0000000000
--- a/ext/tk/lib/tk/menubar.rb
+++ /dev/null
@@ -1,131 +0,0 @@
-#
-# tk/menubar.rb
-#
-# Original version:
-# Copyright (C) 1998 maeda shugo. All rights reserved.
-# This file can be distributed under the terms of the Ruby.
-
-# Usage:
-#
-# menu_spec = [
-# [['File', 0],
-# ['Open', proc{puts('Open clicked')}, 0],
-# '---',
-# ['Quit', proc{exit}, 0]],
-# [['Edit', 0],
-# ['Cut', proc{puts('Cut clicked')}, 2],
-# ['Copy', proc{puts('Copy clicked')}, 0],
-# ['Paste', proc{puts('Paste clicked')}, 0]]
-# ]
-# menubar = TkMenubar.new(nil, menu_spec,
-# 'tearoff'=>false,
-# 'foreground'=>'grey40',
-# 'activeforeground'=>'red',
-# 'font'=>'-adobe-helvetica-bold-r-*--12-*-iso8859-1')
-# menubar.pack('side'=>'top', 'fill'=>'x')
-#
-#
-# OR
-#
-#
-# menubar = TkMenubar.new
-# menubar.add_menu([['File', 0],
-# ['Open', proc{puts('Open clicked')}, 0],
-# '---',
-# ['Quit', proc{exit}, 0]])
-# menubar.add_menu([['Edit', 0],
-# ['Cut', proc{puts('Cut clicked')}, 2],
-# ['Copy', proc{puts('Copy clicked')}, 0],
-# ['Paste', proc{puts('Paste clicked')}, 0]])
-# menubar.configure('tearoff', false)
-# menubar.configure('foreground', 'grey40')
-# menubar.configure('activeforeground', 'red')
-# menubar.configure('font', '-adobe-helvetica-bold-r-*--12-*-iso8859-1')
-# menubar.pack('side'=>'top', 'fill'=>'x')
-#
-#
-# OR
-#
-# radio_var = TkVariable.new('y')
-# menu_spec = [
-# [['File', 0],
-# {:label=>'Open', :command=>proc{puts('Open clicked')}, :underline=>0},
-# '---',
-# ['Check_A', TkVariable.new(true), 6],
-# {:type=>'checkbutton', :label=>'Check_B',
-# :variable=>TkVariable.new, :underline=>6},
-# '---',
-# ['Radio_X', [radio_var, 'x'], 6],
-# ['Radio_Y', [radio_var, 'y'], 6],
-# ['Radio_Z', [radio_var, 'z'], 6],
-# '---',
-# ['cascade', [
-# ['sss', proc{p 'sss'}, 0],
-# ['ttt', proc{p 'ttt'}, 0],
-# ['uuu', proc{p 'uuu'}, 0],
-# ['vvv', proc{p 'vvv'}, 0],
-# ], 0],
-# '---',
-# ['Quit', proc{exit}, 0]],
-# [['Edit', 0],
-# ['Cut', proc{puts('Cut clicked')}, 2],
-# ['Copy', proc{puts('Copy clicked')}, 0],
-# ['Paste', proc{puts('Paste clicked')}, 0]]
-# ]
-# menubar = TkMenubar.new(nil, menu_spec,
-# 'tearoff'=>false,
-# 'foreground'=>'grey40',
-# 'activeforeground'=>'red',
-# 'font'=>'Helvetia 12 bold')
-# menubar.pack('side'=>'top', 'fill'=>'x')
-
-# See tk/menuspce.rb about the format of the menu_spec
-
-# To use add_menu, configuration must be done by calling configure after
-# adding all menus by add_menu, not by the constructor arguments.
-
-require 'tk'
-require 'tk/frame'
-require 'tk/composite'
-require 'tk/menuspec'
-
-class TkMenubar<TkFrame
- include TkComposite
- include TkMenuSpec
-
- def initialize(parent = nil, spec = nil, options = nil)
- if parent.kind_of? Hash
- options = _symbolkey2str(parent)
- spec = options.delete('spec')
- super(options)
- else
- super(parent, options)
- end
-
- @menus = []
-
- spec.each{|info| add_menu(info)} if spec
-
- options.each{|key, value| configure(key, value)} if options
- end
-
- def add_menu(menu_info)
- mbtn, menu = _create_menubutton(@frame, menu_info)
-
- submenus = _get_cascade_menus(menu).flatten
-
- @menus.push([mbtn, menu])
- delegate('tearoff', menu, *submenus)
- delegate('foreground', mbtn, menu, *submenus)
- delegate('background', mbtn, menu, *submenus)
- delegate('disabledforeground', mbtn, menu, *submenus)
- delegate('activeforeground', mbtn, menu, *submenus)
- delegate('activebackground', mbtn, menu, *submenus)
- delegate('font', mbtn, menu, *submenus)
- delegate('kanjifont', mbtn, menu, *submenus)
- end
-
- def [](index)
- return @menus[index]
- end
-end
diff --git a/ext/tk/lib/tk/menuspec.rb b/ext/tk/lib/tk/menuspec.rb
deleted file mode 100644
index 118a4f42b1..0000000000
--- a/ext/tk/lib/tk/menuspec.rb
+++ /dev/null
@@ -1,269 +0,0 @@
-#
-# tk/menuspec.rb
-# Hidethoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-# based on tkmenubar.rb :
-# Copyright (C) 1998 maeda shugo. All rights reserved.
-# This file can be distributed under the terms of the Ruby.
-#
-# The format of the menu_spec is:
-# [ menu_info, menu_info, ... ]
-#
-# And the format of the menu_info is:
-# [
-# [text, underline, configs], # menu button/entry (*1)
-# [label, command, underline, accelerator, configs], # command entry
-# [label, TkVar_obj, underline, accelerator, configs], # checkbutton entry
-# [label, [TkVar_obj, value],
-# underline, accelerator, configs], # radiobutton entry
-# [label, [[...menu_info...], [...menu_info...], ...],
-# underline, accelerator, configs], # cascade entry (*2)
-# '---', # separator
-# ...
-# ]
-#
-# underline, accelerator, and configs are optional pearameters.
-# Hashes are OK instead of Arrays. Then the entry type ('command',
-# 'checkbutton', 'radiobutton' or 'cascade') is given by 'type' key
-# (e.g. :type=>'cascade'). When type is 'cascade', an array of menu_info
-# is acceptable for 'menu' key (then, create sub-menu).
-#
-# NOTE: (*1)
-# If you want to make special menus (*.help for UNIX, *.system for Win,
-# and *.apple for Mac), append 'menu_name'=>name (name is 'help' for UNIX,
-# 'system' for Win, and 'apple' for Mac) option to the configs hash of
-# menu button/entry information.
-#
-# NOTE: (*2)
-# If you want to configure a cascade menu, add :menu_config=>{...configs..}
-# to the configs of the cascade entry.
-
-module TkMenuSpec
- def _create_menu(parent, menu_info, menu_name = nil,
- tearoff = false, default_opts = nil)
- if tearoff.kind_of?(Hash)
- default_opts = tearoff
- tearoff = false
- end
-
- if menu_name.kind_of?(Hash)
- default_opts = menu_name
- menu_name = nil
- tearoff = false
- end
-
- if default_opts.kind_of?(Hash)
- orig_opts = _symbolkey2str(default_opts)
- else
- orig_opts = {}
- end
-
- tearoff = orig_opts.delete('tearoff') if orig_opts.key?('tearoff')
-
- if menu_name
- menu = TkMenu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff)
- else
- menu = TkMenu.new(parent, :tearoff=>tearoff)
- end
-
- for item_info in menu_info
- if item_info.kind_of?(Hash)
- options = orig_opts.dup
- options.update(_symbolkey2str(item_info))
- item_type = (options.delete('type') || 'command').to_s
- menu_name = options.delete('menu_name')
- menu_opts = orig_opts.dup
- menu_opts.update(_symbolkey2str(options.delete('menu_config') || {}))
- if item_type == 'cascade' && options['menu'].kind_of?(Array)
- # create cascade menu
- submenu = _create_menu(menu, options['menu'], menu_name,
- tearoff, menu_opts)
- options['menu'] = submenu
- end
- menu.add(item_type, options)
-
- elsif item_info.kind_of?(Array)
- options = orig_opts.dup
-
- options['label'] = item_info[0] if item_info[0]
-
- case item_info[1]
- when TkVariable
- # checkbutton
- item_type = 'checkbutton'
- options['variable'] = item_info[1]
- options['onvalue'] = true
- options['offvalue'] = false
-
- when Array
- # radiobutton or cascade
- if item_info[1][0].kind_of?(TkVariable)
- # radiobutton
- item_type = 'radiobutton'
- options['variable'] = item_info[1][0]
- options['value'] = item_info[1][1] if item_info[1][1]
-
- else
- # cascade
- item_type = 'cascade'
- menu_opts = orig_opts.dup
- if item_info[4] && item_info[4].kind_of?(Hash)
- opts = _symbolkey2str(item_info[4])
- menu_name = opts.delete('menu_name')
- menu_config = opts.delete('menu_config') || {}
- menu_opts.update(_symbolkey2str(menu_config))
- end
- submenu = _create_menu(menu, item_info[1], menu_name,
- tearoff, menu_opts)
- options['menu'] = submenu
- end
-
- else
- # command
- item_type = 'command'
- options['command'] = item_info[1] if item_info[1]
- end
-
- options['underline'] = item_info[2] if item_info[2]
- options['accelerator'] = item_info[3] if item_info[3]
- if item_info[4] && item_info[4].kind_of?(Hash)
- opts = _symbolkey2str(item_info[4])
- if item_type == 'cascade'
- opts.delete('menu_name')
- opts.delete('menu_config')
- end
- options.update(opts)
- end
- menu.add(item_type, options)
-
- elsif /^-+$/ =~ item_info
- menu.add('separator')
-
- else
- menu.add('command', 'label' => item_info)
- end
- end
-
- menu
- end
- private :_create_menu
-
- def _use_menubar?(parent)
- use_menubar = false
- if parent.kind_of?(TkRoot) || parent.kind_of?(TkToplevel)
- return true
- else
- begin
- parent.cget('menu')
- return true
- rescue
- end
- end
- false
- end
- private :_use_menubar?
-
- def _create_menu_for_menubar(parent)
- unless (mbar = parent.menu).kind_of?(TkMenu)
- mbar = TkMenu.new(parent, :tearoff=>false)
- parent.menu(mbar)
- end
- mbar
- end
- private :_create_menu_for_menubar
-
- def _create_menubutton(parent, menu_info, tearoff=false, default_opts = nil)
- btn_info = menu_info[0]
-
- if tearoff.kind_of?(Hash)
- default_opts = tearoff
- tearoff = false
- end
-
- if default_opts.kind_of?(Hash)
- keys = _symbolkey2str(default_opts)
- else
- keys = {}
- end
-
- tearoff = keys.delete('tearoff') if keys.key?('tearoff')
-
- if _use_menubar?(parent)
- # menubar by menu entries
-
- mbar = _create_menu_for_menubar(parent)
-
- menu_name = nil
-
- if btn_info.kind_of?(Hash)
- keys.update(_symbolkey2str(btn_info))
- menu_name = keys.delete('menu_name')
- keys['label'] = keys.delete('text') if keys.key?('text')
- elsif btn_info.kind_of?(Array)
- keys['label'] = btn_info[0] if btn_info[0]
- keys['underline'] = btn_info[1] if btn_info[1]
- if btn_info[2]&&btn_info[2].kind_of?(Hash)
- keys.update(_symbolkey2str(btn_info[2]))
- menu_name = keys.delete('menu_name')
- end
- else
- keys = {:label=>btn_info}
- end
-
- menu = _create_menu(mbar, menu_info[1..-1], menu_name,
- tearoff, default_opts)
- menu.tearoff(tearoff)
-
- keys['menu'] = menu
- mbar.add('cascade', keys)
-
- [mbar, menu]
-
- else
- # menubar by menubuttons
- mbtn = TkMenubutton.new(parent)
-
- menu_name = nil
-
- if btn_info.kind_of?(Hash)
- keys.update(_symbolkey2str(btn_info))
- menu_name = keys.delete('menu_name')
- keys['text'] = keys.delete('label') if keys.key?('label')
- mbtn.configure(keys)
- elsif btn_info.kind_of?(Array)
- mbtn.configure('text', btn_info[0]) if btn_info[0]
- mbtn.configure('underline', btn_info[1]) if btn_info[1]
- # mbtn.configure('accelerator', btn_info[2]) if btn_info[2]
- if btn_info[2]&&btn_info[2].kind_of?(Hash)
- keys.update(_symbolkey2str(btn_info[2]))
- menu_name = keys.delete('menu_name')
- mbtn.configure(keys)
- end
- else
- mbtn.configure('text', btn_info)
- end
-
- mbtn.pack('side' => 'left')
-
- menu = _create_menu(mbtn, menu_info[1..-1], menu_name,
- tearoff, default_opts)
-
- mbtn.menu(menu)
-
- [mbtn, menu]
- end
- end
- private :_create_menubutton
-
- def _get_cascade_menus(menu)
- menus = []
- (0..(menu.index('last'))).each{|idx|
- if menu.menutype(idx) == 'cascade'
- submenu = menu.entrycget(idx, 'menu')
- menus << [submenu, _get_cascade_menus(submenu)]
- end
- }
- menus
- end
- private :_get_cascade_menus
-end
diff --git a/ext/tk/lib/tk/message.rb b/ext/tk/lib/tk/message.rb
deleted file mode 100644
index 79121bebb3..0000000000
--- a/ext/tk/lib/tk/message.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# tk/message.rb : treat message widget
-#
-require 'tk'
-require 'tk/label'
-
-class TkMessage<TkLabel
- TkCommandNames = ['message'.freeze].freeze
- WidgetClassName = 'Message'.freeze
- WidgetClassNames[WidgetClassName] = self
- #def create_self(keys)
- # if keys and keys != None
- # tk_call_without_enc('message', @path, *hash_kv(keys, true))
- # else
- # tk_call_without_enc('message', @path)
- # end
- #end
- private :create_self
-end
diff --git a/ext/tk/lib/tk/mngfocus.rb b/ext/tk/lib/tk/mngfocus.rb
deleted file mode 100644
index 1a2049c8a8..0000000000
--- a/ext/tk/lib/tk/mngfocus.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# tk/mngfocus.rb : methods for Tcl/Tk standard library 'focus.tcl'
-# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
-#
-require 'tk'
-
-module TkManageFocus
- extend Tk
-
- TkCommandNames = [
- 'tk_focusFollowMouse'.freeze,
- 'tk_focusNext'.freeze,
- 'tk_focusPrev'.freeze
- ].freeze
-
- def TkManageFocus.followsMouse
- tk_call_without_enc('tk_focusFollowsMouse')
- end
-
- def TkManageFocus.next(win)
- tk_tcl2ruby(tk_call('tk_focusNext', win))
- end
- def focusNext
- TkManageFocus.next(self)
- end
-
- def TkManageFocus.prev(win)
- tk_tcl2ruby(tk_call('tk_focusPrev', win))
- end
- def focusPrev
- TkManageFocus.prev(self)
- end
-end
diff --git a/ext/tk/lib/tk/msgcat.rb b/ext/tk/lib/tk/msgcat.rb
deleted file mode 100644
index 061e43fd89..0000000000
--- a/ext/tk/lib/tk/msgcat.rb
+++ /dev/null
@@ -1,292 +0,0 @@
-#
-# tk/msgcat.rb : methods for Tcl message catalog
-# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
-#
-require 'tk'
-
-#class TkMsgCatalog
-class TkMsgCatalog < TkObject
- include TkCore
- extend Tk
- #extend TkMsgCatalog
-
- TkCommandNames = [
- '::msgcat::mc'.freeze,
- '::msgcat::mcmax'.freeze,
- '::msgcat::mclocale'.freeze,
- '::msgcat::mcpreferences'.freeze,
- '::msgcat::mcload'.freeze,
- '::msgcat::mcset'.freeze,
- '::msgcat::mcmset'.freeze,
- '::msgcat::mcunknown'.freeze
- ].freeze
-
- tk_call_without_enc('package', 'require', 'Tcl', '8.2')
-
- PACKAGE_NAME = 'msgcat'.freeze
- def self.package_name
- PACKAGE_NAME
- end
-
- if self.const_defined? :FORCE_VERSION
- tk_call_without_enc('package', 'require', 'msgcat', FORCE_VERSION)
- else
- tk_call_without_enc('package', 'require', 'msgcat')
- end
-
- MSGCAT_EXT = '.msg'
-
- UNKNOWN_CBTBL = Hash.new{|hash,key| hash[key] = {}}.taint
-
- TkCore::INTERP.add_tk_procs('::msgcat::mcunknown', 'args', <<-'EOL')
- if {[set st [catch {eval {ruby_cmd TkMsgCatalog callback} [namespace current] $args} ret]] != 0} {
- #return -code $st $ret
- set idx [string first "\n\n" $ret]
- if {$idx > 0} {
- return -code $st \
- -errorinfo [string range $ret [expr $idx + 2] \
- [string length $ret]] \
- [string range $ret 0 [expr $idx - 1]]
- } else {
- return -code $st $ret
- }
- } else {
- return $ret
- }
- EOL
-
- def self.callback(namespace, locale, src_str, *args)
- src_str = sprintf(src_str, *args) unless args.empty?
- cmd_tbl = TkMsgCatalog::UNKNOWN_CBTBL[TkCore::INTERP.__getip]
- cmd = cmd_tbl[namespace]
- cmd = cmd_tbl['::'] unless cmd # use global scope as interp default
- return src_str unless cmd # no cmd -> return src-str (default action)
- begin
- cmd.call(locale, src_str)
- rescue SystemExit
- exit(0)
- rescue Interrupt
- exit!(1)
- rescue Exception => e
- begin
- msg = _toUTF8(e.class.inspect) + ': ' +
- _toUTF8(e.message) + "\n" +
- "\n---< backtrace of Ruby side >-----\n" +
- _toUTF8(e.backtrace.join("\n")) +
- "\n---< backtrace of Tk side >-------"
- msg.instance_variable_set(:@encoding, 'utf-8')
- rescue Exception
- msg = e.class.inspect + ': ' + e.message + "\n" +
- "\n---< backtrace of Ruby side >-----\n" +
- e.backtrace.join("\n") +
- "\n---< backtrace of Tk side >-------"
- end
- fail(e, msg)
- end
- end
-
- def initialize(namespace = nil)
- if namespace.kind_of?(TkNamespace)
- @namespace = namespace
- elsif namespace == nil
- @namespace = TkNamespace.new('::') # global namespace
- else
- @namespace = TkNamespace.new(namespace)
- end
- @path = @namespace.path
-
- @msgcat_ext = '.msg'
- end
- attr_accessor :msgcat_ext
-
- def method_missing(id, *args)
- # locale(src, trans) ==> set_translation(locale, src, trans)
- loc = id.id2name
- case args.length
- when 0 # set locale
- self.locale=(loc)
-
- when 1 # src only, or trans_list
- if args[0].kind_of?(Array)
- # trans_list
- #list = args[0].collect{|src, trans|
- # [ Tk::UTF8_String.new(src), Tk::UTF8_String.new(trans) ]
- #}
- self.set_translation_list(loc, args[0])
- else
- # src
- #self.set_translation(loc, Tk::UTF8_String.new(args[0]))
- self.set_translation(loc, args[0])
- end
-
- when 2 # src and trans, or, trans_list and enc
- if args[0].kind_of?(Array)
- else
- #self.set_translation(loc, args[0], Tk::UTF8_String.new(args[1]))
- self.set_translation(loc, *args)
- end
-
- when 3 # src and trans and enc
- self.set_translation(loc, *args)
-
- else
- super(id, *args)
-# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
-
- end
- end
-
- # *args ::= form, arg, arg, ...
- def self.translate(*args)
- dst = args.collect{|src|
- tk_call_without_enc('::msgcat::mc', _get_eval_string(src, true))
- }
- Tk.UTF8_String(sprintf(*dst))
- end
- class << self
- alias mc translate
- alias [] translate
- end
- def translate(*args)
- dst = args.collect{|src|
- @namespace.eval{tk_call_without_enc('::msgcat::mc',
- _get_eval_string(src, true))}
- }
- Tk.UTF8_String(sprintf(*dst))
- end
- alias mc translate
- alias [] translate
-
- def self.maxlen(*src_strings)
- tk_call('::msgcat::mcmax', *src_strings).to_i
- end
- def maxlen(*src_strings)
- @namespace.eval{tk_call('::msgcat::mcmax', *src_strings).to_i}
- end
-
- def self.locale
- tk_call('::msgcat::mclocale')
- end
- def locale
- @namespace.eval{tk_call('::msgcat::mclocale')}
- end
-
- def self.locale=(locale)
- tk_call('::msgcat::mclocale', locale)
- end
- def locale=(locale)
- @namespace.eval{tk_call('::msgcat::mclocale', locale)}
- end
-
- def self.preferences
- tk_split_simplelist(tk_call('::msgcat::mcpreferences'))
- end
- def preferences
- tk_split_simplelist(@namespace.eval{tk_call('::msgcat::mcpreferences')})
- end
-
- def self.load_tk(dir)
- number(tk_call('::msgcat::mcload', dir))
- end
-
- def self.load_rb(dir)
- count = 0
- preferences().each{|loc|
- file = File.join(dir, loc + self::MSGCAT_EXT)
- if File.readable?(file)
- count += 1
- eval(open(file){|f| f.read})
- end
- }
- count
- end
-
- def load_tk(dir)
- number(@namespace.eval{tk_call('::msgcat::mcload', dir)})
- end
-
- def load_rb(dir)
- count = 0
- preferences().each{|loc|
- file = File.join(dir, loc + @msgcat_ext)
- if File.readable?(file)
- count += 1
- @namespace.eval(open(file){|f| f.read})
- end
- }
- count
- end
-
- def self.load(dir)
- self.load_rb(dir)
- end
- alias load load_rb
-
- def self.set_translation(locale, src_str, trans_str=None, enc='utf-8')
- if trans_str && trans_str != None
- trans_str = Tk.UTF8_String(_toUTF8(trans_str, enc))
- Tk.UTF8_String(tk_call_without_enc('::msgcat::mcset',
- locale,
- _get_eval_string(src_str, true),
- trans_str))
- else
- Tk.UTF8_String(tk_call_without_enc('::msgcat::mcset',
- locale,
- _get_eval_string(src_str, true)))
- end
- end
- def set_translation(locale, src_str, trans_str=None, enc='utf-8')
- if trans_str && trans_str != None
- trans_str = Tk.UTF8_String(_toUTF8(trans_str, enc))
- Tk.UTF8_String(@namespace.eval{
- tk_call_without_enc('::msgcat::mcset',
- locale,
- _get_eval_string(src_str, true),
- trans_str)
- })
- else
- Tk.UTF8_String(@namespace.eval{
- tk_call_without_enc('::msgcat::mcset',
- locale,
- _get_eval_string(src_str, true))})
- end
- end
-
- def self.set_translation_list(locale, trans_list, enc='utf-8')
- # trans_list ::= [ [src, trans], [src, trans], ... ]
- list = []
- trans_list.each{|src, trans|
- if trans && trans != None
- list << _get_eval_string(src, true)
- list << Tk.UTF8_Stirng(_toUTF8(trans, enc))
- else
- list << _get_eval_string(src, true) << ''
- end
- }
- number(tk_call_without_enc('::msgcat::mcmset', locale, list))
- end
- def set_translation_list(locale, trans_list, enc='utf-8')
- # trans_list ::= [ [src, trans], [src, trans], ... ]
- list = []
- trans_list.each{|src, trans|
- if trans && trans != None
- list << _get_eval_string(src, true)
- list << Tk.UTF8_String(_toUTF8(trans, enc))
- else
- list << _get_eval_string(src, true) << ''
- end
- }
- number(@namespace.eval{
- tk_call_without_enc('::msgcat::mcmset', locale, list)
- })
- end
-
- def self.def_unknown_proc(cmd=Proc.new)
- TkMsgCatalog::UNKNOWN_CBTBL[TkCore::INTERP.__getip]['::'] = cmd
- end
- def def_unknown_proc(cmd=Proc.new)
- TkMsgCatalog::UNKNOWN_CBTBL[TkCore::INTERP.__getip][@namespace.path] = cmd
- end
-end
-
-TkMsgCat = TkMsgCatalog
diff --git a/ext/tk/lib/tk/namespace.rb b/ext/tk/lib/tk/namespace.rb
deleted file mode 100644
index 5bf6474c5b..0000000000
--- a/ext/tk/lib/tk/namespace.rb
+++ /dev/null
@@ -1,500 +0,0 @@
-#
-# tk/namespace.rb : methods to manipulate Tcl/Tk namespace
-# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
-#
-require 'tk'
-
-class TkNamespace < TkObject
- extend Tk
-
- TkCommandNames = [
- 'namespace'.freeze,
- ].freeze
-
- Tk_Namespace_ID_TBL = TkCore::INTERP.create_table
- Tk_Namespace_ID = ["ns".freeze, "00000".taint].freeze
-
- Tk_NsCode_RetObjID_TBL = TkCore::INTERP.create_table
-
- TkCore::INTERP.init_ip_env{
- Tk_Namespace_ID_TBL.clear
- Tk_NsCode_RetObjID_TBL.clear
- }
-
- def TkNamespace.id2obj(id)
- Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id
- end
-
- #####################################
-
- class Ensemble < TkObject
- def __cget_cmd
- ['namespace', 'ensemble', 'configure', self.path]
- end
- private :__cget_cmd
-
- def __config_cmd
- ['namespace', 'ensemble', 'configure', self.path]
- end
- private :__config_cmd
-
- def __configinfo_struct
- {:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil,
- :default_value=>nil, :current_value=>2}
- end
- private :__configinfo_struct
-
- def __boolval_optkeys
- ['prefixes']
- end
- private :__boolval_optkeys
-
- def __listval_optkeys
- ['map', 'subcommands', 'unknown']
- end
- private :__listval_optkeys
-
- def self.exist?(ensemble)
- bool(tk_call('namespace', 'ensemble', 'exists', ensemble))
- end
-
- def initialize(keys = {})
- @ensemble = @path = tk_call('namespace', 'ensemble', 'create', keys)
- end
-
- def cget(slot)
- if slot == :namespace || slot == 'namespace'
- ns = super(slot)
- if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
- TkNamespace::Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
- else
- super(slot)
- end
- end
-
- def configinfo(slot = nil)
- if slot
- if slot == :namespace || slot == 'namespace'
- val = super(slot)
- if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
- val = TkNamespace::Tk_Namespace_ID_TBL[val]
- end
- else
- val = super(slot)
- end
-
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- [slot.to_s, val]
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- {slot.to_s => val}
- end
-
- else
- info = super()
-
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- info.map!{|inf|
- if inf[0] == 'namespace' &&
- TkNamespace::Tk_Namespace_ID_TBL.key?(inf[-1])
- [inf[0], TkNamespace::Tk_Namespace_ID_TBL[inf[-1]]]
- else
- inf
- end
- }
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- val = info['namespace']
- if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
- info['namespace'] = TkNamespace::Tk_Namespace_ID_TBL[val]
- end
- end
-
- info
- end
- end
-
- def exists?
- bool(tk_call('namespace', 'ensemble', 'exists', @path))
- end
- end
-
- #####################################
-
- class ScopeArgs < Array
- include Tk
-
- # alias __tk_call tk_call
- # alias __tk_call_without_enc tk_call_without_enc
- # alias __tk_call_with_enc tk_call_with_enc
- def tk_call(*args)
- #super('namespace', 'eval', @namespace, *args)
- args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
- super('namespace', 'eval', @namespace,
- TkCore::INTERP._merge_tklist(*args))
- end
- def tk_call_without_enc(*args)
- #super('namespace', 'eval', @namespace, *args)
- args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
- super('namespace', 'eval', @namespace,
- TkCore::INTERP._merge_tklist(*args))
- end
- def tk_call_with_enc(*args)
- #super('namespace', 'eval', @namespace, *args)
- args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
- super('namespace', 'eval', @namespace,
- TkCore::INTERP._merge_tklist(*args))
- end
-
- def initialize(namespace, *args)
- @namespace = namespace
- super(args.size)
- self.replace(args)
- end
- end
-
- #####################################
-
- class NsCode < TkObject
- def initialize(scope, use_obj_id = false)
- @scope = scope + ' '
- @use_obj_id = use_obj_id
- end
- def path
- @scope
- end
- def to_eval
- @scope
- end
- def call(*args)
- ret = TkCore::INTERP._eval_without_enc(@scope + array2tk_list(args))
- if @use_obj_id
- ret = TkNamespace::Tk_NsCode_RetObjID_TBL.delete(ret.to_i)
- end
- ret
- end
- end
-
- #####################################
-
- def install_cmd(cmd)
- lst = tk_split_simplelist(super(cmd), false, false)
- if lst[1] =~ /^::/
- lst[1] = @fullname
- else
- lst.insert(1, @fullname)
- end
- TkCore::INTERP._merge_tklist(*lst)
- end
-
- alias __tk_call tk_call
- alias __tk_call_without_enc tk_call_without_enc
- alias __tk_call_with_enc tk_call_with_enc
- def tk_call(*args)
- #super('namespace', 'eval', @fullname, *args)
- args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
- super('namespace', 'eval', @fullname,
- TkCore::INTERP._merge_tklist(*args))
- end
- def tk_call_without_enc(*args)
- #super('namespace', 'eval', @fullname, *args)
- args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
- super('namespace', 'eval', @fullname,
- TkCore::INTERP._merge_tklist(*args))
- end
- def tk_call_with_enc(*args)
- #super('namespace', 'eval', @fullname, *args)
- args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
- super('namespace', 'eval', @fullname,
- TkCore::INTERP._merge_tklist(*args))
- end
- alias ns_tk_call tk_call
- alias ns_tk_call_without_enc tk_call_without_enc
- alias ns_tk_call_with_enc tk_call_with_enc
-
- def initialize(name = nil, parent = nil)
- unless name
- # name = Tk_Namespace_ID.join('')
- name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_)
- Tk_Namespace_ID[1].succ!
- end
- name = __tk_call('namespace', 'current') if name == ''
- if parent
- if parent =~ /^::/
- if name =~ /^::/
- @fullname = parent + name
- else
- @fullname = parent +'::'+ name
- end
- else
- ancestor = __tk_call('namespace', 'current')
- ancestor = '' if ancestor == '::'
- if name =~ /^::/
- @fullname = ancestor + '::' + parent + name
- else
- @fullname = ancestor + '::'+ parent +'::'+ name
- end
- end
- else # parent == nil
- ancestor = __tk_call('namespace', 'current')
- ancestor = '' if ancestor == '::'
- if name =~ /^::/
- @fullname = name
- else
- @fullname = ancestor + '::' + name
- end
- end
- @path = @fullname
- @parent = __tk_call('namespace', 'qualifiers', @fullname)
- @name = __tk_call('namespace', 'tail', @fullname)
-
- # create namespace
- __tk_call('namespace', 'eval', @fullname, '')
-
- Tk_Namespace_ID_TBL[@fullname] = self
- end
-
- def self.children(*args)
- # args ::= [<namespace>] [<pattern>]
- # <pattern> must be glob-style pattern
- tk_split_simplelist(tk_call('namespace', 'children', *args)).collect{|ns|
- # ns is fullname
- if Tk_Namespace_ID_TBL.key?(ns)
- Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
- }
- end
- def children(pattern=None)
- TkNamespace.children(@fullname, pattern)
- end
-
- def self.code(script = Proc.new)
- TkNamespace.new('').code(script)
- end
-=begin
- def code(script = Proc.new)
- if script.kind_of?(String)
- cmd = proc{|*args| ScopeArgs.new(@fullname,*args).instance_eval(script)}
- elsif script.kind_of?(Proc)
- cmd = proc{|*args| ScopeArgs.new(@fullname,*args).instance_eval(&script)}
- else
- fail ArgumentError, "String or Proc is expected"
- end
- TkNamespace::NsCode.new(tk_call_without_enc('namespace', 'code',
- _get_eval_string(cmd, false)))
- end
-=end
- def code(script = Proc.new)
- if script.kind_of?(String)
- cmd = proc{|*args|
- ret = ScopeArgs.new(@fullname,*args).instance_eval(script)
- id = ret.object_id
- TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
- id
- }
- elsif script.kind_of?(Proc)
- cmd = proc{|*args|
- ret = ScopeArgs.new(@fullname,*args).instance_eval(&script)
- id = ret.object_id
- TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
- id
- }
- else
- fail ArgumentError, "String or Proc is expected"
- end
- TkNamespace::NsCode.new(tk_call_without_enc('namespace', 'code',
- _get_eval_string(cmd, false)),
- true)
- end
-
- def self.current_path
- tk_call('namespace', 'current')
- end
- def current_path
- @fullname
- end
-
- def self.current
- ns = self.current_path
- if Tk_Namespace_ID_TBL.key?(ns)
- Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
- end
- def current_namespace
- # ns_tk_call('namespace', 'current')
- # @fullname
- self
- end
- alias current current_namespace
-
- def self.delete(*ns_list)
- tk_call('namespace', 'delete', *ns_list)
- ns_list.each{|ns|
- if ns.kind_of?(TkNamespace)
- Tk_Namespace_ID_TBL.delete(ns.path)
- else
- Tk_Namespace_ID_TBL.delete(ns.to_s)
- end
- }
- end
- def delete
- TkNamespece.delete(@fullname)
- end
-
- def self.ensemble_create(*keys)
- tk_call('namespace', 'ensemble', 'create', *hash_kv(keys))
- end
- def self.ensemble_configure(cmd, slot, value=None)
- if slot.kind_of?(Hash)
- tk_call('namespace', 'ensemble', 'configure', cmd, *hash_kv(slot))
- else
- tk_call('namespace', 'ensemble', 'configure', cmd, '-'+slot.to_s, value)
- end
- end
- def self.ensemble_configinfo(cmd, slot = nil)
- if slot
- tk_call('namespace', 'ensemble', 'configure', cmd, '-' + slot.to_s)
- else
- inf = {}
- Hash(*tk_split_simplelist(tk_call('namespace', 'ensemble', 'configure', cmd))).each{|k, v| inf[k[1..-1]] = v}
- inf
- end
- end
- def self.ensemble_exist?(cmd)
- bool(tk_call('namespace', 'ensemble', 'exists', cmd))
- end
-
- def self.eval(namespace, cmd = Proc.new, *args)
- #tk_call('namespace', 'eval', namespace, cmd, *args)
- TkNamespace.new(namespece).eval(cmd, *args)
- end
-=begin
- def eval(cmd = Proc.new, *args)
- #TkNamespace.eval(@fullname, cmd, *args)
- #ns_tk_call(cmd, *args)
- code_obj = code(cmd)
- ret = code_obj.call(*args)
- # uninstall_cmd(TkCore::INTERP._split_tklist(code_obj.path)[-1])
- uninstall_cmd(_fromUTF8(TkCore::INTERP._split_tklist(_toUTF8(code_obj.path))[-1]))
- tk_tcl2ruby(ret)
- end
-=end
- def eval(cmd = Proc.new, *args)
- code_obj = code(cmd)
- ret = code_obj.call(*args)
- uninstall_cmd(_fromUTF8(TkCore::INTERP._split_tklist(_toUTF8(code_obj.path))[-1]))
- ret
- end
-
- def self.exist?(ns)
- bool(tk_call('namespace', 'exists', ns))
- end
- def exist?
- TkNamespece.exist?(@fullname)
- end
-
- def self.export(*patterns)
- tk_call('namespace', 'export', *patterns)
- end
- def self.export_with_clear(*patterns)
- tk_call('namespace', 'export', '-clear', *patterns)
- end
- def export
- TkNamespace.export(@fullname)
- end
- def export_with_clear
- TkNamespace.export_with_clear(@fullname)
- end
-
- def self.forget(*patterns)
- tk_call('namespace', 'forget', *patterns)
- end
- def forget
- TkNamespace.forget(@fullname)
- end
-
- def self.import(*patterns)
- tk_call('namespace', 'import', *patterns)
- end
- def self.force_import(*patterns)
- tk_call('namespace', 'import', '-force', *patterns)
- end
- def import
- TkNamespace.import(@fullname)
- end
- def force_import
- TkNamespace.force_import(@fullname)
- end
-
- def self.inscope(namespace, script, *args)
- tk_call('namespace', 'inscope', namespace, script, *args)
- end
- def inscope(script, *args)
- TkNamespace.inscope(@fullname, script, *args)
- end
-
- def self.origin(cmd)
- tk_call('namespace', 'origin', cmd)
- end
-
- def self.parent(namespace=None)
- ns = tk_call('namespace', 'parent', namespace)
- if Tk_Namespace_ID_TBL.key?(ns)
- Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
- end
- def parent
- tk_call('namespace', 'parent', @fullname)
- end
-
- def self.get_path
- tk_call('namespace', 'path')
- end
- def self.set_path(*namespace_list)
- tk_call('namespace', 'path', array2tk_list(namespace_list))
- end
- def set_path
- tk_call('namespace', 'path', @fullname)
- end
-
- def self.qualifiers(str)
- tk_call('namespace', 'qualifiers', str)
- end
-
- def self.tail(str)
- tk_call('namespace', 'tail', str)
- end
-
- def self.upvar(namespace, *var_pairs)
- tk_call('namespace', 'upvar', namespace, *(var_pairs.flatten))
- end
- def upvar(*var_pairs)
- TkNamespace.inscope(@fullname, *(var_pairs.flatten))
- end
-
- def self.get_unknown_handler
- tk_tcl2ruby(tk_call('namespace', 'unknown'))
- end
- def self.set_unknown_handler(cmd = Proc.new)
- tk_call('namespace', 'unknown', cmd)
- end
-
- def self.which(name)
- tk_call('namespace', 'which', name)
- end
- def self.which_command(name)
- tk_call('namespace', 'which', '-command', name)
- end
- def self.which_variable(name)
- tk_call('namespace', 'which', '-variable', name)
- end
-end
-
-TkNamespace::Global = TkNamespace.new('::')
diff --git a/ext/tk/lib/tk/optiondb.rb b/ext/tk/lib/tk/optiondb.rb
deleted file mode 100644
index a806f3971d..0000000000
--- a/ext/tk/lib/tk/optiondb.rb
+++ /dev/null
@@ -1,371 +0,0 @@
-#
-# tk/optiondb.rb : treat option database
-#
-require 'tk'
-
-module TkOptionDB
- include Tk
- extend Tk
-
- TkCommandNames = ['option'.freeze].freeze
- CmdClassID = ['CMD_CLASS'.freeze, '00000'.taint].freeze
-
- module Priority
- WidgetDefault = 20
- StartupFile = 40
- UserDefault = 60
- Interactive = 80
- end
-
- def add(pat, value, pri=None)
- # if $SAFE >= 4
- # fail SecurityError, "can't call 'TkOptionDB.add' at $SAFE >= 4"
- # end
- tk_call('option', 'add', pat, value, pri)
- end
- def clear
- # if $SAFE >= 4
- # fail SecurityError, "can't call 'TkOptionDB.crear' at $SAFE >= 4"
- # end
- tk_call_without_enc('option', 'clear')
- end
- def get(win, name, klass)
- tk_call('option', 'get', win ,name, klass)
- end
- def readfile(file, pri=None)
- tk_call('option', 'readfile', file, pri)
- end
- alias read_file readfile
- module_function :add, :clear, :get, :readfile, :read_file
-
- def read_entries(file, f_enc=nil)
- if TkCore::INTERP.safe?
- fail SecurityError,
- "can't call 'TkOptionDB.read_entries' on a safe interpreter"
- end
-
- i_enc = ((Tk.encoding)? Tk.encoding : Tk.encoding_system)
-
- unless f_enc
- f_enc = i_enc
- end
-
- ent = []
- cline = ''
- open(file, 'r') {|f|
- while line = f.gets
- #cline += line.chomp!
- cline.concat(line.chomp!)
- case cline
- when /\\$/ # continue
- cline.chop!
- next
- when /^\s*(!|#)/ # coment
- cline = ''
- next
- when /^([^:]+):(.*)$/
- pat = $1.strip
- val = $2.lstrip
- p "ResourceDB: #{[pat, val].inspect}" if $DEBUG
- pat = TkCore::INTERP._toUTF8(pat, f_enc)
- pat = TkCore::INTERP._fromUTF8(pat, i_enc)
- val = TkCore::INTERP._toUTF8(val, f_enc)
- val = TkCore::INTERP._fromUTF8(val, i_enc)
- ent << [pat, val]
- cline = ''
- else # unknown --> ignore
- cline = ''
- next
- end
- end
- }
- ent
- end
- module_function :read_entries
-
- def read_with_encoding(file, f_enc=nil, pri=None)
- # try to read the file as an OptionDB file
- read_entries(file, f_enc).each{|pat, val|
- add(pat, val, pri)
- }
-
-=begin
- i_enc = Tk.encoding()
-
- unless f_enc
- f_enc = i_enc
- end
-
- cline = ''
- open(file, 'r') {|f|
- while line = f.gets
- cline += line.chomp!
- case cline
- when /\\$/ # continue
- cline.chop!
- next
- when /^\s*!/ # coment
- cline = ''
- next
- when /^([^:]+):\s(.*)$/
- pat = $1
- val = $2
- p "ResourceDB: #{[pat, val].inspect}" if $DEBUG
- pat = TkCore::INTERP._toUTF8(pat, f_enc)
- pat = TkCore::INTERP._fromUTF8(pat, i_enc)
- val = TkCore::INTERP._toUTF8(val, f_enc)
- val = TkCore::INTERP._fromUTF8(val, i_enc)
- add(pat, val, pri)
- cline = ''
- else # unknown --> ignore
- cline = ''
- next
- end
- end
- }
-=end
- end
- module_function :read_with_encoding
-
- # support procs on the resource database
- @@resource_proc_class = Class.new
-
- @@resource_proc_class.const_set(:CARRIER, '.'.freeze)
-
- @@resource_proc_class.instance_variable_set('@method_tbl',
- TkCore::INTERP.create_table)
- @@resource_proc_class.instance_variable_set('@add_method', false)
- @@resource_proc_class.instance_variable_set('@safe_mode', 4)
-
- class << @@resource_proc_class
- private :new
-
-=begin
- CARRIER = '.'.freeze
- METHOD_TBL = TkCore::INTERP.create_table
- ADD_METHOD = false
- SAFE_MODE = 4
-=end
-
-=begin
- def __closed_block_check__(str)
- depth = 0
- str.scan(/[{}]/){|x|
- if x == "{"
- depth += 1
- elsif x == "}"
- depth -= 1
- end
- if depth <= 0 && !($' =~ /\A\s*\Z/)
- fail RuntimeError, "bad string for procedure : #{str.inspect}"
- end
- }
- str
- end
- private :__closed_block_check__
-=end
-
- def __check_proc_string__(str)
- # If you want to check the proc_string, do it in this method.
- # Please define this in the block given to 'new_proc_class' method.
- str
- end
-
- def method_missing(id, *args)
- #res_proc, proc_str = self::METHOD_TBL[id]
- res_proc, proc_str = @method_tbl[id]
-
- proc_source = TkOptionDB.get(self::CARRIER, id.id2name, '').strip
- res_proc = nil if proc_str != proc_source # resource is changed
-
- # unless res_proc.kind_of?(Proc)
- unless TkComm._callback_entry?(res_proc)
- #if id == :new || !(self::METHOD_TBL.has_key?(id) || self::ADD_METHOD)
- if id == :new || !(@method_tbl.has_key?(id) || @add_method)
- raise NoMethodError,
- "not support resource-proc '#{id.id2name}' for #{self.name}"
- end
- proc_str = proc_source
- proc_str = '{' + proc_str + '}' unless /\A\{.*\}\Z/ =~ proc_str
- #proc_str = __closed_block_check__(proc_str)
- proc_str = __check_proc_string__(proc_str)
- res_proc = proc{
- begin
- #eval("$SAFE = #{self::SAFE_MODE};\nProc.new" + proc_str)
- eval("$SAFE = #{@safe_mode};\nProc.new" + proc_str)
- rescue SyntaxError=>err
- raise SyntaxError,
- TkCore::INTERP._toUTF8(err.message.gsub(/\(eval\):\d:/,
- "(#{id.id2name}):"))
- end
- }.call
- #self::METHOD_TBL[id] = [res_proc, proc_source]
- @method_tbl[id] = [res_proc, proc_source]
- end
- res_proc.call(*args)
- end
-
- private :__check_proc_string__, :method_missing
- end
- @@resource_proc_class.freeze
-
-=begin
- def __create_new_class(klass, func, safe = 4, add = false, parent = nil)
- klass = klass.to_s if klass.kind_of? Symbol
- unless (?A..?Z) === klass[0]
- fail ArgumentError, "bad string '#{klass}' for class name"
- end
- unless func.kind_of? Array
- fail ArgumentError, "method-list must be Array"
- end
- func_str = func.join(' ')
- if parent == nil
- install_win(parent)
- elsif parent <= @@resource_proc_class
- install_win(parent::CARRIER)
- else
- fail ArgumentError, "parent must be Resource-Proc class"
- end
- carrier = Tk.tk_call_without_enc('frame', @path, '-class', klass)
-
- body = <<-"EOD"
- class #{klass} < TkOptionDB.module_eval('@@resource_proc_class')
- CARRIER = '#{carrier}'.freeze
- METHOD_TBL = TkCore::INTERP.create_table
- ADD_METHOD = #{add}
- SAFE_MODE = #{safe}
- %w(#{func_str}).each{|f| METHOD_TBL[f.intern] = nil }
- end
- EOD
-
- if parent.kind_of?(Class) && parent <= @@resource_proc_class
- parent.class_eval(body)
- eval(parent.name + '::' + klass)
- else
- eval(body)
- eval('TkOptionDB::' + klass)
- end
- end
-=end
- def __create_new_class(klass, func, safe = 4, add = false, parent = nil)
- if klass.kind_of?(TkWindow)
- carrier = klass.path
- klass = CmdClassID.join(TkCore::INTERP._ip_id_)
- CmdClassID[1].succ!
- parent = nil # ignore parent
- else
- klass = klass.to_s if klass.kind_of?(Symbol)
- unless (?A..?Z) === klass[0]
- fail ArgumentError, "bad string '#{klass}' for class name"
- end
- if parent == nil
- install_win(nil)
- elsif parent.kind_of?(TkWindow)
- install_win(parent.path)
- elsif parent <= @@resource_proc_class
- install_win(parent::CARRIER)
- else
- fail ArgumentError, "parent must be Resource-Proc class"
- end
- carrier = Tk.tk_call_without_enc('frame', @path, '-class', klass)
- end
-
- unless func.kind_of?(Array)
- fail ArgumentError, "method-list must be Array"
- end
- func_str = func.join(' ')
-
- if parent.kind_of?(Class) && parent <= @@resource_proc_class
- cmd_klass = Class.new(parent)
- else
- cmd_klass = Class.new(TkOptionDB.module_eval('@@resource_proc_class'))
- end
- cmd_klass.const_set(:CARRIER, carrier.dup.freeze)
-
- cmd_klass.instance_variable_set('@method_tbl', TkCore::INTERP.create_table)
- cmd_klass.instance_variable_set('@add_method', add)
- cmd_klass.instance_variable_set('@safe_mode', safe)
- func.each{|f|
- cmd_klass.instance_variable_get('@method_tbl')[f.to_s.intern] = nil
- }
-=begin
- cmd_klass.const_set(:METHOD_TBL, TkCore::INTERP.create_table)
- cmd_klass.const_set(:ADD_METHOD, add)
- cmd_klass.const_set(:SAFE_MODE, safe)
- func.each{|f| cmd_klass::METHOD_TBL[f.to_s.intern] = nil }
-=end
-
- cmd_klass
- end
- module_function :__create_new_class
- private_class_method :__create_new_class
-
- def __remove_methods_of_proc_class(klass)
- # for security, make these methods invalid
- class << klass
- def __null_method(*args); nil; end
- [ :class_eval, :name, :superclass, :clone, :dup, :autoload, :autoload?,
- :ancestors, :const_defined?, :const_get, :const_set, :const_missing,
- :class_variables, :constants, :included_modules, :instance_methods,
- :method_defined?, :module_eval, :private_instance_methods,
- :protected_instance_methods, :public_instance_methods,
- :singleton_methods, :remove_const, :remove_method, :undef_method,
- :to_s, :inspect, :display, :method, :methods, :respond_to?,
- :instance_variable_get, :instance_variable_set, :instance_method,
- :instance_eval, :instance_variables, :kind_of?, :is_a?,
- :private_methods, :protected_methods, :public_methods ].each{|m|
- alias_method(m, :__null_method)
- }
- end
- end
- module_function :__remove_methods_of_proc_class
- private_class_method :__remove_methods_of_proc_class
-
- RAND_BASE_CNT = [0]
- RAND_BASE_HEAD = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
- RAND_BASE_CHAR = RAND_BASE_HEAD + 'abcdefghijklmnopqrstuvwxyz0123456789_'
- def __get_random_basename
- name = '%s%03d' % [RAND_BASE_HEAD[rand(RAND_BASE_HEAD.size),1],
- RAND_BASE_CNT[0]]
- len = RAND_BASE_CHAR.size
- (6+rand(10)).times{
- name << RAND_BASE_CHAR[rand(len),1]
- }
- RAND_BASE_CNT[0] = RAND_BASE_CNT[0] + 1
- name
- end
- module_function :__get_random_basename
- private_class_method :__get_random_basename
-
- # define new proc class :
- # If you want to modify the new class or create a new subclass,
- # you must do such operation in the block parameter.
- # Because the created class is flozen after evaluating the block.
- def new_proc_class(klass, func, safe = 4, add = false, parent = nil, &b)
- new_klass = __create_new_class(klass, func, safe, add, parent)
- new_klass.class_eval(&b) if block_given?
- __remove_methods_of_proc_class(new_klass)
- new_klass.freeze
- new_klass
- end
- module_function :new_proc_class
-
- def eval_under_random_base(parent = nil, &b)
- new_klass = __create_new_class(__get_random_basename(),
- [], 4, false, parent)
- ret = new_klass.class_eval(&b) if block_given?
- __remove_methods_of_proc_class(new_klass)
- new_klass.freeze
- ret
- end
- module_function :eval_under_random_base
-
- def new_proc_class_random(klass, func, safe = 4, add = false, &b)
- eval_under_random_base(){
- TkOption.new_proc_class(klass, func, safe, add, self, &b)
- }
- end
- module_function :new_proc_class_random
-end
-TkOption = TkOptionDB
-TkResourceDB = TkOptionDB
diff --git a/ext/tk/lib/tk/optionobj.rb b/ext/tk/lib/tk/optionobj.rb
deleted file mode 100644
index 8fe7e0ee5a..0000000000
--- a/ext/tk/lib/tk/optionobj.rb
+++ /dev/null
@@ -1,212 +0,0 @@
-#
-# tk/optionobj.rb : control options for a group of widgets
-#
-# NOTE: If you want to use key-only option (no value),
-# use Tk::None for the value of the key-only option.
-#
-# e.g. hash_kv({'aaa'=>1, 'bbb'=>Tk::None, 'ccc'=>3})
-# => ["-aaa", 1, "-bbb", "-ccc", 3]
-#
-require 'tk'
-
-module Tk
- class OptionObj < Hash
- include TkUtil
-
- def initialize(hash = nil)
- super()
- @observ = []
- update_without_notify(_symbolkey2str(hash)) if hash
- end
-
- def observ_info
- @observ.dup
- end
-
- def observs
- @observ.collect{|win|
- if win.kind_of?(Array)
- win[0]
- else
- win
- end
- }
- end
-
- def _remove_win(win)
- if win.kind_of?(Array)
- widget, method = win
- @observ.delete_if{|x|
- if x.kind_of?(Array)
- x[0] == widget
- else
- x == widget
- end
- }
- else
- @observ.delete_if{|x|
- if x.kind_of?(Array)
- x[0] == win
- else
- x == win
- end
- }
- end
- end
- private :_remove_win
-
- def assign(*wins)
- # win :=
- # widget #==> call widget.configure(hash)
- # [widget] #==> call widget.configure(hash)
- # [widget, nil, {src=>target, ... }]
- # #==> call widget.configure(hash)
- # with converting hash-key
- # [widget, method] #==> call widget.method(hash)
- # [widget, method, {src=>target, ... }]
- # #==> call widget.method(hash)
- # with converting hash-key
- # [widget [receiver, method, arg, ... ]]
- # #==> call receiver.method(arg, ... , hash)
- # [widget [receiver, method, arg, ... ], {src=>target, ... }]
- # #==> call receiver.method(arg, ... , hash)
- # with onverting hash-key
- #
- # src := option_name_on_optobj
- #
- # target :=
- # nil #==> not use the src
- # option_name_on_target_widget
- # [ option_name_on_target_widget, ... ]
- # #==> set all of them
- #
- wins.each{|win|
- _remove_win(win)
- @observ << win
- notify(win)
- }
- self
- end
-
- def unassign(*wins)
- wins.each{|win|
- _remove_win(win)
- }
- self
- end
-
- def notify(target = nil)
- if target
- targets = [target]
- elsif @observ.empty?
- return self
- else
- targets = @observ.dup
- end
-
- return self if empty?
-
- org_hash = _symbolkey2str(self)
-
- targets.each{|win|
- widget = receiver = win
- hash = org_hash
- begin
- if win.kind_of?(Array)
- widget, method, conv_tbl = win
- receiver = widget
-
- if conv_tbl
- hash = {}
- org_hash.each{|key, val|
- key = conv_tbl[key] if conv_tbl.key?(key)
- next unless key
- if key.kind_of?(Array)
- key.each{|k| hash[k] = val}
- else
- hash[key] = val
- end
- }
- end
-
- if method.kind_of?(Array)
- receiver, method, *args = method
- receiver.__send__(method, *(args << hash))
- elsif method
- widget.__send__(method, hash)
- else
- widget.configure(hash)
- end
-
- else
- widget.configure(self)
- end
- rescue => e
- if ( ( widget.kind_of?(TkObject) \
- && widget.respond_to?('exist?') \
- && ! receiver.exist? ) \
- || ( receiver.kind_of?(TkObject) \
- && receiver.respond_to?('exist?') \
- && ! receiver.exist? ) )
- @observ.delete(win)
- else
- fail e
- end
- end
- }
-
- self
- end
- alias apply notify
-
- def +(hash)
- unless hash.kind_of?(Hash)
- fail ArgumentError, "expect a Hash"
- end
- new_obj = self.dup
- new_obj.update_without_notify(_symbolkey2str(hash))
- new_obj
- end
-
- alias update_without_notify update
-
- def update(hash)
- update_without_notify(_symbolkey2str(hash))
- notify
- end
-
- def configure(key, value=nil)
- if key.kind_of?(Hash)
- update(key)
- else
- store(key,value)
- end
- end
-
- def [](key)
- super(key.to_s)
- end
- alias cget []
-
- def store(key, val)
- key = key.to_s
- super(key, val)
- notify
- end
- def []=(key, val)
- store(key,val)
- end
-
- def replace(hash)
- super(_symbolkey2str(hash))
- notify
- end
-
- def default(opt)
- fail RuntimeError, "unknown option `#{opt}'"
- end
- private :default
-
- undef :default=
- end
-end
diff --git a/ext/tk/lib/tk/pack.rb b/ext/tk/lib/tk/pack.rb
deleted file mode 100644
index 8fab363121..0000000000
--- a/ext/tk/lib/tk/pack.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-#
-# tk/pack.rb : control pack geometry manager
-#
-require 'tk'
-
-module TkPack
- include Tk
- extend Tk
-
- TkCommandNames = ['pack'.freeze].freeze
-
- def configure(win, *args)
- if args[-1].kind_of?(Hash)
- opts = args.pop
- else
- opts = {}
- end
- params = []
- # params.push((win.kind_of?(TkObject))? win.epath: win)
- params.push(_epath(win))
- args.each{|win|
- # params.push((win.kind_of?(TkObject))? win.epath: win)
- params.push(_epath(win))
- }
- opts.each{|k, v|
- params.push("-#{k}")
- # params.push((v.kind_of?(TkObject))? v.epath: v)
- params.push(_epath(v))
- }
- tk_call_without_enc("pack", 'configure', *params)
- end
- alias pack configure
-
- def forget(*args)
- return '' if args.size == 0
- wins = args.collect{|win|
- # (win.kind_of?(TkObject))? win.epath: win
- _epath(win)
- }
- tk_call_without_enc('pack', 'forget', *wins)
- end
-
- def info(slave)
- # slave = slave.epath if slave.kind_of?(TkObject)
- slave = _epath(slave)
- ilist = list(tk_call_without_enc('pack', 'info', slave))
- info = {}
- while key = ilist.shift
- info[key[1..-1]] = ilist.shift
- end
- return info
- end
-
- def propagate(master, mode=None)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- if mode == None
- bool(tk_call_without_enc('pack', 'propagate', master))
- else
- tk_call_without_enc('pack', 'propagate', master, mode)
- end
- end
-
- def slaves(master)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- list(tk_call_without_enc('pack', 'slaves', master))
- end
-
- module_function :pack, :configure, :forget, :info, :propagate, :slaves
-end
-=begin
-def TkPack(win, *args)
- if args[-1].kind_of?(Hash)
- opts = args.pop
- else
- opts = {}
- end
- params = []
- params.push((win.kind_of?(TkObject))? win.epath: win)
- args.each{|win|
- params.push((win.kind_of?(TkObject))? win.epath: win)
- }
- opts.each{|k, v|
- params.push("-#{k}")
- params.push((v.kind_of?(TkObject))? v.epath: v)
- }
- tk_call_without_enc("pack", *params)
-end
-=end
diff --git a/ext/tk/lib/tk/package.rb b/ext/tk/lib/tk/package.rb
deleted file mode 100644
index d1eb27674d..0000000000
--- a/ext/tk/lib/tk/package.rb
+++ /dev/null
@@ -1,139 +0,0 @@
-#
-# tk/package.rb : package command
-#
-require 'tk'
-
-module TkPackage
- include TkCore
- extend TkPackage
-
- TkCommandNames = ['package'.freeze].freeze
-
- def add_path(path)
- Tk::AUTO_PATH.value = Tk::AUTO_PATH.to_a << path
- end
-
- def forget(package)
- tk_call('package', 'forget', package)
- nil
- end
-
- def if_needed(pkg, ver, *arg, &b)
- size = arg.size
-
- if size==0 && !b
- # proc info
- procedure(tk_call('package', 'ifneeded', pkg, ver))
-
- elsif size==0 && b
- # set proc
- cmd = proc(&b)
- tk_call('package', 'ifneeded', pkg, ver, cmd)
- cmd
-
- elsif size==1 && !b
- # set proc
- cmd = arg[0]
- if cmd
- tk_call('package', 'ifneeded', pkg, ver, cmd)
- cmd
- else
- # remove proc
- tk_call('package', 'ifneeded', pkg, ver, '')
- nil
- end
-
- else
- fail ArgumentError, 'too many arguments'
- end
- end
-
- def names
- tk_split_simplelist(tk_call('package', 'names'))
- end
-
- def provide(package, version=nil)
- if version
- tk_call('package', 'provide', package, version)
- end
- if (ret = tk_call('package', 'provide', package)) == ''
- nil
- else
- ret
- end
- end
-
- def present(package, version=None)
- begin
- tk_call('package', 'present', package, version)
- rescue => e
- fail e.class, 'TkPackage ' << e.message
- end
- end
-
- def present_exact(package, version)
- begin
- tk_call('package', 'present', '-exact', package, version)
- rescue => e
- fail e.class, 'TkPackage ' << e.message
- end
- end
-
- def require(package, version=None)
- begin
- tk_call('package', 'require', package, version)
- rescue => e
- fail e.class, 'TkPackage ' << e.message
- end
- end
-
- def require_exact(package, version)
- begin
- tk_call('package', 'require', '-exact', package, version)
- rescue => e
- fail e.class, 'TkPackage ' << e.message
- end
- end
-
- def unknown_proc(*arg, &b)
- size = arg.size
-
- if size==0 && !b
- # proc info
- procedure(tk_call('package', 'unknown'))
-
- elsif size==0 && b
- # set proc
- cmd = proc(&b)
- tk_call('package', 'unknown', cmd)
- cmd
-
- elsif size==1 && !b
- # set proc
- cmd = arg[0]
- if cmd
- tk_call('package', 'unknown', cmd)
- cmd
- else
- # remove proc
- tk_call('package', 'unknown', '')
- nil
- end
-
- else
- fail ArgumentError, 'too many arguments'
- end
- end
-
- def versions(package)
- tk_split_simplelist(tk_call('package', 'versions', package))
- end
-
- def vcompare(version1, version2)
- number(tk_call('package', 'vcompare', version1, version2))
- end
-
- def vsatisfies(version1, version2)
- bool(tk_call('package', 'vsatisfies', version1, version2))
- end
-end
diff --git a/ext/tk/lib/tk/palette.rb b/ext/tk/lib/tk/palette.rb
deleted file mode 100644
index 2b6fdf5d90..0000000000
--- a/ext/tk/lib/tk/palette.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# tk/palette.rb : methods for Tcl/Tk standard library 'palette.tcl'
-# 1998/06/21 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
-#
-require 'tk'
-
-module TkPalette
- include Tk
- extend Tk
-
- TkCommandNames = [
- 'tk_setPalette'.freeze,
- 'tk_bisque'.freeze,
- 'tkDarken'.freeze
- ].freeze
-
- def TkPalette.set(*args)
- args = args.to_a.flatten if args.kind_of? Hash
- tk_call('tk_setPalette', *args)
- end
- def TkPalette.setPalette(*args)
- TkPalette.set(*args)
- end
-
- def TkPalette.bisque
- tk_call('tk_bisque')
- end
-
- def TkPalette.darken(color, percent)
- tk_call('tkDarken', color, percent)
- end
-
- def TkPalette.recolorTree(win, colors)
- if not colors.kind_of?(Hash)
- fail "2nd arg need to be Hash"
- end
-
- tk_call('global', "tkPalette")
- colors.each{|key, value|
- begin
- if win.cget(key) == tk_call('set', "tkPalette(#{key})")
- win[key] = colors[key]
- end
- rescue
- # ignore
- end
- }
-
- TkWinfo.children(win).each{|w| TkPalette.recolorTree(w, colors)}
- end
-
- def recolorTree(colors)
- TkPalette.recolorTree(self, colors)
- end
-end
diff --git a/ext/tk/lib/tk/panedwindow.rb b/ext/tk/lib/tk/panedwindow.rb
deleted file mode 100644
index c6cf3cd11f..0000000000
--- a/ext/tk/lib/tk/panedwindow.rb
+++ /dev/null
@@ -1,232 +0,0 @@
-#
-# tk/panedwindow.rb : treat panedwindow
-#
-require 'tk'
-
-class TkPanedWindow<TkWindow
- TkCommandNames = ['panedwindow'.freeze].freeze
- WidgetClassName = 'Panedwindow'.freeze
- WidgetClassNames[WidgetClassName] = self
- #def create_self(keys)
- # if keys and keys != None
- # tk_call_without_enc('panedwindow', @path, *hash_kv(keys, true))
- # else
- # tk_call_without_enc('panedwindow', @path)
- # end
- #end
- #private :create_self
-
- def add(*args)
- keys = args.pop
- fail ArgumentError, "no window in arguments" unless keys
- if keys && keys.kind_of?(Hash)
- fail ArgumentError, "no window in arguments" if args == []
- # args = args.collect{|w| (w.kind_of?(TkObject))? w.epath: w }
- args = args.collect{|w| _epath(w) }
- #args.push(hash_kv(keys))
- args.concat(hash_kv(keys))
- else
- args.push(keys) if keys
- # args = args.collect{|w| (w.kind_of?(TkObject))? w.epath: w }
- args = args.collect{|w| _epath(w) }
- end
- tk_send_without_enc('add', *args)
- self
- end
-
- def forget(win, *wins)
- wins.unshift(win)
- # tk_send_without_enc('forget', *((w.kind_of?(TkObject))? w.epath: w))
- tk_send_without_enc('forget', *(wins.collect{|w| _epath(w)}))
- self
- end
- alias del forget
- alias delete forget
- alias remove forget
-
- def identify(x, y)
- list(tk_send_without_enc('identify', x, y))
- end
-
- def proxy_coord
- list(tk_send_without_enc('proxy', 'coord'))
- end
- def proxy_forget
- tk_send_without_enc('proxy', 'forget')
- self
- end
- def proxy_place(x, y)
- tk_send_without_enc('proxy', 'place', x, y)
- self
- end
-
- def sash_coord(index)
- list(tk_send('sash', 'coord', index))
- end
- def sash_dragto(index, x, y)
- tk_send('sash', 'dragto', index, x, y)
- self
- end
- def sash_mark(index, x, y)
- tk_send('sash', 'mark', index, x, y)
- self
- end
- def sash_place(index, x, y)
- tk_send('sash', 'place', index, x, y)
- self
- end
-
- def panecget(win, key)
- # win = win.epath if win.kind_of?(TkObject)
- win = _epath(win)
- tk_tcl2ruby(tk_send_without_enc('panecget', win, "-#{key}"))
- end
-
- def paneconfigure(win, key, value=nil)
- # win = win.epath if win.kind_of?(TkObject)
- win = _epath(win)
- if key.kind_of? Hash
- params = []
- key.each{|k, v|
- params.push("-#{k}")
- # params.push((v.kind_of?(TkObject))? v.epath: v)
- params.push(_epath(v))
- }
- tk_send_without_enc('paneconfigure', win, *params)
- else
- # value = value.epath if value.kind_of?(TkObject)
- value = _epath(value)
- tk_send_without_enc('paneconfigure', win, "-#{key}", value)
- end
- self
- end
- alias pane_config paneconfigure
-
- def paneconfiginfo(win, key=nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- # win = win.epath if win.kind_of?(TkObject)
- win = _epath(win)
- if key
- #conf = tk_split_list(tk_send_without_enc('paneconfigure',
- # win, "-#{key}"))
- conf = tk_split_list(tk_send_without_enc('paneconfigure',
- win, "-#{key}"),
- false, true)
- conf[0] = conf[0][1..-1]
- if conf[0] == 'hide'
- conf[3] = bool(conf[3]) unless conf[3].empty?
- conf[4] = bool(conf[4]) unless conf[4].empty?
- end
- conf
- else
- #tk_split_simplelist(tk_send_without_enc('paneconfigure',
- # win)).collect{|conflist|
- # conf = tk_split_simplelist(conflist)
- tk_split_simplelist(tk_send_without_enc('paneconfigure', win),
- false, false).collect{|conflist|
- conf = tk_split_simplelist(conflist, false, true)
- conf[0] = conf[0][1..-1]
- if conf[3]
- if conf[0] == 'hide'
- conf[3] = bool(conf[3]) unless conf[3].empty?
- elsif conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- if conf[4]
- if conf[0] == 'hide'
- conf[4] = bool(conf[4]) unless conf[4].empty?
- elsif conf[4].index('{')
- conf[4] = tk_split_list(conf[4])
- else
- conf[4] = tk_tcl2ruby(conf[4])
- end
- end
- conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
- conf
- }
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- # win = win.epath if win.kind_of?(TkObject)
- win = _epath(win)
- if key
- #conf = tk_split_list(tk_send_without_enc('paneconfigure',
- # win, "-#{key}"))
- conf = tk_split_list(tk_send_without_enc('paneconfigure',
- win, "-#{key}"),
- false, true)
- key = conf.shift[1..-1]
- if key == 'hide'
- conf[2] = bool(conf[2]) unless conf[2].empty?
- conf[3] = bool(conf[3]) unless conf[3].empty?
- end
- { key => conf }
- else
- ret = {}
- #tk_split_simplelist(tk_send_without_enc('paneconfigure',
- # win)).each{|conflist|
- # conf = tk_split_simplelist(conflist)
- tk_split_simplelist(tk_send_without_enc('paneconfigure', win),
- false, false).each{|conflist|
- conf = tk_split_simplelist(conflist, false, true)
- key = conf.shift[1..-1]
- if key
- if key == 'hide'
- conf[2] = bool(conf[2]) unless conf[2].empty?
- elsif conf[2].index('{')
- conf[2] = tk_split_list(conf[2])
- else
- conf[2] = tk_tcl2ruby(conf[2])
- end
- end
- if conf[3]
- if key == 'hide'
- conf[3] = bool(conf[3]) unless conf[3].empty?
- elsif conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- if conf.size == 1
- ret[key] = conf[0][1..-1] # alias info
- else
- ret[key] = conf
- end
- }
- ret
- end
- end
- end
- alias pane_configinfo paneconfiginfo
-
- def current_paneconfiginfo(win, key=nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- conf = paneconfiginfo(win, key)
- {conf[0] => conf[4]}
- else
- ret = {}
- paneconfiginfo(win).each{|conf|
- ret[conf[0]] = conf[4] if conf.size > 2
- }
- ret
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- ret = {}
- paneconfiginfo(win, key).each{|k, conf|
- ret[k] = conf[-1] if conf.kind_of?(Array)
- }
- ret
- end
- end
-
- alias current_pane_configinfo current_paneconfiginfo
-
- def panes
- list(tk_send_without_enc('panes'))
- end
-end
-TkPanedwindow = TkPanedWindow
diff --git a/ext/tk/lib/tk/place.rb b/ext/tk/lib/tk/place.rb
deleted file mode 100644
index f7ebdfcbd6..0000000000
--- a/ext/tk/lib/tk/place.rb
+++ /dev/null
@@ -1,128 +0,0 @@
-#
-# tk/place.rb : control place geometry manager
-#
-require 'tk'
-
-module TkPlace
- include Tk
- extend Tk
-
- TkCommandNames = ['place'.freeze].freeze
-
- def configure(win, slot, value=None)
- # for >= Tk8.4a2 ?
- # win = win.epath if win.kind_of?(TkObject)
- win = _epath(win)
- if slot.kind_of? Hash
- params = []
- slot.each{|k, v|
- params.push("-#{k}")
- # params.push((v.kind_of?(TkObject))? v.epath: v)
- params.push(_epath(v))
- }
- tk_call_without_enc('place', 'configure', win, *params)
- else
- # value = value.epath if value.kind_of?(TkObject)
- value = _epath(value)
- tk_call_without_enc('place', 'configure', win, "-#{slot}", value)
- end
- end
- alias place configure
-
- def configinfo(win, slot = nil)
- # for >= Tk8.4a2 ?
- if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
- # win = win.epath if win.kind_of?(TkObject)
- win = _epath(win)
- if slot
- #conf = tk_split_list(tk_call_without_enc('place', 'configure',
- # win, "-#{slot}") )
- conf = tk_split_simplelist(tk_call_without_enc('place', 'configure',
- win, "-#{slot}") )
- conf[0] = conf[0][1..-1]
- conf[1] = tk_tcl2ruby(conf[1])
- conf[2] = tk_tcl2ruby(conf[1])
- conf[3] = tk_tcl2ruby(conf[1])
- conf[4] = tk_tcl2ruby(conf[1])
- conf
- else
- tk_split_simplelist(tk_call_without_enc('place', 'configure',
- win)).collect{|conflist|
- #conf = list(conflist)
- conf = simplelist(conflist).collect!{|inf| tk_tcl2ruby(inf)}
- conf[0] = conf[0][1..-1]
- conf
- }
- end
- else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
- current_configinfo(win, slot)
- end
- end
-
- def current_configinfo(win, slot = nil)
- # win = win.epath if win.kind_of?(TkObject)
- win = _epath(win)
- if slot
- #conf = tk_split_list(tk_call_without_enc('place', 'configure',
- # win, "-#{slot}") )
- conf = tk_split_simplelist(tk_call_without_enc('place', 'configure',
- win, "-#{slot}") )
- # { conf[0][1..-1] => conf[1] }
- { conf[0][1..-1] => tk_tcl2ruby(conf[4]) }
- else
- ret = {}
- #tk_split_list(tk_call_without_enc('place','configure',win)).each{|conf|
- tk_split_simplelist(tk_call_without_enc('place', 'configure',
- win)).each{|conf_list|
- #ret[conf[0][1..-1]] = conf[1]
- conf = simplelist(conf_list)
- ret[conf[0][1..-1]] = tk_tcl2ruby(conf[4])
- }
- ret
- end
- end
-
- def forget(win)
- # win = win.epath if win.kind_of?(TkObject)
- win = _epath(win)
- tk_call_without_enc('place', 'forget', win)
- end
-
- def info(win)
- # win = win.epath if win.kind_of?(TkObject)
- win = _epath(win)
- #ilist = list(tk_call_without_enc('place', 'info', win))
- ilist = simplelist(tk_call_without_enc('place', 'info', win))
- info = {}
- while key = ilist.shift
- #info[key[1..-1]] = ilist.shift
- info[key[1..-1]] = tk_tcl2ruby(ilist.shift)
- end
- return info
- end
-
- def slaves(master)
- # master = master.epath if master.kind_of?(TkObject)
- master = _epath(master)
- list(tk_call('place', 'slaves', master))
- end
-
- module_function :place, :configure, :configinfo, :current_configinfo
- module_function :forget, :info, :slaves
-end
-=begin
-def TkPlace(win, slot, value=None)
- win = win.epath if win.kind_of?(TkObject)
- if slot.kind_of? Hash
- params = []
- slot.each{|k, v|
- params.push("-#{k}")
- params.push((v.kind_of?(TkObject))? v.epath: v)
- }
- tk_call_without_enc('place', win, *params)
- else
- value = value.epath if value.kind_of?(TkObject)
- tk_call_without_enc('place', win, "-#{slot}", value)
- end
-end
-=end
diff --git a/ext/tk/lib/tk/radiobutton.rb b/ext/tk/lib/tk/radiobutton.rb
deleted file mode 100644
index f8f67d709a..0000000000
--- a/ext/tk/lib/tk/radiobutton.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-#
-# tk/radiobutton.rb : treat radiobutton widget
-#
-require 'tk'
-require 'tk/button'
-
-class TkRadioButton<TkButton
- TkCommandNames = ['radiobutton'.freeze].freeze
- WidgetClassName = 'Radiobutton'.freeze
- WidgetClassNames[WidgetClassName] = self
- #def create_self(keys)
- # if keys and keys != None
- # tk_call_without_enc('radiobutton', @path, *hash_kv(keys, true))
- # else
- # tk_call_without_enc('radiobutton', @path)
- # end
- #end
- #private :create_self
-
- def __boolval_optkeys
- super() << 'indicatoron'
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- super() << 'selectcolor'
- end
- private :__strval_optkeys
-
- def __ruby2val_optkeys # { key=>proc, ... }
- {
- 'variable'=>proc{|v| tk_trace_variable(v)} # for backward compatibility
- }
- end
- private :__ruby2val_optkeys
-
-
- def deselect
- tk_send_without_enc('deselect')
- self
- end
- def select
- tk_send_without_enc('select')
- self
- end
-
- def get_value
- var = tk_send_without_enc('cget', '-variable')
- if TkVariable::USE_TCLs_SET_VARIABLE_FUNCTIONS
- _fromUTF8(INTERP._get_global_var(var))
- else
- INTERP._eval(Kernel.format('global %s; set %s', var, var))
- end
- end
-
- def set_value(val)
- var = tk_send_without_enc('cget', '-variable')
- if TkVariable::USE_TCLs_SET_VARIABLE_FUNCTIONS
- _fromUTF8(INTERP._set_global_var(var, _get_eval_string(val, true)))
- else
- s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
- INTERP._eval(Kernel.format('global %s; set %s %s', var, var, s))
- end
- end
-end
-TkRadiobutton = TkRadioButton
diff --git a/ext/tk/lib/tk/root.rb b/ext/tk/lib/tk/root.rb
deleted file mode 100644
index 0e5584c7c1..0000000000
--- a/ext/tk/lib/tk/root.rb
+++ /dev/null
@@ -1,108 +0,0 @@
-#
-# tk/root.rb : treat root widget
-#
-require 'tk'
-require 'tk/wm'
-require 'tk/menuspec'
-
-class TkRoot<TkWindow
- include Wm
- include TkMenuSpec
-
- def __methodcall_optkeys # { key=>method, ... }
- TOPLEVEL_METHODCALL_OPTKEYS
- end
- private :__methodcall_optkeys
-
-=begin
- ROOT = []
- def TkRoot.new(keys=nil)
- if ROOT[0]
- Tk_WINDOWS["."] = ROOT[0]
- return ROOT[0]
- end
- new = super(:without_creating=>true, :widgetname=>'.')
- if keys # wm commands
- keys.each{|k,v|
- if v.kind_of? Array
- new.send(k,*v)
- else
- new.send(k,v)
- end
- }
- end
- ROOT[0] = new
- Tk_WINDOWS["."] = new
- end
-=end
- def TkRoot.new(keys=nil, &b)
- unless TkCore::INTERP.tk_windows['.']
- TkCore::INTERP.tk_windows['.'] =
- super(:without_creating=>true, :widgetname=>'.'){}
- end
- root = TkCore::INTERP.tk_windows['.']
-
- keys = _symbolkey2str(keys)
-
- # wm commands
- root.instance_eval{
- __methodcall_optkeys.each{|key, method|
- value = keys.delete(key.to_s)
- self.__send__(method, value) if value
- }
- }
-
- if keys # wm commands ( for backward comaptibility )
- keys.each{|k,v|
- if v.kind_of? Array
- root.__send__(k,*v)
- else
- root.__send__(k,v)
- end
- }
- end
-
- root.instance_eval(&b) if block_given?
- root
- end
-
- WidgetClassName = 'Tk'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def self.to_eval
- # self::WidgetClassName
- '.'
- end
-
- def create_self
- @path = '.'
- end
- private :create_self
-
- def path
- "."
- end
-
- def add_menu(menu_info, tearoff=false, opts=nil)
- # See tk/menuspec.rb for menu_info.
- # opts is a hash of default configs for all of cascade menus.
- # Configs of menu_info can override it.
- if tearoff.kind_of?(Hash)
- opts = tearoff
- tearoff = false
- end
- _create_menubutton(self, menu_info, tearoff, opts)
- end
-
- def add_menubar(menu_spec, tearoff=false, opts=nil)
- # See tk/menuspec.rb for menu_spec.
- # opts is a hash of default configs for all of cascade menus.
- # Configs of menu_spec can override it.
- menu_spec.each{|info| add_menu(info, tearoff, opts)}
- self.menu
- end
-
- def TkRoot.destroy
- TkCore::INTERP._invoke('destroy', '.')
- end
-end
diff --git a/ext/tk/lib/tk/scale.rb b/ext/tk/lib/tk/scale.rb
deleted file mode 100644
index 0b703aa055..0000000000
--- a/ext/tk/lib/tk/scale.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-#
-# tk/scale.rb : treat scale widget
-#
-require 'tk'
-
-class TkScale<TkWindow
- TkCommandNames = ['scale'.freeze].freeze
- WidgetClassName = 'Scale'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def create_self(keys)
- if keys and keys != None
- if keys.key?('command') && ! keys['command'].kind_of?(String)
- cmd = keys.delete('command')
- keys['command'] = proc{|val| cmd.call(val.to_f)}
- end
- #tk_call_without_enc('scale', @path, *hash_kv(keys, true))
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
- else
- #tk_call_without_enc('scale', @path)
- tk_call_without_enc(self.class::TkCommandNames[0], @path)
- end
- end
- private :create_self
-
- def __strval_optkeys
- super() << 'label'
- end
- private :__strval_optkeys
-
- def _wrap_command_arg(cmd)
- proc{|val|
- if val.kind_of?(String)
- cmd.call(number(val))
- else
- cmd.call(val)
- end
- }
- end
- private :_wrap_command_arg
-
- def configure_cmd(slot, value)
- configure(slot=>value)
- end
-
- def configure(slot, value=None)
- if (slot == 'command' || slot == :command)
- configure('command'=>value)
- elsif slot.kind_of?(Hash) &&
- (slot.key?('command') || slot.key?(:command))
- slot = _symbolkey2str(slot)
- slot['command'] = _wrap_command_arg(slot.delete('command'))
- end
- super(slot, value)
- end
-
- def command(cmd=Proc.new)
- configure('command'=>cmd)
- end
-
- def get(x=None, y=None)
- number(tk_send_without_enc('get', x, y))
- end
-
- def coords(val=None)
- tk_split_list(tk_send_without_enc('coords', val))
- end
-
- def identify(x, y)
- tk_send_without_enc('identify', x, y)
- end
-
- def set(val)
- tk_send_without_enc('set', val)
- end
-
- def value
- get
- end
-
- def value= (val)
- set(val)
- val
- end
-end
diff --git a/ext/tk/lib/tk/scrollable.rb b/ext/tk/lib/tk/scrollable.rb
deleted file mode 100644
index ec27b76467..0000000000
--- a/ext/tk/lib/tk/scrollable.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-#
-# tk/scrollable.rb : module for scrollable widget
-#
-require 'tk'
-
-module Tk
- module X_Scrollable
- def xscrollcommand(cmd=Proc.new)
- configure_cmd 'xscrollcommand', cmd
- # Tk.update # avoid scrollbar trouble
- self
- end
-
- def xview(*index)
- if index.size == 0
- list(tk_send_without_enc('xview'))
- else
- tk_send_without_enc('xview', *index)
- self
- end
- end
- def xview_moveto(*index)
- xview('moveto', *index)
- end
- def xview_scroll(*index)
- xview('scroll', *index)
- end
-
- def xscrollbar(bar=nil)
- if bar
- @xscrollbar = bar
- @xscrollbar.orient 'horizontal'
- self.xscrollcommand {|*arg| @xscrollbar.set(*arg)}
- @xscrollbar.command {|*arg| self.xview(*arg)}
- Tk.update # avoid scrollbar trouble
- end
- @xscrollbar
- end
- end
-
- module Y_Scrollable
- def yscrollcommand(cmd=Proc.new)
- configure_cmd 'yscrollcommand', cmd
- # Tk.update # avoid scrollbar trouble
- self
- end
-
- def yview(*index)
- if index.size == 0
- list(tk_send_without_enc('yview'))
- else
- tk_send_without_enc('yview', *index)
- self
- end
- end
- def yview_moveto(*index)
- yview('moveto', *index)
- end
- def yview_scroll(*index)
- yview('scroll', *index)
- end
-
- def yscrollbar(bar=nil)
- if bar
- @yscrollbar = bar
- @yscrollbar.orient 'vertical'
- self.yscrollcommand {|*arg| @yscrollbar.set(*arg)}
- @yscrollbar.command {|*arg| self.yview(*arg)}
- Tk.update # avoid scrollbar trouble
- end
- @yscrollbar
- end
- end
-
- module Scrollable
- include X_Scrollable
- include Y_Scrollable
- end
-end
diff --git a/ext/tk/lib/tk/scrollbar.rb b/ext/tk/lib/tk/scrollbar.rb
deleted file mode 100644
index 70aadfdd4c..0000000000
--- a/ext/tk/lib/tk/scrollbar.rb
+++ /dev/null
@@ -1,124 +0,0 @@
-#
-# tk/scrollbar.rb : treat scrollbar widget
-#
-require 'tk'
-
-class TkScrollbar<TkWindow
- TkCommandNames = ['scrollbar'.freeze].freeze
- WidgetClassName = 'Scrollbar'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def create_self(keys)
- @assigned = []
- @scroll_proc = proc{|*args|
- if self.orient == 'horizontal'
- @assigned.each{|w| w.xview(*args)}
- else # 'vertical'
- @assigned.each{|w| w.yview(*args)}
- end
- }
-
- if keys and keys != None
- #tk_call_without_enc('scrollbar', @path, *hash_kv(keys, true))
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
- else
- #tk_call_without_enc('scrollbar', @path)
- tk_call_without_enc(self.class::TkCommandNames[0], @path)
- end
- end
- private :create_self
-
- def propagate_set(src_win, first, last)
- self.set(first, last)
- if self.orient == 'horizontal'
- @assigned.each{|w| w.xview('moveto', first) if w != src_win}
- else # 'vertical'
- @assigned.each{|w| w.yview('moveto', first) if w != src_win}
- end
- end
-
- def assign(*wins)
- begin
- self.command(@scroll_proc) if self.cget('command').cmd != @scroll_proc
- rescue Exception
- self.command(@scroll_proc)
- end
- orient = self.orient
- wins.each{|w|
- @assigned << w unless @assigned.index(w)
- if orient == 'horizontal'
- w.xscrollcommand proc{|first, last| self.propagate_set(w, first, last)}
- else # 'vertical'
- w.yscrollcommand proc{|first, last| self.propagate_set(w, first, last)}
- end
- }
- Tk.update # avoid scrollbar trouble
- self
- end
-
- def assigned_list
- begin
- return @assigned.dup if self.cget('command').cmd == @scroll_proc
- rescue Exception
- end
- fail RuntimeError, "not depend on the assigned_list"
- end
-
- def configure(*args)
- ret = super(*args)
- # Tk.update # avoid scrollbar trouble
- ret
- end
-
- #def delta(deltax=None, deltay=None)
- def delta(deltax, deltay)
- number(tk_send_without_enc('delta', deltax, deltay))
- end
-
- #def fraction(x=None, y=None)
- def fraction(x, y)
- number(tk_send_without_enc('fraction', x, y))
- end
-
- def identify(x, y)
- tk_send_without_enc('identify', x, y)
- end
-
- def get
- #ary1 = tk_send('get').split
- #ary2 = []
- #for i in ary1
- # ary2.push number(i)
- #end
- #ary2
- list(tk_send_without_enc('get'))
- end
-
- def set(first, last)
- tk_send_without_enc('set', first, last)
- self
- end
-
- def activate(element=None)
- tk_send_without_enc('activate', element)
- end
-end
-
-class TkXScrollbar<TkScrollbar
- def create_self(keys)
- keys = {} unless keys
- keys['orient'] = 'horizontal'
- super(keys)
- end
- private :create_self
-end
-
-class TkYScrollbar<TkScrollbar
- def create_self(keys)
- keys = {} unless keys
- keys['orient'] = 'vertical'
- super(keys)
- end
- private :create_self
-end
diff --git a/ext/tk/lib/tk/scrollbox.rb b/ext/tk/lib/tk/scrollbox.rb
deleted file mode 100644
index fd04057fb6..0000000000
--- a/ext/tk/lib/tk/scrollbox.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# tk/scrollbox.rb - Tk Listbox with Scrollbar
-# as an example of Composite Widget
-# $Date$
-# by Yukihiro Matsumoto <matz@netlab.co.jp>
-#
-require 'tk'
-require 'tk/listbox'
-
-class TkScrollbox<TkListbox
- include TkComposite
- def initialize_composite(keys=nil)
- list = TkListbox.new(@frame)
- scroll = TkScrollbar.new(@frame)
- @path = list.path
-
-=begin
- list.configure 'yscroll', scroll.path+" set"
- list.pack 'side'=>'left','fill'=>'both','expand'=>'yes'
- scroll.configure 'command', list.path+" yview"
- scroll.pack 'side'=>'right','fill'=>'y'
-=end
- list.yscrollbar(scroll)
- list.pack('side'=>'left','fill'=>'both','expand'=>'yes')
- scroll.pack('side'=>'right','fill'=>'y')
-
- delegate('DEFAULT', list)
- delegate('foreground', list)
- delegate('background', list, scroll)
- delegate('borderwidth', @frame)
- delegate('relief', @frame)
-
- configure keys if keys
- end
- private :initialize_composite
-end
diff --git a/ext/tk/lib/tk/selection.rb b/ext/tk/lib/tk/selection.rb
deleted file mode 100644
index 5caa6ef8ef..0000000000
--- a/ext/tk/lib/tk/selection.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-#
-# tk/selection.rb : control selection
-#
-require 'tk'
-
-module TkSelection
- include Tk
- extend Tk
-
- TkCommandNames = ['selection'.freeze].freeze
-
- def self.clear(sel=nil)
- if sel
- tk_call_without_enc('selection', 'clear', '-selection', sel)
- else
- tk_call_without_enc('selection', 'clear')
- end
- end
- def self.clear_on_display(win, sel=nil)
- if sel
- tk_call_without_enc('selection', 'clear',
- '-displayof', win, '-selection', sel)
- else
- tk_call_without_enc('selection', 'clear', '-displayof', win)
- end
- end
- def clear(sel=nil)
- TkSelection.clear_on_display(self, sel)
- self
- end
-
- def self.get(keys=nil)
- #tk_call('selection', 'get', *hash_kv(keys))
- _fromUTF8(tk_call_without_enc('selection', 'get', *hash_kv(keys)))
- end
- def self.get_on_display(win, keys=nil)
- #tk_call('selection', 'get', '-displayof', win, *hash_kv(keys))
- _fromUTF8(tk_call_without_enc('selection', 'get', '-displayof',
- win, *hash_kv(keys)))
- end
- def get(keys=nil)
- TkSelection.get_on_display(self, sel)
- end
-
- def self.handle(win, func=Proc.new, keys=nil, &b)
- if func.kind_of?(Hash) && keys == nil
- keys = func
- func = Proc.new(&b)
- end
- args = ['selection', 'handle']
- args.concat(hash_kv(keys))
- args.concat([win, func])
- tk_call_without_enc(*args)
- end
- def handle(func=Proc.new, keys=nil, &b)
- TkSelection.handle(self, func, keys, &b)
- end
-
- def self.get_owner(sel=nil)
- if sel
- window(tk_call_without_enc('selection', 'own', '-selection', sel))
- else
- window(tk_call_without_enc('selection', 'own'))
- end
- end
- def self.get_owner_on_display(win, sel=nil)
- if sel
- window(tk_call_without_enc('selection', 'own',
- '-displayof', win, '-selection', sel))
- else
- window(tk_call_without_enc('selection', 'own', '-displayof', win))
- end
- end
- def get_owner(sel=nil)
- TkSelection.get_owner_on_display(self, sel)
- self
- end
-
- def self.set_owner(win, keys=nil)
- tk_call_without_enc('selection', 'own', *(hash_kv(keys) << win))
- end
- def set_owner(keys=nil)
- TkSelection.set_owner(self, keys)
- self
- end
-end
diff --git a/ext/tk/lib/tk/spinbox.rb b/ext/tk/lib/tk/spinbox.rb
deleted file mode 100644
index 9a10977d12..0000000000
--- a/ext/tk/lib/tk/spinbox.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-#
-# tk/spinbox.rb - Tk spinbox classes
-# $Date$
-# by Yukihiro Matsumoto <matz@caelum.co.jp>
-#
-require 'tk'
-require 'tk/entry'
-
-class TkSpinbox<TkEntry
- TkCommandNames = ['spinbox'.freeze].freeze
- WidgetClassName = 'Spinbox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- class SpinCommand < TkValidateCommand
- class ValidateArgs < TkUtil::CallbackSubst
- KEY_TBL = [
- [ ?d, ?s, :direction ],
- [ ?s, ?e, :current ],
- [ ?W, ?w, :widget ],
- nil
- ]
-
- PROC_TBL = [
- [ ?s, TkComm.method(:string) ],
- [ ?w, TkComm.method(:window) ],
-
- [ ?e, proc{|val|
- #enc = Tk.encoding
- enc = ((Tk.encoding)? Tk.encoding : Tk.encoding_system)
- if enc
- Tk.fromUTF8(TkComm::string(val), enc)
- else
- TkComm::string(val)
- end
- }
- ],
-
- nil
- ]
-
- _setup_subst_table(KEY_TBL, PROC_TBL);
-
- def self.ret_val(val)
- (val)? '1': '0'
- end
- end
-
- def self._config_keys
- ['command']
- end
- end
-
- def __validation_class_list
- super() << SpinCommand
- end
-
- Tk::ValidateConfigure.__def_validcmd(binding, SpinCommand)
-
- #def create_self(keys)
- # tk_call_without_enc('spinbox', @path)
- # if keys and keys != None
- # configure(keys)
- # end
- #end
- #private :create_self
-
- def __boolval_optkeys
- super() << 'wrap'
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- super() << 'buttonbackground' << 'format'
- end
- private :__strval_optkeys
-
- def __listval_optkeys
- super() << 'values'
- end
- private :__listval_optkeys
-
- def identify(x, y)
- tk_send_without_enc('identify', x, y)
- end
-
- def spinup
- tk_send_without_enc('invoke', 'spinup')
- self
- end
-
- def spindown
- tk_send_without_enc('invoke', 'spindown')
- self
- end
-
- def set(str)
- _fromUTF8(tk_send_without_enc('set', _get_eval_enc_str(str)))
- end
-end
diff --git a/ext/tk/lib/tk/tagfont.rb b/ext/tk/lib/tk/tagfont.rb
deleted file mode 100644
index a1807395d2..0000000000
--- a/ext/tk/lib/tk/tagfont.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# tk/tagfont.rb : control font of tags
-#
-require 'tk'
-
-module TkTreatTagFont
- def font_configinfo
- @parent.tagfont_configinfo(@id)
- end
-# alias font font_configinfo
-
- def font_configure(slot)
- @parent.tagfont_configure(@id, slot)
- self
- end
-
- def latinfont_configure(ltn, keys=nil)
- @parent.latintagfont_configure(@id, ltn, keys)
- self
- end
- alias asciifont_configure latinfont_configure
-
- def kanjifont_configure(knj, keys=nil)
- @parent.kanjitagfont_configure(@id, ltn, keys)
- self
- end
-
- def font_copy(win, wintag=nil)
- @parent.tagfont_copy(@id, win, wintag)
- self
- end
-
- def latinfont_copy(win, wintag=nil)
- @parent.latintagfont_copy(@id, win, wintag)
- self
- end
- alias asciifont_copy latinfont_copy
-
- def kanjifont_copy(win, wintag=nil)
- @parent.kanjitagfont_copy(@id, win, wintag)
- self
- end
-end
diff --git a/ext/tk/lib/tk/text.rb b/ext/tk/lib/tk/text.rb
deleted file mode 100644
index 49d4b5625b..0000000000
--- a/ext/tk/lib/tk/text.rb
+++ /dev/null
@@ -1,1550 +0,0 @@
-#
-# tk/text.rb - Tk text classes
-# $Date$
-# by Yukihiro Matsumoto <matz@caelum.co.jp>
-require 'tk'
-require 'tk/itemfont'
-require 'tk/itemconfig'
-require 'tk/scrollable'
-require 'tk/txtwin_abst'
-
-module TkTextTagConfig
- include TkTreatItemFont
- include TkItemConfigMethod
-
- def __item_cget_cmd(id) # id := [ type, tagOrId ]
- [self.path, id[0], 'cget', id[1]]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id) # id := [ type, tagOrId ]
- [self.path, id[0], 'configure', id[1]]
- end
- private :__item_config_cmd
-
- def __item_pathname(id)
- if id.kind_of?(Array)
- id = tagid(id[1])
- end
- [self.path, id].join(';')
- end
- private :__item_pathname
-
- def tag_cget(tagOrId, option)
- itemcget(['tag', tagOrId], option)
- end
- def tag_configure(tagOrId, slot, value=None)
- itemconfigure(['tag', tagOrId], slot, value)
- end
- def tag_configinfo(tagOrId, slot=nil)
- itemconfigure(['tag', tagOrId], slot)
- end
- def current_tag_configinfo(tagOrId, slot=nil)
- itemconfigure(['tag', tagOrId], slot)
- end
-
- def window_cget(tagOrId, option)
- itemcget(['window', tagOrId], option)
- end
- def window_configure(tagOrId, slot, value=None)
- itemconfigure(['window', tagOrId], slot, value)
- end
- def window_configinfo(tagOrId, slot=nil)
- itemconfigure(['window', tagOrId], slot)
- end
- def current_window_configinfo(tagOrId, slot=nil)
- itemconfigure(['window', tagOrId], slot)
- end
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-end
-
-class TkText<TkTextWin
- ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze
- #include TkTreatTextTagFont
- include TkTextTagConfig
- include Scrollable
-
- #######################################
-
- module IndexModMethods
- def +(mod)
- return chars(mod) if mod.kind_of?(Numeric)
-
- mod = mod.to_s
- if mod =~ /^\s*[+-]?\d/
- TkText::IndexString.new(String.new(id) << ' + ' << mod)
- else
- TkText::IndexString.new(String.new(id) << ' ' << mod)
- end
- end
-
- def -(mod)
- return chars(-mod) if mod.kind_of?(Numeric)
-
- mod = mod.to_s
- if mod =~ /^\s*[+-]?\d/
- TkText::IndexString.new(String.new(id) << ' - ' << mod)
- elsif mod =~ /^\s*[-]\s+(\d.*)$/
- TkText::IndexString.new(String.new(id) << ' - -' << $1)
- else
- TkText::IndexString.new(String.new(id) << ' ' << mod)
- end
- end
-
- def chars(mod)
- fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
- if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' chars')
- else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' chars')
- end
- end
- alias char chars
-
- def display_chars(mod)
- # Tk8.5 feature
- fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
- if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display chars')
- else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display chars')
- end
- end
- alias display_char display_chars
-
- def any_chars(mod)
- # Tk8.5 feature
- fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
- if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any chars')
- else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any chars')
- end
- end
- alias any_char any_chars
-
- def indices(mod)
- # Tk8.5 feature
- fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
- if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' indices')
- else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' indices')
- end
- end
-
- def display_indices(mod)
- # Tk8.5 feature
- fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
- if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display indices')
- else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display indices')
- end
- end
-
- def any_indices(mod)
- # Tk8.5 feature
- fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
- if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any indices')
- else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any indices')
- end
- end
-
- def lines(mod)
- fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
- if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' lines')
- else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' lines')
- end
- end
- alias line lines
-
- def display_lines(mod)
- # Tk8.5 feature
- fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
- if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display_lines')
- else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display lines')
- end
- end
- alias display_line display_lines
-
- def any_lines(mod)
- # Tk8.5 feature
- fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
- if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any_lines')
- else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any lines')
- end
- end
- alias any_line any_lines
-
- def linestart
- TkText::IndexString.new(String.new(id) << ' linestart')
- end
- def lineend
- TkText::IndexString.new(String.new(id) << ' lineend')
- end
-
- def display_linestart
- # Tk8.5 feature
- TkText::IndexString.new(String.new(id) << ' display linestart')
- end
- def display_lineend
- # Tk8.5 feature
- TkText::IndexString.new(String.new(id) << ' display lineend')
- end
-
- def wordstart
- TkText::IndexString.new(String.new(id) << ' wordstart')
- end
- def wordend
- TkText::IndexString.new(String.new(id) << ' wordend')
- end
-
- def display_wordstart
- # Tk8.5 feature
- TkText::IndexString.new(String.new(id) << ' display wordstart')
- end
- def display_wordend
- # Tk8.5 feature
- TkText::IndexString.new(String.new(id) << ' display wordend')
- end
- end
-
- class IndexString < String
- include IndexModMethods
-
- def self.at(x,y)
- self.new("@#{x},#{y}")
- end
-
- def self.new(str)
- if str.kind_of?(String)
- super(str)
- elsif str.kind_of?(Symbol)
- super(str.to_s)
- else
- str
- end
- end
-
- def id
- self
- end
- end
-
- #######################################
-
- TkCommandNames = ['text'.freeze].freeze
- WidgetClassName = 'Text'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def self.new(*args, &block)
- obj = super(*args){}
- obj.init_instance_variable
- obj.instance_eval(&block) if defined? yield
- obj
- end
-
- def init_instance_variable
- @cmdtbl = []
- @tags = {}
- end
-
- def __destroy_hook__
- TkTextTag::TTagID_TBL.delete(@path)
- TkTextMark::TMarkID_TBL.delete(@path)
- end
-
- def create_self(keys)
- #if keys and keys != None
- # #tk_call_without_enc('text', @path, *hash_kv(keys, true))
- # tk_call_without_enc(self.class::TkCommandNames[0], @path,
- # *hash_kv(keys, true))
- #else
- # #tk_call_without_enc('text', @path)
- # tk_call_without_enc(self.class::TkCommandNames[0], @path)
- #end
- super(keys)
- init_instance_variable
- end
- private :create_self
-
- def __strval_optkeys
- super() << 'inactiveseletcionbackground'
- end
- private :__strval_optkeys
-
- def self.at(x, y)
- TkText::IndexString.at(x, y)
- end
-
- def at(x, y)
- TkText::IndexString.at(x, y)
- end
-
- def index(idx)
- TkText::IndexString.new(tk_send_without_enc('index',
- _get_eval_enc_str(idx)))
- end
-
- def get_displaychars(*index)
- # Tk8.5 feature
- get('-displaychars', *index)
- end
-
- def value
- _fromUTF8(tk_send_without_enc('get', "1.0", "end - 1 char"))
- end
-
- def value= (val)
- tk_send_without_enc('delete', "1.0", 'end')
- tk_send_without_enc('insert', "1.0", _get_eval_enc_str(val))
- val
- end
-
- def clear
- tk_send_without_enc('delete', "1.0", 'end')
- self
- end
- alias erase clear
-
- def _addcmd(cmd)
- @cmdtbl.push cmd
- end
-
- def _addtag(name, obj)
- @tags[name] = obj
- end
-
- def tagid(tag)
- if tag.kind_of?(TkTextTag) \
- || tag.kind_of?(TkTextMark) \
- || tag.kind_of?(TkTextImage) \
- || tag.kind_of?(TkTextWindow)
- tag.id
- else
- tag # maybe an Array of configure paramters
- end
- end
- private :tagid
-
- def tagid2obj(tagid)
- if @tags[tagid]
- @tags[tagid]
- else
- tagid
- end
- end
-
- def tag_names(index=None)
- #tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag', 'names', _get_eval_enc_str(index)))).collect{|elt|
- tk_split_simplelist(tk_send_without_enc('tag', 'names', _get_eval_enc_str(index)), false, true).collect{|elt|
- tagid2obj(elt)
- }
- end
-
- def mark_names
- #tk_split_simplelist(_fromUTF8(tk_send_without_enc('mark', 'names'))).collect{|elt|
- tk_split_simplelist(tk_send_without_enc('mark', 'names'), false, true).collect{|elt|
- tagid2obj(elt)
- }
- end
-
- def mark_gravity(mark, direction=nil)
- if direction
- tk_send_without_enc('mark', 'gravity',
- _get_eval_enc_str(mark), direction)
- self
- else
- tk_send_without_enc('mark', 'gravity', _get_eval_enc_str(mark))
- end
- end
-
- def mark_set(mark, index)
- tk_send_without_enc('mark', 'set', _get_eval_enc_str(mark),
- _get_eval_enc_str(index))
- self
- end
- alias set_mark mark_set
-
- def mark_unset(*marks)
- tk_send_without_enc('mark', 'unset',
- *(marks.collect{|mark| _get_eval_enc_str(mark)}))
- self
- end
- alias unset_mark mark_unset
-
- def mark_next(index)
- tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'next',
- _get_eval_enc_str(index))))
- end
- alias next_mark mark_next
-
- def mark_previous(index)
- tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'previous',
- _get_eval_enc_str(index))))
- end
- alias previous_mark mark_previous
-
- def image_cget(index, slot)
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- _fromUTF8(tk_send_without_enc('image', 'cget',
- _get_eval_enc_str(index), "-#{slot}"))
- else
- tk_tcl2ruby(_fromUTF8(tk_send_without_enc('image', 'cget',
- _get_eval_enc_str(index),
- "-#{slot}")))
- end
- end
-
- def image_configure(index, slot, value=None)
- if slot.kind_of?(Hash)
- _fromUTF8(tk_send_without_enc('image', 'configure',
- _get_eval_enc_str(index),
- *hash_kv(slot, true)))
- else
- _fromUTF8(tk_send_without_enc('image', 'configure',
- _get_eval_enc_str(index),
- "-#{slot}",
- _get_eval_enc_str(value)))
- end
- self
- end
-
- def image_configinfo(index, slot = nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
- conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true)
- else
- #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
- conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true)
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- # tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).collect{|conflist|
- # conf = tk_split_simplelist(conflist)
- tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).collect{|conflist|
- conf = tk_split_simplelist(conflist, false, true)
- conf[0] = conf[0][1..-1]
- case conf[0]
- when 'text', 'label', 'show', 'data', 'file'
- else
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- if conf[4]
- if conf[4].index('{')
- conf[4] = tk_split_list(conf[4])
- else
- conf[4] = tk_tcl2ruby(conf[4])
- end
- end
- end
- conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
- conf
- }
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
- conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true)
- else
- #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
- conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true)
- end
- key = conf.shift[1..-1]
- { key => conf }
- else
- ret = {}
- #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).each{|conflist|
- # conf = tk_split_simplelist(conflist)
- tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).each{|conflist|
- conf = tk_split_simplelist(conflist, false, true)
- key = conf.shift[1..-1]
- case key
- when 'text', 'label', 'show', 'data', 'file'
- else
- if conf[2]
- if conf[2].index('{')
- conf[2] = tk_split_list(conf[2])
- else
- conf[2] = tk_tcl2ruby(conf[2])
- end
- end
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- end
- if conf.size == 1
- ret[key] = conf[0][1..-1] # alias info
- else
- ret[key] = conf
- end
- }
- ret
- end
- end
- end
-
- def current_image_configinfo(index, slot = nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- conf = image_configinfo(index, slot)
- {conf[0] => conf[4]}
- else
- ret = {}
- image_configinfo(index).each{|conf|
- ret[conf[0]] = conf[4] if conf.size > 2
- }
- ret
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- ret = {}
- image_configinfo(index, slot).each{|k, conf|
- ret[k] = conf[-1] if conf.kind_of?(Array)
- }
- ret
- end
- end
-
- def image_names
- #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'names'))).collect{|elt|
- tk_split_simplelist(tk_send_without_enc('image', 'names'), false, true).collect{|elt|
- tagid2obj(elt)
- }
- end
-
- def set_insert(index)
- tk_send_without_enc('mark','set','insert', _get_eval_enc_str(index))
- self
- end
-
- def set_current(index)
- tk_send_without_enc('mark','set','current', _get_eval_enc_str(index))
- self
- end
-
- def insert(index, chars, *tags)
- if tags[0].kind_of?(Array)
- # multiple chars-taglist argument :: str, [tag,...], str, [tag,...], ...
- args = [chars]
- while tags.size > 0
- args << tags.shift.collect{|x|_get_eval_string(x)}.join(' ') # taglist
- args << tags.shift if tags.size > 0 # chars
- end
- super(index, *args)
- else
- # single chars-taglist argument :: str, tag, tag, ...
- if tags.size == 0
- super(index, chars)
- else
- super(index, chars, tags.collect{|x|_get_eval_string(x)}.join(' '))
- end
- end
- end
-
- def destroy
- @tags = {} unless @tags
- @tags.each_value do |t|
- t.destroy
- end
- super()
- end
-
- def backspace
- self.delete 'insert'
- end
-
- def bbox(index)
- list(tk_send_without_enc('bbox', _get_eval_enc_str(index)))
- end
-
- def compare(idx1, op, idx2)
- bool(tk_send_without_enc('compare', _get_eval_enc_str(idx1),
- op, _get_eval_enc_str(idx2)))
- end
-
- def count(idx1, idx2, *opts)
- # opts are Tk8.5 feature
- cnt = 0
- args = opts.collect{|opt|
- str = opt.to_s
- cnt += 1 if str != 'update'
- '-' + str
- }
- args << _get_eval_enc_str(idx1) << _get_eval_enc_str(idx2)
- if cnt <= 1
- number(tk_send_without_enc('count', *opts))
- else
- list(tk_send_without_enc('count', *opts))
- end
- end
-
- def count_info(idx1, idx2, update=true)
- # Tk8.5 feature
- opts = [
- :chars, :displaychars, :displayindices, :displaylines,
- :indices, :lines, :xpixels, :ypixels
- ]
- if update
- lst = count(idx1, idx2, :update, *opts)
- else
- lst = count(idx1, idx2, *opts)
- end
- info = {}
- opts.each_with_index{|key, idx| info[key] = lst[idx]}
- info
- end
-
- def peer_names()
- # Tk8.5 feature
- list(tk_send_without_enc('peer', 'names'))
- end
-
- def replace(idx1, idx2, *opts)
- tk_send('replace', idx1, idx2, *opts)
- self
- end
-
- def debug
- bool(tk_send_without_enc('debug'))
- end
- def debug=(boolean)
- tk_send_without_enc('debug', boolean)
- #self
- boolean
- end
-
- def dlineinfo(index)
- list(tk_send_without_enc('dlineinfo', _get_eval_enc_str(index)))
- end
-
- def modified?
- bool(tk_send_without_enc('edit', 'modified'))
- end
- def modified(mode)
- tk_send_without_enc('edit', 'modified', mode)
- self
- end
- def modified=(mode)
- modified(mode)
- mode
- end
-
- def edit_redo
- tk_send_without_enc('edit', 'redo')
- self
- end
- def edit_reset
- tk_send_without_enc('edit', 'reset')
- self
- end
- def edit_separator
- tk_send_without_enc('edit', 'separator')
- self
- end
- def edit_undo
- tk_send_without_enc('edit', 'undo')
- self
- end
-
- def xview_pickplace(index)
- tk_send_without_enc('xview', '-pickplace', _get_eval_enc_str(index))
- self
- end
-
- def yview_pickplace(index)
- tk_send_without_enc('yview', '-pickplace', _get_eval_enc_str(index))
- self
- end
-
- def text_copy
- # Tk8.4 feature
- tk_call_without_enc('tk_textCopy', @path)
- self
- end
-
- def text_cut
- # Tk8.4 feature
- tk_call_without_enc('tk_textCut', @path)
- self
- end
-
- def text_paste
- # Tk8.4 feature
- tk_call_without_enc('tk_textPaste', @path)
- self
- end
-
- def tag_add(tag, index1, index2=None)
- tk_send_without_enc('tag', 'add', _get_eval_enc_str(tag),
- _get_eval_enc_str(index1),
- _get_eval_enc_str(index2))
- self
- end
- alias addtag tag_add
- alias add_tag tag_add
-
- def tag_delete(*tags)
- tk_send_without_enc('tag', 'delete',
- *(tags.collect{|tag| _get_eval_enc_str(tag)}))
- if TkTextTag::TTagID_TBL[@path]
- tags.each{|tag|
- if tag.kind_of?(TkTextTag)
- TkTextTag::TTagID_TBL[@path].delete(tag.id)
- else
- TkTextTag::TTagID_TBL[@path].delete(tag)
- end
- }
- end
- self
- end
- alias deltag tag_delete
- alias delete_tag tag_delete
-
- #def tag_bind(tag, seq, cmd=Proc.new, *args)
- # _bind([@path, 'tag', 'bind', tag], seq, cmd, *args)
- # self
- #end
- def tag_bind(tag, seq, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([@path, 'tag', 'bind', tag], seq, cmd, *args)
- self
- end
-
- #def tag_bind_append(tag, seq, cmd=Proc.new, *args)
- # _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args)
- # self
- #end
- def tag_bind_append(tag, seq, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args)
- self
- end
-
- def tag_bind_remove(tag, seq)
- _bind_remove([@path, 'tag', 'bind', tag], seq)
- self
- end
-
- def tag_bindinfo(tag, context=nil)
- _bindinfo([@path, 'tag', 'bind', tag], context)
- end
-
-=begin
- def tag_cget(tag, key)
- case key.to_s
- when 'text', 'label', 'show', 'data', 'file'
- tk_call_without_enc(@path, 'tag', 'cget',
- _get_eval_enc_str(tag), "-#{key}")
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_send('tag', 'cget', tag, "-#{key}"))
- fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('tag','cget',_get_eval_enc_str(tag),'-font')))
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(tag, fnt)
- end
- if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby(_fromUTF8(tk_call_without_enc(@path,'tag','cget',_get_eval_enc_str(tag),"-#{key}")))
- end
- end
-
- def tag_configure(tag, key, val=None)
- if key.kind_of?(Hash)
- key = _symbolkey2str(key)
- if ( key['font'] || key['kanjifont'] \
- || key['latinfont'] || key['asciifont'] )
- tagfont_configure(tag, key)
- else
- tk_send_without_enc('tag', 'configure', _get_eval_enc_str(tag),
- *hash_kv(key, true))
- end
-
- else
- if key == 'font' || key == :font ||
- key == 'kanjifont' || key == :kanjifont ||
- key == 'latinfont' || key == :latinfont ||
- key == 'asciifont' || key == :asciifont
- if val == None
- tagfontobj(tag)
- else
- tagfont_configure(tag, {key=>val})
- end
- else
- tk_send_without_enc('tag', 'configure', _get_eval_enc_str(tag),
- "-#{key}", _get_eval_enc_str(val))
- end
- end
- self
- end
-
- def tag_configinfo(tag, key=nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- case key.to_s
- when 'text', 'label', 'show', 'data', 'file'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
- when 'font', 'kanjifont'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
- conf[4] = tagfont_configinfo(tag, conf[4])
- else
- conf = tk_split_list(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- ret = tk_split_simplelist(_fromUTF8(tk_send('tag','configure',_get_eval_enc_str(tag)))).collect{|conflist|
- conf = tk_split_simplelist(conflist)
- conf[0] = conf[0][1..-1]
- case conf[0]
- when 'text', 'label', 'show', 'data', 'file'
- else
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- if conf[4]
- if conf[4].index('{')
- conf[4] = tk_split_list(conf[4])
- else
- conf[4] = tk_tcl2ruby(conf[4])
- end
- end
- end
- conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
- conf
- }
- fontconf = ret.assoc('font')
- if fontconf
- ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
- fontconf[4] = tagfont_configinfo(tag, fontconf[4])
- ret.push(fontconf)
- else
- ret
- end
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- case key.to_s
- when 'text', 'label', 'show', 'data', 'file'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
- when 'font', 'kanjifont'
- conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
- conf[4] = tagfont_configinfo(tag, conf[4])
- else
- conf = tk_split_list(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
- end
- key = conf.shift[1..-1]
- { key => conf }
- else
- ret = {}
- tk_split_simplelist(_fromUTF8(tk_send('tag','configure',_get_eval_enc_str(tag)))).each{|conflist|
- conf = tk_split_simplelist(conflist)
- key = conf.shift[1..-1]
- case key
- when 'text', 'label', 'show', 'data', 'file'
- else
- if conf[2]
- if conf[2].index('{')
- conf[2] = tk_split_list(conf[2])
- else
- conf[2] = tk_tcl2ruby(conf[2])
- end
- end
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- end
- if conf.size == 1
- ret[key] = conf[0][1..-1] # alias info
- else
- ret[key] = conf
- end
- }
- fontconf = ret['font']
- if fontconf
- ret.delete('font')
- ret.delete('kanjifont')
- fontconf[3] = tagfont_configinfo(tag, fontconf[3])
- ret['font'] = fontconf
- end
- ret
- end
- end
- end
-
- def current_tag_configinfo(tag, key=nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if key
- conf = tag_configinfo(tag, key)
- {conf[0] => conf[4]}
- else
- ret = {}
- tag_configinfo(tag).each{|conf|
- ret[conf[0]] = conf[4] if conf.size > 2
- }
- ret
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- ret = {}
- tag_configinfo(tag, key).each{|k, conf|
- ret[k] = conf[-1] if conf.kind_of?(Array)
- }
- ret
- end
- end
-=end
-
- def tag_raise(tag, above=None)
- tk_send_without_enc('tag', 'raise', _get_eval_enc_str(tag),
- _get_eval_enc_str(above))
- self
- end
-
- def tag_lower(tag, below=None)
- tk_send_without_enc('tag', 'lower', _get_eval_enc_str(tag),
- _get_eval_enc_str(below))
- self
- end
-
- def tag_remove(tag, *indices)
- tk_send_without_enc('tag', 'remove', _get_eval_enc_str(tag),
- *(indices.collect{|idx| _get_eval_enc_str(idx)}))
- self
- end
-
- def tag_ranges(tag)
- #l = tk_split_simplelist(tk_send_without_enc('tag', 'ranges',
- # _get_eval_enc_str(tag)))
- l = tk_split_simplelist(tk_send_without_enc('tag', 'ranges',
- _get_eval_enc_str(tag)),
- false, true)
- r = []
- while key=l.shift
- r.push [TkText::IndexString.new(key), TkText::IndexString.new(l.shift)]
- end
- r
- end
-
- def tag_nextrange(tag, first, last=None)
- simplelist(tk_send_without_enc('tag', 'nextrange',
- _get_eval_enc_str(tag),
- _get_eval_enc_str(first),
- _get_eval_enc_str(last))).collect{|idx|
- TkText::IndexString.new(idx)
- }
- end
-
- def tag_prevrange(tag, first, last=None)
- simplelist(tk_send_without_enc('tag', 'prevrange',
- _get_eval_enc_str(tag),
- _get_eval_enc_str(first),
- _get_eval_enc_str(last))).collect{|idx|
- TkText::IndexString.new(idx)
- }
- end
-
-=begin
- def window_cget(index, slot)
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- _fromUTF8(tk_send_without_enc('window', 'cget',
- _get_eval_enc_str(index), "-#{slot}"))
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_send('window', 'cget', index, "-#{slot}"))
- fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('window', 'cget', _get_eval_enc_str(index), '-font')))
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(index, fnt)
- end
- if slot.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby(_fromUTF8(tk_send_without_enc('window', 'cget', _get_eval_enc_str(index), "-#{slot}")))
- end
- end
-
- def window_configure(index, slot, value=None)
- if index.kind_of?(TkTextWindow)
- index.configure(slot, value)
- else
- if slot.kind_of?(Hash)
- slot = _symbolkey2str(slot)
- win = slot['window']
- # slot['window'] = win.epath if win.kind_of?(TkWindow)
- slot['window'] = _epath(win) if win
- if slot['create']
- p_create = slot['create']
- if p_create.kind_of?(Proc)
-#=begin
- slot['create'] = install_cmd(proc{
- id = p_create.call
- if id.kind_of?(TkWindow)
- id.epath
- else
- id
- end
- })
-#=end
- slot['create'] = install_cmd(proc{_epath(p_create.call)})
- end
- end
- tk_send_without_enc('window', 'configure',
- _get_eval_enc_str(index),
- *hash_kv(slot, true))
- else
- if slot == 'window' || slot == :window
- # id = value
- # value = id.epath if id.kind_of?(TkWindow)
- value = _epath(value)
- end
- if slot == 'create' || slot == :create
- p_create = value
- if p_create.kind_of?(Proc)
-#=begin
- value = install_cmd(proc{
- id = p_create.call
- if id.kind_of?(TkWindow)
- id.epath
- else
- id
- end
- })
-#=end
- value = install_cmd(proc{_epath(p_create.call)})
- end
- end
- tk_send_without_enc('window', 'configure',
- _get_eval_enc_str(index),
- "-#{slot}", _get_eval_enc_str(value))
- end
- end
- self
- end
-
- def window_configinfo(win, slot = nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- conf = tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
- else
- conf = tk_split_list(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win)))).collect{|conflist|
- conf = tk_split_simplelist(conflist)
- conf[0] = conf[0][1..-1]
- case conf[0]
- when 'text', 'label', 'show', 'data', 'file'
- else
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- if conf[4]
- if conf[4].index('{')
- conf[4] = tk_split_list(conf[4])
- else
- conf[4] = tk_tcl2ruby(conf[4])
- end
- end
- end
- conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
- conf
- }
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- conf = tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
- else
- conf = tk_split_list(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
- end
- key = conf.shift[1..-1]
- { key => conf }
- else
- ret = {}
- tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win)))).each{|conflist|
- conf = tk_split_simplelist(conflist)
- key = conf.shift[1..-1]
- case key
- when 'text', 'label', 'show', 'data', 'file'
- else
- if conf[2]
- if conf[2].index('{')
- conf[2] = tk_split_list(conf[2])
- else
- conf[2] = tk_tcl2ruby(conf[2])
- end
- end
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- end
- if conf.size == 1
- ret[key] = conf[0][1..-1] # alias info
- else
- ret[key] = conf
- end
- }
- ret
- end
- end
- end
-
- def current_window_configinfo(win, slot = nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- conf = window_configinfo(win, slot)
- {conf[0] => conf[4]}
- else
- ret = {}
- window_configinfo(win).each{|conf|
- ret[conf[0]] = conf[4] if conf.size > 2
- }
- ret
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- ret = {}
- window_configinfo(win, slot).each{|k, conf|
- ret[k] = conf[-1] if conf.kind_of?(Array)
- }
- ret
- end
- end
-=end
-
- def window_names
- # tk_split_simplelist(_fromUTF8(tk_send_without_enc('window', 'names'))).collect{|elt|
- tk_split_simplelist(tk_send_without_enc('window', 'names'), false, true).collect{|elt|
- tagid2obj(elt)
- }
- end
-
- def _ktext_length(txt)
- if $KCODE !~ /n/i
- return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length
- end
-
- # $KCODE == 'NONE'
- if JAPANIZED_TK
- tk_call_without_enc('kstring', 'length',
- _get_eval_enc_str(txt)).to_i
- else
- begin
- tk_call_without_enc('encoding', 'convertto', 'ascii',
- _get_eval_enc_str(txt)).length
- rescue StandardError, NameError
- # sorry, I have no plan
- txt.length
- end
- end
- end
- private :_ktext_length
-
- def tksearch(*args)
- # call 'search' subcommand of text widget
- # args ::= [<array_of_opts>] <pattern> <start_index> [<stop_index>]
- # If <pattern> is regexp, then it must be a regular expression of Tcl
- nocase = false
- if args[0].kind_of?(Array)
- opts = args.shift.collect{|opt|
- s_opt = opt.to_s
- nocase = true if s_opt == 'nocase'
- '-' + s_opt
- }
- else
- opts = []
- end
-
- if args[0].kind_of?(Regexp)
- regexp = args.shift
- if !nocase && (regexp.options & Regexp::IGNORECASE) != 0
- opts << '-nocase'
- end
- args.unshift(regexp.source)
- end
-
- opts << '--'
-
- ret = tk_send('search', *(opts + args))
- if ret == ""
- nil
- else
- TkText::IndexString.new(ret)
- end
- end
-
- def tksearch_with_count(*args)
- # call 'search' subcommand of text widget
- # args ::= [<array_of_opts>] <var> <pattern> <start_index> [<stop_index>]
- # If <pattern> is regexp, then it must be a regular expression of Tcl
- nocase = false
- if args[0].kind_of?(Array)
- opts = args.shift.collect{|opt|
- s_opt = opt.to_s
- nocase = true if s_opt == 'nocase'
- '-' + s_opt
- }
- else
- opts = []
- end
-
- opts << '-count' << args.shift
-
- if args[0].kind_of?(Regexp)
- regexp = args.shift
- if !nocase && (regexp.options & Regexp::IGNORECASE) != 0
- opts << '-nocase'
- end
- args.unshift(regexp.source)
- end
-
- opts << '--'
-
- ret = tk_send('search', *(opts + args))
- if ret == ""
- nil
- else
- TkText::IndexString.new(ret)
- end
- end
-
- def search_with_length(pat,start,stop=None)
- pat = pat.chr if pat.kind_of?(Integer)
- if stop != None
- return ["", 0] if compare(start,'>=',stop)
- txt = get(start,stop)
- if (pos = txt.index(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of?(String)
- #return [index(start + " + #{pos} chars"), pat.split('').length]
- return [index(start + " + #{pos} chars"),
- _ktext_length(pat), pat.dup]
- else
- #return [index(start + " + #{pos} chars"), $&.split('').length]
- return [index(start + " + #{pos} chars"),
- _ktext_length(match), match]
- end
- else
- return ["", 0]
- end
- else
- txt = get(start,'end - 1 char')
- if (pos = txt.index(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of?(String)
- #return [index(start + " + #{pos} chars"), pat.split('').length]
- return [index(start + " + #{pos} chars"),
- _ktext_length(pat), pat.dup]
- else
- #return [index(start + " + #{pos} chars"), $&.split('').length]
- return [index(start + " + #{pos} chars"),
- _ktext_length(match), match]
- end
- else
- txt = get('1.0','end - 1 char')
- if (pos = txt.index(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of?(String)
- #return [index("1.0 + #{pos} chars"), pat.split('').length]
- return [index("1.0 + #{pos} chars"),
- _ktext_length(pat), pat.dup]
- else
- #return [index("1.0 + #{pos} chars"), $&.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
- end
- else
- return ["", 0]
- end
- end
- end
- end
-
- def search(pat,start,stop=None)
- search_with_length(pat,start,stop)[0]
- end
-
- def rsearch_with_length(pat,start,stop=None)
- pat = pat.chr if pat.kind_of?(Integer)
- if stop != None
- return ["", 0] if compare(start,'<=',stop)
- txt = get(stop,start)
- if (pos = txt.rindex(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of?(String)
- #return [index(stop + " + #{pos} chars"), pat.split('').length]
- return [index(stop + " + #{pos} chars"), _ktext_length(pat), pat.dup]
- else
- #return [index(stop + " + #{pos} chars"), $&.split('').length]
- return [index(stop + " + #{pos} chars"), _ktext_length(match), match]
- end
- else
- return ["", 0]
- end
- else
- txt = get('1.0',start)
- if (pos = txt.rindex(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of?(String)
- #return [index("1.0 + #{pos} chars"), pat.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
- else
- #return [index("1.0 + #{pos} chars"), $&.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
- end
- else
- txt = get('1.0','end - 1 char')
- if (pos = txt.rindex(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of?(String)
- #return [index("1.0 + #{pos} chars"), pat.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
- else
- #return [index("1.0 + #{pos} chars"), $&.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
- end
- else
- return ["", 0]
- end
- end
- end
- end
-
- def rsearch(pat,start,stop=None)
- rsearch_with_length(pat,start,stop)[0]
- end
-
- def dump(type_info, *index, &block)
- if type_info.kind_of?(Symbol)
- type_info = [ type_info.to_s ]
- elsif type_info.kind_of?(String)
- type_info = [ type_info ]
- end
- args = type_info.collect{|inf| '-' + inf}
- args << '-command' << block if block
- str = tk_send('dump', *(args + index))
- result = []
- sel = nil
- i = 0
- while i < str.size
- # retrieve key
- idx = str.index(/ /, i)
- result.push str[i..(idx-1)]
- i = idx + 1
-
- # retrieve value
- case result[-1]
- when 'text'
- if str[i] == ?{
- # text formed as {...}
- val, i = _retrieve_braced_text(str, i)
- result.push val
- else
- # text which may contain backslahes
- val, i = _retrieve_backslashed_text(str, i)
- result.push val
- end
- else
- idx = str.index(/ /, i)
- val = str[i..(idx-1)]
- case result[-1]
- when 'mark'
- case val
- when 'insert'
- result.push TkTextMarkInsert.new(self)
- when 'current'
- result.push TkTextMarkCurrent.new(self)
- when 'anchor'
- result.push TkTextMarkAnchor.new(self)
- else
- result.push tk_tcl2ruby(val)
- end
- when 'tagon'
- if val == 'sel'
- if sel
- result.push sel
- else
- result.push TkTextTagSel.new(self)
- end
- else
- result.push tk_tcl2ruby(val)
- end
- when 'tagoff'
- result.push tk_tcl2ruby(val)
- when 'window'
- result.push tk_tcl2ruby(val)
- when 'image'
- result.push tk_tcl2ruby(val)
- end
- i = idx + 1
- end
-
- # retrieve index
- idx = str.index(/ /, i)
- if idx
- result.push(TkText::IndexString.new(str[i..(idx-1)]))
- i = idx + 1
- else
- result.push(TkText::IndexString.new(str[i..-1]))
- break
- end
- end
-
- kvis = []
- until result.empty?
- kvis.push [result.shift, result.shift, result.shift]
- end
- kvis # result is [[key1, value1, index1], [key2, value2, index2], ...]
- end
-
- def _retrieve_braced_text(str, i)
- cnt = 0
- idx = i
- while idx < str.size
- case str[idx]
- when ?{
- cnt += 1
- when ?}
- cnt -= 1
- if cnt == 0
- break
- end
- end
- idx += 1
- end
- return str[i+1..idx-1], idx + 2
- end
- private :_retrieve_braced_text
-
- def _retrieve_backslashed_text(str, i)
- j = i
- idx = nil
- loop {
- idx = str.index(/ /, j)
- if str[idx-1] == ?\\
- j += 1
- else
- break
- end
- }
- val = str[i..(idx-1)]
- val.gsub!(/\\( |\{|\})/, '\1')
- return val, idx + 1
- end
- private :_retrieve_backslashed_text
-
- def dump_all(*index, &block)
- dump(['all'], *index, &block)
- end
- def dump_mark(*index, &block)
- dump(['mark'], *index, &block)
- end
- def dump_tag(*index, &block)
- dump(['tag'], *index, &block)
- end
- def dump_text(*index, &block)
- dump(['text'], *index, &block)
- end
- def dump_window(*index, &block)
- dump(['window'], *index, &block)
- end
- def dump_image(*index, &block)
- dump(['image'], *index, &block)
- end
-end
-
-#######################################
-
-class TkText::Peer < TkText
- # Tk8.5 feature
- def initialize(text, parent=nil, keys={})
- unless text.kind_of?(TkText)
- fail ArgumentError, "TkText is expected for 1st argument"
- end
- @src_text = text
- super(parent, keys)
- end
-
- def create_self(keys)
- if keys and keys != None
- tk_call_without_enc(@src_text.path, 'peer', 'create', @path)
- else
- tk_call_without_enc(@src_text.path, 'peer', 'create', @path)
- end
- end
- private :create_self
-end
diff --git a/ext/tk/lib/tk/textimage.rb b/ext/tk/lib/tk/textimage.rb
deleted file mode 100644
index a29b23c7dd..0000000000
--- a/ext/tk/lib/tk/textimage.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-#
-# tk/textimage.rb - treat Tk text image object
-#
-require 'tk'
-require 'tk/text'
-
-class TkTextImage<TkObject
- include TkText::IndexModMethods
-
- def initialize(parent, index, keys)
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
- #end
- @t = parent
- if index == 'end' || index == :end
- @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
- elsif index.kind_of? TkTextMark
- if tk_call_without_enc(@t.path,'index',index.path) == tk_call_without_enc(@t.path,'index','end')
- @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
- 'end - 1 chars'))
- else
- @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
- index.path))
- end
- else
- @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
- _get_eval_enc_str(index)))
- end
- @path.gravity = 'left'
- @index = @path.path
- @id = tk_call_without_enc(@t.path, 'image', 'create', @index,
- *hash_kv(keys, true)).freeze
- @path.gravity = 'right'
- end
-
- def id
- TkText::IndexString.new(@id)
- end
- def mark
- @path
- end
-
- def [](slot)
- cget(slot)
- end
- def []=(slot, value)
- configure(slot, value)
- value
- end
-
- def cget(slot)
- @t.image_cget(@index, slot)
- end
-
- def configure(slot, value=None)
- @t.image_configure(@index, slot, value)
- self
- end
-# def configure(slot, value)
-# tk_call @t.path, 'image', 'configure', @index, "-#{slot}", value
-# end
-
- def configinfo(slot = nil)
- @t.image_configinfo(@index, slot)
- end
-
- def current_configinfo(slot = nil)
- @t.current_image_configinfo(@index, slot)
- end
-
- def image
- img = tk_call_without_enc(@t.path, 'image', 'cget', @index, '-image')
- TkImage::Tk_IMGTBL[img]? TkImage::Tk_IMGTBL[img] : img
- end
-
- def image=(value)
- tk_call_without_enc(@t.path, 'image', 'configure', @index, '-image',
- _get_eval_enc_str(value))
- #self
- value
- end
-end
diff --git a/ext/tk/lib/tk/textmark.rb b/ext/tk/lib/tk/textmark.rb
deleted file mode 100644
index 650d95af70..0000000000
--- a/ext/tk/lib/tk/textmark.rb
+++ /dev/null
@@ -1,166 +0,0 @@
-#
-# tk/textmark.rb - methods for treating text marks
-#
-require 'tk'
-require 'tk/text'
-
-class TkTextMark<TkObject
- include TkText::IndexModMethods
-
- TMarkID_TBL = TkCore::INTERP.create_table
- Tk_TextMark_ID = ['mark'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ TMarkID_TBL.clear }
-
- def TkTextMark.id2obj(text, id)
- tpath = text.path
- return id unless TMarkID_TBL[tpath]
- TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id
- end
-
- def initialize(parent, index)
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
- #end
- @parent = @t = parent
- @tpath = parent.path
- # @path = @id = Tk_TextMark_ID.join('')
- @path = @id = Tk_TextMark_ID.join(TkCore::INTERP._ip_id_).freeze
- TMarkID_TBL[@id] = self
- TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
- TMarkID_TBL[@tpath][@id] = self
- Tk_TextMark_ID[1].succ!
- tk_call_without_enc(@t.path, 'mark', 'set', @id,
- _get_eval_enc_str(index))
- @t._addtag id, self
- end
-
- def id
- TkText::IndexString.new(@id)
- end
-
- def exist?
- #if ( tk_split_simplelist(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'names'))).find{|id| id == @id } )
- if ( tk_split_simplelist(tk_call_without_enc(@t.path, 'mark', 'names'), false, true).find{|id| id == @id } )
- true
- else
- false
- end
- end
-
-=begin
- # move to TkText::IndexModMethods module
- def +(mod)
- return chars(mod) if mod.kind_of?(Numeric)
-
- mod = mod.to_s
- if mod =~ /^\s*[+-]?\d/
- TkText::IndexString.new(@id + ' + ' + mod)
- else
- TkText::IndexString.new(@id + ' ' + mod)
- end
- end
-
- def -(mod)
- return chars(-mod) if mod.kind_of?(Numeric)
-
- mod = mod.to_s
- if mod =~ /^\s*[+-]?\d/
- TkText::IndexString.new(@id + ' - ' + mod)
- elsif mod =~ /^\s*[-]\s+(\d.*)$/
- TkText::IndexString.new(@id + ' - -' + $1)
- else
- TkText::IndexString.new(@id + ' ' + mod)
- end
- end
-=end
-
- def pos
- @t.index(@id)
- end
-
- def pos=(where)
- set(where)
- end
-
- def set(where)
- tk_call_without_enc(@t.path, 'mark', 'set', @id,
- _get_eval_enc_str(where))
- self
- end
-
- def unset
- tk_call_without_enc(@t.path, 'mark', 'unset', @id)
- self
- end
- alias destroy unset
-
- def gravity
- tk_call_without_enc(@t.path, 'mark', 'gravity', @id)
- end
-
- def gravity=(direction)
- tk_call_without_enc(@t.path, 'mark', 'gravity', @id, direction)
- #self
- direction
- end
-
- def next(index = nil)
- if index
- @t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'next', _get_eval_enc_str(index))))
- else
- @t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'next', @id)))
- end
- end
-
- def previous(index = nil)
- if index
- @t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'previous', _get_eval_enc_str(index))))
- else
- @t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'previous', @id)))
- end
- end
-end
-
-class TkTextNamedMark<TkTextMark
- def self.new(parent, name, *args)
- if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name]
- return TMarkID_TBL[parent.path][name]
- else
- super(parent, name, *args)
- end
- end
-
- def initialize(parent, name, index=nil)
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
- #end
- @parent = @t = parent
- @tpath = parent.path
- @path = @id = name
- TMarkID_TBL[@id] = self
- TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
- TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id]
- tk_call_without_enc(@t.path, 'mark', 'set', @id,
- _get_eval_enc_str(index)) if index
- @t._addtag id, self
- end
-end
-
-class TkTextMarkInsert<TkTextNamedMark
- def self.new(parent,*args)
- super(parent, 'insert', *args)
- end
-end
-
-class TkTextMarkCurrent<TkTextNamedMark
- def self.new(parent,*args)
- super(parent, 'current', *args)
- end
-end
-
-class TkTextMarkAnchor<TkTextNamedMark
- def self.new(parent,*args)
- super(parent, 'anchor', *args)
- end
-end
diff --git a/ext/tk/lib/tk/texttag.rb b/ext/tk/lib/tk/texttag.rb
deleted file mode 100644
index cc2c56210f..0000000000
--- a/ext/tk/lib/tk/texttag.rb
+++ /dev/null
@@ -1,279 +0,0 @@
-#
-# tk/texttag.rb - methods for treating text tags
-#
-require 'tk'
-require 'tk/text'
-require 'tk/tagfont'
-
-class TkTextTag<TkObject
- include TkTreatTagFont
- include TkText::IndexModMethods
-
- TTagID_TBL = TkCore::INTERP.create_table
- Tk_TextTag_ID = ['tag'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ TTagID_TBL.clear }
-
- def TkTextTag.id2obj(text, id)
- tpath = text.path
- return id unless TTagID_TBL[tpath]
- TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id
- end
-
- def initialize(parent, *args)
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
- #end
- @parent = @t = parent
- @tpath = parent.path
- # @path = @id = Tk_TextTag_ID.join('')
- @path = @id = Tk_TextTag_ID.join(TkCore::INTERP._ip_id_).freeze
- # TTagID_TBL[@id] = self
- TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
- TTagID_TBL[@tpath][@id] = self
- Tk_TextTag_ID[1].succ!
- #tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
- if args != []
- keys = args.pop
- if keys.kind_of?(Hash)
- add(*args) if args != []
- configure(keys)
- else
- args.push keys
- add(*args)
- end
- end
- @t._addtag id, self
- end
-
- def id
- TkText::IndexString.new(@id)
- end
-
- def exist?
- #if ( tk_split_simplelist(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'names'))).find{|id| id == @id } )
- if ( tk_split_simplelist(tk_call_without_enc(@t.path, 'tag', 'names'), false, true).find{|id| id == @id } )
- true
- else
- false
- end
- end
-
- def first
- TkText::IndexString.new(@id + '.first')
- end
-
- def last
- TkText::IndexString.new(@id + '.last')
- end
-
- def add(*indices)
- tk_call_without_enc(@t.path, 'tag', 'add', @id,
- *(indices.collect{|idx| _get_eval_enc_str(idx)}))
- self
- end
-
- def remove(*indices)
- tk_call_without_enc(@t.path, 'tag', 'remove', @id,
- *(indices.collect{|idx| _get_eval_enc_str(idx)}))
- self
- end
-
- def ranges
- l = tk_split_simplelist(tk_call_without_enc(@t.path, 'tag', 'ranges', @id))
- r = []
- while key=l.shift
- r.push [TkText::IndexString.new(key), TkText::IndexString.new(l.shift)]
- end
- r
- end
-
- def nextrange(first, last=None)
- simplelist(tk_call_without_enc(@t.path, 'tag', 'nextrange', @id,
- _get_eval_enc_str(first),
- _get_eval_enc_str(last))).collect{|idx|
- TkText::IndexString.new(idx)
- }
- end
-
- def prevrange(first, last=None)
- simplelist(tk_call_without_enc(@t.path, 'tag', 'prevrange', @id,
- _get_eval_enc_str(first),
- _get_eval_enc_str(last))).collect{|idx|
- TkText::IndexString.new(idx)
- }
- end
-
- def [](key)
- cget key
- end
-
- def []=(key,val)
- configure key, val
- val
- end
-
- def cget(key)
- @t.tag_cget @id, key
- end
-=begin
- def cget(key)
- case key.to_s
- when 'text', 'label', 'show', 'data', 'file'
- _fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget', @id, "-#{key}"))
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_call(@t.path, 'tag', 'cget', @id, "-#{key}"))
- fnt = tk_tcl2ruby(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget',
- @id, '-font')))
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(@id, fnt)
- end
- if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget',
- @id, "-#{key}")))
- end
- end
-=end
-
- def configure(key, val=None)
- @t.tag_configure @id, key, val
- end
-# def configure(key, val=None)
-# if key.kind_of?(Hash)
-# tk_call @t.path, 'tag', 'configure', @id, *hash_kv(key)
-# else
-# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", val
-# end
-# end
-# def configure(key, value)
-# if value == FALSE
-# value = "0"
-# elsif value.kind_of?(Proc)
-# value = install_cmd(value)
-# end
-# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", value
-# end
-
- def configinfo(key=nil)
- @t.tag_configinfo @id, key
- end
-
- def current_configinfo(key=nil)
- @t.current_tag_configinfo @id, key
- end
-
- #def bind(seq, cmd=Proc.new, *args)
- # _bind([@t.path, 'tag', 'bind', @id], seq, cmd, *args)
- # self
- #end
- def bind(seq, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([@t.path, 'tag', 'bind', @id], seq, cmd, *args)
- self
- end
-
- #def bind_append(seq, cmd=Proc.new, *args)
- # _bind_append([@t.path, 'tag', 'bind', @id], seq, cmd, *args)
- # self
- #end
- def bind_append(seq, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([@t.path, 'tag', 'bind', @id], seq, cmd, *args)
- self
- end
-
- def bind_remove(seq)
- _bind_remove([@t.path, 'tag', 'bind', @id], seq)
- self
- end
-
- def bindinfo(context=nil)
- _bindinfo([@t.path, 'tag', 'bind', @id], context)
- end
-
- def raise(above=None)
- tk_call_without_enc(@t.path, 'tag', 'raise', @id,
- _get_eval_enc_str(above))
- self
- end
-
- def lower(below=None)
- tk_call_without_enc(@t.path, 'tag', 'lower', @id,
- _get_eval_enc_str(below))
- self
- end
-
- def destroy
- tk_call_without_enc(@t.path, 'tag', 'delete', @id)
- TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath]
- self
- end
-end
-
-class TkTextNamedTag<TkTextTag
- def self.new(parent, name, *args)
- if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name]
- tagobj = TTagID_TBL[parent.path][name]
- if args != []
- keys = args.pop
- if keys.kind_of?(Hash)
- tagobj.add(*args) if args != []
- tagobj.configure(keys)
- else
- args.push keys
- tagobj.add(*args)
- end
- end
- return tagobj
- else
- super(parent, name, *args)
- end
- end
-
- def initialize(parent, name, *args)
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
- #end
- @parent = @t = parent
- @tpath = parent.path
- @path = @id = name
- TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
- TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id]
- #if mode
- # tk_call @t.path, "addtag", @id, *args
- #end
- if args != []
- keys = args.pop
- if keys.kind_of?(Hash)
- add(*args) if args != []
- configure(keys)
- else
- args.push keys
- add(*args)
- end
- end
- @t._addtag id, self
- end
-end
-
-class TkTextTagSel<TkTextNamedTag
- def self.new(parent, *args)
- super(parent, 'sel', *args)
- end
-end
diff --git a/ext/tk/lib/tk/textwindow.rb b/ext/tk/lib/tk/textwindow.rb
deleted file mode 100644
index 605c40addd..0000000000
--- a/ext/tk/lib/tk/textwindow.rb
+++ /dev/null
@@ -1,149 +0,0 @@
-#
-# tk/textwindow.rb - treat Tk text window object
-#
-require 'tk'
-require 'tk/text'
-
-class TkTextWindow<TkObject
- include TkText::IndexModMethods
-
- def initialize(parent, index, keys = {})
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
- #end
- @t = parent
- if index == 'end' || index == :end
- @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
- 'end - 1 chars'))
- elsif index.kind_of?(TkTextMark)
- if tk_call_without_enc(@t.path,'index',index.path) == tk_call_without_enc(@t.path,'index','end')
- @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
- 'end - 1 chars'))
- else
- @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
- index.path))
- end
- else
- @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index', _get_eval_enc_str(index)))
- end
- @path.gravity = 'left'
- @index = @path.path
- keys = _symbolkey2str(keys)
- @id = keys['window']
- # keys['window'] = @id.epath if @id.kind_of?(TkWindow)
- keys['window'] = _epath(@id) if @id
- if keys['create']
- @p_create = keys['create']
- # if @p_create.kind_of?(Proc)
- if TkComm._callback_entry?(@p_create)
-=begin
- keys['create'] = install_cmd(proc{
- @id = @p_create.call
- if @id.kind_of?(TkWindow)
- @id.epath
- else
- @id
- end
- })
-=end
- keys['create'] = install_cmd(proc{@id = @p_create.call; _epath(@id)})
- end
- end
- tk_call_without_enc(@t.path, 'window', 'create', @index,
- *hash_kv(keys, true))
- @path.gravity = 'right'
- end
-
- def id
- TkText::IndexString.new(_epath(@id))
- end
- def mark
- @path
- end
-
- def [](slot)
- cget(slot)
- end
- def []=(slot, value)
- configure(slot, value)
- value
- end
-
- def cget(slot)
- @t.window_cget(@index, slot)
- end
-
- def configure(slot, value=None)
- if slot.kind_of?(Hash)
- slot = _symbolkey2str(slot)
- if slot['window']
- @id = slot['window']
- # slot['window'] = @id.epath if @id.kind_of?(TkWindow)
- slot['window'] = _epath(@id) if @id
- end
- if slot['create']
- self.create=slot.delete('create')
- end
- if slot.size > 0
- tk_call_without_enc(@t.path, 'window', 'configure', @index,
- *hash_kv(slot, true))
- end
- else
- if slot == 'window' || slot == :window
- @id = value
- # value = @id.epath if @id.kind_of?(TkWindow)
- value = _epath(@id) if @id
- end
- if slot == 'create' || slot == :create
- self.create=value
- else
- tk_call_without_enc(@t.path, 'window', 'configure', @index,
- "-#{slot}", _get_eval_enc_str(value))
- end
- end
- self
- end
-
- def configinfo(slot = nil)
- @t.window_configinfo(@index, slot)
- end
-
- def current_configinfo(slot = nil)
- @t.current_window_configinfo(@index, slot)
- end
-
- def window
- @id
- end
-
- def window=(value)
- @id = value
- # value = @id.epath if @id.kind_of?(TkWindow)
- value = _epath(@id) if @id
- tk_call_without_enc(@t.path, 'window', 'configure', @index,
- '-window', _get_eval_enc_str(value))
- value
- end
-
- def create
- @p_create
- end
-
- def create=(value)
- @p_create = value
- # if @p_create.kind_of?(Proc)
- if TkComm._callback_entry?(@p_create)
- value = install_cmd(proc{
- @id = @p_create.call
- if @id.kind_of?(TkWindow)
- @id.epath
- else
- @id
- end
- })
- end
- tk_call_without_enc(@t.path, 'window', 'configure', @index,
- '-create', _get_eval_enc_str(value))
- value
- end
-end
diff --git a/ext/tk/lib/tk/timer.rb b/ext/tk/lib/tk/timer.rb
deleted file mode 100644
index 47f2b79350..0000000000
--- a/ext/tk/lib/tk/timer.rb
+++ /dev/null
@@ -1,634 +0,0 @@
-#
-# tk/timer.rb : methods for Tcl/Tk after command
-#
-# $Id$
-#
-require 'tk'
-
-class TkTimer
- include TkCore
- extend TkCore
-
- TkCommandNames = ['after'.freeze].freeze
-
- Tk_CBID = ['a'.freeze, '00000'.taint].freeze
- Tk_CBTBL = {}.taint
-
- TkCore::INTERP.add_tk_procs('rb_after', 'id', <<-'EOL')
- if {[set st [catch {eval {ruby_cmd TkTimer callback} $id} ret]] != 0} {
- return -code $st $ret
- } {
- return $ret
- }
- EOL
-
- DEFAULT_IGNORE_EXCEPTIONS = [ NameError, RuntimeError ].freeze
-
- ###############################
- # class methods
- ###############################
- def self.start(*args, &b)
- self.new(*args, &b).start
- end
-
- def self.callback(obj_id)
- ex_obj = Tk_CBTBL[obj_id]
- return "" if ex_obj == nil; # canceled
- ex_obj.cb_call
- end
-
- def self.info(obj = nil)
- if obj
- if obj.kind_of?(TkTimer)
- if obj.after_id
- inf = tk_split_list(tk_call_without_enc('after','info',obj.after_id))
- [Tk_CBTBL[inf[0][1]], inf[1]]
- else
- nil
- end
- else
- fail ArgumentError, "TkTimer object is expected"
- end
- else
- tk_call_without_enc('after', 'info').split(' ').collect!{|id|
- ret = Tk_CBTBL.find{|key,val| val.after_id == id}
- (ret == nil)? id: ret[1]
- }
- end
- end
-
-
- ###############################
- # instance methods
- ###############################
- def do_callback
- @in_callback = true
- @after_id = nil
- begin
- @return_value = @current_proc.call(self)
- rescue SystemExit
- exit(0)
- rescue Interrupt
- exit!(1)
- rescue Exception => e
- if @cancel_on_exception &&
- @cancel_on_exception.find{|exc| e.kind_of?(exc)}
- cancel
- @return_value = e
- @in_callback = false
- return e
- else
- fail e
- end
- end
- if @set_next
- set_next_callback(@current_args)
- else
- @set_next = true
- end
- @in_callback = false
- @return_value
- end
-
- def set_callback(sleep, args=nil)
- if TkCore::INTERP.deleted?
- self.cancel
- return self
- end
- @after_script = "rb_after #{@id}"
- @after_id = tk_call_without_enc('after', sleep, @after_script)
- @current_args = args
- @current_script = [sleep, @after_script]
- self
- end
-
- def set_next_callback(args)
- if @running == false || @proc_max == 0 || @do_loop == 0
- Tk_CBTBL.delete(@id) ;# for GC
- @running = false
- @wait_var.value = 0
- return
- end
- if @current_pos >= @proc_max
- if @do_loop < 0 || (@do_loop -= 1) > 0
- @current_pos = 0
- else
- Tk_CBTBL.delete(@id) ;# for GC
- @running = false
- @wait_var.value = 0
- return
- end
- end
-
- @current_args = args
-
- # if @sleep_time.kind_of?(Proc)
- if TkComm._callback_entry?(@sleep_time)
- sleep = @sleep_time.call(self)
- else
- sleep = @sleep_time
- end
- @current_sleep = sleep
-
- cmd, *cmd_args = @loop_proc[@current_pos]
- @current_pos += 1
- @current_proc = cmd
-
- set_callback(sleep, cmd_args)
- end
-
- def initialize(*args, &b)
- # @id = Tk_CBID.join('')
- @id = Tk_CBID.join(TkCore::INTERP._ip_id_)
- Tk_CBID[1].succ!
-
- @wait_var = TkVariable.new(0)
-
- @cb_cmd = TkCore::INTERP.get_cb_entry(self.method(:do_callback))
-
- @set_next = true
-
- @init_sleep = 0
- @init_proc = nil
- @init_args = []
-
- @current_script = []
- @current_proc = nil
- @current_args = nil
- @return_value = nil
-
- @sleep_time = 0
- @current_sleep = 0
- @loop_exec = 0
- @do_loop = 0
- @loop_proc = []
- @proc_max = 0
- @current_pos = 0
-
- @after_id = nil
- @after_script = nil
-
- @cancel_on_exception = DEFAULT_IGNORE_EXCEPTIONS
- # Unless @cancel_on_exception, Ruby/Tk shows an error dialog box when
- # an excepsion is raised on TkTimer callback procedure.
- # If @cancel_on_exception is an array of exception classes and the raised
- # exception is included in the array, Ruby/Tk cancels executing TkTimer
- # callback procedures silently (TkTimer#cancel is called and no dialog is
- # shown).
-
- if b
- case args.size
- when 0
- add_procs(b)
- when 1
- args << -1 << b
- else
- args << b
- end
- end
-
- set_procs(*args) if args != []
-
- @running = false
- @in_callback = false
- end
-
- attr :after_id
- attr :after_script
- attr :current_proc
- attr :current_args
- attr :current_sleep
- alias :current_interval :current_sleep
- attr :return_value
-
- attr_accessor :loop_exec
-
- def cb_call
- @cb_cmd.call
- end
-
- def get_procs
- [@init_sleep, @init_proc, @init_args, @sleep_time, @loop_exec, @loop_proc]
- end
-
- def current_status
- [@running, @current_sleep, @current_proc, @current_args,
- @do_loop, @cancel_on_exception]
- end
-
- def cancel_on_exception?
- @cancel_on_exception
- end
-
- def cancel_on_exception=(mode)
- if mode.kind_of?(Array)
- @cancel_on_exception = mode
- elsif mode
- @cancel_on_exception = DEFAULT_IGNORE_EXCEPTIONS
- else
- @cancel_on_exception = false
- end
- #self
- end
-
- def running?
- @running
- end
-
- def loop_rest
- @do_loop
- end
-
- def loop_rest=(rest)
- @do_loop = rest
- #self
- end
-
- def set_interval(interval)
- #if interval != 'idle' && interval != :idle \
- # && !interval.kind_of?(Integer) && !interval.kind_of?(Proc)
- if interval != 'idle' && interval != :idle \
- && !interval.kind_of?(Integer) && !TkComm._callback_entry?(interval)
- fail ArgumentError, "expect Integer or Proc"
- end
- @sleep_time = interval
- end
-
- def set_procs(interval, loop_exec, *procs)
- #if interval != 'idle' && interval != :idle \
- # && !interval.kind_of?(Integer) && !interval.kind_of?(Proc)
- if interval != 'idle' && interval != :idle \
- && !interval.kind_of?(Integer) && !TkComm._callback_entry?(interval)
- fail ArgumentError, "expect Integer or Proc for 1st argument"
- end
- @sleep_time = interval
-
- @loop_proc = []
- procs.each{|e|
- # if e.kind_of?(Proc)
- if TkComm._callback_entry?(e)
- @loop_proc.push([e])
- else
- @loop_proc.push(e)
- end
- }
- @proc_max = @loop_proc.size
- @current_pos = 0
-
- if loop_exec.kind_of?(Integer) && loop_exec < 0
- @loop_exec = -1
- elsif loop_exec == true
- @loop_exec = -1
- elsif loop_exec == nil || loop_exec == false || loop_exec == 0
- @loop_exec = 0
- else
- if not loop_exec.kind_of?(Integer)
- fail ArgumentError, "expect Integer for 2nd argument"
- end
- @loop_exec = loop_exec
- end
- @do_loop = @loop_exec
-
- self
- end
-
- def add_procs(*procs)
- procs.each{|e|
- # if e.kind_of?(Proc)
- if TkComm._callback_entry?(e)
- @loop_proc.push([e])
- else
- @loop_proc.push(e)
- end
- }
- @proc_max = @loop_proc.size
-
- self
- end
-
- def delete_procs(*procs)
- procs.each{|e|
- # if e.kind_of?(Proc)
- if TkComm._callback_entry?(e)
- @loop_proc.delete([e])
- else
- @loop_proc.delete(e)
- end
- }
- @proc_max = @loop_proc.size
-
- cancel if @proc_max == 0
-
- self
- end
-
- def delete_at(n)
- @loop_proc.delete_at(n)
- @proc_max = @loop_proc.size
- cancel if @proc_max == 0
- self
- end
-
- def set_start_proc(sleep=nil, init_proc=nil, *init_args, &b)
- # set parameters for 'restart'
- sleep = @init_sleep unless sleep
-
- if sleep != 'idle' && sleep != :idle && !sleep.kind_of?(Integer)
- fail ArgumentError, "expect Integer or 'idle' for 1st argument"
- end
-
- @init_sleep = sleep
- @init_proc = init_proc
- @init_args = init_args
-
- @init_proc = b if !@init_proc && b
- @init_proc = proc{|*args| } if @init_sleep > 0 && !@init_proc
-
- self
- end
-
- def start(*init_args, &b)
- return nil if @running
-
- Tk_CBTBL[@id] = self
- @do_loop = @loop_exec
- @current_pos = 0
- @return_value = nil
- @after_id = nil
-
- @init_sleep = 0
- @init_proc = nil
- @init_args = nil
-
- argc = init_args.size
- if argc > 0
- sleep = init_args.shift
- if sleep != 'idle' && sleep != :idle && !sleep.kind_of?(Integer)
- fail ArgumentError, "expect Integer or 'idle' for 1st argument"
- end
- @init_sleep = sleep
- end
- @init_proc = init_args.shift if argc > 1
- @init_args = init_args if argc > 2
-
- @init_proc = b if !@init_proc && b
- @init_proc = proc{|*args| } if @init_sleep > 0 && !@init_proc
-
- @current_sleep = @init_sleep
- @running = true
- if @init_proc
- # if not @init_proc.kind_of?(Proc)
- if !TkComm._callback_entry?(@init_proc)
- fail ArgumentError, "Argument '#{@init_proc}' need to be Proc"
- end
- @current_proc = @init_proc
- set_callback(@init_sleep, @init_args)
- @set_next = false if @in_callback
- else
- set_next_callback(@init_args)
- end
-
- self
- end
-
- def reset(*reset_args)
- restart() if @running
-
- if @init_proc
- @return_value = @init_proc.call(self)
- else
- @return_value = nil
- end
-
- @current_pos = 0
- @current_args = @init_args
- @current_script = []
-
- @set_next = false if @in_callback
-
- self
- end
-
- def restart(*restart_args, &b)
- cancel if @running
- if restart_args == [] && !b
- start(@init_sleep, @init_proc, *@init_args)
- else
- start(*restart_args, &b)
- end
- end
-
- def cancel
- @running = false
- @wait_var.value = 0
- tk_call 'after', 'cancel', @after_id if @after_id
- @after_id = nil
-
- Tk_CBTBL.delete(@id) ;# for GC
- self
- end
- alias stop cancel
-
- def continue(wait=nil)
- fail RuntimeError, "is already running" if @running
- return restart() if @current_script.empty?
- sleep, cmd = @current_script
- fail RuntimeError, "no procedure to continue" unless cmd
- if wait
- unless wait.kind_of?(Integer)
- fail ArgumentError, "expect Integer for 1st argument"
- end
- sleep = wait
- end
- Tk_CBTBL[@id] = self
- @running = true
- @after_id = tk_call_without_enc('after', sleep, cmd)
- self
- end
-
- def skip
- fail RuntimeError, "is not running now" unless @running
- cancel
- Tk_CBTBL[@id] = self
- @running = true
- set_next_callback(@current_args)
- self
- end
-
- def info
- if @after_id
- inf = tk_split_list(tk_call_without_enc('after', 'info', @after_id))
- [Tk_CBTBL[inf[0][1]], inf[1]]
- else
- nil
- end
- end
-
- def wait(on_thread = true, check_root = false)
- if $SAFE >= 4
- fail SecurityError, "can't wait timer at $SAFE >= 4"
- end
-
- unless @running
- if @return_value.kind_of?(Exception)
- fail @return_value
- else
- return @return_value
- end
- end
-
- @wait_var.wait(on_thread, check_root)
- if @return_value.kind_of?(Exception)
- fail @return_value
- else
- @return_value
- end
- end
- def eventloop_wait(check_root = false)
- wait(false, check_root)
- end
- def thread_wait(check_root = false)
- wait(true, check_root)
- end
- def tkwait(on_thread = true)
- wait(on_thread, true)
- end
- def eventloop_tkwait
- wait(false, true)
- end
- def thread_tkwait
- wait(true, true)
- end
-end
-
-TkAfter = TkTimer
-
-
-class TkRTTimer < TkTimer
- DEFAULT_OFFSET_LIST_SIZE = 5
-
- def initialize(*args, &b)
- super(*args, &b)
-
- @offset_list = Array.new(DEFAULT_OFFSET_LIST_SIZE){ [0, 0] }
- @offset_s = 0
- @offset_u = 0
- @est_time = nil
- end
-
- def start(*args, &b)
- return nil if @running
- @est_time = nil
- @cb_start_time = Time.now
- super(*args, &b)
- end
-
- def cancel
- super()
- @est_time = nil
- @cb_start_time = Time.now
- self
- end
- alias stop cancel
-
- def continue(wait=nil)
- fail RuntimeError, "is already running" if @running
- @cb_start_time = Time.now
- super(wait)
- end
-
- def set_interval(interval)
- super(interval)
- @est_time = nil
- end
-
- def _offset_ave
- size = 0
- d_sec = 0; d_usec = 0
- @offset_list.each_with_index{|offset, idx|
- # weight = 1
- weight = idx + 1
- size += weight
- d_sec += offset[0] * weight
- d_usec += offset[1] * weight
- }
- offset_s, mod = d_sec.divmod(size)
- offset_u = ((mod * 1000000 + d_usec) / size.to_f).round
- [offset_s, offset_u]
- end
- private :_offset_ave
-
- def set_next_callback(args)
- if @running == false || @proc_max == 0 || @do_loop == 0
- Tk_CBTBL.delete(@id) ;# for GC
- @running = false
- @wait_var.value = 0
- return
- end
- if @current_pos >= @proc_max
- if @do_loop < 0 || (@do_loop -= 1) > 0
- @current_pos = 0
- else
- Tk_CBTBL.delete(@id) ;# for GC
- @running = false
- @wait_var.value = 0
- return
- end
- end
-
- @current_args = args
-
- cmd, *cmd_args = @loop_proc[@current_pos]
- @current_pos += 1
- @current_proc = cmd
-
- @offset_s, @offset_u = _offset_ave
-
- if TkComm._callback_entry?(@sleep_time)
- sleep = @sleep_time.call(self)
- else
- sleep = @sleep_time
- end
-
- if @est_time
- @est_time = Time.at(@est_time.to_i, @est_time.usec + sleep*1000)
- else
- @est_time = Time.at(@cb_start_time.to_i,
- @cb_start_time.usec + sleep*1000)
- end
-
- now = Time.now
- real_sleep = ((@est_time.to_i - now.to_i + @offset_s)*1000.0 +
- (@est_time.usec - now.usec + @offset_u)/1000.0).round
- if real_sleep <= 0
- real_sleep = 0
- @offset_s = now.to_i
- @offset_u = now.usec
- end
- @current_sleep = real_sleep
-
- set_callback(real_sleep, cmd_args)
- end
-
- def cb_call
- if @est_time
- @offset_list.shift
-
- @cb_start_time = Time.now
-
- if @current_sleep == 0
- @offset_list.push([
- @offset_s - @cb_start_time.to_i,
- @offset_u - @cb_start_time.usec
- ])
- else
- @offset_list.push([
- @offset_s + (@est_time.to_i - @cb_start_time.to_i),
- @offset_u + (@est_time.usec - @cb_start_time.usec)
- ])
- end
- end
-
- @cb_cmd.call
- end
-end
diff --git a/ext/tk/lib/tk/toplevel.rb b/ext/tk/lib/tk/toplevel.rb
deleted file mode 100644
index 5e199e1330..0000000000
--- a/ext/tk/lib/tk/toplevel.rb
+++ /dev/null
@@ -1,257 +0,0 @@
-#
-# tk/toplevel.rb : treat toplevel widget
-#
-require 'tk'
-require 'tk/wm'
-require 'tk/menuspec'
-
-class TkToplevel<TkWindow
- include Wm
- include TkMenuSpec
-
- TkCommandNames = ['toplevel'.freeze].freeze
- WidgetClassName = 'Toplevel'.freeze
- WidgetClassNames[WidgetClassName] = self
-
-################# old version
-# def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
-# if screen.kind_of? Hash
-# keys = screen.dup
-# else
-# @screen = screen
-# end
-# @classname = classname
-# if keys.kind_of? Hash
-# keys = keys.dup
-# @classname = keys.delete('classname') if keys.key?('classname')
-# @colormap = keys.delete('colormap') if keys.key?('colormap')
-# @container = keys.delete('container') if keys.key?('container')
-# @screen = keys.delete('screen') if keys.key?('screen')
-# @use = keys.delete('use') if keys.key?('use')
-# @visual = keys.delete('visual') if keys.key?('visual')
-# end
-# super(parent, keys)
-# end
-#
-# def create_self
-# s = []
-# s << "-class" << @classname if @classname
-# s << "-colormap" << @colormap if @colormap
-# s << "-container" << @container if @container
-# s << "-screen" << @screen if @screen
-# s << "-use" << @use if @use
-# s << "-visual" << @visual if @visual
-# tk_call 'toplevel', @path, *s
-# end
-#################
-
- def __boolval_optkeys
- super() << 'container'
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- super() << 'screen'
- end
- private :__strval_optkeys
-
- def __val2ruby_optkeys # { key=>proc, ... }
- super().update('menu'=>proc{|v| window(v)})
- end
- private :__val2ruby_optkeys
-
- def __methodcall_optkeys # { key=>method, ... }
- TOPLEVEL_METHODCALL_OPTKEYS
- end
- private :__methodcall_optkeys
-
- def _wm_command_option_chk(keys)
- keys = {} unless keys
- new_keys = {}
- wm_cmds = {}
-
- conf_methods = _symbolkey2str(__methodcall_optkeys())
-
- keys.each{|k,v|
- if conf_methods.key?(k)
- wm_cmds[conf_methods[k]] = v
- elsif Wm.method_defined?(k)
- case k
- when 'screen','class','colormap','container','use','visual'
- new_keys[k] = v
- else
- case self.method(k).arity
- when -1,1
- wm_cmds[k] = v
- else
- new_keys[k] = v
- end
- end
- else
- new_keys[k] = v
- end
- }
- [new_keys, wm_cmds]
- end
- private :_wm_command_option_chk
-
- def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
- my_class_name = nil
- if self.class < WidgetClassNames[WidgetClassName]
- my_class_name = self.class.name
- my_class_name = nil if my_class_name == ''
- end
- if parent.kind_of? Hash
- keys = _symbolkey2str(parent)
- if keys.key?('classname')
- keys['class'] = keys.delete('classname')
- end
- @classname = keys['class']
- @colormap = keys['colormap']
- @container = keys['container']
- @screen = keys['screen']
- @use = keys['use']
- @visual = keys['visual']
- if !@classname && my_class_name
- keys['class'] = @classname = my_class_name
- end
- if @classname.kind_of? TkBindTag
- @db_class = @classname
- @classname = @classname.id
- elsif @classname
- @db_class = TkDatabaseClass.new(@classname)
- else
- @db_class = self.class
- @classname = @db_class::WidgetClassName
- end
- keys, cmds = _wm_command_option_chk(keys)
- super(keys)
- cmds.each{|k,v|
- if v.kind_of? Array
- self.__send__(k,*v)
- else
- self.__send__(k,v)
- end
- }
- return
- end
-
- if screen.kind_of? Hash
- keys = screen
- else
- @screen = screen
- if classname.kind_of? Hash
- keys = classname
- else
- @classname = classname
- end
- end
- if keys.kind_of? Hash
- keys = _symbolkey2str(keys)
- if keys.key?('classname')
- keys['class'] = keys.delete('classname')
- end
- @classname = keys['class'] unless @classname
- @colormap = keys['colormap']
- @container = keys['container']
- @screen = keys['screen'] unless @screen
- @use = keys['use']
- @visual = keys['visual']
- else
- keys = {}
- end
- if !@classname && my_class_name
- keys['class'] = @classname = my_class_name
- end
- if @classname.kind_of? TkBindTag
- @db_class = @classname
- @classname = @classname.id
- elsif @classname
- @db_class = TkDatabaseClass.new(@classname)
- else
- @db_class = self.class
- @classname = @db_class::WidgetClassName
- end
- keys, cmds = _wm_command_option_chk(keys)
- super(parent, keys)
- cmds.each{|k,v|
- if v.kind_of? Array
- self.send(k,*v)
- else
- self.send(k,v)
- end
- }
- end
-
- #def create_self(keys)
- # if keys and keys != None
- # tk_call_without_enc('toplevel', @path, *hash_kv(keys, true))
- # else
- # tk_call_without_enc('toplevel', @path)
- # end
- #end
- #private :create_self
-
- def specific_class
- @classname
- end
-
- def add_menu(menu_info, tearoff=false, opts=nil)
- # See tk/menuspec.rb for menu_info.
- # opts is a hash of default configs for all of cascade menus.
- # Configs of menu_info can override it.
- if tearoff.kind_of?(Hash)
- opts = tearoff
- tearoff = false
- end
- _create_menubutton(self, menu_info, tearoff, opts)
- end
-
- def add_menubar(menu_spec, tearoff=false, opts=nil)
- # See tk/menuspec.rb for menu_spec.
- # opts is a hash of default configs for all of cascade menus.
- # Configs of menu_spec can override it.
- menu_spec.each{|info| add_menu(info, tearoff, opts)}
- self.menu
- end
-
- def self.database_class
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- self
- else
- TkDatabaseClass.new(self.name)
- end
- end
- def self.database_classname
- self.database_class.name
- end
-
- def self.bind(*args, &b)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args, &b)
- else
- TkDatabaseClass.new(self.name).bind(*args, &b)
- end
- end
- def self.bind_append(*args, &b)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args, &b)
- else
- TkDatabaseClass.new(self.name).bind_append(*args, &b)
- end
- end
- def self.bind_remove(*args)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args)
- else
- TkDatabaseClass.new(self.name).bind_remove(*args)
- end
- end
- def self.bindinfo(*args)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args)
- else
- TkDatabaseClass.new(self.name).bindinfo(*args)
- end
- end
-end
diff --git a/ext/tk/lib/tk/txtwin_abst.rb b/ext/tk/lib/tk/txtwin_abst.rb
deleted file mode 100644
index 5520360eab..0000000000
--- a/ext/tk/lib/tk/txtwin_abst.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# tk/txtwin_abst.rb : TkTextWin abstruct class
-#
-require 'tk'
-
-class TkTextWin<TkWindow
- TkCommnadNames = [].freeze
- #def create_self
- # fail RuntimeError, "TkTextWin is an abstract class"
- #end
- #private :create_self
-
- def bbox(index)
- list(tk_send_without_enc('bbox', index))
- end
- def delete(first, last=None)
- tk_send_without_enc('delete', first, last)
- self
- end
- def get(*index)
- _fromUTF8(tk_send_without_enc('get', *index))
- end
- def insert(index, *args)
- tk_send('insert', index, *args)
- self
- end
- def scan_mark(x, y)
- tk_send_without_enc('scan', 'mark', x, y)
- self
- end
- def scan_dragto(x, y)
- tk_send_without_enc('scan', 'dragto', x, y)
- self
- end
- def see(index)
- tk_send_without_enc('see', index)
- self
- end
-end
diff --git a/ext/tk/lib/tk/validation.rb b/ext/tk/lib/tk/validation.rb
deleted file mode 100644
index 0c5b5c61b9..0000000000
--- a/ext/tk/lib/tk/validation.rb
+++ /dev/null
@@ -1,376 +0,0 @@
-#
-# tk/validation.rb - validation support module for entry, spinbox, and so on
-#
-require 'tk'
-
-module Tk
- module ValidateConfigure
- def self.__def_validcmd(scope, klass, keys=nil)
- keys = klass._config_keys unless keys
- keys.each{|key|
- eval("def #{key}(*args, &b)
- __validcmd_call(#{klass.name}, '#{key}', *args, &b)
- end", scope)
- }
- end
-
- def __validcmd_call(klass, key, *args, &b)
- return cget(key) if args.empty? && !b
-
- cmd = (b)? proc(&b) : args.shift
-
- if cmd.kind_of?(klass)
- configure(key, cmd)
- elsif !args.empty?
- configure(key, [cmd, args])
- else
- configure(key, cmd)
- end
- end
-
- def __validation_class_list
- # maybe need to override
- []
- end
-
- def __get_validate_key2class
- k2c = {}
- __validation_class_list.each{|klass|
- klass._config_keys.each{|key|
- k2c[key.to_s] = klass
- }
- }
- k2c
- end
-
- def __conv_vcmd_on_hash_kv(keys)
- key2class = __get_validate_key2class
-
- keys = _symbolkey2str(keys)
- key2class.each{|key, klass|
- if keys[key].kind_of?(Array)
- cmd, *args = keys[key]
- keys[key] = klass.new(cmd, args.join(' '))
- # elsif keys[key].kind_of?(Proc) || keys[key].kind_of?(Method)
- elsif TkComm._callback_entry?(keys[key])
- keys[key] = klass.new(keys[key])
- end
- }
- keys
- end
-
- def create_self(keys)
- super(__conv_vcmd_on_hash_kv(keys))
- end
- private :create_self
-
- def configure(slot, value=TkComm::None)
- if slot.kind_of?(Hash)
- super(__conv_vcmd_on_hash_kv(slot))
- else
- super(__conv_vcmd_on_hash_kv(slot=>value))
- end
- self
- end
-=begin
- def configure(slot, value=TkComm::None)
- key2class = __get_validate_key2class
-
- if slot.kind_of?(Hash)
- slot = _symbolkey2str(slot)
- key2class.each{|key, klass|
- if slot[key].kind_of?(Array)
- cmd, *args = slot[key]
- slot[key] = klass.new(cmd, args.join(' '))
- elsif slot[key].kind_of?(Proc) || slot[key].kind_of?(Method)
- slot[key] = klass.new(slot[key])
- end
- }
- super(slot)
-
- else
- slot = slot.to_s
- if (klass = key2class[slot])
- if value.kind_of?(Array)
- cmd, *args = value
- value = klass.new(cmd, args.join(' '))
- elsif value.kind_of?(Proc) || value.kind_of?(Method)
- value = klass.new(value)
- end
- end
- super(slot, value)
- end
-
- self
- end
-=end
- end
-
- module ItemValidateConfigure
- def self.__def_validcmd(scope, klass, keys=nil)
- keys = klass._config_keys unless keys
- keys.each{|key|
- eval("def item_#{key}(id, *args, &b)
- __item_validcmd_call(#{klass.name}, '#{key}', id, *args, &b)
- end", scope)
- }
- end
-
- def __item_validcmd_call(tagOrId, klass, key, *args, &b)
- return itemcget(tagid(tagOrId), key) if args.empty? && !b
-
- cmd = (b)? proc(&b) : args.shift
-
- if cmd.kind_of?(klass)
- itemconfigure(tagid(tagOrId), key, cmd)
- elsif !args.empty?
- itemconfigure(tagid(tagOrId), key, [cmd, args])
- else
- itemconfigure(tagid(tagOrId), key, cmd)
- end
- end
-
- def __item_validation_class_list(id)
- # maybe need to override
- []
- end
-
- def __get_item_validate_key2class(id)
- k2c = {}
- __item_validation_class_list(id).each{|klass|
- klass._config_keys.each{|key|
- k2c[key.to_s] = klass
- }
- }
- end
-
- def __conv_item_vcmd_on_hash_kv(keys)
- key2class = __get_item_validate_key2class(tagid(tagOrId))
-
- keys = _symbolkey2str(keys)
- key2class.each{|key, klass|
- if keys[key].kind_of?(Array)
- cmd, *args = keys[key]
- keys[key] = klass.new(cmd, args.join(' '))
- # elsif keys[key].kind_of?(Proc) || keys[key].kind_of?(Method)
- elsif TkComm._callback_entry?(keys[key])
- keys[key] = klass.new(keys[key])
- end
- }
- keys
- end
-
- def itemconfigure(tagOrId, slot, value=TkComm::None)
- if slot.kind_of?(Hash)
- super(__conv_item_vcmd_on_hash_kv(slot))
- else
- super(__conv_item_vcmd_on_hash_kv(slot=>value))
- end
- self
- end
-=begin
- def itemconfigure(tagOrId, slot, value=TkComm::None)
- key2class = __get_item_validate_key2class(tagid(tagOrId))
-
- if slot.kind_of?(Hash)
- slot = _symbolkey2str(slot)
- key2class.each{|key, klass|
- if slot[key].kind_of?(Array)
- cmd, *args = slot[key]
- slot[key] = klass.new(cmd, args.join(' '))
- elsif slot[key].kind_of?(Proc) || slot[key].kind_of?(Method)
- slot[key] = klass.new(slot[key])
- end
- }
- super(slot)
-
- else
- slot = slot.to_s
- if (klass = key2class[slot])
- if value.kind_of?(Array)
- cmd, *args = value
- value = klass.new(cmd, args.join(' '))
- elsif value.kind_of?(Proc) || value.kind_of?(Method)
- value = klass.new(value)
- end
- end
- super(slot, value)
- end
-
- self
- end
-=end
- end
-end
-
-class TkValidateCommand
- include TkComm
- extend TkComm
-
- class ValidateArgs < TkUtil::CallbackSubst
- KEY_TBL = [
- [ ?d, ?n, :action ],
- [ ?i, ?x, :index ],
- [ ?s, ?e, :current ],
- [ ?v, ?s, :type ],
- [ ?P, ?e, :value ],
- [ ?S, ?e, :string ],
- [ ?V, ?s, :triggered ],
- [ ?W, ?w, :widget ],
- nil
- ]
-
- PROC_TBL = [
- [ ?n, TkComm.method(:number) ],
- [ ?s, TkComm.method(:string) ],
- [ ?w, TkComm.method(:window) ],
-
- [ ?e, proc{|val|
- #enc = Tk.encoding
- enc = ((Tk.encoding)? Tk.encoding : Tk.encoding_system)
- if enc
- Tk.fromUTF8(TkComm::string(val), enc)
- else
- TkComm::string(val)
- end
- }
- ],
-
- [ ?x, proc{|val|
- idx = TkComm::number(val)
- if idx < 0
- nil
- else
- idx
- end
- }
- ],
-
- nil
- ]
-
- _setup_subst_table(KEY_TBL, PROC_TBL);
-
- #
- # NOTE: The order of parameters which passed to callback procedure is
- # <extra_arg>, <extra_arg>, ... , <subst_arg>, <subst_arg>, ...
- #
-
- #def self._get_extra_args_tbl
- # # return an array of convert procs
- # []
- #end
-
- def self.ret_val(val)
- (val)? '1': '0'
- end
- end
-
- ###############################################
-
- def self._config_keys
- # array of config-option key (string or symbol)
- ['vcmd', 'validatecommand', 'invcmd', 'invalidcommand']
- end
-
- def _initialize_for_cb_class(klass, cmd = Proc.new, *args)
- extra_args_tbl = klass._get_extra_args_tbl
-
- if args.compact.size > 0
- args = args.join(' ')
- keys = klass._get_subst_key(args)
- if cmd.kind_of?(String)
- id = cmd
- elsif cmd.kind_of?(TkCallbackEntry)
- @id = install_cmd(cmd)
- else
- @id = install_cmd(proc{|*arg|
- ex_args = []
- extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)}
- klass.ret_val(cmd.call(
- *(ex_args.concat(klass.scan_args(keys, arg)))
- ))
- }) + ' ' + args
- end
- else
- keys, args = klass._get_all_subst_keys
- if cmd.kind_of?(String)
- id = cmd
- elsif cmd.kind_of?(TkCallbackEntry)
- @id = install_cmd(cmd)
- else
- @id = install_cmd(proc{|*arg|
- ex_args = []
- extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)}
- klass.ret_val(cmd.call(
- *(ex_args << klass.new(*klass.scan_args(keys, arg)))
- ))
- }) + ' ' + args
- end
- end
- end
-
- def initialize(cmd = Proc.new, *args)
- _initialize_for_cb_class(self.class::ValidateArgs, cmd, *args)
- end
-
- def to_eval
- @id
- end
-end
-
-module TkValidation
- include Tk::ValidateConfigure
-
- class ValidateCmd < TkValidateCommand
- module Action
- Insert = 1
- Delete = 0
- Others = -1
- Focus = -1
- Forced = -1
- Textvariable = -1
- TextVariable = -1
- end
- end
-
- #####################################
-
- def __validation_class_list
- super() << ValidateCmd
- end
-
- Tk::ValidateConfigure.__def_validcmd(binding, ValidateCmd)
-
-=begin
- def validatecommand(cmd = Proc.new, args = nil)
- if cmd.kind_of?(ValidateCmd)
- configure('validatecommand', cmd)
- elsif args
- configure('validatecommand', [cmd, args])
- else
- configure('validatecommand', cmd)
- end
- end
-=end
-# def validatecommand(*args, &b)
-# __validcmd_call(ValidateCmd, 'validatecommand', *args, &b)
-# end
-# alias vcmd validatecommand
-
-=begin
- def invalidcommand(cmd = Proc.new, args = nil)
- if cmd.kind_of?(ValidateCmd)
- configure('invalidcommand', cmd)
- elsif args
- configure('invalidcommand', [cmd, args])
- else
- configure('invalidcommand', cmd)
- end
- end
-=end
-# def invalidcommand(*args, &b)
-# __validcmd_call(ValidateCmd, 'invalidcommand', *args, &b)
-# end
-# alias invcmd invalidcommand
-end
diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb
deleted file mode 100644
index e5cacadc1a..0000000000
--- a/ext/tk/lib/tk/variable.rb
+++ /dev/null
@@ -1,1651 +0,0 @@
-#
-# tk/variable.rb : treat Tk variable object
-#
-require 'tk'
-
-class TkVariable
- include Tk
- extend TkCore
-
- include Comparable
-
- #TkCommandNames = ['tkwait'.freeze].freeze
- TkCommandNames = ['vwait'.freeze].freeze
-
- #TkVar_CB_TBL = {}
- #TkVar_ID_TBL = {}
- TkVar_CB_TBL = TkCore::INTERP.create_table
- TkVar_ID_TBL = TkCore::INTERP.create_table
- Tk_VARIABLE_ID = ["v".freeze, "00000".taint].freeze
-
- #TkCore::INTERP.add_tk_procs('rb_var', 'args',
- # "ruby [format \"TkVariable.callback %%Q!%s!\" $args]")
-TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
- if {[set st [catch {eval {ruby_cmd TkVariable callback} $args} ret]] != 0} {
- set idx [string first "\n\n" $ret]
- if {$idx > 0} {
- global errorInfo
- set tcl_backtrace $errorInfo
- set errorInfo [string range $ret [expr $idx + 2] \
- [string length $ret]]
- append errorInfo "\n" $tcl_backtrace
- bgerror [string range $ret 0 [expr $idx - 1]]
- } else {
- bgerror $ret
- }
- return ""
- #return -code $st $ret
- } else {
- return $ret
- }
- EOL
-
- #def TkVariable.callback(args)
- def TkVariable.callback(id, name1, name2, op)
- #name1,name2,op = tk_split_list(args)
- #name1,name2,op = tk_split_simplelist(args)
- if TkVar_CB_TBL[id]
- #_get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
- begin
- _get_eval_string(TkVar_CB_TBL[id].trace_callback(name2, op))
- rescue SystemExit
- exit(0)
- rescue Interrupt
- exit!(1)
- rescue Exception => e
- begin
- msg = _toUTF8(e.class.inspect) + ': ' +
- _toUTF8(e.message) + "\n" +
- "\n---< backtrace of Ruby side >-----\n" +
- _toUTF8(e.backtrace.join("\n")) +
- "\n---< backtrace of Tk side >-------"
- msg.instance_variable_set(:@encoding, 'utf-8')
- rescue Exception
- msg = e.class.inspect + ': ' + e.message + "\n" +
- "\n---< backtrace of Ruby side >-----\n" +
- e.backtrace.join("\n") +
- "\n---< backtrace of Tk side >-------"
- end
- fail(e, msg)
- end
-=begin
- begin
- raise 'check backtrace'
- rescue
- # ignore backtrace before 'callback'
- pos = -($!.backtrace.size)
- end
- begin
- _get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
- rescue
- trace = $!.backtrace
- raise $!, "\n#{trace[0]}: #{$!.message} (#{$!.class})\n" +
- "\tfrom #{trace[1..pos].join("\n\tfrom ")}"
- end
-=end
- else
- ''
- end
- end
-
- def self.new_hash(val = {})
- if val.kind_of?(Hash)
- self.new(val)
- else
- fail ArgumentError, 'Hash is expected'
- end
- end
-
- #
- # default_value is available only when the variable is an assoc array.
- #
- def default_value(val=nil, &b)
- if b
- @def_default = :proc
- @default_val = proc(&b)
- else
- @def_default = :val
- @default_val = val
- end
- self
- end
- def set_default_value(val)
- @def_default = :val
- @default_val = val
- self
- end
- alias default_value= set_default_value
- def default_proc(cmd = Proc.new)
- @def_default = :proc
- @default_val = cmd
- self
- end
-
- def undef_default
- @default_val = nil
- @def_default = false
- self
- end
-
- def default_value_type
- @type
- end
- def default_element_value_type(idxs)
- if idxs.kind_of?(Array)
- index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',')
- else
- index = _get_eval_string(idxs, true)
- end
- @element_type[index]
- end
-
- def _set_default_value_type_core(type, idxs)
- if type.kind_of?(Class)
- if type == NilClass
- type = nil
- elsif type == Numeric
- type = :numeric
- elsif type == TrueClass || type == FalseClass
- type = :bool
- elsif type == String
- type = :string
- elsif type == Symbol
- type = :symbol
- elsif type == Array
- type = :list
- elsif type <= TkVariable
- type = :variable
- elsif type <= TkWindow
- type = :window
- elsif TkComm._callback_entry_class?(type)
- type = :procedure
- else
- type = nil
- end
- else
- case(type)
- when nil
- type = nil
- when :numeric, 'numeric'
- type = :numeric
- when true, false, :bool, 'bool'
- type = :bool
- when :string, 'string'
- type = :string
- when :symbol, 'symbol'
- type = :symbol
- when :list, 'list'
- type = :list
- when :numlist, 'numlist'
- type = :numlist
- when :variable, 'variable'
- type = :variable
- when :window, 'window'
- type = :window
- when :procedure, 'procedure'
- type = :procedure
- else
- return _set_default_value_type_core(type.class, idxs)
- end
- end
- if idxs
- if idxs.kind_of?(Array)
- index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',')
- else
- index = _get_eval_string(idxs, true)
- end
- @element_type[index] = type
- else
- @type = type
- end
- type
- end
- private :_set_default_value_type_core
-
- def set_default_value_type(type)
- _set_default_value_type_core(type, nil)
- self
- end
- alias default_value_type= set_default_value_type
-
- def set_default_element_value_type(idxs, type)
- _set_default_value_type_core(type, idxs)
- self
- end
-
- def _to_default_type(val, idxs = nil)
- if idxs
- if idxs.kind_of?(Array)
- index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',')
- else
- index = _get_eval_string(idxs, true)
- end
- type = @element_type[index]
- else
- type = @type
- end
- return val unless type
- if val.kind_of?(Hash)
- val.keys.each{|k| val[k] = _to_default_type(val[k], idxs) }
- val
- else
- begin
- case(type)
- when :numeric
- number(val)
- when :bool
- TkComm.bool(val)
- when :string
- val
- when :symbol
- val.intern
- when :list
- tk_split_simplelist(val)
- when :numlist
- tk_split_simplelist(val).collect!{|v| number(v)}
- when :variable
- TkVarAccess.new(val)
- when :window
- TkComm.window(val)
- when :procedure
- TkComm.procedure(val)
- else
- val
- end
- rescue
- val
- end
- end
- end
- private :_to_default_type
-
- def _to_default_element_type(idxs, val)
- _to_default_type(val, idxs)
- end
- private :_to_default_element_type
-
- def initialize(val="", type=nil)
- # @id = Tk_VARIABLE_ID.join('')
- begin
- @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_)
- Tk_VARIABLE_ID[1].succ!
- end until INTERP._invoke_without_enc('info', 'globals', @id).empty?
-
- TkVar_ID_TBL[@id] = self
-
- @var = @id
- @elem = nil
-
- @def_default = false
- @default_val = nil
-
- @trace_var = nil
- @trace_elem = nil
- @trace_opts = nil
-
- @type = nil
- var = self
- @element_type = Hash.new{|k,v| var.default_value_type }
-
- self.default_value_type = type
-
- # teach Tk-ip that @id is global var
- INTERP._invoke_without_enc('global', @id)
- #INTERP._invoke('global', @id)
-
- # create and init
- if val.kind_of?(Hash)
- # assoc-array variable
- self[''] = 0
- self.clear
- end
- self.value = val
-
-=begin
- if val == []
- # INTERP._eval(format('global %s; set %s(0) 0; unset %s(0)',
- # @id, @id, @id))
- elsif val.kind_of?(Array)
- a = []
- # val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))}
- # s = '"' + a.join(" ").gsub(/[\[\]$"]/, '\\\\\&') + '"'
- val.each_with_index{|e,i| a.push(i); a.push(e)}
- #s = '"' + array2tk_list(a).gsub(/[\[\]$"]/, '\\\\\&') + '"'
- s = '"' + array2tk_list(a).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
- INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
- elsif val.kind_of?(Hash)
- #s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
- # .gsub(/[\[\]$"]/, '\\\\\&') + '"'
- s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
- .gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
- INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
- else
- #s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"'
- s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
- INTERP._eval(format('global %s; set %s %s', @id, @id, s))
- end
-=end
-=begin
- if val.kind_of?(Hash)
- #s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
- # .gsub(/[\[\]$"]/, '\\\\\&') + '"'
- s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
- .gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
- INTERP._eval(Kernel.format('global %s; array set %s %s', @id, @id, s))
- else
- #s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"'
- s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
- INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s))
- end
-=end
- end
-
- def wait(on_thread = false, check_root = false)
- if $SAFE >= 4
- fail SecurityError, "can't wait variable at $SAFE >= 4"
- end
- on_thread &= (Thread.list.size != 1)
- if on_thread
- if check_root
- INTERP._thread_tkwait('variable', @id)
- else
- INTERP._thread_vwait(@id)
- end
- else
- if check_root
- INTERP._invoke_without_enc('tkwait', 'variable', @id)
- else
- INTERP._invoke_without_enc('vwait', @id)
- end
- end
- end
- def eventloop_wait(check_root = false)
- wait(false, check_root)
- end
- def thread_wait(check_root = false)
- wait(true, check_root)
- end
- def tkwait(on_thread = true)
- wait(on_thread, true)
- end
- def eventloop_tkwait
- wait(false, true)
- end
- def thread_tkwait
- wait(true, true)
- end
-
- def id
- @id
- end
-
- def ref(*idxs)
- # "#{@id}(#{idxs.collect{|idx| _get_eval_string(idx)}.join(',')})"
- TkVarAccess.new("#{@id}(#{idxs.collect{|idx| _get_eval_string(idx)}.join(',')})")
- end
-
- def is_hash?
- #ITNERP._eval("global #{@id}; array exist #{@id}") == '1'
- INTERP._invoke_without_enc('global', @id)
- # INTERP._invoke_without_enc('array', 'exist', @id) == '1'
- TkComm.bool(INTERP._invoke_without_enc('array', 'exist', @id))
- end
-
- def is_scalar?
- ! is_hash?
- end
-
- def exist?(*elems)
- INTERP._invoke_without_enc('global', @id)
- if elems.empty?
- TkComm.bool(tk_call('info', 'exist', @id))
- else
- # array
- index = elems.collect{|idx| _get_eval_string(idx, true)}.join(',')
- TkComm.bool(tk_call('info', 'exist', "#{@id}")) &&
- TkComm.bool(tk_call('info', 'exist', "#{@id}(#{index})"))
- end
- end
-
- def keys
- if (is_scalar?)
- fail RuntimeError, 'cannot get keys from a scalar variable'
- end
- #tk_split_simplelist(INTERP._eval("global #{@id}; array get #{@id}"))
- INTERP._invoke_without_enc('global', @id)
- #tk_split_simplelist(INTERP._fromUTF8(INTERP._invoke_without_enc('array', 'names', @id)))
- tk_split_simplelist(INTERP._invoke_without_enc('array', 'names', @id),
- false, true)
- end
-
- def size
- INTERP._invoke_without_enc('global', @id)
- TkComm.number(INTERP._invoke_without_enc('array', 'size', @id))
- end
-
- def clear
- if (is_scalar?)
- fail RuntimeError, 'cannot clear a scalar variable'
- end
- keys.each{|k| unset(k)}
- self
- end
-
- def update(hash)
- if (is_scalar?)
- fail RuntimeError, 'cannot update a scalar variable'
- end
- hash.each{|k,v| self[k] = v}
- self
- end
-
-unless const_defined?(:USE_TCLs_SET_VARIABLE_FUNCTIONS)
- USE_TCLs_SET_VARIABLE_FUNCTIONS = true
-end
-
-if USE_TCLs_SET_VARIABLE_FUNCTIONS
- ###########################################################################
- # use Tcl function version of set tkvariable
- ###########################################################################
-
- def _value
- #if INTERP._eval("global #{@id}; array exist #{@id}") == '1'
- INTERP._invoke_without_enc('global', @id)
- # if INTERP._invoke('array', 'exist', @id) == '1'
- if TkComm.bool(INTERP._invoke('array', 'exist', @id))
- #Hash[*tk_split_simplelist(INTERP._eval("global #{@id}; array get #{@id}"))]
- Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', @id))]
- else
- _fromUTF8(INTERP._get_global_var(@id))
- end
- end
-
- def value=(val)
- val = val._value if !@type && @type != :variable && val.kind_of?(TkVariable)
- if val.kind_of?(Hash)
- self.clear
- val.each{|k, v|
- #INTERP._set_global_var2(@id, _toUTF8(_get_eval_string(k)),
- # _toUTF8(_get_eval_string(v)))
- INTERP._set_global_var2(@id, _get_eval_string(k, true),
- _get_eval_string(v, true))
- }
- self.value
-# elsif val.kind_of?(Array)
-=begin
- INTERP._set_global_var(@id, '')
- val.each{|v|
- #INTERP._set_variable(@id, _toUTF8(_get_eval_string(v)),
- INTERP._set_variable(@id, _get_eval_string(v, true),
- TclTkLib::VarAccessFlag::GLOBAL_ONLY |
- TclTkLib::VarAccessFlag::LEAVE_ERR_MSG |
- TclTkLib::VarAccessFlag::APPEND_VALUE |
- TclTkLib::VarAccessFlag::LIST_ELEMENT)
- }
- self.value
-=end
-# _fromUTF8(INTERP._set_global_var(@id, array2tk_list(val, true)))
- else
- #_fromUTF8(INTERP._set_global_var(@id, _toUTF8(_get_eval_string(val))))
- _fromUTF8(INTERP._set_global_var(@id, _get_eval_string(val, true)))
- end
- end
-
- def _element_value(*idxs)
- index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',')
- begin
- _fromUTF8(INTERP._get_global_var2(@id, index))
- rescue => e
- case @def_default
- when :proc
- @default_val.call(self, *idxs)
- when :val
- @default_val
- else
- fail e
- end
- end
- #_fromUTF8(INTERP._get_global_var2(@id, index))
- #_fromUTF8(INTERP._get_global_var2(@id, _toUTF8(_get_eval_string(index))))
- #_fromUTF8(INTERP._get_global_var2(@id, _get_eval_string(index, true)))
- end
-
- def []=(*args)
- val = args.pop
- type = default_element_value_type(args)
- val = val._value if !type && type != :variable && val.kind_of?(TkVariable)
- index = args.collect{|idx| _get_eval_string(idx, true)}.join(',')
- _fromUTF8(INTERP._set_global_var2(@id, index, _get_eval_string(val, true)))
- #_fromUTF8(INTERP._set_global_var2(@id, _toUTF8(_get_eval_string(index)),
- # _toUTF8(_get_eval_string(val))))
- #_fromUTF8(INTERP._set_global_var2(@id, _get_eval_string(index, true),
- # _get_eval_string(val, true)))
- end
-
- def unset(*elems)
- if elems.empty?
- INTERP._unset_global_var(@id)
- else
- index = elems.collect{|idx| _get_eval_string(idx, true)}.join(',')
- INTERP._unset_global_var2(@id, index)
- end
- end
- alias remove unset
-
-else
- ###########################################################################
- # use Ruby script version of set tkvariable (traditional methods)
- ###########################################################################
-
- def _value
- begin
- INTERP._eval(Kernel.format('global %s; set %s', @id, @id))
- #INTERP._eval(Kernel.format('set %s', @id))
- #INTERP._invoke_without_enc('set', @id)
- rescue
- if INTERP._eval(Kernel.format('global %s; array exists %s',
- @id, @id)) != "1"
- #if INTERP._eval(Kernel.format('array exists %s', @id)) != "1"
- #if INTERP._invoke_without_enc('array', 'exists', @id) != "1"
- fail
- else
- Hash[*tk_split_simplelist(INTERP._eval(Kernel.format('global %s; array get %s', @id, @id)))]
- #Hash[*tk_split_simplelist(_fromUTF8(INTERP._invoke_without_enc('array', 'get', @id)))]
- end
- end
- end
-
- def value=(val)
- val = val._value if !@type && @type != :variable && val.kind_of?(TkVariable)
- begin
- #s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"'
- s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
- INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s))
- #INTERP._eval(Kernel.format('set %s %s', @id, s))
- #_fromUTF8(INTERP._invoke_without_enc('set', @id, _toUTF8(s)))
- rescue
- if INTERP._eval(Kernel.format('global %s; array exists %s',
- @id, @id)) != "1"
- #if INTERP._eval(Kernel.format('array exists %s', @id)) != "1"
- #if INTERP._invoke_without_enc('array', 'exists', @id) != "1"
- fail
- else
- if val == []
- INTERP._eval(Kernel.format('global %s; unset %s; set %s(0) 0; unset %s(0)', @id, @id, @id, @id))
- #INTERP._eval(Kernel.format('unset %s; set %s(0) 0; unset %s(0)',
- # @id, @id, @id))
- #INTERP._invoke_without_enc('unset', @id)
- #INTERP._invoke_without_enc('set', @id+'(0)', 0)
- #INTERP._invoke_without_enc('unset', @id+'(0)')
- elsif val.kind_of?(Array)
- a = []
- val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e, true))}
- #s = '"' + a.join(" ").gsub(/[\[\]$"]/, '\\\\\&') + '"'
- s = '"' + a.join(" ").gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
- INTERP._eval(Kernel.format('global %s; unset %s; array set %s %s',
- @id, @id, @id, s))
- #INTERP._eval(Kernel.format('unset %s; array set %s %s',
- # @id, @id, s))
- #INTERP._invoke_without_enc('unset', @id)
- #_fromUTF8(INTERP._invoke_without_enc('array','set', @id, _toUTF8(s)))
- elsif val.kind_of?(Hash)
- #s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
- # .gsub(/[\[\]$"]/, '\\\\\&') + '"'
- s = '"' + val.to_a.collect{|e| array2tk_list(e, true)}.join(" ")\
- .gsub(/[\[\]$\\"]/, '\\\\\&') + '"'
- INTERP._eval(Kernel.format('global %s; unset %s; array set %s %s',
- @id, @id, @id, s))
- #INTERP._eval(Kernel.format('unset %s; array set %s %s',
- # @id, @id, s))
- #INTERP._invoke_without_enc('unset', @id)
- #_fromUTF8(INTERP._invoke_without_enc('array','set', @id, _toUTF8(s)))
- else
- fail
- end
- end
- end
- end
-
- def _element_value(*idxs)
- index = idxs.collect{|idx| _get_eval_string(idx)}.join(',')
- begin
- INTERP._eval(Kernel.format('global %s; set %s(%s)', @id, @id, index))
- rescue => e
- case @def_default
- when :proc
- @default_val.call(self, *idxs)
- when :val
- @default_val
- else
- fail e
- end
- end
- #INTERP._eval(Kernel.format('global %s; set %s(%s)', @id, @id, index))
- #INTERP._eval(Kernel.format('global %s; set %s(%s)',
- # @id, @id, _get_eval_string(index)))
- #INTERP._eval(Kernel.format('set %s(%s)', @id, _get_eval_string(index)))
- #INTERP._eval('set ' + @id + '(' + _get_eval_string(index) + ')')
- end
-
- def []=(*args)
- val = args.pop
- type = default_element_value_type(args)
- val = val._value if !type && type != :variable && val.kind_of?(TkVariable)
- index = args.collect{|idx| _get_eval_string(idx)}.join(',')
- INTERP._eval(Kernel.format('global %s; set %s(%s) %s', @id, @id,
- index, _get_eval_string(val)))
- #INTERP._eval(Kernel.format('global %s; set %s(%s) %s', @id, @id,
- # _get_eval_string(index), _get_eval_string(val)))
- #INTERP._eval(Kernel.format('set %s(%s) %s', @id,
- # _get_eval_string(index), _get_eval_string(val)))
- #INTERP._eval('set ' + @id + '(' + _get_eval_string(index) + ') ' +
- # _get_eval_string(val))
- end
-
- def unset(*elems)
- if elems.empty?
- INTERP._eval(Kernel.format('global %s; unset %s', @id, @id))
- #INTERP._eval(Kernel.format('unset %s', @id))
- #INTERP._eval('unset ' + @id)
- else
- index = elems.collect{|idx| _get_eval_string(idx, true)}.join(',')
- INTERP._eval(Kernel.format('global %s; unset %s(%s)', @id, @id, index))
- #INTERP._eval(Kernel.format('global %s; unset %s(%s)',
- # @id, @id, _get_eval_string(elem)))
- #INTERP._eval(Kernel.format('unset %s(%s)', @id, tk_tcl2ruby(elem)))
- #INTERP._eval('unset ' + @id + '(' + _get_eval_string(elem) + ')')
- end
- end
- alias remove unset
-
-end
-
- protected :_value, :_element_value
-
- def value
- _to_default_type(_value)
- end
-
- def [](*idxs)
- _to_default_element_type(idxs, _element_value(*idxs))
- end
-
- def set_value(val)
- self.value = val
- self
- end
-
- def set_element_value(idxs, val)
- if idxs.kind_of?(Array)
- self[*idxs]=val
- else
- self[idxs]=val
- end
- self
- end
-
- def set_value_type(val)
- self.default_value_type = val.class
- self.value = val
- self
- end
-
- alias value_type= set_value_type
-
- def set_element_value_type(idxs, val)
- self.set_default_element_value_type(idxs, val.class)
- if idxs.kind_of?(Array)
- self[*idxs]=val
- else
- self[idxs]=val
- end
- self
- end
-
- def numeric
- number(_value)
- end
- def numeric_element(*idxs)
- number(_element_value(*idxs))
- end
- def set_numeric(val)
- case val
- when Numeric
- self.value=(val)
- when TkVariable
- self.value=(val.numeric)
- else
- raise ArgumentError, "Numeric is expected"
- end
- self
- end
- alias numeric= set_numeric
- def set_numeric_element(idxs, val)
- case val
- when Numeric
- val
- when TkVariable
- val = val.numeric
- else
- raise ArgumentError, "Numeric is expected"
- end
- if idxs.kind_of?(Array)
- self[*idxs]=val
- else
- self[idxs]=val
- end
- self
- end
- def set_numeric_type(val)
- @type = :numeric
- self.numeric=(val)
- self
- end
- alias numeric_type= set_numeric_type
- def set_numeric_element_type(idxs, val)
- self.set_default_element_value_type(idxs, :numeric)
- self.set_numeric_element(idxs, val)
- end
-
- def bool
- TkComm.bool(_value)
-=begin
- # see Tcl_GetBoolean man-page
- case _value.downcase
- when '0', 'false', 'no', 'off'
- false
- else
- true
- end
-=end
- end
- def bool_element(*idxs)
- TkComm.bool(_element_value(*idxs))
- end
- def set_bool(val)
- if ! val
- self.value = '0'
- else
- case val.to_s.downcase
- when 'false', '0', 'no', 'off'
- self.value = '0'
- else
- self.value = '1'
- end
- end
- self
- end
- alias bool= set_bool
- def set_bool_element(idxs, val)
- if ! val
- val = '0'
- else
- case val.to_s.downcase
- when 'false', '0', 'no', 'off'
- val = '0'
- else
- val = '1'
- end
- end
- if idxs.kind_of?(Array)
- self[*idxs]=val
- else
- self[idxs]=val
- end
- self
- end
- def set_bool_type(val)
- @type = :bool
- self.bool=(val)
- self
- end
- alias bool_type= set_bool_type
- def set_bool_element_type(idxs, val)
- self.set_default_element_value_type(idxs, :bool)
- self.set_bool_element(idxs, val)
- end
-
- def variable
- # keeps a Tcl's variable name
- TkVarAccess.new(self._value)
- end
- def variable_element(*idxs)
- TkVarAccess.new(_element_value(*idxs))
- end
- def set_variable(var)
- var = var.id if var.kind_of?(TkVariable)
- self.value = var
- self
- end
- alias variable= set_variable
- def set_variable_element(idxs, var)
- var = var.id if var.kind_of?(TkVariable)
- if idxs.kind_of?(Array)
- self[*idxs]=var
- else
- self[idxs]=var
- end
- self
- end
- def set_variable_type(var)
- @type = :variable
- var = var.id if var.kind_of?(TkVariable)
- self.value = var
- self
- end
- alias variable_type= set_variable_type
- def set_variable_element_type(idxs, var)
- self.set_default_element_value_type(idxs, :variable)
- self.set_variable_element(idxs, var)
- end
-
- def window
- TkComm.window(self._value)
- end
- def window_element(*idxs)
- TkComm.window(_element_value(*idxs))
- end
- def set_window(win)
- win = win._value if win.kind_of?(TkVariable)
- self.value = win
- self
- end
- alias window= set_window
- def set_window_element(idxs, win)
- win = win._value if win.kind_of?(TkVariable)
- if idxs.kind_of?(Array)
- self[*idxs]=win
- else
- self[idxs]=win
- end
- self
- end
- def set_window_type(win)
- @type = :window
- self.window=(win)
- self
- end
- alias window_type= set_window_type
- def set_window_element_type(idxs, win)
- self.set_default_element_value_type(idxs, :window)
- self.set_window_element(idxs, win)
- end
-
- def procedure
- TkComm.procedure(self._value)
- end
- def procedure_element(*idxs)
- TkComm.procedure(_element_value(*idxs))
- end
- def set_procedure(cmd)
- self.value = cmd
- self
- end
- alias procedure= set_procedure
- def set_procedure_element(idxs, cmd)
- cmd = cmd._value if cmd.kind_of?(TkVariable)
- if idxs.kind_of?(Array)
- self[*idxs]=cmd
- else
- self[idxs]=cmd
- end
- self
- end
- def set_procedure_type(cmd)
- @type = :procedure
- self.procedure=(cmd)
- self
- end
- alias procedure_type= set_procedure_type
- def set_procedure_element_type(idxs, cmd)
- self.set_default_element_value_type(idxs, :procedure)
- self.set_proceure_element(idxs, cmd)
- end
-
- def to_i
- number(_value).to_i
- end
- def element_to_i(*idxs)
- number(_element_value(*idxs)).to_i
- end
-
- def to_f
- number(_value).to_f
- end
- def element_to_f(*idxs)
- number(_element_value(*idxs)).to_f
- end
-
- def to_s
- #string(value).to_s
- _value
- end
- alias string to_s
- def element_to_s(*idxs)
- _element_value(*idxs)
- end
- def string_element(*idxs)
- _element_value(*idxs)
- end
- def set_string(val)
- val = val._value if val.kind_of?(TkVariable)
- self.value=val
- self
- end
- alias string= set_string
- def set_string_element(idxs, val)
- val = val._value if val.kind_of?(TkVariable)
- if idxs.kind_of?(Array)
- self[*idxs]=val
- else
- self[idxs]=val
- end
- self
- end
- def set_string_type(val)
- @type = :string
- self.string=(val)
- self
- end
- alias string_type= set_string_type
- def set_string_element_type(idxs, val)
- self.set_default_element_value_type(idxs, :string)
- self.set_string_element(idxs, val)
- end
-
- def to_sym
- _value.intern
- end
- alias symbol to_sym
- def element_to_sym(*idxs)
- _element_value(*idxs).intern
- end
- alias symbol_element element_to_sym
- def set_symbol(val)
- val = val._value if val.kind_of?(TkVariable)
- self.value=val
- self
- end
- alias symbol= set_symbol
- def set_symbol_element(idxs, val)
- val = val._value if val.kind_of?(TkVariable)
- if idxs.kind_of?(Array)
- self[*idxs]=val
- else
- self[idxs]=val
- end
- self
- end
- def set_symbol_type(val)
- @type = :symbol
- self.value=(val)
- self
- end
- alias symbol_type= set_symbol_type
- def set_symbol_element_type(idxs, val)
- self.set_default_element_value_type(idxs, :symbol)
- self.set_symbol_element(idxs, val)
- end
-
- def list
- #tk_split_list(value)
- tk_split_simplelist(_value)
- end
- alias to_a list
- def list_element(*idxs)
- tk_split_simplelist(_element_value(*idxs))
- end
- alias element_to_a list_element
-
- def numlist
- list.collect!{|val| number(val)}
- end
- def numlist_element(*idxs)
- list_element(*idxs).collect!{|val| number(val)}
- end
-
- def set_list(val)
- case val
- when Array
- self.value=(val)
- when TkVariable
- self.value=(val.list)
- else
- raise ArgumentError, "Array is expected"
- end
- self
- end
- alias list= set_list
-
- alias set_numlist set_list
- alias numlist= set_numlist
-
- def set_list_element(idxs, val)
- case val
- when Array
- val
- when TkVariable
- val = val.list
- else
- raise ArgumentError, "Array is expected"
- end
- if idxs.kind_of?(Array)
- self[*idxs]=val
- else
- self[idxs]=val
- end
- self
- end
- alias set_numlist_element set_list_element
-
- def set_list_type(val)
- @type = :list
- self.list=(val)
- self
- end
- alias list_type= set_list_type
- def set_list_element_type(idxs, val)
- self.set_default_element_value_type(idxs, :list)
- self.set_list_element(idxs, val)
- end
- def set_numlist_type(val)
- @type = :numlist
- self.numlist=(val)
- self
- end
- alias numlist_type= set_numlist_type
- def set_numlist_element_type(idxs, val)
- self.set_default_element_value_type(idxs, :numlist)
- self.set_numlist_element(idxs, val)
- end
-
- def lappend(*elems)
- tk_call('lappend', @id, *elems)
- self
- end
- def element_lappend(idxs, *elems)
- if idxs.kind_of?(Array)
- idxs = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',')
- end
- tk_call('lappend', "#{@id}(#{idxs})", *elems)
- self
- end
-
- def lindex(idx)
- tk_call('lindex', self._value, idx)
- end
- alias lget lindex
- def element_lindex(elem_idxs, idx)
- if elem_idxs.kind_of?(Array)
- val = _element_value(*elem_idxs)
- else
- val = _element_value(elem_idxs)
- end
- tk_call('lindex', val, idx)
- end
- alias element_lget element_lindex
-
- def lget_i(idx)
- number(lget(idx)).to_i
- end
- def element_lget_i(elem_idxs, idx)
- number(element_lget(elem_idxs, idx)).to_i
- end
-
- def lget_f(idx)
- number(lget(idx)).to_f
- end
- def element_lget_f(elem_idxs, idx)
- number(element_lget(elem_idxs, idx)).to_f
- end
-
- def lset(idx, val)
- tk_call('lset', @id, idx, val)
- self
- end
- def element_lset(elem_idxs, idx, val)
- if elem_idxs.kind_of?(Array)
- idxs = elem_idxs.collect{|i| _get_eval_string(i, true)}.join(',')
- end
- tk_call('lset', "#{@id}(#{idxs})", idx, val)
- self
- end
-
- def inspect
- #Kernel.format "#<TkVariable: %s>", @id
- '#<TkVariable: ' + @id + '>'
- end
-
- def coerce(other)
- case other
- when TkVariable
- [other._value, self._value]
- when String
- [other, self.to_s]
- when Symbol
- [other, self.to_sym]
- when Integer
- [other, self.to_i]
- when Float
- [other, self.to_f]
- when Array
- [other, self.to_a]
- else
- [other, self._value]
- end
- end
-
- def &(other)
- if other.kind_of?(Array)
- self.to_a & other.to_a
- else
- self.to_i & other.to_i
- end
- end
- def |(other)
- if other.kind_of?(Array)
- self.to_a | other.to_a
- else
- self.to_i | other.to_i
- end
- end
- def +(other)
- case other
- when Array
- self.to_a + other
- when String
- self._value + other
- else
- begin
- number(self._value) + other
- rescue
- self._value + other.to_s
- end
- end
- end
- def -(other)
- if other.kind_of?(Array)
- self.to_a - other
- else
- number(self._value) - other
- end
- end
- def *(other)
- num_or_str(self._value) * other.to_i
- #begin
- # number(self._value) * other
- #rescue
- # self._value * other
- #end
- end
- def /(other)
- number(self._value) / other
- end
- def %(other)
- num_or_str(self._value) % other.to_i
- #begin
- # number(self._value) % other
- #rescue
- # self._value % other
- #end
- end
- def **(other)
- number(self._value) ** other
- end
- def =~(other)
- self._value =~ other
- end
-
- def ==(other)
- case other
- when TkVariable
- #self.equal?(other)
- self._value == other._value
- when String
- self.to_s == other
- when Symbol
- self.to_sym == other
- when Integer
- self.to_i == other
- when Float
- self.to_f == other
- when Array
- self.to_a == other
- when Hash
- # false if self is not an assoc array
- self._value == other
- else
- # false
- self._value == _get_eval_string(other)
- end
- end
-
- def zero?
- numeric.zero?
- end
- def nonzero?
- !(numeric.zero?)
- end
-
- def <=>(other)
- if other.kind_of?(TkVariable)
- begin
- val = other.numeric
- other = val
- rescue
- other = other._value
- end
- elsif other.kind_of?(Numeric)
- begin
- return self.numeric <=> other
- rescue
- return self._value <=> other.to_s
- end
- elsif other.kind_of?(Array)
- return self.list <=> other
- else
- return self._value <=> other
- end
- end
-
- def to_eval
- @id
- end
-
- def trace_callback(elem, op)
- if @trace_var.kind_of? Array
- @trace_var.each{|m,e| e.call(self,elem,op) if m.index(op)}
- end
- if elem.kind_of?(String) && elem != ''
- if @trace_elem.kind_of?(Hash) && @trace_elem[elem].kind_of?(Array)
- @trace_elem[elem].each{|m,e| e.call(self,elem,op) if m.index(op)}
- end
- end
- end
-
- def trace(opts, cmd = Proc.new)
- @trace_var = [] if @trace_var == nil
- #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- @trace_var.unshift([opts,cmd])
- if @trace_opts == nil
- TkVar_CB_TBL[@id] = self
- @trace_opts = opts.dup
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, 'rb_var')
- end
-=end
- else
- newopts = @trace_opts.dup
- #opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
- opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'vdelete',
- @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
- end
-=end
- end
- end
- self
- end
-
- def trace_element(elem, opts, cmd = Proc.new)
- if @elem
- fail(RuntimeError,
- "invalid for a TkVariable which denotes an element of Tcl's array")
- end
- @trace_elem = {} if @trace_elem == nil
- @trace_elem[elem] = [] if @trace_elem[elem] == nil
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- @trace_elem[elem].unshift([opts,cmd])
- if @trace_opts == nil
- TkVar_CB_TBL[@id] = self
- @trace_opts = opts.dup
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
- end
-=end
- else
- newopts = @trace_opts.dup
- # opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
- opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'vdelete',
- @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
- end
-=end
- end
- end
- self
- end
-
- def trace_vinfo
- return [] unless @trace_var
- @trace_var.dup
- end
-
- def _trace_vinfo_for_element(elem)
- if @elem
- fail(RuntimeError,
- "invalid for a TkVariable which denotes an element of Tcl's array")
- end
- return [] unless @trace_elem
- return [] unless @trace_elem[elem]
- @trace_elem[elem].dup
- end
-
- def trace_vdelete(opts,cmd)
- return self unless @trace_var.kind_of? Array
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- idx = -1
- newopts = ''
- @trace_var.each_with_index{|e,i|
- if idx < 0 && e[0] == opts && e[1] == cmd
- idx = i
- next
- end
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- }
- if idx >= 0
- @trace_var.delete_at(idx)
- else
- return self
- end
-
- @trace_elem.each{|elem|
- @trace_elem[elem].each{|e|
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- }
- }
-
- newopts = newopts.to_s
- newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'vdelete',
- @id, @trace_opts, 'rb_var')
- end
-=end
- @trace_opts.replace(newopts)
- if @trace_opts != ''
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
- end
-=end
- end
- end
-
- self
- end
-
- def trace_vdelete_for_element(elem,opts,cmd)
- if @elem
- fail(RuntimeError,
- "invalid for a TkVariable which denotes an element of Tcl's array")
- end
- return self unless @trace_elem.kind_of? Hash
- return self unless @trace_elem[elem].kind_of? Array
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- idx = -1
- @trace_elem[elem].each_with_index{|e,i|
- if idx < 0 && e[0] == opts && e[1] == cmd
- idx = i
- next
- end
- }
- if idx >= 0
- @trace_elem[elem].delete_at(idx)
- else
- return self
- end
-
- newopts = ''
- @trace_var.each{|e|
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- }
- @trace_elem.each{|elem|
- @trace_elem[elem].each{|e|
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- }
- }
-
- newopts = newopts.to_s
- newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'vdelete',
- @id, @trace_opts, 'rb_var')
- end
-=end
- @trace_opts.replace(newopts)
- if @trace_opts != ''
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable', @id,
- @trace_opts, 'rb_var')
- end
-=end
- end
- end
-
- self
- end
-end
-
-class TkVarAccess<TkVariable
- def self.new(name, *args)
- if name.kind_of?(TkVariable)
- name.value = args[0] unless args.empty?
- return name
- end
-
- if v = TkVar_ID_TBL[name]
- v.value = args[0] unless args.empty?
- return v
- end
-
- super(name, *args)
- end
-
- def self.new_hash(name, *args)
- if name.kind_of?(TkVariable)
- unless name.is_hash?
- fail ArgumentError, "already exist as a scalar variable"
- end
- name.value = args[0] unless args.empty?
- return name
- end
-
- if v = TkVar_ID_TBL[name]
- unless v.is_hash?
- fail ArgumentError, "already exist as a scalar variable"
- end
- v.value = args[0] unless args.empty?
- return v
- end
-
- INTERP._invoke_without_enc('global', name)
- if args.empty? && INTERP._invoke_without_enc('array', 'exist', name) == '0'
- self.new(name, {}) # force creating
- else
- self.new(name, *args)
- end
- end
-
- def initialize(varname, val=nil)
- @id = varname
- TkVar_ID_TBL[@id] = self
-
- @var = @id
- @elem = nil
-
- @def_default = false
- @default_val = nil
-
- @trace_var = nil
- @trace_elem = nil
- @trace_opts = nil
-
- @type = nil
- var = self
- @element_type = Hash.new{|k,v| var.default_value_type }
-
- # is an element?
- if @id =~ /^([^(]+)\((.+)\)$/
- # is an element --> var == $1, elem == $2
- @var = $1
- @elem = $2
- end
-
- # teach Tk-ip that @id is global var
- INTERP._invoke_without_enc('global', @var)
-=begin
- begin
- INTERP._invoke_without_enc('global', @id)
- rescue => e
- if @id =~ /^(.+)\([^()]+\)$/
- # is an element --> varname == $1
- INTERP._invoke_without_enc('global', $1)
- else
- fail e
- end
- end
-=end
-
- if val
- if val.kind_of?(Hash)
- # assoc-array variable
- self[''] = 0
- self.clear
- end
- #s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"' #"
- #s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"' #"
- #INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s))
- #INTERP._set_global_var(@id, _toUTF8(_get_eval_string(val)))
- self.value = val
- end
- end
-end
-
-module Tk
- begin
- INTERP._invoke_without_enc('global', 'auto_path')
- auto_path = INTERP._invoke('set', 'auto_path')
- rescue => e
- begin
- INTERP._invoke_without_enc('global', 'env')
- auto_path = INTERP._invoke('set', 'env(TCLLIBPATH)')
- rescue => e
- auto_path = Tk::LIBRARY
- end
- end
-
- AUTO_PATH = TkVarAccess.new('auto_path', auto_path)
-
-=begin
- AUTO_OLDPATH = tk_split_simplelist(INTERP._invoke('set', 'auto_oldpath'))
- AUTO_OLDPATH.each{|s| s.freeze}
- AUTO_OLDPATH.freeze
-=end
-
- TCL_PACKAGE_PATH = TkVarAccess.new('tcl_pkgPath')
- PACKAGE_PATH = TCL_PACKAGE_PATH
-
- TCL_LIBRARY_PATH = TkVarAccess.new('tcl_libPath')
- LIBRARY_PATH = TCL_LIBRARY_PATH
-
- TCL_PRECISION = TkVarAccess.new('tcl_precision')
-end
diff --git a/ext/tk/lib/tk/virtevent.rb b/ext/tk/lib/tk/virtevent.rb
deleted file mode 100644
index d47e80aecd..0000000000
--- a/ext/tk/lib/tk/virtevent.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-#
-# tk/virtevent.rb : treats virtual events
-# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
-#
-require 'tk'
-
-class TkVirtualEvent<TkObject
- extend Tk
-
- TkCommandNames = ['event'.freeze].freeze
-
- TkVirtualEventID = ["VirtEvent".freeze, "00000".taint].freeze
- TkVirtualEventTBL = TkCore::INTERP.create_table
-
- TkCore::INTERP.init_ip_env{ TkVirtualEventTBL.clear }
-
- class PreDefVirtEvent<self
- def self.new(event, *sequences)
- if event =~ /^<(<.*>)>$/
- event = $1
- elsif event !~ /^<.*>$/
- event = '<' + event + '>'
- end
- if TkVirtualEvent::TkVirtualEventTBL.has_key?(event)
- TkVirtualEvent::TkVirtualEventTBL[event]
- else
- super(event, *sequences)
- end
- end
-
- def initialize(event, *sequences)
- @path = @id = event
- TkVirtualEvent::TkVirtualEventTBL[@id] = self
- add(*sequences)
- end
- end
-
- def TkVirtualEvent.getobj(event)
- obj = TkVirtualEventTBL[event]
- if obj
- obj
- else
- if tk_call_without_enc('event', 'info').index("<#{event}>")
- PreDefVirtEvent.new(event)
- else
- fail ArgumentError, "undefined virtual event '<#{event}>'"
- end
- end
- end
-
- def TkVirtualEvent.info
- tk_call_without_enc('event', 'info').split(/\s+/).collect!{|seq|
- TkVirtualEvent.getobj(seq[1..-2])
- }
- end
-
- def initialize(*sequences)
- # @path = @id = '<' + TkVirtualEventID.join('') + '>'
- @path = @id = '<' + TkVirtualEventID.join(TkCore::INTERP._ip_id_) + '>'
- TkVirtualEventID[1].succ!
- add(*sequences)
- end
-
- def add(*sequences)
- if sequences != []
- tk_call_without_enc('event', 'add', "<#{@id}>",
- *(sequences.collect{|seq|
- "<#{tk_event_sequence(seq)}>"
- }) )
- TkVirtualEventTBL[@id] = self
- end
- self
- end
-
- def delete(*sequences)
- if sequences == []
- tk_call_without_enc('event', 'delete', "<#{@id}>")
- TkVirtualEventTBL.delete(@id)
- else
- tk_call_without_enc('event', 'delete', "<#{@id}>",
- *(sequences.collect{|seq|
- "<#{tk_event_sequence(seq)}>"
- }) )
- TkVirtualEventTBL.delete(@id) if info == []
- end
- self
- end
-
- def info
- tk_call_without_enc('event','info',"<#{@id}>").split(/\s+/).collect!{|seq|
- l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
- case (subseq)
- when /^<<[^<>]+>>$/
- TkVirtualEvent.getobj(subseq[1..-2])
- when /^<[^<>]+>$/
- subseq[1..-2]
- else
- subseq.split('')
- end
- }.flatten
- (l.size == 1) ? l[0] : l
- }
- end
-end
-
-TkNamedVirtualEvent = TkVirtualEvent::PreDefVirtEvent
diff --git a/ext/tk/lib/tk/winfo.rb b/ext/tk/lib/tk/winfo.rb
deleted file mode 100644
index c649b4a0c9..0000000000
--- a/ext/tk/lib/tk/winfo.rb
+++ /dev/null
@@ -1,392 +0,0 @@
-#
-# tk/winfo.rb : methods for winfo command
-#
-module TkWinfo
-end
-
-require 'tk'
-
-module TkWinfo
- include Tk
- extend Tk
-
- TkCommandNames = ['winfo'.freeze].freeze
-
- def TkWinfo.atom(name, win=nil)
- if win
- number(tk_call_without_enc('winfo', 'atom', '-displayof', win,
- _get_eval_enc_str(name)))
- else
- number(tk_call_without_enc('winfo', 'atom', _get_eval_enc_str(name)))
- end
- end
- def winfo_atom(name)
- TkWinfo.atom(name, self)
- end
-
- def TkWinfo.atomname(id, win=nil)
- if win
- _fromUTF8(tk_call_without_enc('winfo', 'atomname',
- '-displayof', win, id))
- else
- _fromUTF8(tk_call_without_enc('winfo', 'atomname', id))
- end
- end
- def winfo_atomname(id)
- TkWinfo.atomname(id, self)
- end
-
- def TkWinfo.cells(win)
- number(tk_call_without_enc('winfo', 'cells', win))
- end
- def winfo_cells
- TkWinfo.cells self
- end
-
- def TkWinfo.children(win)
- list(tk_call_without_enc('winfo', 'children', win))
- end
- def winfo_children
- TkWinfo.children self
- end
-
- def TkWinfo.classname(win)
- tk_call_without_enc('winfo', 'class', win)
- end
- def winfo_classname
- TkWinfo.classname self
- end
- alias winfo_class winfo_classname
-
- def TkWinfo.colormapfull(win)
- bool(tk_call_without_enc('winfo', 'colormapfull', win))
- end
- def winfo_colormapfull
- TkWinfo.colormapfull self
- end
-
- def TkWinfo.containing(rootX, rootY, win=nil)
- if win
- window(tk_call_without_enc('winfo', 'containing',
- '-displayof', win, rootX, rootY))
- else
- window(tk_call_without_enc('winfo', 'containing', rootX, rootY))
- end
- end
- def winfo_containing(x, y)
- TkWinfo.containing(x, y, self)
- end
-
- def TkWinfo.depth(win)
- number(tk_call_without_enc('winfo', 'depth', win))
- end
- def winfo_depth
- TkWinfo.depth self
- end
-
- def TkWinfo.exist?(win)
- bool(tk_call_without_enc('winfo', 'exists', win))
- end
- def winfo_exist?
- TkWinfo.exist? self
- end
-
- def TkWinfo.fpixels(win, dist)
- number(tk_call_without_enc('winfo', 'fpixels', win, dist))
- end
- def winfo_fpixels(dist)
- TkWinfo.fpixels self, dist
- end
-
- def TkWinfo.geometry(win)
- tk_call_without_enc('winfo', 'geometry', win)
- end
- def winfo_geometry
- TkWinfo.geometry self
- end
-
- def TkWinfo.height(win)
- number(tk_call_without_enc('winfo', 'height', win))
- end
- def winfo_height
- TkWinfo.height self
- end
-
- def TkWinfo.id(win)
- tk_call_without_enc('winfo', 'id', win)
- end
- def winfo_id
- TkWinfo.id self
- end
-
- def TkWinfo.interps(win=nil)
- if win
- #tk_split_simplelist(tk_call_without_enc('winfo', 'interps',
- # '-displayof', win))
- tk_split_simplelist(tk_call_without_enc('winfo', 'interps',
- '-displayof', win),
- false, true)
- else
- #tk_split_simplelist(tk_call_without_enc('winfo', 'interps'))
- tk_split_simplelist(tk_call_without_enc('winfo', 'interps'),
- false, true)
- end
- end
- def winfo_interps
- TkWinfo.interps self
- end
-
- def TkWinfo.mapped?(win)
- bool(tk_call_without_enc('winfo', 'ismapped', win))
- end
- def winfo_mapped?
- TkWinfo.mapped? self
- end
-
- def TkWinfo.manager(win)
- tk_call_without_enc('winfo', 'manager', win)
- end
- def winfo_manager
- TkWinfo.manager self
- end
-
- def TkWinfo.appname(win)
- tk_call('winfo', 'name', win)
- end
- def winfo_appname
- TkWinfo.appname self
- end
-
- def TkWinfo.parent(win)
- window(tk_call_without_enc('winfo', 'parent', win))
- end
- def winfo_parent
- TkWinfo.parent self
- end
-
- def TkWinfo.widget(id, win=nil)
- if win
- window(tk_call_without_enc('winfo', 'pathname', '-displayof', win, id))
- else
- window(tk_call_without_enc('winfo', 'pathname', id))
- end
- end
- def winfo_widget(id)
- TkWinfo.widget id, self
- end
-
- def TkWinfo.pixels(win, dist)
- number(tk_call_without_enc('winfo', 'pixels', win, dist))
- end
- def winfo_pixels(dist)
- TkWinfo.pixels self, dist
- end
-
- def TkWinfo.reqheight(win)
- number(tk_call_without_enc('winfo', 'reqheight', win))
- end
- def winfo_reqheight
- TkWinfo.reqheight self
- end
-
- def TkWinfo.reqwidth(win)
- number(tk_call_without_enc('winfo', 'reqwidth', win))
- end
- def winfo_reqwidth
- TkWinfo.reqwidth self
- end
-
- def TkWinfo.rgb(win, color)
- list(tk_call_without_enc('winfo', 'rgb', win, color))
- end
- def winfo_rgb(color)
- TkWinfo.rgb self, color
- end
-
- def TkWinfo.rootx(win)
- number(tk_call_without_enc('winfo', 'rootx', win))
- end
- def winfo_rootx
- TkWinfo.rootx self
- end
-
- def TkWinfo.rooty(win)
- number(tk_call_without_enc('winfo', 'rooty', win))
- end
- def winfo_rooty
- TkWinfo.rooty self
- end
-
- def TkWinfo.screen(win)
- tk_call('winfo', 'screen', win)
- end
- def winfo_screen
- TkWinfo.screen self
- end
-
- def TkWinfo.screencells(win)
- number(tk_call_without_enc('winfo', 'screencells', win))
- end
- def winfo_screencells
- TkWinfo.screencells self
- end
-
- def TkWinfo.screendepth(win)
- number(tk_call_without_enc('winfo', 'screendepth', win))
- end
- def winfo_screendepth
- TkWinfo.screendepth self
- end
-
- def TkWinfo.screenheight (win)
- number(tk_call_without_enc('winfo', 'screenheight', win))
- end
- def winfo_screenheight
- TkWinfo.screenheight self
- end
-
- def TkWinfo.screenmmheight(win)
- number(tk_call_without_enc('winfo', 'screenmmheight', win))
- end
- def winfo_screenmmheight
- TkWinfo.screenmmheight self
- end
-
- def TkWinfo.screenmmwidth(win)
- number(tk_call_without_enc('winfo', 'screenmmwidth', win))
- end
- def winfo_screenmmwidth
- TkWinfo.screenmmwidth self
- end
-
- def TkWinfo.screenvisual(win)
- tk_call_without_enc('winfo', 'screenvisual', win)
- end
- def winfo_screenvisual
- TkWinfo.screenvisual self
- end
-
- def TkWinfo.screenwidth(win)
- number(tk_call_without_enc('winfo', 'screenwidth', win))
- end
- def winfo_screenwidth
- TkWinfo.screenwidth self
- end
-
- def TkWinfo.server(win)
- tk_call('winfo', 'server', win)
- end
- def winfo_server
- TkWinfo.server self
- end
-
- def TkWinfo.toplevel(win)
- window(tk_call_without_enc('winfo', 'toplevel', win))
- end
- def winfo_toplevel
- TkWinfo.toplevel self
- end
-
- def TkWinfo.visual(win)
- tk_call_without_enc('winfo', 'visual', win)
- end
- def winfo_visual
- TkWinfo.visual self
- end
-
- def TkWinfo.visualid(win)
- tk_call_without_enc('winfo', 'visualid', win)
- end
- def winfo_visualid
- TkWinfo.visualid self
- end
-
- def TkWinfo.visualsavailable(win, includeids=false)
- if includeids
- list(tk_call_without_enc('winfo', 'visualsavailable',
- win, "includeids"))
- else
- list(tk_call_without_enc('winfo', 'visualsavailable', win))
- end
- end
- def winfo_visualsavailable(includeids=false)
- TkWinfo.visualsavailable self, includeids
- end
-
- def TkWinfo.vrootheight(win)
- number(tk_call_without_enc('winfo', 'vrootheight', win))
- end
- def winfo_vrootheight
- TkWinfo.vrootheight self
- end
-
- def TkWinfo.vrootwidth(win)
- number(tk_call_without_enc('winfo', 'vrootwidth', win))
- end
- def winfo_vrootwidth
- TkWinfo.vrootwidth self
- end
-
- def TkWinfo.vrootx(win)
- number(tk_call_without_enc('winfo', 'vrootx', win))
- end
- def winfo_vrootx
- TkWinfo.vrootx self
- end
-
- def TkWinfo.vrooty(win)
- number(tk_call_without_enc('winfo', 'vrooty', win))
- end
- def winfo_vrooty
- TkWinfo.vrooty self
- end
-
- def TkWinfo.width(win)
- number(tk_call_without_enc('winfo', 'width', win))
- end
- def winfo_width
- TkWinfo.width self
- end
-
- def TkWinfo.x(win)
- number(tk_call_without_enc('winfo', 'x', win))
- end
- def winfo_x
- TkWinfo.x self
- end
-
- def TkWinfo.y(win)
- number(tk_call_without_enc('winfo', 'y', win))
- end
- def winfo_y
- TkWinfo.y self
- end
-
- def TkWinfo.viewable(win)
- bool(tk_call_without_enc('winfo', 'viewable', win))
- end
- def winfo_viewable
- TkWinfo.viewable self
- end
-
- def TkWinfo.pointerx(win)
- number(tk_call_without_enc('winfo', 'pointerx', win))
- end
- def winfo_pointerx
- TkWinfo.pointerx self
- end
-
- def TkWinfo.pointery(win)
- number(tk_call_without_enc('winfo', 'pointery', win))
- end
- def winfo_pointery
- TkWinfo.pointery self
- end
-
- def TkWinfo.pointerxy(win)
- list(tk_call_without_enc('winfo', 'pointerxy', win))
- end
- def winfo_pointerxy
- TkWinfo.pointerxy self
- end
-end
diff --git a/ext/tk/lib/tk/winpkg.rb b/ext/tk/lib/tk/winpkg.rb
deleted file mode 100644
index 737fb959b5..0000000000
--- a/ext/tk/lib/tk/winpkg.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-#
-# tk/winpkg.rb : methods for Tcl/Tk packages for Microsoft Windows
-# 2000/11/22 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
-#
-# ATTENTION !!
-# This is NOT TESTED. Because I have no test-environment.
-#
-require 'tk'
-
-module TkWinDDE
- extend Tk
- extend TkWinDDE
-
- TkCommandNames = ['dde'.freeze].freeze
-
- PACKAGE_NAME = 'dde'.freeze
- def self.package_name
- PACKAGE_NAME
- end
-
- if self.const_defined? :FORCE_VERSION
- tk_call_without_enc('package', 'require', 'dde', FORCE_VERSION)
- else
- tk_call_without_enc('package', 'require', 'dde')
- end
-
- #def servername(topic=None)
- # tk_call('dde', 'servername', topic)
- #end
- def servername(*args)
- if args.size == 0
- tk_call('dde', 'servername')
- else
- if args[-1].kind_of?(Hash) # dde 1.2 +
- keys = _symbolkey2str(args.pop)
- force = (keys.delete('force'))? '-force': None
- exact = (keys.delete('exact'))? '-exact': None
- if keys.size == 0
- tk_call('dde', 'servername', force, exact)
- elsif args.size == 0
- tk_call('dde', 'servername', force, exact, *hash_kv(keys))
- else
- tk_call('dde', 'servername', force, exact,
- *((hash_kv(keys) << '--') + args))
- end
- else
- tk_call('dde', 'servername', *args)
- end
- end
- end
-
- def execute(service, topic, data)
- tk_call('dde', 'execute', service, topic, data)
- end
-
- def async_execute(service, topic, data)
- tk_call('dde', '-async', 'execute', service, topic, data)
- end
-
- def poke(service, topic, item, data)
- tk_call('dde', 'poke', service, topic, item, data)
- end
-
- def request(service, topic, item)
- tk_call('dde', 'request', service, topic, item)
- end
-
- def binary_request(service, topic, item)
- tk_call('dde', 'request', '-binary', service, topic, item)
- end
-
- def services(service, topic)
- tk_call('dde', 'services', service, topic)
- end
-
- def eval(topic, cmd, *args)
- tk_call('dde', 'eval', topic, cmd, *args)
- end
-
- def async_eval(topic, cmd, *args)
- tk_call('dde', 'eval', -async, topic, cmd, *args)
- end
-
- module_function :servername, :execute, :async_execute,
- :poke, :request, :services, :eval
-end
-
-module TkWinRegistry
- extend Tk
- extend TkWinRegistry
-
- TkCommandNames = ['registry'.freeze].freeze
-
- if self.const_defined? :FORCE_VERSION
- tk_call('package', 'require', 'registry', FORCE_VERSION)
- else
- tk_call('package', 'require', 'registry')
- end
-
- def broadcast(keynam, timeout=nil)
- if timeout
- tk_call('registry', 'broadcast', keynam, '-timeout', timeout)
- else
- tk_call('registry', 'broadcast', keynam)
- end
- end
-
- def delete(keynam, valnam=None)
- tk_call('registry', 'delete', keynam, valnam)
- end
-
- def get(keynam, valnam)
- tk_call('registry', 'get', keynam, valnam)
- end
-
- def keys(keynam, pattern=nil)
- lst = tk_split_simplelist(tk_call('registry', 'keys', keynam))
- if pattern
- lst.find_all{|key| key =~ pattern}
- else
- lst
- end
- end
-
- def set(keynam, valnam=None, data=None, dattype=None)
- tk_call('registry', 'set', keynam, valnam, data, dattype)
- end
-
- def type(keynam, valnam)
- tk_call('registry', 'type', keynam, valnam)
- end
-
- def values(keynam, pattern=nil)
- lst = tk_split_simplelist(tk_call('registry', 'values', keynam))
- if pattern
- lst.find_all{|val| val =~ pattern}
- else
- lst
- end
- end
-
- module_function :delete, :get, :keys, :set, :type, :values
-end
diff --git a/ext/tk/lib/tk/wm.rb b/ext/tk/lib/tk/wm.rb
deleted file mode 100644
index 1f432a3848..0000000000
--- a/ext/tk/lib/tk/wm.rb
+++ /dev/null
@@ -1,360 +0,0 @@
-#
-# tk/wm.rb : methods for wm command
-#
-require 'tk'
-
-module Tk
- module Wm
- include TkComm
-
- TkCommandNames = ['wm'.freeze].freeze
-
- TOPLEVEL_METHODCALL_OPTKEYS = {}
-
- def aspect(*args)
- if args.length == 0
- list(tk_call_without_enc('wm', 'aspect', path))
- else
- args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call('wm', 'aspect', path, *args)
- self
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['aspect'] = 'aspect'
-
- def attributes(slot=nil,value=None)
- if slot == nil
- lst = tk_split_list(tk_call('wm', 'attributes', path))
- info = {}
- while key = lst.shift
- info[key[1..-1]] = lst.shift
- end
- info
- elsif slot.kind_of? Hash
- tk_call('wm', 'attributes', path, *hash_kv(slot))
- self
- elsif value == None
- tk_call('wm', 'attributes', path, "-#{slot}")
- else
- tk_call('wm', 'attributes', path, "-#{slot}", value)
- self
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['attributes'] = 'attributes'
-
- def client(name=None)
- if name == None
- tk_call('wm', 'client', path)
- else
- name = '' if name == nil
- tk_call('wm', 'client', path, name)
- self
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['client'] = 'client'
-
- def colormapwindows(*args)
- if args.size == 0
- list(tk_call_without_enc('wm', 'colormapwindows', path))
- else
- args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'colormapwindows', path, *args)
- self
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['colormapwindows'] = 'colormapwindows'
-
- def wm_command(value=nil)
- if value
- tk_call('wm', 'command', path, value)
- self
- else
- #procedure(tk_call('wm', 'command', path))
- tk_call('wm', 'command', path)
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['wm_command'] = 'wm_command'
-
- def deiconify(ex = true)
- if ex
- tk_call_without_enc('wm', 'deiconify', path)
- else
- self.iconify
- end
- self
- end
-
- def focusmodel(mode = nil)
- if mode
- tk_call_without_enc('wm', 'focusmodel', path, mode)
- self
- else
- tk_call_without_enc('wm', 'focusmodel', path)
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['focusmodel'] = 'focusmodel'
-
- def frame
- tk_call_without_enc('wm', 'frame', path)
- end
-
- def geometry(geom=nil)
- if geom
- tk_call_without_enc('wm', 'geometry', path, geom)
- self
- else
- tk_call_without_enc('wm', 'geometry', path)
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['geometry'] = 'geometry'
-
- def wm_grid(*args)
- if args.size == 0
- list(tk_call_without_enc('wm', 'grid', path))
- else
- args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'grid', path, *args)
- self
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['wm_grid'] = 'wm_grid'
-
- def group(leader = nil)
- if leader
- tk_call('wm', 'group', path, leader)
- self
- else
- window(tk_call('wm', 'group', path))
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['group'] = 'group'
-
- def iconbitmap(bmp=nil)
- if bmp
- tk_call_without_enc('wm', 'iconbitmap', path, bmp)
- self
- else
- image_obj(tk_call_without_enc('wm', 'iconbitmap', path))
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['iconbitmap'] = 'iconbitmap'
-
- def iconphoto(*imgs)
- if imgs.empty?
- @wm_iconphoto = nil unless defined? @wm_iconphoto
- return @wm_iconphoto
- end
-
- imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array)
- tk_call_without_enc('wm', 'iconphoto', path, *imgs)
- @wm_iconphoto = imgs
- self
- end
- TOPLEVEL_METHODCALL_OPTKEYS['iconphoto'] = 'iconphoto'
-
- def iconphoto_default(*imgs)
- imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array)
- tk_call_without_enc('wm', 'iconphoto', path, '-default', *imgs)
- self
- end
-
- def iconify(ex = true)
- if ex
- tk_call_without_enc('wm', 'iconify', path)
- else
- self.deiconify
- end
- self
- end
-
- def iconmask(bmp=nil)
- if bmp
- tk_call_without_enc('wm', 'iconmask', path, bmp)
- self
- else
- image_obj(tk_call_without_enc('wm', 'iconmask', path))
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['iconmask'] = 'iconmask'
-
- def iconname(name=nil)
- if name
- tk_call('wm', 'iconname', path, name)
- self
- else
- tk_call('wm', 'iconname', path)
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['iconname'] = 'iconname'
-
- def iconposition(*args)
- if args.size == 0
- list(tk_call_without_enc('wm', 'iconposition', path))
- else
- args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'iconposition', path, *args)
- self
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['iconposition'] = 'iconposition'
-
- def iconwindow(win = nil)
- if win
- tk_call_without_enc('wm', 'iconwindow', path, win)
- self
- else
- w = tk_call_without_enc('wm', 'iconwindow', path)
- (w == '')? nil: window(w)
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['iconwindow'] = 'iconwindow'
-
- def maxsize(*args)
- if args.size == 0
- list(tk_call_without_enc('wm', 'maxsize', path))
- else
- args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'maxsize', path, *args)
- self
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['maxsize'] = 'maxsize'
-
- def minsize(*args)
- if args.size == 0
- list(tk_call_without_enc('wm', 'minsize', path))
- else
- args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'minsize', path, *args)
- self
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['minsize'] = 'minsize'
-
- def overrideredirect(mode=None)
- if mode == None
- bool(tk_call_without_enc('wm', 'overrideredirect', path))
- else
- tk_call_without_enc('wm', 'overrideredirect', path, mode)
- self
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['overrideredirect'] = 'overrideredirect'
-
- def positionfrom(who=None)
- if who == None
- r = tk_call_without_enc('wm', 'positionfrom', path)
- (r == "")? nil: r
- else
- tk_call_without_enc('wm', 'positionfrom', path, who)
- self
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['positionfrom'] = 'positionfrom'
-
- def protocol(name=nil, cmd=nil, &b)
- if cmd
- tk_call_without_enc('wm', 'protocol', path, name, cmd)
- self
- elsif b
- tk_call_without_enc('wm', 'protocol', path, name, proc(&b))
- self
- elsif name
- result = tk_call_without_enc('wm', 'protocol', path, name)
- (result == "")? nil : tk_tcl2ruby(result)
- else
- tk_split_simplelist(tk_call_without_enc('wm', 'protocol', path))
- end
- end
-
- def protocols(kv=nil)
- unless kv
- ret = {}
- self.protocol.each{|name|
- ret[name] = self.protocol(name)
- }
- return ret
- end
-
- unless kv.kind_of?(Hash)
- fail ArgumentError, 'expect a hash of protocol=>command'
- end
- kv.each{|k, v| self.protocol(k, v)}
- self
- end
- TOPLEVEL_METHODCALL_OPTKEYS['protocols'] = 'protocols'
-
- def resizable(*args)
- if args.length == 0
- list(tk_call_without_enc('wm', 'resizable', path)).collect{|e| bool(e)}
- else
- args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'resizable', path, *args)
- self
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['resizable'] = 'resizable'
-
- def sizefrom(who=None)
- if who == None
- r = tk_call_without_enc('wm', 'sizefrom', path)
- (r == "")? nil: r
- else
- tk_call_without_enc('wm', 'sizefrom', path, who)
- self
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['sizefrom'] = 'sizefrom'
-
- def stackorder
- list(tk_call('wm', 'stackorder', path))
- end
-
- def stackorder_isabove(win)
- bool(tk_call('wm', 'stackorder', path, 'isabove', win))
- end
-
- def stackorder_isbelow(win)
- bool(tk_call('wm', 'stackorder', path, 'isbelow', win))
- end
-
- def state(st=nil)
- if st
- tk_call_without_enc('wm', 'state', path, st)
- self
- else
- tk_call_without_enc('wm', 'state', path)
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['state'] = 'state'
-
- def title(str=nil)
- if str
- tk_call('wm', 'title', path, str)
- self
- else
- tk_call('wm', 'title', path)
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['title'] = 'title'
-
- def transient(master=nil)
- if master
- tk_call_without_enc('wm', 'transient', path, master)
- self
- else
- window(tk_call_without_enc('wm', 'transient', path))
- end
- end
- TOPLEVEL_METHODCALL_OPTKEYS['transient'] = 'transient'
-
- def withdraw(ex = true)
- if ex
- tk_call_without_enc('wm', 'withdraw', path)
- else
- self.deiconify
- end
- self
- end
- end
-end
diff --git a/ext/tk/lib/tk/xim.rb b/ext/tk/lib/tk/xim.rb
deleted file mode 100644
index 0ac8559bb9..0000000000
--- a/ext/tk/lib/tk/xim.rb
+++ /dev/null
@@ -1,122 +0,0 @@
-#
-# tk/xim.rb : control imput_method
-#
-require 'tk'
-
-module TkXIM
- include Tk
- extend Tk
-
- TkCommandNames = ['imconfigure'.freeze].freeze
-
- def TkXIM.useinputmethods(value = None, win = nil)
- if value == None
- if win
- bool(tk_call_without_enc('tk', 'useinputmethods',
- '-displayof', win))
- else
- bool(tk_call_without_enc('tk', 'useinputmethods'))
- end
- else
- if win
- bool(tk_call_without_enc('tk', 'useinputmethods',
- '-displayof', win, value))
- else
- bool(tk_call_without_enc('tk', 'useinputmethods', value))
- end
- end
- end
-
- def TkXIM.useinputmethods_displayof(win, value = None)
- TkXIM.useinputmethods(value, win)
- end
-
- def TkXIM.caret(win, keys=nil)
- if keys
- tk_call_without_enc('tk', 'caret', win, *hash_kv(keys))
- self
- else
- lst = tk_split_list(tk_call_without_enc('tk', 'caret', win))
- info = {}
- while key = lst.shift
- info[key[1..-1]] = lst.shift
- end
- info
- end
- end
-
- def TkXIM.configure(win, slot, value=None)
- begin
- if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
- if slot.kind_of? Hash
- tk_call('imconfigure', win, *hash_kv(slot))
- else
- tk_call('imconfigure', win, "-#{slot}", value)
- end
- end
- rescue
- end
- end
-
- def TkXIM.configinfo(win, slot=nil)
- if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
- begin
- if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
- if slot
- conf = tk_split_list(tk_call('imconfigure', win, "-#{slot}"))
- conf[0] = conf[0][1..-1]
- conf
- else
- tk_split_list(tk_call('imconfigure', win)).collect{|conf|
- conf[0] = conf[0][1..-1]
- conf
- }
- end
- else
- []
- end
- rescue
- []
- end
- else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
- TkXIM.current_configinfo(win, slot)
- end
- end
-
- def TkXIM.current_configinfo(win, slot=nil)
- begin
- if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
- if slot
- conf = tk_split_list(tk_call('imconfigure', win, "-#{slot}"))
- { conf[0][1..-1] => conf[1] }
- else
- ret = {}
- tk_split_list(tk_call('imconfigure', win)).each{|conf|
- ret[conf[0][1..-1]] = conf[1]
- }
- ret
- end
- else
- {}
- end
- rescue
- {}
- end
- end
-
- def useinputmethods(value=None)
- TkXIM.useinputmethods(value, self)
- end
-
- def caret(keys=nil)
- TkXIM.caret(self, keys=nil)
- end
-
- def imconfigure(slot, value=None)
- TkXIM.configure(self, slot, value)
- end
-
- def imconfiginfo(slot=nil)
- TkXIM.configinfo(self, slot)
- end
-end
diff --git a/ext/tk/lib/tkafter.rb b/ext/tk/lib/tkafter.rb
deleted file mode 100644
index f65945884c..0000000000
--- a/ext/tk/lib/tkafter.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# tkafter.rb - load tk/after.rb
-#
-require 'tk/timer'
diff --git a/ext/tk/lib/tkbgerror.rb b/ext/tk/lib/tkbgerror.rb
deleted file mode 100644
index deba7a57fa..0000000000
--- a/ext/tk/lib/tkbgerror.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# tkbgerror.rb - load tk/bgerror.rb
-#
-require 'tk/bgerror'
diff --git a/ext/tk/lib/tkcanvas.rb b/ext/tk/lib/tkcanvas.rb
deleted file mode 100644
index 9524614291..0000000000
--- a/ext/tk/lib/tkcanvas.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# tkcanvas.rb - load tk/canvas.rb
-#
-require 'tk/canvas'
diff --git a/ext/tk/lib/tkclass.rb b/ext/tk/lib/tkclass.rb
deleted file mode 100644
index 87f5acc453..0000000000
--- a/ext/tk/lib/tkclass.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# tkclass.rb - Tk classes
-# Date: 2000/11/27 09:23:36
-# by Yukihiro Matsumoto <matz@caelum.co.jp>
-#
-# $Id$
-
-require "tk"
-
-TopLevel = TkToplevel
-Frame = TkFrame
-Label = TkLabel
-Button = TkButton
-Radiobutton = TkRadioButton
-Checkbutton = TkCheckButton
-Message = TkMessage
-Entry = TkEntry
-Spinbox = TkSpinbox
-Text = TkText
-Scale = TkScale
-Scrollbar = TkScrollbar
-Listbox = TkListbox
-Menu = TkMenu
-Menubutton = TkMenubutton
-Canvas = TkCanvas
-Arc = TkcArc
-Bitmap = TkcBitmap
-Line = TkcLine
-Oval = TkcOval
-Polygon = TkcPolygon
-Rectangle = TkcRectangle
-TextItem = TkcText
-WindowItem = TkcWindow
-BitmapImage = TkBitmapImage
-PhotoImage = TkPhotoImage
-Selection = TkSelection
-Winfo = TkWinfo
-Pack = TkPack
-Grid = TkGrid
-Place = TkPlace
-Variable = TkVariable
-Font = TkFont
-VirtualEvent = TkVirtualEvent
-
-def Mainloop
- Tk.mainloop
-end
diff --git a/ext/tk/lib/tkconsole.rb b/ext/tk/lib/tkconsole.rb
deleted file mode 100644
index 9960ddb8ac..0000000000
--- a/ext/tk/lib/tkconsole.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# tkconsole.rb - load tk/console.rb
-#
-require 'tk/console'
diff --git a/ext/tk/lib/tkdialog.rb b/ext/tk/lib/tkdialog.rb
deleted file mode 100644
index bec5e5d29a..0000000000
--- a/ext/tk/lib/tkdialog.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# tkdialog.rb - load tk/dialog.rb
-#
-require 'tk/dialog'
diff --git a/ext/tk/lib/tkentry.rb b/ext/tk/lib/tkentry.rb
deleted file mode 100644
index 2dcfcab5da..0000000000
--- a/ext/tk/lib/tkentry.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# tkentry.rb - load tk/entry.rb
-#
-require 'tk/entry'
diff --git a/ext/tk/lib/tkextlib/ICONS.rb b/ext/tk/lib/tkextlib/ICONS.rb
deleted file mode 100644
index 18d84c05e9..0000000000
--- a/ext/tk/lib/tkextlib/ICONS.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# ICONS support
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-# call setup script for general 'tkextlib' libraries
-require 'tkextlib/setup.rb'
-
-# call setup script
-require 'tkextlib/ICONS/setup.rb'
-
-# load library
-require 'tkextlib/ICONS/icons'
diff --git a/ext/tk/lib/tkextlib/ICONS/icons.rb b/ext/tk/lib/tkextlib/ICONS/icons.rb
deleted file mode 100644
index b430bae55d..0000000000
--- a/ext/tk/lib/tkextlib/ICONS/icons.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-#
-# tkextlib/ICONS/icons.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-
-# call setup script for general 'tkextlib' libraries
-require 'tkextlib/setup.rb'
-
-# call setup script
-require 'tkextlib/ICONS/setup.rb'
-
-# TkPackage.require('icons', '1.0')
-TkPackage.require('icons')
-
-module Tk
- class ICONS < TkImage
- extend Tk
-
- PACKAGE_NAME = 'icons'.freeze
- def self.package_name
- PACKAGE_NAME
- end
-
- def self.package_version
- begin
- TkPackage.require('icons')
- rescue
- ''
- end
- end
-
- def self.create(*args) # icon, icon, ..., ?option=>value, ...?
- if args[-1].kind_of?(Hash)
- keys = args.pop
- icons = simplelist(tk_call('::icons::icons', 'create',
- *(hash_kv(keys) << (args.flatten))))
- else
- icons = simplelist(tk_call('::icons::icons', 'create',
- args.flatten))
- end
-
- icons.collect{|icon| self.new(icon, :without_creating=>true)}
- end
-
- def self.delete(*icons) # icon, icon, ...
- icons = icons.flatten
- return if icons.empty?
- icons.map!{|icon|
- if icon.kind_of?(Tk::ICONS)
- Tk_IMGTBL.delete(icon.path)
- icon.name
- elsif icon.to_s =~ /^::icon::(.*)/
- name = $1
- Tk_IMGTBL.delete(icon)
- name
- else
- Tk_IMGTBL.delete("::icon::#{icon}")
- icon
- end
- }
- tk_call('::icons::icons', 'delete', icons)
- end
-
- def self.query(*args) # icon, icon, ..., ?option=>value, ...?
- if args[-1].kind_of?(Hash)
- keys = args.pop
- simplelist(tk_call('::icons::icons', 'query',
- *(hash_kv(keys) << (args.flatten))))
- else
- simplelist(tk_call('::icons::icons', 'query', args.flatten))
- end . map{|inf| list(inf) }
- end
-
- ##########################################
-
- class << self
- alias _new new
-
- def new(name, keys=nil)
- if obj = Tk_IMGTBL["::icon::#{name}"]
- if keys
- keys = _symbolkey2str(keys)
- unless keys.delete('without_creating')
- tk_call('::icons::icons', 'create', *(hash_kv(keys) << obj.name))
- end
- end
- else
- obj = _new(name, keys)
- end
- obj
- end
- end
-
- ##########################################
-
- def initialize(name, keys=nil)
- if name.kind_of?(String) && name =~ /^::icon::(.+)$/
- @name = $1
- @path = name
- else
- @name = name.to_s
- @path = "::icon::#{@name}"
- end
- keys = _symbolkey2str(keys)
- unless keys.delete('without_creating')
- tk_call('::icons::icons', 'create', *(hash_kv(keys) << @name))
- end
- Tk_IMGTBL[@path] = self
- end
-
- def name
- @name
- end
-
- def delete
- Tk_IMGTBL.delete(@path)
- tk_call('::icons::icons', 'delete', @name)
- self
- end
-
- def query(keys={})
- list(simplelist(tk_call('::icons::icons', 'query',
- *(hash_kv(keys) << @name))
- )[0])
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/ICONS/setup.rb b/ext/tk/lib/tkextlib/ICONS/setup.rb
deleted file mode 100644
index ce0f0bd4d4..0000000000
--- a/ext/tk/lib/tkextlib/ICONS/setup.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# setup.rb -- setup script before calling TkPackage.require()
-#
-# If you need some setup operations (for example, add a library path
-# to the library search path) before using Tcl/Tk library packages
-# wrapped by Ruby scripts in this directory, please write the setup
-# operations in this file.
-#
diff --git a/ext/tk/lib/tkextlib/SUPPORT_STATUS b/ext/tk/lib/tkextlib/SUPPORT_STATUS
deleted file mode 100644
index 8d7b6fc44a..0000000000
--- a/ext/tk/lib/tkextlib/SUPPORT_STATUS
+++ /dev/null
@@ -1,196 +0,0 @@
-
- [ current support status of Tcl/Tk extensions ]
-
- *******<<< RELEASE_DATE of the libraries : 2005/12/11 >>>*******
-
-The following list shows *CURRENT* status when this file was modifyed
-at last. If you want to add other Tcl/Tk extensions to the planed list
-(or change its status position), please request them at the ruby-talk,
-ruby-list, or ruby-dev ML. Although we cannot promise to support your
-requests, we'll try to do.
-
-If you want to check that wrapper libraries are ready to use on your
-environment, please execute 'pkg_checker.rb' with no arguments. The
-script may give you some hints about that.
-
-
- ***** IMPORTANT NOTE **********************************************
-
- 'support' means that Ruby/Tk's wrapper libraries are released.
- 'not support' does *NOT* mean that the extension doesn't work
- on Ruby/Tk.
-
- The version number of each extension means the latest version
- which is checked its feature. That is, it does NOT means only
- version of working. Library files maybe include some features
- which is included in the former version but removed from the
- latest, and maybe able to support the later version then the
- shown version.
-
- Even if the status of the extension is 'not support', you can
- control the functions/widgets of the extension without wrapper
- libraries by Tk.tk_call(), Tk.ip_eval(), and so on.
-
- If you cannot use installed Tcl/Tk extension, please check the
- followings.
-
- (1) On your Tcl/Tk, does the extention work?
-
- (2) Do DLL libraries of the extension exist on DLL load-path?
- (See also "<ruby archive>/ext/tcltklib/README.ActiveTcl")
-
- (3) Is the Tcl library directory of the extension included in
- library search-path of the Tcl interpreter linked Ruby/Tk?
-
- The check results may request you to do some setup operations
- before using the extension. If so, then please write the step
- of setup oprations into the "setup.rb" file in the directory
- of the wrapper libraries for the extention (It is the wrapper
- libraries have the standard structure of the libraries in this
- directory). The "setup" file is required before requiring the
- Tcl library package (TkPackage.require(<libname>)).
-
- *******************************************************************
-
-
-===< support with some examples (may be beta quality) >=======================
-
-Tcllib 1.8
-Tklib 0.4.1 http://sf.net/projects/tcllib ==> tcllib
-
-IWidgets 4.0.2 http://sf.net/projects/incrTcl ==> iwidgets
-
-BWidgets 1.7 http://sf.net/projects/tcllib ==> bwidget
-
-TkTable 2.9 http://sf.net/projects/tktable ==> tktable
- * see also <http://www.korus.hu/~fery/ruby/tktable.rb>
- written by Ferenc Engard (ferenc@engard.hu)
-
-vu 2.3.0 http://tktable.sourceforge.net ==> vu
-
-TkHTML 2.0 http://www.hwaci.com/sw/tkhtml/index.html ==> tkHTML
-
-ICONS 1.0 http://www.satisoft.com/tcltk/icons/ ==> ICONS
-
-TkImg 1.3 http://sf.net/projects/tkimg ==> tkimg
-
-
-BLT 2.4z http://sourceforge.net/projects/blt
- * see also tcltk-ext library on RAA
- (http://raa.ruby-lang.org/)
- ==> blt
-
-TkTreeCtrl CVS/Hd(2005-12-02)
- http://tktreectrl.sourceforge.net/ ==> treectrl
-
-Tile CVS/Hd(2005-12-07)
- http://tktable.sourceforge.net/tile/ ==> tile
-
-
-
-===< support (may be alpha or beta quality) >=================================
-
-IncrTcl CVS/Hd(2005-02-14)
- http://sf.net/projects/incrTcl ==> itcl, itk
-
-TclX CVS/Hd(2005-02-07)
- http://sf.net/projects/tclx
- ==> tclx (partial support; infox command and
- XPG/3 message catalogs only)
-
-Trofs 0.4.3 http://math.nist.gov/~DPorter/tcltk/trofs/
-
-
-
-===< possibly available (not tested; alpha quality) >=========================
-
-winico 0.6
- http://tktable.sourceforge.net
- ==> winico (win32 only)
-
-TkTrans latest(2004-10-11)
- http://www2.cmp.uea.ac.uk/~fuzz/tktrans/default.html
- ==> tktrans (win32 only)
-
-TkDND 1.0a2 http://sourceforge.net/projects/tkdnd ==> tkDND
-
-
-
-===< plan to support (alpha quality libraries may be included) >==============
-
-GraphViz *** http://www.graphviz.org/
-
-Tkgeomap *** http://tkgeomap.sourceforge.net/index.html
-
-
-
-===< not determined to supprt or not >========================================
-
-Tix *** http://tixlibrary.sourceforge.net/
- * see also tcltk-ext library on RAA
- (http://raa.ruby-lang.org/)
-
-TkZinc *** http://www.tkzinc.org/
-
-Wbc *** http://home.t-online.de/home/csaba.nemethi/
-
-Mentry *** http://home.t-online.de/home/csaba.nemethi/
-
-Tablelist *** http://home.t-online.de/home/csaba.nemethi/
-
-ANIGIF *** http://cardtable.sourceforge.net/tcltk/
-
-IMG_ROTATE *** http://cardtable.sourceforge.net/tcltk/
-
-TclVfs *** http://sourceforge.net/projects/tclvfs/
-
-vfwtcl *** http://sourceforge.net/projects/avicaptcl
- * Win32 only
-
-multicast *** http://sourceforge.net/projects/avicaptcl
- * Win32 only
-
-XBit *** http://www.geocities.com/~chengye/
- * current implementation is for Windows only
-
-QuickTimeTcl *** http://hem.fyristorg.com/matben/qt/
- * works under Mac OS (8,9,X) or Windows
-
-
-
-===< may not support (already exist, out of Ruby/Tk scope, and so on) >=======
-
-TkCon *** http://sf.net/projects/tkcon
-
-Expect *** http://sf.net/projects/expect
-
-TclXML *** http://sf.net/projects/tclxml
-
-TclXSLT *** http://sf.net/projects/tclxml
-
-TclDOM *** http://sf.net/projects/tclxml
-
-TclSOAP *** http://sf.net/projects/tclsoap
-
-Snack *** http://www.speech.kth.se/~kare/snack2.2.tar.gz
- * use Snack for Ruby
- (see http://rbsnack.sourceforge.net/)
-
-Tcom *** http://www.vex.net/~cthuang/tcom/
-
-tDOM *** http://www.tdom.org
-
-Mk4tcl *** http://www.equi4.com/metakit/tcl.html
-
-Memchan *** http://memchan.sourceforge.net/
-
-XOTcl *** http://www.xotcl.org/
-
-
-===< tool (may not supprt) >==================================================
-
-tbcload/tclcompiler
- *** http://www.tcl.tk/software/tclpro/
-
-
-(End of List)
diff --git a/ext/tk/lib/tkextlib/blt.rb b/ext/tk/lib/tkextlib/blt.rb
deleted file mode 100644
index 8ac8605513..0000000000
--- a/ext/tk/lib/tkextlib/blt.rb
+++ /dev/null
@@ -1,187 +0,0 @@
-#
-# BLT support
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/variable'
-
-# call setup script for general 'tkextlib' libraries
-require 'tkextlib/setup.rb'
-
-# call setup script
-require 'tkextlib/blt/setup.rb'
-
-# load all image format handlers
-#TkPackage.require('BLT', '2.4')
-TkPackage.require('BLT')
-
-module Tk
- module BLT
- TkComm::TkExtlibAutoloadModule.unshift(self)
-
- extend TkCore
-
- VERSION = tk_call('set', 'blt_version')
- PATCH_LEVEL = tk_call('set', 'blt_patchLevel')
-
- begin
- lib = INTERP._invoke('set', 'blt_library')
- rescue
- lib = ''
- end
- LIBRARY = TkVarAccess.new('blt_library', lib)
-
- begin
- lib = INTERP._invoke('set', 'blt_libPath')
- rescue
- lib = ''
- end
- LIB_PATH = TkVarAccess.new('blt_libPath', lib)
-
- PACKAGE_NAME = 'BLT'.freeze
- def self.package_name
- PACKAGE_NAME
- end
-
- def self.package_version
- begin
- TkPackage.require('BLT')
- rescue
- ''
- end
- end
-
- ####################################################
-
- def self.beep(percent = 50)
- tk_call('::blt::beep', percent)
- end
-
- def self.bgexec(*args)
- if args[0].kind_of?(TkVariable)
- var = args.shift
- else
- var = TkVariable.new
- end
- params = [var]
-
- params.concat(hash_kv(args.shift, true)) if args[0].kind_of?(Hash)
-
- params << '--'
- params.concat(args)
-
- tk_call('::blt::bgexec', *params)
- var
- end
-
- def self.detach_bgexec(*args)
- if args[0].kind_of?(TkVariable)
- var = args.shift
- else
- var = TkVariable.new
- end
- params = [var]
-
- params.concat(hash_kv(args.shift, true)) if args[0].kind_of?(Hash)
-
- params << '--'
- params.concat(args)
- params << '&'
-
- [var, tk_split_list(tk_call('::blt::bgexec', *params))]
- end
-
- def self.bltdebug(lvl = nil)
- if lvl
- tk_call('::blt::bltdebug', lvl)
- else
- number(tk_call('::blt::bltdebug'))
- end
- end
-
- def self.crc32_file(name)
- tk_call_without_enc('::blt::crc32', name)
- end
- def self.crc32_data(dat)
- tk_call_without_enc('::blt::crc32', '-data', dat)
- end
-
- ####################################################
-
- def self.active_legend(graph)
- tk_call_without_enc('Blt_ActiveLegend', graph)
- end
- def self.crosshairs(graph)
- tk_call_without_enc('Blt_Crosshairs', graph)
- end
- def self.zoom_stack(graph)
- tk_call_without_enc('Blt_ZoomStack', graph)
- end
- def self.print_key(graph)
- tk_call_without_enc('Blt_PrintKey', graph)
- end
- def self.closest_point(graph)
- tk_call_without_enc('Blt_ClosestPoint', graph)
- end
-
- module GraphCommand
- def active_legend
- tk_call_without_enc('Blt_ActiveLegend', @path)
- self
- end
- def crosshairs
- tk_call_without_enc('Blt_Crosshairs', @path)
- self
- end
- def zoom_stack
- tk_call_without_enc('Blt_ZoomStack', @path)
- self
- end
- def print_key
- tk_call_without_enc('Blt_PrintKey', @path)
- self
- end
- def closest_point
- tk_call_without_enc('Blt_ClosestPoint', @path)
- self
- end
- end
-
- ####################################################
-
- autoload :PlotComponent,'tkextlib/blt/component.rb'
-
- autoload :Barchart, 'tkextlib/blt/barchart.rb'
- autoload :Bitmap, 'tkextlib/blt/bitmap.rb'
- autoload :Busy, 'tkextlib/blt/busy.rb'
- autoload :Container, 'tkextlib/blt/container.rb'
- autoload :CutBuffer, 'tkextlib/blt/cutbuffer.rb'
- autoload :DragDrop, 'tkextlib/blt/dragdrop.rb'
- autoload :EPS, 'tkextlib/blt/eps.rb'
- autoload :Htext, 'tkextlib/blt/htext.rb'
- autoload :Graph, 'tkextlib/blt/graph.rb'
- autoload :Spline, 'tkextlib/blt/spline.rb'
- autoload :Stripchart, 'tkextlib/blt/stripchart.rb'
- autoload :Table, 'tkextlib/blt/table.rb'
- autoload :Tabnotebook, 'tkextlib/blt/tabnotebook.rb'
- autoload :Tabset, 'tkextlib/blt/tabset.rb'
- autoload :Ted, 'tkextlib/blt/ted.rb'
- autoload :Tile, 'tkextlib/blt/tile.rb'
- autoload :Tree, 'tkextlib/blt/tree.rb'
- autoload :TreeView, 'tkextlib/blt/treeview.rb'
- autoload :Hiertable, 'tkextlib/blt/treeview.rb'
- # Hierbox is obsolete
- autoload :Vector, 'tkextlib/blt/vector.rb'
- autoload :VectorAccess, 'tkextlib/blt/vector.rb'
- autoload :Watch, 'tkextlib/blt/watch.rb'
- autoload :Winop, 'tkextlib/blt/winop.rb'
- autoload :WinOp, 'tkextlib/blt/winop.rb'
-
- # Unix only
- autoload :DnD, 'tkextlib/blt/unix_dnd.rb'
-
- # Windows only
- autoload :Printer, 'tkextlib/blt/win_printer.rb'
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/barchart.rb b/ext/tk/lib/tkextlib/blt/barchart.rb
deleted file mode 100644
index cb481c5889..0000000000
--- a/ext/tk/lib/tkextlib/blt/barchart.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-#
-# tkextlib/blt/barchart.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-require 'tkextlib/blt/component.rb'
-
-module Tk::BLT
- class Barchart < TkWindow
- TkCommandNames = ['::blt::barchart'.freeze].freeze
- WidgetClassName = 'Barchart'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- include PlotComponent
- include GraphCommand
-
- def __boolval_optkeys
- ['bufferelements', 'buffergraph', 'invertxy']
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- ['text', 'label', 'title', 'file',
- 'background', 'plotbackground']
- end
- private :__strval_optkeys
-
- def __tkvariable_optkeys
- super() << 'colormap' << 'fontmap'
- end
- private :__tkvariable_optkeys
-
-=begin
- BarElement_ID = ['blt_barchart_bar'.freeze, '00000'.taint].freeze
-
- def bar(elem=nil, keys={})
- if elem.kind_of?(Hash)
- keys = elem
- elem = nil
- end
- unless elem
- elem = BarElement_ID.join(TkCore::INTERP._ip_id_).freeze
- BarElement_ID[1].succ!
- end
- tk_send('bar', elem, keys)
- Element.new(self, elem, :without_creating=>true)
- end
-=end
-
- def extents(item)
- num_or_str(tk_send_without_enc('extents', item))
- end
-
- def invtransform(x, y)
- list(tk_send_without_enc('invtransform', x, y))
- end
-
- def inside(x, y)
- bool(tk_send_without_enc('inside', x, y))
- end
-
- def metafile(file=None)
- # Windows only
- tk_send('metafile', file)
- self
- end
-
- def snap(output, keys={})
- tk_send_without_enc('snap', *(hash_kv(keys, false) + output))
- self
- end
-
- def transform(x, y)
- list(tk_send_without_enc('transform', x, y))
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/bitmap.rb b/ext/tk/lib/tkextlib/blt/bitmap.rb
deleted file mode 100644
index 31cf8d4229..0000000000
--- a/ext/tk/lib/tkextlib/blt/bitmap.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-#
-# tkextlib/blt/bitmap.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- class Bitmap < TkObject
- extend TkCore
-
- TkCommandNames = ['::blt::bitmap'.freeze].freeze
-
- BITMAP_ID_TBL = TkCore::INTERP.create_table
- BITMAP_ID = ['blt_bitmap_id'.freeze, '00000'.taint].freeze
-
- def self.data(name)
- dat = tk_simple_list(tk_call('::blt::bitmap', 'data', name))
- [ tk_split_list(dat[0]), tk_simple_list(dat[1]) ]
- end
-
- def self.exist?(name)
- bool(tk_call('::blt::bitmap', 'exists', name))
- end
-
- def self.height(name)
- number(tk_call('::blt::bitmap', 'height', name))
- end
-
- def self.width(name)
- number(tk_call('::blt::bitmap', 'width', name))
- end
-
- def self.source(name)
- tk_simple_list(tk_call('::blt::bitmap', 'source', name))
- end
-
- #################################
-
- class << self
- alias _new new
-
- def new(data, keys={})
- _new(:data, nil, data, keys)
- end
- alias define new
-
- def new_with_name(name, data, keys={})
- _new(:data, name, data, keys)
- end
- alias define_with_name new_with_name
-
- def compose(text, keys={})
- _new(:text, nil, text, keys)
- end
-
- def compose_with_name(name, text, keys={})
- _new(:text, name, text, keys)
- end
- end
-
- def initialize(type, name, data, keys = {})
- if name
- @id = name
- else
- @id = BITMAP_ID.join(TkCore::INTERP._ip_id_)
- BITMAP_ID[1].succ!
- BITMAP_ID_TBL[@id] = self
- end
-
- @path = @id
-
- unless bool(tk_call('::blt::bitmap', 'exists', @id))
- if type == :text
- tk_call('::blt::bitmap', 'compose', @id, data, *hash_kv(keys))
- else # :data
- tk_call('::blt::bitmap', 'define', @id, data, *hash_kv(keys))
- end
- end
- end
-
- def exist?
- bool(tk_call('::blt::bitmap', 'exists', @id))
- end
-
- def height
- number(tk_call('::blt::bitmap', 'height', @id))
- end
-
- def width
- number(tk_call('::blt::bitmap', 'width', @id))
- end
-
- def source
- tk_simple_list(tk_call('::blt::bitmap', 'source', @id))
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/busy.rb b/ext/tk/lib/tkextlib/blt/busy.rb
deleted file mode 100644
index 4726e466f4..0000000000
--- a/ext/tk/lib/tkextlib/blt/busy.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-#
-# tkextlib/blt/busy.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/itemconfig.rb'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- module Busy
- extend TkCore
- extend TkItemConfigMethod
-
- TkCommandNames = ['::blt::busy'.freeze].freeze
-
- ###########################
-
- class Shield < TkWindow
- def self.shield_path(win)
- win = window(win) unless win.kind_of?(TkWindow)
- if win.kind_of?(TkToplevel)
- win.path + '._Busy'
- else
- win.path + '_Busy'
- end
- end
-
- def initialize(win)
- @path = self.class.shield_path(win)
- end
- end
-
- def self.shield_path(win)
- Tk::BLT::Busy::Shield.shield_path(win)
- end
- end
-end
-
-class << Tk::BLT::Busy
- def __item_config_cmd(win)
- ['::blt::busy', 'configure', win]
- end
- private :__item_config_cmd
-
- undef itemcget
- alias configure itemconfigure
- alias configinfo itemconfiginfo
- alias current_configinfo current_itemconfiginfo
- private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
-
- ##################################
-
- def hold(win, keys={})
- tk_call('::blt::busy', 'hold', win, *hash_kv(keys))
- end
-
- def release(*wins)
- tk_call('::blt::busy', 'release', *wins)
- end
-
- def forget(*wins)
- tk_call('::blt::busy', 'forget', *wins)
- end
-
- def is_busy(pat=None)
- tk_split_list(tk_call('::blt::busy', 'isbusy', pat))
- end
-
- def names(pat=None)
- tk_split_list(tk_call('::blt::busy', 'names', pat))
- end
- alias windows names
-
- def check(win)
- bool(tk_call('::blt::busy', 'check', win))
- end
-
- def status(win)
- bool(tk_call('::blt::busy', 'status', win))
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/component.rb b/ext/tk/lib/tkextlib/blt/component.rb
deleted file mode 100644
index ad78a5430b..0000000000
--- a/ext/tk/lib/tkextlib/blt/component.rb
+++ /dev/null
@@ -1,1835 +0,0 @@
-#
-# tkextlib/blt/component.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- module PlotComponent
- include TkItemConfigMethod
-
- module OptKeys
- def __item_font_optkeys(id)
- ['font', 'tickfont', 'titlefont']
- end
- private :__item_font_optkeys
-
- def __item_numstrval_optkeys(id)
- ['xoffset', 'yoffset']
- end
- private :__item_numstrval_optkeys
-
- def __item_boolval_optkeys(id)
- ['hide', 'under', 'descending', 'logscale', 'loose', 'showticks',
- 'titlealternate', 'scalesymbols', 'minor', 'raised',
- 'center', 'decoration', 'landscape', 'maxpect']
- end
- private :__item_boolval_optkeys
-
- def __item_strval_optkeys(id)
- ['text', 'label', 'limits', 'title',
- 'show', 'file', 'maskdata', 'maskfile',
- 'color', 'titlecolor', 'fill', 'outline', 'offdash']
- end
- private :__item_strval_optkeys
-
- def __item_listval_optkeys(id)
- ['bindtags']
- end
- private :__item_listval_optkeys
-
- def __item_numlistval_optkeys(id)
- ['dashes', 'majorticks', 'minorticks']
- end
- private :__item_numlistval_optkeys
-
- def __item_tkvariable_optkeys(id)
- ['variable', 'textvariable', 'colormap', 'fontmap']
- end
- private :__item_tkvariable_optkeys
- end
-
- include OptKeys
-
- def __item_cget_cmd(id)
- if id.kind_of?(Array)
- # id := [ type, name ]
- [self.path, id[0], 'cget', id[1]]
- else
- [self.path, id, 'cget']
- end
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- if id.kind_of?(Array)
- # id := [ type, name, ... ]
- type, *names = id
- [self.path, type, 'configure'].concat(names)
- else
- [self.path, id, 'configure']
- end
- end
- private :__item_config_cmd
-
- def __item_pathname(id)
- if id.kind_of?(Array)
- id = tagid(id[1])
- end
- [self.path, id].join(';')
- end
- private :__item_pathname
-
- def axis_cget(id, option)
- ret = itemcget(['axis', tagid(id)], option)
- end
- def axis_configure(*args)
- slot = args.pop
- if slot.kind_of?(Hash)
- value = None
- slot = _symbolkey2str(slot)
- if cmd = slot.delete('command')
- slot['command'] = proc{|w, tick|
- cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
- }
- end
- else
- value = slot
- slot = args.pop
- if slot == :command || slot == 'command'
- cmd = value
- value = proc{|w, tick|
- cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
- }
- end
- end
- id_list = args.flatten.collect!{|id| tagid(id)}.unshift('axis')
- itemconfigure(id_list, slot, value)
- end
- def axis_configinfo(id, slot=nil)
- itemconfiginfo(['axis', tagid(id)], slot)
- end
- def current_axis_configinfo(id, slot=nil)
- current_itemconfiginfo(['axis', tagid(id)], slot)
- end
-
- def crosshairs_cget(option)
- itemcget('crosshairs', option)
- end
- def crosshairs_configure(slot, value=None)
- itemconfigure('crosshairs', slot, value)
- end
- def crosshairs_configinfo(slot=nil)
- itemconfiginfo('crosshairs', slot)
- end
- def current_crosshairs_configinfo(slot=nil)
- current_itemconfiginfo('crosshairs', slot)
- end
-
- def element_cget(id, option)
- itemcget(['element', tagid(id)], option)
- end
- def element_configure(*args)
- slot = args.pop
- if slot.kind_of?(Hash)
- value = None
- else
- value = slot
- slot = args.pop
- end
- id_list = args.flatten.collect!{|id| tagid(id)}.unshift('element')
- itemconfigure(id_list, slot, value)
- end
- def element_configinfo(id, slot=nil)
- itemconfiginfo(['element', tagid(id)], slot)
- end
- def current_element_configinfo(id, slot=nil)
- current_itemconfiginfo(['element', tagid(id)], slot)
- end
-
- def bar_cget(id, option)
- itemcget(['bar', tagid(id)], option)
- end
- def bar_configure(*args)
- slot = args.pop
- if slot.kind_of?(Hash)
- value = None
- else
- value = slot
- slot = args.pop
- end
- id_list = args.flatten.collect!{|id| tagid(id)}.unshift('bar')
- itemconfigure(id_list, slot, value)
- end
- def bar_configinfo(id, slot=nil)
- itemconfiginfo(['bar', tagid(id)], slot)
- end
- def current_bar_configinfo(id, slot=nil)
- current_itemconfiginfo(['bar', tagid(id)], slot)
- end
-
- def line_cget(id, option)
- itemcget(['line', tagid(id)], option)
- end
- def line_configure(*args)
- slot = args.pop
- if slot.kind_of?(Hash)
- value = None
- else
- value = slot
- slot = args.pop
- end
- id_list = args.flatten.collect!{|id| tagid(id)}.unshift('line')
- itemconfigure(id_list, slot, value)
- end
- def line_configinfo(id, slot=nil)
- itemconfiginfo(['line', tagid(id)], slot)
- end
- def current_line_configinfo(id, slot=nil)
- current_itemconfiginfo(['line', tagid(id)], slot)
- end
-
- def gridline_cget(option)
- itemcget('grid', option)
- end
- def gridline_configure(slot, value=None)
- itemconfigure('grid', slot, value)
- end
- def gridline_configinfo(slot=nil)
- itemconfiginfo('grid', slot)
- end
- def current_gridline_configinfo(slot=nil)
- current_itemconfiginfo('grid', slot)
- end
-
- def legend_cget(option)
- itemcget('legend', option)
- end
- def legend_configure(slot, value=None)
- itemconfigure('legend', slot, value)
- end
- def legend_configinfo(slot=nil)
- itemconfiginfo('legend', slot)
- end
- def current_legend_configinfo(slot=nil)
- current_itemconfiginfo('legend', slot)
- end
-
- def pen_cget(id, option)
- itemcget(['pen', tagid(id)], option)
- end
- def pen_configure(*args)
- slot = args.pop
- if slot.kind_of?(Hash)
- value = None
- else
- value = slot
- slot = args.pop
- end
- id_list = args.flatten.collect!{|id| tagid(id)}.unshift('pen')
- itemconfigure(id_list, slot, value)
- end
- def pen_configinfo(id, slot=nil)
- itemconfiginfo(['pen', tagid(id)], slot)
- end
- def current_pen_configinfo(id, slot=nil)
- current_itemconfiginfo(['pen', tagid(id)], slot)
- end
-
- def postscript_cget(option)
- itemcget('postscript', option)
- end
- def postscript_configure(slot, value=None)
- itemconfigure('postscript', slot, value)
- end
- def postscript_configinfo(slot=nil)
- itemconfiginfo('postscript', slot)
- end
- def current_postscript_configinfo(slot=nil)
- current_itemconfiginfo('postscript', slot)
- end
-
- def marker_cget(id, option)
- itemcget(['marker', tagid(id)], option)
- end
- def marker_configure(*args)
- slot = args.pop
- if slot.kind_of?(Hash)
- value = None
- else
- value = slot
- slot = args.pop
- end
- id_list = args.flatten.collect!{|id| tagid(id)}.unshift('marker')
- itemconfigure(id_list, slot, value)
- end
- def marker_configinfo(id, slot=nil)
- itemconfiginfo(['marker', tagid(id)], slot)
- end
- def current_marker_configinfo(id, slot=nil)
- current_itemconfiginfo(['marker', tagid(id)], slot)
- end
-
- alias __itemcget itemcget
- alias __itemconfiginfo itemconfiginfo
- alias __current_itemconfiginfo current_itemconfiginfo
- private :__itemcget, :__itemconfiginfo, :__current_itemconfiginfo
-
- def itemcget(tagOrId, option)
- ret = __itemcget(tagid(tagOrId), option)
- if option == 'bindtags' || option == :bindtags
- ret.collect{|tag| TkBindTag.id2obj(tag)}
- else
- ret
- end
- end
- def itemconfiginfo(tagOrId, slot = nil)
- ret = __itemconfiginfo(tagid(tagOrId), slot)
-
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- if slot == 'bindtags' || slot == :bindtags
- ret[-2] = ret[-2].collect{|tag| TkBindTag.id2obj(tag)}
- ret[-1] = ret[-1].collect{|tag| TkBindTag.id2obj(tag)}
- end
- else
- if (inf = ret.assoc('bindtags'))
- inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)}
- inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)}
- end
- end
-
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if (inf = ret['bindtags'])
- inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)}
- inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)}
- ret['bindtags'] = inf
- end
- end
-
- ret
- end
- def current_itemconfiginfo(tagOrId, slot = nil)
- ret = __current_itemconfiginfo(tagid(tagOrId), slot)
-
- if (val = ret['bindtags'])
- ret['bindtags'] = val.collect{|tag| TkBindTag.id2obj(tag)}
- end
-
- ret
- end
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-
- #################
-
- class Axis < TkObject
- OBJ_ID = ['blt_chart_axis'.freeze, '00000'.taint].freeze
- OBJ_TBL={}
-
- def self.id2obj(chart, id)
- cpath = chart.path
- return id unless OBJ_TBL[cpath]
- OBJ_TBL[cpath][id]? OBJ_TBL[cpath][id]: id
- end
-
- def self.new(chart, axis=nil, keys={})
- if axis.kind_of?(Hash)
- keys = axis
- axis = nil
- end
- OBJ_TBL[chart.path] = {} unless OBJ_TBL[chart.path]
- return OBJ_TBL[chart.path][axis] if axis && OBJ_TBL[chart.path][axis]
- super(chart, axis, keys)
- end
-
- def initialize(chart, axis=nil, keys={})
- if axis.kind_of?(Hash)
- keys = axis
- axis = nil
- end
- if axis
- @axis = @id = axis.to_s
- else
- @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
- OBJ_ID[1].succ!
- end
- @path = @id
- @parent = @chart = chart
- @cpath = @chart.path
- Axis::OBJ_TBL[@cpath][@axis] = self
- keys = _symbolkey2str(keys)
- unless keys.delete('without_creating')
- # @chart.axis_create(@axis, keys)
- tk_call(@chart, 'axis', 'create', @axis, keys)
- end
- end
-
- def id
- @id
- end
-
- def to_eval
- @id
- end
-
- def cget(option)
- @chart.axis_cget(@id, option)
- end
- def configure(key, value=None)
- @chart.axis_configure(@id, key, value)
- self
- end
- def configinfo(key=nil)
- @chart.axis_configinfo(@id, key)
- end
- def current_configinfo(key=nil)
- @chart.current_axis_configinfo(@id, key)
- end
-
- def command(cmd=nil, &b)
- if cmd
- configure('command', cmd)
- elsif b
- configure('command', Proc.new(&b))
- else
- cget('command')
- end
- end
-
- def delete
- @chart.axis_delete(@id)
- self
- end
-
- def invtransform(val)
- @chart.axis_invtransform(@id, val)
- end
-
- def limits
- @chart.axis_limits(@id)
- end
-
- def name
- @axis
- end
-
- def transform(val)
- @chart.axis_transform(@id, val)
- end
-
- def view
- @chart.axis_view(@id)
- self
- end
-
- def use(name=None) # if @id == xaxis | x2axis | yaxis | y2axis
- @chart.axis_use(@id, name)
- end
-
- def use_as(axis) # axis := xaxis | x2axis | yaxis | y2axis
- @chart.axis_use(axis, @id)
- end
- end
-
- #################
-
- class Crosshairs < TkObject
- OBJ_TBL={}
-
- def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(chart, keys)
- end
-
- def initialize(chart, keys={})
- @parent = @chart = chart
- @cpath = @chart.path
- Crosshairs::OBJ_TBL[@cpath] = self
- @chart.crosshair_configure(keys) unless keys.empty?
- @path = @id = 'crosshairs'
- end
-
- def id
- @id
- end
-
- def to_eval
- @id
- end
-
- def cget(option)
- @chart.crosshair_cget(option)
- end
- def configure(key, value=None)
- @chart.crosshair_configure(key, value)
- self
- end
- def configinfo(key=nil)
- @chart.crosshair_configinfo(key)
- end
- def current_configinfo(key=nil)
- @chart.current_crosshair_configinfo(key)
- end
-
- def off
- @chart.crosshair_off
- self
- end
- def on
- @chart.crosshair_on
- self
- end
- def toggle
- @chart.crosshair_toggle
- self
- end
- end
-
- #################
-
- class Element < TkObject
- extend Tk
- extend TkItemFontOptkeys
- extend TkItemConfigOptkeys
-
- extend Tk::BLT::PlotComponent::OptKeys
-
- ElementTypeName = 'element'
- ElementTypeToClass = { ElementTypeName=>self }
- ElementID_TBL = TkCore::INTERP.create_table
-
- TkCore::INTERP.init_ip_env{ ElementID_TBL.clear }
-
- OBJ_ID = ['blt_chart_element'.freeze, '00000'.taint].freeze
- OBJ_TBL={}
-
- def Element.type2class(type)
- ElementTypeToClass[type]
- end
-
- def Element.id2obj(chart, id)
- cpath = chart.path
- return id unless OBJ_TBL[cpath]
- OBJ_TBL[cpath][id]? OBJ_TBL[cpath][id]: id
- end
-
- def self.new(chart, element=nil, keys={})
- if element.kind_of?(Hash)
- keys = element
- element = nil
- end
- OBJ_TBL[chart.path] = {} unless OBJ_TBL[chart.path]
- if element && OBJ_TBL[chart.path][element]
- return OBJ_TBL[chart.path][element]
- end
- super(chart, element, keys)
- end
-
- def initialize(chart, element=nil, keys={})
- if element.kind_of?(Hash)
- keys = element
- element = nil
- end
- if element
- @element = @id = element.to_s
- else
- @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
- OBJ_ID[1].succ!
- end
- @path = @id
- @parent = @chart = chart
- @cpath = @chart.path
- @typename = self.class::ElementTypeName
- Element::OBJ_TBL[@cpath][@element] = self
- keys = _symbolkey2str(keys)
- unless keys.delete('without_creating')
- # @chart.element_create(@element, keys)
- tk_call(@chart, @typename, 'create', @element, keys)
- end
- end
-
- def id
- @id
- end
-
- def to_eval
- @id
- end
-
- def cget(option)
- # @chart.element_cget(@id, option)
- @chart.__send__(@typename + '_cget', @id, option)
- end
- def configure(key, value=None)
- # @chart.element_configure(@id, key, value)
- @chart.__send__(@typename + '_configure', @id, key, value)
- self
- end
- def configinfo(key=nil)
- # @chart.element_configinfo(@id, key)
- @chart.__send__(@typename + '_configinfo', @id, key)
- end
- def current_configinfo(key=nil)
- # @chart.current_element_configinfo(@id, key)
- @chart.__send__('current_' << @typename << '_configinfo', @id, key)
- end
-
- def activate(*args)
- @chart.element_activate(@id, *args)
- end
-
- def closest(x, y, var, keys={})
- # @chart.element_closest(x, y, var, @id, keys)
- @chart.__send__(@typename + '_closest', x, y, var, @id, keys)
- end
-
- def deactivate
- @chart.element_deactivate(@id)
- self
- end
-
- def delete
- @chart.element_delete(@id)
- self
- end
-
- def exist?
- @chart.element_exist?(@id)
- end
-
- def name
- @element
- end
-
- def type
- @chart.element_type(@id)
- end
- end
-
- class Bar < Element
- ElementTypeName = 'bar'.freeze
- ElementTypeToClass[ElementTypeName] = self
- end
- class Line < Element
- ElementTypeName = 'line'.freeze
- ElementTypeToClass[ElementTypeName] = self
- end
-
- #################
-
- class GridLine < TkObject
- OBJ_TBL={}
-
- def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(chart, keys)
- end
-
- def initialize(chart, keys={})
- @parent = @chart = chart
- @cpath = @chart.path
- GridLine::OBJ_TBL[@cpath] = self
- @chart.gridline_configure(keys) unless keys.empty?
- @path = @id = 'grid'
- end
-
- def id
- @id
- end
-
- def to_eval
- @id
- end
-
- def cget(option)
- @chart.gridline_cget(option)
- end
- def configure(key, value=None)
- @chart.gridline_configure(key, value)
- self
- end
- def configinfo(key=nil)
- @chart.gridline_configinfo(key)
- end
- def current_configinfo(key=nil)
- @chart.current_gridline_configinfo(key)
- end
-
- def off
- @chart.gridline_off
- self
- end
- def on
- @chart.gridline_on
- self
- end
- def toggle
- @chart.gridline_toggle
- self
- end
- end
-
- #################
-
- class Legend < TkObject
- OBJ_TBL={}
-
- def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(chart, keys)
- end
-
- def initialize(chart, keys={})
- @parent = @chart = chart
- @cpath = @chart.path
- Crosshairs::OBJ_TBL[@cpath] = self
- @chart.crosshair_configure(keys) unless keys.empty?
- @path = @id = 'legend'
- end
-
- def id
- @id
- end
-
- def to_eval
- @id
- end
-
- def cget(option)
- @chart.legend_cget(option)
- end
- def configure(key, value=None)
- @chart.legend_configure(key, value)
- self
- end
- def configinfo(key=nil)
- @chart.legend_configinfo(key)
- end
- def current_configinfo(key=nil)
- @chart.current_legend_configinfo(key)
- end
-
- def activate(*args)
- @chart.legend_activate(*args)
- end
-
- def deactivate(*args)
- @chart.legend_deactivate(*args)
- end
-
- def get(pos, y=nil)
- @chart.legend_get(pos, y)
- end
- end
-
- #################
-
- class Pen < TkObject
- OBJ_ID = ['blt_chart_pen'.freeze, '00000'.taint].freeze
- OBJ_TBL={}
-
- def self.id2obj(chart, id)
- cpath = chart.path
- return id unless OBJ_TBL[cpath]
- OBJ_TBL[cpath][id]? OBJ_TBL[cpath][id]: id
- end
-
- def self.new(chart, pen=nil, keys={})
- if pen.kind_of?(Hash)
- keys = pen
- pen = nil
- end
- OBJ_TBL[chart.path] = {} unless OBJ_TBL[chart.path]
- return OBJ_TBL[chart.path][pen] if pen && OBJ_TBL[chart.path][pen]
- super(chart, pen, keys)
- end
-
- def initialize(chart, pen=nil, keys={})
- if pen.kind_of?(Hash)
- keys = pen
- pen = nil
- end
- if pen
- @pen = @id = pen.to_s
- else
- @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
- OBJ_ID[1].succ!
- end
- @path = @id
- @parent = @chart = chart
- @cpath = @chart.path
- Pen::OBJ_TBL[@cpath][@pen] = self
- keys = _symbolkey2str(keys)
- unless keys.delete('without_creating')
- # @chart.pen_create(@pen, keys)
- tk_call(@chart, 'pen', 'create', @pen, keys)
- end
- end
-
- def id
- @id
- end
-
- def to_eval
- @id
- end
-
- def cget(option)
- @chart.pen_cget(@id, option)
- end
- def configure(key, value=None)
- @chart.pen_configure(@id, key, value)
- self
- end
- def configinfo(key=nil)
- @chart.pen_configinfo(@id, key)
- end
- def current_configinfo(key=nil)
- @chart.current_pen_configinfo(@id, key)
- end
-
- def delete
- @chart.pen_delete(@id)
- self
- end
-
- def name
- @pen
- end
- end
-
- #################
-
- class Postscript < TkObject
- OBJ_TBL={}
-
- def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(chart, keys)
- end
-
- def initialize(chart, keys={})
- @parent = @chart = chart
- @cpath = @chart.path
- Postscript::OBJ_TBL[@cpath] = self
- @chart.postscript_configure(keys) unless keys.empty?
- @path = @id = 'postscript'
- end
-
- def id
- @id
- end
-
- def to_eval
- @id
- end
-
- def cget(option)
- @chart.postscript_cget(option)
- end
- def configure(key, value=None)
- @chart.postscript_configure(key, value)
- self
- end
- def configinfo(key=nil)
- @chart.postscript_configinfo(key)
- end
- def current_configinfo(key=nil)
- @chart.current_postscript_configinfo(key)
- end
-
- def output(file=nil, keys={})
- if file.kind_of?(Hash)
- keys = file
- file = nil
- end
-
- ret = @chart.postscript_output(file, keys)
-
- if file
- self
- else
- ret
- end
- end
- end
-
- #################
- class Marker < TkObject
- extend Tk
- extend TkItemFontOptkeys
- extend TkItemConfigOptkeys
-
- extend Tk::BLT::PlotComponent::OptKeys
-
- MarkerTypeName = nil
- MarkerTypeToClass = {}
- MarkerID_TBL = TkCore::INTERP.create_table
-
- TkCore::INTERP.init_ip_env{ MarkerID_TBL.clear }
-
- def Marker.type2class(type)
- MarkerTypeToClass[type]
- end
-
- def Marker.id2obj(chart, id)
- cpath = chart.path
- return id unless MarkerID_TBL[cpath]
- MarkerID_TBL[cpath][id]? MarkerID_TBL[cpath][id]: id
- end
-
- def self._parse_create_args(keys)
- fontkeys = {}
- methodkeys = {}
- if keys.kind_of? Hash
- keys = _symbolkey2str(keys)
-
- __item_font_optkeys(nil).each{|key|
- fkey = key.to_s
- fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
-
- fkey = "kanji#{key}"
- fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
-
- fkey = "latin#{key}"
- fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
-
- fkey = "ascii#{key}"
- fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
- }
-
- __item_methodcall_optkeys(nil).each{|key|
- key = key.to_s
- methodkeys[key] = keys.delete(key) if keys.key?(key)
- }
-
- __item_ruby2val_optkeys(nil).each{|key, method|
- key = key.to_s
- keys[key] = method.call(keys[key]) if keys.has_key?(key)
- }
-
- args = itemconfig_hash_kv(nil, keys)
- else
- args = []
- end
-
- [args, fontkeys]
- end
- private_class_method :_parse_create_args
-
- def self.create(chart, keys={})
- unless self::MarkerTypeName
- fail RuntimeError, "#{self} is an abstract class"
- end
- args, fontkeys = _parse_create_args(keys)
- idnum = tk_call_without_enc(chart.path, 'marker', 'create',
- self::MarkerTypeName, *args)
- chart.marker_configure(idnum, fontkeys) unless fontkeys.empty?
- idnum.to_i # 'item id' is an integer number
- end
-
- def self.create_type(chart, type, keys={})
- args, fontkeys = _parse_create_args(keys)
- idnum = tk_call_without_enc(chart.path, 'marker', 'create',
- type, *args)
- chart.marker_configure(idnum, fontkeys) unless fontkeys.empty?
- id = idnum.to_i # 'item id' is an integer number
- obj = self.allocate
- obj.instance_eval{
- @parent = @chart = chart
- @cpath = chart.path
- @id = id
- unless Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath]
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] = {}
- end
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
- }
- obj
- end
-
- def initialize(parent, *args)
- @parent = @chart = parent
- @cpath = parent.path
-
- @path = @id = create_self(*args) # an integer number as 'item id'
- unless Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath]
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] = {}
- end
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
- end
- def create_self(*args)
- self.class.create(@chart, *args) # return an integer as 'item id'
- end
- private :create_self
-
- def id
- @id
- end
-
- def to_eval
- @id
- end
-
- def cget(option)
- @chart.marker_cget(@id, option)
- end
- def configure(key, value=None)
- @chart.marker_configure(@id, key, value)
- self
- end
- def configinfo(key=nil)
- @chart.marker_configinfo(@id, key)
- end
- def current_configinfo(key=nil)
- @chart.current_marker_configinfo(@id, key)
- end
-
- def after(target=None)
- @chart.marker_after(@id, target)
- end
-
- def before(target=None)
- @chart.marker_before(@id, target)
- end
-
- def delete
- @chart.marker_delete(@id)
- end
-
- def exist?
- @chart.marker_exist(@id)
- end
-
- def type
- @chart.marker_type(@id)
- end
- end
-
- class TextMarker < Marker
- MarkerTypeName = 'text'.freeze
- MarkerTypeToClass[MarkerTypeName] = self
- end
- class LineMarker < Marker
- MarkerTypeName = 'line'.freeze
- MarkerTypeToClass[MarkerTypeName] = self
- end
- class BitmapMarker < Marker
- MarkerTypeName = 'bitmap'.freeze
- MarkerTypeToClass[MarkerTypeName] = self
- end
- class ImageMarker < Marker
- MarkerTypeName = 'image'.freeze
- MarkerTypeToClass[MarkerTypeName] = self
- end
- class PolygonMarker < Marker
- MarkerTypeName = 'polygon'.freeze
- MarkerTypeToClass[MarkerTypeName] = self
- end
- class WindowMarker < Marker
- MarkerTypeName = 'window'.freeze
- MarkerTypeToClass[MarkerTypeName] = self
- end
-
- #################
-
- def __destroy_hook__
- Axis::OBJ_TBL.delete(@path)
- Crosshairs::OBJ_TBL.delete(@path)
- Element::OBJ_TBL.delete(@path)
- GridLine::OBJ_TBL.delete(@path)
- Legend::OBJ_TBL.delete(@path)
- Pen::OBJ_TBL.delete(@path)
- Postscript::OBJ_TBL.delete(@path)
- Marker::OBJ_TBL.delete(@path)
- super()
- end
-
- #################
-
- def tagid(tag)
- if tag.kind_of?(Axis) ||
- tag.kind_of?(Crosshairs) ||
- tag.kind_of?(Element) ||
- tag.kind_of?(GridLine) ||
- tag.kind_of?(Legend) ||
- tag.kind_of?(Pen) ||
- tag.kind_of?(Postscript) ||
- tag.kind_of?(Marker)
- tag.id
- else
- tag # maybe an Array of configure paramters
- end
- end
-
- def _component_bind(target, tag, context, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([path, target, 'bind', tagid(tag)], context, cmd, *args)
- self
- end
- def _component_bind_append(target, tag, context, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([path, target, 'bind', tagid(tag)], context, cmd, *args)
- self
- end
- def _component_bind_remove(target, tag, context)
- _bind_remove([path, target, 'bind', tagid(tag)], context)
- self
- end
- def _component_bindinfo(target, tag, context=nil)
- _bindinfo([path, target, 'bind', tagid(tag)], context)
- end
- private :_component_bind, :_component_bind_append
- private :_component_bind_remove, :_component_bindinfo
-
- def axis_bind(tag, context, *args)
- _component_bind('axis', tag, context, *args)
- end
- def axis_bind_append(tag, context, *args)
- _component_bind_append('axis', tag, context, *args)
- end
- def axis_bind_remove(tag, context)
- _component_bind_remove('axis', tag, context)
- end
- def axis_bindinfo(tag, context=nil)
- _component_bindinfo('axis', tag, context)
- end
-
- def element_bind(tag, context, *args)
- _component_bind('element', tag, context, *args)
- end
- def element_bind_append(tag, context, *args)
- _component_bind_append('element', tag, context, *args)
- end
- def element_bind_remove(tag, context)
- _component_bind_remove('element', tag, context)
- end
- def element_bindinfo(tag, context=nil)
- _component_bindinfo('element', tag, context)
- end
-
- def bar_bind(tag, context, *args)
- _component_bind('bar', tag, context, *args)
- end
- def bar_bind_append(tag, context, *args)
- _component_bind_append('bar', tag, context, *args)
- end
- def bar_bind_remove(tag, context)
- _component_bind_remove('bar', tag, context)
- end
- def bar_bindinfo(tag, context=nil)
- _component_bindinfo('bar', tag, context)
- end
-
- def line_bind(tag, context, *args)
- _component_bind('line', tag, context, *args)
- end
- def line_bind_append(tag, context, *args)
- _component_bind_append('line', tag, context, *args)
- end
- def line_bind_remove(tag, context)
- _component_bind_remove('line', tag, context)
- end
- def line_bindinfo(tag, context=nil)
- _component_bindinfo('line', tag, context)
- end
-
- def legend_bind(tag, context, *args)
- _component_bind('legend', tag, context, *args)
- end
- def legend_bind_append(tag, context, *args)
- _component_bind_append('legend', tag, context, *args)
- end
- def legend_bind_remove(tag, context)
- _component_bind_remove('legend', tag, context)
- end
- def legend_bindinfo(tag, context=nil)
- _component_bindinfo('legend', tag, context)
- end
-
- def marker_bind(tag, context, *args)
- _component_bind('marker', tag, context, *args)
- end
- def marker_bind_append(tag, context, *args)
- _component_bind_append('marker', tag, context, *args)
- end
- def marker_bind_remove(tag, context)
- _component_bind_remove('marker', tag, context)
- end
- def marker_bindinfo(tag, context=nil)
- _component_bindinfo('marker', tag, context)
- end
-
- ###################
-
- def axis_create(id=nil, keys={})
- # tk_send('axis', 'create', tagid(id), keys)
- Tk::BLT::PlotComponent::Axis.new(self, tagid(id), keys)
- end
- def axis_delete(*ids)
- tk_send('axis', 'delete', *(ids.collect{|id| tagid(id)}))
- self
- end
- def axis_invtransform(id, val)
- list(tk_send('axis', 'invtransform', tagid(id), val))
- end
- def axis_limits(id)
- list(tk_send('axis', 'limits', tagid(id)))
- end
- def axis_names(*pats)
- simplelist(tk_send('axis', 'names',
- *(pats.collect{|pat| tagid(pat)}))).collect{|axis|
- Tk::BLT::PlotComponent::Axis.id2obj(self, axis)
- }
- end
- def axis_transform(id, val)
- list(tk_send('axis', 'transform', tagid(id), val))
- end
- def axis_view(id)
- tk_send('axis', 'view', tagid(id))
- self
- end
- def axis_use(id, target=nil)
- if target
- Tk::BLT::PlotComponent::Axis.id2obj(self,
- tk_send('axis', 'use',
- tagid(id), tagid(target)))
- else
- Tk::BLT::PlotComponent::Axis.id2obj(self,
- tk_send('axis', 'use', tagid(id)))
- end
- end
-
- ###################
-
- def crosshairs_off
- tk_send_without_enc('crosshairs', 'off')
- self
- end
- def crosshairs_on
- tk_send_without_enc('crosshairs', 'on')
- self
- end
- def crosshairs_toggle
- tk_send_without_enc('crosshairs', 'toggle')
- self
- end
-
- ###################
-
- def element_create(id=nil, keys={})
- # tk_send('element', 'create', tagid(id), keys)
- Tk::BLT::PlotComponent::Element.new(self, tagid(id), keys)
- end
- def element_activate(*args)
- if args.empty?
- list(tk_send('element', 'activate')).collect{|elem|
- Tk::BLT::PlotComponent::Element.id2obj(self, elem)
- }
- else
- # id, *indices
- id = args.shift
- tk_send('element', 'activate', tagid(id), *args)
- end
- end
- def element_closest(x, y, var, *args)
- if args[-1].kind_of?(Hash)
- keys = args.pop
- bool(tk_send('element', 'closest', x, y, var,
- *(hash_kv(keys).concat(args.collect{|id| tagid(id)}))))
- else
- bool(tk_send('element', 'closest', x, y, var,
- *(args.collect{|id| tagid(id)})))
- end
- end
- def element_deactivate(*ids)
- tk_send('element', 'deactivate', *(ids.collect{|id| tagid(id)}))
- self
- end
- def element_delete(*ids)
- tk_send('element', 'delete', *(ids.collect{|id| tagid(id)}))
- self
- end
- def element_exist?(id)
- bool(tk_send('element', 'exists', tagid(id)))
- end
- def element_names(*pats)
- simplelist(tk_send('element', 'names',
- *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
- Tk::BLT::PlotComponent::Element.id2obj(self, elem)
- }
- end
- def element_show(*names)
- if names.empty?
- simplelist(tk_send('element', 'show'))
- else
- tk_send('element', 'show', *(names.collect{|n| tagid(n)}))
- self
- end
- end
- def element_type(id)
- tk_send('element', 'type', tagid(id))
- end
-
- ###################
-
- def bar_create(id=nil, keys={})
- # tk_send('bar', 'create', tagid(id), keys)
- Tk::BLT::PlotComponent::Bar.new(self, tagid(id), keys)
- end
- alias bar bar_create
- def bar_activate(*args)
- if args.empty?
- list(tk_send('bar', 'activate')).collect{|elem|
- Tk::BLT::PlotComponent::Element.id2obj(self, elem)
- }
- else
- # id, *indices
- id = args.shift
- tk_send('bar', 'activate', tagid(id), *args)
- end
- end
- def bar_closest(x, y, var, *args)
- if args[-1].kind_of?(Hash)
- keys = args.pop
- bool(tk_send('bar', 'closest', x, y, var,
- *(hash_kv(keys).concat(args.collect{|id| tagid(id)}))))
- else
- bool(tk_send('bar', 'closest', x, y, var,
- *(args.collect{|id| tagid(id)})))
- end
- end
- def bar_deactivate(*ids)
- tk_send('bar', 'deactivate', *(ids.collect{|id| tagid(id)}))
- self
- end
- def bar_delete(*ids)
- tk_send('bar', 'delete', *(ids.collect{|id| tagid(id)}))
- self
- end
- def bar_exist?(id)
- bool(tk_send('bar', 'exists', tagid(id)))
- end
- def bar_names(*pats)
- simplelist(tk_send('bar', 'names',
- *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
- Tk::BLT::PlotComponent::Element.id2obj(self, elem)
- }
- end
- def bar_show(*names)
- if names.empty?
- simplelist(tk_send('bar', 'show'))
- else
- tk_send('bar', 'show', *(names.collect{|n| tagid(n)}))
- self
- end
- end
- def bar_type(id)
- tk_send('bar', 'type', tagid(id))
- end
-
- ###################
-
- def line_create(id=nil, keys={})
- # tk_send('line', 'create', tagid(id), keys)
- Tk::BLT::PlotComponent::Line.new(self, tagid(id), keys)
- end
- alias bar line_create
- def line_activate(*args)
- if args.empty?
- list(tk_send('line', 'activate')).collect{|elem|
- Tk::BLT::PlotComponent::Element.id2obj(self, elem)
- }
- else
- # id, *indices
- id = args.shift
- tk_send('line', 'activate', tagid(id), *args)
- end
- end
- def line_closest(x, y, var, *args)
- if args[-1].kind_of?(Hash)
- keys = args.pop
- bool(tk_send('line', 'closest', x, y, var,
- *(hash_kv(keys).concat(args.collect{|id| tagid(id)}))))
- else
- bool(tk_send('line', 'closest', x, y, var,
- *(args.collect{|id| tagid(id)})))
- end
- end
- def line_deactivate(*ids)
- tk_send('line', 'deactivate', *(ids.collect{|id| tagid(id)}))
- self
- end
- def line_delete(*ids)
- tk_send('line', 'delete', *(ids.collect{|id| tagid(id)}))
- self
- end
- def line_exist?(id)
- bool(tk_send('line', 'exists', tagid(id)))
- end
- def line_names(*pats)
- simplelist(tk_send('line', 'names',
- *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
- Tk::BLT::PlotComponent::Element.id2obj(self, elem)
- }
- end
- def line_show(*names)
- if names.empty?
- simplelist(tk_send('line', 'show'))
- else
- tk_send('line', 'show', *(names.collect{|n| tagid(n)}))
- self
- end
- end
- def line_type(id)
- tk_send('line', 'type', tagid(id))
- end
-
- ###################
-
- def gridline_off
- tk_send_without_enc('grid', 'off')
- self
- end
- def gridline_on
- tk_send_without_enc('grid', 'on')
- self
- end
- def gridline_toggle
- tk_send_without_enc('grid', 'toggle')
- self
- end
-
- ###################
-
- def legend_window_create(parent=nil, keys=nil)
- if parent.kind_of?(Hash)
- keys = _symbolkey2str(parent)
- parent = keys.delete('parent')
- widgetname = keys.delete('widgetname')
- keys.delete('without_creating')
- elsif keys
- keys = _symbolkey2str(keys)
- widgetname = keys.delete('widgetname')
- keys.delete('without_creating')
- end
-
- legend = self.class.new(parent, :without_creating=>true,
- :widgetname=>widgetname)
- class << legend
- def __destroy_hook__
- TkCore::INTERP.tk_windows.delete(@path)
- end
- end
-
- if keys
- self.legend_configure(keys.update('position'=>legend))
- else
- self.legend_configure('position'=>legend)
- end
- legend
- end
-
- def legend_activate(*pats)
- list(tk_send('legend', 'activate',
- *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
- Tk::BLT::PlotComponent::Element.id2obj(self, elem)
- }
- end
- def legend_deactivate(*pats)
- list(tk_send('legend', 'deactivate',
- *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
- Tk::BLT::PlotComponent::Element.id2obj(self, elem)
- }
- end
- def legend_get(pos, y=nil)
- if y
- Tk::BLT::PlotComponent::Element.id2obj(self,
- tk_send('legend', 'get',
- _at(pos, y)))
- else
- Tk::BLT::PlotComponent::Element.id2obj(self,
- tk_send('legend', 'get', pos))
- end
- end
-
- ###################
-
- def pen_create(id=nil, keys={})
- # tk_send('pen', 'create', tagid(id), keys)
- Tk::BLT::PlotComponent::Pen.new(self, tagid(id), keys)
- end
- def pen_delete(*ids)
- tk_send('pen', 'delete', *(ids.collect{|id| tagid(id)}))
- self
- end
- def pen_names(*pats)
- simplelist(tk_send('pen', 'names',
- *(pats.collect{|pat| tagid(pat)}))).collect{|pen|
- Tk::BLT::PlotComponent::Pen.id2obj(self, pen)
- }
- end
-
- ###################
-
- def postscript_output(file=nil, keys={})
- if file.kind_of?(Hash)
- keys = file
- file = nil
- end
-
- if file
- tk_send('postscript', 'output', file, keys)
- self
- else
- tk_send('postscript', 'output', keys)
- end
- end
-
- ###################
-
- def marker_create(type, keys={})
- case type
- when :text, 'text'
- Tk::BLT::PlotComponent::TextMarker.new(self, keys)
- when :line, 'line'
- Tk::BLT::PlotComponent::LineMarker.new(self, keys)
- when :bitmap, 'bitmap'
- Tk::BLT::PlotComponent::BitmapMarker.new(self, keys)
- when :image, 'image'
- Tk::BLT::PlotComponent::ImageMarker.new(self, keys)
- when :polygon, 'polygon'
- Tk::BLT::PlotComponent::PolygonMarker.new(self, keys)
- when :window, 'window'
- Tk::BLT::PlotComponent::WindowMarker.new(self, keys)
- else
- if type.kind_of?(Tk::BLT::PlotComponent::Marker)
- type.new(self, keys)
- else
- Tk::BLT::PlotComponent::Marker.create_type(self, type, keys)
- end
- end
- end
- def marker_after(id, target=nil)
- if target
- tk_send_without_enc('marker', 'after', tagid(id), tagid(target))
- else
- tk_send_without_enc('marker', 'after', tagid(id))
- end
- self
- end
- def marker_before(id, target=None)
- if target
- tk_send_without_enc('marker', 'before', tagid(id), tagid(target))
- else
- tk_send_without_enc('marker', 'before', tagid(id))
- end
- self
- end
- def marker_delete(*ids)
- tk_send('marker', 'delete', *(ids.collect{|id| tagid(id)}))
- self
- end
- def marker_exist?(id)
- bool(tk_send('marker', 'exists', tagid(id)))
- end
- def marker_names(*pats)
- simplelist(tk_send('marker', 'names',
- *(pats.collect{|pat| tagid(pat)}))).collect{|id|
- Tk::BLT::PlotComponent::Marker.id2obj(self, id)
- }
- end
- def marker_type(id)
- tk_send('marker', 'type', tagid(id))
- end
-
- ###################
-
- def xaxis_cget(option)
- itemcget('xaxis', option)
- end
- def xaxis_configure(slot, value=None)
- if slot.kind_of?(Hash)
- slot = _symbolkey2str(slot)
- if cmd = slot.delete('command')
- slot['command'] = proc{|w, tick|
- cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
- }
- end
- elsif slot == :command || slot == 'command'
- cmd = value
- value = proc{|w, tick|
- cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
- }
- end
- itemconfigure('xaxis', slot, value)
- end
- def xaxis_configinfo(slot=nil)
- itemconfiginfo('xaxis', slot)
- end
- def current_xaxis_configinfo(slot=nil)
- current_itemconfiginfo('xaxis', slot)
- end
- def xaxis_bind(context, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([path, 'xaxis', 'bind'], context, cmd, *args)
- self
- end
- def xaxis_bind_append(context, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([path, 'xaxis', 'bind'], context, cmd, *args)
- self
- end
- def xaxis_bind_remove(context)
- _bind_remove([path, 'xaxis', 'bind'], context)
- self
- end
- def xaxis_bindinfo(context=nil)
- _bindinfo([path, 'xaxis', 'bind'], context)
- end
- def xaxis_invtransform(val)
- list(tk_send('xaxis', 'invtransform', val))
- end
- def xaxis_limits
- list(tk_send('xaxis', 'limits'))
- end
- def xaxis_transform(val)
- list(tk_send('xaxis', 'transform', val))
- end
- def xaxis_use(target=nil)
- if target
- Tk::BLT::PlotComponent::Axis.id2obj(self,
- tk_send('xaxis', 'use',
- tagid(target)))
- else
- Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('xaxis', 'use'))
- end
- end
-
- def x2axis_cget(option)
- itemcget('x2axis', option)
- end
- def x2axis_configure(slot, value=None)
- if slot.kind_of?(Hash)
- slot = _symbolkey2str(slot)
- if cmd = slot.delete('command')
- slot['command'] = proc{|w, tick|
- cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
- }
- end
- elsif slot == :command || slot == 'command'
- cmd = value
- value = proc{|w, tick|
- cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
- }
- end
- itemconfigure('x2axis', slot, value)
- end
- def x2axis_configinfo(slot=nil)
- itemconfiginfo('x2axis', slot)
- end
- def current_x2axis_configinfo(slot=nil)
- current_itemconfiginfo('x2axis', slot)
- end
- def x2axis_bind(context, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([path, 'x2axis', 'bind'], context, cmd, *args)
- self
- end
- def x2axis_bind_append(context, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([path, 'x2axis', 'bind'], context, cmd, *args)
- self
- end
- def x2axis_bind_remove(context)
- _bind_remove([path, 'x2axis', 'bind'], context)
- self
- end
- def x2axis_bindinfo(context=nil)
- _bindinfo([path, 'x2axis', 'bind'], context)
- end
- def x2axis_invtransform(val)
- list(tk_send('x2axis', 'invtransform', val))
- end
- def x2axis_limits
- list(tk_send('x2axis', 'limits'))
- end
- def x2axis_transform(val)
- list(tk_send('x2axis', 'transform', val))
- end
- def x2axis_use(target=nil)
- if target
- Tk::BLT::PlotComponent::Axis.id2obj(self,
- tk_send('x2axis', 'use',
- tagid(target)))
- else
- Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('x2axis', 'use'))
- end
- end
-
- def yaxis_cget(option)
- itemcget('yaxis', option)
- end
- def yaxis_configure(slot, value=None)
- if slot.kind_of?(Hash)
- slot = _symbolkey2str(slot)
- if cmd = slot.delete('command')
- slot['command'] = proc{|w, tick|
- cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
- }
- end
- elsif slot == :command || slot == 'command'
- cmd = value
- value = proc{|w, tick|
- cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
- }
- end
- itemconfigure('yaxis', slot, value)
- end
- def yaxis_configinfo(slot=nil)
- itemconfiginfo('yaxis', slot)
- end
- def current_yaxis_configinfo(slot=nil)
- current_itemconfiginfo('yaxis', slot)
- end
- def yaxis_bind(context, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([path, 'yaxis', 'bind'], context, cmd, *args)
- self
- end
- def yaxis_bind_append(context, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([path, 'yaxis', 'bind'], context, cmd, *args)
- self
- end
- def yaxis_bind_remove(context)
- _bind_remove([path, 'yaxis', 'bind'], context)
- self
- end
- def yaxis_bindinfo(context=nil)
- _bindinfo([path, 'yaxis', 'bind'], context)
- end
- def yaxis_invtransform(val)
- list(tk_send('yaxis', 'invtransform', val))
- end
- def yaxis_limits
- list(tk_send('yaxis', 'limits'))
- end
- def yaxis_transform(val)
- list(tk_send('yaxis', 'transform', val))
- end
- def yaxis_use(target=nil)
- if target
- Tk::BLT::PlotComponent::Axis.id2obj(self,
- tk_send('yaxis', 'use',
- tagid(target)))
- else
- Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('yaxis', 'use'))
- end
- end
-
- def y2axis_cget(option)
- itemcget('y2axis', option)
- end
- def y2axis_configure(slot, value=None)
- if slot.kind_of?(Hash)
- slot = _symbolkey2str(slot)
- if cmd = slot.delete('command')
- slot['command'] = proc{|w, tick|
- cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
- }
- end
- elsif slot == :command || slot == 'command'
- cmd = value
- value = proc{|w, tick|
- cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
- }
- end
- itemconfigure('y2axis', slot, value)
- end
- def y2axis_configinfo(slot=nil)
- axis_configinfo('y2axis', slot)
- end
- def current_y2axis_configinfo(slot=nil)
- current_itemconfiginfo('y2axis', slot)
- end
- def y2axis_bind(context, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([path, 'y2axis', 'bind'], context, cmd, *args)
- self
- end
- def y2axis_bind_append(context, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([path, 'y2axis', 'bind'], context, cmd, *args)
- self
- end
- def y2axis_bind_remove(context)
- _bind_remove([path, 'y2axis', 'bind'], context)
- self
- end
- def y2axis_bindinfo(context=nil)
- _bindinfo([path, 'y2axis', 'bind'], context)
- end
- def y2axis_invtransform(val)
- list(tk_send('y2axis', 'invtransform', val))
- end
- def y2axis_limits
- list(tk_send('y2axis', 'limits'))
- end
- def y2axis_transform(val)
- list(tk_send('y2axis', 'transform', val))
- end
- def y2axis_use(target=nil)
- if target
- Tk::BLT::PlotComponent::Axis.id2obj(self,
- tk_send('y2axis', 'use',
- tagid(target)))
- else
- Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('y2axis', 'use'))
- end
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/container.rb b/ext/tk/lib/tkextlib/blt/container.rb
deleted file mode 100644
index 60ba1dec1e..0000000000
--- a/ext/tk/lib/tkextlib/blt/container.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# tkextlib/blt/container.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- class Container < TkWindow
- TkCommandNames = ['::blt::container'.freeze].freeze
- WidgetClassName = 'Container'.freeze
- WidgetClassNames[WidgetClassName] = self
- end
-
- def __strval_optkeys
- super() << 'name'
- end
- private :__strval_optkeys
-
- def find_command(pat)
- list(tk_send_without_enc(tk_call(self.path, 'find', '-command', pat)))
- end
-
- def find_name(pat)
- list(tk_send_without_enc(tk_call(self.path, 'find', '-name', pat)))
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/cutbuffer.rb b/ext/tk/lib/tkextlib/blt/cutbuffer.rb
deleted file mode 100644
index 1cc39dfb94..0000000000
--- a/ext/tk/lib/tkextlib/blt/cutbuffer.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# tkextlib/blt/cutbuffer.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- module CutBuffer
- TkCommandNames = ['::blt::cutbuffer'.freeze].freeze
-
- def self.get(num = 0)
- Tk.tk_call('::blt::cutbuffer', 'get', num)
- end
- def self.rotate(count = 1)
- Tk.tk_call('::blt::cutbuffer', 'rotate', count)
- end
- def self.set(val, num = 0)
- Tk.tk_call('::blt::cutbuffer', 'set', val, num)
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/dragdrop.rb b/ext/tk/lib/tkextlib/blt/dragdrop.rb
deleted file mode 100644
index 68fb9e591a..0000000000
--- a/ext/tk/lib/tkextlib/blt/dragdrop.rb
+++ /dev/null
@@ -1,214 +0,0 @@
-#
-# tkextlib/blt/dragdrop.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/itemconfig'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- module DragDrop
- extend TkCore
-
- TkCommandNames = ['::blt::drag&drop'.freeze].freeze
-
- class Token < TkWindow
- WidgetClassName = 'DragDropToken'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def initialize(arg)
- if arg.kind_of?(Hash) # arg is a hash includes the widgetpath of token
- arg = _symbolkey2str(arg)
- install_win(nil, arg['widgetname'])
- else # arg is a drag&drop source
- tk_call('::blt::drag&drop', 'source', arg)
- install_win(nil, tk_call('::blt::drag&drop', 'token', arg))
- end
- end
- end
-
- ###################################
-
- extend TkItemConfigMethod
- extend Tk::ValidateConfigure
-
- class << self
- def __item_config_cmd(id) # id := ['source'|'target', win]
- ['::blt::drag&drop', id[0], id[1]]
- end
- private :__item_config_cmd
-
- def __item_boolval_optkeys(id)
- super(id) << 'selftarget'
- end
- private :__item_boolval_optkeys
-
- def __item_listval_optkeys(id)
- super(id) << 'send'
- end
- private :__item_listval_optkeys
-
- def __item_strval_optkeys(id)
- super(id) << 'rejectbg' << 'rejectfg' << 'tokenbg'
- end
- private :__item_strval_optkeys
-
- undef itemcget
- private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
-
- def source_configure(win, slot, value=None)
- itemconfigure(['source', win], slot, value)
- end
- def source_configinfo(win, slot=nil)
- itemconfiginfo(['source', win], slot)
- end
- def current_source_configinfo(win, slot=nil)
- current_itemconfiginfo(['source', win], slot)
- end
- end
-
- class PackageCommand < TkValidateCommand
- class ValidateArgs < TkUtil::CallbackSubst
- KEY_TBL = [
- [ ?t, ?w, :token ],
- [ ?W, ?w, :widget ],
- nil
- ]
-
- PROC_TBL = [
- [ ?w, TkComm.method(:window) ],
- nil
- ]
-
- _setup_subst_table(KEY_TBL, PROC_TBL)
-
- def self.ret_val(val)
- val
- end
- end
-
- def self._config_keys
- ['packagecmd']
- end
- end
-
- class SiteCommand < TkValidateCommand
- class ValidateArgs < TkUtil::CallbackSubst
- KEY_TBL = [
- [ ?s, ?b, :compatible ],
- [ ?t, ?w, :token ],
- nil
- ]
-
- PROC_TBL = [
- [ ?b, TkComm.method(:bool) ],
- [ ?w, TkComm.method(:window) ],
- nil
- ]
-
- _setup_subst_table(KEY_TBL, PROC_TBL)
-
- def self.ret_val(val)
- val
- end
- end
-
- def self._config_keys
- ['sitecmd']
- end
- end
-
- def self.__validation_class_list
- super() << PackageCommand << SiteCommand
- end
-
- class << self
- Tk::ValidateConfigure.__def_validcmd(binding, PackageCommand)
- Tk::ValidateConfigure.__def_validcmd(binding, SiteCommand)
- end
-
- ###################################
-
- class DnD_Handle < TkUtil::CallbackSubst
- KEY_TBL = [
- [ ?i, ?s, :ip_name ],
- [ ?v, ?v, :value ],
- [ ?W, ?w, :widget ],
- nil
- ]
-
- PROC_TBL = [
- [ ?i, TkComm.method(:string) ],
- [ ?v, TkComm.method(:tk_tcl2ruby) ],
- [ ?w, TkComm.method(:window) ],
- nil
- ]
-
- _setup_subst_table(KEY_TBL, PROC_TBL)
- end
-
- def self.source_handler(win, datatype, cmd=Proc.new, *args)
- _bind_for_event_class(DnD_Handle,
- ['::blt::drag&drop', 'source', win, 'handler'],
- cmd, *args)
- end
-
- def self.target_handler(win, datatype, cmd=Proc.new, *args)
- _bind_for_event_class(DnD_Handle,
- ['::blt::drag&drop', 'target', win, 'handler'],
- cmd, *args)
- end
-
- ###################################
-
- def self.init_source(win)
- tk_call('::blt::drag&drop', 'source', win)
- end
-
- def self.source()
- list(tk_call('::blt::drag&drop', 'source'))
- end
-
- def self.source_handler_list(win)
- simplelist(tk_call('::blt::drag&drop', 'source', win, 'handler'))
- end
- def self.source_handler_info(win, type)
- tk_tcl2ruby(tk_call('::blt::drag&drop', 'source', win, 'handler', type))
- end
-
- def self.target
- list(tk_call('::blt::drag&drop', 'target'))
- end
- def self.target_handler_list(win)
- simplelist(tk_call('::blt::drag&drop', 'target', win, 'handler'))
- end
-
- def self.handle_target(win, type, val=None)
- tk_call('::blt::drag&drop', 'target', win, 'handle', type, val)
- end
-
- def self.token(win)
- window(tk_call('::blt::drag&drop', 'token', win))
- end
-
- def self.drag(win, x, y)
- tk_call('::blt::drag&drop', 'drag', win, x, y)
- end
- def self.drop(win, x, y)
- tk_call('::blt::drag&drop', 'drop', win, x, y)
- end
-
- def self.errors(cmd=Proc.new)
- tk_call('::blt::drag&drop', 'errors', cmd)
- end
-
- def self.active
- bool(tk_call('::blt::drag&drop', 'active'))
- end
-
- def self.location(x=None, y=None)
- list(tk_call('::blt::drag&drop', 'location', x, y))
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/eps.rb b/ext/tk/lib/tkextlib/blt/eps.rb
deleted file mode 100644
index 586a42470c..0000000000
--- a/ext/tk/lib/tkextlib/blt/eps.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# tkextlib/blt/eps.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/canvas'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- class EPS < TkcItem
- CItemTypeName = 'eps'.freeze
- CItemTypeToClass[CItemTypeName] = self
- end
-end
-
-class TkCanvas
- alias __BLT_EPS_item_strval_optkeys __item_strval_optkeys
- def __item_strval_optkeys(id)
- __BLT_EPS_item_strval_optkeys(id) + [
- 'shadowcolor', 'title', 'titlecolor'
- ]
- end
- private :__item_strval_optkeys
-
- alias __BLT_EPS_item_boolval_optkeys __item_boolval_optkeys
- def __item_boolval_optkeys(id)
- __BLT_EPS_item_boolval_optkeys(id) + ['showimage']
- end
- private :__item_boolval_optkeys
-end
-
diff --git a/ext/tk/lib/tkextlib/blt/graph.rb b/ext/tk/lib/tkextlib/blt/graph.rb
deleted file mode 100644
index 9ae99bff5c..0000000000
--- a/ext/tk/lib/tkextlib/blt/graph.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# tkextlib/blt/graph.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-require 'tkextlib/blt/component.rb'
-
-module Tk::BLT
- class Graph < TkWindow
- TkCommandNames = ['::blt::graph'.freeze].freeze
- WidgetClassName = 'Graph'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- include PlotComponent
- include GraphCommand
-
- def __boolval_optkeys
- ['bufferelements', 'invertxy']
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- ['text', 'label', 'title', 'file', 'plotbackground']
- end
- private :__strval_optkeys
-
-=begin
- BarElement_ID = ['blt_graph_bar'.freeze, '00000'.taint].freeze
-
- def bar(elem=nil, keys={})
- if elem.kind_of?(Hash)
- keys = elem
- elem = nil
- end
- unless elem
- elem = BarElement_ID.join(TkCore::INTERP._ip_id_).freeze
- BarElement_ID[1].succ!
- end
- tk_send('bar', elem, keys)
- Element.new(self, elem, :without_creating=>true)
- end
-=end
-
- def extents(item)
- num_or_str(tk_send_without_enc('extents', item))
- end
-
- def invtransform(x, y)
- list(tk_send_without_enc('invtransform', x, y))
- end
-
- def inside(x, y)
- bool(tk_send_without_enc('inside', x, y))
- end
-
- def snap(output, keys={})
- tk_send_without_enc('snap', *(hash_kv(keys, false) + output))
- self
- end
-
- def transform(x, y)
- list(tk_send_without_enc('transform', x, y))
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/htext.rb b/ext/tk/lib/tkextlib/blt/htext.rb
deleted file mode 100644
index a0cf3dc036..0000000000
--- a/ext/tk/lib/tkextlib/blt/htext.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-#
-# tkextlib/blt/htext.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/itemconfig.rb'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- class Htext<TkWindow
- Htext_Var = TkVarAccess.new_hash('htext')
- Htext_Widget = TkVarAccess.new('htext(widget)', :window)
- Htext_File = TkVarAccess.new('htext(file)')
- Htext_Line = TkVarAccess.new('htext(line)')
-
- include TkItemConfigMethod
- include Scrollable
-
- TkCommandNames = ['::blt::htext'.freeze].freeze
- WidgetClassName = 'Htext'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- alias window_cget itemcget
- alias window_configure itemconfigure
- alias window_configuinfo itemconfiginfo
- alias current_window_configuinfo current_itemconfiginfo
-
- def __strval_optkeys
- super() << 'filename'
- end
- private :__strval_optkeys
-
- def append(win, keys={})
- tk_send('append', _epath(win), keys)
- self
- end
-
- def goto_line(idx)
- tk_send_without_enc('gotoline', idx)
- self
- end
- def current_line
- number(tk_send_without_enc('gotoline'))
- end
-
- def index(str)
- number(tk_send('index', str))
- end
-
- def line_pos(str)
- tk_send('linepos', str)
- end
-
- def range(from=None, to=None)
- tk_send_without_enc('range', from, to)
- end
-
- def scan_mark(pos)
- tk_send_without_enc('scan', 'mark', pos)
- self
- end
-
- def scan_dragto(pos)
- tk_send_without_enc('scan', 'dragto', pos)
- self
- end
-
- def search(pat, from=None, to=None)
- num = number(tk_send('search', pat, from, to))
- (num < 0)? nil: num
- end
-
- def selection_adjust(index)
- tk_send_without_enc('selection', 'adjust', index)
- self
- end
- def selection_clear()
- tk_send_without_enc('selection', 'clear')
- self
- end
- def selection_from(index)
- tk_send_without_enc('selection', 'from', index)
- self
- end
- def selection_line(index)
- tk_send_without_enc('selection', 'line', index)
- self
- end
- def selection_present()
- bool(tk_send_without_enc('selection', 'present'))
- end
- def selection_range(first, last)
- tk_send_without_enc('selection', 'range', first, last)
- self
- end
- def selection_to(index)
- tk_send_without_enc('selection', 'to', index)
- self
- end
- def selection_word(index)
- tk_send_without_enc('selection', 'word', index)
- self
- end
-
- def windows(pat=None)
- list(tk_send('windows', pat))
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/setup.rb b/ext/tk/lib/tkextlib/blt/setup.rb
deleted file mode 100644
index ce0f0bd4d4..0000000000
--- a/ext/tk/lib/tkextlib/blt/setup.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# setup.rb -- setup script before calling TkPackage.require()
-#
-# If you need some setup operations (for example, add a library path
-# to the library search path) before using Tcl/Tk library packages
-# wrapped by Ruby scripts in this directory, please write the setup
-# operations in this file.
-#
diff --git a/ext/tk/lib/tkextlib/blt/spline.rb b/ext/tk/lib/tkextlib/blt/spline.rb
deleted file mode 100644
index 9f75a0b217..0000000000
--- a/ext/tk/lib/tkextlib/blt/spline.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# tkextlib/blt/spline.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- module Spline
- extend TkCore
-
- TkCommandNames = ['::blt::spline'.freeze].freeze
-
- def self.natural(x, y, sx, sy)
- tk_call('::blt::spline', 'natural', x, y, sx, sy)
- end
-
- def self.quadratic(x, y, sx, sy)
- tk_call('::blt::spline', 'quadratic', x, y, sx, sy)
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/stripchart.rb b/ext/tk/lib/tkextlib/blt/stripchart.rb
deleted file mode 100644
index fe5afbb095..0000000000
--- a/ext/tk/lib/tkextlib/blt/stripchart.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# tkextlib/blt/stripchart.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-require 'tkextlib/blt/component.rb'
-
-module Tk::BLT
- class Stripchart < TkWindow
- TkCommandNames = ['::blt::stripchart'.freeze].freeze
- WidgetClassName = 'Stripchart'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- include PlotComponent
- include GraphCommand
-
- def __boolval_optkeys
- ['bufferelements', 'buffergraph', 'invertxy']
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- ['text', 'label', 'title', 'file',
- 'background', 'plotbackground']
- end
- private :__strval_optkeys
-
-=begin
- BarElement_ID = ['blt_stripchart_bar'.freeze, '00000'.taint].freeze
-
- def bar(elem=nil, keys={})
- if elem.kind_of?(Hash)
- keys = elem
- elem = nil
- end
- unless elem
- elem = BarElement_ID.join(TkCore::INTERP._ip_id_).freeze
- BarElement_ID[1].succ!
- end
- tk_send('bar', elem, keys)
- Element.new(self, elem, :without_creating=>true)
- end
-=end
-
- def extents(item)
- num_or_str(tk_send_without_enc('extents', item))
- end
-
- def invtransform(x, y)
- list(tk_send_without_enc('invtransform', x, y))
- end
-
- def inside(x, y)
- bool(tk_send_without_enc('inside', x, y))
- end
-
- def metafile(file=None)
- # Windows only
- tk_send('metafile', file)
- self
- end
-
- def snap(output, keys={})
- tk_send_without_enc('snap', *(hash_kv(keys, false) + output))
- self
- end
-
- def transform(x, y)
- list(tk_send_without_enc('transform', x, y))
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/table.rb b/ext/tk/lib/tkextlib/blt/table.rb
deleted file mode 100644
index fc1bf54e65..0000000000
--- a/ext/tk/lib/tkextlib/blt/table.rb
+++ /dev/null
@@ -1,344 +0,0 @@
-#
-# tkextlib/blt/table.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/itemconfig.rb'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- module Table
- include Tk
- extend Tk
- extend TkItemConfigMethod
-
- TkCommandNames = ['::blt::table'.freeze].freeze
-
- module TableContainer
- def blt_table_add(*args)
- Tk::BLT::Table.add(@path, *args)
- self
- end
-
- def blt_table_arrange()
- Tk::BLT::Table.arrange(@path)
- self
- end
-
- def blt_table_cget(*args)
- Tk::BLT::Table.cget(@path, *args)
- end
-
- def blt_table_configure(*args)
- Tk::BLT::Table.configure(@path, *args)
- self
- end
-
- def blt_table_configinfo(*args)
- Tk::BLT::Table.configinfo(@path, *args)
- end
-
- def blt_table_current_configinfo(*args)
- Tk::BLT::Table.current_configinfo(@path, *args)
- end
-
- def blt_table_locate(x, y)
- Tk::BLT::Table.locate(@path, x, y)
- end
-
- def blt_table_delete(*args)
- Tk::BLT::Table.delete(@path, *args)
- self
- end
-
- def blt_table_extents(item)
- Tk::BLT::Table.extents(@path, item)
- end
-
- def blt_table_insert(*args)
- Tk::BLT::Table.insert(@path, *args)
- self
- end
-
- def blt_table_insert_before(*args)
- Tk::BLT::Table.insert_before(@path, *args)
- self
- end
-
- def blt_table_insert_after(*args)
- Tk::BLT::Table.insert_after(@path, *args)
- self
- end
-
- def blt_table_join(first, last)
- Tk::BLT::Table.join(@path, first, last)
- self
- end
-
- def blt_table_save()
- Tk::BLT::Table.save(@path)
- end
-
- def blt_table_search(*args)
- Tk::BLT::Table.search(@path, *args)
- end
-
- def blt_table_split(*args)
- Tk::BLT::Table.split(@path, *args)
- self
- end
-
- def blt_table_itemcget(*args)
- Tk::BLT::Table.itemcget(@path, *args)
- end
-
- def blt_table_itemconfigure(*args)
- Tk::BLT::Table.itemconfigure(@path, *args)
- self
- end
-
- def blt_table_itemconfiginfo(*args)
- Tk::BLT::Table.itemconfiginfo(@path, *args)
- end
-
- def blt_table_current_itemconfiginfo(*args)
- Tk::BLT::Table.current_itemconfiginfo(@path, *args)
- end
-
- def blt_table_iteminfo(item)
- Tk::BLT::Table.iteminfo(@path, item)
- end
- end
- end
-end
-
-
-############################################
-class << Tk::BLT::Table
- def __item_cget_cmd(id) # id := [ container, item ]
- ['::blt::table', 'cget', id[0].path, id[1]]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id) # id := [ container, item, ... ]
- container, *items = id
- ['::blt::table', 'configure', container.path, *items]
- end
- private :__item_config_cmd
-
- def __item_pathname(id)
- id[0].path + ';'
- end
- private :__item_pathname
-
- alias __itemcget itemcget
- alias __itemconfigure itemconfigure
- alias __itemconfiginfo itemconfiginfo
- alias __current_itemconfiginfo current_itemconfiginfo
-
- private :__itemcget, :__itemconfigure
- private :__itemconfiginfo, :__current_itemconfiginfo
-
- def __boolval_optkeys
- super() << 'propagate'
- end
- private :__boolval_optkeys
-
- def tagid(tag)
- if tag.kind_of?(Array)
- case tag[0]
- when Integer
- # [row, col]
- tag.join(',')
- when :c, :C, 'c', 'C', :r, :R, 'r', 'R'
- # c0 or r1 or C*, and so on
- tag.collect{|elem| elem.to_s}.join('')
- else
- tag
- end
- elsif tag.kind_of?(TkWindow)
- _epath(tag)
- else
- tag
- end
- end
-
- def tagid2obj(tagid)
- tagid
- end
-
- ############################################
-
- def cget(container, option)
- __itemcget([container], option)
- end
-
- def configure(container, *args)
- __itemconfigure([container], *args)
- end
-
- def configinfo(container, *args)
- __itemconfiginfo([container], *args)
- end
-
- def current_configinfo(container, *args)
- __current_itemconfiginfo([container], *args)
- end
-
- def itemcget(container, item, option)
- __itemcget([container, tagid(item)], option)
- end
-
- def itemconfigure(container, *args)
- if args[-1].kind_of?(Hash)
- # container, item, item, ... , hash_optkeys
- keys = args.pop
- id = [container]
- args.each{|item| id << tagid(item)}
- __itemconfigure(id, keys)
- else
- # container, item, item, ... , option, value
- val = args.pop
- opt = args.pop
- id = [container]
- args.each{|item| id << tagid(item)}
- __itemconfigure(id, opt, val)
- end
- end
-
- def itemconfiginfo(container, *args)
- slot = args[-1]
- if slot.kind_of?(String) || slot.kind_of?(Symbol)
- slot = slot.to_s
- if slot[0] == ?. || slot =~ /^\d+,\d+$/ || slot =~ /^(c|C|r|R)(\*|\d+)/
- # widget || row,col || Ci or Ri
- slot = nil
- else
- # option
- slot = args.pop
- end
- else
- slot = nil
- end
-
- id = [container]
- args.each{|item| id << tagid(item)}
- __itemconfiginfo(id, slot)
- end
-
- def info(container)
- ret = {}
- inf = list(tk_call('::blt::table', 'info', container))
- until inf.empty?
- opt = inf.slice!(0..1)
- ret[opt[1..-1]] = opt[1]
- end
- ret
- end
-
- def iteminfo(container, item)
- ret = {}
- inf = list(tk_call('::blt::table', 'info', container, tagid(item)))
- until inf.empty?
- opt = inf.slice!(0..1)
- ret[opt[1..-1]] = opt[1]
- end
- ret
- end
-
- ############################################
-
- def create_container(container)
- tk_call('::blt::table', container)
- begin
- class << container
- include Tk::BLT::TABLE::TableContainer
- end
- rescue
- warn('fail to include TableContainer methods (frozen object?)')
- end
- container
- end
-
- def add(container, *args)
- if args.empty?
- tk_call('::blt::table', container)
- else
- args = args.collect{|arg|
- if arg.kind_of?(TkWindow)
- _epath(arg)
- elsif arg.kind_of?(Array) # index
- arg.join(',')
- else
- arg
- end
- }
- tk_call('::blt::table', container, *args)
- end
- end
-
- def arrange(container)
- tk_call('::blt::table', 'arrange', container)
- end
-
- def delete(container, *args)
- tk_call('::blt::table', 'delete', container, *args)
- end
-
- def extents(container, item)
- ret = []
- inf = list(tk_call('::blt::table', 'extents', container, item))
- ret << inf.slice!(0..4) until inf.empty?
- ret
- end
-
- def forget(*wins)
- wins = wins.collect{|win| _epath(win)}
- tk_call('::blt::table', 'forget', *wins)
- end
-
- def insert(container, *args)
- tk_call('::blt::table', 'insert', container, *args)
- end
-
- def insert_before(container, *args)
- tk_call('::blt::table', 'insert', container, '-before', *args)
- end
-
- def insert_after(container, *args)
- tk_call('::blt::table', 'insert', container, '-after', *args)
- end
-
- def join(container, first, last)
- tk_call('::blt::table', 'join', container, first, last)
- end
-
- def locate(container, x, y)
- tk_call('::blt::table', 'locate', container, x, y)
- end
-
- def containers(arg={})
- list(tk_call('::blt::table', 'containers', *hash_kv(arg)))
- end
-
- def containers_pattern(pat)
- list(tk_call('::blt::table', 'containers', '-pattern', pat))
- end
-
- def containers_slave(win)
- list(tk_call('::blt::table', 'containers', '-slave', win))
- end
-
- def save(container)
- tk_call('::blt::table', 'save', container)
- end
-
- def search(container, keys={})
- list(tk_call('::blt::table', 'containers', *hash_kv(keys)))
- end
-
- def split(container, *args)
- tk_call('::blt::table', 'split', container, *args)
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/tabnotebook.rb b/ext/tk/lib/tkextlib/blt/tabnotebook.rb
deleted file mode 100644
index 508fa2b82f..0000000000
--- a/ext/tk/lib/tkextlib/blt/tabnotebook.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# tkextlib/blt/tabnotebook.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-require 'tkextlib/blt/tabset.rb'
-
-module Tk::BLT
- class Tabnotebook < Tabset
- TkCommandNames = ['::blt::tabnotebook'.freeze].freeze
- WidgetClassName = 'Tabnotebook'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def get_tab(index)
- Tk::BLT::Tabset::Tab.id2obj(tk_send_without_enc('id', tagindex(index)))
- end
- alias get_id get_tab
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/tabset.rb b/ext/tk/lib/tkextlib/blt/tabset.rb
deleted file mode 100644
index c26b6ee001..0000000000
--- a/ext/tk/lib/tkextlib/blt/tabset.rb
+++ /dev/null
@@ -1,401 +0,0 @@
-#
-# tkextlib/blt/tabset.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- class Tabset < TkWindow
- class Tab < TkObject
- include TkTreatItemFont
-
- TabID_TBL = TkCore::INTERP.create_table
- TabsetTab_ID = ['blt_tabset_tab'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ TabID_TBL.clear }
-
- def self.id2obj(tabset, id)
- tpath = tabset.path
- return id unless TabID_TBL[tpath]
- TabID_TBL[tpath][id]? TabID_TBL[tpath]: id
- end
-
- def self.new(parent, pos=nil, name=nil, keys={})
- if pos.kind_of?(Hash)
- keys = pos
- name = nil
- pos = nil
- end
- if name.kind_of?(Hash)
- keys = name
- name = nil
- end
-
- if name && TabID_TBL[parent.path] && TabID_TBL[parent.path][name]
- TabID_TBL[parent.path][name]
- else
- super(parent, pos, name, keys)
- end
- end
-
- def initialize(parent, pos, name, keys)
- @t = parent
- @tpath = parent.path
- if name
- @path = @id = name
- TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath]
- TabID_TBL[@tpath][@id] = self
-
- unless (list(tk_call(@tpath, 'tab', 'names', @id)).empty?)
- if pos
- idx = tk_call(@tpath, 'index', '-name', @id)
- if pos.to_s == 'end'
- tk_call(@tpath, idx, 'moveto', 'after', 'end')
- else
- tk_call(@tpath, idx, 'moveto', 'before', pos)
- end
- end
- tk_call(@tpath, 'tab', 'configure', @id, keys)
- return
- end
-
- else
- @path = @id = TabsetTab_ID.join(TkCore::INTERP._ip_id_)
- TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath]
- TabID_TBL[@tpath][@id] = self
- TabsetTab_ID[1].succ!
- end
-
- pos = 'end' unless pos
- tk_call(@tpath, 'insert', pos, @id, keys)
- end
-
- #def bind(context, cmd=Proc.new, *args)
- # @t.tab_bind(@id, context, cmd, *args)
- # self
- #end
- def bind(context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- @t.tab_bind(@id, context, cmd, *args)
- self
- end
- #def bind_append(context, cmd=Proc.new, *args)
- # @t.tab_bind_append(@id, context, cmd, *args)
- # self
- #end
- def bind_append(context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- @t.tab_bind_append(@id, context, cmd, *args)
- self
- end
- def bind_remove(context)
- @t.tab_bind_remove(@id, context)
- self
- end
- def bindinfo(context=nil)
- @t.tab_bindinfo(@id, context)
- end
-
- def cget(*args)
- @t.tab_cget(@id, *args)
- end
- def configure(*args)
- @t.tab_configure(@id, *args)
- end
- def configinfo(*args)
- @t.tab_configinfo(@id, *args)
- end
- def current_configinfo(*args)
- @t.current_tab_configinfo(@id, *args)
- end
-
- def delete()
- @t.delete(@id)
- TabID_TBL[@tpath].delete(@id)
- self
- end
-
- def get_name()
- @id.dup
- end
-
- def focus()
- @t.focus(self.index)
- end
-
- def index()
- @t.index_name(@id)
- end
-
- def invoke()
- @t.invoke(self.index)
- end
-
- def move_before(idx)
- @t.move_before(self.index, idx)
- end
- def move_after(idx)
- @t.move_after(self.index, idx)
- end
-
- def perforation_highlight(mode)
- @t.perforation.highlight(self.index, mode)
- end
- def perforation_invoke()
- @t.perforation.invoke(self.index)
- end
-
- def see()
- @t.see(self.index)
- end
-
- def tearoff(name=None)
- @t.tab_tearoff(self.index, *args)
- end
- end
-
- ########################################
-
- class NamedTab < Tab
- def self.new(parent, name)
- super(parent, nil, name, {})
- end
- end
-
- ########################################
-
- include X_Scrollable
- include TkItemConfigMethod
-
- TkCommandNames = ['::blt::tabset'.freeze].freeze
- WidgetClassName = 'Tabset'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __destroy_hook__
- Tk::BLT::Tabset::Tab::TabID_TBL.delete(@path)
- end
-
- ########################################
-
- def __boolval_optkeys
- super() << 'samewidth' << 'tearoff'
- end
- private :__strval_optkeys
-
- def __strval_optkeys
- super() << 'tabbackground' << 'tabforeground'
- end
- private :__strval_optkeys
-
- def __item_cget_cmd(id)
- [self.path, 'tab', 'cget', id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- [self.path, 'tab', 'configure', id]
- end
- private :__item_config_cmd
-
- def __item_pathname(tagOrId)
- if tagOrId.kind_of?(Tk::BLT::Tabset::Tab)
- self.path + ';' + tagOrId.id.to_s
- else
- self.path + ';' + tagOrId.to_s
- end
- end
- private :__item_pathname
-
- alias tab_cget itemcget
- alias tab_configure itemconfigure
- alias tab_configinfo itemconfiginfo
- alias current_tab_configinfo current_itemconfiginfo
-
- def __item_strval_optkeys(id)
- super(id) << 'shadow'
- end
- private :__item_strval_optkeys
-
- def tagid(tab)
- if tab.kind_of?(Tk::BLT::Tabset::Tab)
- tab.id
- else
- tab
- end
- end
-
- def tagindex(tab)
- if tab.kind_of?(Tk::BLT::Tabset::Tab)
- tab.index
- else
- tab
- end
- end
-
- ########################################
-
- def activate(index)
- tk_send('activate', tagindex(index))
- self
- end
- alias highlight activate
-
- #def tabbind(tag, context, cmd=Proc.new, *args)
- # _bind([path, "bind", tagid(tag)], context, cmd, *args)
- # self
- #end
- def tabbind(tag, context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([path, "bind", tagid(tag)], context, cmd, *args)
- self
- end
- #def tabbind_append(tag, context, cmd=Proc.new, *args)
- # _bind_append([path, "bind", tagid(tag)], context, cmd, *args)
- # self
- #end
- def tabbind_append(tag, context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([path, "bind", tagid(tag)], context, cmd, *args)
- self
- end
- def tabbind_remove(tag, context)
- _bind_remove([path, "bind", tagid(tag)], context)
- self
- end
- def tabbindinfo(tag, context=nil)
- _bindinfo([path, "bind", tagid(tag)], context)
- end
-
- def delete(first, last=None)
- tk_send('delete', tagindex(first), tagindex(last))
- if first.kind_of?(Tk::BLT::Tabset::Tab)
- TabID_TBL[@path].delete(first.id)
- end
- # middle tabs of the range are unknown
- if last.kind_of?(Tk::BLT::Tabset::Tab)
- TabID_TBL[@path].delete(last.id)
- end
- self
- end
-
- def focus(index)
- tk_send('focus', tagindex(index))
- self
- end
-
- def get_tab(index)
- Tk::BLT::Tabset::Tab.id2obj(tk_send_without_enc('get', tagindex(index)))
- end
-
- def index(str)
- num_or_str(tk_send('index', str))
- end
- def index_name(tab)
- num_or_str(tk_send('index', '-mame', tagid(tab)))
- end
-
- def insert(pos, tab, keys={})
- Tk::BLT::Tabset::Tab.new(self, tagindex(pos), tagid(tab), keys)
- end
-
- def invoke(index)
- tk_send('invoke', tagindex(index))
- end
-
- def move_before(index, base_idx)
- tk_send('move', tagindex(index), 'before', tagindex(base_idx))
- self
- end
- def move_after(index, base_idx)
- tk_send('move', tagindex(index), 'after', tagindex(base_idx))
- self
- end
-
- def nearest(x, y)
- Tk::BLT::Tabset::Tab.id2obj(num_or_str(tk_send_without_enc('nearest', x, y)))
- end
-
- def perforation_highlight(index, mode)
- tk_send('perforation', 'highlight', tagindex(index), mode)
- self
- end
- def perforation_invoke(index)
- tk_send('perforation', 'invoke', tagindex(index))
- end
-
- def scan_mark(x, y)
- tk_send_without_enc('scan', 'mark', x, y)
- self
- end
- def scan_dragto(x, y)
- tk_send_without_enc('scan', 'dragto', x, y)
- self
- end
-
- def see(index)
- tk_send('see', tagindex(index))
- self
- end
-
- def size()
- number(tk_send_without_enc('size'))
- end
-
- def select(index)
- tk_send('select', tagindex(index))
- self
- end
-
- def tab_names(pat=None)
- simplelist(tk_send('tab', 'names', pat)).collect{|name|
- Tk::BLT::Tabset::Tab.id2obj(name)
- }
- end
-
- def tab_tearoff(index, name=None)
- window(tk_send('tab', 'tearoff', tagindex(index), name))
- end
-
- def xscrollcommand(cmd=Proc.new)
- configure_cmd 'scrollcommand', cmd
- self
- end
- alias scrollcommand xscrollcommand
-
- def xview(*index)
- if index.empty?
- list(tk_send_without_enc('view'))
- else
- tk_send_without_enc('view', *index)
- self
- end
- end
- alias view xview
- alias view_moveto xview_moveto
- alias view_scroll xview_scroll
-
- alias scrollbar xscrollbar
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/ted.rb b/ext/tk/lib/tkextlib/blt/ted.rb
deleted file mode 100644
index 39495842b4..0000000000
--- a/ext/tk/lib/tkextlib/blt/ted.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-# tkextlib/blt/ted.rb
-#
-# *** This is alpha version, because there is no document on BLT. ***
-#
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- module Ted
- extend TkCore
-
- TkCommandNames = ['::blt::ted'.freeze].freeze
-
- ##############################
-
- extend TkItemConfigMethod
-
- class << self
- def __item_cget_cmd(id)
- ['::blt::ted', 'cget', id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- ['::blt::ted', 'configure', id]
- end
- private :__item_config_cmd
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-
- def cget(master, option)
- itemconfigure(master, slot, value)
- end
- def configure(master, slot, value=None)
- itemconfigure(master, slot, value)
- end
- def configinfo(master, slot=nil)
- itemconfiginfo(master, slot)
- end
- def current_configinfo(master, slot=nil)
- current_itemconfiginfo(master, slot)
- end
- end
-
- ##############################
-
- def self.edit(master, *args)
- tk_call('::blt::ted', 'edit', master, *args)
- end
- def self.rep(master, *args)
- tk_call('::blt::ted', 'rep', master, *args)
- end
- def self.select(master, *args)
- tk_call('::blt::ted', 'select', master, *args)
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/tile.rb b/ext/tk/lib/tkextlib/blt/tile.rb
deleted file mode 100644
index 5f5242f299..0000000000
--- a/ext/tk/lib/tkextlib/blt/tile.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# tkextlib/blt/tile.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- module Tile
- autoload :Button, 'tkextlib/blt/tile/button.rb'
- autoload :CheckButton, 'tkextlib/blt/tile/checkbutton.rb'
- autoload :Checkbutton, 'tkextlib/blt/tile/checkbutton.rb'
- autoload :Radiobutton, 'tkextlib/blt/tile/radiobutton.rb'
- autoload :RadioButton, 'tkextlib/blt/tile/radiobutton.rb'
- autoload :Frame, 'tkextlib/blt/tile/frame.rb'
- autoload :Label, 'tkextlib/blt/tile/label.rb'
- autoload :Scrollbar, 'tkextlib/blt/tile/scrollbar.rb'
- autoload :Toplevel, 'tkextlib/blt/tile/toplevel.rb'
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/tile/button.rb b/ext/tk/lib/tkextlib/blt/tile/button.rb
deleted file mode 100644
index dd715c8b98..0000000000
--- a/ext/tk/lib/tkextlib/blt/tile/button.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# tkextlib/blt/tile/button.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/button'
-require 'tkextlib/blt/tile.rb'
-
-module Tk::BLT
- module Tile
- class Button < TkButton
- TkCommandNames = ['::blt::tile::button'.freeze].freeze
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb b/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb
deleted file mode 100644
index ebe79179a5..0000000000
--- a/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# tkextlib/blt/tile/checkbutton.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/checkbutton'
-require 'tkextlib/blt/tile.rb'
-
-module Tk::BLT
- module Tile
- class Checkbutton < TkCheckbutton
- TkCommandNames = ['::blt::tile::checkbutton'.freeze].freeze
- end
- CheckButton = Checkbutton
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/tile/frame.rb b/ext/tk/lib/tkextlib/blt/tile/frame.rb
deleted file mode 100644
index 10469fd35f..0000000000
--- a/ext/tk/lib/tkextlib/blt/tile/frame.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# tkextlib/blt/tile/frame.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/frame'
-require 'tkextlib/blt/tile.rb'
-
-module Tk::BLT
- module Tile
- class Frame < TkFrame
- TkCommandNames = ['::blt::tile::frame'.freeze].freeze
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/tile/label.rb b/ext/tk/lib/tkextlib/blt/tile/label.rb
deleted file mode 100644
index ec67babd58..0000000000
--- a/ext/tk/lib/tkextlib/blt/tile/label.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# tkextlib/blt/tile/label.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/label'
-require 'tkextlib/blt/tile.rb'
-
-module Tk::BLT
- module Tile
- class Label < TkLabel
- TkCommandNames = ['::blt::tile::label'.freeze].freeze
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb b/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb
deleted file mode 100644
index 7573aa08d6..0000000000
--- a/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# tkextlib/blt/tile/radiobutton.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/radiobutton'
-require 'tkextlib/blt/tile.rb'
-
-module Tk::BLT
- module Tile
- class Radiobutton < TkRadiobutton
- TkCommandNames = ['::blt::tile::radiobutton'.freeze].freeze
- end
- RadioButton = Radiobutton
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb b/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb
deleted file mode 100644
index ba3bf316f0..0000000000
--- a/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# tkextlib/blt/tile/scrollbar.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/scrollbar'
-require 'tkextlib/blt/tile.rb'
-
-module Tk::BLT
- module Tile
- class Scrollbar < TkScrollbar
- TkCommandNames = ['::blt::tile::scrollbar'.freeze].freeze
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/tile/toplevel.rb b/ext/tk/lib/tkextlib/blt/tile/toplevel.rb
deleted file mode 100644
index 6cc2c91415..0000000000
--- a/ext/tk/lib/tkextlib/blt/tile/toplevel.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# tkextlib/blt/tile/toplevel.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/toplevel'
-require 'tkextlib/blt/tile.rb'
-
-module Tk::BLT
- module Tile
- class Toplevel < TkToplevel
- TkCommandNames = ['::blt::tile::toplevel'.freeze].freeze
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/tree.rb b/ext/tk/lib/tkextlib/blt/tree.rb
deleted file mode 100644
index 07dc7ef7e8..0000000000
--- a/ext/tk/lib/tkextlib/blt/tree.rb
+++ /dev/null
@@ -1,923 +0,0 @@
-#
-# tkextlib/blt/tree.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- class Tree < TkObject
- TkCommandNames = ['::blt::tree'.freeze].freeze
-
- ###################################
-
- class Node < TkObject
- TreeNodeID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TreeNodeID_TBL.clear }
-
- def self.id2obj(tree, id)
- tpath = tree.path
- return id unless TreeNodeID_TBL[tpath]
- if TreeNodeID_TBL[tpath][id]
- TreeNodeID_TBL[tpath][id]
- else
- begin
- self.new(tree, nil, 'node'=>Integer(id))
- rescue
- id
- end
- end
- end
-
- def self.new(tree, parent, keys={})
- keys = _symbolkey2str(keys)
- tpath = tree.path
-
- if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id])
- keys.delete('node')
- tk_call(tree.path, 'move', id, parent, keys) if parent
- return obj
- end
-
- super(tree, parent, keys)
- end
-
- def initialize(tree, parent, keys={})
- @parent = @tree = tree
- @tpath = @parent.path
-
- parent = tk_call(@tpath, 'root') unless parent
-
- if (id = keys['node']) && bool(tk_call(@tpath, 'exists', id))
- @path = @id = id
- keys.delete('node')
- tk_call(@tpath, 'move', @id, parent, keys) if parent
- else
- @path = @id = tk_call(@tpath, 'insert', parent, keys)
- end
-
- TreeNodeID_TBL[@tpath] = {} unless TreeNodeID_TBL[@tpath]
- TreeNodeID_TBL[@tpath][@id] = self
- end
-
- def id
- @id
- end
-
- def apply(keys={})
- @tree.apply(@id, keys)
- self
- end
-
- def children()
- @tree.children(@id)
- end
-
- def copy(parent, keys={})
- @tree.copy(@id, parent, keys)
- end
- def copy_to(dest_tree, parent, keys={})
- @tree.copy_to(@id, dest_tree, parent, keys)
- end
-
- def degree()
- @tree.degree(@id)
- end
-
- def delete()
- @tree.delete(@id)
- self
- end
-
- def depth()
- @tree.depth(@id)
- end
-
- def dump()
- @tree.dump(@id)
- end
-
- def dump_to_file(file)
- @tree.dump_to_file(@id, file)
- self
- end
-
- def exist?(keys={})
- @tree.exist?(@id, keys)
- end
-
- def find(keys={})
- @tree.find(@id, keys)
- end
-
- def find_child(label)
- @tree.find_child(@id, label)
- end
-
- def first_child()
- @tree.first_child(@id)
- end
-
- def get()
- @tree.get(@id)
- end
- def get_value(key, default_val=None)
- @tree.get_value(@id, key, default_val)
- end
-
- def index()
- @tree.index(@id)
- end
-
- def leaf?()
- @tree.leaf?(@id)
- end
- def link?()
- @tree.link?(@id)
- end
- def root?()
- @tree.root?(@id)
- end
-
- def keys()
- @tree.keys(@id)
- end
-
- def label(text = nil)
- @tree.label(@id, nil)
- end
- def label=(text)
- @tree.label(@id, text)
- end
-
- def last_child()
- @tree.last_child(@id)
- end
-
- def move(dest, keys={})
- @tree.keys(@id, dest, keys)
- self
- end
-
- def next()
- @tree.next(@id)
- end
-
- def next_sibling()
- @tree.next_sibling(@id)
- end
-
- def parent()
- @tree.parent(@id)
- end
-
- def fullpath()
- @tree.fullpath(@id)
- end
-
- def position()
- @tree.position(@id)
- end
-
- def previous()
- @tree.previous(@id)
- end
-
- def prev_sibling()
- @tree.prev_sibling(@id)
- end
-
- def restore(str, keys={})
- @tree.restore(@id, str, keys)
- self
- end
- def restore_overwrite(str, keys={})
- @tree.restore_overwrite(@id, str, keys)
- self
- end
-
- def restore_from_file(file, keys={})
- @tree.restore_from_file(@id, file, keys)
- self
- end
- def restore_overwrite_from_file(file, keys={})
- @tree.restore_overwrite_from_file(@id, file, keys)
- self
- end
-
- def root()
- @tree.root(@id)
- self
- end
-
- def set(data)
- @tree.set(@id, data)
- self
- end
-
- def size()
- @tree.size(@id)
- end
-
- def sort(keys={})
- @tree.sort(@id, keys)
- self
- end
-
- def type(key)
- @tree.type(@id, key)
- end
-
- def unset(*keys)
- @tree.unset(@id, *keys)
- self
- end
-
- def values(key=None)
- @tree.values(@id, key)
- end
- end
-
- ###################################
-
- class Tag < TkObject
- TreeTagID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TreeTagID_TBL.clear }
- TreeTag_ID = ['blt_tree_tag'.freeze, '00000'.taint].freeze
-
- def self.id2obj(tree, id)
- tpath = tree.path
- return id unless TreeTagID_TBL[tpath]
- if TreeTagID_TBL[tpath][id]
- TreeTagID_TBL[tpath][id]
- else
- self.new(tree, id)
- end
- end
-
- def initialize(tree, tag_str = nil)
- @parent = @tree = tree
- @tpath = @parent.path
-
- if tag_str
- @path = @id = tag_str.dup.freeze
- else
- @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_)
- TreeTagID_TBL[@id] = self
- TreeTag_ID[1].succ!
- end
- TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
- TreeTagID_TBL[@tpath][@id] = self
- end
-
- def id
- @id
- end
-
- def add(*nodes)
- tk_call(@tpath, 'tag', 'add', @id, *nodes)
- self
- end
-
- def delete(*nodes)
- tk_call(@tpath, 'tag', 'delete', @id, *nodes)
- self
- end
-
- def forget()
- tk_call(@tpath, 'tag', 'forget', @id)
- TreeTagID_TBL[@tpath].delete(@id)
- self
- end
-
- def nodes()
- simplelist(tk_call(@tpath, 'tag', 'nodes', @id)).collect{|node|
- Tk::BLT::Tree::Node.id2obj(@path, node)
- }
- end
-
- def set(node)
- tk_call(@tpath, 'tag', 'set', node, @id)
- self
- end
-
- def unset(node)
- tk_call(@tpath, 'tag', 'unset', node, @id)
- self
- end
- end
-
- ###################################
-
- class Notify < TkObject
- NotifyID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ NotifyID_TBL.clear }
-
- def self.id2obj(tree, id)
- tpath = tree.path
- return id unless NotifyID_TBL[tpath]
- if NotifyID_TBL[tpath][id]
- NotifyID_TBL[tpath][id]
- else
- begin
- self.new([tree, id])
- rescue
- id
- end
- end
- end
-
- def self.new(tree, *args, &b)
- if tree.kind_of?(Array)
- # not create
- if obj = NotifyID_TBL[tree[0].path][tree[1]]
- return obj
- else
- return super(false, tree[0], tree[1])
- end
- end
-
- super(true, tree, *args, &b)
- end
-
- def initialize(create, tree, *args, &b)
- @parent = @tree = tree
- @tpath = @parent.path
-
- unless create
- @path = @id = args[0]
- return
- end
-
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0])
- cmd = args.shift
- # elsif args[-1].kind_of?(Proc) || args[-1].kind_of?(Method)
- elsif TkComm._callback_entry?(args[-1])
- cmd = args.pop
- elsif b
- cmd = Proc.new(&b)
- else
- fail ArgumentError, "lack of 'command' argument"
- end
-
- args = args.collect{|arg| '-' << arg.to_s}
-
- args << proc{|id, type|
- cmd.call(Tk::BLT::Tree::Node.id2obj(@tree, id),
- ((type[0] == ?-)? type[1..-1]: type))
- }
-
- @path = @id = tk_call(@tpath, 'notify', 'create', *args)
- end
-
- def id
- @id
- end
-
- def delete()
- tk_call(@tpath, 'notify', 'delete', @id)
- NotifyID_TBL[tpath].delete(@id)
- self
- end
-
- def info()
- lst = simplelist(tk_call(@tpath, 'notify', 'info', id))
- lst[0] = Tk::BLT::Tree::Notify.id2obj(@tree, lst[0])
- lst[1] = simplelist(lst[1]).collect{|flag| flag[1..-1]}
- lst[2] = tk_tcl2ruby(lst[2])
- lst
- end
- end
-
- ###################################
-
- class Trace < TkObject
- TraceID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TraceID_TBL.clear }
-
- def self.id2obj(tree, id)
- tpath = tree.path
- return id unless TraceID_TBL[tpath]
- if TraceID_TBL[tpath][id]
- TraceID_TBL[tpath][id]
- else
- begin
- self.new([tree, id])
- rescue
- id
- end
- end
- end
-
- def self.new(tree, *args, &b)
- if tree.kind_of?(Array)
- # not create
- if obj = TraceID_TBL[tree[0].path][tree[1]]
- return obj
- else
- return super(false, tree[0], tree[1])
- end
- end
-
- super(true, tree, *args, &b)
- end
-
- def initialize(create, tree, node, key, opts, cmd=nil, &b)
- @parent = @tree = tree
- @tpath = @parent.path
-
- unless create
- @path = @id = node # == traceID
- return
- end
-
- if !cmd
- if b
- cmd = Proc.new(&b)
- else
- fail ArgumentError, "lack of 'command' argument"
- end
- end
-
- @path = @id = tk_call(@tpath, 'trace', 'create', node, key, opts,
- proc{|t, id, k, ops|
- tobj = Tk::BLT::Tree.id2obj(t)
- if tobj.kind_of?(Tk::BLT::Tree)
- nobj = Tk::BLT::Tree::Node.id2obj(tobj, id)
- else
- nobj = id
- end
- cmd.call(tobj, nobj, k, ops)
- })
- end
-
- def id
- @id
- end
-
- def delete()
- tk_call(@tpath, 'trace', 'delete', @id)
- TraceID_TBL[tpath].delete(@id)
- self
- end
-
- def info()
- lst = simplelist(tk_call(@tpath, 'trace', 'info', id))
- lst[0] = Tk::BLT::Tree::Trace.id2obj(@tree, lst[0])
- lst[2] = simplelist(lst[2])
- lst[3] = tk_tcl2ruby(lst[3])
- lst
- end
- end
-
- ###################################
-
- TreeID_TBL = TkCore::INTERP.create_table
- Tree_ID = ['blt_tree'.freeze, '00000'.taint].freeze
-
- def __keyonly_optkeys
- {
- # apply / find command
- 'invert'=>nil, 'leafonly'=>nil, 'nocase'=>nil,
-
- # apply / find / sort command
- 'path'=>nil,
-
- # copy / restore / restorefile command
- 'overwrite'=>nil,
-
- # copy command
- 'recurse'=>nil, 'tags'=>nil,
-
- # sort command
- 'ascii'=>nil, 'decreasing'=>nil, 'disctionary'=>nil,
- 'integer'=>nil, 'real'=>nil, 'recurse'=>nil, 'reorder'=>nil,
- }
- end
-
- def self.id2obj(id)
- TreeID_TBL[id]? TreeID_TBL[id]: id
- end
-
- def self.names(pat = None)
- simplelist(tk_call('::blt::tree', 'names', pat)).collect{|name|
- id2obj(name)
- }
- end
-
- def self.destroy(*names)
- tk_call('::blt::tree', 'destroy',
- *(names.collect{|n| (n.kind_of?(Tk::BLT::Tree))? n.id: n }) )
- end
-
- def self.new(name = nil)
- return TreeID_TBL[name] if name && TreeID_TBL[name]
- super(name)
- end
-
- def initialzie(name = nil)
- if name
- @path = @id = name
- else
- @path = @id = Tree_ID.join(TkCore::INTERP._ip_id_)
- TreeID_TBL[@id] = self
- Tree_ID[1].succ!
- end
- TreeID_TBL[@id] = self
- tk_call('::blt::tree', 'create', @id)
- end
-
- def __destroy_hook__
- Tk::BLT::Tree::Node::TreeNodeID_TBL.delete(@path)
- Tk::BLT::Tree::Tag::TreeTagID_TBL.delete(@path)
- Tk::BLT::Tree::Notify::NotifyID_TBL.delete(@path)
- Tk::BLT::Tree::Trace::TraceID_TBL.delete(@path)
- end
-
- def tagid(tag)
- if tag.kind_of?(Tk::BLT::Tree::Node) ||
- tag.kind_of?(Tk::BLT::Tree::Tag) ||
- tag.kind_of?(Tk::BLT::Tree::Notify) ||
- tag.kind_of?(Tk::BLT::Tree::Trace)
- tag.id
- else
- tag # maybe an Array of configure paramters
- end
- end
-
- def destroy()
- tk_call('::blt::tree', 'destroy', @id)
- self
- end
-
- def ancestor(node1, node2)
- Tk::BLT::Tree::Node.id2obj(self, tk_call('::blt::tree', 'ancestor',
- tagid(node1), tagid(node2)))
- end
-
- def apply(node, keys={})
- tk_call('::blt::tree', 'apply', tagid(node), __conv_keyonly_opts(keys))
- self
- end
-
- def attach(tree_obj)
- tk_call('::blt::tree', 'attach', tree_obj)
- self
- end
-
- def children(node)
- simplelist(tk_call('::blt::tree', 'children', tagid(node))).collect{|n|
- Tk::BLT::Tree::Node.id2obj(self, n)
- }
- end
-
- def copy(src, parent, keys={})
- id = tk_call('::blt::tree', 'copy', tagid(src), tagid(parent),
- __conv_keyonly_opts(keys))
- Tk::BLT::Tree::Node.new(self, nil, 'node'=>id)
- end
- def copy_to(src, dest_tree, parent, keys={})
- return copy(src, parent, keys={}) unless dest_tree
-
- id = tk_call('::blt::tree', 'copy', tagid(src), dest_tree,
- tagid(parent), __conv_keyonly_opts(keys))
- Tk::BLT::Tree::Node.new(dest_tree, nil, 'node'=>id)
- end
-
- def degree(node)
- number(tk_call('::blt::tree', 'degree', tagid(node)))
- end
-
- def delete(*nodes)
- tk_call('::blt::tree', 'delete', *(nodes.collect{|node| tagid(node)}))
- nodes.each{|node|
- if node.kind_of?(Tk::BLT::Tree::Node)
- Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.id)
- else
- Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.to_s)
- end
- }
- self
- end
-
- def depth(node)
- number(tk_call('::blt::tree', 'depth', tagid(node)))
- end
-
- def dump(node)
- simplelist(tk_call('::blt::tree', 'dump', tagid(node))).collect{|n|
- simplelist(n)
- }
- end
-
- def dump_to_file(node, file)
- tk_call('::blt::tree', 'dumpfile', tagid(node), file)
- self
- end
-
- def exist?(node, key=None)
- bool(tk_call('::blt::tree', 'exists', tagid(node), key))
- end
-
- def find(node, keys={})
- simplelist(tk_call('::blt::tree', 'find', tagid(node),
- __conv_keyonly_opts(keys))).collect{|n|
- Tk::BLT::Tree::Node.id2obj(self, n)
- }
- end
-
- def find_child(node, label)
- ret = tk_call('::blt::tree', 'findchild', tagid(node), label)
- (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
- end
-
- def first_child(node)
- ret = tk_call('::blt::tree', 'firstchild', tagid(node))
- (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
- end
-
- def get(node)
- Hash[*simplelist(tk_call('::blt::tree', 'get', tagid(node)))]
- end
- def get_value(node, key, default_val=None)
- tk_call('::blt::tree', 'get', tagid(node), key, default_val)
- end
-
- def index(node)
- Tk::BLT::Tree::Node.id2obj(self,
- tk_call('::blt::tree', 'index', tagid(node)))
- end
-
- def insert(parent, keys={})
- id = tk_call('::blt::tree', 'insert', tagid(parent), keys)
- Tk::BLT::Tree::Node.new(self, nil, 'node'=>id)
- end
-
- def ancestor?(node1, node2)
- bool(tk_call('::blt::tree', 'is', 'ancestor',
- tagid(node1), tagid(node2)))
- end
- def before?(node1, node2)
- bool(tk_call('::blt::tree', 'is', 'before',
- tagid(node1), tagid(node2)))
- end
- def leaf?(node)
- bool(tk_call('::blt::tree', 'is', 'leaf', tagid(node)))
- end
- def link?(node)
- bool(tk_call('::blt::tree', 'is', 'link', tagid(node)))
- end
- def root?(node)
- bool(tk_call('::blt::tree', 'is', 'root', tagid(node)))
- end
-
- def keys(node, *nodes)
- if nodes.empty?
- simplelist(tk_call('blt::tree', 'keys', tagid(node)))
- else
- simplelist(tk_call('blt::tree', 'keys', tagid(node),
- *(nodes.collect{|n| tagid(n)}))).collect{|lst|
- simplelist(lst)
- }
- end
- end
-
- def label(node, text=nil)
- if text
- tk_call('::blt::tree', 'label', tagid(node), text)
- text
- else
- tk_call('::blt::tree', 'label', tagid(node))
- end
- end
-
- def last_child(node)
- ret = tk_call('::blt::tree', 'lastchild', tagid(node))
- (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
- end
-
- def link(parent, node, keys={})
- ret = tk_call('::blt::tree', 'link', tagid(parent), tagid(node),
- __conv_keyonly_opts(keys))
- (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
- end
-
- def move(node, dest, keys={})
- tk_call('::blt::tree', 'move', tagid(node), tagid(dest), keys)
- self
- end
-
- def next(node)
- ret = tk_call('::blt::tree', 'next', tagid(node))
- (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
- end
-
- def next_sibling(node)
- ret = tk_call('::blt::tree', 'nextsibling', tagid(node))
- (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
- end
-
- def notify_create(*args, &b)
- Tk::BLT::Tree::Notify.new(self, *args, &b)
- end
-
- def notify_delete(id)
- if id.kind_of?(Tk::BLT::Tree::Notify)
- id.delete
- else
- tk_call(@path, 'notify', 'delete', id)
- Tk::BLT::Tree::Notify::NotifyID_TBL[@path].delete(id.to_s)
- end
- self
- end
-
- def notify_info(id)
- lst = simplelist(tk_call(@path, 'notify', 'info', tagid(id)))
- lst[0] = Tk::BLT::Tree::Notify.id2obj(self, lst[0])
- lst[1] = simplelist(lst[1]).collect{|flag| flag[1..-1]}
- lst[2] = tk_tcl2ruby(lst[2])
- lst
- end
-
- def notify_names()
- tk_call(@path, 'notify', 'names').collect{|id|
- Tk::BLT::Tree::Notify.id2obj(self, id)
- }
- end
-
- def parent(node)
- ret = tk_call('::blt::tree', 'parent', tagid(node))
- (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
- end
-
- def fullpath(node)
- tk_call('::blt::tree', 'path', tagid(node))
- end
-
- def position(node)
- number(tk_call('::blt::tree', 'position', tagid(node)))
- end
-
- def previous(node)
- ret = tk_call('::blt::tree', 'previous', tagid(node))
- (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
- end
-
- def prev_sibling(node)
- ret = tk_call('::blt::tree', 'prevsibling', tagid(node))
- (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
- end
-
- def restore(node, str, keys={})
- tk_call('::blt::tree', 'restore', tagid(node), str,
- __conv_keyonly_opts(keys))
- self
- end
- def restore_overwrite(node, str, keys={})
- keys = __conv_keyonly_opts(keys)
- keys.delete('overwrite')
- keys.delete(:overwrite)
- tk_call('::blt::tree', 'restore', tagid(node), str, '-overwrite', keys)
- self
- end
-
- def restore_from_file(node, file, keys={})
- tk_call('::blt::tree', 'restorefile', tagid(node), file,
- __conv_keyonly_opts(keys))
- self
- end
- def restore_overwrite_from_file(node, file, keys={})
- keys = __conv_keyonly_opts(keys)
- keys.delete('overwrite')
- keys.delete(:overwrite)
- tk_call('::blt::tree', 'restorefile', tagid(node), file,
- '-overwrite', keys)
- self
- end
-
- def root(node=None)
- Tk::BLT::Tree::Node.id2obj(self, tk_call('::blt::tree', 'root',
- tagid(node)))
- end
-
- def set(node, data)
- unless data.kind_of?(Hash)
- fail ArgumentError, 'Hash is expected for data'
- end
- args = []
- data.each{|k, v| args << k << v}
- tk_call('::blt::tree', 'set', tagid(node), *args)
- self
- end
-
- def size(node)
- number(tk_call('::blt::tree', 'size', tagid(node)))
- end
-
- def sort(node, keys={})
- tk_call('::blt::tree', 'sort', tagid(node), __conv_keyonly_opts(keys))
- self
- end
-
- def tag_add(tag, *nodes)
- tk_call(@path, 'tag', 'add', tagid(tag), *(nodes.collect{|n| tagid(n)}))
- self
- end
-
- def tag_delete(tag, *nodes)
- tk_call(@path, 'tag', 'delete', tagid(tag),
- *(nodes.collect{|n| tagid(n)}))
- self
- end
-
- def tag_forget(tag)
- tag = tag.id if tag.kind_of?(Tk::BLT::Tree::Tag)
- tk_call(@path, 'tag', 'forget', tag)
- TreeTagID_TBL[@path].delete(tag)
- self
- end
-
- def tag_get(node, *patterns)
- simplelist(tk_call(@tpath, 'tag', 'get', tagid(node),
- *(patterns.collect{|pat| tagid(pat)}))).collect{|str|
- Tk::BLT::Tree::Tag.id2obj(self, str)
- }
- end
-
- def tag_names(node = None)
- simplelist(tk_call(@tpath, 'tag', 'names', tagid(node))).collect{|str|
- Tk::BLT::Tree::Tag.id2obj(self, str)
- }
- end
-
- def tag_nodes(tag)
- simplelist(tk_call(@tpath, 'tag', 'nodes', tagid(tag))).collect{|node|
- Tk::BLT::Tree::Node.id2obj(self, node)
- }
- end
-
- def tag_set(node, *tags)
- tk_call(@path, 'tag', 'set', tagid(node), *(tags.collect{|t| tagid(t)}))
- self
- end
-
- def tag_unset(node, *tags)
- tk_call(@path, 'tag', 'unset', tagid(node),
- *(tags.collect{|t| tagid(t)}))
- self
- end
-
- def trace_create(*args, &b)
- Tk::BLT::Tree::Trace.new(self, *args, &b)
- end
-
-=begin
- def trace_delete(*args)
- args.each{|id|
- if id.kind_of?(Tk::BLT::Tree::Trace)
- id.delete
- else
- tk_call(@path, 'trace', 'delete', id)
- Tk::BLT::Tree::Trace::TraceID_TBL[@path].delete(id.to_s)
- end
- self
- }
- end
-=end
- def trace_delete(*args)
- args = args.collect{|id| tagid(id)}
- tk_call(@path, 'trace', 'delete', *args)
- args.each{|id| Tk::BLT::Tree::Trace::TraceID_TBL[@path].delete(id.to_s)}
- self
- end
-
- def trace_info(id)
- lst = simplelist(tk_call(@path, 'trace', 'info', tagid(id)))
- lst[0] = Tk::BLT::Tree::Trace.id2obj(self, lst[0])
- lst[2] = simplelist(lst[2])
- lst[3] = tk_tcl2ruby(lst[3])
- lst
- end
-
- def trace_names()
- tk_call(@path, 'trace', 'names').collect{|id|
- Tk::BLT::Tree::Trace.id2obj(self, id)
- }
- end
-
- def type(node, key)
- tk_call('::blt::tree', 'type', tagid(node), key)
- end
-
- def unset(node, *keys)
- tk_call('::blt::tree', 'unset', tagid(node), *keys)
- self
- end
-
- def values(node, key=None)
- simplelist(tk_call('::blt::tree', 'values', tagid(node), key))
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/treeview.rb b/ext/tk/lib/tkextlib/blt/treeview.rb
deleted file mode 100644
index 0343d28b9c..0000000000
--- a/ext/tk/lib/tkextlib/blt/treeview.rb
+++ /dev/null
@@ -1,1146 +0,0 @@
-#
-# tkextlib/blt/treeview.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-require 'tk/validation.rb'
-
-module Tk::BLT
- class Treeview < TkWindow
- module ConfigMethod
- end
-
- module TagOrID_Methods
- end
-
- class Node < TkObject
- end
-
- class Tag < TkObject
- end
- end
-
- class Hiertable < Treeview
- end
-end
-
-######################################
-
-module Tk::BLT::Treeview::ConfigMethod
- include TkItemConfigMethod
-
- def __item_boolval_optkeys(id)
- case id
- when Array
- # id := [ 'column', name ]
- ['edit', 'hide']
- when 'sort'
- ['decreasing']
- else
- []
- end
- end
- private :__item_boolval_optkeys
-
- def __item_strval_optkeys(id)
- case id
- when Array
- # id := [ 'column', name ]
- super() << 'titleforeground' << 'titleshadow'
- when 'sort'
- ['decreasing']
- else
- []
- end
- end
- private :__item_strval_optkeys
-
- def __item_listval_optkeys(id)
- case id
- when 'entry'
- ['bindtags']
- else
- []
- end
- end
- private :__item_listval_optkeys
-
- def __item_cget_cmd(id)
- if id.kind_of?(Array)
- # id := [ type, name ]
- [self.path, id[0], 'cget', id[1]]
- else
- [self.path, id, 'cget']
- end
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- if id.kind_of?(Array)
- # id := [ type, name ]
- [self.path, id[0], 'configure', id[1]]
- else
- [self.path, id, 'configure']
- end
- end
- private :__item_config_cmd
-
- def __item_pathname(id)
- if id.kind_of?(Array)
- id = tagid(id[1])
- end
- [self.path, id].join(';')
- end
- private :__item_pathname
-
- def column_cget(name, option)
- itemcget(['column', name], option)
- end
- def column_configure(name, slot, value=None)
- itemconfigure(['column', name], slot, value)
- end
- def column_configinfo(name, slot=nil)
- itemconfiginfo(['column', name], slot)
- end
- def current_column_configinfo(name, slot=nil)
- current_itemconfiginfo(['column', name], slot)
- end
-
- def button_cget(option)
- itemcget('button', option)
- end
- def button_configure(slot, value=None)
- itemconfigure('button', slot, value)
- end
- def button_configinfo(slot=nil)
- itemconfiginfo('button', slot)
- end
- def current_button_configinfo(slot=nil)
- current_itemconfiginfo('button', slot)
- end
-
- def entry_cget(option)
- ret = itemcget('entry', option)
- if option == 'bindtags' || option == :bindtags
- ret.collect{|tag| TkBindTag.id2obj(tag)}
- else
- ret
- end
- end
- def entry_configure(slot, value=None)
- itemconfigure('entry', slot, value)
- end
- def entry_configinfo(slot=nil)
- ret = itemconfiginfo('entry', slot)
-
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- if slot == 'bindtags' || slot == :bindtags
- ret[-2] = ret[-2].collect{|tag| TkBindTag.id2obj(tag)}
- ret[-1] = ret[-1].collect{|tag| TkBindTag.id2obj(tag)}
- end
- else
- inf = ret.assoc('bindtags')
- inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)}
- inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)}
- end
-
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if (inf = ret['bindtags'])
- inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)}
- inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)}
- ret['bindtags'] = inf
- end
- end
-
- ret
- end
- def current_entry_configinfo(slot=nil)
- ret = current_itemconfiginfo('entry', slot)
-
- if (val = ret['bindtags'])
- ret['bindtags'] = val.collect{|tag| TkBindTag.id2obj(tag)}
- end
-
- ret
- end
-
- def sort_cget(option)
- itemcget('sort', option)
- end
- def sort_configure(slot, value=None)
- itemconfigure('sort', slot, value)
- end
- def sort_configinfo(slot=nil)
- itemconfiginfo('sort', slot)
- end
- def current_sort_configinfo(slot=nil)
- current_itemconfiginfo('sort', slot)
- end
-
- def text_cget(option)
- itemcget('text', option)
- end
- def text_configure(slot, value=None)
- itemconfigure('text', slot, value)
- end
- def text_configinfo(slot=nil)
- itemconfiginfo('text', slot)
- end
- def current_text_configinfo(slot=nil)
- current_itemconfiginfo('text', slot)
- end
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-end
-
-class Tk::BLT::Treeview
- TkCommandNames = ['::blt::treeview'.freeze].freeze
- WidgetClassName = 'TreeView'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- include Scrollable
- include ValidateConfigure
- include ItemValidateConfigure
- include Tk::BLT::Treeview::ConfigMethod
-
- ########################
-
- def __boolval_optkeys
- ['autocreate', 'allowduplicates', 'exportselection', 'flat', 'hideroot',
- 'newtags', 'showtitles', 'sortselection']
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- super() + ['focusforeground', 'linecolor', 'separator', 'trim']
- end
- private :__strval_optkeys
-
- ########################
-
- class OpenCloseCommand < TkValidateCommand
- class ValidateArgs < TkUtil::CallbackSubst
- KEY_TBL = [
- [ ?W, ?w, :widget ],
- [ ?p, ?s, :name ],
- [ ?P, ?s, :fullpath ],
- [ ?#, ?x, :node_id ],
- nil
- ]
-
- PROC_TBL = [
- [ ?x, TkComm.method(:num_or_str) ],
- [ ?s, TkComm.method(:string) ],
- [ ?w, TkComm.method(:window) ],
- nil
- ]
-
- _setup_subst_table(KEY_TBL, PROC_TBL);
-
- def self.ret_val(val)
- val
- end
- end
-
- def self._config_keys
- ['opencommand', 'closecomand']
- end
- end
-
- def __validation_class_list
- super() << OpenCloseCommand
- end
-
- Tk::ValidateConfigure.__def_validcmd(binding, OpenCloseCommand)
-
- ########################
-
- def __item_validation_class_list(id)
- case id
- when 'entry'
- super(id) << OpenCloseCommand
- else
- super(id)
- end
- end
-
- Tk::ItemValidateConfigure.__def_validcmd(binding, OpenCloseCommand)
-
- ########################
-
- def __destroy_hook__
- Tk::BLT::Treeview::Node::TreeNodeID_TBL.delete(@path)
- Tk::BLT::Treeview::Tag::TreeTagID_TBL.delete(@path)
- end
-
- def tagid(tag)
- if tag.kind_of?(Tk::BLT::Treeview::Node) \
- || tag.kind_of?(Tk::BLT::Treeview::Tag)
- tag.id
- else
- tag # maybe an Array of configure paramters
- end
- end
- private :tagid
-
- def tagid2obj(tagid)
- if tagid.kind_of?(Integer)
- Tk::BLT::Treeview::Node.id2obj(self, tagid.to_s)
- elsif tagid.kind_of?(String)
- if tagid =~ /^\d+$/
- Tk::BLT::Treeview::Node.id2obj(self, tagid)
- else
- Tk::BLT::Treeview::Tag.id2obj(self, tagid)
- end
- else
- tagid
- end
- end
-
- def bbox(*tags)
- list(tk_send('bbox', *(tags.collect{|tag| tagid(tag)})))
- end
-
- def screen_bbox(*tags)
- list(tk_send('bbox', '-screen', *(tags.collect{|tag| tagid(tag)})))
- end
-
- def tag_bind(tag, seq, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([@path, 'bind', tagid(tag)], seq, cmd, *args)
- self
- end
- def tag_bind_append(tag, seq, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([@path, 'bind', tagid(tag)], seq, cmd, *args)
- self
- end
- def tag_bind_remove(tag, seq)
- _bind_remove([@path, 'bind', tagid(tag)], seq)
- self
- end
- def tag_bindinfo(tag, seq=nil)
- _bindinfo([@path, 'bind', tagid(tag)], seq)
- end
-
- def button_activate(tag)
- tk_send('button', 'activate', tagid(tag))
- self
- end
-
- def button_bind(tag, seq, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([@path, 'button', 'bind', tagid(tag)], seq, cmd, *args)
- self
- end
- def button_bind_append(tag, seq, *args)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([@path, 'button', 'bind', tagid(tag)], seq, cmd, *args)
- self
- end
- def button_bind_remove(tag, seq)
- _bind_remove([@path, 'button', 'bind', tagid(tag)], seq)
- self
- end
- def button_bindinfo(tag, seq=nil)
- _bindinfo([@path, 'button', 'bind', tagid(tag)], seq)
- end
-
- def close(*tags)
- tk_send('close', *(tags.collect{|tag| tagid(tag)}))
- self
- end
- def close_recurse(*tags)
- tk_send('close', '-recurse', *(tags.collect{|tag| tagid(tag)}))
- self
- end
-
- def column_activate(column=None)
- if column == None
- tk_send('column', 'activate')
- else
- tk_send('column', 'activate', column)
- self
- end
- end
-
- def column_delete(*fields)
- tk_send('column', 'delete', *fields)
- self
- end
- def column_insert(pos, field, *opts)
- tk_send('column', 'insert', pos, field, *opts)
- self
- end
- def column_invoke(field)
- tk_send('column', 'invoke', field)
- self
- end
- def column_move(name, dest)
- tk_send('column', 'move', name, dest)
- self
- end
- def column_names()
- simplelist(tk_send('column', 'names'))
- end
- def column_nearest(x, y=None)
- tk_send('column', 'nearest', x, y)
- end
-
- def curselection
- simplelist(tk_send('curselection')).collect{|id| tagid2obj(id)}
- end
-
- def delete(*tags)
- tk_send('delete', *(tags.collect{|tag| tagid(tag)}))
- self
- end
-
- def entry_activate(tag)
- tk_send('entry', 'activate', tagid(tag))
- self
- end
- def entry_children(tag, first=None, last=None)
- simplelist(tk_send('entry', 'children', tagid(tag),
- first, last)).collect{|id| tagid2obj(id)}
- end
- def entry_delete(tag, first=None, last=None)
- tk_send('entry', 'delete', tagid(tag), first, last)
- end
- def entry_before?(tag1, tag2)
- bool(tk_send('entry', 'isbefore', tagid(tag1), tagid(tag2)))
- end
- def entry_hidden?(tag)
- bool(tk_send('entry', 'ishidden', tagid(tag)))
- end
- def entry_open?(tag)
- bool(tk_send('entry', 'isopen', tagid(tag)))
- end
-
- def entry_size(tag)
- number(tk_send('entry', 'size', tagid(tag)))
- end
- def entry_size_recurse(tag)
- number(tk_send('entry', 'size', '-recurse', tagid(tag)))
- end
-
- def _search_flags(keys)
- keys = _symbolkey2str(keys)
- keys['exact'] = None if keys.delete('exact')
- keys['glob'] = None if keys.delete('glob')
- keys['regexp'] = None if keys.delete('regexp')
- keys['nonmatching'] = None if keys.delete('nonmatching')
- end
- private :_search_flags
-
- ################################
-
- class FindExecFlagValue < TkValidateCommand
- class ValidateArgs < TkUtil::CallbackSubst
- KEY_TBL = [
- [ ?W, ?w, :widget ],
- [ ?p, ?s, :name ],
- [ ?P, ?s, :fullpath ],
- [ ?#, ?x, :node_id ],
- nil
- ]
-
- PROC_TBL = [
- [ ?x, TkComm.method(:num_or_str) ],
- [ ?s, TkComm.method(:string) ],
- [ ?w, TkComm.method(:window) ],
- nil
- ]
-
- _setup_subst_table(KEY_TBL, PROC_TBL);
-
- def self.ret_val(val)
- val
- end
- end
-
- def self._config_keys
- []
- end
- end
-
- def _find_exec_flag_value(val)
- if val.kind_of?(Array)
- cmd, *args = val
- FindExecFlagValue.new(cmd, args.join(' '))
- elsif TkComm._callback_entry?(val)
- FindExecFlagValue.new(val)
- else
- val
- end
- end
-
- ################################
-
- def find(first, last, keys={})
- keys = _search_flags(keys)
- keys['exec'] = _find_exec_flag_value(keys['exec']) if keys.key?('exec')
- args = hash_kv(keys) << '--' << tagid(first) << tagid(last)
- simplelist(tk_send('find', *args)).collect{|id| tagid2obj(id)}
- end
-
- def tag_focus(tag)
- tk_send('focus', tagid(tag))
- self
- end
- def get(*tags)
- simplelist(tk_send('get', *(tags.collect{|tag| tagid(tag)})))
- end
- def get_full(*tags)
- simplelist(tk_send('get', '-full', *(tags.collect{|tag| tagid(tag)})))
- end
-
- def hide(*tags)
- if tags[-1].kind_of?(Hash)
- keys = tags.pop
- else
- keys = {}
- end
- keys = _search_flags(keys)
- args = hash_kv(keys) << '--'
- args.concat(tags.collect{|t| tagid(t)})
- tk_send('hide', *args)
- self
- end
-
- def index(str)
- tagid2obj(tk_send('index', str))
- end
- def index_at(tag, str)
- tagid2obj(tk_send('index', '-at', tagid(tag), str))
- end
- def index_at_path(tag, str)
- tagid2obj(tk_send('index', '-at', tagid(tag), '-path', str))
- end
-
- def insert(pos, parent=nil, keys={})
- Tk::BLT::Treeview::Node.new(pos, parent, keys)
- end
- def insert_at(tag, pos, parent=nil, keys={})
- if parent.kind_of?(Hash)
- keys = parent
- parent = nil
- end
-
- keys = _symbolkey2str(keys)
- keys['at'] = tagid(tag)
-
- Tk::BLT::Treeview::Node.new(pos, parent, keys)
- end
-
- def move_before(tag, dest)
- tk_send('move', tagid(tag), 'before', tagid(dest))
- self
- end
- def move_after(tag, dest)
- tk_send('move', tagid(tag), 'after', tagid(dest))
- self
- end
- def move_into(tag, dest)
- tk_send('move', tagid(tag), 'into', tagid(dest))
- self
- end
-
- def nearest(x, y, var=None)
- tagid2obj(tk_send('nearest', x, y, var))
- end
-
- def open(*tags)
- tk_send('open', *(tags.collect{|tag| tagid(tag)}))
- self
- end
- def open_recurse(*tags)
- tk_send('open', '-recurse', *(tags.collect{|tag| tagid(tag)}))
- self
- end
-
- def range(first, last)
- simplelist(tk_send('range', tagid(first), tagid(last))).collect{|id|
- tagid2obj(id)
- }
- end
- def range_open(first, last)
- simplelist(tk_send('range', '-open',
- tagid(first), tagid(last))).collect{|id|
- tagid2obj(id)
- }
- end
-
- def scan_mark(x, y)
- tk_send_without_enc('scan', 'mark', x, y)
- self
- end
- def scan_dragto(x, y)
- tk_send_without_enc('scan', 'dragto', x, y)
- self
- end
-
- def see(tag)
- tk_send_without_enc('see', tagid(tag))
- self
- end
- def see_anchor(anchor, tag)
- tk_send_without_enc('see', '-anchor', anchor, tagid(tag))
- self
- end
-
- def selection_anchor(tag)
- tk_send_without_enc('selection', 'anchor', tagid(tag))
- self
- end
- def selection_cancel()
- tk_send_without_enc('selection', 'cancel')
- self
- end
- def selection_clear(first, last=None)
- tk_send_without_enc('selection', 'clear', tagid(first), tagid(last))
- self
- end
- def selection_clear_all()
- tk_send_without_enc('selection', 'clearall')
- self
- end
- def selection_mark(tag)
- tk_send_without_enc('selection', 'mark', tagid(tag))
- self
- end
- def selection_include?(tag)
- bool(tk_send('selection', 'include', tagid(tag)))
- end
- def selection_present?()
- bool(tk_send('selection', 'present'))
- end
- def selection_set(first, last=None)
- tk_send_without_enc('selection', 'set', tagid(first), tagid(last))
- self
- end
- def selection_toggle(first, last=None)
- tk_send_without_enc('selection', 'toggle', tagid(first), tagid(last))
- self
- end
-
- def show(*tags)
- if tags[-1].kind_of?(Hash)
- keys = tags.pop
- else
- keys = {}
- end
- keys = _search_flags(keys)
- args = hash_kv(keys) << '--'
- args.concat(tags.collect{|t| tagid(t)})
- tk_send('show', *args)
- self
- end
-
- def sort_auto(mode)
- tk_send('sort', 'auto', mode)
- self
- end
- def sort_auto=(mode)
- tk_send('sort', 'auto', mode)
- mode
- end
- def sort_auto?
- bool(tk_send('sort', 'auto'))
- end
- def sort_once(*tags)
- tk_send('sort', 'once', *(tags.collect{|tag| tagid(tag)}))
- self
- end
- def sort_once_recurse(*tags)
- tk_send('sort', 'once', '-recurse', *(tags.collect{|tag| tagid(tag)}))
- self
- end
-
- def tag_add(tag, *ids)
- tk_send('tag', 'add', tagid(tag), *ids)
- self
- end
- def tag_delete(tag, *ids)
- tk_send('tag', 'delete', tagid(tag), *ids)
- self
- end
- def tag_forget(tag)
- tk_send('tag', 'forget', tagid(tag))
- self
- end
- def tag_names(id=nil)
- id = (id)? tagid(id): None
-
- simplelist(tk_send('tag', 'nodes', id)).collect{|tag|
- Tk::BLT::Treeview::Tag.id2obj(self, tag)
- }
- end
- def tag_nodes(tag)
- simplelist(tk_send('tag', 'nodes', tagid(tag))).collect{|id|
- Tk::BLT::Treeview::Node.id2obj(self, id)
- }
- end
-
- def text_apply
- tk_send('text', 'apply')
- self
- end
- def text_cancel
- tk_send('text', 'cancel')
- self
- end
-
- def text_delete(first, last)
- tk_send('text', 'delete', first, last)
- self
- end
- def text_get(x, y)
- tk_send('text', 'get', x, y)
- end
- def text_get_root(x, y)
- tk_send('text', 'get', '-root', x, y)
- end
- def text_icursor(idx)
- tk_send('text', 'icursor', idx)
- self
- end
- def text_index(idx)
- num_or_str(tk_send('text', 'index', idx))
- end
- def text_insert(idx, str)
- tk_send('text', 'insert', idx, str)
- self
- end
-
- def text_selection_adjust(idx)
- tk_send('text', 'selection', 'adjust', idx)
- self
- end
- def text_selection_clear
- tk_send('text', 'selection', 'clear')
- self
- end
- def text_selection_from(idx)
- tk_send('text', 'selection', 'from', idx)
- self
- end
- def text_selection_present
- num_or_str(tk_send('text', 'selection', 'present'))
- end
- def text_selection_range(start, last)
- tk_send('text', 'selection', 'range', start, last)
- self
- end
- def text_selection_to(idx)
- tk_send('text', 'selection', 'to', idx)
- self
- end
-
- def toggle(tag)
- tk_send('toggle', tagid(tag))
- self
- end
-end
-
-######################################
-
-module Tk::BLT::Treeview::TagOrID_Methods
- def bbox
- @tree.bbox(self)
- end
- def screen_bbox
- @tree.screen_bbox(self)
- end
-
- def bind(seq, *args)
- @tree.tag_bind(self, seq, *args)
- self
- end
- def bind_append(seq, *args)
- @tree.tag_bind_append(self, seq, *args)
- self
- end
- def bind_remove(seq)
- @tree.tag_bind_remove(self, seq)
- self
- end
- def bindinfo(seq=nil)
- @tree.tag_bindinfo(self, seq)
- end
-
- def button_activate
- @tree.button_activate(self)
- self
- end
-
- def button_bind(seq, *args)
- @tree.button_bind(self, seq, *args)
- self
- end
- def button_bind_append(seq, *args)
- @tree.button_bind_append(self, seq, *args)
- self
- end
- def button_bind_remove(seq)
- @tree.button_bind_remove(self, seq)
- self
- end
- def button_bindinfo(seq=nil)
- @tree.button_bindinfo(self, seq)
- end
-
- def close
- @tree.close(self)
- self
- end
- def close_recurse
- @tree.close_recurse(self)
- self
- end
-
- def delete
- @tree.delete(self)
- self
- end
-
- def entry_activate
- @tree.entry_activate(self)
- self
- end
- def entry_children(first=None, last=None)
- @tree.entry_children(self, first, last)
- end
- def entry_delete(first=None, last=None)
- @tree.entry_delete(self, first, last)
- end
- def entry_before?(tag)
- @tree.entry_before?(self, tag)
- end
- def entry_hidden?
- @tree.entry_before?(self)
- end
- def entry_open?
- @tree.entry_open?(self)
- end
-
- def entry_size
- @tree.entry_size(self)
- end
- def entry_size_recurse
- @tree.entry_size_recurse(self)
- end
-
- def focus
- @tree.tag_focus(self)
- self
- end
-
- def get
- @tree.get(self)
- end
- def get_full
- @tree.get_full(self)
- end
-
- def hide
- @tree.hide(self)
- self
- end
-
- def index(str)
- @tree.index_at(self, str)
- end
- def index_path(str)
- @tree.index_at_path(self, str)
- end
-
- def insert(pos, parent=nil, keys={})
- @tree.insert_at(self, pos, parent, keys)
- end
-
- def move_before(dest)
- @tree.move_before(self, dest)
- self
- end
- def move_after(dest)
- @tree.move_after(self, dest)
- self
- end
- def move_into(dest)
- @tree.move_into(self, dest)
- self
- end
-
- def open
- @tree.open(self)
- self
- end
- def open_recurse
- @tree.open_recurse(self)
- self
- end
-
- def range_to(tag)
- @tree.range(self, tag)
- end
- def range_open_to(tag)
- @tree.range(self, tag)
- end
-
- def see
- @tree.see(self)
- self
- end
- def see_anchor(anchor)
- @tree.see_anchor(anchor, self)
- self
- end
-
- def selection_anchor
- @tree.selection_anchor(self)
- self
- end
- def selection_clear
- @tree.selection_clear(self)
- self
- end
- def selection_mark
- @tree.selection_mark(self)
- self
- end
- def selection_include?
- @tree.selection_include?(self)
- end
- def selection_set
- @tree.selection_set(self)
- self
- end
- def selection_toggle
- @tree.selection_toggle(self)
- self
- end
-
- def show
- @tree.show(self)
- self
- end
-
- def sort_once
- @tree.sort_once(self)
- self
- end
- def sort_once_recurse
- @tree.sort_once_recurse(self)
- self
- end
-
- def toggle
- @tree.toggle(self)
- self
- end
-end
-
-######################################
-
-class Tk::BLT::Treeview::Node < TkObject
- include Tk::BLT::Treeview::TagOrID_Methods
-
- TreeNodeID_TBL = TkCore::INTERP.create_table
- TreeNode_ID = ['blt_treeview_node'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ TreeNodeID_TBL.clear }
-
- def self.id2obj(tree, id)
- tpath = tree.path
- return id unless TreeNodeID_TBL[tpath]
- if TreeNodeID_TBL[tpath][id]
- TreeNodeID_TBL[tpath][id]
- else
- begin
- self.new(tree, nil, nil, 'node'=>Integer(id))
- rescue
- id
- end
- end
- end
-
- def self.new(tree, pos, parent=nil, keys={})
- if parent.kind_of?(Hash)
- keys = parent
- parent = nil
- end
-
- keys = _symbolkey2str(keys)
- tpath = tree.path
-
- if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id])
- keys.delete('node')
- tk_call(tree.path, 'move', id, pos, parent) if parent
- return obj
- end
-
- super(tree, pos, parent, keys)
- end
-
- def initialize(tree, pos, parent, keys)
- @parent = @tree = tree
- @tpath = @parent.path
-
- if (id = keys['node'])
- @path = @id = id
- tk_call(@tpath, 'move', @id, pos, tagid(parent)) if parent
- else
- name = TreeNode_ID.join(TkCore::INTERP._ip_id_).freeze
- TreeNode_ID[1].succ!
-
- at = keys.delete['at']
-
- if parent
- if parent.kind_of?(Tk::BLT::Treeview::Node) ||
- parent.kind_of?(Tk::BLT::Treeview::Tag)
- path = [get_full(parent.id)[0], name]
- at = nil # ignore 'at' option
- else
- path = [parent.to_s, name]
- end
- else
- path = name
- end
-
- if at
- @id = tk_call(@tpath, 'insert', '-at', tagid(at), pos, path, keys)
- else
- @id = tk_call(@tpath, 'insert', pos, path, keys)
- end
- @path = @id
- end
-
- TreeNodeID_TBL[@tpath] = {} unless TreeNodeID_TBL[@tpath]
- TreeNodeID_TBL[@tpath][@id] = self
- end
-
- def id
- @id
- end
-end
-
-######################################
-
-class Tk::BLT::Treeview::Tag < TkObject
- include Tk::BLT::Treeview::TagOrID_Methods
-
- TreeTagID_TBL = TkCore::INTERP.create_table
- TreeTag_ID = ['blt_treeview_tag'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ TreeTagID_TBL.clear }
-
- def self.id2obj(tree, id)
- tpath = tree.path
- return id unless TreeTagID_TBL[tpath]
- if TreeTagID_TBL[tpath][id]
- TreeTagID_TBL[tpath][id]
- else
- begin
- self.new(tree, nil, nil, 'name'=>Integer(id))
- rescue
- id
- end
- end
- end
-
- def self.new_by_name(tree, name, *ids)
- if (obj = TreeTagID_TBL[tree.path][name])
- return obj
- end
- new([tree, name], ids)
- end
-
- def self.new(tree, *ids)
- if tree.kind_of?(Array)
- super(tree[0], tree[1], ids)
- else
- super(tree, nil, ids)
- end
- end
-
- def initialize(tree, name, ids)
- @parent = @tree = tree
- @tpath = @parent.path
-
- if name
- @path = @id = name
- else
- @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_).freeze
- TreeTag_ID[1].succ!
- end
-
- TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
- TreeTagID_TBL[@tpath][@id] = self
-
- unless ids.empty?
- tk_call(@tpath, 'tag', 'add', @id, *(ids.collect{|id| tagid(id)}))
- end
- end
-
- def tagid(tag)
- if tag.kind_of?(Tk::BLT::Treeview::Node) \
- || tag.kind_of?(Tk::BLT::Treeview::Tag)
- tag.id
- else
- tag
- end
- end
- private :tagid
-
- def id
- @id
- end
-
- def add(*ids)
- tk_call(@tpath, 'tag', 'add', @id, *(ids{|id| tagid(id)}))
- self
- end
-
- def remove(*ids)
- tk_call(@tpath, 'tag', 'delete', @id, *(ids{|id| tagid(id)}))
- self
- end
-
- def forget
- tk_call(@tpath, 'tag', 'forget', @id)
- self
- end
-
- def nodes
- simplelist(tk_call(@tpath, 'tag', 'nodes', @id)).collect{|id|
- Tk::BLT::Treeview::Node.id2obj(@tree, id)
- }
- end
-end
-
-class Tk::BLT::Hiertable
- TkCommandNames = ['::blt::hiertable'.freeze].freeze
- WidgetClassName = 'Hiertable'.freeze
- WidgetClassNames[WidgetClassName] = self
-end
diff --git a/ext/tk/lib/tkextlib/blt/unix_dnd.rb b/ext/tk/lib/tkextlib/blt/unix_dnd.rb
deleted file mode 100644
index 3130c1e56f..0000000000
--- a/ext/tk/lib/tkextlib/blt/unix_dnd.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-#
-# tkextlib/blt/unix_dnd.rb
-#
-# *** This is alpha version, because there is no document on BLT. ***
-#
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- module DnD
- extend TkCore
-
- TkCommandNames = ['::blt::dnd'.freeze].freeze
-
- ##############################
-
- extend TkItemConfigMethod
-
- class << self
- def __item_cget_cmd(id)
- ['::blt::dnd', *id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- ['::blt::dnd', *id]
- end
- private :__item_config_cmd
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-
- def cget(win, option)
- itemconfigure(['cget', win], slot, value)
- end
- def configure(win, slot, value=None)
- itemconfigure(['configure', win], slot, value)
- end
- def configinfo(win, slot=nil)
- itemconfiginfo(['configure', win], slot)
- end
- def current_configinfo(win, slot=nil)
- current_itemconfiginfo(['configure', win], slot)
- end
-
- def tokwn_cget(win, option)
- itemconfigure(['token', 'cget', win], slot, value)
- end
- def token_configure(win, slot, value=None)
- itemconfigure(['token', 'configure', win], slot, value)
- end
- def token_configinfo(win, slot=nil)
- itemconfiginfo(['token', 'configure', win], slot)
- end
- def current_token_configinfo(win, slot=nil)
- current_itemconfiginfo(['token', 'configure', win], slot)
- end
-
- def token_windowconfigure(win, slot, value=None)
- itemconfigure(['token', 'window', win], slot, value)
- end
- def token_windowconfiginfo(win, slot=nil)
- itemconfiginfo(['token', 'window', win], slot)
- end
- def current_token_windowconfiginfo(win, slot=nil)
- current_itemconfiginfo(['token', 'window', win], slot)
- end
- end
-
- ##############################
-
- def self.cancel(win)
- tk_call('::blt::dnd', 'cancel', *wins)
- end
- def self.delete(*wins)
- tk_call('::blt::dnd', 'delete', *wins)
- end
- def self.delete_source(*wins)
- tk_call('::blt::dnd', 'delete', '-source', *wins)
- end
- def self.delete_target(*wins)
- tk_call('::blt::dnd', 'delete', '-target', *wins)
- end
- def self.drag(win, x, y, token=None)
- tk_call('::blt::dnd', 'drag', win, x, y, token)
- end
- def self.drop(win, x, y, token=None)
- tk_call('::blt::dnd', 'drop', win, x, y, token)
- end
- def self.get_data(win, fmt=nil, cmd=nil)
- if fmt
- tk_call('::blt::dnd', 'getdata', win, fmt, cmd)
- else
- list(tk_call('::blt::dnd', 'getdata', win))
- end
- end
- def self.names(pat=None)
- list(tk_call('::blt::dnd', 'names', pat))
- end
- def self.source_names(pat=None)
- list(tk_call('::blt::dnd', 'names', '-source', pat))
- end
- def self.target_names(pat=None)
- list(tk_call('::blt::dnd', 'names', '-target', pat))
- end
- def self.pull(win, fmt)
- tk_call('::blt::dnd', 'pull', win, fmt)
- end
- def self.register(win, keys={})
- tk_call('::blt::dnd', 'register', win, keys)
- end
- def self.select(win, x, y, timestamp)
- tk_call('::blt::dnd', 'select', win, x, y, timestamp)
- end
- def self.set_data(win, fmt=nil, cmd=nil)
- if fmt
- tk_call('::blt::dnd', 'setdata', win, fmt, cmd)
- else
- list(tk_call('::blt::dnd', 'setdata', win))
- end
- end
- def self.token(*args)
- tk_call('::blt::dnd', 'token', *args)
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/vector.rb b/ext/tk/lib/tkextlib/blt/vector.rb
deleted file mode 100644
index 540b6b9102..0000000000
--- a/ext/tk/lib/tkextlib/blt/vector.rb
+++ /dev/null
@@ -1,243 +0,0 @@
-#
-# tkextlib/blt/vector.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- class Vector < TkVariable
- TkCommandNames = ['::blt::vector'.freeze].freeze
-
- def self.create(*args)
- tk_call('::blt::vector', 'create', *args)
- end
-
- def self.destroy(*args)
- tk_call('::blt::vector', 'destroy', *args)
- end
-
- def self.expr(expression)
- tk_call('::blt::vector', 'expr', expression)
- end
-
- def self.names(pat=None)
- simplelist(tk_call('::blt::vector', 'names', pat)).collect{|name|
- if TkVar_ID_TBL[name]
- TkVar_ID_TBL[name]
- elsif name[0..1] == '::' && TkVar_ID_TBL[name[2..-1]]
- TkVar_ID_TBL[name[2..-1]]
- else
- name
- end
- }
- end
-
- ####################################
-
- def initialize(size=nil, keys={})
- if size.kind_of?(Hash)
- keys = size
- size = nil
- end
- if size.kind_of?(Array)
- # [first, last]
- size = size.join(':')
- end
- if size
- @id = INTERP._invoke('::blt::vector', 'create',
- "#auto(#{size})", *hash_kv(keys))
- else
- @id = INTERP._invoke('::blt::vector', 'create',
- "#auto", *hash_kv(keys))
- end
-
- TkVar_ID_TBL[@id] = self
-
- @def_default = false
- @default_val = nil
-
- @trace_var = nil
- @trace_elem = nil
- @trace_opts = nil
-
- # teach Tk-ip that @id is global var
- INTERP._invoke_without_enc('global', @id)
- end
-
- def destroy
- tk_call('::blt::vector', 'destroy', @id)
- end
-
- def inspect
- '#<Tk::BLT::Vector: ' + @id + '>'
- end
-
- def to_s
- @id
- end
-
- def *(item)
- list(tk_call(@id, '*', item))
- end
-
- def +(item)
- list(tk_call(@id, '+', item))
- end
-
- def -(item)
- list(tk_call(@id, '-', item))
- end
-
- def /(item)
- list(tk_call(@id, '/', item))
- end
-
- def append(*vectors)
- tk_call(@id, 'append', *vectors)
- end
-
- def binread(channel, len=None, keys={})
- if len.kind_of?(Hash)
- keys = len
- len = None
- end
- keys = _symbolkey2str(keys)
- keys['swap'] = None if keys.delete('swap')
- tk_call(@id, 'binread', channel, len, keys)
- end
-
- def clear()
- tk_call(@id, 'clear')
- self
- end
-
- def delete(*indices)
- tk_call(@id, 'delete', *indices)
- self
- end
-
- def dup_vector(vec)
- tk_call(@id, 'dup', vec)
- self
- end
-
- def expr(expression)
- tk_call(@id, 'expr', expression)
- self
- end
-
- def index(idx, val=None)
- number(tk_call(@id, 'index', idx, val))
- end
-
- def [](idx)
- index(idx)
- end
-
- def []=(idx, val)
- index(idx, val)
- end
-
- def length()
- number(tk_call(@id, 'length'))
- end
-
- def length=(size)
- number(tk_call(@id, 'length', size))
- end
-
- def merge(*vectors)
- tk_call(@id, 'merge', *vectors)
- self
- end
-
- def normalize(vec=None)
- tk_call(@id, 'normalize', vec)
- self
- end
-
- def notify(keyword)
- tk_call(@id, 'notify', keyword)
- self
- end
-
- def offset()
- number(tk_call(@id, 'offset'))
- end
-
- def offset=(val)
- number(tk_call(@id, 'offset', val))
- end
-
- def random()
- tk_call(@id, 'random')
- end
-
- def populate(vector, density=None)
- tk_call(@id, 'populate', vector, density)
- self
- end
-
- def range(first, last=None)
- list(tk_call(@id, 'range', first, last))
- end
-
- def search(val1, val2=None)
- list(tk_call(@id, 'search', val1, val2))
- end
-
- def set(item)
- tk_call(@id, 'set', item)
- self
- end
-
- def seq(start, finish=None, step=None)
- tk_call(@id, 'seq', start, finish, step)
- self
- end
-
- def sort(*vectors)
- tk_call(@id, 'sort', *vectors)
- self
- end
-
- def sort_reverse(*vectors)
- tk_call(@id, 'sort', '-reverse', *vectors)
- self
- end
-
- def split(*vectors)
- tk_call(@id, 'split', *vectors)
- self
- end
-
- def variable(var)
- tk_call(@id, 'variable', var)
- self
- end
- end
-
- class VectorAccess < Vector
- def self.new(name)
- return TkVar_ID_TBL[name] if TkVar_ID_TBL[name]
- super(name, size=nil, keys={})
- end
-
- def initialize(vec_name)
- @id = vec_name
- TkVar_ID_TBL[@id] = self
-
- @def_default = false
- @default_val = nil
-
- @trace_var = nil
- @trace_elem = nil
- @trace_opts = nil
-
- # teach Tk-ip that @id is global var
- INTERP._invoke_without_enc('global', @id)
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/watch.rb b/ext/tk/lib/tkextlib/blt/watch.rb
deleted file mode 100644
index ae5e50f126..0000000000
--- a/ext/tk/lib/tkextlib/blt/watch.rb
+++ /dev/null
@@ -1,142 +0,0 @@
-#
-# tkextlib/blt/watch.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- class Watch < TkObject
- extend TkCore
-
- TkCommandNames = ['::blt::watch'.freeze].freeze
-
- WATCH_ID_TBL = TkCore::INTERP.create_table
- BLT_WATCH_ID = ['blt_watch_id'.freeze, '00000'.taint].freeze
-
- def self.names(state = None)
- tk_split_list(tk_call('::blt::watch', 'names', state)).collect{|name|
- WATCH_ID_TBL[name] || name
- }
- end
-
- def __numval_optkeys
- ['maxlevel']
- end
- private :__numval_optkeys
-
- def __boolval_optkeys
- ['active']
- end
- private :__boolval_optkeys
-
- def __config_cmd
- ['::blt::watch', 'configure', self.path]
- end
- private :__config_cmd
-
- def initialize(name = nil, keys = {})
- if name.kind_of?(Hash)
- keys = name
- name = nil
- end
-
- if name
- @id = name.to_s
- else
- @id = BLT_WATCH_ID.join(TkCore::INTERP._ip_id_)
- BLT_WATCH_ID[1].succ!
- end
-
- @path = @id
-
- WATCH_ID_TBL[@id] = self
- tk_call('::blt::watch', 'create', @id, *hash_kv(keys))
- end
-
- def activate
- tk_call('::blt::watch', 'activate', @id)
- self
- end
- def deactivate
- tk_call('::blt::watch', 'deactivate', @id)
- self
- end
- def delete
- tk_call('::blt::watch', 'delete', @id)
- self
- end
- def info
- ret = []
- lst = tk_split_simplelist(tk_call('::blt::watch', 'info', @id))
- until lst.empty?
- k, v, *lst = lst
- k = k[1..-1]
- case k
- when /^(#{__strval_optkeys.join('|')})$/
- # do nothing
-
- when /^(#{__numval_optkeys.join('|')})$/
- begin
- v = number(v)
- rescue
- v = nil
- end
-
- when /^(#{__numstrval_optkeys.join('|')})$/
- v = num_or_str(v)
-
- when /^(#{__boolval_optkeys.join('|')})$/
- begin
- v = bool(v)
- rescue
- v = nil
- end
-
- when /^(#{__listval_optkeys.join('|')})$/
- v = simplelist(v)
-
- when /^(#{__numlistval_optkeys.join('|')})$/
- v = list(v)
-
- else
- if v.index('{')
- v = tk_split_list(v)
- else
- v = tk_tcl2ruby(v)
- end
- end
-
- ret << [k, v]
- end
-
- ret
- end
- def configinfo(slot = nil)
- if slot
- slot = slot.to_s
- v = cget(slot)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- [slot, v]
- else
- {slot=>v}
- end
- else
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- info
- else
- Hash[*(info.flatten)]
- end
- end
- end
- def cget(key)
- key = key.to_s
- begin
- info.assoc(key)[1]
- rescue
- fail ArgumentError, "unknown option '#{key}'"
- end
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/win_printer.rb b/ext/tk/lib/tkextlib/blt/win_printer.rb
deleted file mode 100644
index 7ac6a0dcfc..0000000000
--- a/ext/tk/lib/tkextlib/blt/win_printer.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-#
-# tkextlib/blt/win_printer.rb
-#
-# *** Windows only ***
-#
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- class Printer < TkObject
- extend TkCore
-
- TkCommandNames = ['::blt::printer'.freeze].freeze
-
- def self.enum(attribute)
- simplelist(tk_call('::blt::printer', 'enum', attribute))
- end
-
- def self.names(pat=None)
- simplelist(tk_call('::blt::printer', 'names', pat))
- end
-
- def self.open(printer)
- self.new(printer)
- end
-
- #################################
-
- def initialize(printer)
- @printer_id = tk_call('::blt::printer', 'open', printer)
- end
-
- def close
- tk_call('::blt::print', 'close', @printer_id)
- self
- end
- def get_attrs(var)
- tk_call('::blt::print', 'getattrs', @printer_id, var)
- var
- end
- def set_attrs(var)
- tk_call('::blt::print', 'setattrs', @printer_id, var)
- self
- end
- def snap(win)
- tk_call('::blt::print', 'snap', @printer_id, win)
- self
- end
- def write(str)
- tk_call('::blt::print', 'write', @printer_id, str)
- self
- end
- def write_with_title(title, str)
- tk_call('::blt::print', 'write', @printer_id, title, str)
- self
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/blt/winop.rb b/ext/tk/lib/tkextlib/blt/winop.rb
deleted file mode 100644
index e371d28ab7..0000000000
--- a/ext/tk/lib/tkextlib/blt/winop.rb
+++ /dev/null
@@ -1,107 +0,0 @@
-#
-# tkextlib/blt/winop.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/blt.rb'
-
-module Tk::BLT
- module Winop
- extend TkCore
-
- TkCommandNames = ['::blt::winop'.freeze].freeze
- end
- WinOp = Winop
-end
-
-class << Tk::BLT::Winop
- def changes(win)
- tk_call('::blt::winop', 'changes', win)
- end
-
- def colormap(win)
- Hash[*list(tk_call('::blt::winop', 'colormap', win))]
- end
-
- def convolve(src, dest, filter)
- tk_call('::blt::winop', 'convolve', src, dest, filter)
- end
-
- def image_convolve(src, dest, filter)
- tk_call('::blt::winop', 'image', 'convolve', src, dest, filter)
- end
- def image_gradient(photo, left, right, type)
- tk_call('::blt::winop', 'image', 'gradient', photo, left, right, type)
- end
- def image_read_jpeg(file, photo)
- tk_call('::blt::winop', 'image', 'readjpeg', file, photo)
- end
- def image_resample(src, dest, horiz_filter=None, vert_filter=None)
- tk_call('::blt::winop', 'image', 'resample',
- src, dest, horiz_filter, vert_filter)
- end
- def image_rotate(src, dest, angle)
- tk_call('::blt::winop', 'image', 'rotate', src, dest, angle)
- end
- def image_snap(win, photo, width=None, height=None)
- tk_call('::blt::winop', 'image', 'snap', win, photo, width, height)
- end
- def image_subsample(src, dest, x, y, width, height,
- horiz_filter=None, vert_filter=None)
- tk_call('::blt::winop', 'image', 'subsample',
- src, dest, x, y, width, height, horiz_filter, vert_filter)
- end
-
- def quantize(src, dest, colors)
- tk_call('::blt::winop', 'quantize', src, dest, colors)
- end
-
- def query()
- tk_call('::blt::winop', 'query')
- end
-
- def read_jpeg(file, photo)
- tk_call('::blt::winop', 'readjpeg', file, photo)
- end
-
- def resample(src, dest, horiz_filter=None, vert_filter=None)
- tk_call('::blt::winop', 'resample',
- src, dest, horiz_filter, vert_filter)
- end
-
- def subsample(src, dest, x, y, width, height,
- horiz_filter=None, vert_filter=None)
- tk_call('::blt::winop', 'subsample',
- src, dest, x, y, width, height, horiz_filter, vert_filter)
- end
-
- def raise(*wins)
- tk_call('::blt::winop', 'raise', *wins)
- end
-
- def lower(*wins)
- tk_call('::blt::winop', 'lower', *wins)
- end
-
- def map(*wins)
- tk_call('::blt::winop', 'map', *wins)
- end
-
- def unmap(*wins)
- tk_call('::blt::winop', 'unmap', *wins)
- end
-
- def move(win, x, y)
- tk_call('::blt::winop', 'move', win, x, y)
- end
-
- def snap(win, photo)
- tk_call('::blt::winop', 'snap', win, photo)
- end
-
- def warpto(win = None)
- tk_call('::blt::winop', 'warpto', win)
- end
- alias warp_to warpto
-end
diff --git a/ext/tk/lib/tkextlib/bwidget.rb b/ext/tk/lib/tkextlib/bwidget.rb
deleted file mode 100644
index 62631d8b54..0000000000
--- a/ext/tk/lib/tkextlib/bwidget.rb
+++ /dev/null
@@ -1,151 +0,0 @@
-#
-# BWidget extension support
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-
-# call setup script for general 'tkextlib' libraries
-require 'tkextlib/setup.rb'
-
-# call setup script
-require 'tkextlib/bwidget/setup.rb'
-
-# load all image format handlers
-#TkPackage.require('BWidget', '1.7')
-TkPackage.require('BWidget')
-
-module Tk
- module BWidget
- TkComm::TkExtlibAutoloadModule.unshift(self)
-
- extend TkCore
-
- LIBRARY = tk_call('set', '::BWIDGET::LIBRARY')
-
- PACKAGE_NAME = 'BWidget'.freeze
- def self.package_name
- PACKAGE_NAME
- end
-
- def self.package_version
- begin
- TkPackage.require('BWidget')
- rescue
- ''
- end
- end
-
- def self.XLFDfont(cmd, *args)
- if args[-1].kind_of?(Hash)
- keys = args.pop
- args.concat(hash_kv(keys))
- end
- tk_call('BWidget::XLFDfont', cmd, *args)
- end
-
- def self.assert(exp, msg=None)
- tk_call('BWidget::assert', exp, msg)
- end
-
- def self.badOptionString(type, value, list)
- tk_call('BWidget::badOptionString', type, value, list)
- end
-
- def self.bindMouseWheel(widget)
- tk_call('BWidget::bindMouseWheel', widget)
- end
-
- def self.classes(klass)
- list(tk_call('BWidget::classes', klass))
- end
-
- def self.clonename(menu)
- tk_call('BWidget::clonename', menu)
- end
-
- def self.focus(opt, path)
- tk_call('BWidget::focus', opt, path)
- end
-
- def self.get3dcolor(path, bgcolor)
- tk_call('BWidget::get3dcolor', path, bgcolor)
- end
-
- def self.getname(name)
- tk_call('BWidget::getname', name)
- end
-
- def self.grab(opt, path)
- tk_call('BWidget::grab', opt, path)
- end
-
- def self.inuse(klass)
- bool(tk_call('BWidget::inuse', klass))
- end
-
- def self.library(klass, *klasses)
- tk_call('BWidget::library', klass, *klasses)
- end
-
- def self.lreorder(list, neworder)
- tk_call('BWidget::lreorder', list, neworder)
- end
-
- def self.parsetext(text)
- tk_call('BWidget::parsetext', text)
- end
-
- def self.place(path, w, h, *args)
- if args[-1].kind_of?(Hash)
- keys = args.pop
- args.concat(hash_kv(keys))
- end
- tk_call('BWidget::place', path, w, h, *(args.flatten))
- end
-
- def self.write(file, mode=None)
- tk_call('BWidget::write', file, mode)
- end
-
- def self.wrongNumArgsString(str)
- tk_call('BWidget::wrongNumArgsString', str)
- end
-
- ####################################################
-
- autoload :ArrowButton, 'tkextlib/bwidget/arrowbutton'
- autoload :Bitmap, 'tkextlib/bwidget/bitmap'
- autoload :Button, 'tkextlib/bwidget/button'
- autoload :ButtonBox, 'tkextlib/bwidget/buttonbox'
- autoload :ComboBox, 'tkextlib/bwidget/combobox'
- autoload :Dialog, 'tkextlib/bwidget/dialog'
- autoload :DragSite, 'tkextlib/bwidget/dragsite'
- autoload :DropSite, 'tkextlib/bwidget/dropsite'
- autoload :DynamicHelp, 'tkextlib/bwidget/dynamichelp'
- autoload :Entry, 'tkextlib/bwidget/entry'
- autoload :Label, 'tkextlib/bwidget/label'
- autoload :LabelEntry, 'tkextlib/bwidget/labelentry'
- autoload :LabelFrame, 'tkextlib/bwidget/labelframe'
- autoload :ListBox, 'tkextlib/bwidget/listbox'
- autoload :MainFrame, 'tkextlib/bwidget/mainframe'
- autoload :MessageDlg, 'tkextlib/bwidget/messagedlg'
- autoload :NoteBook, 'tkextlib/bwidget/notebook'
- autoload :PagesManager, 'tkextlib/bwidget/pagesmanager'
- autoload :PanedWindow, 'tkextlib/bwidget/panedwindow'
- autoload :PasswdDlg, 'tkextlib/bwidget/passwddlg'
- autoload :ProgressBar, 'tkextlib/bwidget/progressbar'
- autoload :ProgressDlg, 'tkextlib/bwidget/progressdlg'
- autoload :ScrollableFrame, 'tkextlib/bwidget/scrollableframe'
- autoload :ScrolledWindow, 'tkextlib/bwidget/scrolledwindow'
- autoload :ScrollView, 'tkextlib/bwidget/scrollview'
- autoload :SelectColor, 'tkextlib/bwidget/selectcolor'
- autoload :SelectFont, 'tkextlib/bwidget/selectfont'
- autoload :Separator, 'tkextlib/bwidget/separator'
- autoload :SpinBox, 'tkextlib/bwidget/spinbox'
- autoload :TitleFrame, 'tkextlib/bwidget/titleframe'
- autoload :Tree, 'tkextlib/bwidget/tree'
- autoload :Widget, 'tkextlib/bwidget/widget'
-
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb b/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb
deleted file mode 100644
index 770e5e9ef1..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# tkextlib/bwidget/arrowbutton.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/button'
-
-module Tk
- module BWidget
- class ArrowButton < Tk::BWidget::Button
- end
- end
-end
-
-class Tk::BWidget::ArrowButton
- TkCommandNames = ['ArrowButton'.freeze].freeze
- WidgetClassName = 'ArrowButton'.freeze
- WidgetClassNames[WidgetClassName] = self
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/bitmap.rb b/ext/tk/lib/tkextlib/bwidget/bitmap.rb
deleted file mode 100644
index 6cfde203e8..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/bitmap.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# tkextlib/bwidget/bitmap.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-require 'tk'
-require 'tk/image'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class Bitmap < TkPhotoImage
- end
- end
-end
-
-class Tk::BWidget::Bitmap
- def initialize(name)
- @path = tk_call_without_enc('Bitmap::get', name)
- Tk_IMGTBL[@path] = self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/button.rb b/ext/tk/lib/tkextlib/bwidget/button.rb
deleted file mode 100644
index 4a9d4a7948..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/button.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# tkextlib/bwidget/button.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/button'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class Button < TkButton
- end
- end
-end
-
-class Tk::BWidget::Button
- TkCommandNames = ['Button'.freeze].freeze
- WidgetClassName = 'Button'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'helptext'
- end
- private :__strval_optkeys
-
- def __tkvariable_optkeys
- super() << 'helpvar'
- end
- private :__tkvariable_optkeys
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/buttonbox.rb b/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
deleted file mode 100644
index ef999239f9..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-#
-# tkextlib/bwidget/buttonbox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/button'
-
-module Tk
- module BWidget
- class ButtonBox < TkWindow
- end
- end
-end
-
-class Tk::BWidget::ButtonBox
- TkCommandNames = ['ButtonBox'.freeze].freeze
- WidgetClassName = 'ButtonBox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- include TkItemConfigMethod
-
- def __boolval_optkeys
- super() << 'homogeneous'
- end
- private :__boolval_optkeys
-
- def tagid(tagOrId)
- if tagOrId.kind_of?(Tk::BWidget::Button)
- name = tagOrId[:name]
- return index(name) unless name.empty?
- end
- if tagOrId.kind_of?(TkButton)
- return index(tagOrId[:text])
- end
- # index(tagOrId.to_s)
- index(_get_eval_string(tagOrId))
- end
-
- def add(keys={}, &b)
- win = window(tk_send('add', *hash_kv(keys)))
- win.instance_eval(&b) if b
- win
- end
-
- def delete(idx)
- tk_send('delete', tagid(idx))
- self
- end
-
- def index(idx)
- if idx.kind_of?(Tk::BWidget::Button)
- name = idx[:name]
- idx = name unless name.empty?
- end
- if idx.kind_of?(TkButton)
- idx = idx[:text]
- end
- number(tk_send('index', idx.to_s))
- end
-
- def insert(idx, keys={}, &b)
- win = window(tk_send('insert', tagid(idx), *hash_kv(keys)))
- win.instance_eval(&b) if b
- win
- end
-
- def invoke(idx)
- tk_send('invoke', tagid(idx))
- self
- end
-
- def set_focus(idx)
- tk_send('setfocus', tagid(idx))
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/combobox.rb b/ext/tk/lib/tkextlib/bwidget/combobox.rb
deleted file mode 100644
index 31f71c3aaf..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/combobox.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# tkextlib/bwidget/combobox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/entry'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/listbox'
-require 'tkextlib/bwidget/spinbox'
-
-module Tk
- module BWidget
- class ComboBox < Tk::BWidget::SpinBox
- end
- end
-end
-
-class Tk::BWidget::ComboBox
- include Scrollable
-
- TkCommandNames = ['ComboBox'.freeze].freeze
- WidgetClassName = 'ComboBox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def get_listbox(&b)
- win = window(tk_send_without_enc('getlistbox'))
- win.instance_eval(&b) if b
- win
- end
-
- def icursor(idx)
- tk_send_without_enc('icursor', idx)
- end
-
- def post
- tk_send_without_enc('post')
- self
- end
-
- def unpost
- tk_send_without_enc('unpost')
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/dialog.rb b/ext/tk/lib/tkextlib/bwidget/dialog.rb
deleted file mode 100644
index 2790d88d24..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/dialog.rb
+++ /dev/null
@@ -1,157 +0,0 @@
-#
-# tkextlib/bwidget/dialog.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/frame'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/buttonbox'
-
-module Tk
- module BWidget
- class Dialog < TkWindow
- end
- end
-end
-
-class Tk::BWidget::Dialog
- TkCommandNames = ['Dialog'.freeze].freeze
- WidgetClassName = 'Dialog'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- include TkItemConfigMethod
-
- def __strval_optkeys
- super() << 'title'
- end
- private :__strval_optkeys
-
- def __boolval_optkeys
- super() << 'transient' << 'homogeneous'
- end
- private :__boolval_optkeys
-
- def initialize(parent=nil, keys=nil)
- @relative = ''
- if parent.kind_of?(Hash)
- keys = _symbolkey2str(parent)
- @relative = keys['parent'] if keys.key?('parent')
- @relative = keys.delete('relative') if keys.key?('relative')
- super(keys)
- elsif keys
- keys = _symbolkey2str(keys)
- @relative = keys.delete('parent') if keys.key?('parent')
- @relative = keys.delete('relative') if keys.key?('relative')
- super(parent, keys)
- else
- super(parent)
- end
- end
-
- def create_self(keys)
- cmd = self.class::TkCommandNames[0]
- if keys and keys != None
- tk_call_without_enc(cmd, @path, '-parent', @relative,
- *hash_kv(keys, true))
- else
- tk_call_without_enc(cmd, @path, '-parent', @relative)
- end
- end
-
- def cget(slot)
- if slot.to_s == 'relative'
- super('parent')
- else
- super(slot)
- end
- end
-
- def configure(slot, value=None)
- if slot.kind_of?(Hash)
- slot = _symbolkey2str(slot)
- slot['parent'] = slot.delete('relative') if slot.key?('relative')
- super(slot)
- else
- if slot.to_s == 'relative'
- super('parent', value)
- else
- super(slot, value)
- end
- end
- end
-
- def configinfo(slot=nil)
- if slot
- if slot.to_s == 'relative'
- super('parent')
- else
- super(slot)
- end
- else
- ret = super()
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- ret << ['relative', 'parent']
- else
- ret['relative'] = 'parent'
- end
- end
- end
-
- def tagid(tagOrId)
- if tagOrId.kind_of?(Tk::BWidget::Button)
- name = tagOrId[:name]
- return index(name) unless name.empty?
- end
- if tagOrId.kind_of?(TkButton)
- return index(tagOrId[:text])
- end
- # index(tagOrId.to_s)
- index(_get_eval_string(tagOrId))
- end
-
- def add(keys={}, &b)
- win = window(tk_send('add', *hash_kv(keys)))
- win.instance_eval(&b) if b
- win
- end
-
- def get_frame(&b)
- win = window(tk_send('getframe'))
- win.instance_eval(&b) if b
- win
- end
-
- def get_buttonbox(&b)
- win = window(@path + '.bbox')
- win.instance_eval(&b) if b
- win
- end
-
- def draw(focus_win=None)
- tk_send('draw', focus_win)
- end
-
- def enddialog(ret)
- tk_send('enddialog', ret)
- end
-
- def index(idx)
- get_buttonbox.index(idx)
- end
-
- def invoke(idx)
- tk_send('invoke', tagid(idx))
- self
- end
-
- def set_focus(idx)
- tk_send('setfocus', tagid(idx))
- self
- end
-
- def withdraw
- tk_send('withdraw')
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/dragsite.rb b/ext/tk/lib/tkextlib/bwidget/dragsite.rb
deleted file mode 100644
index 4d4de1780c..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/dragsite.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# tkextlib/bwidget/dragsite.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- module DragSite
- end
- end
-end
-
-module Tk::BWidget::DragSite
- include Tk
- extend Tk
-
- def self.include(klass, type, event)
- tk_call('DragSite::include', klass, type, event)
- end
-
- def self.register(path, keys={})
- tk_call('DragSite::register', path, *hash_kv(keys))
- end
-
- def self.set_drag(path, subpath, initcmd, endcmd, force=None)
- tk_call('DragSite::setdrag', path, subpath, initcmd, endcmd, force)
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/dropsite.rb b/ext/tk/lib/tkextlib/bwidget/dropsite.rb
deleted file mode 100644
index e5e98fbc51..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/dropsite.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# tkextlib/bwidget/dropsite.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- module DropSite
- end
- end
-end
-
-module Tk::BWidget::DropSite
- include Tk
- extend Tk
-
- def self.include(klass, type)
- tk_call('DropSite::include', klass, type)
- end
-
- def self.register(path, keys={})
- tk_call('DropSite::register', path, *hash_kv(keys))
- end
-
- def self.set_cursor(cursor)
- tk_call('DropSite::setcursor', cursor)
- end
-
- def self.set_drop(path, subpath, dropover, drop, force=None)
- tk_call('DropSite::setdrop', path, subpath, dropover, drop, force)
- end
-
- def self.set_operation(op)
- tk_call('DropSite::setoperation', op)
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb b/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb
deleted file mode 100644
index 224304f2ab..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# tkextlib/bwidget/dynamichelp.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- module DynamicHelp
- end
- end
-end
-
-module Tk::BWidget::DynamicHelp
- include Tk
- extend Tk
-
- def self.__pathname
- 'DynamicHelp::configure'
- end
-
- def __strval_optkeys
- super() << 'topbackground'
- end
- private :__strval_optkeys
-
- def self.__cget_cmd
- ['DynamicHelp::configure']
- end
-
- def self.__config_cmd
- ['DynamicHelp::configure']
- end
-
- def self.cget(slot)
- self.current_configinfo(slot).values[0]
- end
-
- def self.add(widget, keys={})
- tk_call('DynamicHelp::add', widget, *hash_kv(keys))
- end
-
- def self.delete(widget)
- tk_call('DynamicHelp::delete', widget)
- end
-
- def self.include(klass, type)
- tk_call('DynamicHelp::include', klass, type)
- end
-
- def self.sethelp(path, subpath, force=None)
- tk_call('DynamicHelp::sethelp', path, subpath, force)
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/entry.rb b/ext/tk/lib/tkextlib/bwidget/entry.rb
deleted file mode 100644
index aafb4aa7ff..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/entry.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# tkextlib/bwidget/entry.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/entry'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class Entry < TkEntry
- end
- end
-end
-
-class Tk::BWidget::Entry
- include Scrollable
-
- TkCommandNames = ['Entry'.freeze].freeze
- WidgetClassName = 'Entry'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'helptext' << 'insertbackground'
- end
- private :__strval_optkeys
-
- def __boolval_optkeys
- super() << 'dragenabled' << 'dropenabled' << 'editable'
- end
- private :__boolval_optkeys
-
- def __tkvariable_optkeys
- super() << 'helpvar'
- end
- private :__tkvariable_optkeys
-
- def invoke
- tk_send_without_enc('invoke')
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/label.rb b/ext/tk/lib/tkextlib/bwidget/label.rb
deleted file mode 100644
index ce10ecaf8b..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/label.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# tkextlib/bwidget/label.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/label'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class Label < TkLabel
- end
- end
-end
-
-class Tk::BWidget::Label
- TkCommandNames = ['Label'.freeze].freeze
- WidgetClassName = 'Label'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'helptext'
- end
- private :__strval_optkeys
-
- def __boolval_optkeys
- super() << 'dragenabled' << 'dropenabled'
- end
- private :__boolval_optkeys
-
- def __tkvariable_optkeys
- super() << 'helpvar'
- end
- private :__tkvariable_optkeys
-
- def set_focus
- tk_send_without_enc('setfocus')
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/labelentry.rb b/ext/tk/lib/tkextlib/bwidget/labelentry.rb
deleted file mode 100644
index 931feb9b48..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/labelentry.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# tkextlib/bwidget/labelentry.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/entry'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/labelframe'
-require 'tkextlib/bwidget/entry'
-
-module Tk
- module BWidget
- class LabelEntry < TkEntry
- end
- end
-end
-
-class Tk::BWidget::LabelEntry
- include Scrollable
-
- TkCommandNames = ['LabelEntry'.freeze].freeze
- WidgetClassName = 'LabelEntry'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'helptext' << 'insertbackground' << 'entryfg' << 'entrybg'
- end
- private :__strval_optkeys
-
- def __tkvariable_optkeys
- super() << 'helpvar'
- end
- private :__tkvariable_optkeys
-
- def __font_optkeys
- super() << 'labelfont'
- end
- private :__font_optkeys
-
- #def entrybind(*args)
- # _bind([path, 'bind'], *args)
- # self
- #end
- def entrybind(context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([path, 'bind'], context, cmd, *args)
- self
- end
-
- #def entrybind_append(*args)
- # _bind_append([path, 'bind'], *args)
- # self
- #end
- def entrybind_append(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([path, 'bind'], context, cmd, *args)
- self
- end
-
- def entrybind_remove(*args)
- _bind_remove([path, 'bind'], *args)
- self
- end
-
- def entrybindinfo(*args)
- _bindinfo([path, 'bind'], *args)
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/labelframe.rb b/ext/tk/lib/tkextlib/bwidget/labelframe.rb
deleted file mode 100644
index f7b267eebb..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/labelframe.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# tkextlib/bwidget/labelframe.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/frame'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/label'
-
-module Tk
- module BWidget
- class LabelFrame < TkWindow
- end
- end
-end
-
-class Tk::BWidget::LabelFrame
- TkCommandNames = ['LabelFrame'.freeze].freeze
- WidgetClassName = 'LabelFrame'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'helptext'
- end
- private :__strval_optkeys
-
- def __boolval_optkeys
- super() << 'dragenabled' << 'dropenabled'
- end
- private :__boolval_optkeys
-
- def __tkvariable_optkeys
- super() << 'helpvar'
- end
- private :__tkvariable_optkeys
-
- def self.align(*args)
- tk_call('LabelFrame::align', *args)
- end
- def get_frame(&b)
- win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
- win
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/listbox.rb b/ext/tk/lib/tkextlib/bwidget/listbox.rb
deleted file mode 100644
index 1267500661..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/listbox.rb
+++ /dev/null
@@ -1,339 +0,0 @@
-#
-# tkextlib/bwidget/listbox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/canvas'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class ListBox < TkWindow
- # is NOT a subclass of a listbox widget class.
- # because it constructed on a canvas widget.
-
- class Item < TkObject
- end
- end
- end
-end
-
-class Tk::BWidget::ListBox
- include TkItemConfigMethod
- include Scrollable
-
- TkCommandNames = ['ListBox'.freeze].freeze
- WidgetClassName = 'ListBox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- class Event_for_Items < TkEvent::Event
- def self._get_extra_args_tbl
- [
- TkComm.method(:string) # item idenfier
- ]
- end
- end
-
- def __boolval_optkeys
- super() << 'autofocus' << 'dragenabled' << 'dropenabled' << 'selectfill'
- end
- private :__boolval_optkeys
-
- def tagid(tag)
- if tag.kind_of?(Tk::BWidget::ListBox::Item)
- tag.id
- else
- # tag
- _get_eval_string(tag)
- end
- end
-
- #def imagebind(*args)
- # _bind_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
- # self
- #end
- def imagebind(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_for_event_class(Event_for_Items, [path, 'bindImage'],
- context, cmd, *args)
- self
- end
-
- #def imagebind_append(*args)
- # _bind_append_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
- # self
- #end
- def imagebind_append(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append_for_event_class(Event_for_Items, [path, 'bindImage'],
- context, cmd, *args)
- self
- end
-
- def imagebind_remove(*args)
- _bind_remove_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
- self
- end
-
- def imagebindinfo(*args)
- _bindinfo_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
- end
-
- #def textbind(*args)
- # _bind_for_event_class(Event_for_Items, [path, 'bindText'], *args)
- # self
- #end
- def textbind(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_for_event_class(Event_for_Items, [path, 'bindText'],
- context, cmd, *args)
- self
- end
-
- #def textbind_append(*args)
- # _bind_append_for_event_class(Event_for_Items, [path, 'bindText'], *args)
- # self
- #end
- def textbind_append(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append_for_event_class(Event_for_Items, [path, 'bindText'],
- context, cmd, *args)
- self
- end
-
- def textbind_remove(*args)
- _bind_remove_for_event_class(Event_for_Items, [path, 'bindText'], *args)
- self
- end
-
- def textbindinfo(*args)
- _bindinfo_for_event_class(Event_for_Items, [path, 'bindText'], *args)
- end
-
- def delete(*args)
- tk_send('delete', *args)
- self
- end
-
- def edit(item, text, *args)
- tk_send('edit', tagid(item), text, *args)
- self
- end
-
- def exist?(item)
- bool(tk_send('exists', tagid(item)))
- end
-
- def index(item)
- num_or_str(tk_send('index', tagid(item)))
- end
-
- def insert(idx, item, keys={})
- tk_send('insert', idx, tagid(item), *hash_kv(keys))
- self
- end
-
- def get_item(idx)
- tk_send('items', idx)
- end
-
- def items(first=None, last=None)
- list(tk_send('items', first, last))
- end
-
- def move(item, idx)
- tk_send('move', tagid(item), idx)
- self
- end
-
- def reorder(neworder)
- tk_send('reorder', neworder)
- self
- end
-
- def see(item)
- tk_send('see', tagid(item))
- self
- end
-
- def selection_clear
- tk_send_without_enc('selection', 'clear')
- self
- end
-
- def selection_set(*args)
- tk_send_without_enc('selection', 'set',
- *(args.collect{|item| tagid(item)}))
- self
- end
-
- def selection_add(*args)
- tk_send_without_enc('selection', 'add',
- *(args.collect{|item| tagid(item)}))
- self
- end
-
- def selection_remove(*args)
- tk_send_without_enc('selection', 'remove',
- *(args.collect{|item| tagid(item)}))
- self
- end
-
- def selection_get(*args)
- simplelist(tk_send_without_enc('selection', 'get')).collect{|item|
- Tk::BWidget::ListBox::Item.id2obj(self, item)
- }
- end
-end
-
-class Tk::BWidget::ListBox::Item
- include TkTreatTagFont
-
- ListItem_TBL = TkCore::INTERP.create_table
- ListItem_ID = ['bw:item'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ ListItem_TBL.clear }
-
- def self.id2obj(lbox, id)
- lpath = lbox.path
- return id unless ListItem_TBL[lpath]
- ListItem_TBL[lpath][id]? ListItem_TBL[lpath][id]: id
- end
-
- def initialize(lbox, *args)
- if lbox.kind_of?(Tk::BWidget::ListBox)
- @listbox = lbox
- else
- fail RuntimeError,
- "expect Tk::BWidget::ListBox or Tk::BWidget::ListBox::Item for 1st argument"
- end
-
- if args[-1].kind_of?(Hash)
- keys = _symbolkey2str(args.pop)
- else
- keys = {}
- end
-
- index = keys.delete('index')
- unless args.empty?
- index = args.shift
- end
- index = 'end' unless index
-
- unless args.empty?
- fail RuntimeError, 'too much arguments'
- end
-
- @lpath = @listbox.path
-
- if keys.key?('itemname')
- @path = @id = keys.delete('itemname')
- else
- @path = @id = ListItem_ID.join(TkCore::INTERP._ip_id_)
- ListItem_ID[1].succ!
- end
-
- ListItem_TBL[@id] = self
- ListItem_TBL[@lpath] = {} unless ListItem_TBL[@lpath]
- ListItem_TBL[@lpath][@id] = self
-
- @listbox.insert(index, @id, keys)
- end
-
- def listbox
- @listbox
- end
-
- def id
- @id
- end
-
- def [](key)
- cget(key)
- end
-
- def []=(key, val)
- configure(key, val)
- val
- end
-
- def cget(key)
- @listbox.itemcget(@id, key)
- end
-
- def configure(key, val=None)
- @listbox.itemconfigure(@id, key, val)
- end
-
- def configinfo(key=nil)
- @listbox.itemconfiginfo(@id, key)
- end
-
- def current_configinfo(key=nil)
- @listbox.current_itemconfiginfo(@id, key)
- end
-
- def delete
- @listbox.delete(@id)
- self
- end
-
- def edit(*args)
- @listbox.edit(@id, *args)
- self
- end
-
- def exist?
- @listbox.exist?(@id)
- end
-
- def index
- @listbox.index(@id)
- end
-
- def move(index)
- @listbox.move(@id, index)
- end
-
- def see
- @listbox.see(@id)
- end
-
- def selection_add
- @listbox.selection_add(@id)
- end
-
- def selection_remove
- @listbox.selection_remove(@id)
- end
-
- def selection_set
- @listbox.selection_set(@id)
- end
-
- def selection_toggle
- @listbox.selection_toggle(@id)
- end
-end
-
diff --git a/ext/tk/lib/tkextlib/bwidget/mainframe.rb b/ext/tk/lib/tkextlib/bwidget/mainframe.rb
deleted file mode 100644
index c54e878557..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/mainframe.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-#
-# tkextlib/bwidget/mainframe.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/frame'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/progressbar'
-
-module Tk
- module BWidget
- class MainFrame < TkWindow
- end
- end
-end
-
-class Tk::BWidget::MainFrame
- TkCommandNames = ['MainFrame'.freeze].freeze
- WidgetClassName = 'MainFrame'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'progressfg'
- end
- private :__strval_optkeys
-
- def __tkvariable_optkeys
- super() << 'progressvar'
- end
- private :__tkvariable_optkeys
-
- def __val2ruby_optkeys # { key=>proc, ... }
- # The method is used to convert a opt-value to a ruby's object.
- # When get the value of the option "key", "proc.call(value)" is called.
- {
- 'menu'=>proc{|v| simplelist(v).collect!{|elem| simplelist(v)}}
- }
- end
- private :__val2ruby_optkeys
-
- def add_indicator(keys={}, &b)
- win = window(tk_send('addindicator', *hash_kv(keys)))
- win.instance_eval(&b) if b
- win
- end
-
- def add_toolbar(&b)
- win = window(tk_send('addtoolbar'))
- win.instance_eval(&b) if b
- win
- end
-
- def get_frame(&b)
- win = window(tk_send('getframe'))
- win.instance_eval(&b) if b
- win
- end
-
- def get_indicator(idx, &b)
- win = window(tk_send('getindicator', idx))
- win.instance_eval(&b) if b
- win
- end
-
- def get_menu(menu_id, &b)
- win = window(tk_send('getmenu', menu_id))
- win.instance_eval(&b) if b
- win
- end
-
- def get_toolbar(idx, &b)
- win = window(tk_send('gettoolbar', idx))
- win.instance_eval(&b) if b
- win
- end
-
- def set_menustate(tag, state)
- tk_send('setmenustate', tag, state)
- self
- end
-
- def show_statusbar(name)
- tk_send('showstatusbar', name)
- self
- end
-
- def show_toolbar(idx, mode)
- tk_send('showtoolbar', idx, mode)
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/messagedlg.rb b/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
deleted file mode 100644
index 9c946d0630..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
+++ /dev/null
@@ -1,178 +0,0 @@
-#
-# tkextlib/bwidget/messagedlg.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/dialog.rb'
-
-module Tk
- module BWidget
- class MessageDlg < TkWindow
- end
- end
-end
-
-class Tk::BWidget::MessageDlg
- TkCommandNames = ['MessageDlg'.freeze].freeze
- WidgetClassName = 'MessageDlg'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def initialize(parent=nil, keys=nil)
- @relative = ''
- if parent.kind_of?(Hash)
- keys = _symbolkey2str(parent)
- @relative = keys['parent'] if keys.key?('parent')
- @relative = keys.delete('relative') if keys.key?('relative')
- super(keys)
- elsif keys
- keys = _symbolkey2str(keys)
- @relative = keys.delete('parent') if keys.key?('parent')
- @relative = keys.delete('relative') if keys.key?('relative')
- super(parent, keys)
- else
- super(parent)
- end
- end
-
- def create_self(keys)
- # NOT create widget.
- # Because the widget no longer exist when returning from creation.
- @keys = _symbolkey2str(keys).update('parent'=>@relative)
- @info = nil
- end
- private :create_self
-
- def __strval_optkeys
- super() << 'message' << 'title'
- end
- private :__strval_optkeys
-
- def __listval_optkeys
- super() << 'buttons'
- end
- private :__listval_optkeys
-
- def cget(slot)
- slot = slot.to_s
- if slot == 'relative'
- slot = 'parent'
- end
- if winfo_exist?
- val = super(slot)
- @keys[slot] = val
- end
- @keys[slot]
- end
-
- def configure(slot, value=None)
- if winfo_exist?
- super(slot, value)
- end
- if slot.kind_of?(Hash)
- slot = _symbolkey2str(slot)
- slot['parent'] = slot.delete('relative') if slot.key?('relative')
- @keys.update(slot)
-
- if @info
- # update @info
- slot.each{|k, v|
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if (inf = @info.assoc(k))
- inf[-1] = v
- else
- @info << [k, '', '', '', v]
- end
- else
- if (inf = @info[k])
- inf[-1] = v
- else
- @info[k] = ['', '', '', v]
- end
- end
- }
- end
-
- else # ! Hash
- slot = slot.to_s
- slot = 'parent' if slot == 'relative'
- @keys[slot] = value
-
- if @info
- # update @info
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if (inf = @info.assoc(slot))
- inf[-1] = value
- else
- @info << [slot, '', '', '', value]
- end
- else
- if (inf = @info[slot])
- inf[-1] = value
- else
- @info[slot] = ['', '', '', value]
- end
- end
- end
- end
-
- self
- end
-
- def configinfo(slot=nil)
- if winfo_exist?
- @info = super()
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- @info << ['relative', 'parent']
- else
- @info['relative'] = 'parent'
- end
- end
-
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if @info
- if winfo_exist?
- # update @keys
- @info.each{|inf| @keys[inf[0]] = inf[-1] if inf.size > 2 }
- end
- else
- @info = []
- @keys.each{|k, v|
- @info << [k, '', '', '', v]
- }
- @info << ['relative', 'parent']
- end
-
- if slot
- @info.asoc(slot.to_s).dup
- else
- @info.dup
- end
-
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if @info
- if winfo_exist?
- # update @keys
- @info.each{|k, inf| @keys[k] = inf[-1] if inf.size > 2 }
- end
- else
- @info = {}
- @keys.each{|k, v|
- @info[k] = ['', '', '', v]
- }
- @info['relative'] = 'parent'
- end
-
- if slot
- @info[slot.to_s].dup
- else
- @info.dup
- end
- end
- end
-
- def create
- num_or_str(tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys)))
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/notebook.rb b/ext/tk/lib/tkextlib/bwidget/notebook.rb
deleted file mode 100644
index 5146d4915d..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/notebook.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-#
-# tkextlib/bwidget/notebook.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/frame'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class NoteBook < TkWindow
- end
- end
-end
-
-class Tk::BWidget::NoteBook
- include TkItemConfigMethod
-
- TkCommandNames = ['NoteBook'.freeze].freeze
- WidgetClassName = 'NoteBook'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- class Event_for_Tabs < TkEvent::Event
- def self._get_extra_args_tbl
- [
- TkComm.method(:string) # page idenfier
- ]
- end
- end
-
- def __boolval_optkeys
- super() << 'homogeneous'
- end
- private :__boolval_optkeys
-
- def tagid(id)
- if id.kind_of?(TkWindow)
- #id.path
- id.epath
- elsif id.kind_of?(TkObject)
- id.to_eval
- else
- # id.to_s
- _get_eval_string(id)
- end
- end
-
- #def tabbind(*args)
- # _bind_for_event_class(Event_for_Tabs, [path, 'bindtabs'], *args)
- # self
- #end
- def tabbind(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_for_event_class(Event_for_Tabs, [path, 'bindtabs'],
- context, cmd, *args)
- self
- end
-
- #def tabbind_append(*args)
- # _bind_append_for_event_class(Event_for_Tabs, [path, 'bindtabs'], *args)
- # self
- #end
- def tabbind_append(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append_for_event_class(Event_for_Tabs, [path, 'bindtabs'],
- context, cmd, *args)
- self
- end
-
- def tabbind_remove(*args)
- _bind_remove_for_event_class(Event_for_Tabs, [path, 'bindtabs'], *args)
- self
- end
-
- def tabbindinfo(*args)
- _bindinfo_for_event_class(Event_for_Tabs, [path, 'bindtabs'], *args)
- end
-
- def add(page, &b)
- win = window(tk_send('add', tagid(page)))
- win.instance_eval(&b) if b
- win
- end
-
- def compute_size
- tk_send('compute_size')
- self
- end
-
- def delete(page, destroyframe=None)
- tk_send('delete', tagid(page), destroyframe)
- self
- end
-
- def get_frame(page, &b)
- win = window(tk_send('getframe', tagid(page)))
- win.instance_eval(&b) if b
- win
- end
-
- def index(page)
- num_or_str(tk_send('index', tagid(page)))
- end
-
- def insert(index, page, keys={}, &b)
- win = window(tk_send('insert', index, tagid(page), *hash_kv(keys)))
- win.instance_eval(&b) if b
- win
- end
-
- def move(page, index)
- tk_send('move', tagid(page), index)
- self
- end
-
- def get_page(page)
- tk_send('pages', page)
- end
-
- def pages(first=None, last=None)
- list(tk_send('pages', first, last))
- end
-
- def raise(page=nil)
- if page
- tk_send('raise', page)
- self
- else
- tk_send('raise')
- end
- end
-
- def see(page)
- tk_send('see', page)
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb b/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
deleted file mode 100644
index fc01284be6..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-#
-# tkextlib/bwidget/pagesmanager.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/frame'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class PagesManager < TkWindow
- end
- end
-end
-
-class Tk::BWidget::PagesManager
- TkCommandNames = ['PagesManager'.freeze].freeze
- WidgetClassName = 'PagesManager'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def tagid(id)
- # id.to_s
- _get_eval_string(id)
- end
-
- def add(page, &b)
- win = window(tk_send('add', tagid(page)))
- win.instance_eval(&b) if b
- win
- end
-
- def compute_size
- tk_send('compute_size')
- self
- end
-
- def delete(page)
- tk_send('delete', tagid(page))
- self
- end
-
- def get_frame(page, &b)
- win = window(tk_send('getframe', tagid(page)))
- win.instance_eval(&b) if b
- win
- end
-
- def get_page(page)
- tk_send('pages', page)
- end
-
- def pages(first=None, last=None)
- list(tk_send('pages', first, last))
- end
-
- def raise(page=None)
- tk_send('raise', page)
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/panedwindow.rb b/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
deleted file mode 100644
index 19982c6095..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# tkextlib/bwidget/panedwindow.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/frame'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class PanedWindow < TkWindow
- end
- end
-end
-
-class Tk::BWidget::PanedWindow
- TkCommandNames = ['PanedWindow'.freeze].freeze
- WidgetClassName = 'PanedWindow'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def add(keys={})
- window(tk_send('add', *hash_kv(keys)))
- end
-
- def get_frame(idx, &b)
- win = window(tk_send_without_enc('getframe', idx))
- win.instance_eval(&b) if b
- win
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/panelframe.rb b/ext/tk/lib/tkextlib/bwidget/panelframe.rb
deleted file mode 100644
index 13f8817d74..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/panelframe.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# tkextlib/bwidget/panelframe.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/frame'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class PanelFrame < TkWindow
- end
- end
-end
-
-class Tk::BWidget::PanelFrame
- TkCommandNames = ['PanelFrame'.freeze].freeze
- WidgetClassName = 'PanelFrame'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() + ['panelforeground', 'panelbackground']
- end
- private :__strval_optkeys
-
- def add(win, keys={})
- tk_send('add', win, keys)
- self
- end
-
- def delete(*wins)
- tk_send('delete', *wins)
- self
- end
-
- def get_frame(&b)
- win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
- win
- end
-
- def items
- list(tk_send('items'))
- end
-
- def remove(*wins)
- tk_send('remove', *wins)
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/passwddlg.rb b/ext/tk/lib/tkextlib/bwidget/passwddlg.rb
deleted file mode 100644
index 0b635d97bb..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/passwddlg.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# tkextlib/bwidget/passwddlg.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/messagedlg'
-
-module Tk
- module BWidget
- class PasswdDlg < Tk::BWidget::MessageDlg
- end
- end
-end
-
-class Tk::BWidget::PasswdDlg
- TkCommandNames = ['PasswdDlg'.freeze].freeze
- WidgetClassName = 'PasswdDlg'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'loginhelptext' << 'loginlabel' << 'logintext' <<
- 'passwdlabel' << 'passwdtext'
- end
- private :__strval_optkeys
-
- def __boolval_optkeys
- super() << 'passwdeditable' << 'homogeneous'
- end
- private :__boolval_optkeys
-
- def __tkvariable_optkeys
- super() << 'loginhelpvar' << 'logintextvariable' <<
- 'passwdhelpvar' << 'passwdtextvariable'
- end
- private :__tkvariable_optkeys
-
- def create
- login, passwd = simplelist(tk_call(self.class::TkCommandNames[0],
- @path, *hash_kv(@keys)))
- [login, passwd]
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/progressbar.rb b/ext/tk/lib/tkextlib/bwidget/progressbar.rb
deleted file mode 100644
index 0253ce2ada..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/progressbar.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# tkextlib/bwidget/progressbar.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class ProgressBar < TkWindow
- end
- end
-end
-
-class Tk::BWidget::ProgressBar
- TkCommandNames = ['ProgressBar'.freeze].freeze
- WidgetClassName = 'ProgressBar'.freeze
- WidgetClassNames[WidgetClassName] = self
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/progressdlg.rb b/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
deleted file mode 100644
index fbf00f3b00..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# tkextlib/bwidget/progressdlg.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/variable'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/progressbar'
-require 'tkextlib/bwidget/messagedlg'
-
-module Tk
- module BWidget
- class ProgressDlg < Tk::BWidget::MessageDlg
- end
- end
-end
-
-class Tk::BWidget::ProgressDlg
- TkCommandNames = ['ProgressDlg'.freeze].freeze
- WidgetClassName = 'ProgressDlg'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def create_self(keys)
- # NOT create widget for reusing the object
- super(keys)
- @keys['textvariable'] = TkVariable.new unless @keys.key?('textvariable')
- @keys['variable'] = TkVariable.new unless @keys.key?('variable')
- end
-
- def textvariable
- @keys['textvariable']
- end
-
- def text
- @keys['textvariable'].value
- end
-
- def text= (txt)
- @keys['textvariable'].value = txt
- end
-
- def variable
- @keys['variable']
- end
-
- def value
- @keys['variable'].value
- end
-
- def value= (val)
- @keys['variable'].value = val
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb b/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb
deleted file mode 100644
index a3986681a5..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# tkextlib/bwidget/scrollableframe.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/frame'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class ScrollableFrame < TkWindow
- end
- end
-end
-
-class Tk::BWidget::ScrollableFrame
- include Scrollable
-
- TkCommandNames = ['ScrollableFrame'.freeze].freeze
- WidgetClassName = 'ScrollableFrame'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def get_frame(&b)
- win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
- win
- end
-
- def see(win, vert=None, horiz=None)
- tk_send_without_enc('see', win, vert, horiz)
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb b/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
deleted file mode 100644
index e9e53235b7..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# tkextlib/bwidget/scrolledwindow.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/frame'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class ScrolledWindow < TkWindow
- end
- end
-end
-
-class Tk::BWidget::ScrolledWindow
- TkCommandNames = ['ScrolledWindow'.freeze].freeze
- WidgetClassName = 'ScrolledWindow'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def get_frame(&b)
- win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
- win
- end
-
- def set_widget(win)
- tk_send_without_enc('setwidget', win)
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/scrollview.rb b/ext/tk/lib/tkextlib/bwidget/scrollview.rb
deleted file mode 100644
index 0546af2c43..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/scrollview.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# tkextlib/bwidget/scrollview.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class ScrollView < TkWindow
- end
- end
-end
-
-class Tk::BWidget::ScrollView
- TkCommandNames = ['ScrollView'.freeze].freeze
- WidgetClassName = 'ScrollView'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'fill'
- end
- private :__strval_optkeys
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/selectcolor.rb b/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
deleted file mode 100644
index 742a84cd84..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# tkextlib/bwidget/selectcolor.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/messagedlg'
-
-module Tk
- module BWidget
- class SelectColor < Tk::BWidget::MessageDlg
- end
- end
-end
-
-class Tk::BWidget::SelectColor
- extend Tk
-
- TkCommandNames = ['SelectColor'.freeze].freeze
- WidgetClassName = 'SelectColor'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def dialog(keys={})
- newkeys = @keys.dup
- newkeys.update(_symbolkey2str(keys))
- tk_call('SelectColor::dialog', @path, *hash_kv(newkeys))
- end
-
- def menu(*args)
- if args[-1].kind_of?(Hash)
- keys = args.pop
- else
- keys = {}
- end
- place = args.flatten
- newkeys = @keys.dup
- newkeys.update(_symbolkey2str(keys))
- tk_call('SelectColor::menu', @path, place, *hash_kv(newkeys))
- end
-
- def self.set_color(idx, color)
- tk_call('SelectColor::setcolor', idx, color)
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/selectfont.rb b/ext/tk/lib/tkextlib/bwidget/selectfont.rb
deleted file mode 100644
index 478787602a..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/selectfont.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-#
-# tkextlib/bwidget/selectfont.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/messagedlg'
-
-module Tk
- module BWidget
- class SelectFont < Tk::BWidget::MessageDlg
- class Dialog < Tk::BWidget::SelectFont
- end
- class Toolbar < TkWindow
- end
- end
- end
-end
-
-class Tk::BWidget::SelectFont
- extend Tk
-
- TkCommandNames = ['SelectFont'.freeze].freeze
- WidgetClassName = 'SelectFont'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'sampletext' << 'title'
- end
- private :__strval_optkeys
-
- def __font_optkeys
- [] # without fontobj operation
- end
- private :__font_optkeys
-
- def create
- tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys))
- end
-
- def self.load_font
- tk_call('SelectFont::loadfont')
- end
-end
-
-class Tk::BWidget::SelectFont::Dialog
- def __font_optkeys
- [] # without fontobj operation
- end
-
- def create_self(keys)
- super(keys)
- @keys['type'] = 'dialog'
- end
-
- def configure(slot, value=None)
- if slot.kind_of?(Hash)
- slot.delete['type']
- slot.delete[:type]
- return self if slot.empty?
- else
- return self if slot == 'type' || slot == :type
- end
- super(slot, value)
- end
-
- def create
- @keys['type'] = 'dialog'
- tk_call(Tk::BWidget::SelectFont::TkCommandNames[0], @path, *hash_kv(@keys))
- end
-end
-
-class Tk::BWidget::SelectFont::Toolbar
- def __font_optkeys
- [] # without fontobj operation
- end
-
- def create_self(keys)
- keys = {} unless keys
- keys = _symbolkey2str(keys)
- keys['type'] = 'toolbar'
- tk_call(Tk::BWidget::SelectFont::TkCommandNames[0], @path, *hash_kv(keys))
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/separator.rb b/ext/tk/lib/tkextlib/bwidget/separator.rb
deleted file mode 100644
index d9c3458e51..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/separator.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# tkextlib/bwidget/separator.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class Separator < TkWindow
- end
- end
-end
-
-class Tk::BWidget::Separator
- TkCommandNames = ['Separator'.freeze].freeze
- WidgetClassName = 'Separator'.freeze
- WidgetClassNames[WidgetClassName] = self
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/setup.rb b/ext/tk/lib/tkextlib/bwidget/setup.rb
deleted file mode 100644
index ce0f0bd4d4..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/setup.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# setup.rb -- setup script before calling TkPackage.require()
-#
-# If you need some setup operations (for example, add a library path
-# to the library search path) before using Tcl/Tk library packages
-# wrapped by Ruby scripts in this directory, please write the setup
-# operations in this file.
-#
diff --git a/ext/tk/lib/tkextlib/bwidget/spinbox.rb b/ext/tk/lib/tkextlib/bwidget/spinbox.rb
deleted file mode 100644
index ca4c046e5c..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/spinbox.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-#
-# tkextlib/bwidget/entry.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-require 'tkextlib/bwidget/arrowbutton'
-require 'tkextlib/bwidget/entry'
-
-module Tk
- module BWidget
- class SpinBox < TkEntry
- end
- end
-end
-
-class Tk::BWidget::SpinBox
- include Scrollable
-
- TkCommandNames = ['SpinBox'.freeze].freeze
- WidgetClassName = 'SpinBox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'helptext' << 'insertbackground' << 'entryfg' << 'entrybg'
- end
- private :__strval_optkeys
-
- def __boolval_optkeys
- super() << 'dragenabled' << 'dropenabled' << 'editable'
- end
- private :__boolval_optkeys
-
- def __listval_optkeys
- super() << 'values'
- end
- private :__listval_optkeys
-
- def __tkvariable_optkeys
- super() << 'helpvar'
- end
- private :__tkvariable_optkeys
-
- #def entrybind(*args)
- # _bind([path, 'bind'], *args)
- # self
- #end
- def entrybind(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([path, 'bind'], context, cmd, *args)
- self
- end
-
- #def entrybind_append(*args)
- # _bind_append([path, 'bind'], *args)
- # self
- #end
- def entrybind_append(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([path, 'bind'], context, cmd, *args)
- self
- end
-
- def entrybind_remove(*args)
- _bind_remove([path, 'bind'], *args)
- self
- end
-
- def entrybindinfo(*args)
- _bindinfo([path, 'bind'], *args)
- self
- end
-
- def get_index_of_value
- number(tk_send_without_enc('getvalue'))
- end
- alias get_value get_index_of_value
- alias get_value_index get_index_of_value
-
- def set_value_by_index(idx)
- idx = "@#{idx}" if idx.kind_of?(Integer)
- tk_send_without_enc('setvalue', idx)
- self
- end
- alias set_value set_value_by_index
- alias set_index_value set_value_by_index
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/statusbar.rb b/ext/tk/lib/tkextlib/bwidget/statusbar.rb
deleted file mode 100644
index df16e4c0b7..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/statusbar.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# tkextlib/bwidget/statusbar.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/frame'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class StatusBar < TkWindow
- end
- end
-end
-
-class Tk::BWidget::StatusBar
- TkCommandNames = ['StatusBar'.freeze].freeze
- WidgetClassName = 'StatusBar'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __boolval_optkeys
- super() << 'showresize'
- end
- private :__boolval_optkeys
-
- def add(win, keys={})
- tk_send('add', win, keys)
- self
- end
-
- def delete(*wins)
- tk_send('delete', *wins)
- self
- end
-
- def get_frame(&b)
- win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
- win
- end
-
- def items
- list(tk_send('items'))
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/titleframe.rb b/ext/tk/lib/tkextlib/bwidget/titleframe.rb
deleted file mode 100644
index f519490430..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/titleframe.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# tkextlib/bwidget/titleframe.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/frame'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class TitleFrame < TkWindow
- end
- end
-end
-
-class Tk::BWidget::TitleFrame
- TkCommandNames = ['TitleFrame'.freeze].freeze
- WidgetClassName = 'TitleFrame'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def get_frame(&b)
- win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
- win
- end
-end
diff --git a/ext/tk/lib/tkextlib/bwidget/tree.rb b/ext/tk/lib/tkextlib/bwidget/tree.rb
deleted file mode 100644
index e7178debe2..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/tree.rb
+++ /dev/null
@@ -1,434 +0,0 @@
-#
-# tkextlib/bwidget/tree.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/canvas'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- class Tree < TkWindow
- class Node < TkObject
- end
- end
- end
-end
-
-class Tk::BWidget::Tree
- include TkItemConfigMethod
- include Scrollable
-
- TkCommandNames = ['Tree'.freeze].freeze
- WidgetClassName = 'Tree'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- class Event_for_Items < TkEvent::Event
- def self._get_extra_args_tbl
- [
- TkComm.method(:string) # item idenfier
- ]
- end
- end
-
- def __strval_optkeys
- super() << 'crossfill' << 'linesfill'
- end
- private :__strval_optkeys
-
- def __boolval_optkeys
- super() << 'dragenabled' << 'dropenabled' <<
- 'redraw' << 'selectfill' << 'showlines'
- end
- private :__boolval_optkeys
-
- def __tkvariable_optkeys
- super() << 'helpvar'
- end
- private :__tkvariable_optkeys
-
- def tagid(tag)
- if tag.kind_of?(Tk::BWidget::Tree::Node)
- tag.id
- else
- # tag
- _get_eval_string(tag)
- end
- end
-
- #def imagebind(*args)
- # _bind_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
- # self
- #end
- def imagebind(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_for_event_class(Event_for_Items, [path, 'bindImage'],
- context, cmd, *args)
- self
- end
-
- #def imagebind_append(*args)
- # _bind_append_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
- # self
- #end
- def imagebind_append(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append_for_event_class(Event_for_Items, [path, 'bindImage'],
- context, cmd, *args)
- self
- end
-
- def imagebind_remove(*args)
- _bind_remove_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
- self
- end
-
- def imagebindinfo(*args)
- _bindinfo_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
- end
-
- #def textbind(*args)
- # _bind_for_event_class(Event_for_Items, [path, 'bindText'], *args)
- # self
- #end
- def textbind(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_for_event_class(Event_for_Items, [path, 'bindText'],
- context, cmd, *args)
- self
- end
-
- #def textbind_append(*args)
- # _bind_append_for_event_class(Event_for_Items, [path, 'bindText'], *args)
- # self
- #end
- def textbind_append(context, *args)
- #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append_for_event_class(Event_for_Items, [path, 'bindText'],
- context, cmd, *args)
- self
- end
-
- def textbind_remove(*args)
- _bind_remove_for_event_class(Event_for_Items, [path, 'bindText'], *args)
- self
- end
-
- def textbindinfo(*args)
- _bindinfo_for_event_class(Event_for_Items, [path, 'bindText'], *args)
- end
-
- def close_tree(node, recurse=None)
- tk_send('closetree', tagid(node), recurse)
- self
- end
-
- def delete(*args)
- tk_send('delete', *(args.collect{|node| tagid(node)}))
- self
- end
-
- def edit(node, text, *args)
- tk_send('edit', tagid(node), text, *args)
- self
- end
-
- def exist?(node)
- bool(tk_send('exists', tagid(node)))
- end
-
- def index(node)
- num_or_str(tk_send('index', tagid(node)))
- end
-
- def insert(idx, parent, node, keys={})
- tk_send('insert', idx, tagid(parent), tagid(node), *hash_kv(keys))
- self
- end
-
- def move(parent, node, idx)
- tk_send('move', tagid(parent), tagid(node), idx)
- self
- end
-
- def get_node(node, idx)
- Tk::BWidget::Tree::Node.id2obj(self, tk_send('nodes', tagid(node), idx))
- end
-
- def nodes(node, first=None, last=None)
- simplelist(tk_send('nodes', tagid(node), first, last)).collect{|node|
- Tk::BWidget::Tree::Node.id2obj(self, node)
- }
- end
-
- def open?(node)
- bool(@tree.itemcget(tagid(node), 'open'))
- end
-
- def open_tree(node, recurse=None)
- tk_send('opentree', tagid(node), recurse)
- self
- end
-
- def parent(node)
- Tk::BWidget::Tree::Node.id2obj(self, tk_send('parent', tagid(node)))
- end
-
- def reorder(node, neworder)
- tk_send('reorder', tagid(node), neworder)
- self
- end
-
- def see(node)
- tk_send('see', tagid(node))
- self
- end
-
- def selection_add(*args)
- tk_send_without_enc('selection', 'add',
- *(args.collect{|node| tagid(node)}))
- self
- end
-
- def selection_clear
- tk_send_without_enc('selection', 'clear')
- self
- end
-
- def selection_get
- list(tk_send_without_enc('selection', 'get'))
- end
-
- def selection_include?(*args)
- bool(tk_send_without_enc('selection', 'get',
- *(args.collect{|node| tagid(node)})))
- end
-
- def selection_range(*args)
- tk_send_without_enc('selection', 'range',
- *(args.collect{|node| tagid(node)}))
- self
- end
-
- def selection_remove(*args)
- tk_send_without_enc('selection', 'remove',
- *(args.collect{|node| tagid(node)}))
- self
- end
-
- def selection_set(*args)
- tk_send_without_enc('selection', 'set',
- *(args.collect{|node| tagid(node)}))
- self
- end
-
- def selection_toggle(*args)
- tk_send_without_enc('selection', 'toggle',
- *(args.collect{|node| tagid(node)}))
- self
- end
-
- def toggle(node)
- tk_send_without_enc('toggle', tagid(node))
- self
- end
-
- def visible(node)
- bool(tk_send_without_enc('visible', tagid(node)))
- end
-end
-
-class Tk::BWidget::Tree::Node
- include TkTreatTagFont
-
- TreeNode_TBL = TkCore::INTERP.create_table
- TreeNode_ID = ['bw:node'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ TreeNode_TBL.clear }
-
- def self.id2obj(tree, id)
- tpath = tree.path
- return id unless TreeNode_TBL[tpath]
- TreeNode_TBL[tpath][id]? TreeNode_TBL[tpath][id]: id
- end
-
- def initialize(tree, *args)
- if tree.kind_of?(Tk::BWidget::Tree)
- @tree = tree
- parent = args.shift
- if parent.kind_of?(Tk::BWidget::Tree::Node)
- if parent.tree.path != @tree.path
- fail RuntimeError, 'tree of parent node is not match'
- end
- end
- elsif tree.kind_of?(Tk::BWidget::Tree::Node)
- @tree = tree.tree
- parent = tree.parent
- else
- fail RuntimeError,
- "expect Tk::BWidget::Tree or Tk::BWidget::Tree::Node for 1st argument"
- end
-
- if args[-1].kind_of?(Hash)
- keys = _symbolkey2str(args.pop)
- else
- keys = {}
- end
-
- index = keys.delete('index')
- unless args.empty?
- index = args.shift
- end
- index = 'end' unless index
-
- unless args.empty?
- fail RuntimeError, 'too much arguments'
- end
-
- @tpath = @tree.path
-
- if keys.key?('nodename')
- @path = @id = keys.delete('nodename')
- else
- @path = @id = TreeNode_ID.join(TkCore::INTERP._ip_id_)
- TreeNode_ID[1].succ!
- end
-
- TreeNode_TBL[@id] = self
- TreeNode_TBL[@tpath] = {} unless TreeNode_TBL[@tpath]
- TreeNode_TBL[@tpath][@id] = self
-
- @tree.insert(index, parent, @id, keys)
- end
-
- def tree
- @tree
- end
-
- def id
- @id
- end
-
- def [](key)
- cget(key)
- end
-
- def []=(key, val)
- configure(key, val)
- val
- end
-
- def cget(key)
- @tree.itemcget(@id, key)
- end
-
- def configure(key, val=None)
- @tree.itemconfigure(@id, key, val)
- end
-
- def configinfo(key=nil)
- @tree.itemconfiginfo(@id, key)
- end
-
- def current_configinfo(key=nil)
- @tree.current_itemconfiginfo(@id, key)
- end
-
- def close_tree(recurse=None)
- @tree.close_tree(@id, recurse)
- self
- end
-
- def delete
- @tree.delete(@id)
- self
- end
-
- def edit(*args)
- @tree.edit(@id, *args)
- self
- end
-
- def exist?
- @tree.exist?(@id)
- end
-
- def index
- @tree.index(@id)
- end
-
- def move(index, parent=nil)
- if parent
- @tree.move(parent, @id, index)
- else
- @tree.move(self.parent, @id, index)
- end
- end
-
- def open_tree(recurse=None)
- @tree.open_tree(@id, recurse)
- self
- end
-
- def open?
- bool(@tree.itemcget(@id, 'open'))
- end
-
- def parent
- @tree.parent(@id)
- end
-
- def reorder(neworder)
- @tree.reorder(@id, neworder)
- end
-
- def see
- @tree.see(@id)
- end
-
- def selection_add
- @tree.selection_add(@id)
- end
-
- def selection_remove
- @tree.selection_remove(@id)
- end
-
- def selection_set
- @tree.selection_set(@id)
- end
-
- def selection_toggle
- @tree.selection_toggle(@id)
- end
-
- def toggle
- @tree.toggle(@id)
- end
-
- def visible
- @tree.visible(@id)
- end
-end
-
diff --git a/ext/tk/lib/tkextlib/bwidget/widget.rb b/ext/tk/lib/tkextlib/bwidget/widget.rb
deleted file mode 100644
index 568e503a8b..0000000000
--- a/ext/tk/lib/tkextlib/bwidget/widget.rb
+++ /dev/null
@@ -1,113 +0,0 @@
-#
-# tkextlib/bwidget/widget.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/bwidget.rb'
-
-module Tk
- module BWidget
- module Widget
- end
- end
-end
-
-module Tk::BWidget::Widget
- include Tk
- extend Tk
-
- def self.__pathname
- 'Widget::configure'
- end
-
- def self.__cget_cmd
- ['Widget::cget']
- end
-
- def self.__config_cmd
- ['Widget::configure']
- end
-
- def self.cget(slot)
- self.current_configinfo(slot).values[0]
- end
-
- def self.add_map(klass, subclass, subpath, opts)
- tk_call('Widget::addmap', klass, subclass, subpath, opts)
- end
-
- def self.bwinclude(klass, subclass, subpath, *args)
- tk_call('Widget::bwinclude', klass, subclass, subpath, *args)
- end
-
- def self.create(klass, path, rename=None, &b)
- win = window(tk_call('Widget::create', klass, path, rename))
- win.instance_eval(&b) if b
- win
- end
-
- def self.declare(klass, optlist)
- tk_call('Widget::declare', klass, optlist)
- end
-
- def self.define(klass, filename, *args)
- tk_call('Widget::define', klass, filename, *args)
- end
-
- def self.destroy(win)
- tk_call('Widget::destroy', _epath(win))
- end
-
- def self.focus_next(win)
- tk_call('Widget::focusNext', win)
- end
-
- def self.focus_ok(win)
- tk_call('Widget::focusOk', win)
- end
-
- def self.focus_prev(win)
- tk_call('Widget::focusPrev', win)
- end
-
- def self.generate_doc(dir, widgetlist)
- tk_call('Widget::generate-doc', dir, widgetlist)
- end
-
- def self.generate_widget_doc(klass, iscmd, file)
- tk_call('Widget::generate-widget-doc', klass, iscmd, file)
- end
-
- def self.get_option(win, option)
- tk_call('Widget::getoption', win, option)
- end
-
- def self.get_variable(win, varname, my_varname=None)
- tk_call('Widget::getVariable', win, varname, my_varname)
- end
-
- def self.has_changed(win, option, pvalue)
- tk_call('Widget::hasChanged', win, option, pvalue)
- end
-
- def self.init(klass, win, options)
- tk_call('Widget::init', klass, win, options)
- end
-
- def self.set_option(win, option, value)
- tk_call('Widget::setoption', win, option, value)
- end
-
- def self.sub_cget(win, subwidget)
- tk_call('Widget::subcget', win, subwidget)
- end
-
- def self.sync_options(klass, subclass, subpath, options)
- tk_call('Widget::syncoptions', klass, subclass, subpath, options)
- end
-
- def self.tkinclude(klass, tkwidget, subpath, *args)
- tk_call('Widget::tkinclude', klass, tkwidget, subpath, *args)
- end
-end
diff --git a/ext/tk/lib/tkextlib/itcl.rb b/ext/tk/lib/tkextlib/itcl.rb
deleted file mode 100644
index 1d6ecf04f2..0000000000
--- a/ext/tk/lib/tkextlib/itcl.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# [incr Tcl] support
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-# call setup script for general 'tkextlib' libraries
-require 'tkextlib/setup.rb'
-
-# call setup script
-require 'tkextlib/itcl/setup.rb'
-
-# load library
-require 'tkextlib/itcl/incr_tcl.rb'
diff --git a/ext/tk/lib/tkextlib/itcl/incr_tcl.rb b/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
deleted file mode 100644
index 07abf3a7bf..0000000000
--- a/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
+++ /dev/null
@@ -1,172 +0,0 @@
-#
-# tkextlib/itk/incr_tcl.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-
-# call setup script
-require 'tkextlib/itcl.rb'
-
-# TkPackage.require('Itcl', '3.2')
-TkPackage.require('Itcl')
-
-module Tk
- module Itcl
- include Tk
- extend Tk
-
- LIBRARY = TkVarAccess.new('::itcl::library')
- PURIST = TkVarAccess.new('::itcl::purist')
-
- VERSION = TkCore::INTERP._invoke("set", "::itcl::version").freeze
- PATCHLEVEL = TkCore::INTERP._invoke("set", "::itcl::patchLevel").freeze
-
- PACKAGE_NAME = 'Itcl'.freeze
- def self.package_name
- PACKAGE_NAME
- end
-
- def self.package_version
- begin
- TkPackage.require('Itcl')
- rescue
- ''
- end
- end
-
- ##############################################
-
- class ItclObject < TkObject
- ITCL_CLASSNAME = ''.freeze
-
- ITCL_OBJ_ID = ['itclobj'.freeze, '00000'.taint].freeze
- ITCL_OBJ_TBL = {}.taint
-
- def initialize(*args)
- if (@klass = self.class::ITCL_CLASSNAME).empty?
- fail RuntimeError, 'unknown itcl class (abstract class?)'
- end
- @id = Tk::Itcl::ItclObject::TCL_OBJ_ID.join(TkCore::INTERP._ip_id_)
- @path = @id
- Tk::Itcl::ItclObject::ITCL_OBJ_ID[1].succ!
- end
-
- def self.call_proc(name, *args)
- tk_call("#{ITCL_CLASSNAME}::#{cmd}", *args)
- end
-
- def call_method(name, *args)
- tk_call(@path, name, *args)
- end
-
- def isa(klass)
- bool(tk_call(@path, 'isa', klass))
- end
- alias itcl_kind_of? isa
-
- def info_class
- tk_call(@path, 'info', 'class')
- end
-
- def info_inherit
- simplelist(tk_call(@path, 'info', 'inherit'))
- end
-
- def info_heritage
- list(tk_call(@path, 'info', 'heritage'))
- end
-
- def info_function(*args)
- if args[-1].kind_of?(Array)
- params = args.pop
- params.each{|param|
- param = param.to_s
- args << ( (param[0] == ?-)? param: "-#{param}" )
- }
- end
- list(tk_call(@path, 'info', 'function', *args))
- end
-
- def info_variable(*args)
- if args[-1].kind_of?(Array)
- params = args.pop
- params.each{|param|
- param = param.to_s
- args << ( (param[0] == ?-)? param: "-#{param}" )
- }
- end
- list(tk_call(@path, 'info', 'variable', *args))
- end
- end
-
- ##############################################
-
- def self.body(klass, func, args, body)
- tk_call('::itcl::body', "#{klass}::#{func}", args, body)
- end
-
- def self.code(cmd, *args)
- tk_call('::itcl::code', cmd, *args)
- end
-
- def self.code_in_namespace(namespace, cmd, *args)
- tk_call('::itcl::code', '-namespace', namespace, cmd, *args)
- end
-
- def self.configbody(klass, var, body)
- tk_call('::itcl::configbody', "#{klass}::#{var}", body)
- end
-
- def self.create_itcl_class(name, body)
- TkCore::INTERP._invoke('::itcl::class', name, body)
- klass = Class.new(Tk::Itcl::ItclObject)
- klass.const_set('ITCL_CLASSNAME', name.dup.freeze)
- klass
- end
-
- def self.delete_itcl_class(*names)
- tk_call('::itcl::delete', 'class', *names)
- end
-
- def self.delete_itcl_object(*names)
- tk_call('::itcl::delete', 'object', *names)
- end
-
- def self.delete_namespace(*names)
- tk_call('::itcl::delete', 'namespace', *names)
- end
-
- def self.ensemble(name, *args)
- tk_call('::itcl::ensemble', name, *args)
- end
-
- def self.find_classes(pat=None)
- simplelist(tk_call('::itcl::find', 'classes', pat))
- end
-
- def self.find_objects(*args)
- simplelist(tk_call('::itcl::find', 'objects', *args))
- end
-
- def self.is_itcl_class(target)
- bool(tk_call('::itcl::is', 'class', target))
- end
-
- def self.is_itcl_object(target)
- bool(tk_call('::itcl::is', 'object', target))
- end
-
- def self.create_local_obj(klass, name, *args)
- tk_call('::itcl::local', klass, name, *args)
- end
-
- def self.is_itcl_instance(klass, target)
- bool(tk_call('::itcl::is', 'object', '-class', klass, target))
- end
-
- def self.scope(var)
- tk_call('::itcl::scope', var)
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/itcl/setup.rb b/ext/tk/lib/tkextlib/itcl/setup.rb
deleted file mode 100644
index 5be0588703..0000000000
--- a/ext/tk/lib/tkextlib/itcl/setup.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# setup.rb -- setup script before calling TkPackage.require()
-#
-# If you need some setup operations (for example, add a library path
-# to the library search path) before using Tcl/Tk library packages
-# wrapped by Ruby scripts in this directory, please write the setup
-# operations in this file.
-#
-
-
-# set [incr Tcl] library directory
-
-# ENV['ITCL_LIBRARY'] = '/usr/local/ActiveTcl/lib/itcl3.2/'
diff --git a/ext/tk/lib/tkextlib/itk.rb b/ext/tk/lib/tkextlib/itk.rb
deleted file mode 100644
index 7492bd3eb4..0000000000
--- a/ext/tk/lib/tkextlib/itk.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# [incr Tk] support
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-# call setup script for general 'tkextlib' libraries
-require 'tkextlib/setup.rb'
-
-# call setup script
-require 'tkextlib/itk/setup.rb'
-
-# load library
-require 'tkextlib/itk/incr_tk.rb'
diff --git a/ext/tk/lib/tkextlib/itk/incr_tk.rb b/ext/tk/lib/tkextlib/itk/incr_tk.rb
deleted file mode 100644
index 0626536e36..0000000000
--- a/ext/tk/lib/tkextlib/itk/incr_tk.rb
+++ /dev/null
@@ -1,428 +0,0 @@
-#
-# tkextlib/itk/incr_tk.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/menuspec'
-require 'tkextlib/itcl.rb'
-
-# call setup script
-require 'tkextlib/itk.rb'
-
-#TkPackage.require('Itk', '3.2')
-TkPackage.require('Itk')
-
-module Tk
- module Itk
- include Tk
- extend Tk
-
- LIBRARY = TkVarAccess.new('::itk::library')
-
- PACKAGE_NAME = 'Itk'.freeze
- def self.package_name
- PACKAGE_NAME
- end
-
- def self.package_version
- begin
- TkPackage.require('Itk')
- rescue
- ''
- end
- end
-
- def self.usual(arg, *args)
- tk_call('::itk::usual', arg, *args)
- end
-
- def self.usual_names
- list(tk_call('::itk::usual'))
- end
-
- ############################
-
- class Archetype < TkWindow
- TkCommandNames = [].freeze
- # WidgetClassName = 'Archetype'.freeze
- # WidgetClassNames[WidgetClassName] = self
-
- def self.to_eval
- '::itk::' << self::WidgetClassName
- end
-
- def __destroy_hook__
- Tk::Itk::Component::ComponentID_TBL.delete(self.path)
- end
-
- #### [incr Tk] public methods
- def component
- simplelist(tk_send('component'))
- end
-
- def component_path(name)
- window(tk_send('component', name))
- end
- alias component_widget component_path
-
- def component_invoke(name, cmd, *args)
- window(tk_send('component', name, cmd, *args))
- end
-
- def component_obj(*names)
- names = component if names.empty?
- names.collect{|name| Tk::Itk::Component.new(self.path, name) }
- end
-
- #### [incr Tk] protected methods
-=begin
- def itk_component_add(visibility, name, create_cmds, option_cmds=None)
- args = []
- visibility.each{|v| v = v.to_s; args << ( (v[0] == ?-)? v: "-#{v}" )}
- args << '--' << name << create_cmd << option_cmds
- tk_call('itk_component', 'add', *args)
- end
-
- def itk_component_delete(*names)
- tk_call('itk_component', 'delete', *names)
- end
-
- def itk_initialize(keys={})
- tk_call('itk_initialize', keys)
- end
-
- def itk_option_add(*args)
- tk_call('itk_option', 'add', *args)
- end
-
- def itk_option_define(name, resource, klass, init, config=None)
- tk_call('itk_option', 'define', name, resource, klass, init, config)
- end
-
- def itk_option_remove(*args)
- tk_call('itk_option', 'remove', *args)
- end
-=end
- end
-
- ############################
-
- class Toplevel < Archetype
- TkCommandNames = ['::itk::Toplevel'].freeze
- WidgetClassName = 'Toplevel'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- include Wm
- include TkMenuSpec
-
- def __strval_optkeys
- super() << 'title'
- end
- private :__strval_optkeys
- end
-
- ############################
-
- class Widget < Archetype
- TkCommandNames = ['::itk::Widget'].freeze
- WidgetClassName = 'Widget'.freeze
- WidgetClassNames[WidgetClassName] = self
- end
-
-
- ############################
-
- class Component < TkObject
- def __cget_cmd
- [self.master, 'component', self.name, 'cget']
- end
- private :__cget_cmd
-
- def __config_cmd
- [self.master, 'component', self.name, 'configure']
- end
- private :__config_cmd
-
- ComponentID_TBL = TkCore::INTERP.create_table
- Itk_Component_ID = ['itk:component'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ ComponentID_TBL.clear }
-
- def self.id2obj(master, id)
- if master.kind_of?(TkObject)
- master = master.path
- else
- master = master.to_s
- end
- return id unless ComponentID_TBL.key?(master)
- (ComponentID_TBL.key?(id))? ComponentID_TBL[master][id]: id
- end
-
- def self.new(master, component=nil)
- if master.kind_of?(TkObject)
- master = master.path
- else
- master = master.to_s
- end
-
- if component.kind_of?(Tk::Itk::Component)
- component = component.name
- elsif component
- component = component.to_s
- else
- component = Itk_Component_ID.join(TkCore::INTERP._ip_id_)
- Itk_Component_ID[1].succ!
- end
-
- if ComponentID_TBL.key?(master)
- if ComponentID_TBL[master].key?(component)
- return ComponentID_TBL[master][component]
- end
- else
- ComponentID_TBL[master] = {}
- end
-
- super(master, component)
- end
-
- def initialize(master, component)
- @master = master
- @component = component
-
- ComponentID_TBL[@master][@component] = self
-
- begin
- @widget = window(tk_call(@master, 'component', @component))
- @path = @widget.path
- rescue
- @widget = nil
- @path = nil
- end
- end
-
- def path
- unless @path
- begin
- @widget = window(tk_call(@master, 'component', @component))
- @path = @widget.path
- rescue
- fail RuntimeError, 'component is not assigned to a widget'
- end
- end
- @path
- end
-
- def epath
- path()
- end
-
- def to_eval
- path()
- end
-
- def master
- @master
- end
-
- def name
- @component
- end
-
- def widget
- unless @widget
- begin
- @widget = window(tk_call(@master, 'component', @component))
- @path = @widget.path
- rescue
- fail RuntimeError, 'component is not assigned to a widget'
- end
- end
- @widget
- end
-
- def widget_class
- unless @widget
- begin
- @widget = window(tk_call(@master, 'component', @component))
- @path = @widget.path
- @widget.classname
- rescue
- nil
- end
- end
- end
-
- def method_missing(id, *args)
- name = id.id2name
-
- # try 1 : component command
- begin
- return tk_call(@master, 'component', @component, name, *args)
- rescue
- end
-
- # try 2 : component configure
- len = args.length
- begin
- case len
- when 1
- if name[-1] == ?=
- return configure(name[0..-2], args[0])
- else
- return configure(name, args[0])
- end
- when 0
- return cget(name)
- end
- rescue
- end
-
- # try 3 : widget method or widget configure
- begin
- unless @widget
- @widget = window(tk_call(@master, 'component', @component))
- @path = @widget.path
- end
- @widget.__send__(id, *args)
- rescue
- end
-
- # unknown method
- super(id, *args)
- # fail RuntimeError, "unknown method '#{name}' for #{self.inspect}"
- end
-
- def tk_send(cmd, *rest)
- begin
- tk_call(@master, 'component', @component, cmd, *rest)
- rescue
- unless @path
- begin
- @widget = window(tk_call(@master, 'component', @component))
- @path = @widget.path
- rescue
- fail RuntimeError, 'component is not assigned to a widget'
- end
- end
- tk_call(@path, cmd, *rest)
- end
- end
-
- def tk_send_without_enc(cmd, *rest)
- begin
- tk_call_without_enc(@master, 'component', @component, cmd, *rest)
- rescue
- unless @path
- begin
- @widget = window(tk_call(@master, 'component', @component))
- @path = @widget.path
- rescue
- fail RuntimeError, 'component is not assigned to a widget'
- end
- end
- tk_call_without_enc(@path, cmd, *rest)
- end
- end
-
- def tk_send_with_enc(cmd, *rest)
- begin
- tk_call_with_enc(@master, 'component', @component, cmd, *rest)
- rescue
- unless @path
- begin
- @widget = window(tk_call(@master, 'component', @component))
- @path = @widget.path
- rescue
- fail RuntimeError, 'component is not assigned to a widget'
- end
- end
- tk_call_with_enc(@path, cmd, *rest)
- end
- end
-
- #def bind(*args)
- # unless @widget
- # begin
- # @widget = window(tk_call(@master, 'component', @component))
- # @path = @widget.path
- # rescue
- # fail RuntimeError, 'component is not assigned to a widget'
- # end
- # end
- # @widget.bind(*args)
- #end
- def bind(context, *args)
- unless @widget
- begin
- @widget = window(tk_call(@master, 'component', @component))
- @path = @widget.path
- rescue
- fail RuntimeError, 'component is not assigned to a widget'
- end
- end
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- @widget.bind(context, cmd, *args)
- end
-
- #def bind_append(*args)
- # unless @widget
- # begin
- # @widget = window(tk_call(@master, 'component', @component))
- # @path = @widget.path
- # rescue
- # fail RuntimeError, 'component is not assigned to a widget'
- # end
- # end
- # @widget.bind_append(*args)
- #end
- def bind_append(context, *args)
- unless @widget
- begin
- @widget = window(tk_call(@master, 'component', @component))
- @path = @widget.path
- rescue
- fail RuntimeError, 'component is not assigned to a widget'
- end
- end
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- @widget.bind_append(context, cmd, *args)
- end
-
- def bind_remove(*args)
- unless @widget
- begin
- @widget = window(tk_call(@master, 'component', @component))
- @path = @widget.path
- rescue
- fail RuntimeError, 'component is not assigned to a widget'
- end
- end
- @widget.bind_remove(*args)
- end
-
- def bindinfo(*args)
- unless @widget
- begin
- @widget = window(tk_call(@master, 'component', @component))
- @path = @widget.path
- rescue
- fail RuntimeError, 'component is not assigned to a widget'
- end
- end
- @widget.bindinfo(*args)
- end
-
- end
- end
-end
diff --git a/ext/tk/lib/tkextlib/itk/setup.rb b/ext/tk/lib/tkextlib/itk/setup.rb
deleted file mode 100644
index e47b64adae..0000000000
--- a/ext/tk/lib/tkextlib/itk/setup.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# setup.rb -- setup script before calling TkPackage.require()
-#
-# If you need some setup operations (for example, add a library path
-# to the library search path) before using Tcl/Tk library packages
-# wrapped by Ruby scripts in this directory, please write the setup
-# operations in this file.
-#
-
-
-# set [incr Tk] library directory
-
-# ENV['ITK_LIBRARY'] = '/usr/local/ActiveTcl/lib/itk3.2/'
diff --git a/ext/tk/lib/tkextlib/iwidgets.rb b/ext/tk/lib/tkextlib/iwidgets.rb
deleted file mode 100644
index ebd4cf7507..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-#
-# [incr Widgets] support
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/itcl'
-require 'tkextlib/itk'
-
-# call setup script for general 'tkextlib' libraries
-#require 'tkextlib/setup.rb'
-
-# call setup script
-#require 'tkextlib/iwidgets/setup.rb'
-
-# load all image format handlers
-#TkPackage.require('Iwidgets', '4.0')
-TkPackage.require('Iwidgets')
-
-module Tk
- module Iwidgets
- TkComm::TkExtlibAutoloadModule.unshift(self)
-
- extend TkCore
-
- PACKAGE_NAME = 'Iwidgets'.freeze
- def self.package_name
- PACKAGE_NAME
- end
-
- def self.package_version
- begin
- TkPackage.require('Iwidgets')
- rescue
- ''
- end
- end
-
- ####################################################
-
- autoload :Buttonbox, 'tkextlib/iwidgets/buttonbox'
- autoload :Calendar, 'tkextlib/iwidgets/calendar'
- autoload :Canvasprintbox, 'tkextlib/iwidgets/canvasprintbox'
- autoload :Canvasprintdialog, 'tkextlib/iwidgets/canvasprintdialog'
- autoload :Checkbox, 'tkextlib/iwidgets/checkbox'
- autoload :Combobox, 'tkextlib/iwidgets/combobox'
- autoload :Dateentry, 'tkextlib/iwidgets/dateentry'
- autoload :Datefield, 'tkextlib/iwidgets/datefield'
- autoload :Dialog, 'tkextlib/iwidgets/dialog'
- autoload :Dialogshell, 'tkextlib/iwidgets/dialogshell'
- autoload :Disjointlistbox, 'tkextlib/iwidgets/disjointlistbox'
- autoload :Entryfield, 'tkextlib/iwidgets/entryfield'
- autoload :Extbutton, 'tkextlib/iwidgets/extbutton'
- autoload :Extfileselectionbox, 'tkextlib/iwidgets/extfileselectionbox'
- autoload :Extfileselectiondialog,'tkextlib/iwidgets/extfileselectiondialog'
- autoload :Feedback, 'tkextlib/iwidgets/feedback'
- autoload :Fileselectionbox, 'tkextlib/iwidgets/fileselectionbox'
- autoload :Fileselectiondialog, 'tkextlib/iwidgets/fileselectiondialog'
- autoload :Finddialog, 'tkextlib/iwidgets/finddialog'
- autoload :Hierarchy, 'tkextlib/iwidgets/hierarchy'
- autoload :Hyperhelp, 'tkextlib/iwidgets/hyperhelp'
- autoload :Labeledframe, 'tkextlib/iwidgets/labeledframe'
- autoload :Labeledwidget, 'tkextlib/iwidgets/labeledwidget'
- autoload :Mainwindow, 'tkextlib/iwidgets/mainwindow'
- autoload :Menubar, 'tkextlib/iwidgets/menubar'
- autoload :Messagebox, 'tkextlib/iwidgets/messagebox'
- autoload :Messagedialog, 'tkextlib/iwidgets/messagedialog'
- autoload :Notebook, 'tkextlib/iwidgets/notebook'
- autoload :Optionmenu, 'tkextlib/iwidgets/optionmenu'
- autoload :Panedwindow, 'tkextlib/iwidgets/panedwindow'
- autoload :Pushbutton, 'tkextlib/iwidgets/pushbutton'
- autoload :Promptdialog, 'tkextlib/iwidgets/promptdialog'
- autoload :Radiobox, 'tkextlib/iwidgets/radiobox'
- autoload :Scrolledcanvas, 'tkextlib/iwidgets/scrolledcanvas'
- autoload :Scrolledframe, 'tkextlib/iwidgets/scrolledframe'
- autoload :Scrolledhtml, 'tkextlib/iwidgets/scrolledhtml'
- autoload :Scrolledlistbox, 'tkextlib/iwidgets/scrolledlistbox'
- autoload :Scrolledtext, 'tkextlib/iwidgets/scrolledtext'
- autoload :Scrolledwidget, 'tkextlib/iwidgets/scrolledwidget'
- autoload :Selectionbox, 'tkextlib/iwidgets/selectionbox'
- autoload :Selectiondialog, 'tkextlib/iwidgets/selectiondialog'
- autoload :Shell, 'tkextlib/iwidgets/shell'
- autoload :Spindate, 'tkextlib/iwidgets/spindate'
- autoload :Spinint, 'tkextlib/iwidgets/spinint'
- autoload :Spinner, 'tkextlib/iwidgets/spinner'
- autoload :Spintime, 'tkextlib/iwidgets/spintime'
- autoload :Tabnotebook, 'tkextlib/iwidgets/tabnotebook'
- autoload :Tabset, 'tkextlib/iwidgets/tabset'
- autoload :Timeentry, 'tkextlib/iwidgets/timeentry'
- autoload :Timefield, 'tkextlib/iwidgets/timefield'
- autoload :Toolbar, 'tkextlib/iwidgets/toolbar'
- autoload :Watch, 'tkextlib/iwidgets/watch'
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb b/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb
deleted file mode 100644
index a055e07ac9..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb
+++ /dev/null
@@ -1,119 +0,0 @@
-#
-# tkextlib/iwidgets/buttonbox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Buttonbox < Tk::Itk::Widget
- end
- end
-end
-
-class Tk::Iwidgets::Buttonbox
- TkCommandNames = ['::iwidgets::buttonbox'.freeze].freeze
- WidgetClassName = 'Buttonbox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- ####################################
-
- include TkItemConfigMethod
-
- def __item_cget_cmd(id)
- [self.path, 'buttoncget', id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- [self.path, 'buttonconfigure', id]
- end
- private :__item_config_cmd
-
- def __item_boolval_optkeys(id)
- super(id) << 'defaultring'
- end
- private :__item_boolval_optkeys
-
- def tagid(tagOrId)
- if tagOrId.kind_of?(Tk::Itk::Component)
- tagOrId.name
- else
- #_get_eval_string(tagOrId)
- tagOrId
- end
- end
-
- alias buttoncget itemcget
- alias buttonconfigure itemconfigure
- alias buttonconfiginfo itemconfiginfo
- alias current_buttonconfiginfo current_itemconfiginfo
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-
- ####################################
-
- def add(tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- if tag
- tag = Tk::Itk::Component.new(self, tagid(tag))
- else
- tag = Tk::Itk::Component.new(self)
- end
- tk_call(@path, 'add', tagid(tag), *hash_kv(keys))
- tag
- end
-
- def default(idx)
- tk_call(@path, 'default', index(idx))
- self
- end
-
- def delete(idx)
- tk_call(@path, 'delete', index(idx))
- self
- end
-
- def hide(idx)
- tk_call(@path, 'hide', index(idx))
- self
- end
-
- def index(idx)
- number(tk_call(@path, 'index', tagid(idx)))
- end
-
- def insert(idx, tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- if tag
- tag = Tk::Itk::Component.new(self, tagid(tag))
- else
- tag = Tk::Itk::Component.new(self)
- end
- tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys))
- tag
- end
-
- def invoke(idx=nil)
- if idx
- tk_call(@path, 'invoke', index(idx))
- else
- tk_call(@path, 'invoke')
- end
- self
- end
-
- def show(idx)
- tk_call(@path, 'show', index(idx))
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/calendar.rb b/ext/tk/lib/tkextlib/iwidgets/calendar.rb
deleted file mode 100644
index 0152f8593a..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/calendar.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-#
-# tkextlib/iwidgets/calendar.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Calendar < Tk::Itk::Widget
- end
- end
-end
-
-class Tk::Iwidgets::Calendar
- TkCommandNames = ['::iwidgets::calendar'.freeze].freeze
- WidgetClassName = 'Calendar'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() + [
- 'buttonforeground', 'outline', 'selectcolor',
- 'weekdaybackground', 'weekendbackground'
- ]
- end
- private :__strval_optkeys
-
- def __listval_optkeys
- super() << 'days'
- end
- private :__listval_optkeys
-
- def __font_optkeys
- super() + ['currentdatefont', 'datefont', 'dayfont', 'titlefont']
- end
- private :__font_optkeys
-
- ####################################
-
- include Tk::ValidateConfigure
-
- class CalendarCommand < TkValidateCommand
- #class CalCmdArgs < TkUtil::CallbackSubst
- class ValidateArgs < TkUtil::CallbackSubst
- KEY_TBL = [ [?d, ?s, :date], nil ]
- PROC_TBL = [ [?s, TkComm.method(:string) ], nil ]
- _setup_subst_table(KEY_TBL, PROC_TBL);
-
- def self.ret_val(val)
- val
- end
- end
-
- def self._config_keys
- # array of config-option key (string or symbol)
- ['command']
- end
-
- #def initialize(cmd = Proc.new, *args)
- # _initialize_for_cb_class(CalCmdArgs, cmd, *args)
- #end
- end
-
- def __validation_class_list
- super() << CalendarCommand
- end
-
- Tk::ValidateConfigure.__def_validcmd(binding, CalendarCommand)
-=begin
- def command(cmd = Proc.new, args = nil)
- if cmd.kind_of?(CalendarCommand)
- configure('command', cmd)
- elsif args
- configure('command', [cmd, args])
- else
- configure('command', cmd)
- end
- end
-=end
-
- ####################################
-
- def get_string
- tk_call(@path, 'get', '-string')
- end
- alias get get_string
-
- def get_clicks
- number(tk_call(@path, 'get', '-clicks'))
- end
-
- def select(date)
- tk_call(@path, 'select', date)
- self
- end
-
- def show(date)
- tk_call(@path, 'show', date)
- self
- end
- def show_now
- tk_call(@path, 'show', 'now')
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb b/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb
deleted file mode 100644
index fa5e90ad05..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# tkextlib/iwidgets/canvasprintbox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Canvasprintbox < Tk::Itk::Widget
- end
- end
-end
-
-class Tk::Iwidgets::Canvasprintbox
- TkCommandNames = ['::iwidgets::canvasprintbox'.freeze].freeze
- WidgetClassName = 'Canvasprintbox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'filename'
- end
- private :__strval_optkeys
-
- def __boolval_optkeys
- super() << 'stretch'
- end
- private :__boolval_optkeys
-
- def get_output
- tk_call(@path, 'getoutput')
- end
-
- def print
- bool(tk_call(@path, 'print'))
- end
-
- def refresh
- tk_call(@path, 'refresh')
- self
- end
-
- def set_canvas(win)
- tk_call(@path, 'setcanvas', win)
- self
- end
-
- def stop
- tk_call(@path, 'stop')
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb b/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb
deleted file mode 100644
index bbf507677c..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# tkextlib/iwidgets/canvasprintdialog.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Canvasprintdialog < Tk::Iwidgets::Dialog
- end
- end
-end
-
-class Tk::Iwidgets::Canvasprintdialog
- TkCommandNames = ['::iwidgets::canvasprintdialog'.freeze].freeze
- WidgetClassName = 'Canvasprintdialog'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def get_output
- tk_call(@path, 'getoutput')
- end
-
- def print
- bool(tk_call(@path, 'print'))
- end
-
- def refresh
- tk_call(@path, 'refresh')
- self
- end
-
- def set_canvas(win)
- tk_call(@path, 'setcanvas', win)
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/checkbox.rb b/ext/tk/lib/tkextlib/iwidgets/checkbox.rb
deleted file mode 100644
index abd23299a8..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/checkbox.rb
+++ /dev/null
@@ -1,116 +0,0 @@
-#
-# tkextlib/iwidgets/checkbox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Checkbox < Tk::Iwidgets::Labeledframe
- end
- end
-end
-
-class Tk::Iwidgets::Checkbox
- TkCommandNames = ['::iwidgets::checkbox'.freeze].freeze
- WidgetClassName = 'Checkbox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- ####################################
-
- include TkItemConfigMethod
-
- def __item_cget_cmd(id)
- [self.path, 'buttoncget', id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- [self.path, 'buttonconfigure', id]
- end
- private :__item_config_cmd
-
- def __item_boolval_optkeys(id)
- super(id) << 'defaultring'
- end
- private :__item_boolval_optkeys
-
- def tagid(tagOrId)
- if tagOrId.kind_of?(Tk::Itk::Component)
- tagOrId.name
- else
- #_get_eval_string(tagOrId)
- tagOrId
- end
- end
-
- alias buttoncget itemcget
- alias buttonconfigure itemconfigure
- alias buttonconfiginfo itemconfiginfo
- alias current_buttonconfiginfo current_itemconfiginfo
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-
- ####################################
-
- def add(tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- if tag
- tag = Tk::Itk::Component.new(self, tagid(tag))
- else
- tag = Tk::Itk::Component.new(self)
- end
- tk_call(@path, 'add', tagid(tag), *hash_kv(keys))
- tag
- end
-
- def delete(idx)
- tk_call(@path, 'delete', index(idx))
- self
- end
-
- def deselect(idx)
- tk_call(@path, 'deselect', index(idx))
- self
- end
-
- def flash(idx)
- tk_call(@path, 'flash', index(idx))
- self
- end
-
- def get(idx)
- simplelist(tk_call(@path, 'get', index(idx))).collect{|id|
- Tk::Itk::Component.id2obj(id)
- }
- end
-
- def index(idx)
- number(tk_call(@path, 'index', tagid(idx)))
- end
-
- def insert(idx, tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- if tag
- tag = Tk::Itk::Component.new(self, tagid(tag))
- else
- tag = Tk::Itk::Component.new(self)
- end
- tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys))
- tag
- end
-
- def select(idx)
- tk_call(@path, 'select', index(idx))
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/combobox.rb b/ext/tk/lib/tkextlib/iwidgets/combobox.rb
deleted file mode 100644
index a6d54d78fa..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/combobox.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-#
-# tkextlib/iwidgets/combobox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Combobox < Tk::Iwidgets::Entryfield
- end
- end
-end
-
-class Tk::Iwidgets::Combobox
- TkCommandNames = ['::iwidgets::combobox'.freeze].freeze
- WidgetClassName = 'Combobox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __boolval_optkeys
- super() << 'completion' << 'dropdown' << 'editable' << 'unique'
- end
- private :__boolval_optkeys
-
- def clear(component=None)
- tk_call(@path, 'clear', component)
- self
- end
-
- def delete_list(first, last=None)
- tk_call(@path, 'delete', 'list', first, last)
- self
- end
-
- def delete_entry(first, last=None)
- tk_call(@path, 'delete', 'entry', first, last)
- self
- end
-
- def get_list_contents(index)
- tk_call(@path, 'get', index)
- end
-
- def insert_list(idx, *elems)
- tk_call(@path, 'insert', 'list', idx, *elems)
- self
- end
-
- def insert_entry(idx, *elems)
- tk_call(@path, 'insert', 'entry', idx, *elems)
- self
- end
-
- # listbox methods
- def size
- tk_send_without_enc('size').to_i
- end
- def see(index)
- tk_send_without_enc('see', index)
- self
- end
- def selection_anchor(index)
- tk_send_without_enc('selection', 'anchor', index)
- self
- end
- def selection_clear(first, last=None)
- tk_send_without_enc('selection', 'clear', first, last)
- self
- end
- def selection_includes(index)
- bool(tk_send_without_enc('selection', 'includes', index))
- end
- def selection_set(first, last=None)
- tk_send_without_enc('selection', 'set', first, last)
- self
- end
-
- # scrolledlistbox methods
- def get_curselection
- tk_call(@path, 'getcurselection')
- end
- def justify(dir)
- tk_call(@path, 'justify', dir)
- self
- end
- def sort(*params, &b)
- # see 'lsort' man page about params
- if b
- tk_call(@path, 'sort', '-command', proc(&b), *params)
- else
- tk_call(@path, 'sort', *params)
- end
- self
- end
- def sort_ascending
- tk_call(@path, 'sort', 'ascending')
- self
- end
- def sort_descending
- tk_call(@path, 'sort', 'descending')
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/dateentry.rb b/ext/tk/lib/tkextlib/iwidgets/dateentry.rb
deleted file mode 100644
index 0a8897f50d..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/dateentry.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# tkextlib/iwidgets/dateentry.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Dateentry < Tk::Iwidgets::Datefield
- end
- end
-end
-
-class Tk::Iwidgets::Dateentry
- TkCommandNames = ['::iwidgets::dateentry'.freeze].freeze
- WidgetClassName = 'Dateentry'.freeze
- WidgetClassNames[WidgetClassName] = self
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/datefield.rb b/ext/tk/lib/tkextlib/iwidgets/datefield.rb
deleted file mode 100644
index 632f3334dc..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/datefield.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# tkextlib/iwidgets/datefield.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Datefield < Tk::Iwidgets::Labeledwidget
- end
- end
-end
-
-class Tk::Iwidgets::Datefield
- TkCommandNames = ['::iwidgets::datefield'.freeze].freeze
- WidgetClassName = 'Datefield'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __boolval_optkeys
- super() << 'gmt'
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- super() << 'textbackground'
- end
- private :__strval_optkeys
-
- def __font_optkeys
- super() << 'textfont'
- end
- private :__font_optkeys
-
- def get_string
- tk_call(@path, 'get', '-string')
- end
- alias get get_string
-
- def get_clicks
- number(tk_call(@path, 'get', '-clicks'))
- end
-
- def valid?
- bool(tk_call(@path, 'isvalid'))
- end
- alias isvalid? valid?
-
- def show(date=None)
- tk_call(@path, 'show', date)
- self
- end
- def show_now
- tk_call(@path, 'show', 'now')
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/dialog.rb b/ext/tk/lib/tkextlib/iwidgets/dialog.rb
deleted file mode 100644
index 8540eae1b5..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/dialog.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# tkextlib/iwidgets/dialog.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Dialog < Tk::Iwidgets::Dialogshell
- end
- end
-end
-
-class Tk::Iwidgets::Dialog
- TkCommandNames = ['::iwidgets::dialog'.freeze].freeze
- WidgetClassName = 'Dialog'.freeze
- WidgetClassNames[WidgetClassName] = self
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb b/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb
deleted file mode 100644
index d6c668621d..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb
+++ /dev/null
@@ -1,119 +0,0 @@
-#
-# tkextlib/iwidgets/dialogshell.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Dialogshell < Tk::Iwidgets::Shell
- end
- end
-end
-
-class Tk::Iwidgets::Dialogshell
- TkCommandNames = ['::iwidgets::dialogshell'.freeze].freeze
- WidgetClassName = 'Dialogshell'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- ####################################
-
- include TkItemConfigMethod
-
- def __item_cget_cmd(id)
- [self.path, 'buttoncget', id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- [self.path, 'buttonconfigure', id]
- end
- private :__item_config_cmd
-
- def __item_boolval_optkeys(id)
- super(id) << 'defaultring'
- end
- private :__item_boolval_optkeys
-
- def tagid(tagOrId)
- if tagOrId.kind_of?(Tk::Itk::Component)
- tagOrId.name
- else
- #_get_eval_string(tagOrId)
- tagOrId
- end
- end
-
- alias buttoncget itemcget
- alias buttonconfigure itemconfigure
- alias buttonconfiginfo itemconfiginfo
- alias current_buttonconfiginfo current_itemconfiginfo
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-
- ####################################
-
- def add(tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- if tag
- tag = Tk::Itk::Component.new(self, tagid(tag))
- else
- tag = Tk::Itk::Component.new(self)
- end
- tk_call(@path, 'add', tagid(tag), *hash_kv(keys))
- tag
- end
-
- def default(idx)
- tk_call(@path, 'default', index(idx))
- self
- end
-
- def delete(idx)
- tk_call(@path, 'delete', index(idx))
- self
- end
-
- def hide(idx)
- tk_call(@path, 'hide', index(idx))
- self
- end
-
- def index(idx)
- number(tk_call(@path, 'index', tagid(idx)))
- end
-
- def insert(idx, tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- if tag
- tag = Tk::Itk::Component.new(self, tagid(tag))
- else
- tag = Tk::Itk::Component.new(self)
- end
- tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys))
- tag
- end
-
- def invoke(idx=nil)
- if idx
- tk_call(@path, 'invoke', index(idx))
- else
- tk_call(@path, 'invoke')
- end
- self
- end
-
- def show(idx)
- tk_call(@path, 'show', index(idx))
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb b/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb
deleted file mode 100644
index 9bc063ba69..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-#
-# tkextlib/iwidgets/disjointlistbox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Disjointlistbox < Tk::Itk::Widget
- end
- end
-end
-
-class Tk::Iwidgets::Disjointlistbox
- TkCommandNames = ['::iwidgets::disjointlistbox'.freeze].freeze
- WidgetClassName = 'Disjointlistbox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'lhslabeltext' << 'rhslabeltext' << 'lhsbuttonlabel' << 'rhsbuttonlabel'
- end
- private :__strval_optkeys
-
- def set_lhs(*items)
- tk_call(@path, 'setlhs', items)
- self
- end
- def set_rhs(*items)
- tk_call(@path, 'setrhs', items)
- self
- end
-
- def get_lhs
- simplelist(tk_call(@path, 'getlhs'))
- end
- def get_rhs
- simplelist(tk_call(@path, 'getrhs'))
- end
-
- def insert_lhs(*items)
- tk_call(@path, 'insertlhs', items)
- self
- end
- def insert_rhs(*items)
- tk_call(@path, 'insertrhs', items)
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
deleted file mode 100644
index 6aa933ce06..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
+++ /dev/null
@@ -1,166 +0,0 @@
-#
-# tkextlib/iwidgets/entryfield.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Entryfield < Tk::Iwidgets::Labeledwidget
- end
- end
-end
-
-class Tk::Iwidgets::Entryfield
- TkCommandNames = ['::iwidgets::entryfield'.freeze].freeze
- WidgetClassName = 'Entryfield'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __font_optkeys
- super() << 'textfont'
- end
- private :__font_optkeys
-
- ####################################
-
- include Tk::ValidateConfigure
-
- class EntryfieldValidate < TkValidateCommand
- #class CalCmdArgs < TkUtil::CallbackSubst
- class ValidateArgs < TkUtil::CallbackSubst
- KEY_TBL = [
- [ ?c, ?s, :char ],
- [ ?P, ?s, :post ],
- [ ?S, ?s, :current ],
- [ ?W, ?w, :widget ],
- nil
- ]
- PROC_TBL = [
- [ ?s, TkComm.method(:string) ],
- [ ?w, TkComm.method(:window) ],
- nil
- ]
- _setup_subst_table(KEY_TBL, PROC_TBL);
- end
-
- def self._config_keys
- ['validate', 'invalid']
- end
- end
-
- def __validation_class_list
- super() << EntryfieldValidate
- end
-
- Tk::ValidateConfigure.__def_validcmd(binding, EntryfieldValidate)
-=begin
- def validate(cmd = Proc.new, args = nil)
- if cmd.kind_of?(ValidateCmd)
- configure('validate', cmd)
- elsif args
- configure('validate', [cmd, args])
- else
- configure('validate', cmd)
- end
- end
-
- def invalid(cmd = Proc.new, args = nil)
- if cmd.kind_of?(ValidateCmd)
- configure('invalid', cmd)
- elsif args
- configure('invalid', [cmd, args])
- else
- configure('invalid', cmd)
- end
- end
-=end
-
- ####################################
-
- def clear
- tk_call(@path, 'clear')
- self
- end
-
- def delete(first, last=None)
- tk_send_without_enc('delete', first, last)
- self
- end
-
- def value
- _fromUTF8(tk_send_without_enc('get'))
- end
- def value= (val)
- tk_send_without_enc('delete', 0, 'end')
- tk_send_without_enc('insert', 0, _get_eval_enc_str(val))
- val
- end
- alias get value
- alias set value=
-
- def cursor=(index)
- tk_send_without_enc('icursor', index)
- #self
- index
- end
- alias icursor cursor=
-
- def index(index)
- number(tk_send_without_enc('index', index))
- end
-
- def insert(pos,text)
- tk_send_without_enc('insert', pos, _get_eval_enc_str(text))
- self
- end
-
- def mark(pos)
- tk_send_without_enc('scan', 'mark', pos)
- self
- end
- def dragto(pos)
- tk_send_without_enc('scan', 'dragto', pos)
- self
- end
- def selection_adjust(index)
- tk_send_without_enc('selection', 'adjust', index)
- self
- end
- def selection_clear
- tk_send_without_enc('selection', 'clear')
- self
- end
- def selection_from(index)
- tk_send_without_enc('selection', 'from', index)
- self
- end
- def selection_present()
- bool(tk_send_without_enc('selection', 'present'))
- end
- def selection_range(s, e)
- tk_send_without_enc('selection', 'range', s, e)
- self
- end
- def selection_to(index)
- tk_send_without_enc('selection', 'to', index)
- self
- end
-
- # based on tk/scrollable.rb
- def xview(*index)
- if index.size == 0
- list(tk_send_without_enc('xview'))
- else
- tk_send_without_enc('xview', *index)
- self
- end
- end
- def xview_moveto(*index)
- xview('moveto', *index)
- end
- def xview_scroll(*index)
- xview('scroll', *index)
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/extbutton.rb b/ext/tk/lib/tkextlib/iwidgets/extbutton.rb
deleted file mode 100644
index 158d9d474a..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/extbutton.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# tkextlib/iwidgets/extbutton.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Extbutton < Tk::Itk::Widget
- end
- end
-end
-
-class Tk::Iwidgets::Extbutton
- TkCommandNames = ['::iwidgets::extbutton'.freeze].freeze
- WidgetClassName = 'Extbutton'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'bitmapforeground' << 'ringbackground'
- end
- private :__strval_optkeys
-
- def __boolval_optkeys
- super() << 'defaultring'
- end
- private :__boolval_optkeys
-
- def invoke
- tk_call(@path, 'invoke')
- self
- end
-
- def flash
- tk_call(@path, 'flash')
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb b/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb
deleted file mode 100644
index 501f4c90a0..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# tkextlib/iwidgets/extfileselectionbox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Extfileselectionbox < Tk::Itk::Widget
- end
- end
-end
-
-class Tk::Iwidgets::Extfileselectionbox
- TkCommandNames = ['::iwidgets::extfileselectionbox'.freeze].freeze
- WidgetClassName = 'Extfileselectionbox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() + [
- 'dirslabel', 'fileslabel', 'filterlabel', 'mask', 'nomatchstring',
- 'selectionlabel'
- ]
- end
- private :__strval_optkeys
-
- def __boolval_optkeys
- super() + ['dirson', 'fileson', 'filteron', 'selectionon']
- end
- private :__boolval_optkeys
-
- def child_site
- window(tk_call(@path, 'childsite'))
- end
-
- def filter
- tk_call(@path, 'filter')
- self
- end
-
- def get
- tk_call(@path, 'get')
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb b/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb
deleted file mode 100644
index 14388be7c4..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# tkextlib/iwidgets/extfileselectiondialog.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Extfileselectiondialog < Tk::Iwidgets::Dialog
- end
- end
-end
-
-class Tk::Iwidgets::Extfileselectiondialog
- TkCommandNames = ['::iwidgets::extfileselectiondialog'.freeze].freeze
- WidgetClassName = 'Extfileselectiondialog'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def child_site
- window(tk_call(@path, 'childsite'))
- end
-
- def filter
- tk_call(@path, 'filter')
- self
- end
-
- def get
- tk_call(@path, 'get')
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/feedback.rb b/ext/tk/lib/tkextlib/iwidgets/feedback.rb
deleted file mode 100644
index 0a25237a24..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/feedback.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# tkextlib/iwidgets/feedback.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Feedback < Tk::Iwidgets::Labeledwidget
- end
- end
-end
-
-class Tk::Iwidgets::Feedback
- TkCommandNames = ['::iwidgets::feedback'.freeze].freeze
- WidgetClassName = 'Feedback'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'barcolor'
- end
- private :__strval_optkeys
-
- def reset
- tk_call(@path, 'reset')
- self
- end
-
- def step(inc=1)
- tk_call(@path, 'step', inc)
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb b/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb
deleted file mode 100644
index 7b331d0b40..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# tkextlib/iwidgets/fileselectionbox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Fileselectionbox < Tk::Itk::Widget
- end
- end
-end
-
-class Tk::Iwidgets::Fileselectionbox
- TkCommandNames = ['::iwidgets::fileselectionbox'.freeze].freeze
- WidgetClassName = 'Fileselectionbox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() + [
- 'directory', 'dirslabel', 'fileslabel', 'filterlabel', 'mask',
- 'nomatchstring', 'selectionlabel'
- ]
- end
- private :__strval_optkeys
-
- def __boolval_optkeys
- super() + ['dirson', 'fileson', 'filteron', 'selectionon']
- end
- private :__boolval_optkeys
-
- def child_site
- window(tk_call(@path, 'childsite'))
- end
-
- def filter
- tk_call(@path, 'filter')
- self
- end
-
- def get
- tk_call(@path, 'get')
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb b/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb
deleted file mode 100644
index 50f459e56d..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# tkextlib/iwidgets/fileselectiondialog.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Fileselectiondialog < Tk::Iwidgets::Dialog
- end
- end
-end
-
-class Tk::Iwidgets::Fileselectiondialog
- TkCommandNames = ['::iwidgets::fileselectiondialog'.freeze].freeze
- WidgetClassName = 'Fileselectiondialog'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def child_site
- window(tk_call(@path, 'childsite'))
- end
-
- def filter
- tk_call(@path, 'filter')
- self
- end
-
- def get
- tk_call(@path, 'get')
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/finddialog.rb b/ext/tk/lib/tkextlib/iwidgets/finddialog.rb
deleted file mode 100644
index 75e219c37e..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/finddialog.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# tkextlib/iwidgets/finddialog.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Finddialog < Tk::Iwidgets::Dialogshell
- end
- end
-end
-
-class Tk::Iwidgets::Finddialog
- TkCommandNames = ['::iwidgets::finddialog'.freeze].freeze
- WidgetClassName = 'Finddialog'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() + [
- 'patternbackground', 'patternforeground',
- 'searchbackground', 'searchforeground'
- ]
- end
- private :__strval_optkeys
-
- def __val2ruby_optkeys # { key=>proc, ... }
- super().update('textwidget'=>proc{|v| window(v)})
- end
- private :__val2ruby_optkeys
-
- def clear
- tk_call(@path, 'clear')
- self
- end
-
- def find
- tk_call(@path, 'find')
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb b/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb
deleted file mode 100644
index 4cc6aeecbd..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb
+++ /dev/null
@@ -1,309 +0,0 @@
-#
-# tkextlib/iwidgets/hierarchy.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/text'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Hierarchy < Tk::Iwidgets::Scrolledwidget
- end
- end
-end
-
-class Tk::Iwidgets::Hierarchy
- ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze
- include TkTextTagConfig
-
- TkCommandNames = ['::iwidgets::hierarchy'.freeze].freeze
- WidgetClassName = 'Hierarchy'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- ####################################
-
- include Tk::ValidateConfigure
-
- class QueryCommand < TkValidateCommand
- class ValidateArgs < TkUtil::CallbackSubst
- KEY_TBL = [ [?n, ?s, :node], nil ]
- PROC_TBL = [ [?s, TkComm.method(:string) ], nil ]
- _setup_subst_table(KEY_TBL, PROC_TBL);
-
- def self.ret_val(val)
- val
- end
- end
-
- def self._config_keys
- # array of config-option key (string or symbol)
- ['querycommand']
- end
- end
-
- class IndicatorCommand < TkValidateCommand
- class ValidateArgs < TkUtil::CallbackSubst
- KEY_TBL = [
- [ ?n, ?s, :node ],
- [ ?s, ?b, :status ],
- nil
- ]
-
- PROC_TBL = [
- [ ?s, TkComm.method(:string) ],
- [ ?b, TkComm.method(:bool) ],
- nil
- ]
-
- _setup_subst_table(KEY_TBL, PROC_TBL);
-
- def self.ret_val(val)
- val
- end
- end
-
- def self._config_keys
- # array of config-option key (string or symbol)
- ['iconcommand', 'icondblcommand', 'imagedblcommand']
- end
- end
-
- class IconCommand < TkValidateCommand
- class ValidateArgs < TkUtil::CallbackSubst
- KEY_TBL = [
- [ ?n, ?s, :node ],
- [ ?i, ?s, :icon ],
- nil
- ]
- PROC_TBL = [ [ ?s, TkComm.method(:string) ], nil ]
- _setup_subst_table(KEY_TBL, PROC_TBL);
-
- def self.ret_val(val)
- val
- end
- end
-
- def self._config_keys
- # array of config-option key (string or symbol)
- ['dblclickcommand', 'imagecommand', 'selectcommand']
- end
- end
-
- def __validation_class_list
- super() << QueryCommand << IndicatorCommand << IconCommand
- end
-
- Tk::ValidateConfigure.__def_validcmd(binding, QueryCommand)
- Tk::ValidateConfigure.__def_validcmd(binding, IndicatorCommand)
- Tk::ValidateConfigure.__def_validcmd(binding, IconCommand)
-
- ####################################
-
- def __boolval_optkeys
- super() << 'alwaysquery' << 'expanded' << 'filter'
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- super() << 'markbackground' << 'markforeground' << 'textbackground'
- end
- private :__strval_optkeys
-
- def __font_optkeys
- super() << 'textfont'
- end
- private :__font_optkeys
-
- def clear
- tk_call(@path, 'clear')
- self
- end
-
- def collapse(node)
- tk_call(@path, 'collapse')
- self
- end
-
- def current
- tk_call(@path, 'current')
- end
-
- def draw(mode=None)
- case mode
- when None
- # do nothing
- when 'now', :now
- mode = '-now'
- when 'eventually', :eventually
- mode = '-eventually'
- when String, Symbol
- mode = mode.to_s
- mode = '-' << mode if mode[0] != ?-
- end
- tk_call(@path, 'draw', mode)
- end
-
- def expand(node)
- tk_call(@path, 'expand', node)
- self
- end
-
- def expanded?(node)
- bool(tk_call(@path, 'expanded', node))
- end
-
- def exp_state
- list(tk_call(@path, 'expState'))
- end
- alias expand_state exp_state
- alias expanded_list exp_state
-
- def mark_clear
- tk_call(@path, 'mark', 'clear')
- self
- end
- def mark_add(*nodes)
- tk_call(@path, 'mark', 'add', *nodes)
- self
- end
- def mark_remove(*nodes)
- tk_call(@path, 'mark', 'remove', *nodes)
- self
- end
- def mark_get
- list(tk_call(@path, 'mark', 'get'))
- end
-
- def refresh(node)
- tk_call(@path, 'refresh', node)
- self
- end
-
- def prune(node)
- tk_call(@path, 'prune', node)
- self
- end
-
- def selection_clear
- tk_call(@path, 'selection', 'clear')
- self
- end
- def selection_add(*nodes)
- tk_call(@path, 'selection', 'add', *nodes)
- self
- end
- def selection_remove(*nodes)
- tk_call(@path, 'selection', 'remove', *nodes)
- self
- end
- def selection_get
- list(tk_call(@path, 'selection', 'get'))
- end
-
- def toggle(node)
- tk_call(@path, 'toggle', node)
- self
- end
-
- # based on TkText widget
-
- def bbox(index)
- list(tk_send_without_enc('bbox', _get_eval_enc_str(index)))
- end
-
- def compare(idx1, op, idx2)
- bool(tk_send_without_enc('compare', _get_eval_enc_str(idx1),
- op, _get_eval_enc_str(idx2)))
- end
-
- def debug
- bool(tk_send_without_enc('debug'))
- end
- def debug=(boolean)
- tk_send_without_enc('debug', boolean)
- #self
- boolean
- end
-
- def delete(first, last=None)
- tk_send_without_enc('delete', first, last)
- self
- end
-
- def dlineinfo(index)
- list(tk_send_without_enc('dlineinfo', _get_eval_enc_str(index)))
- end
-
- def get(*index)
- _fromUTF8(tk_send_without_enc('get', *index))
- end
-
- def index(index)
- tk_send_without_enc('index', _get_eval_enc_str(index))
- end
-
- def insert(index, chars, *tags)
- if tags[0].kind_of? Array
- # multiple chars-taglist argument :: str, [tag,...], str, [tag,...], ...
- args = [chars]
- while tags.size > 0
- args << tags.shift.collect{|x|_get_eval_string(x)}.join(' ') # taglist
- args << tags.shift if tags.size > 0 # chars
- end
- super(index, *args)
- else
- # single chars-taglist argument :: str, tag, tag, ...
- if tags.size == 0
- super(index, chars)
- else
- super(index, chars, tags.collect{|x|_get_eval_string(x)}.join(' '))
- end
- end
- end
-
- def scan_mark(x, y)
- tk_send_without_enc('scan', 'mark', x, y)
- self
- end
- def scan_dragto(x, y)
- tk_send_without_enc('scan', 'dragto', x, y)
- self
- end
- def see(index)
- tk_send_without_enc('see', index)
- self
- end
-
- # based on tk/scrollable.rb
- def xview(*index)
- if index.size == 0
- list(tk_send_without_enc('xview'))
- else
- tk_send_without_enc('xview', *index)
- self
- end
- end
- def xview_moveto(*index)
- xview('moveto', *index)
- end
- def xview_scroll(*index)
- xview('scroll', *index)
- end
-
- def yview(*index)
- if index.size == 0
- list(tk_send_without_enc('yview'))
- else
- tk_send_without_enc('yview', *index)
- self
- end
- end
- def yview_moveto(*index)
- yview('moveto', *index)
- end
- def yview_scroll(*index)
- yview('scroll', *index)
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb b/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb
deleted file mode 100644
index 77b0e090cd..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-#
-# tkextlib/iwidgets/hyperhelp.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Hyperhelp < Tk::Iwidgets::Shell
- end
- end
-end
-
-class Tk::Iwidgets::Hyperhelp
- TkCommandNames = ['::iwidgets::hyperhelp'.freeze].freeze
- WidgetClassName = 'Hyperhelp'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'helpdir'
- end
- private :__strval_optkeys
-
- def __listval_optkeys
- super() << 'topics'
- end
- private :__listval_optkeys
-
- def show_topic(topic)
- tk_call(@path, 'showtopic', topic)
- self
- end
-
- def follow_link(href)
- tk_call(@path, 'followlink', href)
- self
- end
-
- def forward
- tk_call(@path, 'forward')
- self
- end
-
- def back
- tk_call(@path, 'back')
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb b/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb
deleted file mode 100644
index e77e85045d..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# tkextlib/iwidgets/labeledframe.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Labeledframe < Tk::Itk::Archetype
- end
- end
-end
-
-class Tk::Iwidgets::Labeledframe
- TkCommandNames = ['::iwidgets::labeledframe'.freeze].freeze
- WidgetClassName = 'Labeledframe'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'labeltext'
- end
- private :__strval_optkeys
-
- def __tkvariable_optkeys
- super() << 'labelvariable'
- end
- private :__tkvariable_optkeys
-
- def __font_optkeys
- super() << 'labelfont'
- end
- private :__font_optkeys
-
- def child_site
- window(tk_call(@path, 'childsite'))
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb b/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb
deleted file mode 100644
index 99387710cb..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# tkextlib/iwidgets/labeledwidget.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Labeledwidget < Tk::Itk::Widget
- end
- end
-end
-
-class Tk::Iwidgets::Labeledwidget
- extend TkCore
-
- TkCommandNames = ['::iwidgets::labeledwidget'.freeze].freeze
- WidgetClassName = 'Labeledwidget'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'labeltext'
- end
- private :__strval_optkeys
-
- def __tkvariable_optkeys
- super() << 'labelvariable'
- end
- private :__tkvariable_optkeys
-
- def __font_optkeys
- super() << 'labelfont'
- end
- private :__font_optkeys
-
- def self.alignlabels(*wins)
- tk_call('::iwidgets::Labeledwidget::alignlabels', *wins)
- end
-
- def child_site
- window(tk_call(@path, 'childsite'))
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb b/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb
deleted file mode 100644
index 4b2541b997..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# tkextlib/iwidgets/mainwindow.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Mainwindow < Tk::Iwidgets::Shell
- end
- end
-end
-
-class Tk::Iwidgets::Mainwindow
- TkCommandNames = ['::iwidgets::mainwindow'.freeze].freeze
- WidgetClassName = 'Mainwindow'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __boolval_optkeys
- super() << 'helpline' << 'statusline'
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- super() << 'menubarbackground' << 'menubarforeground' << 'toolbarforeground'
- end
- private :__strval_optkeys
-
- def __font_optkeys
- super() << 'menubarfont' << 'toolbarfont'
- end
- private :__font_optkeys
-
- def child_site
- window(tk_call(@path, 'childsite'))
- end
-
- def menubar(*args)
- unless args.empty?
- tk_call(@path, 'menubar', *args)
- end
- window(tk_call(@path, 'menubar'))
- end
-
- def mousebar(*args)
- unless args.empty?
- tk_call(@path, 'mousebar', *args)
- end
- window(tk_call(@path, 'mousebar'))
- end
-
- def msgd(*args)
- unless args.empty?
- tk_call(@path, 'msgd', *args)
- end
- window(tk_call(@path, 'msgd'))
- end
-
- def toolbar(*args)
- unless args.empty?
- tk_call(@path, 'toolbar', *args)
- end
- window(tk_call(@path, 'toolbar'))
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/menubar.rb b/ext/tk/lib/tkextlib/iwidgets/menubar.rb
deleted file mode 100644
index dea3d34c2a..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/menubar.rb
+++ /dev/null
@@ -1,210 +0,0 @@
-#
-# tkextlib/iwidgets/menubar.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Menubar < Tk::Itk::Widget
- end
- end
-end
-
-class Tk::Iwidgets::Menubar
- TkCommandNames = ['::iwidgets::menubar'.freeze].freeze
- WidgetClassName = 'Menubar'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'menubuttons'
- end
- private :__strval_optkeys
-
- def __tkvariable_optkeys
- super() << 'helpvariable'
- end
- private :__tkvariable_optkeys
-
- ####################################
-
- include TkItemConfigMethod
-
- def __item_cget_cmd(id)
- [self.path, 'menucget', id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- [self.path, 'menuconfigure', id]
- end
- private :__item_config_cmd
-
- def __item_strval_optkeys(id)
- super(id) << 'selectcolor'
- end
- private :__item_strval_optkeys
-
- def __item_tkvariable_optkeys(id)
- super(id) << 'helpstr'
- end
- private :__item_tkvariable_optkeys
-
- def tagid(tagOrId)
- if tagOrId.kind_of?(Tk::Itk::Component)
- tagOrId.name
- else
- #_get_eval_string(tagOrId)
- tagOrId
- end
- end
-
- alias menucget itemcget
- alias menuconfigure itemconfigure
- alias menuconfiginfo itemconfiginfo
- alias current_menuconfiginfo current_itemconfiginfo
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-
- ####################################
-
- def __methodcall_optkeys
- {'menubuttons'=>'menubuttons'}
- end
-
- def menubuttons(val = nil)
- unless val
- return tk_call(@path, 'cget', '-menubuttons')
- end
-
- tk_call(@path, 'configure', '-menubuttons', _parse_menu_spec(val))
- self
- end
-
- def _parse_menu_spec(menu_spec)
- ret = ''
- menu_spec.each{|spec|
- next unless spec
-
- if spec.kind_of?(Hash)
- args = [spec]
- type = 'options'
- else
- type, *args = spec
- end
-
- type = type.to_s
- case type
- when 'options'
- keys = args[0]
- ary = [type]
- ary.concat(hash_kv(keys))
- ret << array2tk_list(ary) << "\n"
-
- when 'menubutton', 'cascade'
- name, keys = args
- if keys
- ary = [type, name]
- keys = _symbolkey2str(keys)
- keys['menu'] = _parse_menu_spec(keys['menu']) if keys.key?('menu')
- ary.concat(hash_kv(keys))
- ret << array2tk_list(ary) << "\n"
- else
- ret << array2tk_list([type, name]) << "\n"
- end
-
- else
- name, keys = args
- if keys
- ary = [type, name]
- ary.concat(hash_kv(keys))
- ret << array2tk_list(ary) << "\n"
- else
- ret << array2tk_list([type, name]) << "\n"
- end
- end
- }
- ret
- end
-
- ####################################
-
- def add(type, tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- if tag
- tag = Tk::Itk::Component.new(self, tagid(tag))
- else
- tag = Tk::Itk::Component.new(self)
- end
- keys = _symbolkey2str(keys)
- keys['menu'] = _parse_menu_spec(keys['menu']) if keys.key?('menu')
- tk_call(@path, 'add', type, tagid(tag), *hash_kv(keys))
- tag
- end
-
- def delete(path1, path2=nil)
- if path2
- else
- tk_call(@path, 'delete', index(idx))
- end
- self
- end
-
- def index(idx)
- number(tk_call(@path, 'index', tagid(idx)))
- end
-
- def insert(idx, type, tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- if tag
- tag = Tk::Itk::Component.new(self, tagid(tag))
- else
- tag = Tk::Itk::Component.new(self)
- end
- keys = _symbolkey2str(keys)
- keys['menu'] = _parse_menu_spec(keys['menu']) if keys.key?('menu')
- tk_call(@path, 'insert', index(idx), type, tagid(tag), *hash_kv(keys))
- tag
- end
-
- def invoke(idx)
- tk_call(@path, 'invoke', index(idx))
- self
- end
-
- def menupath(pat)
- if (win = tk_call(@path, 'path', pat)) == '-1'
- return nil
- end
- window(win)
- end
- def menupath_glob(pat)
- if (win = tk_call(@path, 'path', '-glob', pat)) == '-1'
- return nil
- end
- window(win)
- end
- def menupath_tclregexp(pat)
- if (win = tk_call(@path, 'path', '-regexp', pat)) == '-1'
- return nil
- end
- window(win)
- end
-
- def type(path)
- tk_call(@path, 'type', path)
- end
-
- def yposition(path)
- number(tk_call(@path, 'yposition', path))
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/messagebox.rb b/ext/tk/lib/tkextlib/iwidgets/messagebox.rb
deleted file mode 100644
index 2bbbec7666..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/messagebox.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-#
-# tkextlib/iwidgets/messagebox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Messagebox < Tk::Iwidgets::Scrolledwidget
- end
- end
-end
-
-class Tk::Iwidgets::Messagebox
- TkCommandNames = ['::iwidgets::messagebox'.freeze].freeze
- WidgetClassName = 'Messagebox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- ####################################
-
- include TkItemConfigMethod
-
- def __item_cget_cmd(id)
- [self.path, 'type', 'cget', id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- [self.path, 'type', 'configure', id]
- end
- private :__item_config_cmd
-
- def tagid(tagOrId)
- if tagOrId.kind_of?(Tk::Itk::Component)
- tagOrId.name
- else
- #_get_eval_string(tagOrId)
- tagOrId
- end
- end
-
- def __item_boolval_optkeys(id)
- super(id) << 'bell' << 'show'
- end
- private :__item_boolval_optkeys
-
- alias typecget itemcget
- alias typeconfigure itemconfigure
- alias typeconfiginfo itemconfiginfo
- alias current_typeconfiginfo current_itemconfiginfo
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-
- ####################################
-
- def __strval_optkeys
- super() << 'filename' << 'savedir'
- end
- private :__strval_optkeys
-
- def type_add(tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- unless tag
- tag = Tk::Itk::Component.new(self)
- end
- tk_call(@path, 'type', 'add', tagid(tag), *hash_kv(keys))
- tag
- end
-
- def clear
- tk_call(@path, 'clear')
- self
- end
-
- def export(file)
- tk_call(@path, 'export', file)
- self
- end
-
- def issue(string, type=None, *args)
- tk_call(@path, 'issue', string, tagid(type), *args)
- self
- end
-
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb b/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb
deleted file mode 100644
index c19b83e517..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# tkextlib/iwidgets/messagedialog.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Messagedialog < Tk::Iwidgets::Dialog
- end
- end
-end
-
-class Tk::Iwidgets::Messagedialog
- TkCommandNames = ['::iwidgets::messagedialog'.freeze].freeze
- WidgetClassName = 'Messagedialog'.freeze
- WidgetClassNames[WidgetClassName] = self
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/notebook.rb b/ext/tk/lib/tkextlib/iwidgets/notebook.rb
deleted file mode 100644
index 0f9d713ea1..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/notebook.rb
+++ /dev/null
@@ -1,168 +0,0 @@
-#
-# tkextlib/iwidgets/notebook.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Notebook < Tk::Itk::Widget
- end
- end
-end
-
-class Tk::Iwidgets::Notebook
- TkCommandNames = ['::iwidgets::notebook'.freeze].freeze
- WidgetClassName = 'Notebook'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- ####################################
-
- include TkItemConfigMethod
-
- def __item_cget_cmd(id)
- [self.path, 'pagecget', id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- [self.path, 'pageconfigure', id]
- end
- private :__item_config_cmd
-
- def tagid(tagOrId)
- if tagOrId.kind_of?(Tk::Itk::Component)
- tagOrId.name
- else
- #_get_eval_string(tagOrId)
- tagOrId
- end
- end
-
- alias pagecget itemcget
- alias pageconfigure itemconfigure
- alias pageconfiginfo itemconfiginfo
- alias current_pageconfiginfo current_itemconfiginfo
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-
- ####################################
-
- def __boolval_optkeys
- super() << 'auto'
- end
- private :__boolval_optkeys
-
- def add(keys={})
- window(tk_call(@path, 'add', *hash_kv(keys)))
- end
-
- def child_site_list
- list(tk_call(@path, 'childsite'))
- end
-
- def child_site(idx)
- if (new_idx = self.index(idx)) < 0
- new_idx = tagid(idx)
- end
- window(tk_call(@path, 'childsite', new_idx))
- end
-
- def delete(idx1, idx2=nil)
- if (new_idx1 = self.index(idx1)) < 0
- new_idx1 = tagid(idx1)
- end
- if idx2
- if (new_idx2 = self.index(idx2)) < 0
- new_idx2 = tagid(idx2)
- end
- tk_call(@path, 'delete', new_idx1, new_idx2)
- else
- tk_call(@path, 'delete', new_idx1)
- end
- self
- end
-
- def index(idx)
- number(tk_call(@path, 'index', tagid(idx)))
- end
-
- def insert(idx, keys={})
- if (new_idx = self.index(idx)) < 0
- new_idx = tagid(idx)
- end
- window(tk_call(@path, 'insert', new_idx, *hash_kv(keys)))
- end
-
- def next
- tk_call(@path, 'next')
- self
- end
-
- def prev
- tk_call(@path, 'prev')
- self
- end
-
- def select(idx)
- if (new_idx = self.index(idx)) < 0
- new_idx = tagid(idx)
- end
- tk_call(@path, 'select', new_idx)
- self
- end
-
- def scrollcommand(cmd=Proc.new)
- configure_cmd 'scrollcommand', cmd
- self
- end
- alias xscrollcommand scrollcommand
- alias yscrollcommand scrollcommand
-
- def xscrollbar(bar=nil)
- if bar
- @scrollbar = bar
- @scrollbar.orient 'horizontal'
- self.scrollcommand {|*arg| @scrollbar.set(*arg)}
- @scrollbar.command {|*arg| self.xview(*arg)}
- Tk.update # avoid scrollbar trouble
- end
- @scrollbar
- end
- def yscrollbar(bar=nil)
- if bar
- @scrollbar = bar
- @scrollbar.orient 'vertical'
- self.scrollcommand {|*arg| @scrollbar.set(*arg)}
- @scrollbar.command {|*arg| self.yview(*arg)}
- Tk.update # avoid scrollbar trouble
- end
- @scrollbar
- end
- alias scrollbar yscrollbar
-
- def view(*idxs)
- if idxs.size == 0
- window(tk_send_without_enc('view'))
- else
- tk_send_without_enc('view', *idxs)
- self
- end
- end
- alias xview view
- alias yview view
-
- def view_moveto(*idxs)
- view('moveto', *idxs)
- end
- alias xview_moveto view_moveto
- alias yview_moveto view_moveto
- def view_scroll(*idxs)
- view('scroll', *idxs)
- end
- alias xview_scroll view_scroll
- alias yview_scroll view_scroll
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb b/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb
deleted file mode 100644
index 0c74440be7..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-#
-# tkextlib/iwidgets/optionmenu.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Optionmenu < Tk::Iwidgets::Labeledwidget
- end
- end
-end
-
-class Tk::Iwidgets::Optionmenu
- TkCommandNames = ['::iwidgets::optionmenu'.freeze].freeze
- WidgetClassName = 'Optionmenu'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __boolval_optkeys
- super() << 'cyclicon'
- end
- private :__boolval_optkeys
-
- def delete(first, last=nil)
- if last
- tk_call(@path, 'delete', first, last)
- else
- tk_call(@path, 'delete', first)
- end
- self
- end
-
- def disable(idx)
- tk_call(@path, 'disable', idx)
- self
- end
-
- def enable(idx)
- tk_call(@path, 'enable', idx)
- self
- end
-
- def get(first=nil, last=nil)
- if last
- simplelist(tk_call(@path, 'get', first, last))
- elsif first
- tk_call(@path, 'get', first)
- else
- tk_call(@path, 'get')
- end
- end
- def get_range(first, last)
- get(first, last)
- end
- def get_selected
- get()
- end
-
- def index(idx)
- number(tk_call(@path, 'index', idx))
- end
-
- def insert(idx, *args)
- tk_call(@path, 'insert', idx, *args)
- self
- end
-
- def select(idx)
- tk_call(@path, 'select', idx)
- self
- end
-
- def sort(*params, &b)
- # see 'lsort' man page about params
- if b
- tk_call(@path, 'sort', '-command', proc(&b), *params)
- else
- tk_call(@path, 'sort', *params)
- end
- self
- end
- def sort_ascending
- tk_call(@path, 'sort', 'ascending')
- self
- end
- def sort_descending
- tk_call(@path, 'sort', 'descending')
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb b/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb
deleted file mode 100644
index 035df0a5b8..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-#
-# tkextlib/iwidgets/panedwindow.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Panedwindow < Tk::Itk::Widget
- end
- end
-end
-
-class Tk::Iwidgets::Panedwindow
- TkCommandNames = ['::iwidgets::panedwindow'.freeze].freeze
- WidgetClassName = 'Panedwindow'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- ####################################
-
- include TkItemConfigMethod
-
- def __item_cget_cmd(id)
- [self.path, 'panecget', id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- [self.path, 'paneconfigure', id]
- end
- private :__item_config_cmd
-
- def tagid(tagOrId)
- if tagOrId.kind_of?(Tk::Itk::Component)
- tagOrId.name
- else
- #_get_eval_string(tagOrId)
- tagOrId
- end
- end
-
- alias panecget itemcget
- alias paneconfigure itemconfigure
- alias paneconfiginfo itemconfiginfo
- alias current_paneconfiginfo current_itemconfiginfo
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-
- ####################################
-
- def __boolval_optkeys
- super() << 'showhandle'
- end
- private :__boolval_optkeys
-
- def add(tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- if tag
- tag = Tk::Itk::Component.new(self, tagid(tag))
- else
- tag = Tk::Itk::Component.new(self)
- end
- window(tk_call(@path, 'add', tagid(tag), *hash_kv(keys)))
- tag
- end
-
- def child_site_list
- list(tk_call(@path, 'childsite'))
- end
-
- def child_site(idx)
- window(tk_call(@path, 'childsite', index(idx)))
- end
-
- def delete(idx)
- tk_call(@path, 'delete', index(idx))
- self
- end
-
- def fraction(*percentages)
- tk_call(@path, 'fraction', *percentages)
- self
- end
-
- def hide(idx)
- tk_call(@path, 'hide', index(idx))
- self
- end
-
- def index(idx)
- number(tk_call(@path, 'index', tagid(idx)))
- end
-
- def insert(idx, tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- if tag
- tag = Tk::Itk::Component.new(self, tagid(tag))
- else
- tag = Tk::Itk::Component.new(self)
- end
- window(tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys)))
- tag
- end
-
- def invoke(idx=nil)
- if idx
- tk_call(@path, 'invoke', index(idx))
- else
- tk_call(@path, 'invoke')
- end
- self
- end
-
- def reset
- tk_call(@path, 'reset')
- self
- end
-
- def show(idx)
- tk_call(@path, 'show', index(idx))
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb b/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb
deleted file mode 100644
index 620b14b5d5..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb
+++ /dev/null
@@ -1,131 +0,0 @@
-#
-# tkextlib/iwidgets/promptdialog.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Promptdialog < Tk::Iwidgets::Dialog
- end
- end
-end
-
-class Tk::Iwidgets::Promptdialog
- TkCommandNames = ['::iwidgets::promptdialog'.freeze].freeze
- WidgetClassName = 'Promptdialog'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- # index method is not available, because it shows index of the entry field
- def default(name)
- tk_call(@path, 'default', tagid(name))
- self
- end
-
- def hide(name)
- tk_call(@path, 'hide', tagid(name))
- self
- end
-
- def invoke(name=nil)
- if name
- tk_call(@path, 'invoke', tagid(name))
- else
- tk_call(@path, 'invoke')
- end
- self
- end
-
- def show(name)
- tk_call(@path, 'show', tagid(name))
- self
- end
-
-
- # based on Tk::Iwidgets::Entryfield
- def clear
- tk_call(@path, 'clear')
- self
- end
-
- def delete(first, last=None)
- tk_send_without_enc('delete', first, last)
- self
- end
-
- def value
- _fromUTF8(tk_send_without_enc('get'))
- end
- def value= (val)
- tk_send_without_enc('delete', 0, 'end')
- tk_send_without_enc('insert', 0, _get_eval_enc_str(val))
- val
- end
- alias get value
- alias set value=
-
- def cursor=(index)
- tk_send_without_enc('icursor', index)
- #self
- index
- end
- alias icursor cursor=
-
- def index(idx)
- number(tk_send_without_enc('index', idx))
- end
-
- def insert(pos,text)
- tk_send_without_enc('insert', pos, _get_eval_enc_str(text))
- self
- end
-
- def mark(pos)
- tk_send_without_enc('scan', 'mark', pos)
- self
- end
- def dragto(pos)
- tk_send_without_enc('scan', 'dragto', pos)
- self
- end
- def selection_adjust(index)
- tk_send_without_enc('selection', 'adjust', index)
- self
- end
- def selection_clear
- tk_send_without_enc('selection', 'clear')
- self
- end
- def selection_from(index)
- tk_send_without_enc('selection', 'from', index)
- self
- end
- def selection_present()
- bool(tk_send_without_enc('selection', 'present'))
- end
- def selection_range(s, e)
- tk_send_without_enc('selection', 'range', s, e)
- self
- end
- def selection_to(index)
- tk_send_without_enc('selection', 'to', index)
- self
- end
-
- def xview(*index)
- if index.size == 0
- list(tk_send_without_enc('xview'))
- else
- tk_send_without_enc('xview', *index)
- self
- end
- end
- def xview_moveto(*index)
- xview('moveto', *index)
- end
- def xview_scroll(*index)
- xview('scroll', *index)
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb b/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb
deleted file mode 100644
index c21007ca6c..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# tkextlib/iwidgets/pushbutton.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Pushbutton < Tk::Itk::Widget
- end
- end
-end
-
-class Tk::Iwidgets::Pushbutton
- TkCommandNames = ['::iwidgets::pushbutton'.freeze].freeze
- WidgetClassName = 'Pushbutton'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __boolval_optkeys
- super() << 'defaultring'
- end
- private :__boolval_optkeys
-
- def invoke
- tk_call_without_enc(@path, 'invoke')
- self
- end
-
- def flash
- tk_call_without_enc(@path, 'flash')
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/radiobox.rb b/ext/tk/lib/tkextlib/iwidgets/radiobox.rb
deleted file mode 100644
index d4316754f2..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/radiobox.rb
+++ /dev/null
@@ -1,116 +0,0 @@
-#
-# tkextlib/iwidgets/radiobox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Radiobox < Tk::Iwidgets::Labeledframe
- end
- end
-end
-
-class Tk::Iwidgets::Radiobox
- TkCommandNames = ['::iwidgets::radiobox'.freeze].freeze
- WidgetClassName = 'Radiobox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- ####################################
-
- include TkItemConfigMethod
-
- def __item_cget_cmd(id)
- [self.path, 'buttoncget', id]
- end
- private :__item_cget_cmd
-
- def __item_config_cmd(id)
- [self.path, 'buttonconfigure', id]
- end
- private :__item_config_cmd
-
- def __item_boolval_optkeys(id)
- super(id) << 'defaultring'
- end
- private :__item_boolval_optkeys
-
- def tagid(tagOrId)
- if tagOrId.kind_of?(Tk::Itk::Component)
- tagOrId.name
- else
- #_get_eval_string(tagOrId)
- tagOrId
- end
- end
-
- alias buttoncget itemcget
- alias buttonconfigure itemconfigure
- alias buttonconfiginfo itemconfiginfo
- alias current_buttonconfiginfo current_itemconfiginfo
-
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
-
- ####################################
-
- def add(tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- if tag
- tag = Tk::Itk::Component.new(self, tagid(tag))
- else
- tag = Tk::Itk::Component.new(self)
- end
- tk_call(@path, 'add', tagid(tag), *hash_kv(keys))
- tag
- end
-
- def delete(idx)
- tk_call(@path, 'delete', index(idx))
- self
- end
-
- def deselect(idx)
- tk_call(@path, 'deselect', index(idx))
- self
- end
-
- def flash(idx)
- tk_call(@path, 'flash', index(idx))
- self
- end
-
- def get(idx)
- simplelist(tk_call(@path, 'get', index(idx))).collect{|id|
- Tk::Itk::Component.id2obj(id)
- }
- end
-
- def index(idx)
- number(tk_call(@path, 'index', tagid(idx)))
- end
-
- def insert(idx, tag=nil, keys={})
- if tag.kind_of?(Hash)
- keys = tag
- tag = nil
- end
- if tag
- tag = Tk::Itk::Component.new(self, tagid(tag))
- else
- tag = Tk::Itk::Component.new(self)
- end
- tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys))
- tag
- end
-
- def select(idx)
- tk_call(@path, 'select', index(idx))
- self
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb b/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb
deleted file mode 100644
index bddef50841..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# tkextlib/iwidgets/buttonbox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Scopedobject < TkObject
- end
- end
-end
-
-class Tk::Iwidgets::Scopedobject
- TkCommandNames = ['::iwidgets::scopedobject'.freeze].freeze
- WidgetClassName = 'Scopedobject'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def initialize(obj_name, keys={})
- @path = tk_call(self.class::TkCommandNames[0], obj_name, *hash_kv(keys))
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
deleted file mode 100644
index 407c8f2aad..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
+++ /dev/null
@@ -1,347 +0,0 @@
-#
-# tkextlib/iwidgets/scrolledcanvas.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/canvas'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Scrolledcanvas < Tk::Iwidgets::Scrolledwidget
- end
- end
-end
-
-class Tk::Iwidgets::Scrolledcanvas
- TkCommandNames = ['::iwidgets::scrolledcanvas'.freeze].freeze
- WidgetClassName = 'Scrolledcanvas'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- ################################
-
- def __boolval_optkeys
- super() << 'autoresize'
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- super() << 'textbackground'
- end
- private :__strval_optkeys
-
- def initialize(*args)
- super(*args)
- @canvas = component_widget('canvas')
- end
-
- def method_missing(id, *args)
- if @canvas.methods.include?(id.id2name)
- @canvas.__send__(id, *args)
- else
- super(id, *args)
- end
- end
-
- ################################
-
- def child_site
- window(tk_call(@path, 'childsite'))
- end
-
- def justify(dir)
- tk_call(@path, 'justify', dir)
- self
- end
-
- ##########################
- include TkCanvasItemConfig
-
- def tagid(tag)
- if tag.kind_of?(TkcItem) || tag.kind_of?(TkcTag)
- tag.id
- elsif tag.kind_of?(Tk::Itk::Component)
- tag.name
- else
- tag # maybe an Array of configure paramters
- end
- end
- private :tagid
-
- # create a canvas item without creating a TkcItem object
- def create(type, *args)
- type.create(self, *args)
- end
-
- #######################
-
- def addtag(tag, mode, *args)
- tk_send_without_enc('addtag', tagid(tag), mode, *args)
- self
- end
- def addtag_above(tagOrId, target)
- addtag(tagOrId, 'above', tagid(target))
- end
- def addtag_all(tagOrId)
- addtag(tagOrId, 'all')
- end
- def addtag_below(tagOrId, target)
- addtag(tagOrId, 'below', tagid(target))
- end
- def addtag_closest(tagOrId, x, y, halo=None, start=None)
- addtag(tagOrId, 'closest', x, y, halo, start)
- end
- def addtag_enclosed(tagOrId, x1, y1, x2, y2)
- addtag(tagOrId, 'enclosed', x1, y1, x2, y2)
- end
- def addtag_overlapping(tagOrId, x1, y1, x2, y2)
- addtag(tagOrId, 'overlapping', x1, y1, x2, y2)
- end
- def addtag_withtag(tagOrId, tag)
- addtag(tagOrId, 'withtag', tagid(tag))
- end
-
- def bbox(tagOrId, *tags)
- list(tk_send_without_enc('bbox', tagid(tagOrId),
- *tags.collect{|t| tagid(t)}))
- end
-
- #def itembind(tag, context, cmd=Proc.new, *args)
- # _bind([path, "bind", tagid(tag)], context, cmd, *args)
- # self
- #end
- def itembind(tag, context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind([path, "bind", tagid(tag)], context, cmd, *args)
- self
- end
-
- #def itembind_append(tag, context, cmd=Proc.new, *args)
- # _bind_append([path, "bind", tagid(tag)], context, cmd, *args)
- # self
- #end
- def itembind_append(tag, context, *args)
- # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
- if TkComm._callback_entry?(args[0]) || !block_given?
- cmd = args.shift
- else
- cmd = Proc.new
- end
- _bind_append([path, "bind", tagid(tag)], context, cmd, *args)
- self
- end
-
- def itembind_remove(tag, context)
- _bind_remove([path, "bind", tagid(tag)], context)
- self
- end
-
- def itembindinfo(tag, context=nil)
- _bindinfo([path, "bind", tagid(tag)], context)
- end
-
- def canvasx(screen_x, *args)
- #tk_tcl2ruby(tk_send_without_enc('canvasx', screen_x, *args))
- number(tk_send_without_enc('canvasx', screen_x, *args))
- end
- def canvasy(screen_y, *args)
- #tk_tcl2ruby(tk_send_without_enc('canvasy', screen_y, *args))
- number(tk_send_without_enc('canvasy', screen_y, *args))
- end
-
- def coords(tag, *args)
- if args == []
- tk_split_list(tk_send_without_enc('coords', tagid(tag)))
- else
- tk_send_without_enc('coords', tagid(tag), *(args.flatten))
- self
- end
- end
-
- def dchars(tag, first, last=None)
- tk_send_without_enc('dchars', tagid(tag),
- _get_eval_enc_str(first), _get_eval_enc_str(last))
- self
- end
-
- def delete(*args)
- if TkcItem::CItemID_TBL[self.path]
- find('withtag', *args).each{|item|
- if item.kind_of?(TkcItem)
- TkcItem::CItemID_TBL[self.path].delete(item.id)
- end
- }
- end
- tk_send_without_enc('delete', *args.collect{|t| tagid(t)})
- self
- end
- alias remove delete
-
- def dtag(tag, tag_to_del=None)
- tk_send_without_enc('dtag', tagid(tag), tag_to_del)
- self
- end
-
- def find(mode, *args)
- list(tk_send_without_enc('find', mode, *args)).collect!{|id|
- TkcItem.id2obj(self, id)
- }
- end
- def find_above(target)
- find('above', tagid(target))
- end
- def find_all
- find('all')
- end
- def find_below(target)
- find('below', tagid(target))
- end
- def find_closest(x, y, halo=None, start=None)
- find('closest', x, y, halo, start)
- end
- def find_enclosed(x1, y1, x2, y2)
- find('enclosed', x1, y1, x2, y2)
- end
- def find_overlapping(x1, y1, x2, y2)
- find('overlapping', x1, y1, x2, y2)
- end
- def find_withtag(tag)
- find('withtag', tag)
- end
-
- def itemfocus(tagOrId=nil)
- if tagOrId
- tk_send_without_enc('focus', tagid(tagOrId))
- self
- else
- ret = tk_send_without_enc('focus')
- if ret == ""
- nil
- else
- TkcItem.id2obj(self, ret)
- end
- end
- end
-
- def gettags(tagOrId)
- list(tk_send_without_enc('gettags', tagid(tagOrId))).collect{|tag|
- TkcTag.id2obj(self, tag)
- }
- end
-
- def icursor(tagOrId, index)
- tk_send_without_enc('icursor', tagid(tagOrId), index)
- self
- end
-
- def index(tagOrId, idx)
- number(tk_send_without_enc('index', tagid(tagOrId), idx))
- end
-
- def insert(tagOrId, index, string)
- tk_send_without_enc('insert', tagid(tagOrId), index,
- _get_eval_enc_str(string))
- self
- end
-
- def lower(tag, below=nil)
- if below
- tk_send_without_enc('lower', tagid(tag), tagid(below))
- else
- tk_send_without_enc('lower', tagid(tag))
- end
- self
- end
-
- def move(tag, x, y)
- tk_send_without_enc('move', tagid(tag), x, y)
- self
- end
-
- def postscript(keys)
- tk_send("postscript", *hash_kv(keys))
- end
-
- def raise(tag, above=nil)
- if above
- tk_send_without_enc('raise', tagid(tag), tagid(above))
- else
- tk_send_without_enc('raise', tagid(tag))
- end
- self
- end
-
- def scale(tag, x, y, xs, ys)
- tk_send_without_enc('scale', tagid(tag), x, y, xs, ys)
- self
- end
-
- def scan_mark(x, y)
- tk_send_without_enc('scan', 'mark', x, y)
- self
- end
- def scan_dragto(x, y)
- tk_send_without_enc('scan', 'dragto', x, y)
- self
- end
-
- def select(mode, *args)
- r = tk_send_without_enc('select', mode, *args)
- (mode == 'item')? TkcItem.id2obj(self, r): self
- end
- def select_adjust(tagOrId, index)
- select('adjust', tagid(tagOrId), index)
- end
- def select_clear
- select('clear')
- end
- def select_from(tagOrId, index)
- select('from', tagid(tagOrId), index)
- end
- def select_item
- select('item')
- end
- def select_to(tagOrId, index)
- select('to', tagid(tagOrId), index)
- end
-
- def itemtype(tag)
- TkcItem.type2class(tk_send('type', tagid(tag)))
- end
-
- def xview(*index)
- if index.size == 0
- list(tk_send_without_enc('xview'))
- else
- tk_send_without_enc('xview', *index)
- self
- end
- end
- def xview_moveto(*index)
- xview('moveto', *index)
- end
- def xview_scroll(*index)
- xview('scroll', *index)
- end
-
- def yview(*index)
- if index.size == 0
- list(tk_send_without_enc('yview'))
- else
- tk_send_without_enc('yview', *index)
- self
- end
- end
- def yview_moveto(*index)
- yview('moveto', *index)
- end
- def yview_scroll(*index)
- yview('scroll', *index)
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb
deleted file mode 100644
index 8b47460357..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-#
-# tkextlib/iwidgets/scrolledframe.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Scrolledframe < Tk::Iwidgets::Scrolledwidget
- end
- end
-end
-
-class Tk::Iwidgets::Scrolledframe
- TkCommandNames = ['::iwidgets::scrolledframe'.freeze].freeze
- WidgetClassName = 'Scrolledframe'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def child_site
- window(tk_call(@path, 'childsite'))
- end
-
- def justify(dir)
- tk_call(@path, 'justify', dir)
- self
- end
-
- def xview(*index)
- if index.size == 0
- list(tk_send_without_enc('xview'))
- else
- tk_send_without_enc('xview', *index)
- self
- end
- end
- def xview_moveto(*index)
- xview('moveto', *index)
- end
- def xview_scroll(*index)
- xview('scroll', *index)
- end
-
- def yview(*index)
- if index.size == 0
- list(tk_send_without_enc('yview'))
- else
- tk_send_without_enc('yview', *index)
- self
- end
- end
- def yview_moveto(*index)
- yview('moveto', *index)
- end
- def yview_scroll(*index)
- yview('scroll', *index)
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb
deleted file mode 100644
index 9b69ef07fe..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# tkextlib/iwidgets/scrolledhtml.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Scrolledhtml < Tk::Iwidgets::Scrolledtext
- end
- end
-end
-
-class Tk::Iwidgets::Scrolledhtml
- TkCommandNames = ['::iwidgets::scrolledhtml'.freeze].freeze
- WidgetClassName = 'Scrolledhtml'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __boolval_optkeys
- super() << 'update'
- end
- private :__boolval_optkeys
-
- def __strval_optkeys
- super() << 'fontname' << 'link' << 'alink' << 'textbackground'
- end
- private :__strval_optkeys
-
- def __font_optkeys
- super() << 'fixedfont'
- end
- private :__font_optkeys
-
- def import(href)
- tk_call(@path, 'import', href)
- self
- end
-
- def import_link(href)
- tk_call(@path, 'import', '-link', href)
- self
- end
-
- def pwd
- tk_call(@path, 'pwd')
- end
-
- def render(htmltext, workdir=None)
- tk_call(@path, 'render', htmltext, workdir)
- self
- end
-
- def title
- tk_call(@path, 'title')
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb
deleted file mode 100644
index cd1f6f0f79..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb
+++ /dev/null
@@ -1,207 +0,0 @@
-#
-# tkextlib/iwidgets/scrolledlistbox.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/listbox'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Scrolledlistbox < Tk::Iwidgets::Scrolledwidget
- end
- end
-end
-
-class Tk::Iwidgets::Scrolledlistbox
- TkCommandNames = ['::iwidgets::scrolledlistbox'.freeze].freeze
- WidgetClassName = 'Scrolledlistbox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'textbackground'
- end
- private :__strval_optkeys
-
- def __tkvariable_optkeys
- super() << 'listvariable'
- end
- private :__tkvariable_optkeys
-
- def __font_optkeys
- super() << 'textfont'
- end
- private :__font_optkeys
-
- ################################
-
- def initialize(*args)
- super(*args)
- @listbox = component_widget('listbox')
- end
-
- def method_missing(id, *args)
- if @listbox.methods.include?(id.id2name)
- @listbox.__send__(id, *args)
- else
- super(id, *args)
- end
- end
-
- ################################
-
- def clear
- tk_call(@path, 'clear')
- self
- end
-
- def get_curselection
- tk_call(@path, 'getcurselection')
- end
-
- def justify(dir)
- tk_call(@path, 'justify', dir)
- self
- end
-
- def selected_item_count
- number(tk_call(@path, 'selecteditemcount'))
- end
-
- def sort(*params, &b)
- # see 'lsort' man page about params
- if b
- tk_call(@path, 'sort', '-command', proc(&b), *params)
- else
- tk_call(@path, 'sort', *params)
- end
- self
- end
- def sort_ascending
- tk_call(@path, 'sort', 'ascending')
- self
- end
- def sort_descending
- tk_call(@path, 'sort', 'descending')
- self
- end
-
- #####################################
-
- def bbox(index)
- list(tk_send_without_enc('bbox', index))
- end
- def delete(first, last=None)
- tk_send_without_enc('delete', first, last)
- self
- end
- def get(*index)
- _fromUTF8(tk_send_without_enc('get', *index))
- end
- def insert(index, *args)
- tk_send('insert', index, *args)
- self
- end
- def scan_mark(x, y)
- tk_send_without_enc('scan', 'mark', x, y)
- self
- end
- def scan_dragto(x, y)
- tk_send_without_enc('scan', 'dragto', x, y)
- self
- end
- def see(index)
- tk_send_without_enc('see', index)
- self
- end
-
- #####################################
-
- include TkListItemConfig
-
- def tagid(tag)
- if tag.kind_of?(Tk::Itk::Component)
- tag.name
- else
- super(tag)
- end
- end
- private :tagid
-
- #####################################
-
- def activate(y)
- tk_send_without_enc('activate', y)
- self
- end
- def curselection
- list(tk_send_without_enc('curselection'))
- end
- def get(first, last=nil)
- if last
- # tk_split_simplelist(_fromUTF8(tk_send_without_enc('get', first, last)))
- tk_split_simplelist(tk_send_without_enc('get', first, last),
- false, true)
- else
- _fromUTF8(tk_send_without_enc('get', first))
- end
- end
- def nearest(y)
- tk_send_without_enc('nearest', y).to_i
- end
- def size
- tk_send_without_enc('size').to_i
- end
- def selection_anchor(index)
- tk_send_without_enc('selection', 'anchor', index)
- self
- end
- def selection_clear(first, last=None)
- tk_send_without_enc('selection', 'clear', first, last)
- self
- end
- def selection_includes(index)
- bool(tk_send_without_enc('selection', 'includes', index))
- end
- def selection_set(first, last=None)
- tk_send_without_enc('selection', 'set', first, last)
- self
- end
-
- def index(idx)
- tk_send_without_enc('index', idx).to_i
- end
-
- #####################################
-
- def xview(*index)
- if index.size == 0
- list(tk_send_without_enc('xview'))
- else
- tk_send_without_enc('xview', *index)
- self
- end
- end
- def xview_moveto(*index)
- xview('moveto', *index)
- end
- def xview_scroll(*index)
- xview('scroll', *index)
- end
-
- def yview(*index)
- if index.size == 0
- list(tk_send_without_enc('yview'))
- else
- tk_send_without_enc('yview', *index)
- self
- end
- end
- def yview_moveto(*index)
- yview('moveto', *index)
- end
- def yview_scroll(*index)
- yview('scroll', *index)
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb
deleted file mode 100644
index fdafc8dc7f..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb
+++ /dev/null
@@ -1,538 +0,0 @@
-#
-# tkextlib/iwidgets/scrolledtext.rb
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-
-require 'tk'
-require 'tk/text'
-require 'tkextlib/iwidgets.rb'
-
-module Tk
- module Iwidgets
- class Scrolledtext < Tk::Iwidgets::Scrolledwidget
- end
- end
-end
-
-class Tk::Iwidgets::Scrolledtext
- TkCommandNames = ['::iwidgets::scrolledtext'.freeze].freeze
- WidgetClassName = 'Scrolledtext'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __strval_optkeys
- super() << 'textbackground'
- end
- private :__strval_optkeys
-
- def __font_optkeys
- super() << 'textfont'
- end
- private :__font_optkeys
-
- ################################
-
- def initialize(*args)
- super(*args)
- @text = component_widget('text')
- end
-
- def method_missing(id, *args)
- if @text.methods.include?(id.id2name)
- @text.__send__(id, *args)
- else
- super(id, *args)
- end
- end
-
- ################################
-
- def child_site
- window(tk_call(@path, 'childsite'))
- end
-
- def clear
- tk_call(@path, 'clear')
- self
- end
-
- def import(file, idx=nil)
- if idx
- tk_call(@path, 'import', file, index(idx))
- else
- tk_call(@path, 'import', file)
- end
- self
- end
-
- def export(file)
- tk_call(@path, 'export', file)
- self
- end
-
- #####################################
-
- include TkTextTagConfig
-
- def tagid(tag)
- if tag.kind_of?(Tk::Itk::Component)
- tag.name
- else
- super(tag)
- end
- end
- private :tagid
-
- def bbox(index)
- list(tk_send('bbox', index))
- end
- def compare(idx1, op, idx2)
- bool(tk_send_without_enc('compare', _get_eval_enc_str(idx1),
- op, _get_eval_enc_str(idx2)))
- end
-
- def debug
- bool(tk_send_without_enc('debug'))
- end
- def debug=(boolean)
- tk_send_without_enc('debug', boolean)
- #self
- boolean
- end
-
- def delete(first, last=None)
- tk_send_without_enc('delete', first, last)
- self
- end
-
- def dlineinfo(index)
- list(tk_send_without_enc('dlineinfo', _get_eval_enc_str(index)))
- end
-
- def get(*index)
- _fromUTF8(tk_send_without_enc('get', *index))
- end
- def get_displaychars(*index)
- # Tk8.5 feature
- get('-displaychars', *index)
- end
-
- def image_cget(index, slot)
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- _fromUTF8(tk_send_without_enc('image', 'cget',
- _get_eval_enc_str(index), "-#{slot}"))
- else
- tk_tcl2ruby(_fromUTF8(tk_send_without_enc('image', 'cget',
- _get_eval_enc_str(index),
- "-#{slot}")))
- end
- end
-
- def image_configure(index, slot, value=None)
- if slot.kind_of? Hash
- _fromUTF8(tk_send_without_enc('image', 'configure',
- _get_eval_enc_str(index),
- *hash_kv(slot, true)))
- else
- _fromUTF8(tk_send_without_enc('image', 'configure',
- _get_eval_enc_str(index),
- "-#{slot}",
- _get_eval_enc_str(value)))
- end
- self
- end
-
- def image_configinfo(index, slot = nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
- conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true)
- else
- #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
- conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true)
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).collect{|conflist|
- # conf = tk_split_simplelist(conflist)
- tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).collect{|conflist|
- conf = tk_split_simplelist(conflist, false, true)
- conf[0] = conf[0][1..-1]
- case conf[0]
- when 'text', 'label', 'show', 'data', 'file'
- else
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- if conf[4]
- if conf[4].index('{')
- conf[4] = tk_split_list(conf[4])
- else
- conf[4] = tk_tcl2ruby(conf[4])
- end
- end
- end
- conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
- conf
- }
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
- conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true)
- else
- #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
- conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true)
- end
- key = conf.shift[1..-1]
- { key => conf }
- else
- ret = {}
- #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).each{|conflist|
- # conf = tk_split_simplelist(conflist)
- tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).each{|conflist|
- conf = tk_split_simplelist(conflist, false, true)
- key = conf.shift[1..-1]
- case key
- when 'text', 'label', 'show', 'data', 'file'
- else
- if conf[2]
- if conf[2].index('{')
- conf[2] = tk_split_list(conf[2])
- else
- conf[2] = tk_tcl2ruby(conf[2])
- end
- end
- if conf[3]
- if conf[3].index('{')
- conf[3] = tk_split_list(conf[3])
- else
- conf[3] = tk_tcl2ruby(conf[3])
- end
- end
- end
- if conf.size == 1
- ret[key] = conf[0][1..-1] # alias info
- else
- ret[key] = conf
- end
- }
- ret
- end
- end
- end
-
- def current_image_configinfo(index, slot = nil)
- if TkComm::GET_CONFIGINFO_AS_ARRAY
- if slot
- conf = image_configinfo(index, slot)
- {conf[0] => conf[4]}
- else
- ret = {}
- image_configinfo(index).each{|conf|
- ret[conf[0]] = conf[4] if conf.size > 2
- }
- ret
- end
- else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
- ret = {}
- image_configinfo(index, slot).each{|k, conf|
- ret[k] = conf[-1] if conf.kind_of?(Array)
- }
- ret
- end
- end
-
- def image_names
- #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'names'))).collect{|elt|
- tk_split_simplelist(tk_send_without_enc('image', 'names'), false, true).collect{|elt|
- tagid2obj(elt)
- }
- end
-
- def index(idx)
- tk_send_without_enc('index', _get_eval_enc_str(idx))
- end
-
- def insert(index, *args)
- tk_send('insert', index, *args)
- self
- end
-
- def mark_names
- #tk_split_simplelist(_fromUTF8(tk_send_without_enc('mark', 'names'))).collect{|elt|
- tk_split_simplelist(tk_send_without_enc('mark', 'names'), false, true).collect{|elt|
- tagid2obj(elt)
- }
- end
-
- def mark_gravity(mark, direction=nil)
- if direction
- tk_send_without_enc('mark', 'gravity',
- _get_eval_enc_str(mark), direction)
- self
- else
- tk_send_without_enc('mark', 'gravity', _get_eval_enc_str(mark))
- end
- end
-
- def mark_set(mark, index)
- tk_send_without_enc('mark', 'set', _get_eval_enc_str(mark),
- _get_eval_enc_str(index))
- self
- end
- alias set_mark mark_set
-
- def mark_unset(*marks)
- tk_send_without_enc('mark', 'unset',
- *(marks.collect{|mark| _get_eval_enc_str(mark)}))
- self
- end
- alias unset_mark mark_unset
-
- def mark_next(index)
- tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'next',
- _get_eval_enc_str(index))))
- end
- alias next_mark mark_next
-
- def mark_previous(index)
- tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'previous',
- _get_eval_enc_str(index))))
- end
- alias previous_mark mark_previous
-
- def scan_mark(x, y)
- tk_send_without_enc('scan', 'mark', x, y)
- self
- end
- def scan_dragto(x, y)
- tk_send_without_enc('scan', 'dragto', x, y)
- self
- end
-
-
- def _ktext_length(txt)
- if $KCODE !~ /n/i
- return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length
- end
-
- # $KCODE == 'NONE'
- if JAPANIZED_TK
- tk_call_without_enc('kstring', 'length',
- _get_eval_enc_str(txt)).to_i
- else
- begin
- tk_call_without_enc('encoding', 'convertto', 'ascii',
- _get_eval_enc_str(txt)).length
- rescue StandardError, NameError
- # sorry, I have no plan
- txt.length
- end
- end
- end
- private :_ktext_length
-
- def tksearch(*args)
- # call 'search' subcommand of text widget
- # args ::= [<array_of_opts>] <pattern> <start_index> [<stop_index>]
- # If <pattern> is regexp, then it must be a regular expression of Tcl
- if args[0].kind_of?(Array)
- opts = args.shift.collect{|opt| '-' + opt.to_s }
- else
- opts = []
- end
-
- opts << '--'
-
- ret = tk_send('search', *(opts + args))
- if ret == ""
- nil
- else
- ret
- end
- end
-
- def tksearch_with_count(*args)
- # call 'search' subcommand of text widget
- # args ::= [<array_of_opts>] <var> <pattern> <start_index> [<stop_index>]
- # If <pattern> is regexp, then it must be a regular expression of Tcl
- if args[0].kind_of?(Array)
- opts = args.shift.collect{|opt| '-' + opt.to_s }
- else
- opts = []
- end
-
- opts << '-count' << args.shift << '--'
-
- ret = tk_send('search', *(opts + args))
- if ret == ""
- nil
- else
- ret
- end
- end
-
- def search_with_length(pat,start,stop=None)
- pat = pat.chr if pat.kind_of? Integer
- if stop != None
- return ["", 0] if compare(start,'>=',stop)
- txt = get(start,stop)
- if (pos = txt.index(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of? String
- #return [index(start + " + #{pos} chars"), pat.split('').length]
- return [index(start + " + #{pos} chars"),
- _ktext_length(pat), pat.dup]
- else
- #return [index(start + " + #{pos} chars"), $&.split('').length]
- return [index(start + " + #{pos} chars"),
- _ktext_length(match), match]
- end
- else
- return ["", 0]
- end
- else
- txt = get(start,'end - 1 char')
- if (pos = txt.index(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of? String
- #return [index(start + " + #{pos} chars"), pat.split('').length]
- return [index(start + " + #{pos} chars"),
- _ktext_length(pat), pat.dup]
- else
- #return [index(start + " + #{pos} chars"), $&.split('').length]
- return [index(start + " + #{pos} chars"),
- _ktext_length(match), match]
- end
- else
- txt = get('1.0','end - 1 char')
- if (pos = txt.index(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of? String
- #return [index("1.0 + #{pos} chars"), pat.split('').length]
- return [index("1.0 + #{pos} chars"),
- _ktext_length(pat), pat.dup]
- else
- #return [index("1.0 + #{pos} chars"), $&.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
- end
- else
- return ["", 0]
- end
- end
- end
- end
-
- def search(pat,start,stop=None)
- search_with_length(pat,start,stop)[0]
- end
-
- def rsearch_with_length(pat,start,stop=None)
- pat = pat.chr if pat.kind_of? Integer
- if stop != None
- return ["", 0] if compare(start,'<=',stop)
- txt = get(stop,start)
- if (pos = txt.rindex(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of? String
- #return [index(stop + " + #{pos} chars"), pat.split('').length]
- return [index(stop + " + #{pos} chars"), _ktext_length(pat), pat.dup]
- else
- #return [index(stop + " + #{pos} chars"), $&.split('').length]
- return [index(stop + " + #{pos} chars"), _ktext_length(match), match]
- end
- else
- return ["", 0]
- end
- else
- txt = get('1.0',start)
- if (pos = txt.rindex(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of? String
- #return [index("1.0 + #{pos} chars"), pat.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
- else
- #return [index("1.0 + #{pos} chars"), $&.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
- end
- else
- txt = get('1.0','end - 1 char')
- if (pos = txt.rindex(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of? String
- #return [index("1.0 + #{pos} chars"), pat.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
- else
- #return [index("1.0 + #{pos} chars"), $&.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
- end
- else
- return ["", 0]
- end
- end
- end
- end
-
- def rsearch(pat,start,stop=None)
- rsearch_with_length(pat,start,stop)[0]
- end
-
- def see(index)
- tk_send_without_enc('see', index)
- self
- end
-
- ###############################
-
- def xview(*index)
- if index.size == 0
- list(tk_send_without_enc('xview'))
- else
- tk_send_without_enc('xview', *index)
- self
- end
- end
- def xview_moveto(*index)
- xview('moveto', *index)
- end
- def xview_scroll(*index)
- xview('scroll', *index)
- end
-
- def yview(*index)
- if index.size == 0
- list(tk_send_without_enc('yview'))
- else
- tk_send_without_enc('yview', *index)
- self
- end
- end
- def yview_moveto(*index)
- yview('moveto', *index)
- end
- def yview_scroll(*index)
- yview('scroll', *index)
- end
-end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb
deleted file mode 100644
index eef093d314..0000000000
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb
+++ /dev/null